<!DOCTYPE html>
<html>
<head>
<title>configdef-doc.md</title>
<meta http-equiv="Content-type" content="text/html;charset=UTF-8">

<style>
/* https://github.com/microsoft/vscode/blob/master/extensions/markdown-language-features/media/markdown.css */
/*---------------------------------------------------------------------------------------------
 *  Copyright (c) Microsoft Corporation. All rights reserved.
 *  Licensed under the MIT License. See License.txt in the project root for license information.
 *--------------------------------------------------------------------------------------------*/

body {
	font-family: var(--vscode-markdown-font-family, -apple-system, BlinkMacSystemFont, "Segoe WPC", "Segoe UI", "Ubuntu", "Droid Sans", sans-serif);
	font-size: var(--vscode-markdown-font-size, 14px);
	padding: 0 26px;
	line-height: var(--vscode-markdown-line-height, 22px);
	word-wrap: break-word;
}

#code-csp-warning {
	position: fixed;
	top: 0;
	right: 0;
	color: white;
	margin: 16px;
	text-align: center;
	font-size: 12px;
	font-family: sans-serif;
	background-color:#444444;
	cursor: pointer;
	padding: 6px;
	box-shadow: 1px 1px 1px rgba(0,0,0,.25);
}

#code-csp-warning:hover {
	text-decoration: none;
	background-color:#007acc;
	box-shadow: 2px 2px 2px rgba(0,0,0,.25);
}

body.scrollBeyondLastLine {
	margin-bottom: calc(100vh - 22px);
}

body.showEditorSelection .code-line {
	position: relative;
}

body.showEditorSelection .code-active-line:before,
body.showEditorSelection .code-line:hover:before {
	content: "";
	display: block;
	position: absolute;
	top: 0;
	left: -12px;
	height: 100%;
}

body.showEditorSelection li.code-active-line:before,
body.showEditorSelection li.code-line:hover:before {
	left: -30px;
}

.vscode-light.showEditorSelection .code-active-line:before {
	border-left: 3px solid rgba(0, 0, 0, 0.15);
}

.vscode-light.showEditorSelection .code-line:hover:before {
	border-left: 3px solid rgba(0, 0, 0, 0.40);
}

.vscode-light.showEditorSelection .code-line .code-line:hover:before {
	border-left: none;
}

.vscode-dark.showEditorSelection .code-active-line:before {
	border-left: 3px solid rgba(255, 255, 255, 0.4);
}

.vscode-dark.showEditorSelection .code-line:hover:before {
	border-left: 3px solid rgba(255, 255, 255, 0.60);
}

.vscode-dark.showEditorSelection .code-line .code-line:hover:before {
	border-left: none;
}

.vscode-high-contrast.showEditorSelection .code-active-line:before {
	border-left: 3px solid rgba(255, 160, 0, 0.7);
}

.vscode-high-contrast.showEditorSelection .code-line:hover:before {
	border-left: 3px solid rgba(255, 160, 0, 1);
}

.vscode-high-contrast.showEditorSelection .code-line .code-line:hover:before {
	border-left: none;
}

img {
	max-width: 100%;
	max-height: 100%;
}

a {
	text-decoration: none;
}

a:hover {
	text-decoration: underline;
}

a:focus,
input:focus,
select:focus,
textarea:focus {
	outline: 1px solid -webkit-focus-ring-color;
	outline-offset: -1px;
}

hr {
	border: 0;
	height: 2px;
	border-bottom: 2px solid;
}

h1 {
	padding-bottom: 0.3em;
	line-height: 1.2;
	border-bottom-width: 1px;
	border-bottom-style: solid;
}

h1, h2, h3 {
	font-weight: normal;
}

table {
	border-collapse: collapse;
}

table > thead > tr > th {
	text-align: left;
	border-bottom: 1px solid;
}

table > thead > tr > th,
table > thead > tr > td,
table > tbody > tr > th,
table > tbody > tr > td {
	padding: 5px 10px;
}

table > tbody > tr + tr > td {
	border-top: 1px solid;
}

blockquote {
	margin: 0 7px 0 5px;
	padding: 0 16px 0 10px;
	border-left-width: 5px;
	border-left-style: solid;
}

code {
	font-family: Menlo, Monaco, Consolas, "Droid Sans Mono", "Courier New", monospace, "Droid Sans Fallback";
	font-size: 1em;
	line-height: 1.357em;
}

