~ubuntu-branches/ubuntu/intrepid/ruby1.8/intrepid-updates

« back to all changes in this revision

Viewing changes to ext/tk/sample/tkextlib/tkHTML/page3/index.html

  • Committer: Bazaar Package Importer
  • Author(s): akira yamada
  • Date: 2007-03-13 22:11:58 UTC
  • mfrom: (1.1.5 upstream)
  • Revision ID: james.westby@ubuntu.com-20070313221158-h3oql37brlaf2go2
Tags: 1.8.6-1
* new upstream version, 1.8.6.
* libruby1.8 conflicts with libopenssl-ruby1.8 (< 1.8.6) (closes: #410018)
* changed packaging style to cdbs from dbs.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
<html><body bgcolor="white">
 
2
<hr>
 
3
<h1 align="center">Embedding Tcl in C/C++ Applications</h1>
 
4
 
 
5
    <table width="100%">
 
6
    <tr><td valign="top" align="left" width="46%">
 
7
    <b>Presented At:</b>
 
8
  <blockquote>
 
9
     The&nbsp;Tcl2K&nbsp;Conference<br>
 
10
     Austin, Texas<br>
 
11
     <nobr>9:00am, February 15, 2000</nobr><br>
 
12
  </blockquote>
 
13
    </td>
 
14
    <td width="5%">&nbsp;</td>
 
15
    <td valign="top" align="left" width="46%">
 
16
    <b>Instructor:</b>
 
17
  <blockquote>
 
18
     D. Richard Hipp<br>
 
19
     drh@hwaci.com<br>
 
20
     http://www.hwaci.com/drh/<br>
 
21
     704.948.4565
 
22
  </blockquote>
 
23
    </td></tr>
 
24
    </table><p>
 
25
  <center><table border="2">
 
26
  <tr><td>
 
27
  <p align="center">
 
28
  Copies of these notes, example source code,<br>and other
 
29
  resources related to this tutorial<br>are available online at
 
30
  <a href="http://www.hwaci.com/tcl2k/">
 
31
  http://www.hwaci.com/tcl2k/</a></p>
 
32
  <p align="center"><small>$Id: index.html 11708 2007-02-12 23:01:19Z shyouhei $</small></p></td></tr>
 
33
  </table>
 
34
  </center>
 
35
</p>
 
36
 
 
37
<br clear="both"><p><hr></p>
 
38
<h2 align="center">Tutorial Outline</h2>
 
39
<p><ul><li>Introduction</li>
 
40
<li>Building It Yourself</li>
 
41
<ul><li>"Hello, World!" using Tcl</li>
 
42
<li>Tcl scripts as C strings</li>
 
43
<li>Adding new Tcl commands</li>
 
44
<li>A tour of the Tcl API</li>
 
45
<li>Tcl initialization scripts</li>
 
46
<li>Adding Tk</li>
 
47
</ul><li>Tools Survey</li>
 
48
<li>Mktclapp</li>
 
49
<ul><li>"Hello World" using mktclapp</li>
 
50
<li>Adding C code</li>
 
51
<li>Other Features</li>
 
52
<li>Invoking Tcl from C</li>
 
53
<li>Running mktclapp directly</li>
 
54
<li>Real-world examples</li>
 
55
</ul><li>Summary</li>
 
56
</ul></p>
 
57
<br clear="both"><p><hr></p>
 
58
<h2 align="center">Embedding Tcl in C/C++ Applications</h2>
 
59
<p><ul><li>You know how to program in Tcl/Tk</li></ul><ul><li>You know how to program in C/C++</li></ul><ul><li>This tutorial is about how to do both at the same time.</li></ul></p>
 
60
<br clear="both"><p><hr></p>
 
61
<h2 align="center">Why Mix C With Tcl/Tk?</h2>
 
62
<p><ul><li>Use C for the things C is good at and Tcl for the things
 
63
  Tcl is good at.</li></ul><ul><li>Generate standalone executables.
 
64
  <ul><li>Eliminate the need to install Tcl/Tk.</li>
 
65
  <li>Prevent problems when the wrong version of Tcl/Tk is installed.</li>
 
66
  </ul></li></ul><ul><li>Prevent end users from changing the source code.
 
67
  <ul><li>Keeps users from creating new bugs.</li>
 
68
  <li>Protects proprietary code.</li>
 
69
  </ul></li></ul><ul><li>Office politics</li></ul><ul><li>Use Tcl/Tk as a portability layer for a large C program</li></ul><ul><li>Use Tcl as a testing interface</li></ul></p>
 
70
<br clear="both"><p><hr></p>
 
71
<h2 align="center">Why Mix C With Tcl/Tk?</h2>
 
72
<p><blockquote><big><b>
 
73
  "Use C for the things C is good at and use Tcl/Tk for the things
 
74
  Tcl/Tk is good at."
 
75
  </b></blockquote></p><p>
 
76
 
 
77
    <table width="100%">
 
78
    <tr><td valign="top" align="left" width="46%">
 
79
    <b>C is good at:</b>
 
80
  <ul>
 
81
  <li>Speed</li>
 
82
  <li>Complex data structures</li>
 
83
  <li>Computation</li>
 
84
  <li>Interacting with hardware</li>
 
85
  <li>Byte-by-byte data analysis</li>
 
86
  </ul>
 
87
    </td>
 
88
    <td width="5%">&nbsp;</td>
 
89
    <td valign="top" align="left" width="46%">
 
90
    <b>Tcl/Tk is good at:</b>
 
91
  <ul>
 
92
  <li>Building a user interface</li>
 
93
  <li>Manipulation of strings</li>
 
94
  <li>Portability</li>
 
95
  <li>Opening sockets</li>
 
96
  <li>Handling events</li>
 
97
  </ul>
 
98
    </td></tr>
 
99
    </table>
 
100
<br clear="both"><p><hr></p>
 
101
<h2 align="center">Programming Models</h2>
 
102
<table width="100%">
 
103
<tr><td valign="top" width="49%">
 
104
 
 
105
  <p><b>Mainstream Tcl Programming Model:</b></p>
 
106
</td>
 
107
<td width="2%">&nbsp;</td>
 
108
<td valign="top" width="49%">
 
109
 
 
110
  <p><b>Embedded Tcl Programming Model:&nbsp;&nbsp;</b></p>
 
111
</td></tr>
 
112
<tr><td valign="top" width="49%">
 
113
 
 
114
  <ul><li>Add bits of C code to a large Tcl program</li></ul>
 
115
</td>
 
116
<td width="2%">&nbsp;</td>
 
117
<td valign="top" width="49%">
 
118
 
 
119
  <ul><li>Add bits of Tcl code to a large C program</li></ul>
 
120
</td></tr>
 
121
<tr><td valign="top" width="49%">
 
122
 
 
123
  <ul><li>Main Tcl script loads extensions written in C</li></ul>
 
124
</td>
 
125
<td width="2%">&nbsp;</td>
 
126
<td valign="top" width="49%">
 
127
 
 
128
  <ul><li>Main C procedure invokes the Tcl interpreter</li></ul>
 
129
</td></tr>
 
130
<tr><td valign="top" width="49%">
 
131
 
 
132
  <ul><li>Tcl/Tk is a programming language</li></ul>
 
133
</td>
 
134
<td width="2%">&nbsp;</td>
 
135
<td valign="top" width="49%">
 
136
 
 
137
  <ul><li>Tcl/Tk is a C library</li></ul>
 
138
</td></tr>
 
139
<tr><td valign="top" width="49%">
 
140
 
 
141
  <center><img src="image1"><br>
 
142
  Most of the Tcl2K conference is about</center>
 
143
</td>
 
144
<td width="2%">&nbsp;</td>
 
145
<td valign="top" width="49%">
 
146
 
 
147
  <center><img src="image1"><br>
 
148
  This tutorial is about</center>
 
149
</td></tr>
 
150
</table>
 
151
 
 
152
<br clear="both"><p><hr></p>
 
153
<h2 align="center">"Hello, World!" Using The Tcl Library</h2>
 
154
<table cellspacing="0" cellpadding="0" border="0">
 
155
<tr><td valign="center">
 
156
<small><tt>#include&nbsp;&lt;tcl.h></tt></small></td>
 
157
<td>&nbsp;&nbsp;</td>
 
158
<td valign="center"><img src="image2"></td>
 
159
<td>&nbsp;&nbsp;</td>
 
160
<td valign="center">Always include &lt;tcl.h></td>
 
161
</tr>
 
162
<tr><td valign="center">
 
163
<small><tt>int&nbsp;main(int&nbsp;argc,&nbsp;char&nbsp;**argv){<br>
 
164
&nbsp;&nbsp;Tcl_Interp&nbsp;*interp;</tt></small></td>
 
165
<td></td><td></td><td></td><td></td>
 
166
</tr>
 
167
<tr><td valign="center">
 
168
<small><tt>&nbsp;&nbsp;interp&nbsp;=&nbsp;Tcl_CreateInterp();</tt></small></td>
 
169
<td>&nbsp;&nbsp;</td>
 
170
<td valign="center"><img src="image2"></td>
 
171
<td>&nbsp;&nbsp;</td>
 
172
<td valign="center">Create a new Tcl interpreter</td>
 
173
</tr>
 
174
<tr><td valign="center">
 
175
<small><tt>&nbsp;&nbsp;Tcl_Eval(interp,&nbsp;"puts&nbsp;{Hello,&nbsp;World!}");</tt></small></td>
 
176
<td>&nbsp;&nbsp;</td>
 
177
<td valign="center"><img src="image2"></td>
 
178
<td>&nbsp;&nbsp;</td>
 
179
<td valign="center">Execute a Tcl command.</td>
 
180
</tr>
 
181
<tr><td valign="center">
 
182
<small><tt>&nbsp;&nbsp;return&nbsp;0;<br>
 
183
}</tt></small></td>
 
184
<td></td><td></td><td></td><td></td>
 
185
</tr>
 
186
</table>
 
187
 
 
188
<br clear="both"><p><hr></p>
 
189
<h2 align="center">Compiling "Hello, World!"</h2>
 
190
<p><p><b>Unix:</b></p>
 
191
  <blockquote><tt>
 
192
  $ gcc hello.c -ltcl -lm -ldl<br>
 
193
  $ ./a.out<br>
 
194
  Hello, World!</tt></blockquote>
 
195
 
 
196
  <p><b>Windows using Cygwin:</b></p>
 
197
  <blockquote><tt>
 
198
  C:> gcc hello.c -ltcl80 -lm<br>
 
199
  C:> a.exe<br>
 
200
  Hello, World!</tt></blockquote>
 
201
 
 
202
  <p><b>Windows using Mingw32:</b></p>
 
203
  <blockquote><tt>
 
204
  C:> gcc -mno-cygwin hello.c -ltcl82 -lm<br>
 
205
  </tt></blockquote>
 
206
<table><tr><td valign="top"><img src="image3"></td>
 
207
<td valign="top"><b>Also works with VC++</b></td></tr></table></p>
 
208
<br clear="both"><p><hr></p>
 
209
<h2 align="center">Where Does <tt>-ltcl</tt> Come From On Unix?</h2>
 
210
<p><p>Build it yourself using these steps:</p></p><p>
 
211
<p><ul><li>Get tcl8.2.2.tar.gz from Scriptics</li></ul><ul><li><tt>zcat tcl8.2.2.tar.gz | tar vx </tt></li></ul><ul><li><tt>cd tcl8.2.2/unix</tt></li></ul><ul><li><tt>./configure --disable-shared</tt></li></ul><ul><li><tt>make</tt></li></ul><ul><li>Move <b>libtcl8.2.a</b> to your lib directory.</li></ul><ul><li>Copy <b>../generic/tcl.h</b> into /usr/include.</li></ul></p>
 
212
<br clear="both"><p><hr></p>
 
213
<h2 align="center">What Other Libraries Are Required For Unix?</h2>
 
214
<p><ul><li>The sequence of <b>-l</b> options after <b>-ltcl</b>
 
215
  varies from system to system</li></ul><ul><li>Observe what libraries the TCL makefile inserts when
 
216
  it is building <b>tclsh</b></li></ul><ul><li>Examples in this talk are for RedHat Linux 6.0 for Intel</li></ul></p>
 
217
<br clear="both"><p><hr></p>
 
218
<h2 align="center">How To Compile Under Unix Without Installing Tcl</h2>
 
219
<p><p>Specify the *.a file directly:</p>
 
220
  <blockquote><pre>
 
221
  $ gcc -I../tcl8.2.2/generic hello.c \ 
 
222
      ../tcl8.2.2/unix/libtcl8.2.a -lm -ldl
 
223
  $ strip a.out
 
224
  $ ./a.out
 
225
  Hello, World!</pre></blockquote>
 
226
 
 
227
  <p>Or, tell the C compiler where to look for *.a files:</p>
 
228
  <blockquote><pre>
 
229
  $ gcc -I../tcl8.2.2/generic hello.c \ 
 
230
      -L../tcl8.2.2/unix -ltcl -lm -ldl
 
231
  $ strip a.out
 
232
  $ ./a.out
 
233
  Hello, World!</pre></blockquote>
 
234
<table><tr><td valign="top"><img src="image3"></td>
 
235
<td valign="top"><b>The <tt>-I../tcl8.2.2</tt> argument
 
236
  tells the compiler where to
 
237
  find <tt>&lt;tcl.h&gt;</tt>.</p></b></td></tr></table></p>
 
238
<br clear="both"><p><hr></p>
 
239
<h2 align="center">What's "Cygwin"?</h2>
 
240
<p><ul><li>An implementation of GCC/G++ and all development tools
 
241
  for Windows95/98/NT/2000</li></ul><ul><li>Available for free download at
 
242
  <blockquote>
 
243
  <tt>http://sourceware.cygnus.com/cygwin/</tt>
 
244
  </blockquote></li></ul><ul><li>Also available shrink-wrapped at your local software retailer or
 
245
  online at
 
246
  <blockquote>
 
247
  <tt>http://www.cygnus.com/cygwin/index.html</tt>
 
248
  </blockquote></li></ul><ul><li>Programs compiled using Cygwin require a special
 
249
  DLL (<b>cygwin1.dll</b>) that provides a POSIX system API</li></ul><ul><li>Cygwin1.dll cannot be shipped with proprietary programs
 
250
  without purchasing a license from Cygnus.</li></ul><ul><li>Mingw32 is the same compiler as Cygwin, but generates
 
251
  binaries that do not use cygwin1.dll</li></ul></p>
 
252
<br clear="both"><p><hr></p>
 
253
<h2 align="center">Where Does <tt>-ltcl82</tt> Come From On Windows?</h2>
 
254
<p><p>Build it like this:</p></p><p>
 
255
<p><ul><li>Get <b>tcl82.lib</b> and <b>tcl82.dll</b> from Scriptics.</li></ul><ul><li><tt>echo EXPORTS >tcl82.def</tt></li></ul><ul><li><tt>nm tcl82.lib | grep 'T _' | sed 's/.* T _//' >>tcl82.def</tt></li></ul><ul><li><tt>dlltool --def tcl82.def --dllname tcl82.dll --output-lib libtcl82.a</tt></li></ul><ul><li>Move <b>libtcl82.a</b> to the lib directory and <b>tcl82.dll</b>
 
256
  to the bin directory.</li></ul></p>
 
257
<br clear="both"><p><hr></p>
 
258
<h2 align="center">Where Does Your Code Go?</h2>
 
259
<table cellspacing="0" cellpadding="0" border="0">
 
260
<tr><td valign="center">
 
261
<small><tt>#include&nbsp;&lt;tcl.h><br>
 
262
&nbsp;<br>
 
263
int&nbsp;main(int&nbsp;argc,&nbsp;char&nbsp;**argv){<br>
 
264
&nbsp;&nbsp;Tcl_Interp&nbsp;*interp;<br>
 
265
&nbsp;&nbsp;interp&nbsp;=&nbsp;Tcl_CreateInterp();</tt></small></td>
 
266
<td></td><td></td><td></td><td></td>
 
267
</tr>
 
268
<tr><td valign="center">
 
269
<small><tt>&nbsp;&nbsp;/*&nbsp;Your&nbsp;application&nbsp;code&nbsp;goes&nbsp;here&nbsp;*/</tt></small></td>
 
270
<td>&nbsp;&nbsp;</td>
 
271
<td valign="center"><img src="image2"></td>
 
272
<td>&nbsp;&nbsp;</td>
 
273
<td valign="center">Insert C code here to do whatever it is your program is
 
274
  suppose to do</td>
 
275
</tr>
 
276
<tr><td valign="center">
 
277
<small><tt>&nbsp;&nbsp;return&nbsp;0;<br>
 
278
}</tt></small></td>
 
279
<td></td><td></td><td></td><td></td>
 
280
</tr>
 
281
</table>
 
282
 
 
283
<br clear="both"><p><hr></p>
 
284
<h2 align="center">Building A Simple TCLSH</h2>
 
285
<table cellspacing="0" cellpadding="0" border="0">
 
286
<tr><td valign="center">
 
287
<small><tt>#include&nbsp;&lt;tcl.h><br>
 
288
&nbsp;<br>
 
289
int&nbsp;main(int&nbsp;argc,&nbsp;char&nbsp;**argv){<br>
 
290
&nbsp;&nbsp;Tcl_Interp&nbsp;*interp;<br>
 
291
&nbsp;&nbsp;char&nbsp;*z;<br>
 
292
&nbsp;&nbsp;char&nbsp;zLine[2000];<br>
 
293
&nbsp;&nbsp;interp&nbsp;=&nbsp;Tcl_CreateInterp();</tt></small></td>
 
294
<td></td><td></td><td></td><td></td>
 
295
</tr>
 
296
<tr><td valign="center">
 
297
<small><tt>&nbsp;&nbsp;while(&nbsp;fgets(zLine,sizeof(zLine),stdin)&nbsp;){</tt></small></td>
 
298
<td>&nbsp;&nbsp;</td>
 
299
<td valign="center"><img src="image2"></td>
 
300
<td>&nbsp;&nbsp;</td>
 
301
<td valign="center">Get one line of input</td>
 
302
</tr>
 
303
<tr><td valign="center">
 
304
<small><tt>&nbsp;&nbsp;&nbsp;&nbsp;Tcl_Eval(interp,&nbsp;zLine);</tt></small></td>
 
305
<td>&nbsp;&nbsp;</td>
 
306
<td valign="center"><img src="image2"></td>
 
307
<td>&nbsp;&nbsp;</td>
 
308
<td valign="center">Execute the input as Tcl.</td>
 
309
</tr>
 
310
<tr><td valign="center">
 
311
<small><tt>&nbsp;&nbsp;&nbsp;&nbsp;z&nbsp;=&nbsp;Tcl_GetStringResult(interp);<br>
 
312
&nbsp;&nbsp;&nbsp;&nbsp;if(&nbsp;z[0]&nbsp;){<br>
 
313
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;printf("����P�X�\n",&nbsp;z);<br>
 
314
&nbsp;&nbsp;&nbsp;&nbsp;}</tt></small></td>
 
315
<td>&nbsp;&nbsp;</td>
 
316
<td valign="center"><img src="image2"></td>
 
317
<td>&nbsp;&nbsp;</td>
 
318
<td valign="center">Print result if not empty</td>
 
319
</tr>
 
320
<tr><td valign="center">
 
321
<small><tt>&nbsp;&nbsp;}<br>
 
322
&nbsp;&nbsp;return&nbsp;0;<br>
 
323
}</tt></small></td>
 
324
<td></td><td></td><td></td><td></td>
 
325
</tr>
 
326
</table>
 
327
<p><table><tr><td valign="top"><img src="image3"></td>
 
328
<td valign="top"><b>What if user types more than 2000 characters?</b></td></tr></table>
 
329
</p>
 
330
 
 
331
<br clear="both"><p><hr></p>
 
332
<h2 align="center">Building A Simple TCLSH</h2>
 
333
<p>Use TCL to handle input.  Allows input lines of unlimited length.</p><p>
 
334
<table cellspacing="0" cellpadding="0" border="0">
 
335
<tr><td valign="center">
 
336
<small><tt>#include&nbsp;&lt;tcl.h><br>
 
337
&nbsp;<br>
 
338
/*&nbsp;Tcl&nbsp;code&nbsp;to&nbsp;implement&nbsp;the<br>
 
339
**&nbsp;input&nbsp;loop&nbsp;*/<br>
 
340
static&nbsp;char&nbsp;zLoop[]&nbsp;=&nbsp;<br>
 
341
&nbsp;&nbsp;"while&nbsp;{![eof&nbsp;stdin]}&nbsp;{\n"</tt></small></td>
 
342
<td></td><td></td><td></td><td></td>
 
343
</tr>
 
344
<tr><td valign="center">
 
345
<small><tt>&nbsp;&nbsp;"&nbsp;&nbsp;set&nbsp;line&nbsp;[gets&nbsp;stdin]\n"</tt></small></td>
 
346
<td>&nbsp;&nbsp;</td>
 
347
<td valign="center"><img src="image2"></td>
 
348
<td>&nbsp;&nbsp;</td>
 
349
<td valign="center">Get one line of input</td>
 
350
</tr>
 
351
<tr><td valign="center">
 
352
<small><tt>&nbsp;&nbsp;"&nbsp;&nbsp;set&nbsp;result&nbsp;[eval&nbsp;$line]\n"</tt></small></td>
 
353
<td>&nbsp;&nbsp;</td>
 
354
<td valign="center"><img src="image2"></td>
 
355
<td>&nbsp;&nbsp;</td>
 
356
<td valign="center">Execute input as Tcl</td>
 
357
</tr>
 
358
<tr><td valign="center">
 
359
<small><tt>&nbsp;&nbsp;"&nbsp;&nbsp;if&nbsp;{$result!=\"\"}&nbsp;{puts&nbsp;$result}\n"</tt></small></td>
 
360
<td>&nbsp;&nbsp;</td>
 
361
<td valign="center"><img src="image2"></td>
 
362
<td>&nbsp;&nbsp;</td>
 
363
<td valign="center">Print result</td>
 
364
</tr>
 
365
<tr><td valign="center">
 
366
<small><tt>&nbsp;&nbsp;"}\n"<br>
 
367
;<br>
 
368
&nbsp;<br>
 
369
<br>
 
370
int&nbsp;main(int&nbsp;argc,&nbsp;char&nbsp;**argv){<br>
 
371
&nbsp;&nbsp;Tcl_Interp&nbsp;*interp;<br>
 
372
&nbsp;&nbsp;interp&nbsp;=&nbsp;Tcl_CreateInterp();</tt></small></td>
 
373
<td></td><td></td><td></td><td></td>
 
374
</tr>
 
375
<tr><td valign="center">
 
376
<small><tt>&nbsp;&nbsp;Tcl_Eval(interp,&nbsp;zLoop);</tt></small></td>
 
377
<td>&nbsp;&nbsp;</td>
 
378
<td valign="center"><img src="image2"></td>
 
379
<td>&nbsp;&nbsp;</td>
 
380
<td valign="center">Run the Tcl input loop</td>
 
381
</tr>
 
382
<tr><td valign="center">
 
383
<small><tt>&nbsp;&nbsp;return&nbsp;0;<br>
 
384
}</tt></small></td>
 
385
<td></td><td></td><td></td><td></td>
 
386
</tr>
 
387
</table>
 
388
<p><table><tr><td valign="top"><img src="image3"></td>
 
389
<td valign="top"><b>But what about commands that span multiple lines of input?</b></td></tr></table>
 
390
</p>
 
391
 
 
392
<br clear="both"><p><hr></p>
 
393
<h2 align="center">Better Handling Of Command-Line Input</h2>
 
394
<p>The file "input.tcl"</p><p>
 
395
<table cellspacing="0" cellpadding="0" border="0">
 
396
<tr><td valign="center">
 
397
<small><tt>set&nbsp;line&nbsp;{}<br>
 
398
while&nbsp;{![eof&nbsp;stdin]}&nbsp;{</tt></small></td>
 
399
<td></td><td></td><td></td><td></td>
 
400
</tr>
 
401
<tr><td valign="center">
 
402
<small><tt>&nbsp;&nbsp;if&nbsp;{$line!=""}&nbsp;{<br>
 
403
&nbsp;&nbsp;&nbsp;&nbsp;puts&nbsp;-nonewline&nbsp;">&nbsp;"<br>
 
404
&nbsp;&nbsp;}&nbsp;else&nbsp;{<br>
 
405
&nbsp;&nbsp;&nbsp;&nbsp;puts&nbsp;-nonewline&nbsp;"%&nbsp;"<br>
 
406
&nbsp;&nbsp;}<br>
 
407
&nbsp;&nbsp;flush&nbsp;stdout</tt></small></td>
 
408
<td>&nbsp;&nbsp;</td>
 
409
<td valign="center"><img src="image2"></td>
 
410
<td>&nbsp;&nbsp;</td>
 
411
<td valign="center">Prompt for user input.  The prompt is normally &quot;%&quot;
 
412
  but changes to &quot;&gt;&quot; if the current line is a continuation.</td>
 
413
</tr>
 
414
<tr><td valign="center">
 
415
<small><tt>&nbsp;&nbsp;append&nbsp;line&nbsp;[gets&nbsp;stdin]<br>
 
416
&nbsp;&nbsp;if&nbsp;{[info&nbsp;complete&nbsp;$line]}&nbsp;{</tt></small></td>
 
417
<td></td><td></td><td></td><td></td>
 
418
</tr>
 
419
<tr><td valign="center">
 
420
<small><tt>&nbsp;&nbsp;&nbsp;&nbsp;if&nbsp;{[catch&nbsp;{uplevel&nbsp;#0&nbsp;$line}&nbsp;result]}&nbsp;{</tt></small></td>
 
421
<td>&nbsp;&nbsp;</td>
 
422
<td valign="center"><img src="image2"></td>
 
423
<td>&nbsp;&nbsp;</td>
 
424
<td valign="center">If the command is complete, execute it.</td>
 
425
</tr>
 
426
<tr><td valign="center">
 
427
<small><tt>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;puts&nbsp;stderr&nbsp;"Error:&nbsp;$result"<br>
 
428
&nbsp;&nbsp;&nbsp;&nbsp;}&nbsp;elseif&nbsp;{$result!=""}&nbsp;{<br>
 
429
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;puts&nbsp;$result<br>
 
430
&nbsp;&nbsp;&nbsp;&nbsp;}<br>
 
431
&nbsp;&nbsp;&nbsp;&nbsp;set&nbsp;line&nbsp;{}</tt></small></td>
 
432
<td></td><td></td><td></td><td></td>
 
433
</tr>
 
434
<tr><td valign="center">
 
435
<small><tt>&nbsp;&nbsp;}&nbsp;else&nbsp;{<br>
 
436
&nbsp;&nbsp;&nbsp;&nbsp;append&nbsp;line&nbsp;\n<br>
 
437
&nbsp;&nbsp;}</tt></small></td>
 
438
<td>&nbsp;&nbsp;</td>
 
439
<td valign="center"><img src="image2"></td>
 
440
<td>&nbsp;&nbsp;</td>
 
441
<td valign="center">If the command is incomplete, append a newline and get
 
442
  another line of text.</td>
 
443
</tr>
 
444
<tr><td valign="center">
 
445
<small><tt>}</tt></small></td>
 
446
<td></td><td></td><td></td><td></td>
 
447
</tr>
 
448
</table>
 
449
 
 
450
<br clear="both"><p><hr></p>
 
451
<h2 align="center">Better Handling Of Command-Line Input</h2>
 
452
<p>The file "input.c"</p><p>
 
453
<table cellspacing="0" cellpadding="0" border="0">
 
454
<tr><td valign="center">
 
455
<small><tt>#include&nbsp;&lt;tcl.h><br>
 
456
&nbsp;<br>
 
457
int&nbsp;main(int&nbsp;argc,&nbsp;char&nbsp;**argv){<br>
 
458
&nbsp;&nbsp;Tcl_Interp&nbsp;*interp;<br>
 
459
&nbsp;&nbsp;interp&nbsp;=&nbsp;Tcl_CreateInterp();</tt></small></td>
 
460
<td></td><td></td><td></td><td></td>
 
461
</tr>
 
462
<tr><td valign="center">
 
463
<small><tt>&nbsp;&nbsp;Tcl_Eval(interp,&nbsp;"source&nbsp;input.tcl");</tt></small></td>
 
464
<td>&nbsp;&nbsp;</td>
 
465
<td valign="center"><img src="image2"></td>
 
466
<td>&nbsp;&nbsp;</td>
 
467
<td valign="center">Read and execute the input loop</td>
 
468
</tr>
 
469
<tr><td valign="center">
 
470
<small><tt>&nbsp;&nbsp;return&nbsp;0;<br>
 
471
}</tt></small></td>
 
472
<td></td><td></td><td></td><td></td>
 
473
</tr>
 
474
</table>
 
475
<p><table><tr><td valign="top"><img src="image3"></td>
 
476
<td valign="top"><b>But now the program is not standalone!</b></td></tr></table>
 
477
</p>
 
478
 
 
479
<br clear="both"><p><hr></p>
 
480
<h2 align="center">Converting Scripts Into C Strings</h2>
 
481
<table cellspacing="0" cellpadding="0" border="0">
 
482
<tr><td valign="center">
 
483
<small><tt>static&nbsp;char&nbsp;zInputLoop[]&nbsp;=&nbsp;<br>
 
484
&nbsp;&nbsp;"set&nbsp;line&nbsp;{}\n"<br>
 
485
&nbsp;&nbsp;"while&nbsp;{![eof&nbsp;stdin]}&nbsp;{\n"<br>
 
486
&nbsp;&nbsp;"&nbsp;&nbsp;if&nbsp;{$line!=\"\"}&nbsp;{\n"<br>
 
487
&nbsp;&nbsp;"&nbsp;&nbsp;&nbsp;&nbsp;puts&nbsp;-nonewline&nbsp;\">&nbsp;\"\n"<br>
 
488
&nbsp;&nbsp;"&nbsp;&nbsp;}&nbsp;else&nbsp;{\n"<br>
 
489
&nbsp;&nbsp;"&nbsp;&nbsp;&nbsp;&nbsp;puts&nbsp;-nonewline&nbsp;\"%&nbsp;\"\n"<br>
 
490
&nbsp;&nbsp;"&nbsp;&nbsp;}\n"<br>
 
491
&nbsp;&nbsp;"&nbsp;&nbsp;flush&nbsp;stdout\n"<br>
 
492
&nbsp;&nbsp;"&nbsp;&nbsp;append&nbsp;line&nbsp;[gets&nbsp;stdin]\n"<br>
 
493
&nbsp;&nbsp;"&nbsp;&nbsp;if&nbsp;{[info&nbsp;complete&nbsp;$line]}&nbsp;{\n"<br>
 
494
&nbsp;&nbsp;"&nbsp;&nbsp;&nbsp;&nbsp;if&nbsp;{[catch&nbsp;{uplevel&nbsp;#0&nbsp;$line}&nbsp;result]}&nbsp;{\n"<br>
 
495
&nbsp;&nbsp;"&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;puts&nbsp;stderr&nbsp;\"Error:&nbsp;$result\"\n"<br>
 
496
&nbsp;&nbsp;"&nbsp;&nbsp;&nbsp;&nbsp;}&nbsp;elseif&nbsp;{$result!=\"\"}&nbsp;{\n"<br>
 
497
&nbsp;&nbsp;"&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;puts&nbsp;$result\n"<br>
 
498
&nbsp;&nbsp;"&nbsp;&nbsp;&nbsp;&nbsp;}\n"<br>
 
499
&nbsp;&nbsp;"&nbsp;&nbsp;&nbsp;&nbsp;set&nbsp;line&nbsp;{}\n"<br>
 
500
&nbsp;&nbsp;"&nbsp;&nbsp;}&nbsp;else&nbsp;{\n"<br>
 
501
&nbsp;&nbsp;"&nbsp;&nbsp;&nbsp;&nbsp;append&nbsp;line&nbsp;\\n\n"<br>
 
502
&nbsp;&nbsp;"&nbsp;&nbsp;}\n"<br>
 
503
&nbsp;&nbsp;"}\n"<br>
 
504
;</tt></small></td>
 
505
<td></td><td></td><td></td><td></td>
 
506
</tr>
 
507
</table>
 
508
 
 
509
<br clear="both"><p><hr></p>
 
510
<h2 align="center">Compile Tcl Scripts Into C Programs</h2>
 
511
<table cellspacing="0" cellpadding="0" border="0">
 
512
<tr><td valign="center">
 
513
<small><tt>#include&nbsp;&lt;tcl.h><br>
 
514
</tt></small></td>
 
515
<td></td><td></td><td></td><td></td>
 
516
</tr>
 
517
<tr><td valign="center">
 
518
<small><tt><br>
 
519
static&nbsp;char&nbsp;zInputLoop[]&nbsp;=&nbsp;<br>
 
520
&nbsp;&nbsp;/*&nbsp;Actual&nbsp;code&nbsp;omitted&nbsp;*/<br>
 
521
;</tt></small></td>
 
522
<td>&nbsp;&nbsp;</td>
 
523
<td valign="center"><img src="image2"></td>
 
524
<td>&nbsp;&nbsp;</td>
 
525
<td valign="center">Copy and paste the converted Tcl script here</td>
 
526
</tr>
 
527
<tr><td valign="center">
 
528
<small><tt><br>
 
529
int&nbsp;main(int&nbsp;argc,&nbsp;char&nbsp;**argv){<br>
 
530
&nbsp;&nbsp;Tcl_Interp&nbsp;*interp;<br>
 
531
&nbsp;&nbsp;interp&nbsp;=&nbsp;Tcl_CreateInterp();</tt></small></td>
 
532
<td></td><td></td><td></td><td></td>
 
533
</tr>
 
534
<tr><td valign="center">
 
535
<small><tt>&nbsp;&nbsp;Tcl_Eval(interp,&nbsp;zInputLoop);</tt></small></td>
 
536
<td>&nbsp;&nbsp;</td>
 
537
<td valign="center"><img src="image2"></td>
 
538
<td>&nbsp;&nbsp;</td>
 
539
<td valign="center">Execute the Tcl code</td>
 
540
</tr>
 
541
<tr><td valign="center">
 
542
<small><tt>&nbsp;&nbsp;return&nbsp;0;<br>
 
543
}</tt></small></td>
 
544
<td></td><td></td><td></td><td></td>
 
545
</tr>
 
546
</table>
 
547
 
 
548
<br clear="both"><p><hr></p>
 
549
<h2 align="center">Converting Scripts To Strings<br>Using SED Or TCLSH</h2>
 
550
<table cellspacing="0" cellpadding="0" border="0">
 
551
<tr><td valign="center">
 
552
<small><tt>sed&nbsp;-e&nbsp;'s/\\/\\\\/g'&nbsp;\&nbsp;</tt></small></td>
 
553
<td>&nbsp;&nbsp;</td>
 
554
<td valign="center"><img src="image2"></td>
 
555
<td>&nbsp;&nbsp;</td>
 
556
<td valign="center">Convert <b>\</b> into <b>\\</b></td>
 
557
</tr>
 
558
<tr><td valign="center">
 
559
<small><tt>&nbsp;&nbsp;-e&nbsp;'s/"/\\"/g'&nbsp;\&nbsp;</tt></small></td>
 
560
<td>&nbsp;&nbsp;</td>
 
561
<td valign="center"><img src="image2"></td>
 
562
<td>&nbsp;&nbsp;</td>
 
563
<td valign="center">Convert <b>"</b> into <b>\"</b></td>
 
564
</tr>
 
565
<tr><td valign="center">
 
566
<small><tt>&nbsp;&nbsp;-e&nbsp;'s/^/&nbsp;&nbsp;"/'&nbsp;\&nbsp;</tt></small></td>
 
567
<td>&nbsp;&nbsp;</td>
 
568
<td valign="center"><img src="image2"></td>
 
569
<td>&nbsp;&nbsp;</td>
 
570
<td valign="center">Add <b>"</b> to start of each line</td>
 
571
</tr>
 
572
<tr><td valign="center">
 
573
<small><tt>&nbsp;&nbsp;-e&nbsp;'s/$/\\n"/'&nbsp;input.tcl</tt></small></td>
 
574
<td>&nbsp;&nbsp;</td>
 
575
<td valign="center"><img src="image2"></td>
 
576
<td>&nbsp;&nbsp;</td>
 
577
<td valign="center">Add <b>\n"</b> to end of each line</td>
 
578
</tr>
 
579
<tr><td valign="center">
 
580
<small><tt><br>
 
581
&nbsp;<br>
 
582
<br>
 
583
&nbsp;<br>
 
584
<br>
 
585
while&nbsp;{![eof&nbsp;stdin]}&nbsp;{<br>
 
586
&nbsp;&nbsp;set&nbsp;line&nbsp;[gets&nbsp;stdin]</tt></small></td>
 
587
<td></td><td></td><td></td><td></td>
 
588
</tr>
 
589
<tr><td valign="center">
 
590
<small><tt>&nbsp;&nbsp;regsub&nbsp;-all&nbsp;{\}&nbsp;$line&nbsp;{&amp;&amp;}&nbsp;line</tt></small></td>
 
591
<td>&nbsp;&nbsp;</td>
 
592
<td valign="center"><img src="image2"></td>
 
593
<td>&nbsp;&nbsp;</td>
 
594
<td valign="center">Convert <b>\</b> into <b>\\</b></td>
 
595
</tr>
 
596
<tr><td valign="center">
 
597
<small><tt>&nbsp;&nbsp;regsub&nbsp;-all&nbsp;{"}&nbsp;$line&nbsp;{\"}&nbsp;line</tt></small></td>
 
598
<td>&nbsp;&nbsp;</td>
 
599
<td valign="center"><img src="image2"></td>
 
600
<td>&nbsp;&nbsp;</td>
 
601
<td valign="center">Convert <b>"</b> into <b>\"</b></td>
 
602
</tr>
 
603
<tr><td valign="center">
 
604
<small><tt>&nbsp;&nbsp;puts&nbsp;"\"$line\\n\""</tt></small></td>
 
605
<td>&nbsp;&nbsp;</td>
 
606
<td valign="center"><img src="image2"></td>
 
607
<td>&nbsp;&nbsp;</td>
 
608
<td valign="center">Add <b>"</b> in front and <b>\n"</b> at the end</td>
 
609
</tr>
 
610
<tr><td valign="center">
 
611
<small><tt>}</tt></small></td>
 
612
<td></td><td></td><td></td><td></td>
 
613
</tr>
 
614
</table>
 
615
 
 
616
<br clear="both"><p><hr></p>
 
617
<h2 align="center">Converting Scripts Into C Strings</h2>
 
618
<p>You may want to save space by removing comments and extra whitespace
 
619
  from scripts.</p><p>
 
620
<table cellspacing="0" cellpadding="0" border="0">
 
621
<tr><td valign="center">
 
622
<small><tt>static&nbsp;char&nbsp;zInputLoop[]&nbsp;=&nbsp;<br>
 
623
&nbsp;&nbsp;"set&nbsp;line&nbsp;{}\n"<br>
 
624
&nbsp;&nbsp;"while&nbsp;{![eof&nbsp;stdin]}&nbsp;{\n"<br>
 
625
&nbsp;&nbsp;"if&nbsp;{$line!=\"\"}&nbsp;{\n"<br>
 
626
&nbsp;&nbsp;"puts&nbsp;-nonewline&nbsp;\">&nbsp;\"\n"<br>
 
627
&nbsp;&nbsp;"}&nbsp;else&nbsp;{\n"<br>
 
628
&nbsp;&nbsp;"puts&nbsp;-nonewline&nbsp;\"%&nbsp;\"\n"<br>
 
629
&nbsp;&nbsp;"}\n"<br>
 
630
&nbsp;&nbsp;"flush&nbsp;stdout\n"<br>
 
631
&nbsp;&nbsp;"append&nbsp;line&nbsp;[gets&nbsp;stdin]\n"<br>
 
632
&nbsp;&nbsp;"if&nbsp;{[info&nbsp;complete&nbsp;$line]}&nbsp;{\n"<br>
 
633
&nbsp;&nbsp;"if&nbsp;{[catch&nbsp;{uplevel&nbsp;#0&nbsp;$line}&nbsp;result]}&nbsp;{\n"<br>
 
634
&nbsp;&nbsp;"puts&nbsp;stderr&nbsp;\"Error:&nbsp;$result\"\n"<br>
 
635
&nbsp;&nbsp;"}&nbsp;elseif&nbsp;{$result!=\"\"}&nbsp;{\n"<br>
 
636
&nbsp;&nbsp;"puts&nbsp;$result\n"<br>
 
637
&nbsp;&nbsp;"}\n"<br>
 
638
&nbsp;&nbsp;"set&nbsp;line&nbsp;{}\n"<br>
 
639
&nbsp;&nbsp;"}&nbsp;else&nbsp;{\n"<br>
 
640
&nbsp;&nbsp;"append&nbsp;line&nbsp;\\n\n"<br>
 
641
&nbsp;&nbsp;"}\n"<br>
 
642
&nbsp;&nbsp;"}\n"<br>
 
643
;</tt></small></td>
 
644
<td></td><td></td><td></td><td></td>
 
645
</tr>
 
646
</table>
 
647
 
 
648
<br clear="both"><p><hr></p>
 
649
<h2 align="center">Converting Scripts To Strings</h2>
 
650
<table cellspacing="0" cellpadding="0" border="0">
 
651
<tr><td valign="center">
 
652
<small><tt>sed&nbsp;-e&nbsp;'s/\\/\\\\/g'&nbsp;\&nbsp;<br>
 
653
&nbsp;&nbsp;-e&nbsp;'s/"/\\"/g'&nbsp;\&nbsp;</tt></small></td>
 
654
<td></td><td></td><td></td><td></td>
 
655
</tr>
 
656
<tr><td valign="center">
 
657
<small><tt>&nbsp;&nbsp;-e&nbsp;'/^&nbsp;*#/d'&nbsp;\&nbsp;</tt></small></td>
 
658
<td>&nbsp;&nbsp;</td>
 
659
<td valign="center"><img src="image2"></td>
 
660
<td>&nbsp;&nbsp;</td>
 
661
<td valign="center">Delete lines that begin with #</td>
 
662
</tr>
 
663
<tr><td valign="center">
 
664
<small><tt>&nbsp;&nbsp;-e&nbsp;'/^&nbsp;*$/d'&nbsp;\&nbsp;</tt></small></td>
 
665
<td>&nbsp;&nbsp;</td>
 
666
<td valign="center"><img src="image2"></td>
 
667
<td>&nbsp;&nbsp;</td>
 
668
<td valign="center">Delete blank lines</td>
 
669
</tr>
 
670
<tr><td valign="center">
 
671
<small><tt>&nbsp;&nbsp;-e&nbsp;'s/^&nbsp;*/&nbsp;&nbsp;"/'&nbsp;\&nbsp;</tt></small></td>
 
672
<td>&nbsp;&nbsp;</td>
 
673
<td valign="center"><img src="image2"></td>
 
674
<td>&nbsp;&nbsp;</td>
 
675
<td valign="center">Delete leading spaces</td>
 
676
</tr>
 
677
<tr><td valign="center">
 
678
<small><tt>&nbsp;&nbsp;-e&nbsp;'s/$/\\n"/'&nbsp;input.tcl<br>
 
679
&nbsp;<br>
 
680
<br>
 
681
&nbsp;<br>
 
682
<br>
 
683
&nbsp;<br>
 
684
while&nbsp;{![eof&nbsp;stdin]}&nbsp;{<br>
 
685
&nbsp;&nbsp;set&nbsp;line&nbsp;[gets&nbsp;stdin]</tt></small></td>
 
686
<td></td><td></td><td></td><td></td>
 
687
</tr>
 
688
<tr><td valign="center">
 
689
<small><tt>&nbsp;&nbsp;set&nbsp;line&nbsp;[string&nbsp;trimleft&nbsp;$line]</tt></small></td>
 
690
<td>&nbsp;&nbsp;</td>
 
691
<td valign="center"><img src="image2"></td>
 
692
<td>&nbsp;&nbsp;</td>
 
693
<td valign="center">Remove leading space</td>
 
694
</tr>
 
695
<tr><td valign="center">
 
696
<small><tt>&nbsp;&nbsp;if&nbsp;{$line==""}&nbsp;continue</tt></small></td>
 
697
<td>&nbsp;&nbsp;</td>
 
698
<td valign="center"><img src="image2"></td>
 
699
<td>&nbsp;&nbsp;</td>
 
700
<td valign="center">Delete blank lines</td>
 
701
</tr>
 
702
<tr><td valign="center">
 
703
<small><tt>&nbsp;&nbsp;if&nbsp;{[string&nbsp;index&nbsp;$line&nbsp;0]=="#"}&nbsp;{<br>
 
704
&nbsp;&nbsp;&nbsp;&nbsp;continue<br>
 
705
&nbsp;&nbsp;}</tt></small></td>
 
706
<td>&nbsp;&nbsp;</td>
 
707
<td valign="center"><img src="image2"></td>
 
708
<td>&nbsp;&nbsp;</td>
 
709
<td valign="center">Delete lines starting with #</td>
 
710
</tr>
 
711
<tr><td valign="center">
 
712
<small><tt>&nbsp;&nbsp;regsub&nbsp;-all&nbsp;{\}&nbsp;$line&nbsp;{&amp;&amp;}&nbsp;line<br>
 
713
&nbsp;&nbsp;regsub&nbsp;-all&nbsp;{"}&nbsp;$line&nbsp;{\"}&nbsp;line<br>
 
714
&nbsp;&nbsp;puts&nbsp;"\"$line\\n\""<br>
 
715
}</tt></small></td>
 
716
<td></td><td></td><td></td><td></td>
 
717
</tr>
 
718
</table>
 
719
 
 
720
<br clear="both"><p><hr></p>
 
721
<h2 align="center">Removing Comments Or Leading Space<br>Will Break Some Tcl Scripts!</h2>
 
722
<table cellspacing="0" cellpadding="0" border="0">
 
723
<tr><td valign="center">
 
724
<small><tt>image&nbsp;create&nbsp;bitmap&nbsp;smiley&nbsp;-data&nbsp;{</tt></small></td>
 
725
<td></td><td></td><td></td><td></td>
 
726
</tr>
 
727
<tr><td valign="center">
 
728
<small><tt>#define&nbsp;smile_width&nbsp;15<br>
 
729
#define&nbsp;smile_height&nbsp;15</tt></small></td>
 
730
<td>&nbsp;&nbsp;</td>
 
731
<td valign="center"><img src="image2"></td>
 
732
<td>&nbsp;&nbsp;</td>
 
733
<td valign="center">These lines begin with # but are not comment</td>
 
734
</tr>
 
735
<tr><td valign="center">
 
736
<small><tt>static&nbsp;unsigned&nbsp;char&nbsp;smile_bits[]&nbsp;=&nbsp;{<br>
 
737
&nbsp;&nbsp;&nbsp;0xc0,&nbsp;0x01,&nbsp;0x30,&nbsp;0x06,&nbsp;0x0c,&nbsp;0x18,<br>
 
738
&nbsp;&nbsp;&nbsp;0x04,&nbsp;0x10,&nbsp;0x22,&nbsp;0x22,&nbsp;0x52,&nbsp;0x25,<br>
 
739
&nbsp;&nbsp;&nbsp;0x01,&nbsp;0x40,&nbsp;0x01,&nbsp;0x40,&nbsp;0x01,&nbsp;0x40,<br>
 
740
&nbsp;&nbsp;&nbsp;0x12,&nbsp;0x24,&nbsp;0xe2,&nbsp;0x23,&nbsp;0x04,&nbsp;0x10,<br>
 
741
&nbsp;&nbsp;&nbsp;0x0c,&nbsp;0x18,&nbsp;0x30,&nbsp;0x06,&nbsp;0xc0,&nbsp;0x01};<br>
 
742
}<br>
 
743
&nbsp;<br>
 
744
<br>
 
745
&nbsp;<br>
 
746
text&nbsp;.t<br>
 
747
pack&nbsp;.t<br>
 
748
.t&nbsp;insert&nbsp;end&nbsp;[string&nbsp;trim&nbsp;{</tt></small></td>
 
749
<td></td><td></td><td></td><td></td>
 
750
</tr>
 
751
<tr><td valign="center">
 
752
<small><tt>She&nbsp;walks&nbsp;in&nbsp;beauty,&nbsp;like&nbsp;the&nbsp;night<br>
 
753
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Of&nbsp;cloudless&nbsp;climes&nbsp;and&nbsp;starry&nbsp;skies;<br>
 
754
And&nbsp;all&nbsp;that's&nbsp;best&nbsp;of&nbsp;dark&nbsp;and&nbsp;bright<br>
 
755
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Meet&nbsp;in&nbsp;her&nbsp;aspect&nbsp;and&nbsp;her&nbsp;eyes;</tt></small></td>
 
756
<td>&nbsp;&nbsp;</td>
 
757
<td valign="center"><img src="image2"></td>
 
758
<td>&nbsp;&nbsp;</td>
 
759
<td valign="center">Indentation is deleted on lines 2
 
760
  and 4</td>
 
761
</tr>
 
762
<tr><td valign="center">
 
763
<small><tt>}]&nbsp;<br>
 
764
&nbsp;<br>
 
765
</tt></small></td>
 
766
<td></td><td></td><td></td><td></td>
 
767
</tr>
 
768
</table>
 
769
<p><table><tr><td valign="top"><img src="image3"></td>
 
770
<td valign="top"><b>Problems like these are rare</b></td></tr></table>
 
771
</p>
 
772
 
 
773
<br clear="both"><p><hr></p>
 
774
<h2 align="center">Adding A "continue" Command</h2>
 
775
<table cellspacing="0" cellpadding="0" border="0">
 
776
<tr><td valign="center">
 
777
<small><tt>set&nbsp;line&nbsp;{}<br>
 
778
while&nbsp;{![eof&nbsp;stdin]}&nbsp;{<br>
 
779
&nbsp;&nbsp;if&nbsp;{$line!=""}&nbsp;{<br>
 
780
&nbsp;&nbsp;&nbsp;&nbsp;puts&nbsp;-nonewline&nbsp;">&nbsp;"<br>
 
781
&nbsp;&nbsp;}&nbsp;else&nbsp;{<br>
 
782
&nbsp;&nbsp;&nbsp;&nbsp;puts&nbsp;-nonewline&nbsp;"%&nbsp;"<br>
 
783
&nbsp;&nbsp;}<br>
 
784
&nbsp;&nbsp;flush&nbsp;stdout<br>
 
785
&nbsp;&nbsp;append&nbsp;line&nbsp;[gets&nbsp;stdin]<br>
 
786
&nbsp;&nbsp;if&nbsp;{[info&nbsp;complete&nbsp;$line]}&nbsp;{</tt></small></td>
 
787
<td></td><td></td><td></td><td></td>
 
788
</tr>
 
789
<tr><td valign="center">
 
790
<small><tt>&nbsp;&nbsp;&nbsp;&nbsp;if&nbsp;{[lindex&nbsp;$line&nbsp;0]=="continue"}&nbsp;{<br>
 
791
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;break;</tt></small></td>
 
792
<td>&nbsp;&nbsp;</td>
 
793
<td valign="center"><img src="image2"></td>
 
794
<td>&nbsp;&nbsp;</td>
 
795
<td valign="center">Break out of the loop if the command
 
796
  is "continue"</td>
 
797
</tr>
 
798
<tr><td valign="center">
 
799
<small><tt>&nbsp;&nbsp;&nbsp;&nbsp;}&nbsp;elseif&nbsp;{[catch&nbsp;{uplevel&nbsp;#0&nbsp;$line}&nbsp;result]}&nbsp;{<br>
 
800
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;puts&nbsp;stderr&nbsp;"Error:&nbsp;$result"<br>
 
801
&nbsp;&nbsp;&nbsp;&nbsp;}&nbsp;elseif&nbsp;{$result!=""}&nbsp;{<br>
 
802
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;puts&nbsp;$result<br>
 
803
&nbsp;&nbsp;&nbsp;&nbsp;}<br>
 
804
&nbsp;&nbsp;&nbsp;&nbsp;set&nbsp;line&nbsp;{}<br>
 
805
&nbsp;&nbsp;}&nbsp;else&nbsp;{<br>
 
806
&nbsp;&nbsp;&nbsp;&nbsp;append&nbsp;line&nbsp;\n<br>
 
807
&nbsp;&nbsp;}<br>
 
808
}</tt></small></td>
 
809
<td></td><td></td><td></td><td></td>
 
810
</tr>
 
811
</table>
 
812
 
 
813
<br clear="both"><p><hr></p>
 
814
<h2 align="center">Stop For Tcl Input At Various Points<br>In A C Program</h2>
 
815
<table cellspacing="0" cellpadding="0" border="0">
 
816
<tr><td valign="center">
 
817
<small><tt>#include&nbsp;&lt;tcl.h><br>
 
818
&nbsp;<br>
 
819
static&nbsp;char&nbsp;zInputLoop[]&nbsp;=&nbsp;<br>
 
820
&nbsp;&nbsp;/*&nbsp;Tcl&nbsp;Input&nbsp;loop&nbsp;as&nbsp;a&nbsp;C&nbsp;string&nbsp;*/<br>
 
821
;<br>
 
822
&nbsp;<br>
 
823
int&nbsp;main(int&nbsp;argc,&nbsp;char&nbsp;**argv){<br>
 
824
&nbsp;&nbsp;Tcl_Interp&nbsp;*interp;<br>
 
825
&nbsp;&nbsp;interp&nbsp;=&nbsp;Tcl_CreateInterp();</tt></small></td>
 
826
<td></td><td></td><td></td><td></td>
 
827
</tr>
 
828
<tr><td valign="center">
 
829
<small><tt>&nbsp;&nbsp;/*&nbsp;Application&nbsp;C&nbsp;code&nbsp;*/</tt></small></td>
 
830
<td>&nbsp;&nbsp;</td>
 
831
<td valign="center"><img src="image2"></td>
 
832
<td>&nbsp;&nbsp;</td>
 
833
<td valign="center">Do some computation</td>
 
834
</tr>
 
835
<tr><td valign="center">
 
836
<small><tt>&nbsp;&nbsp;Tcl_Eval(interp,&nbsp;zInputLoop);</tt></small></td>
 
837
<td>&nbsp;&nbsp;</td>
 
838
<td valign="center"><img src="image2"></td>
 
839
<td>&nbsp;&nbsp;</td>
 
840
<td valign="center">Stop for some Tcl input</td>
 
841
</tr>
 
842
<tr><td valign="center">
 
843
<small><tt>&nbsp;&nbsp;/*&nbsp;More&nbsp;application&nbsp;C&nbsp;code&nbsp;*/</tt></small></td>
 
844
<td>&nbsp;&nbsp;</td>
 
845
<td valign="center"><img src="image2"></td>
 
846
<td>&nbsp;&nbsp;</td>
 
847
<td valign="center">Do more computation</td>
 
848
</tr>
 
849
<tr><td valign="center">
 
850
<small><tt>&nbsp;&nbsp;Tcl_Eval(interp,&nbsp;zInputLoop);</tt></small></td>
 
851
<td>&nbsp;&nbsp;</td>
 
852
<td valign="center"><img src="image2"></td>
 
853
<td>&nbsp;&nbsp;</td>
 
854
<td valign="center">Stop for more Tcl input</td>
 
855
</tr>
 
856
<tr><td valign="center">
 
857
<small><tt>&nbsp;&nbsp;/*&nbsp;Finish&nbsp;up&nbsp;the&nbsp;application&nbsp;*/</tt></small></td>
 
858
<td>&nbsp;&nbsp;</td>
 
859
<td valign="center"><img src="image2"></td>
 
860
<td>&nbsp;&nbsp;</td>
 
861
<td valign="center">Finish the computation</td>
 
862
</tr>
 
863
<tr><td valign="center">
 
864
<small><tt>&nbsp;&nbsp;return&nbsp;0;<br>
 
865
}</tt></small></td>
 
866
<td></td><td></td><td></td><td></td>
 
867
</tr>
 
868
</table>
 
869
 
 
870
<br clear="both"><p><hr></p>
 
871
<h2 align="center">Using Tcl For Testing</h2>
 
872
<table cellspacing="0" cellpadding="0" border="0">
 
873
<tr><td valign="center">
 
874
<small><tt>#include&nbsp;&lt;tcl.h><br>
 
875
&nbsp;<br>
 
876
static&nbsp;char&nbsp;zInputLoop[]&nbsp;=&nbsp;<br>
 
877
&nbsp;&nbsp;/*&nbsp;Tcl&nbsp;Input&nbsp;loop&nbsp;as&nbsp;a&nbsp;C&nbsp;string&nbsp;*/<br>
 
878
;<br>
 
879
&nbsp;<br>
 
880
</tt></small></td>
 
881
<td></td><td></td><td></td><td></td>
 
882
</tr>
 
883
<tr><td valign="center">
 
884
<small><tt>int&nbsp;main(int&nbsp;argc,&nbsp;char&nbsp;**argv){<br>
 
885
#ifdef&nbsp;TESTING<br>
 
886
&nbsp;&nbsp;Tcl_Interp&nbsp;*interp;</tt></small></td>
 
887
<td>&nbsp;&nbsp;</td>
 
888
<td valign="center"><img src="image2"></td>
 
889
<td>&nbsp;&nbsp;</td>
 
890
<td valign="center">Create interpreter only if TESTING
 
891
 is defined</td>
 
892
</tr>
 
893
<tr><td valign="center">
 
894
<small><tt>&nbsp;&nbsp;interp&nbsp;=&nbsp;Tcl_CreateInterp();<br>
 
895
#endif<br>
 
896
&nbsp;&nbsp;/*&nbsp;Application&nbsp;C&nbsp;code&nbsp;*/</tt></small></td>
 
897
<td></td><td></td><td></td><td></td>
 
898
</tr>
 
899
<tr><td valign="center">
 
900
<small><tt>#ifdef&nbsp;TESTING<br>
 
901
&nbsp;&nbsp;Tcl_Eval(interp,&nbsp;zInputLoop);<br>
 
902
#endif</tt></small></td>
 
903
<td>&nbsp;&nbsp;</td>
 
904
<td valign="center"><img src="image2"></td>
 
905
<td>&nbsp;&nbsp;</td>
 
906
<td valign="center">Accept command-line input only if TESTING
 
907
  is defined</td>
 
908
</tr>
 
909
<tr><td valign="center">
 
910
<small><tt>&nbsp;&nbsp;/*&nbsp;More&nbsp;application&nbsp;C&nbsp;code&nbsp;*/<br>
 
911
#ifdef&nbsp;TESTING<br>
 
912
&nbsp;&nbsp;Tcl_Eval(interp,&nbsp;zInputLoop);<br>
 
913
#endif<br>
 
914
&nbsp;&nbsp;/*&nbsp;Finish&nbsp;up&nbsp;the&nbsp;application&nbsp;*/<br>
 
915
&nbsp;&nbsp;return&nbsp;0;<br>
 
916
}</tt></small></td>
 
917
<td></td><td></td><td></td><td></td>
 
918
</tr>
 
919
</table>
 
920
 
 
921
<br clear="both"><p><hr></p>
 
922
<h2 align="center">Creating A New Tcl Command In C</h2>
 
923
<table cellspacing="0" cellpadding="0" border="0">
 
924
<tr><td valign="center">
 
925
<small><tt>#include&nbsp;&lt;tcl.h><br>
 
926
&nbsp;<br>
 
927
int&nbsp;NewCmd(</tt></small></td>
 
928
<td></td><td></td><td></td><td></td>
 
929
</tr>
 
930
<tr><td valign="center">
 
931
<small><tt>&nbsp;&nbsp;void&nbsp;*clientData,<br>
 
932
&nbsp;&nbsp;Tcl_Interp&nbsp;*interp,<br>
 
933
&nbsp;&nbsp;int&nbsp;argc,<br>
 
934
&nbsp;&nbsp;char&nbsp;**argv</tt></small></td>
 
935
<td>&nbsp;&nbsp;</td>
 
936
<td valign="center"><img src="image2"></td>
 
937
<td>&nbsp;&nbsp;</td>
 
938
<td valign="center">The Tcl command is implemented as
 
939
  a C function with four arguments.</td>
 
940
</tr>
 
941
<tr><td valign="center">
 
942
<small><tt>){<br>
 
943
&nbsp;&nbsp;printf("Hello,&nbsp;World!\n");</tt></small></td>
 
944
<td></td><td></td><td></td><td></td>
 
945
</tr>
 
946
<tr><td valign="center">
 
947
<small><tt>&nbsp;&nbsp;return&nbsp;TCL_OK;</tt></small></td>
 
948
<td>&nbsp;&nbsp;</td>
 
949
<td valign="center"><img src="image2"></td>
 
950
<td>&nbsp;&nbsp;</td>
 
951
<td valign="center">Returns TCL_OK or TCL_ERROR</td>
 
952
</tr>
 
953
<tr><td valign="center">
 
954
<small><tt>}<br>
 
955
&nbsp;<br>
 
956
static&nbsp;char&nbsp;zInputLoop[]&nbsp;=&nbsp;<br>
 
957
&nbsp;&nbsp;/*&nbsp;Tcl&nbsp;code&nbsp;omitted...&nbsp;*/<br>
 
958
;<br>
 
959
&nbsp;<br>
 
960
int&nbsp;main(int&nbsp;argc,&nbsp;char&nbsp;**argv){<br>
 
961
&nbsp;&nbsp;Tcl_Interp&nbsp;*interp;<br>
 
962
&nbsp;&nbsp;interp&nbsp;=&nbsp;Tcl_CreateInterp();</tt></small></td>
 
963
<td></td><td></td><td></td><td></td>
 
964
</tr>
 
965
<tr><td valign="center">
 
966
<small><tt>&nbsp;&nbsp;Tcl_CreateCommand(interp,&nbsp;"helloworld",<br>
 
967
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;NewCmd,&nbsp;0,&nbsp;0);</tt></small></td>
 
968
<td>&nbsp;&nbsp;</td>
 
969
<td valign="center"><img src="image2"></td>
 
970
<td>&nbsp;&nbsp;</td>
 
971
<td valign="center">Tell the interpreter which C function to call when the
 
972
  "helloworld" Tcl command is executed</td>
 
973
</tr>
 
974
<tr><td valign="center">
 
975
<small><tt>&nbsp;&nbsp;Tcl_Eval(interp,&nbsp;zInputLoop);<br>
 
976
&nbsp;&nbsp;return&nbsp;0;<br>
 
977
}</tt></small></td>
 
978
<td></td><td></td><td></td><td></td>
 
979
</tr>
 
980
</table>
 
981
 
 
982
<br clear="both"><p><hr></p>
 
983
<h2 align="center">Linkage From Tcl To C</h2>
 
984
<p><p align="center"><img src="image4"></p></p><p><ul><li>3rd parameter of Tcl_CreateCommand() is a pointer to the C subroutine
 
985
 that implements the command.</li></ul><ul><li>4th parameter to Tcl_CreateCommand() becomes the 1st parameter to 
 
986
 the C routine whenever the Tcl command is executed.</li></ul><ul><li>1st parameter to Tcl_CreateCommand() must be a valid Tcl interpreter.
 
987
 The same pointer appears as the second parameter to the C routine
 
988
 whenever the Tcl command is executed.</li></ul></p>
 
989
 
 
990
<br clear="both"><p><hr></p>
 
991
<h2 align="center">Linkage From Tcl To C</h2>
 
992
<p><p align="center"><img src="image5"></p></p><p><ul><li>5th parameter of Tcl_CreateCommand() is a pointer to the C subroutine
 
993
 that is called when the Tcl command is deleted.</li></ul><ul><li>4th parameter to Tcl_CreateCommand() becomes the 1st parameter to 
 
994
 the C routine.</li></ul></p>
 
995
 
 
996
<br clear="both"><p><hr></p>
 
997
<h2 align="center">When To Use A Delete Proc</h2>
 
998
<p>Examples of where the delete proc is used in standard Tcl/Tk:</p><p>
 
999
<table cellspacing="0" cellpadding="0" border="0">
 
1000
<tr><td valign="center">
 
1001
<small><tt>button&nbsp;.b&nbsp;-text&nbsp;Hello<br>
 
1002
pack&nbsp;.b</tt></small></td>
 
1003
<td></td><td></td><td></td><td></td>
 
1004
</tr>
 
1005
<tr><td valign="center">
 
1006
<small><tt>rename&nbsp;.b&nbsp;{}</tt></small></td>
 
1007
<td>&nbsp;&nbsp;</td>
 
1008
<td valign="center"><img src="image2"></td>
 
1009
<td>&nbsp;&nbsp;</td>
 
1010
<td valign="center">Deleting the <b>.b</b> command causes the button to be destroyed</td>
 
1011
</tr>
 
1012
<tr><td valign="center">
 
1013
<small><tt><br>
 
1014
&nbsp;<br>
 
1015
</tt></small></td>
 
1016
<td></td><td></td><td></td><td></td>
 
1017
</tr>
 
1018
<tr><td valign="center">
 
1019
<small><tt>image&nbsp;create&nbsp;photo&nbsp;smiley&nbsp;\&nbsp;<br>
 
1020
&nbsp;&nbsp;&nbsp;&nbsp;-file&nbsp;smiley.gif</tt></small></td>
 
1021
<td></td><td></td><td></td><td></td>
 
1022
</tr>
 
1023
<tr><td valign="center">
 
1024
<small><tt>rename&nbsp;smiley&nbsp;{}</tt></small></td>
 
1025
<td>&nbsp;&nbsp;</td>
 
1026
<td valign="center"><img src="image2"></td>
 
1027
<td>&nbsp;&nbsp;</td>
 
1028
<td valign="center">Deleting the <b>smiley</b> command destroys the image and reclaims the
 
1029
  memory used to hold the image</td>
 
1030
</tr>
 
1031
</table>
 
1032
<p><ul><li>Always use a delete proc if the clientData is a pointer to
 
1033
  malloced memory or some other resource that needs freeing</li></ul><ul><li>Delete procs are never used in the Tcl core but are used
 
1034
  extensively in Tk</li></ul></p>
 
1035
 
 
1036
<br clear="both"><p><hr></p>
 
1037
<h2 align="center">Linkage From Tcl To C</h2>
 
1038
<p>The <tt>argc</tt> and <tt>argv</tt> parameters work just like in 
 
1039
 <tt>main()</tt></p><p>
 
1040
<table cellspacing="0" cellpadding="0" border="0">
 
1041
<tr><td valign="center">
 
1042
<small><tt>helloworld&nbsp;one&nbsp;{two&nbsp;three}&nbsp;four</tt></small></td>
 
1043
<td>&nbsp;&nbsp;</td>
 
1044
<td valign="center"><img src="image2"></td>
 
1045
<td>&nbsp;&nbsp;</td>
 
1046
<td valign="center"><tt>argc = 4<br>
 
1047
  argv[0] = "helloworld"<br>
 
1048
  argv[1] = "one"<br>
 
1049
  argv[2] = "two three"<br>
 
1050
  argv[3] = "four"<br>
 
1051
  argv[4] = NULL</tt></td>
 
1052
</tr>
 
1053
</table>
 
1054
 
 
1055
<br clear="both"><p><hr></p>
 
1056
<h2 align="center">A Short-Cut</h2>
 
1057
<p>In a program with many new Tcl commands implemented in C, it becomes
 
1058
  tedious to type the same four parameters over and over again.  So
 
1059
  we define a short-cut.</p><p>
 
1060
<table cellspacing="0" cellpadding="0" border="0">
 
1061
<tr><td valign="center">
 
1062
<small><tt>#define&nbsp;TCLARGS&nbsp;\&nbsp;<br>
 
1063
&nbsp;&nbsp;&nbsp;&nbsp;void&nbsp;*clientData,&nbsp;\&nbsp;<br>
 
1064
&nbsp;&nbsp;&nbsp;&nbsp;Tcl_Interp&nbsp;*interp,&nbsp;\&nbsp;<br>
 
1065
&nbsp;&nbsp;&nbsp;&nbsp;int&nbsp;argc,&nbsp;\&nbsp;<br>
 
1066
&nbsp;&nbsp;&nbsp;&nbsp;char&nbsp;*argv</tt></small></td>
 
1067
<td>&nbsp;&nbsp;</td>
 
1068
<td valign="center"><img src="image2"></td>
 
1069
<td>&nbsp;&nbsp;</td>
 
1070
<td valign="center">Define TCLARGS once in a header file</td>
 
1071
</tr>
 
1072
<tr><td valign="center">
 
1073
<small><tt>&nbsp;<br>
 
1074
&nbsp;<br>
 
1075
&nbsp;</tt></small></td>
 
1076
<td></td><td></td><td></td><td></td>
 
1077
</tr>
 
1078
<tr><td valign="center">
 
1079
<small><tt>int&nbsp;NewCmd(TCLARGS){</tt></small></td>
 
1080
<td>&nbsp;&nbsp;</td>
 
1081
<td valign="center"><img src="image2"></td>
 
1082
<td>&nbsp;&nbsp;</td>
 
1083
<td valign="center">Use the TCLARGS macro to define new C functions
 
1084
  that implement Tcl commands.</td>
 
1085
</tr>
 
1086
<tr><td valign="center">
 
1087
<small><tt>&nbsp;&nbsp;&nbsp;/*&nbsp;implementation...&nbsp;*/<br>
 
1088
}</tt></small></td>
 
1089
<td></td><td></td><td></td><td></td>
 
1090
</tr>
 
1091
</table>
 
1092
<p><table><tr><td valign="top"><img src="image3"></td>
 
1093
<td valign="top"><b>For brevity, we will use the TCLARGS macro during the
 
1094
  rest of this talk.</b></td></tr></table>
 
1095
</p>
 
1096
 
 
1097
<br clear="both"><p><hr></p>
 
1098
<h2 align="center">Returning A Value From C Back To Tcl</h2>
 
1099
<table cellspacing="0" cellpadding="0" border="0">
 
1100
<tr><td valign="center">
 
1101
<small><tt>int&nbsp;NewCmd(TCLARGS){</tt></small></td>
 
1102
<td>&nbsp;&nbsp;</td>
 
1103
<td valign="center"><img src="image2"></td>
 
1104
<td>&nbsp;&nbsp;</td>
 
1105
<td valign="center">Note that the C function returns an "int"</td>
 
1106
</tr>
 
1107
<tr><td valign="center">
 
1108
<small><tt>&nbsp;&nbsp;return&nbsp;TCL_OK;</tt></small></td>
 
1109
<td>&nbsp;&nbsp;</td>
 
1110
<td valign="center"><img src="image2"></td>
 
1111
<td>&nbsp;&nbsp;</td>
 
1112
<td valign="center">Return value is TCL_OK or TCL_ERROR</td>
 
1113
</tr>
 
1114
<tr><td valign="center">
 
1115
<small><tt>}</tt></small></td>
 
1116
<td></td><td></td><td></td><td></td>
 
1117
</tr>
 
1118
</table>
 
1119
<p><ul><li>TCL_OK and TCL_ERROR are defined in &lt;tcl.h&gt;</li></ul><ul><li>Other valid return values TCL_RETURN, TCL_BREAK and TCL_CONTINUE
 
1120
  are rarely used</li></ul><ul><li>Common mistake: forgetting to return TCL_OK</li></ul></p>
 
1121
 
 
1122
<br clear="both"><p><hr></p>
 
1123
<h2 align="center">Returning A Value From C Back To Tcl</h2>
 
1124
<table cellspacing="0" cellpadding="0" border="0">
 
1125
<tr><td valign="center">
 
1126
<small><tt>int&nbsp;NewCmd(TCLARGS){</tt></small></td>
 
1127
<td></td><td></td><td></td><td></td>
 
1128
</tr>
 
1129
<tr><td valign="center">
 
1130
<small><tt>&nbsp;&nbsp;Tcl_SetResult(interp,"Hello!",TCL_STATIC);</tt></small></td>
 
1131
<td>&nbsp;&nbsp;</td>
 
1132
<td valign="center"><img src="image2"></td>
 
1133
<td>&nbsp;&nbsp;</td>
 
1134
<td valign="center">Set the result to "Hello!"</td>
 
1135
</tr>
 
1136
<tr><td valign="center">
 
1137
<small><tt>&nbsp;&nbsp;return&nbsp;TCL_OK;<br>
 
1138
}</tt></small></td>
 
1139
<td></td><td></td><td></td><td></td>
 
1140
</tr>
 
1141
</table>
 
1142
<p><ul><li>Result should be the text of an error message if you 
 
1143
  return TCL_ERROR.</li></ul><ul><li>3rd argument to Tcl_SetResult() can be TCL_STATIC,
 
1144
  TCL_DYNAMIC, TCL_VOLATILE, or a function pointer.</li></ul><ul><li>Also consider using Tcl_AppendResult().</li></ul><ul><li>Direct access to <tt>interp->result</tt> is deprecated.</li></ul><ul><li>See the man pages for details.</li></ul></p>
 
1145
 
 
1146
<br clear="both"><p><hr></p>
 
1147
<h2 align="center">The Tcl_Obj Interface</h2>
 
1148
<p><ul><li>A new way to write Tcl commands in C code</li></ul><ul><li>First introduced in Tcl8.0</li></ul><ul><li>Can be much faster, especially for lists or numeric values.</li></ul><ul><li>Able to handle arbitrary binary data.</li></ul><ul><li>More difficult to program.</li></ul></p>
 
1149
<br clear="both"><p><hr></p>
 
1150
<h2 align="center">The Tcl_Obj Interface</h2>
 
1151
<table cellspacing="0" cellpadding="0" border="0">
 
1152
<tr><td valign="center">
 
1153
<small><tt>int&nbsp;NewObjCmd(<br>
 
1154
&nbsp;&nbsp;void&nbsp;*clientData,<br>
 
1155
&nbsp;&nbsp;Tcl_Interp&nbsp;*interp,<br>
 
1156
&nbsp;&nbsp;int&nbsp;objc,</tt></small></td>
 
1157
<td></td><td></td><td></td><td></td>
 
1158
</tr>
 
1159
<tr><td valign="center">
 
1160
<small><tt>&nbsp;&nbsp;Tcl_Obj&nbsp;*const*&nbsp;objv</tt></small></td>
 
1161
<td>&nbsp;&nbsp;</td>
 
1162
<td valign="center"><img src="image2"></td>
 
1163
<td>&nbsp;&nbsp;</td>
 
1164
<td valign="center">4th parameter is an array Tcl_Objs, not an array of strings</td>
 
1165
</tr>
 
1166
<tr><td valign="center">
 
1167
<small><tt>){<br>
 
1168
&nbsp;&nbsp;/*&nbsp;Implementation...&nbsp;*/<br>
 
1169
&nbsp;&nbsp;return&nbsp;TCL_OK;<br>
 
1170
}<br>
 
1171
&nbsp;<br>
 
1172
static&nbsp;char&nbsp;zInputLoop[]&nbsp;=&nbsp;<br>
 
1173
&nbsp;&nbsp;/*&nbsp;Tcl&nbsp;code&nbsp;omitted...&nbsp;*/<br>
 
1174
;<br>
 
1175
&nbsp;<br>
 
1176
int&nbsp;main(int&nbsp;argc,&nbsp;char&nbsp;**argv){<br>
 
1177
&nbsp;&nbsp;Tcl_Interp&nbsp;*interp;<br>
 
1178
&nbsp;&nbsp;interp&nbsp;=&nbsp;Tcl_CreateInterp();</tt></small></td>
 
1179
<td></td><td></td><td></td><td></td>
 
1180
</tr>
 
1181
<tr><td valign="center">
 
1182
<small><tt>&nbsp;&nbsp;Tcl_CreateObjCommand(interp,&nbsp;"newcmd",<br>
 
1183
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;NewObjCmd,&nbsp;0,&nbsp;0);</tt></small></td>
 
1184
<td>&nbsp;&nbsp;</td>
 
1185
<td valign="center"><img src="image2"></td>
 
1186
<td>&nbsp;&nbsp;</td>
 
1187
<td valign="center">Use a different function to register the command</td>
 
1188
</tr>
 
1189
<tr><td valign="center">
 
1190
<small><tt>&nbsp;&nbsp;Tcl_Eval(interp,&nbsp;zInputLoop);<br>
 
1191
&nbsp;&nbsp;return&nbsp;0;<br>
 
1192
}</tt></small></td>
 
1193
<td></td><td></td><td></td><td></td>
 
1194
</tr>
 
1195
</table>
 
1196
 
 
1197
<br clear="both"><p><hr></p>
 
1198
<h2 align="center">The Tcl_Obj Interface</h2>
 
1199
<p><ul><li>There are countless access methods for reading information from and
 
1200
  placing information in Tcl_Objs.  Always use the access methods.</li></ul><ul><li>Details provided at Lee Bernhard's talk this afternoon.</li></ul><ul><li>Definitely use Tcl_Objs if you are writing a new Tcl extension.</li></ul><ul><li>Tcl_Objs address some of the weaknesses of Tcl relative to C/C++.
 
1201
  <ul>
 
1202
  <li> Tcl_Objs are faster </li>
 
1203
  <li> Tcl_Objs work with binary data </li>
 
1204
  </ul>
 
1205
  But C/C++ is faster still and better for working with binary data.</li></ul><ul><li>When mixing C/C++ with Tcl/Tk the benefits of Tcl_Objs are
 
1206
  less important.  Using Tcl_Objs in this context may not be
 
1207
  worth the extra trouble.</li></ul><ul><li>This talk will focus on the string interface.</li></ul></p>
 
1208
<br clear="both"><p><hr></p>
 
1209
<h2 align="center">Nickel Tour Of The Tcl API</h2>
 
1210
<p><p><b>Memory allocation functions</b></p>
 
1211
<center><table width="90%"><tr>
 
1212
<td width="32%" valign="top"><small><tt>
 
1213
  Tcl_Alloc<br>
 
1214
</tt></small></td>
 
1215
<td width="32%" valign="top"><small><tt>
 
1216
  Tcl_Free<br>
 
1217
</tt></small></td>
 
1218
<td width="32%" valign="top"><small><tt>
 
1219
  Tcl_Realloc<br>
 
1220
</tt></small></td>
 
1221
</table></center><p><b>Functions useful in the implementation of new  Tcl commands</b></p>
 
1222
<center><table width="90%"><tr>
 
1223
<td width="32%" valign="top"><small><tt>
 
1224
  Tcl_AppendElement<br>
 
1225
  Tcl_AppendResult<br>
 
1226
  Tcl_GetBoolean<br>
 
1227
</tt></small></td>
 
1228
<td width="32%" valign="top"><small><tt>
 
1229
  Tcl_GetDouble<br>
 
1230
  Tcl_GetInt<br>
 
1231
  Tcl_GetStringResult<br>
 
1232
</tt></small></td>
 
1233
<td width="32%" valign="top"><small><tt>
 
1234
  Tcl_ResetResult<br>
 
1235
  Tcl_SetResult<br>
 
1236
</tt></small></td>
 
1237
</table></center><p><b>Functions for controlling the Tcl interpreter</b></p>
 
1238
<center><table width="90%"><tr>
 
1239
<td width="32%" valign="top"><small><tt>
 
1240
  Tcl_CreateCommand<br>
 
1241
  Tcl_CreateInterp<br>
 
1242
</tt></small></td>
 
1243
<td width="32%" valign="top"><small><tt>
 
1244
  Tcl_CreateObjCommand<br>
 
1245
  Tcl_DeleteCommand<br>
 
1246
</tt></small></td>
 
1247
<td width="32%" valign="top"><small><tt>
 
1248
  Tcl_DeleteInterp<br>
 
1249
  Tcl_Exit<br>
 
1250
</tt></small></td>
 
1251
</table></center></p>
 
1252
<br clear="both"><p><hr></p>
 
1253
<h2 align="center">Nickel Tour Of The Tcl API</h2>
 
1254
<p><p><b>I/O functions</b></p>
 
1255
<center><table width="90%"><tr>
 
1256
<td width="32%" valign="top"><small><tt>
 
1257
  Tcl_Close<br>
 
1258
  Tcl_Eof<br>
 
1259
  Tcl_Flush<br>
 
1260
  Tcl_GetChannel<br>
 
1261
  Tcl_GetChannelMode<br>
 
1262
  Tcl_GetChannelName<br>
 
1263
</tt></small></td>
 
1264
<td width="32%" valign="top"><small><tt>
 
1265
  Tcl_Gets<br>
 
1266
  Tcl_OpenCommandChannel<br>
 
1267
  Tcl_OpenFileChannel<br>
 
1268
  Tcl_OpenTcpClient<br>
 
1269
  Tcl_OpenTcpServer<br>
 
1270
  Tcl_Read<br>
 
1271
</tt></small></td>
 
1272
<td width="32%" valign="top"><small><tt>
 
1273
  Tcl_Seek<br>
 
1274
  Tcl_Tell<br>
 
1275
  Tcl_Ungets<br>
 
1276
  Tcl_Write<br>
 
1277
  Tcl_WriteChars<br>
 
1278
</tt></small></td>
 
1279
</table></center><p><b>Names and meanings of system error codes</b></p>
 
1280
<center><table width="90%"><tr>
 
1281
<td width="32%" valign="top"><small><tt>
 
1282
  Tcl_ErrnoId<br>
 
1283
  Tcl_ErrnoMsg<br>
 
1284
</tt></small></td>
 
1285
<td width="32%" valign="top"><small><tt>
 
1286
  Tcl_GetErrno<br>
 
1287
  Tcl_SetErrno<br>
 
1288
</tt></small></td>
 
1289
<td width="32%" valign="top"><small><tt>
 
1290
  Tcl_SignalId<br>
 
1291
  Tcl_SignalMsg<br>
 
1292
</tt></small></td>
 
1293
</table></center></p>
 
1294
<br clear="both"><p><hr></p>
 
1295
<h2 align="center">Nickel Tour Of The Tcl API</h2>
 
1296
<p><p><b>General Operating System Calls</b></p>
 
1297
<center><table width="90%"><tr>
 
1298
<td width="32%" valign="top"><small><tt>
 
1299
  Tcl_Access<br>
 
1300
  Tcl_Chdir<br>
 
1301
  Tcl_GetCwd<br>
 
1302
</tt></small></td>
 
1303
<td width="32%" valign="top"><small><tt>
 
1304
  Tcl_GetHostName<br>
 
1305
  Tcl_GetNameOfExecutable<br>
 
1306
  Tcl_Sleep<br>
 
1307
</tt></small></td>
 
1308
<td width="32%" valign="top"><small><tt>
 
1309
  Tcl_Stat<br>
 
1310
</tt></small></td>
 
1311
</table></center><p><b>String Manipulation And Comparison</b></p>
 
1312
<center><table width="90%"><tr>
 
1313
<td width="32%" valign="top"><small><tt>
 
1314
  Tcl_Concat<br>
 
1315
  Tcl_Merge<br>
 
1316
</tt></small></td>
 
1317
<td width="32%" valign="top"><small><tt>
 
1318
  Tcl_SplitList<br>
 
1319
  Tcl_StringCaseMatch<br>
 
1320
</tt></small></td>
 
1321
<td width="32%" valign="top"><small><tt>
 
1322
  Tcl_StringMatch<br>
 
1323
</tt></small></td>
 
1324
</table></center><p><b>Dynamically Resizable Strings</b></p>
 
1325
<center><table width="90%"><tr>
 
1326
<td width="49%" valign="top"><small><tt>
 
1327
  Tcl_DStringAppend<br>
 
1328
  Tcl_DStringAppendElement<br>
 
1329
  Tcl_DStringEndSublist<br>
 
1330
  Tcl_DStringInit<br>
 
1331
  Tcl_DStringLength<br>
 
1332
</tt></small></td>
 
1333
<td width="49%" valign="top"><small><tt>
 
1334
  Tcl_DStringResult<br>
 
1335
  Tcl_DStringSetLength<br>
 
1336
  Tcl_DStringStartSublist<br>
 
1337
  Tcl_DStringValue<br>
 
1338
</tt></small></td>
 
1339
</table></center></p>
 
1340
<br clear="both"><p><hr></p>
 
1341
<h2 align="center">Nickel Tour Of The Tcl API</h2>
 
1342
<p><p><b>Event Handlers</b></p>
 
1343
<center><table width="90%"><tr>
 
1344
<td width="49%" valign="top"><small><tt>
 
1345
  Tcl_CancelIdleCall<br>
 
1346
  Tcl_CreateChannelHandler<br>
 
1347
  Tcl_CreateTimerHandler<br>
 
1348
  Tcl_DeleteChannelHandler<br>
 
1349
</tt></small></td>
 
1350
<td width="49%" valign="top"><small><tt>
 
1351
  Tcl_DeleteTimerHandler<br>
 
1352
  Tcl_DoOneEvent<br>
 
1353
  Tcl_DoWhenIdle<br>
 
1354
</tt></small></td>
 
1355
</table></center><p><b>Functions For Reading And Writing Tcl Variables</b></p>
 
1356
<center><table width="90%"><tr>
 
1357
<td width="32%" valign="top"><small><tt>
 
1358
  Tcl_GetVar<br>
 
1359
  Tcl_GetVar2<br>
 
1360
  Tcl_LinkVar<br>
 
1361
  Tcl_SetVar<br>
 
1362
  Tcl_SetVar2<br>
 
1363
</tt></small></td>
 
1364
<td width="32%" valign="top"><small><tt>
 
1365
  Tcl_TraceVar<br>
 
1366
  Tcl_TraceVar2<br>
 
1367
  Tcl_UnlinkVar<br>
 
1368
  Tcl_UnsetVar<br>
 
1369
  Tcl_UnsetVar2<br>
 
1370
</tt></small></td>
 
1371
<td width="32%" valign="top"><small><tt>
 
1372
  Tcl_UntraceVar<br>
 
1373
  Tcl_UntraceVar2<br>
 
1374
  Tcl_UpdateLinkedVar<br>
 
1375
</tt></small></td>
 
1376
</table></center><p><b>Functions For Executing Tcl Code</b></p>
 
1377
<center><table width="90%"><tr>
 
1378
<td width="32%" valign="top"><small><tt>
 
1379
  Tcl_Eval<br>
 
1380
  Tcl_EvalFile<br>
 
1381
</tt></small></td>
 
1382
<td width="32%" valign="top"><small><tt>
 
1383
  Tcl_EvalObj<br>
 
1384
  Tcl_GlobalEval<br>
 
1385
</tt></small></td>
 
1386
<td width="32%" valign="top"><small><tt>
 
1387
  Tcl_GlobalEvalObj<br>
 
1388
  Tcl_VarEval<br>
 
1389
</tt></small></td>
 
1390
</table></center></p>
 
1391
<br clear="both"><p><hr></p>
 
1392
<h2 align="center">Nickel Tour Of The Tcl API</h2>
 
1393
<p><p><b>Functions For Dealing With Unicode</b></p>
 
1394
<center><table width="90%"><tr>
 
1395
<td width="49%" valign="top"><small><tt>
 
1396
  Tcl_NumUtfChars<br>
 
1397
  Tcl_UniCharAtIndex<br>
 
1398
  Tcl_UniCharIsAlnum<br>
 
1399
  Tcl_UniCharIsAlpha<br>
 
1400
  Tcl_UniCharIsControl<br>
 
1401
  Tcl_UniCharIsDigit<br>
 
1402
  Tcl_UniCharIsGraph<br>
 
1403
  Tcl_UniCharIsLower<br>
 
1404
  Tcl_UniCharIsPrint<br>
 
1405
  Tcl_UniCharIsPunct<br>
 
1406
  Tcl_UniCharIsSpace<br>
 
1407
  Tcl_UniCharIsUpper<br>
 
1408
  Tcl_UniCharIsWordChar<br>
 
1409
  Tcl_UniCharLen<br>
 
1410
  Tcl_UniCharNcmp<br>
 
1411
  Tcl_UniCharToLower<br>
 
1412
  Tcl_UniCharToTitle<br>
 
1413
</tt></small></td>
 
1414
<td width="49%" valign="top"><small><tt>
 
1415
  Tcl_UniCharToUpper<br>
 
1416
  Tcl_UniCharToUtf<br>
 
1417
  Tcl_UniCharToUtfDString<br>
 
1418
  Tcl_UtfAtIndex<br>
 
1419
  Tcl_UtfBackslash<br>
 
1420
  Tcl_UtfCharComplete<br>
 
1421
  Tcl_UtfFindFirst<br>
 
1422
  Tcl_UtfFindLast<br>
 
1423
  Tcl_UtfNcasecmp<br>
 
1424
  Tcl_UtfNcmp<br>
 
1425
  Tcl_UtfNext<br>
 
1426
  Tcl_UtfPrev<br>
 
1427
  Tcl_UtfToLower<br>
 
1428
  Tcl_UtfToTitle<br>
 
1429
  Tcl_UtfToUniChar<br>
 
1430
  Tcl_UtfToUniCharDString<br>
 
1431
  Tcl_UtfToUpper<br>
 
1432
</tt></small></td>
 
1433
</table></center>
 
1434
  <p><b>Functions For Dealing With Tcl_Objs</b></p>
 
1435
  <blockquote><i>Too numerous to list...</i></blockquote></p>
 
1436
<br clear="both"><p><hr></p>
 
1437
<h2 align="center">Documentation Of The Tcl API</h2>
 
1438
<p><ul><li>Tcl comes with excellent man pages</li></ul><ul><li>"Use the source, Luke"</li></ul><ul><li>See <tt>tclDecl.h</tt> for a list of API functions</li></ul><ul><li>The header comments on the implementation of API functions usually
 
1439
  gives a good description of what the function does and how it should
 
1440
  be used.</li></ul><ul><li>Most API functions are used within Tcl and Tk.  Use grep to locate
 
1441
  examples.</li></ul></p>
 
1442
<br clear="both"><p><hr></p>
 
1443
<h2 align="center">Initialization Scripts</h2>
 
1444
<p><ul><li>Run the mini TCLSH implemented above and execute the <tt>parray</tt> command</li></ul><ul><li>It doesn't work!  What's wrong? </p></li></li></ul><ul><li><tt>parray</tt> is really a Tcl proc that is read in when the
 
1445
 interpreter is initialized. </p></li></li></ul><ul><li><tt>parray</tt> (and several other commands) are stored in a
 
1446
  handful of &quot;Initialization Scripts&quot; </p></li></li></ul><ul><li>All the initialization scripts are stored in the 
 
1447
 &quot;Tcl Library&quot; - a directory on the host
 
1448
 computer. </p></li></li></ul><table><tr><td valign="top"><img src="image3"></td>
 
1449
<td valign="top"><b>Invoke the Tcl_Init() function to locate and read the
 
1450
 Tcl initialization scripts.</b></td></tr></table></p>
 
1451
<br clear="both"><p><hr></p>
 
1452
<h2 align="center">The <tt>Tcl_Init()</tt> Function</h2>
 
1453
<table cellspacing="0" cellpadding="0" border="0">
 
1454
<tr><td valign="center">
 
1455
<small><tt>#include&nbsp;&lt;tcl.h><br>
 
1456
&nbsp;<br>
 
1457
static&nbsp;char&nbsp;zInputLoop[]&nbsp;=&nbsp;<br>
 
1458
&nbsp;&nbsp;/*&nbsp;Tcl&nbsp;code&nbsp;omitted...&nbsp;*/<br>
 
1459
;<br>
 
1460
&nbsp;<br>
 
1461
int&nbsp;main(int&nbsp;argc,&nbsp;char&nbsp;**argv){<br>
 
1462
&nbsp;&nbsp;Tcl_Interp&nbsp;*interp;<br>
 
1463
&nbsp;&nbsp;interp&nbsp;=&nbsp;Tcl_CreateInterp();</tt></small></td>
 
1464
<td></td><td></td><td></td><td></td>
 
1465
</tr>
 
1466
<tr><td valign="center">
 
1467
<small><tt>&nbsp;&nbsp;Tcl_Init(interp);</tt></small></td>
 
1468
<td>&nbsp;&nbsp;</td>
 
1469
<td valign="center"><img src="image2"></td>
 
1470
<td>&nbsp;&nbsp;</td>
 
1471
<td valign="center">Locate and read the initialization scripts</td>
 
1472
</tr>
 
1473
<tr><td valign="center">
 
1474
<small><tt>&nbsp;&nbsp;/*&nbsp;Call&nbsp;Tcl_CreateCommand()?&nbsp;*/<br>
 
1475
&nbsp;&nbsp;Tcl_Eval(interp,&nbsp;zInputLoop);<br>
 
1476
&nbsp;&nbsp;return&nbsp;0;<br>
 
1477
}</tt></small></td>
 
1478
<td></td><td></td><td></td><td></td>
 
1479
</tr>
 
1480
</table>
 
1481
<p><table><tr><td valign="top"><img src="image3"></td>
 
1482
<td valign="top"><b>But Tcl_Init() can fail. We need to check its return value...</b></td></tr></table>
 
1483
</p>
 
1484
 
 
1485
<br clear="both"><p><hr></p>
 
1486
<h2 align="center">The <tt>Tcl_Init()</tt> Function</h2>
 
1487
<table cellspacing="0" cellpadding="0" border="0">
 
1488
<tr><td valign="center">
 
1489
<small><tt>#include&nbsp;&lt;tcl.h><br>
 
1490
&nbsp;<br>
 
1491
static&nbsp;char&nbsp;zInputLoop[]&nbsp;=&nbsp;<br>
 
1492
&nbsp;&nbsp;/*&nbsp;Tcl&nbsp;code&nbsp;omitted...&nbsp;*/<br>
 
1493
;<br>
 
1494
&nbsp;<br>
 
1495
int&nbsp;main(int&nbsp;argc,&nbsp;char&nbsp;**argv){<br>
 
1496
&nbsp;&nbsp;Tcl_Interp&nbsp;*interp;<br>
 
1497
&nbsp;&nbsp;interp&nbsp;=&nbsp;Tcl_CreateInterp();</tt></small></td>
 
1498
<td></td><td></td><td></td><td></td>
 
1499
</tr>
 
1500
<tr><td valign="center">
 
1501
<small><tt>&nbsp;&nbsp;if(&nbsp;Tcl_Init(interp)!=TCL_OK&nbsp;){<br>
 
1502
&nbsp;&nbsp;&nbsp;&nbsp;fprintf(stderr,"Tcl_Init()&nbsp;failed:&nbsp;����P�X�",<br>
 
1503
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Tcl_GetStringResult(interp));<br>
 
1504
&nbsp;&nbsp;}</tt></small></td>
 
1505
<td>&nbsp;&nbsp;</td>
 
1506
<td valign="center"><img src="image2"></td>
 
1507
<td>&nbsp;&nbsp;</td>
 
1508
<td valign="center">Print error message if Tcl_Init() fails</td>
 
1509
</tr>
 
1510
<tr><td valign="center">
 
1511
<small><tt>&nbsp;&nbsp;/*&nbsp;Call&nbsp;Tcl_CreateCommand()?&nbsp;*/<br>
 
1512
&nbsp;&nbsp;Tcl_Eval(interp,&nbsp;zInputLoop);<br>
 
1513
&nbsp;&nbsp;return&nbsp;0;<br>
 
1514
}</tt></small></td>
 
1515
<td></td><td></td><td></td><td></td>
 
1516
</tr>
 
1517
</table>
 
1518
<p><table><tr><td valign="top"><img src="image3"></td>
 
1519
<td valign="top"><b>But now the program is not standalone.</b></td></tr></table>
 
1520
</p>
 
1521
 
 
1522
<br clear="both"><p><hr></p>
 
1523
<h2 align="center">How <tt>Tcl_Init()</tt> Works</h2>
 
1524
<p><ul><li>Computes the value of variable <tt>tcl_libPath</tt>.</li></ul><ul><li>Invokes the procedure named &quot;<tt>tclInit</tt>&quot;</li></ul><ul><li>A default <tt>tclInit</tt> procedure is built into Tcl.
 
1525
  You can define an alternative <tt>tclInit</tt> procedure
 
1526
  prior to calling <tt>Tcl_Init()</tt>.</li></ul></p>
 
1527
<br clear="both"><p><hr></p>
 
1528
<h2 align="center">The Default <tt>initTcl</tt> Procedure</h2>
 
1529
<table cellspacing="0" cellpadding="0" border="0">
 
1530
<tr><td valign="center">
 
1531
<small><tt>set&nbsp;errors&nbsp;{}<br>
 
1532
set&nbsp;dirs&nbsp;{}<br>
 
1533
if&nbsp;{[info&nbsp;exists&nbsp;tcl_library]}&nbsp;{<br>
 
1534
&nbsp;&nbsp;lappend&nbsp;dirs&nbsp;$tcl_library<br>
 
1535
}&nbsp;else&nbsp;{<br>
 
1536
&nbsp;&nbsp;if&nbsp;{[info&nbsp;exists&nbsp;env(TCL_LIBRARY)]}&nbsp;{<br>
 
1537
&nbsp;&nbsp;&nbsp;&nbsp;lappend&nbsp;dirs&nbsp;$env(TCL_LIBRARY)<br>
 
1538
&nbsp;&nbsp;}<br>
 
1539
&nbsp;&nbsp;lappend&nbsp;dirs&nbsp;$tclDefaultLibrary<br>
 
1540
&nbsp;&nbsp;unset&nbsp;tclDefaultLibrary<br>
 
1541
&nbsp;&nbsp;set&nbsp;dirs&nbsp;[concat&nbsp;$dirs&nbsp;$tcl_libPath]<br>
 
1542
}<br>
 
1543
foreach&nbsp;i&nbsp;$dirs&nbsp;{<br>
 
1544
&nbsp;&nbsp;set&nbsp;tcl_library&nbsp;$i<br>
 
1545
&nbsp;&nbsp;set&nbsp;tclfile&nbsp;[file&nbsp;join&nbsp;$i&nbsp;init.tcl]<br>
 
1546
&nbsp;&nbsp;if&nbsp;{[file&nbsp;exists&nbsp;$tclfile]}&nbsp;{<br>
 
1547
&nbsp;&nbsp;&nbsp;&nbsp;if&nbsp;{![catch&nbsp;{uplevel&nbsp;#0&nbsp;[list&nbsp;source&nbsp;$tclfile]}&nbsp;msg]}&nbsp;{<br>
 
1548
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return<br>
 
1549
&nbsp;&nbsp;&nbsp;&nbsp;}&nbsp;else&nbsp;{<br>
 
1550
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;append&nbsp;errors&nbsp;"$tclfile:&nbsp;$msg\n$errorInfo\n"<br>
 
1551
&nbsp;&nbsp;&nbsp;&nbsp;}<br>
 
1552
&nbsp;&nbsp;}<br>
 
1553
}<br>
 
1554
error&nbsp;"Can't&nbsp;find&nbsp;a&nbsp;usable&nbsp;init.tcl&nbsp;..."</tt></small></td>
 
1555
<td></td><td></td><td></td><td></td>
 
1556
</tr>
 
1557
</table>
 
1558
 
 
1559
<br clear="both"><p><hr></p>
 
1560
<h2 align="center">The Default Initialization Sequence</h2>
 
1561
<p><ul><li>The <tt>tclInit</tt> procedure locates and sources the <tt>init.tcl</tt>
 
1562
  script.  The directory that contains <tt>init.tcl</tt> is stored in
 
1563
  the <tt>tcl_library</tt> variable.</li></ul><ul><li>The <tt>init.tcl</tt> script creates an <tt>unknown</tt> procedure.
 
1564
  The <tt>unknown</tt> procedure will run whenever Tcl encounters an
 
1565
  unknown command.</li></ul><ul><li>The <tt>unknown</tt> procedure consults the file <tt>tclIndex</tt> in the
 
1566
  <tt>tcl_library</tt> directory to see if the command is defined by one of
 
1567
  the initialization scripts.</li></ul><ul><li>The <tt>unknown</tt> procedure sources any needed initialization scripts
 
1568
  and retries the command.</li></ul><table><tr><td valign="top"><img src="image3"></td>
 
1569
<td valign="top"><b>Commands defined in the initialization scripts are loaded
 
1570
  on demand.</b></td></tr></table></p>
 
1571
<br clear="both"><p><hr></p>
 
1572
<h2 align="center">Standalone Initialization Techniques</h2>
 
1573
<p><p><b>Manually execute all initialization scripts</b></p>
 
1574
<ul><li>Convert all initialization scripts into C strings and
 
1575
  put them in the executable.</li></ul><ul><li>Call <tt>Tcl_Eval()</tt> on each initialization script and omit the
 
1576
  call to <tt>Tcl_Init()</tt></li></ul><ul><li>Or, redefine <tt>tclInit</tt> so that it does not attempt to source
 
1577
  <tt>init.tcl</tt> then call <tt>Tcl_Eval()</tt> on each initialization
 
1578
  script after <tt>Tcl_Init()</tt> returns.</li></ul><table><tr><td valign="top"><img src="image3"></td>
 
1579
<td valign="top"><b>This approach is not recommended</b></td></tr></table></p>
 
1580
<br clear="both"><p><hr></p>
 
1581
<h2 align="center">Standalone Initialization Techniques</h2>
 
1582
<p><p><b>Redefining the builtin <tt>source</tt> command</b></p>
 
1583
<ul><li>Convert all initialization scripts into C strings and
 
1584
  put them in the executable.</li></ul><ul><li>Create a new <tt>source</tt> command that
 
1585
  calls <tt>Tcl_Eval()</tt> on the appropriate built-in string
 
1586
  instead of reading from the disk.</li></ul><ul><li>Read from disk if the named file is not one that is built in.</li></ul></p>
 
1587
<br clear="both"><p><hr></p>
 
1588
<h2 align="center">Redefining <tt>source</tt></h2>
 
1589
<table cellspacing="0" cellpadding="0" border="0">
 
1590
<tr><td valign="center">
 
1591
<small><tt>static&nbsp;char&nbsp;zInitTcl[]&nbsp;=&nbsp;"...";<br>
 
1592
static&nbsp;char&nbsp;zParrayTcl[]&nbsp;=&nbsp;"...";</tt></small></td>
 
1593
<td>&nbsp;&nbsp;</td>
 
1594
<td valign="center"><img src="image2"></td>
 
1595
<td>&nbsp;&nbsp;</td>
 
1596
<td valign="center">Scripts <tt>init.tcl</tt> and <tt>parray.tcl</tt></td>
 
1597
</tr>
 
1598
<tr><td valign="center">
 
1599
<small><tt><br>
 
1600
int&nbsp;NewSourceCmd(TCLARGS){</tt></small></td>
 
1601
<td></td><td></td><td></td><td></td>
 
1602
</tr>
 
1603
<tr><td valign="center">
 
1604
<small><tt>&nbsp;&nbsp;if(&nbsp;!strcmp(argv[1],"/builtin/init.tcl")&nbsp;)<br>
 
1605
&nbsp;&nbsp;&nbsp;&nbsp;return&nbsp;Tcl_Eval(interp,&nbsp;zInitTcl);<br>
 
1606
&nbsp;&nbsp;if(&nbsp;!strcmp(argv[1],"/builtin/parray.tcl")&nbsp;)<br>
 
1607
&nbsp;&nbsp;&nbsp;&nbsp;return&nbsp;Tcl_Eval(interp,&nbsp;zParrayTcl);</tt></small></td>
 
1608
<td>&nbsp;&nbsp;</td>
 
1609
<td valign="center"><img src="image2"></td>
 
1610
<td>&nbsp;&nbsp;</td>
 
1611
<td valign="center">Call <tt>Tcl_Eval()</tt> on builtin strings if the names match</td>
 
1612
</tr>
 
1613
<tr><td valign="center">
 
1614
<small><tt>&nbsp;&nbsp;return&nbsp;Tcl_EvalFile(interp,&nbsp;argv[1]);</tt></small></td>
 
1615
<td>&nbsp;&nbsp;</td>
 
1616
<td valign="center"><img src="image2"></td>
 
1617
<td>&nbsp;&nbsp;</td>
 
1618
<td valign="center">Call <tt>Tcl_EvalFile()</tt> if no match</td>
 
1619
</tr>
 
1620
<tr><td valign="center">
 
1621
<small><tt>}<br>
 
1622
&nbsp;<br>
 
1623
int&nbsp;main(int&nbsp;argc,&nbsp;char&nbsp;**argv){<br>
 
1624
&nbsp;&nbsp;Tcl_Interp&nbsp;*interp;</tt></small></td>
 
1625
<td></td><td></td><td></td><td></td>
 
1626
</tr>
 
1627
<tr><td valign="center">
 
1628
<small><tt>&nbsp;&nbsp;setenv("TCL_LIBRARY","/builtin");</tt></small></td>
 
1629
<td>&nbsp;&nbsp;</td>
 
1630
<td valign="center"><img src="image2"></td>
 
1631
<td>&nbsp;&nbsp;</td>
 
1632
<td valign="center">Causes <tt>tclInit</tt> to look for <tt>init.tcl</tt> in <tt>/builtin</tt></td>
 
1633
</tr>
 
1634
<tr><td valign="center">
 
1635
<small><tt>&nbsp;&nbsp;interp&nbsp;=&nbsp;Tcl_CreateInterp();</tt></small></td>
 
1636
<td></td><td></td><td></td><td></td>
 
1637
</tr>
 
1638
<tr><td valign="center">
 
1639
<small><tt>&nbsp;&nbsp;Tcl_CreateCommand(interp,&nbsp;"source",<br>
 
1640
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;NewSourceCmd,&nbsp;0,&nbsp;0);</tt></small></td>
 
1641
<td>&nbsp;&nbsp;</td>
 
1642
<td valign="center"><img src="image2"></td>
 
1643
<td>&nbsp;&nbsp;</td>
 
1644
<td valign="center">Redefine <tt>source</tt></td>
 
1645
</tr>
 
1646
<tr><td valign="center">
 
1647
<small><tt>&nbsp;&nbsp;Tcl_Init(interp);<br>
 
1648
&nbsp;&nbsp;Tcl_Eval(interp,&nbsp;zInputLoop);<br>
 
1649
&nbsp;&nbsp;return&nbsp;0;<br>
 
1650
}</tt></small></td>
 
1651
<td></td><td></td><td></td><td></td>
 
1652
</tr>
 
1653
</table>
 
1654
 
 
1655
<br clear="both"><p><hr></p>
 
1656
<h2 align="center">Redefining <tt>source</tt></h2>
 
1657
<p><ul><li>This approach works for all versions of Tcl and Tk.</li></ul><ul><li>Also need to redefine the "<tt>file exists</tt>" Tcl command since it
 
1658
  too is used by <tt>tclInit</tt>.</li></ul><ul><li>To verify that the program is really standalone, remove the call
 
1659
  to <tt>Tcl_EvalFile()</tt>.</li></ul></p>
 
1660
<br clear="both"><p><hr></p>
 
1661
<h2 align="center">Standalone Initialization Techniques</h2>
 
1662
<p><p><b>Use the <tt>Tcl</tt>*<tt>InsertProc()</tt> functions</b></p>
 
1663
<ul><li>Three routines that overload basic file I/O operations:
 
1664
  <ul>
 
1665
  <li> <tt>TclStatInsertProc()</tt> </li>
 
1666
  <li> <tt>TclAccessInsertProc()</tt> </li>
 
1667
  <li> <tt>TclOpenFileChannelInsertProc()</tt> </li>
 
1668
  </ul></li></ul><ul><li>Allows us to implement a virtual filesystem that overlays the
 
1669
  real filesystem.</li></ul><ul><li>The virtual filesystem contains all the initialization scripts
 
1670
  as compiled-in strings.  The initialization scripts look like
 
1671
  they are resident on disk even though they are built in.</li></ul><ul><li>These functions first appeared in Tcl8.0.3.  
 
1672
  Presumably to support TclPro Wrapper.</li></ul><ul><li>The only documentation is comments on the code. 
 
1673
  See the Tcl source file <tt>generic/tclIOUtil.c</tt></li></ul></p>
 
1674
<br clear="both"><p><hr></p>
 
1675
<h2 align="center">The <tt>TclStatInsertProc()</tt> Function</h2>
 
1676
<p><ul><li>Sole argument is a pointer to a function whose interface is the
 
1677
  same as <tt>stat()</tt></li></ul><ul><li>Functions are stacked. Tcl tries each <tt>stat</tt> function on the
 
1678
  list, beginning with the most recently inserted, until one succeeds.</li></ul></p>
 
1679
<br clear="both"><p><hr></p>
 
1680
<h2 align="center">The <tt>TclStatInsertProc()</tt> Function</h2>
 
1681
<table cellspacing="0" cellpadding="0" border="0">
 
1682
<tr><td valign="center">
 
1683
<small><tt>#include&nbsp;&lt;tclInt.h></tt></small></td>
 
1684
<td>&nbsp;&nbsp;</td>
 
1685
<td valign="center"><img src="image2"></td>
 
1686
<td>&nbsp;&nbsp;</td>
 
1687
<td valign="center">Rather than <tt>&lt;tcl.h&gt;</tt>!</td>
 
1688
</tr>
 
1689
<tr><td valign="center">
 
1690
<small><tt><br>
 
1691
static&nbsp;int<br>
 
1692
BltinFileStat(char&nbsp;*path,struct&nbsp;stat&nbsp;*buf){<br>
 
1693
&nbsp;&nbsp;char&nbsp;*zData;<br>
 
1694
&nbsp;&nbsp;int&nbsp;nData;</tt></small></td>
 
1695
<td></td><td></td><td></td><td></td>
 
1696
</tr>
 
1697
<tr><td valign="center">
 
1698
<small><tt>&nbsp;&nbsp;zData&nbsp;=&nbsp;FindBuiltinFile(path,&nbsp;0,&nbsp;&amp;nData);</tt></small></td>
 
1699
<td>&nbsp;&nbsp;</td>
 
1700
<td valign="center"><img src="image2"></td>
 
1701
<td>&nbsp;&nbsp;</td>
 
1702
<td valign="center">Check if <tt>path</tt> is a builtin</td>
 
1703
</tr>
 
1704
<tr><td valign="center">
 
1705
<small><tt>&nbsp;&nbsp;if(&nbsp;zData==0&nbsp;){<br>
 
1706
&nbsp;&nbsp;&nbsp;&nbsp;return&nbsp;-1;<br>
 
1707
&nbsp;&nbsp;}</tt></small></td>
 
1708
<td>&nbsp;&nbsp;</td>
 
1709
<td valign="center"><img src="image2"></td>
 
1710
<td>&nbsp;&nbsp;</td>
 
1711
<td valign="center">Fail if <tt>path</tt> is not a builtin</td>
 
1712
</tr>
 
1713
<tr><td valign="center">
 
1714
<small><tt>&nbsp;&nbsp;memset(buf,&nbsp;0,&nbsp;sizeof(*buf));<br>
 
1715
&nbsp;&nbsp;buf->st_mode&nbsp;=&nbsp;0400;<br>
 
1716
&nbsp;&nbsp;buf->st_size&nbsp;=&nbsp;nData;</tt></small></td>
 
1717
<td></td><td></td><td></td><td></td>
 
1718
</tr>
 
1719
<tr><td valign="center">
 
1720
<small><tt>&nbsp;&nbsp;return&nbsp;0;</tt></small></td>
 
1721
<td>&nbsp;&nbsp;</td>
 
1722
<td valign="center"><img src="image2"></td>
 
1723
<td>&nbsp;&nbsp;</td>
 
1724
<td valign="center">Success if it is builtin</td>
 
1725
</tr>
 
1726
<tr><td valign="center">
 
1727
<small><tt>}<br>
 
1728
&nbsp;<br>
 
1729
int&nbsp;main(int&nbsp;argc,&nbsp;char&nbsp;**argv){<br>
 
1730
&nbsp;&nbsp;Tcl_Interp&nbsp;*interp;</tt></small></td>
 
1731
<td></td><td></td><td></td><td></td>
 
1732
</tr>
 
1733
<tr><td valign="center">
 
1734
<small><tt>&nbsp;&nbsp;TclStatInsertProc(BltinFileStat);</tt></small></td>
 
1735
<td>&nbsp;&nbsp;</td>
 
1736
<td valign="center"><img src="image2"></td>
 
1737
<td>&nbsp;&nbsp;</td>
 
1738
<td valign="center">Register new <tt>stat</tt> function</td>
 
1739
</tr>
 
1740
<tr><td valign="center">
 
1741
<small><tt>&nbsp;&nbsp;interp&nbsp;=&nbsp;Tcl_CreateInterp();<br>
 
1742
&nbsp;&nbsp;Tcl_Init(interp);<br>
 
1743
&nbsp;&nbsp;Tcl_Eval(interp,&nbsp;zInputLoop);<br>
 
1744
&nbsp;&nbsp;return&nbsp;0;<br>
 
1745
}</tt></small></td>
 
1746
<td></td><td></td><td></td><td></td>
 
1747
</tr>
 
1748
</table>
 
1749
 
 
1750
<br clear="both"><p><hr></p>
 
1751
<h2 align="center">The <tt>TclAccessInsertProc()</tt> Function</h2>
 
1752
<table cellspacing="0" cellpadding="0" border="0">
 
1753
<tr><td valign="center">
 
1754
<small><tt>#include&nbsp;&lt;tclInt.h></tt></small></td>
 
1755
<td>&nbsp;&nbsp;</td>
 
1756
<td valign="center"><img src="image2"></td>
 
1757
<td>&nbsp;&nbsp;</td>
 
1758
<td valign="center">Rather than <tt>&lt;tcl.h&gt;</tt>!</td>
 
1759
</tr>
 
1760
<tr><td valign="center">
 
1761
<small><tt><br>
 
1762
/*&nbsp;BltinFileStat()&nbsp;not&nbsp;shown...&nbsp;*/<br>
 
1763
&nbsp;<br>
 
1764
static&nbsp;int<br>
 
1765
BltinFileAccess(char&nbsp;*path,&nbsp;int&nbsp;mode){<br>
 
1766
&nbsp;&nbsp;char&nbsp;*zData;</tt></small></td>
 
1767
<td></td><td></td><td></td><td></td>
 
1768
</tr>
 
1769
<tr><td valign="center">
 
1770
<small><tt>&nbsp;&nbsp;if(&nbsp;mode&nbsp;&amp;&nbsp;3&nbsp;)&nbsp;return&nbsp;-1;</tt></small></td>
 
1771
<td>&nbsp;&nbsp;</td>
 
1772
<td valign="center"><img src="image2"></td>
 
1773
<td>&nbsp;&nbsp;</td>
 
1774
<td valign="center">All builtins are read-only</td>
 
1775
</tr>
 
1776
<tr><td valign="center">
 
1777
<small><tt>&nbsp;&nbsp;zData&nbsp;=&nbsp;FindBuiltinFile(path,&nbsp;0,&nbsp;&amp;nData);</tt></small></td>
 
1778
<td>&nbsp;&nbsp;</td>
 
1779
<td valign="center"><img src="image2"></td>
 
1780
<td>&nbsp;&nbsp;</td>
 
1781
<td valign="center">Check if <tt>path</tt> is a builtin</td>
 
1782
</tr>
 
1783
<tr><td valign="center">
 
1784
<small><tt>&nbsp;&nbsp;if(&nbsp;zData==0&nbsp;)&nbsp;return&nbsp;-1;</tt></small></td>
 
1785
<td>&nbsp;&nbsp;</td>
 
1786
<td valign="center"><img src="image2"></td>
 
1787
<td>&nbsp;&nbsp;</td>
 
1788
<td valign="center">Fail if <tt>path</tt> is not a builtin</td>
 
1789
</tr>
 
1790
<tr><td valign="center">
 
1791
<small><tt>&nbsp;&nbsp;return&nbsp;0;</tt></small></td>
 
1792
<td>&nbsp;&nbsp;</td>
 
1793
<td valign="center"><img src="image2"></td>
 
1794
<td>&nbsp;&nbsp;</td>
 
1795
<td valign="center">Success if it is builtin</td>
 
1796
</tr>
 
1797
<tr><td valign="center">
 
1798
<small><tt>}<br>
 
1799
&nbsp;<br>
 
1800
int&nbsp;main(int&nbsp;argc,&nbsp;char&nbsp;**argv){<br>
 
1801
&nbsp;&nbsp;Tcl_Interp&nbsp;*interp;</tt></small></td>
 
1802
<td></td><td></td><td></td><td></td>
 
1803
</tr>
 
1804
<tr><td valign="center">
 
1805
<small><tt>&nbsp;&nbsp;TclStatInsertProc(BltinFileStat);<br>
 
1806
&nbsp;&nbsp;TclAccessInsertProc(BltinFileAccess);</tt></small></td>
 
1807
<td>&nbsp;&nbsp;</td>
 
1808
<td valign="center"><img src="image2"></td>
 
1809
<td>&nbsp;&nbsp;</td>
 
1810
<td valign="center">Register new <tt>stat</tt> and <tt>access</tt> functions</td>
 
1811
</tr>
 
1812
<tr><td valign="center">
 
1813
<small><tt>&nbsp;&nbsp;interp&nbsp;=&nbsp;Tcl_CreateInterp();<br>
 
1814
&nbsp;&nbsp;Tcl_Init(interp);<br>
 
1815
&nbsp;&nbsp;Tcl_Eval(interp,&nbsp;zInputLoop);<br>
 
1816
&nbsp;&nbsp;return&nbsp;0;<br>
 
1817
}</tt></small></td>
 
1818
<td></td><td></td><td></td><td></td>
 
1819
</tr>
 
1820
</table>
 
1821
 
 
1822
<br clear="both"><p><hr></p>
 
1823
<h2 align="center">The <tt>TclOpenFileChannelInsertProc()</tt> Function</h2>
 
1824
<table cellspacing="0" cellpadding="0" border="0">
 
1825
<tr><td valign="center">
 
1826
<small><tt>static&nbsp;Tcl_Channel&nbsp;BuiltinFileOpen(<br>
 
1827
&nbsp;&nbsp;Tcl_Interp&nbsp;*interp,&nbsp;&nbsp;&nbsp;/*&nbsp;The&nbsp;TCL&nbsp;interpreter&nbsp;doing&nbsp;the&nbsp;open&nbsp;*/<br>
 
1828
&nbsp;&nbsp;char&nbsp;*zFilename,&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;/*&nbsp;Name&nbsp;of&nbsp;the&nbsp;file&nbsp;to&nbsp;open&nbsp;*/<br>
 
1829
&nbsp;&nbsp;char&nbsp;*modeString,&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;/*&nbsp;Mode&nbsp;string&nbsp;for&nbsp;the&nbsp;open&nbsp;(ignored)&nbsp;*/<br>
 
1830
&nbsp;&nbsp;int&nbsp;permissions&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;/*&nbsp;Permissions&nbsp;for&nbsp;a&nbsp;newly&nbsp;created&nbsp;file&nbsp;(ignored)&nbsp;*/<br>
 
1831
){<br>
 
1832
&nbsp;&nbsp;char&nbsp;*zData;<br>
 
1833
&nbsp;&nbsp;BuiltinFileStruct&nbsp;*p;<br>
 
1834
&nbsp;&nbsp;int&nbsp;nData;<br>
 
1835
&nbsp;&nbsp;char&nbsp;zName[50];<br>
 
1836
&nbsp;&nbsp;Tcl_Channel&nbsp;chan;<br>
 
1837
&nbsp;&nbsp;static&nbsp;int&nbsp;count&nbsp;=&nbsp;1;<br>
 
1838
&nbsp;<br>
 
1839
&nbsp;&nbsp;zData&nbsp;=&nbsp;FindBuiltinFile(zFilename,&nbsp;1,&nbsp;&amp;nData);<br>
 
1840
&nbsp;&nbsp;if(&nbsp;zData==0&nbsp;)&nbsp;return&nbsp;NULL;<br>
 
1841
&nbsp;&nbsp;p&nbsp;=&nbsp;(BuiltinFileStruct*)Tcl_Alloc(&nbsp;sizeof(BuiltinFileStruct)&nbsp;);<br>
 
1842
&nbsp;&nbsp;if(&nbsp;p==0&nbsp;)&nbsp;return&nbsp;NULL;<br>
 
1843
&nbsp;&nbsp;p->zData&nbsp;=&nbsp;zData;<br>
 
1844
&nbsp;&nbsp;p->nData&nbsp;=&nbsp;nData;<br>
 
1845
&nbsp;&nbsp;p->cursor&nbsp;=&nbsp;0;<br>
 
1846
&nbsp;&nbsp;sprintf(zName,"etbi_bffffc7c_8049b04",((int)BuiltinFileOpen)>>12,count++);<br>
 
1847
&nbsp;&nbsp;chan&nbsp;=&nbsp;Tcl_CreateChannel(&amp;builtinChannelType,&nbsp;zName,&nbsp;<br>
 
1848
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(ClientData)p,&nbsp;TCL_READABLE);<br>
 
1849
&nbsp;&nbsp;return&nbsp;chan;<br>
 
1850
}</tt></small></td>
 
1851
<td></td><td></td><td></td><td></td>
 
1852
</tr>
 
1853
</table>
 
1854
 
 
1855
<br clear="both"><p><hr></p>
 
1856
<h2 align="center">The <tt>TclOpenFileChannelInsertProc()</tt> Function</h2>
 
1857
<table cellspacing="0" cellpadding="0" border="0">
 
1858
<tr><td valign="center">
 
1859
<small><tt>static&nbsp;Tcl_ChannelType&nbsp;builtinChannelType&nbsp;=&nbsp;{<br>
 
1860
&nbsp;&nbsp;"builtin",&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;/*&nbsp;Type&nbsp;name.&nbsp;*/<br>
 
1861
&nbsp;&nbsp;NULL,&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;/*&nbsp;Always&nbsp;non-blocking.*/<br>
 
1862
&nbsp;&nbsp;BuiltinFileClose,&nbsp;&nbsp;&nbsp;/*&nbsp;Close&nbsp;proc.&nbsp;*/<br>
 
1863
&nbsp;&nbsp;BuiltinFileInput,&nbsp;&nbsp;&nbsp;/*&nbsp;Input&nbsp;proc.&nbsp;*/<br>
 
1864
&nbsp;&nbsp;BuiltinFileOutput,&nbsp;&nbsp;/*&nbsp;Output&nbsp;proc.&nbsp;*/<br>
 
1865
&nbsp;&nbsp;BuiltinFileSeek,&nbsp;&nbsp;&nbsp;&nbsp;/*&nbsp;Seek&nbsp;proc.&nbsp;*/<br>
 
1866
&nbsp;&nbsp;NULL,&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;/*&nbsp;Set&nbsp;option&nbsp;proc.&nbsp;*/<br>
 
1867
&nbsp;&nbsp;NULL,&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;/*&nbsp;Get&nbsp;option&nbsp;proc.&nbsp;*/<br>
 
1868
&nbsp;&nbsp;BuiltinFileWatch,&nbsp;&nbsp;&nbsp;/*&nbsp;Watch&nbsp;for&nbsp;events&nbsp;on&nbsp;console.&nbsp;*/<br>
 
1869
&nbsp;&nbsp;BuiltinFileHandle,&nbsp;&nbsp;/*&nbsp;Get&nbsp;a&nbsp;handle&nbsp;from&nbsp;the&nbsp;device.&nbsp;*/<br>
 
1870
};</tt></small></td>
 
1871
<td></td><td></td><td></td><td></td>
 
1872
</tr>
 
1873
</table>
 
1874
<p>
 
1875
  <p>For additional information see:</p>
 
1876
  <ul>
 
1877
  <li>The man page for <tt>Tcl_CreateChannel()</tt></li>
 
1878
  <li>Tk source code file <tt>generic/tkConsole.c</tt></li>
 
1879
  </ul>
 
1880
</p>
 
1881
 
 
1882
<br clear="both"><p><hr></p>
 
1883
<h2 align="center">Initializing Tk</h2>
 
1884
<p><ul><li>All the same initialization script issues as Tcl</li></ul><ul><li>Tk initialization scripts are in a different directory
 
1885
  than the Tcl initialization scripts - the "Tk Library"</li></ul><ul><li>Call <tt>Tk_Init()</tt> after <tt>Tcl_Init()</tt></li></ul><ul><li>Must have an event loop or Tk will not work!</li></ul></p>
 
1886
<br clear="both"><p><hr></p>
 
1887
<h2 align="center">Implementing An Event Loop</h2>
 
1888
<table cellspacing="0" cellpadding="0" border="0">
 
1889
<tr><td valign="center">
 
1890
<small><tt>button&nbsp;.b&nbsp;-text&nbsp;Hello&nbsp;-command&nbsp;exit<br>
 
1891
pack&nbsp;.b</tt></small></td>
 
1892
<td>&nbsp;&nbsp;</td>
 
1893
<td valign="center"><img src="image2"></td>
 
1894
<td>&nbsp;&nbsp;</td>
 
1895
<td valign="center">Create a Tk interface</td>
 
1896
</tr>
 
1897
<tr><td valign="center">
 
1898
<small><tt><br>
 
1899
</tt></small></td>
 
1900
<td></td><td></td><td></td><td></td>
 
1901
</tr>
 
1902
<tr><td valign="center">
 
1903
<small><tt>bind&nbsp;.&nbsp;&lt;Destroy>&nbsp;{<br>
 
1904
&nbsp;&nbsp;if&nbsp;{![winfo&nbsp;exists&nbsp;.]}&nbsp;exit<br>
 
1905
}</tt></small></td>
 
1906
<td>&nbsp;&nbsp;</td>
 
1907
<td valign="center"><img src="image2"></td>
 
1908
<td>&nbsp;&nbsp;</td>
 
1909
<td valign="center">Close the application when the main window
 
1910
  is destroyed</td>
 
1911
</tr>
 
1912
<tr><td valign="center">
 
1913
<small><tt><br>
 
1914
</tt></small></td>
 
1915
<td></td><td></td><td></td><td></td>
 
1916
</tr>
 
1917
<tr><td valign="center">
 
1918
<small><tt>while&nbsp;1&nbsp;{vwait&nbsp;forever}</tt></small></td>
 
1919
<td>&nbsp;&nbsp;</td>
 
1920
<td valign="center"><img src="image2"></td>
 
1921
<td>&nbsp;&nbsp;</td>
 
1922
<td valign="center">The event loop</td>
 
1923
</tr>
 
1924
</table>
 
1925
 
 
1926
<br clear="both"><p><hr></p>
 
1927
<h2 align="center">"Hello, World!" Using Tk</h2>
 
1928
<table cellspacing="0" cellpadding="0" border="0">
 
1929
<tr><td valign="center">
 
1930
<small><tt>#include&nbsp;&lt;tk.h><br>
 
1931
&nbsp;<br>
 
1932
</tt></small></td>
 
1933
<td></td><td></td><td></td><td></td>
 
1934
</tr>
 
1935
<tr><td valign="center">
 
1936
<small><tt>static&nbsp;char&nbsp;zHello[]&nbsp;=&nbsp;</tt></small></td>
 
1937
<td>&nbsp;&nbsp;</td>
 
1938
<td valign="center"><img src="image2"></td>
 
1939
<td>&nbsp;&nbsp;</td>
 
1940
<td valign="center">The application code</td>
 
1941
</tr>
 
1942
<tr><td valign="center">
 
1943
<small><tt>&nbsp;&nbsp;"button&nbsp;.b&nbsp;"<br>
 
1944
&nbsp;&nbsp;&nbsp;&nbsp;"-text&nbsp;{Hello,&nbsp;World}&nbsp;"<br>
 
1945
&nbsp;&nbsp;&nbsp;&nbsp;"-command&nbsp;exit\n"<br>
 
1946
&nbsp;&nbsp;"pack&nbsp;.b\n";<br>
 
1947
&nbsp;<br>
 
1948
</tt></small></td>
 
1949
<td></td><td></td><td></td><td></td>
 
1950
</tr>
 
1951
<tr><td valign="center">
 
1952
<small><tt>static&nbsp;char&nbsp;zEventLoop[]&nbsp;=</tt></small></td>
 
1953
<td>&nbsp;&nbsp;</td>
 
1954
<td valign="center"><img src="image2"></td>
 
1955
<td>&nbsp;&nbsp;</td>
 
1956
<td valign="center">The event loop</td>
 
1957
</tr>
 
1958
<tr><td valign="center">
 
1959
<small><tt>&nbsp;&nbsp;"bind&nbsp;.&nbsp;&lt;Destroy>&nbsp;{\n"<br>
 
1960
&nbsp;&nbsp;"&nbsp;&nbsp;if&nbsp;{![winfo&nbsp;exists&nbsp;.]}&nbsp;exit\n"<br>
 
1961
&nbsp;&nbsp;"}\n"<br>
 
1962
&nbsp;&nbsp;"while&nbsp;1&nbsp;{vwait&nbsp;forever}\n";<br>
 
1963
&nbsp;<br>
 
1964
<br>
 
1965
int&nbsp;main(int&nbsp;argc,&nbsp;char&nbsp;**argv){<br>
 
1966
&nbsp;&nbsp;Tcl_Interp&nbsp;*interp;<br>
 
1967
&nbsp;&nbsp;interp&nbsp;=&nbsp;Tcl_CreateInterp();</tt></small></td>
 
1968
<td></td><td></td><td></td><td></td>
 
1969
</tr>
 
1970
<tr><td valign="center">
 
1971
<small><tt>&nbsp;&nbsp;Tcl_Init(interp);<br>
 
1972
&nbsp;&nbsp;Tk_Init(interp);</tt></small></td>
 
1973
<td>&nbsp;&nbsp;</td>
 
1974
<td valign="center"><img src="image2"></td>
 
1975
<td>&nbsp;&nbsp;</td>
 
1976
<td valign="center">We really should check the return values of the init functions...</td>
 
1977
</tr>
 
1978
<tr><td valign="center">
 
1979
<small><tt>&nbsp;&nbsp;Tcl_Eval(interp,&nbsp;zHello);</tt></small></td>
 
1980
<td></td><td></td><td></td><td></td>
 
1981
</tr>
 
1982
<tr><td valign="center">
 
1983
<small><tt>&nbsp;&nbsp;Tcl_Eval(interp,&nbsp;zEventLoop);</tt></small></td>
 
1984
<td>&nbsp;&nbsp;</td>
 
1985
<td valign="center"><img src="image2"></td>
 
1986
<td>&nbsp;&nbsp;</td>
 
1987
<td valign="center">The event loop never returns</td>
 
1988
</tr>
 
1989
<tr><td valign="center">
 
1990
<small><tt>&nbsp;&nbsp;/*NOTREACHED*/<br>
 
1991
}</tt></small></td>
 
1992
<td></td><td></td><td></td><td></td>
 
1993
</tr>
 
1994
</table>
 
1995
 
 
1996
<br clear="both"><p><hr></p>
 
1997
<h2 align="center">Compiling "Hello, World!" For Tk</h2>
 
1998
<p><p><b>Unix:</b></p>
 
1999
  <blockquote><pre>
 
2000
  $ gcc hello.c -ltk -L/usr/X11R6/lib \ 
 
2001
        -lX11 -ltcl -lm -ldl
 
2002
  $ ./a.out</pre></blockquote>
 
2003
 
 
2004
  <p><b>Windows using Cygwin:</b></p>
 
2005
  <blockquote><pre>
 
2006
  C:> gcc hello.c -mwindows -ltk80 -ltcl80 -lm
 
2007
  C:> a.exe</pre></blockquote>
 
2008
 
 
2009
  <p><b>Windows using Mingw32:</b></p>
 
2010
  <blockquote><pre>
 
2011
  C:> gcc -mno-cygwin hello.c -mwindows \ 
 
2012
           -ltk82 -ltcl82 -lm
 
2013
  C:> a.exe</pre></blockquote></p>
 
2014
<br clear="both"><p><hr></p>
 
2015
<h2 align="center">Making The Program Standalone</h2>
 
2016
<p><p>To make a Tcl application standalone you have to convert the following
 
2017
     initialization scripts to C strings and compile them into the
 
2018
     executable:</p>
 
2019
  <table><tr>
 
2020
  <td valign="top"><tt>
 
2021
    &nbsp;&nbsp;auto.tcl<br>
 
2022
    &nbsp;&nbsp;history.tcl<br>
 
2023
    &nbsp;&nbsp;init.tcl
 
2024
  </tt></td>
 
2025
  <td valign="top"><tt>
 
2026
    &nbsp;&nbsp;ldAout.tcl<br>
 
2027
    &nbsp;&nbsp;package.tcl
 
2028
  </tt></td>
 
2029
  <td valign="top"><tt>
 
2030
    &nbsp;&nbsp;parray.tcl<br>
 
2031
    &nbsp;&nbsp;safe.tcl
 
2032
  </tt></td>
 
2033
  <td valign="top"><tt>
 
2034
    &nbsp;&nbsp;tclIndex<br>
 
2035
    &nbsp;&nbsp;word.tcl
 
2036
  </tt></td>
 
2037
  </tr></table>
 
2038
 
 
2039
  <p>To make a Tk application standalone requires these additional
 
2040
     initialization scripts from the Tk Library:</p>
 
2041
  <table><tr>
 
2042
  <td valign="top"><tt>
 
2043
    &nbsp;&nbsp;bgerror.tcl<br>
 
2044
    &nbsp;&nbsp;button.tcl<br>
 
2045
    &nbsp;&nbsp;clrpick.tcl<br>
 
2046
    &nbsp;&nbsp;comdlg.tcl<br>
 
2047
    &nbsp;&nbsp;console.tcl<br>
 
2048
    &nbsp;&nbsp;dialog.tcl
 
2049
  </tt></td>
 
2050
  <td valign="top"><tt>
 
2051
    &nbsp;&nbsp;entry.tcl<br>
 
2052
    &nbsp;&nbsp;focus.tcl<br>
 
2053
    &nbsp;&nbsp;listbox.tcl<br>
 
2054
    &nbsp;&nbsp;menu.tcl<br>
 
2055
    &nbsp;&nbsp;msgbox.tcl<br>
 
2056
    &nbsp;&nbsp;optMenu.tcl
 
2057
  </tt></td>
 
2058
  <td valign="top"><tt>
 
2059
    &nbsp;&nbsp;palette.tcl<br>
 
2060
    &nbsp;&nbsp;safetk.tcl<br>
 
2061
    &nbsp;&nbsp;scale.tcl<br>
 
2062
    &nbsp;&nbsp;scrlbar.tcl<br>
 
2063
    &nbsp;&nbsp;tclIndex<br>
 
2064
    &nbsp;&nbsp;tearoff.tcl
 
2065
  </tt></td>
 
2066
  <td valign="top"><tt>
 
2067
    &nbsp;&nbsp;text.tcl<br>
 
2068
    &nbsp;&nbsp;tk.tcl<br>
 
2069
    &nbsp;&nbsp;tkfbox.tcl<br>
 
2070
    &nbsp;&nbsp;xmfbox.tcl
 
2071
  </tt></td>
 
2072
  </tr></table>
 
2073
 
 
2074
  <p>Total of about 13K lines and 400K bytes of text or 9K lines and
 
2075
     250K bytes if you strip comments and leading spaces</p></p>
 
2076
<br clear="both"><p><hr></p>
 
2077
<h2 align="center">A Review Of The Features We Want</h2>
 
2078
<p><ol type="A">
 
2079
  <li value="1">
 
2080
  Combine C/C++ with Tcl/Tk into a single executable.</dd>
 
2081
  </li></ol>
 
2082
 
 
2083
  <ol type="A">
 
2084
  <li value="2">
 
2085
  The executable should be standalone.  It must not depend
 
2086
  on files not normally found on the system.
 
2087
  </li></ol>
 
2088
 
 
2089
  <ol type="A">
 
2090
  <li value="3">
 
2091
  It should be difficult for end users to alter the program
 
2092
  (and introduce bugs).
 
2093
  </li></ol></p>
 
2094
<br clear="both"><p><hr></p>
 
2095
<h2 align="center">Available Programming Aids</h2>
 
2096
<p><p>Several tools are available.  The chart below shows which tools
 
2097
 help achieve which objectives.</p>
 
2098
 
 
2099
 <center><table border="2">
 
2100
 <tr>
 
2101
   <td></td>
 
2102
   <td colspan="3" align="center">
 
2103
      <b>Features The Tool Helps To Achieve</b></td>
 
2104
 </tr>
 
2105
 <tr>
 
2106
   <td align="center"><b>Tool Name</b></td>
 
2107
   <td align="center">Mix C and Tcl</td>
 
2108
   <td align="center">Standalone</td>
 
2109
   <td align="center">Hide Source</td>
 
2110
 </tr>
 
2111
 <tr>
 
2112
   <td>SWIG</td>
 
2113
   <td align="center"><img src="image6"></td>
 
2114
   <td>&nbsp;</td>
 
2115
   <td>&nbsp;</td>
 
2116
 </tr>
 
2117
 <tr>
 
2118
   <td>TclPro Wrapper</td>
 
2119
   <td>&nbsp;</td>
 
2120
   <td align="center"><img src="image6"></td>
 
2121
   <td align="center"><img src="image6"></td>
 
2122
 </tr>
 
2123
 <tr>
 
2124
   <td>FreeWrap</td>
 
2125
   <td>&nbsp;</td>
 
2126
   <td align="center"><img src="image6"></td>
 
2127
   <td align="center"><img src="image6"></td>
 
2128
 </tr>
 
2129
 <tr>
 
2130
   <td>Wrap</td>
 
2131
   <td>&nbsp;</td>
 
2132
   <td align="center"><img src="image6"></td>
 
2133
   <td>&nbsp;</td>
 
2134
 </tr>
 
2135
 <tr>
 
2136
   <td>mktclapp</td>
 
2137
   <td align="center"><img src="image6"></td>
 
2138
   <td align="center"><img src="image6"></td>
 
2139
   <td align="center"><img src="image6"></td>
 
2140
 </tr>
 
2141
 </table></center></p>
 
2142
<br clear="both"><p><hr></p>
 
2143
<h2 align="center">SWIG</h2>
 
2144
<table><tr><td valign="top"><img src="image7"></td>
 
2145
<td valign="top"><p><ul><li>Creates an interface between an existing C/C++ library and a high-level
 
2146
  programming language.  Support for:
 
2147
  <ul>
 
2148
  <li> Tcl/Tk </li>
 
2149
  <li> Perl </li>
 
2150
  <li> Python </li>
 
2151
  <li> Java </li>
 
2152
  <li> Eiffel </li>
 
2153
  <li> Guile </li>
 
2154
  </ul></li></ul><ul><li>No changes required to C/C++ code.  Can be used with legacy libraries.</li></ul><ul><li>Generates an extension, not a standalone binary</li></ul><ul><li>The tutorial on SWIG was yesterday afternoon.</li></ul><ul><li>http://www.swig.org/</li></ul></p></td></tr></table>
 
2155
 
 
2156
<br clear="both"><p><hr></p>
 
2157
<h2 align="center">Wrapper Programs</h2>
 
2158
<table><tr><td valign="top"><img src="image8"></td>
 
2159
<td valign="top"><p><ul><li>Convert a pure Tcl/Tk program into a standalone binary</li></ul><ul><li>Several wrapper programs are available:
 
2160
  <ul>
 
2161
  <li> TclPro Wrapper - http://www.scriptics.com/ </li>
 
2162
  <li> FreeWrap - http://www.albany.net/~dlabelle/freewrap/freewrap.html </li>
 
2163
  <li> Wrap - http://members1.chello.nl/~j.nijtmans/wrap.html </li>
 
2164
  </ul></li></ul><ul><li>No C compiler required!</li></ul><ul><li>TclPro will convert Tcl script into bytecode so that it cannot be
 
2165
  easily read by the end user.  FreeWrap encrypts the scripts.</li></ul><ul><li>FreeWrap uses compression on its executable. 
 
2166
  Wrap uses compression on both the executable and on the bundled script files.</li></ul><ul><li>Usually include extensions like winico and/or BLT</li></ul></p></td></tr></table>
 
2167
 
 
2168
<br clear="both"><p><hr></p>
 
2169
<h2 align="center">mktclapp</h2>
 
2170
<table><tr><td valign="top"><img src="image9"></td>
 
2171
<td valign="top"><p><ul><li>Mix C/C++ with Tcl/Tk into a standalone binary</li></ul>
 
2172
<ul><li><tt>mktclapp</tt> generates an application initialization file
 
2173
  that contains Tcl scripts as strings and makes all necessary calls 
 
2174
  to <tt>Tcl_Init</tt>, <tt>Tcl_CreateCommand</tt>, 
 
2175
  <tt>Tcl</tt>*<tt>InsertProc</tt>, etc.</li></ul><ul><li>Features to make it easier to write new Tcl command in C</li></ul><ul><li><tt>xmktclapp.tcl</tt> provides a GUI interface to <tt>mktclapp</tt></li></ul><ul><li>http://www.hwaci.com/sw/mktclapp/</li></ul></p></td></tr></table>
 
2176
 
 
2177
<br clear="both"><p><hr></p>
 
2178
<h2 align="center">"Hello, World!" Using Mktclapp</h2>
 
2179
<p><ul><li>Download <tt>mktclapp.c</tt> and <tt>xmktclapp.tcl</tt> from
 
2180
  http://www.hwaci.com/sw/mktclapp/</li></ul><ul><li>Compile <tt>mktclapp</tt>:
 
2181
  <blockquote><pre>
 
2182
  cc -o mktclapp mktclapp.c
 
2183
  </pre></blockquote></li></ul><ul><li>Create "Hello, World!" as a Tcl script in file <tt>hw.tcl</tt>:
 
2184
  <blockquote><pre>
 
2185
  button .b -text {Hello, World!} -command exit
 
2186
  pack .b
 
2187
  </pre></blockquote></li></ul><ul><li>Launch xmktclapp:
 
2188
  <blockquote><pre>
 
2189
  wish xmktclapp.tcl
 
2190
  </pre></blockquote></li></ul></p>
 
2191
<br clear="both"><p><hr></p>
 
2192
<h2 align="center">"Hello, World!" Using Mktclapp</h2>
 
2193
<table width="100%"><tr><td valign="top"><p><ul><li>Set "Command Line Input?" to "None"</li></ul><ul><li>Set "Standalone?" to "Yes"</li></ul><ul><li>Enter "<tt>hw.mta</tt>" for the Configuration File</li></ul><ul><li>Enter "<tt>hw.c</tt>" for the Output C File</li></ul></p></td>
 
2194
<td valign="top" align="right"><img src="image10"></td></tr></table>
 
2195
 
 
2196
<br clear="both"><p><hr></p>
 
2197
<h2 align="center">"Hello, World!" Using Mktclapp</h2>
 
2198
<table width="100%"><tr><td valign="top"><p><ul><li>Go to the "Tcl Scripts" page</li></ul><ul><li>Press "Insert" and add <tt>hw.tcl</tt> to the list of
 
2199
  Tcl scripts</li></ul><ul><li>Change the "Startup Script" to be <tt>hw.tcl</tt>.</li></ul><ul><li>Select File/Build and File/Exit</li></ul></p></td>
 
2200
<td valign="top" align="right"><img src="image11"></td></tr></table>
 
2201
 
 
2202
<br clear="both"><p><hr></p>
 
2203
<h2 align="center">"Hello, World!" Using Mktclapp</h2>
 
2204
<p><ul><li>Mktclapp generates <tt>hw.c</tt>.
 
2205
  Compile it something like this:
 
2206
  <pre>
 
2207
  cc hw.c -ltk -L/usr/X11R6/lib -lX11 -ltcl -lm -ldl
 
2208
  </pre></li></ul><ul><li>Or, if using Cygwin:
 
2209
  <pre>
 
2210
  gcc hw.c -mwindows -ltk80 -ltcl80 -lm
 
2211
  </pre></li></ul><ul><li>Or, if using Mingw32:
 
2212
  <pre>
 
2213
  gcc -mno-cygwin hw.c -mwindows -ltk82 -ltcl82 -lm
 
2214
  </pre></li></ul><ul><li>And you're done!</li></ul></p>
 
2215
<br clear="both"><p><hr></p>
 
2216
<h2 align="center">Adding C Code To Your Program</h2>
 
2217
<p>Put the new C code in a new source file named "<tt>add.c</tt>"</p><p>
 
2218
<table cellspacing="0" cellpadding="0" border="0">
 
2219
<tr><td valign="center">
 
2220
<small><tt>#include&nbsp;"hw.h"</tt></small></td>
 
2221
<td>&nbsp;&nbsp;</td>
 
2222
<td valign="center"><img src="image2"></td>
 
2223
<td>&nbsp;&nbsp;</td>
 
2224
<td valign="center">Generated by mktclapp</td>
 
2225
</tr>
 
2226
<tr><td valign="center">
 
2227
<small><tt></tt></small></td>
 
2228
<td></td><td></td><td></td><td></td>
 
2229
</tr>
 
2230
<tr><td valign="center">
 
2231
<small><tt>int&nbsp;ET_COMMAND_add(ET_TCLARGS){</tt></small></td>
 
2232
<td>&nbsp;&nbsp;</td>
 
2233
<td valign="center"><img src="image2"></td>
 
2234
<td>&nbsp;&nbsp;</td>
 
2235
<td valign="center"><tt>ET_TCLARGS</tt> is a macro defined in <tt>hw.h</tt></td>
 
2236
</tr>
 
2237
<tr><td valign="center">
 
2238
<small><tt>&nbsp;&nbsp;int&nbsp;a,&nbsp;b;<br>
 
2239
&nbsp;&nbsp;char&nbsp;zResult[30];<br>
 
2240
&nbsp;&nbsp;a&nbsp;=&nbsp;atoi(argv[1]);<br>
 
2241
&nbsp;&nbsp;b&nbsp;=&nbsp;atoi(argv[2]);<br>
 
2242
&nbsp;&nbsp;sprintf(zResult,&nbsp;"-1073742724",&nbsp;a+b);<br>
 
2243
&nbsp;&nbsp;Tcl_SetResult(interp,&nbsp;zResult,&nbsp;TCL_VOLATILE);<br>
 
2244
&nbsp;&nbsp;return&nbsp;TCL_OK;<br>
 
2245
}</tt></small></td>
 
2246
<td></td><td></td><td></td><td></td>
 
2247
</tr>
 
2248
</table>
 
2249
 
 
2250
<br clear="both"><p><hr></p>
 
2251
<h2 align="center">Adding C Code To Your Program</h2>
 
2252
<table width="100%"><tr><td valign="top"><p><ul><li>Go to the "C/C++ Modules" page of xmktclapp.tcl</li></ul>
 
2253
<ul><li>Press "Insert" and add <tt>add.c</tt> to the list of
 
2254
  C/C++ modules</p></li></ul></li></ul><ul><li>Select File/Build and File/Exit</li></ul></p></td>
 
2255
<td valign="top" align="right"><img src="image12"></td></tr></table>
 
2256
 
 
2257
<br clear="both"><p><hr></p>
 
2258
<h2 align="center">Adding C Code To Your Program</h2>
 
2259
<p><ul><li>Compile as follows:
 
2260
  <pre>
 
2261
  cc add.c hw.c -ltk -L/usr/X11R6/lib -ltcl -lm -ldl
 
2262
  </pre></li></ul><ul><li>Or construct a Makefile that compiles <tt>add.c</tt> into <tt>add.o</tt>
 
2263
  and <tt>hw.c</tt> into <tt>hw.o</tt> and then links them.</li></ul><ul><li>Compile the same way for Windows except use the usual Windows
 
2264
  libraries and options...</li></ul><table><tr><td valign="top"><img src="image3"></td>
 
2265
<td valign="top"><b>Don't have to worry with <tt>Tcl_CreateCommand()</tt> - Mktclapp takes
 
2266
  care of that automatically.</b></td></tr></table></p>
 
2267
<br clear="both"><p><hr></p>
 
2268
<h2 align="center">Checking Parameters In The <tt>add</tt> Command</h2>
 
2269
<p>Modify <tt>add.c</tt> to insure the <tt>add</tt> command
 
2270
  is called with exactly two integer arguments</p><p>
 
2271
<table cellspacing="0" cellpadding="0" border="0">
 
2272
<tr><td valign="center">
 
2273
<small><tt>#include&nbsp;"hw.h"<br>
 
2274
&nbsp;<br>
 
2275
int&nbsp;ET_COMMAND_add(ET_TCLARGS){<br>
 
2276
&nbsp;&nbsp;int&nbsp;a,&nbsp;b;<br>
 
2277
&nbsp;&nbsp;char&nbsp;zResult[30];</tt></small></td>
 
2278
<td></td><td></td><td></td><td></td>
 
2279
</tr>
 
2280
<tr><td valign="center">
 
2281
<small><tt>&nbsp;&nbsp;if(&nbsp;argc!=3&nbsp;){<br>
 
2282
&nbsp;&nbsp;&nbsp;&nbsp;Tcl_AppendResult(interp,<br>
 
2283
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;"wrong&nbsp;#&nbsp;args:&nbsp;should&nbsp;be:&nbsp;\"",<br>
 
2284
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;argv[0],&nbsp;"&nbsp;VALUE&nbsp;VALUE\"",&nbsp;0);<br>
 
2285
&nbsp;&nbsp;&nbsp;&nbsp;return&nbsp;TCL_ERROR;<br>
 
2286
&nbsp;&nbsp;}</tt></small></td>
 
2287
<td>&nbsp;&nbsp;</td>
 
2288
<td valign="center"><img src="image2"></td>
 
2289
<td>&nbsp;&nbsp;</td>
 
2290
<td valign="center">Report an error if there are not exactly
 
2291
  2 arguments</td>
 
2292
</tr>
 
2293
<tr><td valign="center">
 
2294
<small><tt>&nbsp;&nbsp;if(&nbsp;Tcl_GetInt(interp,&nbsp;argv[1],&nbsp;&amp;a)!=TCL_OK&nbsp;){<br>
 
2295
&nbsp;&nbsp;&nbsp;&nbsp;return&nbsp;TCL_ERROR;<br>
 
2296
&nbsp;&nbsp;}</tt></small></td>
 
2297
<td>&nbsp;&nbsp;</td>
 
2298
<td valign="center"><img src="image2"></td>
 
2299
<td>&nbsp;&nbsp;</td>
 
2300
<td valign="center">Report an error if the first argument is
 
2301
  not an integer</td>
 
2302
</tr>
 
2303
<tr><td valign="center">
 
2304
<small><tt>&nbsp;&nbsp;if(&nbsp;Tcl_GetInt(interp,&nbsp;argv[2],&nbsp;&amp;b)!=TCL_OK&nbsp;){<br>
 
2305
&nbsp;&nbsp;&nbsp;&nbsp;return&nbsp;TCL_ERROR;<br>
 
2306
&nbsp;&nbsp;}</tt></small></td>
 
2307
<td>&nbsp;&nbsp;</td>
 
2308
<td valign="center"><img src="image2"></td>
 
2309
<td>&nbsp;&nbsp;</td>
 
2310
<td valign="center">Do the same for the second argument</td>
 
2311
</tr>
 
2312
<tr><td valign="center">
 
2313
<small><tt>&nbsp;&nbsp;sprintf(zResult,&nbsp;"-1073742724",&nbsp;a+b);<br>
 
2314
&nbsp;&nbsp;Tcl_SetResult(interp,&nbsp;zResult,&nbsp;TCL_VOLATILE);<br>
 
2315
&nbsp;&nbsp;return&nbsp;TCL_OK;<br>
 
2316
}</tt></small></td>
 
2317
<td></td><td></td><td></td><td></td>
 
2318
</tr>
 
2319
</table>
 
2320
 
 
2321
<br clear="both"><p><hr></p>
 
2322
<h2 align="center">Using The Tcl_Obj Interface</h2>
 
2323
<p>In the file <tt>objadd.c</tt> put this code:</p><p>
 
2324
<table cellspacing="0" cellpadding="0" border="0">
 
2325
<tr><td valign="center">
 
2326
<small><tt>#include&nbsp;"hw.h"</tt></small></td>
 
2327
<td></td><td></td><td></td><td></td>
 
2328
</tr>
 
2329
<tr><td valign="center">
 
2330
<small><tt><br>
 
2331
int&nbsp;ET_OBJCOMMAND_add2(ET_OBJARGS){<br>
 
2332
&nbsp;&nbsp;int&nbsp;a,&nbsp;b;</tt></small></td>
 
2333
<td>&nbsp;&nbsp;</td>
 
2334
<td valign="center"><img src="image2"></td>
 
2335
<td>&nbsp;&nbsp;</td>
 
2336
<td valign="center">Use "<tt>ET_OBJCOMMAND</tt>" instead of "<tt>ET_COMMAND</tt>" and
 
2337
  "<tt>ET_OBJARGS</tt>" instead of "<tt>ET_TCLARGS</tt>"</td>
 
2338
</tr>
 
2339
<tr><td valign="center">
 
2340
<small><tt>&nbsp;&nbsp;if(&nbsp;objc!=3&nbsp;){<br>
 
2341
&nbsp;&nbsp;&nbsp;&nbsp;Tcl_WrongNumArgs(interp,&nbsp;1,&nbsp;objv,<br>
 
2342
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;"number&nbsp;number");<br>
 
2343
&nbsp;&nbsp;&nbsp;&nbsp;return&nbsp;TCL_ERROR;<br>
 
2344
&nbsp;&nbsp;}</tt></small></td>
 
2345
<td>&nbsp;&nbsp;</td>
 
2346
<td valign="center"><img src="image2"></td>
 
2347
<td>&nbsp;&nbsp;</td>
 
2348
<td valign="center">A special routine for "wrong # args" error</td>
 
2349
</tr>
 
2350
<tr><td valign="center">
 
2351
<small><tt>&nbsp;&nbsp;if(&nbsp;Tcl_GetIntFromObj(interp,&nbsp;objv[1],&nbsp;&amp;a)&nbsp;){</tt></small></td>
 
2352
<td>&nbsp;&nbsp;</td>
 
2353
<td valign="center"><img src="image2"></td>
 
2354
<td>&nbsp;&nbsp;</td>
 
2355
<td valign="center">Instead of <tt>Tcl_GetInt</tt></td>
 
2356
</tr>
 
2357
<tr><td valign="center">
 
2358
<small><tt>&nbsp;&nbsp;&nbsp;&nbsp;return&nbsp;TCL_ERROR;<br>
 
2359
&nbsp;&nbsp;}<br>
 
2360
&nbsp;&nbsp;if(&nbsp;Tcl_GetIntFromObj(interp,&nbsp;objv[2],&nbsp;&amp;b)&nbsp;){<br>
 
2361
&nbsp;&nbsp;&nbsp;&nbsp;return&nbsp;TCL_ERROR;<br>
 
2362
&nbsp;&nbsp;}</tt></small></td>
 
2363
<td></td><td></td><td></td><td></td>
 
2364
</tr>
 
2365
<tr><td valign="center">
 
2366
<small><tt>&nbsp;&nbsp;Tcl_SetIntObj(Tcl_GetObjResult(interp),&nbsp;a+b);</tt></small></td>
 
2367
<td>&nbsp;&nbsp;</td>
 
2368
<td valign="center"><img src="image2"></td>
 
2369
<td>&nbsp;&nbsp;</td>
 
2370
<td valign="center">Result stored as integer, not a string</td>
 
2371
</tr>
 
2372
<tr><td valign="center">
 
2373
<small><tt>&nbsp;&nbsp;return&nbsp;TCL_OK;<br>
 
2374
}</tt></small></td>
 
2375
<td></td><td></td><td></td><td></td>
 
2376
</tr>
 
2377
</table>
 
2378
 
 
2379
<br clear="both"><p><hr></p>
 
2380
<h2 align="center">Speed Of Tcl_Obj Versus "char*"  Interfaces</h2>
 
2381
<p><ul><li>Compile both <tt>add</tt> and <tt>add2</tt> into the same executable.</li></ul><ul><li>Compare their speeds:
 
2382
  <pre>
 
2383
   time {add 123456 654321} 10000
 
2384
  <font color="blue">26 microseconds per iteration</font>
 
2385
   time {add2 123456 654321} 10000
 
2386
  <font color="blue">4 microseconds per iteration</font>
 
2387
  </pre></li></ul><ul><li>The Tcl_Obj version is 650 faster!</li></ul><ul><li>Replace the addition with a "real" computation that takes
 
2388
  10 milliseconds.</li></ul><ul><li>Now the Tcl_Obj version is only 0.2 faster!</li></ul><table><tr><td valign="top"><img src="image3"></td>
 
2389
<td valign="top"><b>In many real-world problems, the Tcl_Obj interface has no noticeable
 
2390
  speed advantage over the string interface.</b></td></tr></table></p>
 
2391
<br clear="both"><p><hr></p>
 
2392
<h2 align="center">More About Built-in Tcl Scripts</h2>
 
2393
<table><tr><td valign="top"><img src="image11"></td>
 
2394
<td valign="top"><p><ul><li>Comments and leading white-space are removed from the
 
2395
  script by default.  Use the "Don't Strip Comments"
 
2396
  button to change this.</li></ul><ul><li>The file name must exactly match the name that is
 
2397
  used by the <tt>source</tt> command.</li></ul></p></td></tr></table>
 
2398
 
 
2399
<br clear="both"><p><hr></p>
 
2400
<h2 align="center">Locations Of Libraries</h2>
 
2401
<table><tr><td valign="top"><img src="image13"></td>
 
2402
<td valign="top"><p><ul><li>Tells mktclapp where to look for script libraries.</li></ul><ul><li>All Tcl scripts in the indicated directories are
 
2403
  compiled into the <tt>appinit.c</tt> file.</li></ul><ul><li>Comments and extra white-space are removed. 
 
2404
  There is no way to turn this off.</li></ul></p></td></tr></table>
 
2405
 
 
2406
<br clear="both"><p><hr></p>
 
2407
<h2 align="center">Built-in Binary Data Files</h2>
 
2408
<table><tr><td valign="top"><img src="image14"></td>
 
2409
<td valign="top"><p><ul><li>Arbitrary files become part of the virtual filesystem</li></ul><ul><li>No comment or white-space removal is attempted</li></ul><ul><li>Useful for images or other binary data</li></ul></p></td></tr></table>
 
2410
 
 
2411
<br clear="both"><p><hr></p>
 
2412
<h2 align="center">New Commands In Namespaces</h2>
 
2413
<p>Two underscores (__)  are replaced by two colons (::) in
 
2414
  command names, thus giving the ability to define new commands
 
2415
  in a namespace</p><p>
 
2416
<table cellspacing="0" cellpadding="0" border="0">
 
2417
<tr><td valign="center">
 
2418
<small><tt>#include&nbsp;&lt;hw.h></tt></small></td>
 
2419
<td></td><td></td><td></td><td></td>
 
2420
</tr>
 
2421
<tr><td valign="center">
 
2422
<small><tt><br>
 
2423
int&nbsp;ET_COMMAND_adder__add(ET_TCLARGS){<br>
 
2424
&nbsp;&nbsp;int&nbsp;a,&nbsp;b;</tt></small></td>
 
2425
<td>&nbsp;&nbsp;</td>
 
2426
<td valign="center"><img src="image2"></td>
 
2427
<td>&nbsp;&nbsp;</td>
 
2428
<td valign="center">Creates the Tcl command called "<tt>adder::add</tt>"</td>
 
2429
</tr>
 
2430
<tr><td valign="center">
 
2431
<small><tt>&nbsp;&nbsp;char&nbsp;*zResult[30];<br>
 
2432
&nbsp;&nbsp;if(&nbsp;argc!=3&nbsp;){<br>
 
2433
&nbsp;&nbsp;&nbsp;&nbsp;Tcl_AppendResult(interp,<br>
 
2434
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;"wrong&nbsp;#&nbsp;args:&nbsp;should&nbsp;be:&nbsp;\"",<br>
 
2435
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;argv[0],&nbsp;"&nbsp;VALUE&nbsp;VALUE\"",&nbsp;0);<br>
 
2436
&nbsp;&nbsp;&nbsp;&nbsp;return&nbsp;TCL_ERROR;<br>
 
2437
&nbsp;&nbsp;}<br>
 
2438
&nbsp;&nbsp;if(&nbsp;Tcl_GetInt(interp,&nbsp;argv[1],&nbsp;&amp;a)!=TCL_OK&nbsp;){<br>
 
2439
&nbsp;&nbsp;&nbsp;&nbsp;return&nbsp;TCL_ERROR;<br>
 
2440
&nbsp;&nbsp;}<br>
 
2441
&nbsp;&nbsp;if(&nbsp;Tcl_GetInt(interp,&nbsp;argv[1],&nbsp;&amp;b)!=TCL_OK&nbsp;){<br>
 
2442
&nbsp;&nbsp;&nbsp;&nbsp;return&nbsp;TCL_ERROR;<br>
 
2443
&nbsp;&nbsp;}<br>
 
2444
&nbsp;&nbsp;sprintf(zResult,&nbsp;"-1073742724",&nbsp;a+b);<br>
 
2445
&nbsp;&nbsp;Tcl_SetResult(interp,&nbsp;zResult,&nbsp;TCL_VOLATILE);<br>
 
2446
&nbsp;&nbsp;return&nbsp;TCL_OK;<br>
 
2447
}</tt></small></td>
 
2448
<td></td><td></td><td></td><td></td>
 
2449
</tr>
 
2450
</table>
 
2451
 
 
2452
<br clear="both"><p><hr></p>
 
2453
<h2 align="center">Adding Your Own <tt>main()</tt></h2>
 
2454
<table cellspacing="0" cellpadding="0" border="0">
 
2455
<tr><td valign="center">
 
2456
<small><tt>int&nbsp;main(int&nbsp;argc,&nbsp;char&nbsp;**argv){<br>
 
2457
&nbsp;&nbsp;/*&nbsp;Application&nbsp;specific&nbsp;initialization&nbsp;*/</tt></small></td>
 
2458
<td></td><td></td><td></td><td></td>
 
2459
</tr>
 
2460
<tr><td valign="center">
 
2461
<small><tt>&nbsp;&nbsp;Et_Init(argc,&nbsp;argv);</tt></small></td>
 
2462
<td>&nbsp;&nbsp;</td>
 
2463
<td valign="center"><img src="image2"></td>
 
2464
<td>&nbsp;&nbsp;</td>
 
2465
<td valign="center">Never returns!</td>
 
2466
</tr>
 
2467
<tr><td valign="center">
 
2468
<small><tt>&nbsp;&nbsp;/*NOTREACHED*/<br>
 
2469
&nbsp;&nbsp;return&nbsp;0;<br>
 
2470
}</tt></small></td>
 
2471
<td></td><td></td><td></td><td></td>
 
2472
</tr>
 
2473
</table>
 
2474
<p><table><tr><td valign="top"><img src="image3"></td>
 
2475
<td valign="top"><b>The "Autofork" feature is disabled if you supply your own <tt>main()</tt></b></td></tr></table>
 
2476
</p>
 
2477
 
 
2478
<br clear="both"><p><hr></p>
 
2479
<h2 align="center">Initializing The Tcl Interpreter</h2>
 
2480
<table cellspacing="0" cellpadding="0" border="0">
 
2481
<tr><td valign="center">
 
2482
<small><tt>#include&nbsp;&lt;tcl.h><br>
 
2483
&nbsp;<br>
 
2484
int&nbsp;counter&nbsp;=&nbsp;0;<br>
 
2485
&nbsp;<br>
 
2486
int&nbsp;main(int&nbsp;argc,&nbsp;char&nbsp;**argv){<br>
 
2487
&nbsp;&nbsp;&nbsp;Et_Init(argc,&nbsp;argv);<br>
 
2488
&nbsp;&nbsp;&nbsp;/*NOTREACHED*/<br>
 
2489
&nbsp;&nbsp;&nbsp;return&nbsp;0;<br>
 
2490
}<br>
 
2491
&nbsp;<br>
 
2492
int&nbsp;Et_AppInit(Tcl_Interp&nbsp;*interp){</tt></small></td>
 
2493
<td></td><td></td><td></td><td></td>
 
2494
</tr>
 
2495
<tr><td valign="center">
 
2496
<small><tt>&nbsp;&nbsp;if(&nbsp;Blt_Init(Interp)&nbsp;){<br>
 
2497
&nbsp;&nbsp;&nbsp;&nbsp;return&nbsp;TCL_ERROR;<br>
 
2498
&nbsp;&nbsp;}</tt></small></td>
 
2499
<td>&nbsp;&nbsp;</td>
 
2500
<td valign="center"><img src="image2"></td>
 
2501
<td>&nbsp;&nbsp;</td>
 
2502
<td valign="center">Example: Initialize an extension</td>
 
2503
</tr>
 
2504
<tr><td valign="center">
 
2505
<small><tt>&nbsp;&nbsp;Tcl_LinkVar(interp,&nbsp;"counter",&nbsp;&amp;counter,<br>
 
2506
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;TCL_LINK_INT);</tt></small></td>
 
2507
<td>&nbsp;&nbsp;</td>
 
2508
<td valign="center"><img src="image2"></td>
 
2509
<td>&nbsp;&nbsp;</td>
 
2510
<td valign="center">Or link a C variable to a Tcl variable</td>
 
2511
</tr>
 
2512
<tr><td valign="center">
 
2513
<small><tt>&nbsp;&nbsp;return&nbsp;TCL_OK;</tt></small></td>
 
2514
<td>&nbsp;&nbsp;</td>
 
2515
<td valign="center"><img src="image2"></td>
 
2516
<td>&nbsp;&nbsp;</td>
 
2517
<td valign="center">Return TCL_OK if successful</td>
 
2518
</tr>
 
2519
<tr><td valign="center">
 
2520
<small><tt>}</tt></small></td>
 
2521
<td></td><td></td><td></td><td></td>
 
2522
</tr>
 
2523
</table>
 
2524
 
 
2525
<br clear="both"><p><hr></p>
 
2526
<h2 align="center">Writing Your Own Event Loop</h2>
 
2527
<table cellspacing="0" cellpadding="0" border="0">
 
2528
<tr><td valign="center">
 
2529
<small><tt>#include&nbsp;&lt;tcl.h><br>
 
2530
</tt></small></td>
 
2531
<td></td><td></td><td></td><td></td>
 
2532
</tr>
 
2533
<tr><td valign="center">
 
2534
<small><tt>void&nbsp;Et_CustomMainLoop(Tcl_Interp&nbsp;*interp){</tt></small></td>
 
2535
<td>&nbsp;&nbsp;</td>
 
2536
<td valign="center"><img src="image2"></td>
 
2537
<td>&nbsp;&nbsp;</td>
 
2538
<td valign="center">Replaces the default event loop</td>
 
2539
</tr>
 
2540
<tr><td valign="center">
 
2541
<small><tt>&nbsp;&nbsp;return;</tt></small></td>
 
2542
<td>&nbsp;&nbsp;</td>
 
2543
<td valign="center"><img src="image2"></td>
 
2544
<td>&nbsp;&nbsp;</td>
 
2545
<td valign="center">Ex: Return without handling any events.</td>
 
2546
</tr>
 
2547
<tr><td valign="center">
 
2548
<small><tt>}<br>
 
2549
&nbsp;<br>
 
2550
int&nbsp;main(int&nbsp;argc,&nbsp;char&nbsp;**argv){</tt></small></td>
 
2551
<td></td><td></td><td></td><td></td>
 
2552
</tr>
 
2553
<tr><td valign="center">
 
2554
<small><tt>&nbsp;&nbsp;Et_Init(argc,&nbsp;argv);</tt></small></td>
 
2555
<td>&nbsp;&nbsp;</td>
 
2556
<td valign="center"><img src="image2"></td>
 
2557
<td>&nbsp;&nbsp;</td>
 
2558
<td valign="center">This now returns after initializing Tcl</td>
 
2559
</tr>
 
2560
<tr><td valign="center">
 
2561
<small><tt>&nbsp;&nbsp;/*&nbsp;Application&nbsp;code&nbsp;here&nbsp;*/<br>
 
2562
&nbsp;&nbsp;return&nbsp;0;<br>
 
2563
}</tt></small></td>
 
2564
<td></td><td></td><td></td><td></td>
 
2565
</tr>
 
2566
</table>
 
2567
 
 
2568
<br clear="both"><p><hr></p>
 
2569
<h2 align="center">Writing Your Own Event Loop</h2>
 
2570
<table cellspacing="0" cellpadding="0" border="0">
 
2571
<tr><td valign="center">
 
2572
<small><tt>#include&nbsp;&lt;tcl.h><br>
 
2573
&nbsp;<br>
 
2574
void&nbsp;Et_CustomMainLoop(Tcl_Interp&nbsp;*interp){</tt></small></td>
 
2575
<td></td><td></td><td></td><td></td>
 
2576
</tr>
 
2577
<tr><td valign="center">
 
2578
<small><tt>&nbsp;&nbsp;for(;;){<br>
 
2579
&nbsp;&nbsp;&nbsp;&nbsp;Tcl_DoOneEvent(TCL_ALL_EVENTS|TCL_DONT_WAIT);<br>
 
2580
&nbsp;&nbsp;&nbsp;&nbsp;/*&nbsp;Other&nbsp;processing...&nbsp;*/<br>
 
2581
&nbsp;&nbsp;}</tt></small></td>
 
2582
<td>&nbsp;&nbsp;</td>
 
2583
<td valign="center"><img src="image2"></td>
 
2584
<td>&nbsp;&nbsp;</td>
 
2585
<td valign="center">Intermix processing and event handling</td>
 
2586
</tr>
 
2587
<tr><td valign="center">
 
2588
<small><tt>}<br>
 
2589
&nbsp;<br>
 
2590
int&nbsp;main(int&nbsp;argc,&nbsp;char&nbsp;**argv){</tt></small></td>
 
2591
<td></td><td></td><td></td><td></td>
 
2592
</tr>
 
2593
<tr><td valign="center">
 
2594
<small><tt>&nbsp;&nbsp;Et_Init(argc,&nbsp;argv);</tt></small></td>
 
2595
<td>&nbsp;&nbsp;</td>
 
2596
<td valign="center"><img src="image2"></td>
 
2597
<td>&nbsp;&nbsp;</td>
 
2598
<td valign="center">Never returns</td>
 
2599
</tr>
 
2600
<tr><td valign="center">
 
2601
<small><tt>&nbsp;&nbsp;/*NOTREACHED*/<br>
 
2602
&nbsp;&nbsp;return&nbsp;0;<br>
 
2603
}</tt></small></td>
 
2604
<td></td><td></td><td></td><td></td>
 
2605
</tr>
 
2606
</table>
 
2607
 
 
2608
<br clear="both"><p><hr></p>
 
2609
<h2 align="center">Mktclapp Initialization Sequence</h2>
 
2610
<p><ul><li>Initialization starts when the <tt>Et_Init()</tt> 
 
2611
  function is called either by client code or by
 
2612
  the <tt>main()</tt> that mktclapp generates</li></ul><ul><li>Create the main Tcl interpreter</li></ul><ul><li>Construct the virtual filesystem overlay by redefining
 
2613
  the <tt>source</tt> command and by using the 
 
2614
  <tt>Tcl</tt>*<tt>InsertProc()</tt> functions</li></ul><ul><li>Call <tt>Et_PreInit()</tt> if the client defines it</li></ul><ul><li>Call <tt>Tcl_Init()</tt> and <tt>Tk_Init()</tt></li></ul><ul><li>Call <tt>Tcl_CreateCommand()</tt> and <tt>Tcl_CreateObjCommand()</tt>
 
2615
  for every <tt>ET_COMMAND_</tt>* and <tt>ET_OBJCOMMAND_</tt>* function
 
2616
  in the client code</li></ul><ul><li>Call <tt>Et_AppInit()</tt> if the client defines it</li></ul><ul><li>Run the main Tcl script if there is one</li></ul><ul><li>Call <tt>Et_CustomMainLoop()</tt> if defined by client code or
 
2617
  else run the built-in event loop</li></ul></p>
 
2618
<br clear="both"><p><hr></p>
 
2619
<h2 align="center">Invoking Tcl From C</h2>
 
2620
<p><ul><li>Use one of the built-in evaluation functions:
 
2621
  <center><table width="80%">
 
2622
  <tr><td valign="top" width="50%"><ul>
 
2623
     <li> Tcl_Eval() </li>
 
2624
     <li> Tcl_VarEval() </li>
 
2625
     <li> Tcl_EvalFile() </li>
 
2626
     <li> Tcl_GlobalEval() </li>
 
2627
     </ul></td>
 
2628
  <td valign="top" width="50%"><ul>
 
2629
     <li> Tcl_EvalObj() </li>
 
2630
     <li> Tcl_GlobalEvalObj() </li>
 
2631
   </ul></td></tr>
 
2632
  </table></center></li></ul><ul><li>Mktclapp provides evaluation functions with variable argument
 
2633
  lists as in <tt>printf()</tt>:
 
2634
  <ul>
 
2635
  <li> Et_EvalF() </li>
 
2636
  <li> Et_GlobalEvalF() </li>
 
2637
  </ul></li></ul><ul><li>Mktclapp provides a global variable <tt>Et_Interp</tt> which is
 
2638
  a pointer to the main interpreter</li></ul></p>
 
2639
<br clear="both"><p><hr></p>
 
2640
<h2 align="center">Invoking Tcl From C</h2>
 
2641
<p>Example:  A C function that pops up an error message dialog box</p><p>
 
2642
<table cellspacing="0" cellpadding="0" border="0">
 
2643
<tr><td valign="center">
 
2644
<small><tt>#include&nbsp;"appinit.h"<br>
 
2645
&nbsp;<br>
 
2646
void&nbsp;ErrMsg(char&nbsp;*zMsg){<br>
 
2647
&nbsp;&nbsp;Tcl_SetVar(Et_Interp,&nbsp;"zMsg",&nbsp;zMsg,&nbsp;TCL_GLOBAL_ONLY);<br>
 
2648
&nbsp;&nbsp;Tcl_GlobalEval(Et_Interp,&nbsp;<br>
 
2649
&nbsp;&nbsp;&nbsp;&nbsp;"tk_messageBox&nbsp;-icon&nbsp;error&nbsp;-msg&nbsp;$zMsg&nbsp;-type&nbsp;ok");<br>
 
2650
&nbsp;&nbsp;Tcl_UnsetVar(Et_Interp,&nbsp;"zMsg",&nbsp;TCL_GLOBAL_ONLY);<br>
 
2651
}</tt></small></td>
 
2652
<td></td><td></td><td></td><td></td>
 
2653
</tr>
 
2654
</table>
 
2655
 
 
2656
<br clear="both"><p><hr></p>
 
2657
<h2 align="center">Invoking Tcl From C</h2>
 
2658
<p>The same C function implemented using <tt>Et_EvalF()</tt> instead
 
2659
  of <tt>Tcl_GlobalEval()</tt></p><p>
 
2660
<table cellspacing="0" cellpadding="0" border="0">
 
2661
<tr><td valign="center">
 
2662
<small><tt>#include&nbsp;"appinit.h"<br>
 
2663
&nbsp;<br>
 
2664
void&nbsp;ErrMsg(char&nbsp;*zMsg){<br>
 
2665
&nbsp;&nbsp;Et_EvalF(Et_Interp,&nbsp;<br>
 
2666
&nbsp;&nbsp;&nbsp;&nbsp;"tk_messageBox&nbsp;-icon&nbsp;error&nbsp;-msg&nbsp;{����P�X�}&nbsp;-type&nbsp;ok",<br>
 
2667
&nbsp;&nbsp;&nbsp;&nbsp;zMsg);<br>
 
2668
}</tt></small></td>
 
2669
<td></td><td></td><td></td><td></td>
 
2670
</tr>
 
2671
</table>
 
2672
<p>
 
2673
  <ul><li>
 
2674
  Suppose the function is called as follows:
 
2675
  <blockquote>
 
2676
    <tt>ErrMsg("Syntax error near \"}\"");</tt>
 
2677
  </blockquote>
 
2678
  </li></ul>
 
2679
 
 
2680
  <ul><li>
 
2681
  The command that gets executed is:
 
2682
  <pre>
 
2683
    tk_messageBox -icon error -msg \ 
 
2684
        {Syntax error near "}"} -type ok
 
2685
  </pre>
 
2686
  </li></ul>
 
2687
 
 
2688
  <ul><li>
 
2689
  But this is an ill-formed Tcl command!
 
2690
  </li></ul>
 
2691
</p>
 
2692
 
 
2693
<br clear="both"><p><hr></p>
 
2694
<h2 align="center">Invoking Tcl From C</h2>
 
2695
<p>Use the "<tt></tt>" format to generate a quoted string</p><p>
 
2696
<table cellspacing="0" cellpadding="0" border="0">
 
2697
<tr><td valign="center">
 
2698
<small><tt>#include&nbsp;"appinit.h"<br>
 
2699
&nbsp;<br>
 
2700
void&nbsp;ErrMsg(char&nbsp;*zMsg){<br>
 
2701
&nbsp;&nbsp;Et_EvalF(Et_Interp,&nbsp;<br>
 
2702
&nbsp;&nbsp;&nbsp;&nbsp;"tk_messageBox&nbsp;-icon&nbsp;error&nbsp;-msg&nbsp;\"%\"&nbsp;-type&nbsp;ok",<br>
 
2703
&nbsp;&nbsp;&nbsp;&nbsp;zMsg);<br>
 
2704
}</tt></small></td>
 
2705
<td></td><td></td><td></td><td></td>
 
2706
</tr>
 
2707
</table>
 
2708
<p><ul><li>The <tt></tt> puts a backslash before all characters that
 
2709
  are special to Tcl</li></ul><ul><li>The Tcl command becomes:
 
2710
  <pre>
 
2711
    tk_messageBox -icon error -msg \ 
 
2712
        "Syntax error near \"\}\"" -type ok
 
2713
  </pre></li></ul></p>
 
2714
 
 
2715
<br clear="both"><p><hr></p>
 
2716
<h2 align="center">Other Functions Provided By Mktclapp</h2>
 
2717
<p><ul><li><tt>void Et_ResultF(Tcl_Interp*, ...);</tt></li></ul><ul><li><tt>char *Et_DStringAppendF(Tcl_DString*, ...);</tt></li></ul><ul><li><tt>int Et_AppendObjF(Tcl_Obj*, ...);</tt></li></ul><ul><li><tt>char *mprintf(const char *format, ...);<br>
 
2718
  char *vmprintf(const char *format, va_list);</tt></li></ul><ul><li><tt>void Et_NewBuiltinFile(char *filename, char *data, int amt);</tt></li></ul></p>
 
2719
<br clear="both"><p><hr></p>
 
2720
<h2 align="center">Operating Mktclapp From The Command Line</h2>
 
2721
<p><ul><li>Generate the <tt>appinit.h</tt> header file like this:
 
2722
  <blockquote>
 
2723
  <tt>mktclapp -header &gt;appinit.h</tt>
 
2724
  </blockquote></li></ul><ul><li>Generate the <tt>appinit.c</tt> file like this:
 
2725
  <blockquote>
 
2726
  <tt>mktclapp -f appinit.mta >appinit.c</tt>
 
2727
  </blockquote></li></ul><ul><li>The <tt>*.mta</tt> file is just a list of command-line options</li></ul><ul><li>Enter
 
2728
  <blockquote>
 
2729
  <tt>mktclapp -help</tt>
 
2730
  </blockquote>
 
2731
  to get a list of available options</li></ul><ul><li>Look at MTA files generated by xmktclapp.tcl for examples</li></ul></p>
 
2732
<br clear="both"><p><hr></p>
 
2733
<h2 align="center">Format Of An MTA File</h2>
 
2734
<table cellspacing="0" cellpadding="0" border="0">
 
2735
<tr><td valign="center">
 
2736
<small><tt>#&nbsp;Configuration&nbsp;file&nbsp;generated&nbsp;by&nbsp;xmktclapp<br>
 
2737
#&nbsp;Hand&nbsp;editing&nbsp;is&nbsp;not&nbsp;recommended<br>
 
2738
#</tt></small></td>
 
2739
<td>&nbsp;&nbsp;</td>
 
2740
<td valign="center"><img src="image2"></td>
 
2741
<td>&nbsp;&nbsp;</td>
 
2742
<td valign="center">Comments begin with one #</td>
 
2743
</tr>
 
2744
<tr><td valign="center">
 
2745
<small><tt>##&nbsp;Autofork&nbsp;No<br>
 
2746
##&nbsp;CFile:add.c&nbsp;1<br>
 
2747
##&nbsp;CFile:objadd.c&nbsp;1<br>
 
2748
##&nbsp;CmdLine&nbsp;Console<br>
 
2749
##&nbsp;ConfigFile&nbsp;hw.mta<br>
 
2750
##&nbsp;Data:check.gif&nbsp;1<br>
 
2751
##&nbsp;MainScript&nbsp;hw.tcl<br>
 
2752
##&nbsp;Mode&nbsp;Tcl/Tk<br>
 
2753
##&nbsp;NoSource&nbsp;No<br>
 
2754
##&nbsp;OutputFile&nbsp;hw.c<br>
 
2755
##&nbsp;Shroud&nbsp;No<br>
 
2756
##&nbsp;Standalone&nbsp;Yes<br>
 
2757
##&nbsp;TclFile:hw.tcl&nbsp;1<br>
 
2758
##&nbsp;TclLib&nbsp;/usr/lib/tcl8.0<br>
 
2759
##&nbsp;TkLib&nbsp;/usr/lib/tk8.0</tt></small></td>
 
2760
<td>&nbsp;&nbsp;</td>
 
2761
<td valign="center"><img src="image2"></td>
 
2762
<td>&nbsp;&nbsp;</td>
 
2763
<td valign="center">Lines beginning with two #s are used
 
2764
  by xmktclapp.tcl and ignored by mktclapp</td>
 
2765
</tr>
 
2766
<tr><td valign="center">
 
2767
<small><tt>-console<br>
 
2768
-main-script&nbsp;"hw.tcl"<br>
 
2769
-tcl-library&nbsp;"/usr/lib/tcl8.0"<br>
 
2770
-tk-library&nbsp;"/usr/lib/tk8.0"<br>
 
2771
"add.c"<br>
 
2772
"objadd.c"<br>
 
2773
-i&nbsp;"check.gif"<br>
 
2774
-strip-tcl&nbsp;"hw.tcl"</tt></small></td>
 
2775
<td>&nbsp;&nbsp;</td>
 
2776
<td valign="center"><img src="image2"></td>
 
2777
<td>&nbsp;&nbsp;</td>
 
2778
<td valign="center">All other lines are read by mktclapp and
 
2779
  ignored by xmktclapp.tcl</td>
 
2780
</tr>
 
2781
</table>
 
2782
 
 
2783
<br clear="both"><p><hr></p>
 
2784
<h2 align="center">Summary</h2>
 
2785
<p><ul><li>Use Tcl for the things Tcl is good at and use C/C++ for the things that
 
2786
  C/C++ is good at</li></ul><ul><li>Use wrapper programs to make pure Tcl programs standalone</li></ul><ul><li>Use mktclapp to combine Tcl/Tk with C/C++ into a standalone</li></ul></p>
 
2787
<br clear="both"><p><hr></p>