body.wordWrap pre {
	white-space: pre-wrap;
}

pre:not(.hljs),
pre.hljs code > div {
	padding: 16px;
	border-radius: 3px;
	overflow: auto;
}

pre code {
	color: var(--vscode-editor-foreground);
	tab-size: 4;
}

/** Theming */

.vscode-light pre {
	background-color: rgba(220, 220, 220, 0.4);
}

.vscode-dark pre {
	background-color: rgba(10, 10, 10, 0.4);
}

.vscode-high-contrast pre {
	background-color: rgb(0, 0, 0);
}

.vscode-high-contrast h1 {
	border-color: rgb(0, 0, 0);
}

.vscode-light table > thead > tr > th {
	border-color: rgba(0, 0, 0, 0.69);
}

.vscode-dark table > thead > tr > th {
	border-color: rgba(255, 255, 255, 0.69);
}

.vscode-light h1,
.vscode-light hr,
.vscode-light table > tbody > tr + tr > td {
	border-color: rgba(0, 0, 0, 0.18);
}

.vscode-dark h1,
.vscode-dark hr,
.vscode-dark table > tbody > tr + tr > td {
	border-color: rgba(255, 255, 255, 0.18);
}

</style>

<style>
/* Tomorrow Theme */
/* http://jmblog.github.com/color-themes-for-google-code-highlightjs */
/* Original theme - https://github.com/chriskempson/tomorrow-theme */

/* Tomorrow Comment */
.hljs-comment,
.hljs-quote {
	color: #8e908c;
}

/* Tomorrow Red */
.hljs-variable,
.hljs-template-variable,
.hljs-tag,
.hljs-name,
.hljs-selector-id,
.hljs-selector-class,
.hljs-regexp,
.hljs-deletion {
	color: #c82829;
}

/* Tomorrow Orange */
.hljs-number,
.hljs-built_in,
.hljs-builtin-name,
.hljs-literal,
.hljs-type,
.hljs-params,
.hljs-meta,
.hljs-link {
	color: #f5871f;
}

/* Tomorrow Yellow */
.hljs-attribute {
	color: #eab700;
}

/* Tomorrow Green */
.hljs-string,
.hljs-symbol,
.hljs-bullet,
.hljs-addition {
	color: #718c00;
}

/* Tomorrow Blue */
.hljs-title,
.hljs-section {
	color: #4271ae;
}

/* Tomorrow Purple */
.hljs-keyword,
.hljs-selector-tag {
	color: #8959a8;
}

.hljs {
	display: block;
	overflow-x: auto;
	color: #4d4d4c;
	padding: 0.5em;
}

.hljs-emphasis {
	font-style: italic;
}

.hljs-strong {
	font-weight: bold;
}
</style>

<style>
/*
 * Markdown PDF CSS
 */

 body {
	font-family: -apple-system, BlinkMacSystemFont, "Segoe WPC", "Segoe UI", "Ubuntu", "Droid Sans", sans-serif, "Meiryo";
	padding: 0 12px;
}

pre {
	background-color: #f8f8f8;
	border: 1px solid #cccccc;
	border-radius: 3px;
	overflow-x: auto;
	white-space: pre-wrap;
	overflow-wrap: break-word;
}

pre:not(.hljs) {
	padding: 23px;
	line-height: 19px;
}

blockquote {
	background: rgba(127, 127, 127, 0.1);
	border-color: rgba(0, 122, 204, 0.5);
}

.emoji {
	height: 1.4em;
}

code {
	font-size: 14px;
	line-height: 19px;
}

/* for inline code */
:not(pre):not(.hljs) > code {
	color: #C9AE75; /* Change the old color so it seems less like an error */
	font-size: inherit;
}

/* Page Break : use <div class="page"/> to insert page break
-------------------------------------------------------- */
.page {
	page-break-after: always;
}

</style>

<script src="https://unpkg.com/mermaid/dist/mermaid.min.js"></script>
</head>
<body>
  <script>
    mermaid.initialize({
      startOnLoad: true,
      theme: document.body.classList.contains('vscode-dark') || document.body.classList.contains('vscode-high-contrast')
          ? 'dark'
          : 'default'
    });
  </script>
<!-- configdef-doc.md rev1.0.1 2023-06-17 -->
<h1 id="configdef"><strong>configdef</strong></h1>
<h2 id="intro"><strong>Intro</strong></h2>
<p><em><strong>configdef</strong></em> is a configuration utility created for Tcl developers, Tcl extension writers in particular. While <em>configdef</em> may also be useful in non-Tcl projects, at this point it doesn't provide the comprehensive capabilities of Gnu configure or cmake. <em>configdef</em> does offer simplicity, flexibility and works on any system that can run an up-to-date Tcl interpreter (which is virtually all of them).</p>
<h2 id="system-requirements"><strong>System requirements</strong></h2>
<p>The <em>configdef</em> archive contains ready-to-run binaries for Windows and Linux systems.</p>
<p>For other OS, or when custom features are needed, binaries can be regenerated. For such purposes it's necessary to have a statically compiled Tcl 8.7 or 9.0. This will be described in detail in a later section.</p>
<h2 id="installation"><strong>Installation</strong></h2>
<p>Decompress the downloaded archive in any convenient directory. Archives contain the following file structure:</p>
<pre><code>+ configdef
  + bin
    - config
    - config.exe
    - genPkgIndex
    - genPkgIndex.exe
  + doc
    - configdef-doc.md
    - configdef-doc.pdf
  + generic
    - config.tcl
    - genPkgIndex.tcl
    - mkconfig.tcl
    - mkGenPkgIndex.tcl
    - tcltkparams.tcl
  + tools
    + config8.vfs
    + config9.vfs
    + genPkgIndex8.vfs
    + genPkgIndex9.vfs
    + unix
    + win
</code></pre>
<p>It's only necessary to copy config and genPkgIndex (or the *.exe files) to a directory on the exec path. For unix users that's typically /usr/local/bin. Windows users might want to create a &quot;bin&quot; directory in their home directory and add it to their personal or system-wide path.</p>
<h2 id="using-configdef"><strong>Using <em>configdef</em></strong></h2>
<h3 id="the-configdef-file"><strong>The <em>config.def</em> file</strong></h3>
<p>The <em>config.def</em> file describes and defines configuration options that are transformed into a usable <em>Makefile</em>. The syntax of this Makefile is compatible with any recent version of Gnu make.</p>
<p><em>config.def</em> is intended to be processed by the <em>config</em> utility on a <em>per directory basis</em>. IOW every directory with configurable options will have its own <em>config.def</em> file. It's possible to cascade configuration such that <em>config.def</em> in a directory sets up or points to <em>config.def</em> in one or more subdirectories.</p>
<h4 id="configdef-syntax"><strong><em>config.def</em> syntax</strong></h4>
<p>Note that <em>config.def</em> is a normal Tcl file and can contain additional <em>procs</em>, global variables or <em>source</em> other Tcl files as needed. The basic components are described in this section.</p>
<p><strong>Vars</strong> variable contains a list of undefined variables that must be defined on the <em>config</em> command line. For example:</p>
<pre><code>set Vars {filename}
config -filename=myfile.tcl
# if filename not supplied:
ERROR: missing input: -filename=...
</code></pre>
<p><strong>Defaults</strong> variable has a list of variable+default value pairs. Variables listed here don't have to be supplied on the <em>config</em> command line except to override the default:</p>
<pre><code>set Defaults {
    tcldir c:/tcl87b1s
    ...
}
# global variable &quot;tcldir&quot; is visible in config.def
# This invocation overrides the default value:
config -tcldir=c:/tcl90b1s
</code></pre>
<p><strong>helptext</strong>. Optional list of strings providing help for <em>mandatory</em> arguments to <em>config</em>. (As described above re: <strong>Vars</strong>.) These strings are displayed when <code>config -help</code> is called.</p>
<p><strong>helptext_optional</strong>. Optional list of strings with help text for optional params to <em>config</em>. Optional params correspond to variables given under <strong>Defaults</strong>.</p>
<p><strong>DEFINES</strong>. The DEFINES variable contains a list of variable/value pairs. Here the first member of the pair becomes a Makefile variable and the second is the value.</p>
<pre><code>set DEFINES {
    tclinc  $tclinc
    tcllib  $tcllib
    ...
}
# in the Makefile:
TCLINC = c:/tcl87b1/include
TCLLIB = c:/tcl87b1/lib
...
</code></pre>
<p>When there are several Makefile variables to initialize it's convenient to use this special syntax:</p>
<pre><code>set DEFINES {
    * {tclinc tcllib tclsrc ...}
    ...
}
</code></pre>
<p>The output is identical to the prior example.</p>
<p><em>configdef</em> provides a large number of Tcl-related variables automatically when &quot;tcldir&quot; or &quot;tclsrc&quot; is specified in <strong>Defaults</strong> or on the <em>config</em> command line. (&quot;tcldir&quot; is the directory where Tcl is installed, &quot;tclsrc&quot; is the Tcl source directory. Similarly, Tk variables are generated when &quot;tkdir&quot; and &quot;tksrc&quot; are provided.)</p>
<p>DEFINES don't have to be predefined in Defaults. It's quite possible and often useful to create values for arbitrary variables. DEFINES values can make use of the full range of Tcl facilities:</p>
<pre><code>set DEFINES {
    ...
    config_vfs  {../config[string index $::tclver 0].vfs}
    progs	{\$(CONFIG) \$(PKGNDX)}
    ...
}
# Makefile:
CONFIG_VFS = ../config8.vfs
PROGS = $(CONFIG) $(PKGNDX)
</code></pre>
<p>Note that a value must be enclosed in {} when it contains spaces, Tcl variables or commands. Also &quot;$&quot; must be escaped with &quot;\&quot; when the $ refers to Makefile and not Tcl variables. Furthermore, values defined in <strong>Defaults</strong> or command line and used directly need not be namespace-qualified (&quot;:<img class="emoji" alt="blush" src="data:image/png;base64,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" />. However when used in a command in the value (right-hand side) then the global namespace qualifiers are necessary.</p>
<p>The <strong>RULES</strong> variable is slightly more complex. This variable defines Makefile rules, with each rule consisting of 3 parts: the target, list of dependencies, and a list of operations. <strong>RULES</strong> looks like this:</p>
<div style="page-break-after: always;"></div>
<pre><code>set RULES {
    all {$(PROGS)} {
    }
    cfginit {} {
        {rm -rf $(CONFIG_VFSLIB)}
        {cp -r $(TCLLBRY) $(CONFIG_VFSLIB)}
        {cp $(GEN)/config.tcl $(GEN)/tcltkparams.tcl $(CONFIG_VFS)}
    }
    $(CONFIG) {$(CONFIG_VFS)/config.tcl \
            $(CONFIG_VFS)/tcltkparams.tcl} {
        {make cfginit}
        {$(TCLSH) $(GEN)/mkconfig.tcl}
    }
    ...
}
# Makefile:
all: $(PROGS)

cfginit: 
    rm -rf $(CONFIG_VFSLIB)
    cp -r $(TCLLBRY) $(CONFIG_VFSLIB)
    cp $(GEN)/config.tcl $(GEN)/tcltkparams.tcl $(CONFIG_VFS)

$(CONFIG): $(CONFIG_VFS)/config.tcl  $(CONFIG_VFS)/tcltkparams.tcl
    make cfginit
    $(TCLSH) $(GEN)/mkconfig.tcl
</code></pre>
<p>Note that the rules list is evaluated but the target and dependencies are not. Because Makefile variables are common and essential in rules, $... is not treated as a Tcl variable during <em>configdef</em> evaluation, except when enclosed in a Tcl command invocation:</p>
<pre><code>$(MYTARGET) {&lt;dependency list&gt;} {
    {[expr {$::my_tcl_variable ? &lt;do something&gt; : &lt;do something else&gt;}]}
    {$(CC) -o $@ -c $&lt; ...}
}
# &lt;$my_tcl_variable&gt; is evaluated as expected, but $(CC), etc., are ignored
</code></pre>
<h4 id="cascading-configdef"><strong>Cascading <em>config.def</em></strong></h4>
<p>As noted above, configuration can proceed from one directory to another. All that's necessary is defining a <em>proc</em> named &quot;nextcfg&quot; that takes no arguments. The proc returns a list of directories/config arguments. Each directory will be visited in turn and config arguments applied.</p>
<pre><code>proc nextcfg {} {
    lappend ls ../subdirA [list -tcldir=$::tcldir] \
        ../subdirB [list -tcllib=$::tcllib]
    return $ls
}
</code></pre>
<p>nextcfg can make use of Defaults, procs, and other Tcl features defined in config.def, assuming that the section was already processed. For this reason, nextcfg is typically placed at the bottom of the config.def file.</p>
<h3 id="genpkgindex"><strong>genPkgIndex</strong></h3>
<p><em>configdef</em> includes the <strong>genPkgIndex</strong> utility which unsurprisingly generates a <em>pkgIndex.tcl</em> file for binary extensions.</p>
<p>genPkgIndex takes 2 mandatory and 2 optional arguments. The syntax is as follows:</p>
<pre><code>genPkgIndex(.exe) -pkgnm &lt;package name&gt; -pkgver &lt;pkg version&gt; ?-script &lt;string&gt;? ?-filename &lt;output file&gt;?
</code></pre>
<p>If &lt;filename&gt; is not given then output goes to stdout. If &lt;script&gt; is absent then the built-in standard pkgIndex.tcl is generated:</p>
<pre><code>genPkgIndex -pkgnm mypkg -pkgver 1.1
# writes to stdout:
# if {[package vsatisfies [package provide Tcl] 9.0-]} {
#    package ifneeded mypkg 1.0 [list load [file join $dir tcl9mypkg10.dll]]
# } else {
#    package ifneeded mypkg 1.0 [list load [file join  $ dir mypkg10.dll]]
# }
</code></pre>
<p>Of course, a script can be provided. The script should have embedded $pkgnm, $pkgver, $tcl9libnm and $libnm variables at the appropriate places. Otherwise $, [, ] characters must be backslash escaped.</p>
<h3 id="generating-binaries-from-source"><strong>Generating binaries from source</strong></h3>
<p>Complete source code is included in the release archive. Generating binaries for supported platforms is pretty straightforward. The only required dependency is a statically compiled Tcl 8.7 or 9.0 <em>tclsh</em>. Consult the Tcl documentation for details of compiling Tcl.</p>
<p>If <em>configdef</em> sources have been modified, very likely the default <em>config</em> and <em>genPkgIndex</em> are no longer valid. To generate these files follow these steps:</p>
<ol>
<li>Locate the appropriate directory, unix or win under the tools directory.</li>
<li>Modify config.def to match the user's platform. The main options are in Defaults re: &quot;tcldir&quot; and &quot;tclsrc&quot; which should point to valid locations. (Note that &quot;tcldir&quot; and &quot;tclsrc&quot; are usable after successful compilation and installation of Tcl 8.7 or 9.0.)</li>
<li>Make sure config8.vfs or config9.vfs is up to date and has the appropriate tcl_library (same Tcl version as intended to use in the next step).</li>
<li>Running &quot;/path/to/tclsh* ../../generic/mkconfig.tcl&quot; should generate ./config(.exe) in tools/unix(or win) directory.</li>
<li>Now running &quot;./config(.exe)&quot; should generate a new (and correct) Makefile.</li>
<li>Run &quot;make clean&quot;, &quot;make&quot; and &quot;make install&quot;.</li>
<li>It's only necessary to use one of Tcl 8.7 or 9.0 as either will produce valid, functionally equivalent <em>config</em> and <em>genPkgIndex</em> programs.</li>
</ol>
<h2 id="built-in-variables"><strong>Built-in variables</strong></h2>
<p>As a convenience to users <em>configdef</em> supplies a number of Tcl global variables. These can be redefined in <strong>Defaults</strong> or <strong>DEFINES</strong> lists.</p>
<h3 id="makefile-defines"><strong>Makefile DEFINES</strong></h3>
<p>Several variables are computed by <em>configdef</em> that automatically appear in the Makefile.</p>
<table>
<thead>
<tr>
<th>variable</th>
<th>Makefile</th>
<th>value</th>
<th>(info)</th>
</tr>
</thead>
<tbody>
<tr>
<td>cc</td>
<td>CC</td>
<td>gcc</td>
<td></td>
</tr>
<tr>
<td>libext</td>
<td>LIBEXT</td>
<td>dll, so</td>
<td></td>
</tr>
<tr>
<td>objext</td>
<td>OBJEXT</td>
<td>obj, o</td>
<td></td>
</tr>
<tr>
<td>exe</td>
<td>EXE</td>
<td>.exe, &quot;&quot;</td>
<td></td>
</tr>
<tr>
<td>starext</td>
<td>STAREXT</td>
<td>.lib, .a</td>
<td>(static archive extension)</td>
</tr>
</tbody>
</table>
<h3 id="tcltk-specific-variables"><strong>Tcl/Tk-specific variables</strong></h3>
<p>Establishing certain variables in <strong>Defaults</strong> or on the command line leads to automatically produced variables.</p>
<p>(Defaults) <code>tcldir /path/to/installed_Tcl</code><br>
(cmdline) <code>-tcldir=/path/to/installed_Tcl</code></p>
<table>
<thead>
<tr>
<th>variable</th>
<th>value</th>
</tr>
</thead>
<tbody>
<tr>
<td>tclbin</td>
<td>$tcldir/bin</td>
</tr>
<tr>
<td>tclsh</td>
<td>$tcldir/bin/tclsh*</td>
</tr>
<tr>
<td>tclinc</td>
<td>$tcldir/include</td>
</tr>
<tr>
<td>tcllib</td>
<td>$tcldir/lib</td>
</tr>
<tr>
<td>tclstub</td>
<td>$tcldir/lib/tcl*stub*</td>
</tr>
<tr>
<td>tclver</td>
<td>tcl version</td>
</tr>
</tbody>
</table>
<p>(Defaults) <code>tclsrc /path/to/Tcl_source_dir</code><br>
(cmdline) <code>-tclsrc=/path/to/Tcl_source_dir</code></p>
<table>
<thead>
<tr>
<th>variable</th>
<th>value</th>
<th>info</th>
</tr>
</thead>
<tbody>
<tr>
<td>tcllbry</td>
<td>$tclsrc/library</td>
<td></td>
</tr>
<tr>
<td>tclobjd</td>
<td>$tclsrc/obj_dir</td>
<td>dir containing object files</td>
</tr>
<tr>
<td>tclshsd</td>
<td>$tclsrc/tclsh*</td>
<td>tclsh (in source directory)</td>
</tr>
<tr>
<td>tclstubsd</td>
<td>$tclsrc/tcl*stub*</td>
<td>stub (in source directory)</td>
</tr>
<tr>
<td>tclgen</td>
<td>$tclsrc/generic</td>
<td></td>
</tr>
<tr>
<td>tclver</td>
<td>tcl version</td>
<td></td>
</tr>
</tbody>
</table>
<p>(Defaults) <code>tkdir /path/to/installed_Tk</code><br>
(cmdline) <code>-tkdir=/path/to/installed_Tk</code></p>
<table>
<thead>
<tr>
<th>variable</th>
<th>value</th>
<th>info</th>
</tr>
</thead>
<tbody>
<tr>
<td>tkbin</td>
<td>$tkdir/bin</td>
<td></td>
</tr>
<tr>
<td>tksh</td>
<td>$tkdir/bin/wish*</td>
<td></td>
</tr>
<tr>
<td>tkinc</td>
<td>$tkdir/include</td>
<td></td>
</tr>
<tr>
<td>tklib</td>
<td>$tkdir/lib</td>
<td></td>
</tr>
<tr>
<td>tkstub</td>
<td>$tkdir/lib/tk*stub*</td>
<td></td>
</tr>
<tr>
<td>tkver</td>
<td>Tk version</td>
<td></td>
</tr>
</tbody>
</table>
<p>(Defaults) <code>tclsrc /path/to/Tk_source_dir</code><br>
(cmdline) <code>-tclsrc=/path/to/Tk_source_dir</code></p>
<table>
<thead>
<tr>
<th>variable</th>
<th>value</th>
<th>info</th>
</tr>
</thead>
<tbody>
<tr>
<td>tklbry</td>
<td>$tksrc/library</td>
<td></td>
</tr>
<tr>
<td>tkobjd</td>
<td>$tksrc/obj_dir</td>
<td>dir containing Tk object files</td>
</tr>
<tr>
<td>tkwishsd</td>
<td>$tksrc/wish*</td>
<td></td>
</tr>
<tr>
<td>tkstubsd</td>
<td>$tksrc/tk*stub*</td>
<td></td>
</tr>
<tr>
<td>tkgen</td>
<td>$tksrc/generic</td>
<td></td>
</tr>
<tr>
<td>tkver</td>
<td>Tk version</td>
<td></td>
</tr>
</tbody>
</table>

</body>
</html>
