1 <!doctype linuxdoc system>
4 $Id: ir-tcl.sgml,v 1.28 1998-01-30 16:45:58 adam Exp $
8 <title>IrTcl User's Guide and Reference
9 <author><htmlurl url="http://www.indexdata.dk/" name="Index Data">,
10 <tt><htmlurl url="mailto:info@indexdata.dk" name="info@indexdata.dk"></tt>
11 <date>$Revision: 1.28 $
13 This document describes IrTcl -- an information retrieval toolkit for
14 Tcl and Tk that provides access to the Z39.50/SR protocol.
22 This document describes the <sf/IrTcl/ information retrieval toolkit,
23 which offers a high-level, client interface to the Z39.50 and SR protocols.
24 The toolkit is based on the Tcl/Tk toolkit developed by Prof. John
25 K. Ousterhout at the University of California [ref 1].
26 Tcl is a simple, somewhat shell-like, interpreted language. What
27 makes Tcl attractive is that it also offers a C API, which makes
28 extensions to the language possible. The most important Tcl extension is
29 probably Tk -- A Motif look-and-feel interface to the X window
32 To interface the Z39.50/SR protocol <sf/IrTcl/ uses <bf/YAZ/.
33 <bf/YAZ/ offers two transport types: RFC1729/BER on TCP/IP and the mOSI
35 However, the mOSI transport is only an option, and hence it is not
36 needed unless you wish to communicate within an OSI environment.
37 See [ref 2] for more information about the XTI/mOSI implementation.
39 <sf/IrTcl/ is normally implemented as a <it/dynamic/ library (DLL)
40 which is dynamically loaded by using the Tcl command <tt/load/.
41 However, <sf/IrTcl/ can be compiled as a traditional <it/static/
44 <sect>Compilation and installation
47 In order to compile you need:
49 <item> An ANSI C compiler such as GNU C.
50 <item> <htmlurl url="http://sunscript.sun.com/TclTkCore/" name="Tcl">.
51 Version 7.5, 7.6 and 8.0 has been tested.
52 <item> <htmlurl url="http://www.indexdata.dk/yaz/" name="YAZ">
53 version 1.4 or higher.
56 As an option you may want:
58 <item> <htmlurl url="http://sunscript.sun.com/TclTkCore/" name="Tk">.
59 Version 4.1, 4.2 and 8.0 has been tested.
63 Unpack the <sf/IrTcl/ package at the same directory level as <bf/YAZ/.
70 This command tries to configure <sf/IrTcl/ for your system and creates
73 The <tt>configure</tt> command tries to locate the file <tt/tclConfig.sh/
74 which should be generated by Tcl's installation script. Configure
75 looks for your Tcl shell in order to locate this file. For example
76 if <tt/tclsh/ is located in <tt>/home/joe/bin</tt>, configure will
77 assume that <tt>tclConfig.sh</tt> is installed in <tt>/home/joe/lib</tt>,
78 in which case the prefix is <tt>/home/joe</tt>. If you have
79 more than one Tcl version installed on your system, or if configure
80 cannot find the Tcl shell in your path, you can specify the prefix
81 by adding <tt>--prefix=</tt>prefix to the configure command, i.e.
83 $ ./configure --prefix=/home/joe
86 The prefix is also used to determine where <sf/IrTcl/ is installed.
87 The <sf/IrTcl/ executables are installed in prefix/bin and libraries
88 and support files are installed in prefix/irtcl.
90 Compile <sf/IrTcl/ by typing:
95 For Tcl versions that support dynamic libraries the command above
96 will create the shared library, <tt/irtcl.so/, as well as the
97 normal static library, <tt/libirtcl.a/.
99 For Tcl versions that doesn't support dynamic libraries the
100 make command will create two shells will build-in <sf/IrTcl/ support --
101 a Tcl shell called <tt/ir-tcl/ and a Tcl/Tk shell called <tt/ir-tk/.
102 The traditional static library, <tt/libirtcl.a/, is build as well.
104 To install the programs and support files type:
109 If you wish to install man pages type:
114 Summary of files installed (the names refer to the Makefile variables):
117 <tag><tt>irtcl.so</tt></tag> The <sf/IrTcl/ shared dynamic library.
118 The actual name of this library vary. Installed in <tt>IRTCLDIR</tt>.
119 This file is only generated when using newer versions of Tcl.
121 <tag><tt>ir-tk</tt></tag> The <sf/IrTcl/ shell for Tk. This shell
122 is not needed when using a Tk that support for shared libraries is present.
123 Installed in <tt>BINDIR</tt> -- defaults to
124 <tt>/usr/local/bin</tt>. <tt>ir-tk</tt> works like
125 <tt>wish</tt> &mdash without arguments it reads commands from stdin.
126 A source file may be specified by option <tt>-f</tt>. <tt>ir-tk</tt>
127 accept the same set of options as <tt>wish</tt>.
129 <tag><tt>ir-tcl</tt></tag> The <sf/IrTcl/ shell for Tcl. This program
130 is not needed when using a Tcl that supports shared libraries. Installed
131 in <tt>BINDIR</tt> -- defaults to <tt>/usr/local/bin</tt>.
133 <tag><tt>client.tcl</tt></tag> A graphical client for <tt>ir-tk</tt>.
134 The client is installed as an executable script called <tt>irclient</tt> in
135 <tt>BINDIR</tt>. This client needs a number of files, bitmaps, etc.
136 The client looks for the files in the current directory &mdash if
137 this fails it tries to look in the directory <tt>IRTCLDIR</tt>
138 -- defaults to <tt>/usr/local/lib/irtcl</tt>.
140 <tag><tt>libirtcl.a</tt></tag> The <sf/IrTcl/ library.
141 Installed in <tt>LIBDIR</tt> -- defaults to <tt>/usr/local/lib</tt>.
143 <tag><tt>ir-tcl.h</tt></tag> The <sf/IrTcl/ header file.
144 Installed in <tt>INCDIR</tt> -- defaults to <tt>/usr/local/include</tt>.
146 <tag><tt>irtdb.tcl</tt></tag> A setup file with definitions
147 of target and queries. Read and updated by <tt>client.tcl</tt>. Installed
148 in <tt>IRTCLDIR</tt> -- defaults to <tt>/usr/local/lib/irtcl</tt>.
150 <tag><tt>formats/*</tt></tag> Display format files written
151 in Tk. Read by <tt>client.tcl</tt>. Installed
152 in <tt>IRTCLDIR</tt> -- defaults to <tt>/usr/local/lib/irtcl</tt>.
154 <tag><tt>bitmaps/*</tt></tag> Various bitmap files. Read by
155 <tt>client.tcl</tt>. Installed
156 in <tt>IRTCLDIR</tt> -- defaults to <tt>/usr/local/lib/irtcl</tt>.
158 <tag><tt>LICENSE</tt></tag> LICENSE file. Read by
159 <tt>client.tcl</tt>. Installed
160 in <tt>IRTCLDIR</tt> -- defaults to <tt>/usr/local/lib/irtcl</tt>.
166 Basic Tcl is handled by the program <tt/tclsh/. The script
167 must use the <tt/load/ command to load the <sf/IrTcl/ dynamic
168 library. If dynamic libraries are unsupported the <tt/ir-tcl/ program
169 should be used instead, since that program is statically linked
170 with the <sf/IrTcl/ library.
172 So the static, non-dynamic, version goes like this:
177 and the dynamic version goes like:
187 If your Tcl/Tk supports dynamic libraries you can use the
188 <tt/load/ command from within <tt/wish/ as described in the previous
190 If not, you must use the <tt>ir-tk</tt> shell that acts as <tt>wish</tt>
191 except that it includes the <sf/IrTcl/ commands.
193 The enclosed script <tt>client.tcl</tt> is a graphical client
194 which demonstates an example of a user interface for the Z39.50/SR protocols.
195 At first the script was relatively small but it has grown since the
196 beginning. At present it is about 3000 lines.
198 To start the client with dynamic library support use:
203 Note: Substitute the real name for the wish interpreter above, for
204 version 8.0 it is probably called <tt/wish8.0/.
206 To start the client without dynamic library support use:
208 $ ./ir-tk -f client.tcl
211 The client lets up define targets and query types within the interface.
212 Hence, you will not need to modify configation files.
214 Stuff concerning targets can be found in the pull down menu 'Target'
215 with the following options:
217 <tag>Connect</tag> Establishes connection to a target.
218 <tag>Disconnect</tag> Closes a target connection.
219 <tag>About</tag> Shows implementation Id, implementation Version, etc
220 for the current target.
221 <tag>Setup</tag> Pops up a target definition window. You may alter
223 <tag>Setup new</tag> Lets you define a new target.
226 The term query type refers to a collection of search fields. The
227 pull down menu Options|Query deals with queries. You may
228 insert/modify/remove query types.
230 <sect>Overview of the API
233 Basically, <sf/IrTcl/ is a set of commands introduced to Tcl.
234 When extending Tcl there are two approaches: action-oriented commands
235 and object-oriented commands.
237 Action-oriented commands manipulate
238 Tcl variables and each command introduces only one action.
239 The string manipulation commands in Tcl are action oriented.
241 Object-oriented commands are added for every declared
242 variable (object). Object-oriented commands usually provide a set of
243 actions (methods) to manipulate the object.
244 The widgets in Tk (X objects) are examples of the object-oriented style.
246 <sf/IrTcl/ commands are object-oriented. The main reason
247 for this is that the data structures involved in the IR protocol
248 are not easily represented by Tcl data structures.
249 Also, the <sf/IrTcl/ objects tend to exist for a relativly long time.
250 Note that although we use the term object-oriented commands, this
251 does not mean that the programming style is strictly object-oriented. For
252 example, there is such no such thing as inheritance.
254 We are now ready to present the three commands introduced to Tcl by
258 <tag/ir/ The ir object represents a connection to a target. More
259 precisely it describes a Z-association.
260 <tag/ir-set/ The ir-set describes a result set, which is
261 conceptually a collection of records returned by the target.
262 The ir-set object may retrieve records from a target by means of
263 the ir object; it may read/write records from/to a local file or it may be
264 updated with a user-edited record.
265 <tag/ir-scan/ The scan object represents a list of scan lines
266 retrieved from a target.
271 To create a new IR object called <tt/z-assoc/ write:
278 Each object provides a set of <em/settings/ which may either be
279 readable, writeable of both. All settings immediately follow
280 the name of the object. If a value is present the setting
281 is set to <em/value/.
285 We wish to set the preferred-message-size to 18000 on the
289 z-assoc preferredMessageSize 18000
292 To read the current value of preferred-message-size use:
295 z-assoc preferredMessageSize
299 One important category consists of settings is those that relate to the
300 event-driven model. When <sf/IrTcl/ receives responses from the target, i.e.
301 init responses, search responses, etc., a <em/callback/ routine
302 is called. Callback routines are represented in Tcl as
303 a list, which is re-interpreted prior to invocation.
304 The method is similar to the one used in Tk to capture X events.
306 For each SR/Z39.50 request there is a corresponding object action. The most
307 important actions are:
309 <tag/connect/ Establishes connection with a target
310 <tag/init/ Sends an initialize request.
311 <tag/search/ Sends a search request.
312 <tag/present/ Sends a present request.
313 <tag/scan/ Sends a scan request.
318 This example shows a complete connect - init - search - present scenario.
320 First an IR object, called <tt/z/, is created.
321 Also a result set <tt/z.1/ is introduced by the <tt/ir-set/
322 and it is specified that the result set uses <tt/z/ as its association.
324 The setting <tt/databaseNames/ is set to the
325 database <tt/books/ to which the following searches are directed.
326 A callback is then defined and a connection is established to
327 <tt/fake.com/ by the <tt/connect/ action.
328 If the connect succeeds the <tt/connect-response/ is called.
330 In the Tcl procedure, <tt/connect-response/, a callback is defined
331 <em/before/ the init request is executed.
332 The Tcl procedure <tt/init-response/ is called when a
333 init response is returned from the target.
335 The <tt/init-response/ procedure sets up a <tt/search-response/
336 callback handler and sends a search-request by using a query which
337 consists of a single word <tt/science/.
339 When the <tt/search-response/ procedure is called it defines
340 a variable <tt/hits/ and sets it to the value of the setting
341 <tt/resultCount/. If <tt/hits/ is positive a present-request is
342 sent -- asking for 5 records from position 1.
344 Finally, a present response is received and the number of records
345 returned is stored in the variable <tt/ret/.
349 z databaseNames books
351 z callback {connect-response}
354 proc connect-response {} {
355 z callback {init-response}
359 proc init-response {} {
360 z callback {search-response}
364 proc search-response {} {
365 set hits [z.1 resultCount]
368 z callback {present-response}
373 proc present-response {} {
374 set ret [z.1 numberOfRecordsReturned]
375 puts "$ret records returned"
380 The previous example program doesn't care about error conditions.
381 If errors occur in the program they will be trapped by the Tcl error
382 handler. This is not always appropriate. However, Tcl offers a
383 <tt/catch/ command to support error handling by the program itself.
388 The ir object describes an association with a target.
389 This section covers the connect-init-disconnect actions provided
391 An ir object is created by the <tt/ir/ command and the
392 created object enters a 'not connected' state, because it isn't
393 connected to a target yet.
398 A connection is established by the <tt/connect/ action which is
399 immediately followed by a hostname. A number of settings affect the
400 <tt/connect/ action. Obviously, these settings should be set
401 <bf/before/ connecting. The settings are:
404 <tag><tt>comstack </tt><tt>mosi|tcpip</tt></tag>
406 <tag><tt>protocol </tt><tt>Z39|SR</tt></tag>
407 Protocol type - ANSI/NISO Z39.50 or ISO SR.
408 <tag><tt>callback </tt><em>list</em></tag>
409 Tcl script called when the connection is established.
410 <tag><tt>failback </tt><em>list</em></tag>
411 Fatal error Tcl script. Called on protocol errors or if target
415 If the connect is unsuccessful either the connect action itself
416 will return an error code or the failback handler is invoked.
418 In general, the <tt>failback</tt> handler is invoked when serious
419 unrecoverable errors occur when communicating with the target.
420 In this case the <sf/IrTcl/ system shuts down the connection.
421 The <tt>failback</tt> handler might inspect the <tt>failInfo</tt>
422 setting to determine the cause of the failure; it returns
423 two elements. The first is an error integer; the second is an
424 english representation of the error. The error codes and
425 the corresponding messages are:
428 <tag><tt>0</tt></tag>ok
429 <tag><tt>1</tt></tag>connect failed
430 <tag><tt>2</tt></tag>connection closed
431 <tag><tt>3</tt></tag>connection closed
432 <tag><tt>4</tt></tag>failed to decode incoming APDU
433 <tag><tt>5</tt></tag>unknown APDU
436 Note: in case 3 the connection was closed during read a read operation
437 whereas in case 4 it was closed during a write operation.
442 If the connect operation succeeds the <tt/init/ action should be used.
443 The init related settings are:
446 <tag><tt>preferredMessageSize </tt><em>integer</em></tag>
447 Preferred-message-size. Default value is 30000.
448 <tag><tt>maximumRecordSize </tt><em>integer</em></tag>
449 Maximum-record-size. Default value is 30000.
450 <tag><tt>idAuthentication </tt><em>string</em> ...</tag>
451 Id-authentication. There are three forms. If any empty is
452 given, the Id-authentication is not used. If one non-empty string
453 is given, the 'open' authentication is used. If three strings are
454 specified, the version 'id-pass' authentication (version 3 only)
455 is used in which case the first string is groupId; the second string
456 is userId and the third string is password.
457 <tag><tt>implementationName </tt><em>string</em></tag>
458 Implementation-name of origin system.
459 <tag><tt>implementationId</tt></tag>
460 Implementation-id of origin system. This setting is read-only.
461 <tag><tt>implementationVersion</tt></tag>
462 Implementation-version of origin system. This settings is read-only.
463 <tag><tt>options </tt><em>list</em></tag>
464 Options to be negotiated in the init service. The list contains
465 the options that are set. Possible values are <tt>search</tt>,
466 <tt>present</tt>, <tt>delSet</tt>, <tt>resourceReport</tt>,
467 <tt>triggerResourceCtrl</tt>, <tt>resourceCtrl</tt>,
468 <tt>accessCtrl</tt>, <tt>scan</tt>, <tt>sort</tt>,
469 <tt>extendedServices</tt>, <tt>level-1Segmentation</tt>,
470 <tt>level-2Segmentation</tt>, <tt>concurrentOperations</tt> and
471 <tt>namedResultSets</tt>. Currently the default options are:
472 <tt>search</tt>, <tt>present</tt>, <tt>scan</tt> and
473 <tt>namedResultSets</tt>. The <tt>options</tt> setting is set to its default
474 value when an ir object is created and when a <tt>disconnect</tt>
476 <tag><tt>protocolVersion </tt><em>integer</em></tag>
477 Protocol version: 2, 3, etc. Default is 2.
478 <tag><tt>referenceId </tt><em>string</em></tag>
479 Reference-id of init operation. If <em>string</em> is empty no
480 reference-id is used.
481 <tag><tt>initResponse </tt><em>list</em></tag>
482 Init-response Tcl script.
483 <tag><tt>callback </tt><em>list</em></tag>
484 General response Tcl script. Only used if <tt>initResponse</tt>
488 The init-response handler should inspect some of the settings shown
492 <tag><tt>initResult </tt>returns <em>boolean</em></tag>
493 Init response status. True if init operation was successful;
495 <tag><tt>preferredMessageSize </tt>returns <em>integer</em></tag>
496 Preferred-message-size after negotiation.
497 <tag><tt>maximumRecordSize </tt>returns <em>integer</em></tag>
498 Maximum-record-size after negotiation.
499 <tag><tt>targetImplementationName </tt>returns <em>string</em></tag>
500 Implementation-name of target system.
501 <tag><tt>targetImplementationId </tt>returns <em>string</em></tag>
502 Implementation-id of target system.
503 <tag><tt>targetImplementationVersion </tt>returns <em>string</em></tag>
504 Implementation-version of target system.
505 <tag><tt>options </tt>returns <em>list</em></tag>
506 Options after negotiation. The list contains the options that are set.
507 <tag><tt>protocolVersion </tt>returns <em>integer</em></tag>
508 Protocol version: 2, 3, etc after negotiation.
509 <tag><tt>userInformationField </tt>returns <em>string</em></tag>
510 User information field.
511 <tag><tt>referenceId </tt>returns <em>string</em></tag>
512 Reference-id of init response.
517 Consider a client with the ability to access multiple targets.
519 We define a list of targets that we wish to connect to.
520 Each item in the list describes the target parameters with
521 the following four components: association-name, comstack-type,
522 protocol-type and a hostname.
524 The list for the two targets: ISO/SR target DANBIB and TCP/Z39.50
525 target Data Research, will be defined as:
527 set targetList { {danbib mosi SR 0103/find2.denet.dk:4500}
528 {drs tcpip Z39 dranet.dra.com} }
531 The Tcl code below defines, connect and initialize the
532 targets in <tt/targetList/:
535 foreach target $targetList {
536 set assoc [lindex $target 0]
538 $assoc comstack [lindex $target 1]
539 $assoc protocol [lindex $target 2]
540 $assoc failback [list fail-response $assoc]
541 $assoc callback [list connect-response $assoc]
542 $assoc connect [lindex $target 3]
545 proc connect-response {assoc} {
546 $assoc callback [list init-response $assoc]
550 proc fail-response {assoc} {
551 puts "$assoc closed connection or protocol error"
554 proc init-response {assoc} {
555 if {[$assoc initResult]} {
556 puts "$assoc initialized ok"
558 puts "$assoc didn't initialize"
563 <tt/target/ is bound to each item in the list of targets.
564 The <tt/assoc/ is set to the ir object name.
565 Then, the comstack, protocol and failback are set for the <tt/assoc/ object.
566 The ir object name is argument to the <tt/fail-response/ and
567 <tt/connect-response/ routines.
568 Note the use of the Tcl <tt/list/ command which
569 is necessary here because the argument contains variables
570 (<tt/assoc/) that should be substituted before the handler is defined.
571 After the connect operation, the <tt/init-response/ handler
572 is defined in much the same way as the failback handler.
573 And, finally, an init request is executed.
580 To terminate the connection the <tt/disconnect/ action should be used.
581 This action has no parameters.
582 Another connection may be established by a new <tt/connect/ action on
588 This section covers the queries used by <sf/IrTcl/, and how searches and
589 presents are handled.
591 A search operation and a result set is described by the ir set object.
592 The ir set object is defined by the <tt/ir-set/ command which
593 has two parameters. The first is the name of the new ir set object, and
594 the second, which is optional, is the name of an assocation -- an ir
595 object. The second argument is required if the ir set object should be able
596 to perform searches and presents. However, it is not required if
597 only ``local'' operations is done with the ir set object.
599 When the ir set object is created a number of settings are inherited
600 from the ir object, such as the selected databass, query type,
601 etc. Thus, the ir object contains what we could call default
607 Search requests are sent by the <tt/search/ action which
608 takes a query as parameter. There are two types of queries,
609 RPN and CCL, controlled by the setting <tt/queryType/.
610 A string representation for the query is used in <sf/IrTcl/ since
611 Tcl has reasonably powerful string manipulaton capabilities.
612 The RPN query used in <sf/IrTcl/ is the prefix query notation also used in
613 the <bf/YAZ/ test client.
615 The CCL query is an uninterpreted octet-string which is parsed by the target.
616 We refer to the standard: ISO 8777. Note that only a few targets
617 actually support the CCL query and the interpretation of
618 the standard may vary.
620 The prefix query notation (which is converted to RPN) offer a few
624 <tag><tt>@attr </tt><em>list op</em></tag>
625 The attributes in list are applied to op
626 <tag><tt>@and </tt><em>op1 op2</em></tag>
627 Boolean <em/and/ on op1 and op2
628 <tag><tt>@or </tt><em>op1 op2</em></tag>
629 Boolean <em/or/ on op1 and op2
630 <tag><tt>@not </tt><em>op1 op2</em></tag>
631 Boolean <em/not/ on op1 and op2
632 <tag><tt>@prox </tt><em>list op1 op2</em></tag>
633 Proximity operation on op1 and op2. Not implemented yet.
634 <tag><tt>@set </tt><em>name</em></tag>
636 <tag><tt>@attrset </tt><em>set</em></tag>
637 Whole query uses the specified attribute <em>set</em>. If this operator is
638 used it must be defined at the beginning of the query.
641 It is simple to build RPN queries in <sf/IrTcl/. Search terms
642 are sequences of characters, as in:
647 Boolean operators use the prefix notation (instead of the suffix/RPN),
650 @and science technology
653 Search terms may be associated with attributes. These
654 attributes are indicated by the <tt/@attr/ operator.
655 Assuming the bib-1 attribute set, we can set the use-attribute
656 (type is 1) to title (value is 4):
662 Also, it is possible to apply attributes to a range of search terms.
663 In the query below, both search terms have use=title but the <tt/tech/
664 term is right truncated:
667 @attr 1=4 @and @attr 5=1 tech beta
670 To search for the DatabaseInfo records from an Explain server, we
673 @attrset exp1 @attr 1=1 DatabaseInfo
679 The settings that affect the search are listed below:
682 <tag><tt>databaseNames </tt><em>list</em></tag>
684 <tag><tt>smallSetUpperBound </tt><em>integer</em></tag>
685 Small set upper bound. Default 0.
686 <tag><tt>largeSetLowerBound </tt><em>integer</em></tag>
687 Large set lower bound. Default 2.
688 <tag><tt>mediumSetPresentNumber </tt><em>integer</em></tag>
689 Medium set present number. Default 0.
690 <tag><tt>replaceIndicator </tt><em>boolean</em></tag>
691 Replace-indicator. Default true (1).
692 <tag><tt>setName </tt><em>string</em></tag>
693 Name of result set. Default name of set is <tt/default/.
694 <tag><tt>queryType rpn|ccl</tt></tag>
695 Query type-1 or query type-2. Default rpn (type-1).
696 <tag><tt>preferredRecordSyntax </tt><em>string</em></tag>
697 Preferred record syntax -- UNIMARC, USMARC, etc.
698 <tag><tt>smallSetElementSetNames </tt><em>string</em></tag>
699 small-set-element-set names. If <em>string</em> is empty
700 the element set is not set. Default is empty (not set).
701 <tag><tt>mediumSetElementSetNames </tt><em>string</em></tag>
702 medium-set-element-set names. If <em>string</em> is empty
703 the element set is not set. Default is empty (not set).
704 <tag><tt>nextResultSetPosition </tt>returns <em>integer</em></tag>
705 Next result set position.
706 <tag><tt>referenceId </tt><em>string</em></tag>
707 Reference-id. If <em>string</em> is empty no reference-id is used.
708 <tag><tt>searchResponse </tt><em>list</em></tag>
709 Search-response Tcl script.
710 <tag><tt>callback </tt><em>list</em></tag>
711 General response Tcl script. Only used if searchResponse is not specified.
712 This setting is valid only for the <tt/ir/ object -- not the
716 Setting the <tt/databaseNames/ is mandatory. All other settings
717 have reasonable defaults.
718 The search-response handler, specified by the <tt/callback/ - or
719 the <tt/searchResponse/ setting,
720 should read some of the settings shown below:
723 <tag><tt>searchStatus</tt> returns <em>boolean</em></tag>
724 Search-status. True if search operation was successful; false
726 <tag><tt>responseStatus </tt>returns <em>list</em></tag>
727 Response status information.
728 <tag><tt>resultCount </tt>returns <em>integer</em></tag>
730 <tag><tt>numberOfRecordsReturned </tt>returns <em>integer</em></tag>
731 Number of records returned.
732 <tag><tt>referenceId </tt>returns <em>string</em></tag>
733 Reference-id of search response.
736 The <tt/responseStatus/ signals one of three conditions which
737 is indicated by the value of the first item in the list:
740 <tag><tt>NSD</tt></tag> indicates that the target has returned one or
741 more non-surrogate diagnostic messages. The <tt/NSD/ item is followed by
742 a list with all non-surrogate messages. Each non-surrogate message consists
743 of three items. The first item of the three items is the error
744 code (integer); the next item is a textual representation of the error
745 code in plain english; the third item is additional information, possibly
746 empty if no additional information was returned by the target.
748 <tag><tt>DBOSD</tt></tag> indicates a successful operation where the
749 target has returned one or more records. Each record may be
750 either a database record or a surrogate diagnostic.
752 <tag><tt>OK</tt></tag> indicates a successful operation -- no records are
753 returned from the target.
758 We continue with the multiple-targets example.
759 The <tt/init-response/ procedure will attempt to make searches:
762 proc init-response {assoc} {
763 puts "$assoc connected"
764 ir-set ${assoc}.1 $assoc
765 $assoc.1 queryType rpn
766 $assoc.1 databaseNames base-a base-b
767 $assoc callback [list search-response $assoc ${assoc}.1]
768 $assoc.1 search "@attr 1=4 @and @attr 5=1 tech beta"
772 An ir set object is defined and the
773 ir object is told about the name of ir object.
774 The ir set object use the name of the ir object as prefix.
776 Then, the query-type is defined to be RPN, i.e. we will
777 use the prefix query notation later on.
779 Two databases, <tt/base-a/ and <tt/base-b/, are selected.
781 A <tt/search-response/ handler is defined with the
782 ir object and the ir-set object as parameters and
783 the search is executed.
785 The first part of the <tt/search-response/ looks like:
787 proc search-response {assoc rset} {
788 set status [$rset responseStatus]
789 set type [lindex $status 0]
790 if {$type == "NSD"} {
791 set code [lindex $status 1]
792 set msg [lindex $status 2]
793 set addinfo [lindex $status 3]
794 puts "NSD $code: $msg: $addinfo"
797 set hits [$rset resultCount]
798 if {$type == "DBOSD"} {
799 set ret [$rset numberOfRecordsReturned]
804 The response status is stored in variable <tt/status/ and
805 the first element indicates the condition.
806 If non-surrogate diagnostics are returned they are displayed.
807 Otherwise, the search was a success and the number of hits
808 is read. Finally, it is tested whether the search response
809 returned records (database or diagnostic).
811 Note that we actually didn't inspect the search status (setting
812 <tt/searchStatus/) to determine whether the search was successful or not,
813 because the standard specifies that one or more non-surrogate
814 diagnostics should be returned by the target in case of errors.
818 If one or more records are returned from the target they
819 will be stored in the result set object.
820 In the case in which the search response contains records, it is
821 very similar to the present response case. Therefore, some settings
822 are common to both situations.
827 The <tt/present/ action sends a present request. The <tt/present/ is
828 followed by two optional integers. The first integer is the
829 result-set starting position -- defaults to 1. The second integer
830 is the number of records requested -- defaults to 10.
831 The settings which could be modified before a <tt/present/
835 <tag><tt>preferredRecordSyntax </tt><em>string</em></tag>
836 preferred record syntax -- UNIMARC, USMARC, etc.
837 <tag><tt>elementSetNames </tt><em>string</em></tag>
838 Element-set names. If <em>string</em> is empty
839 the element set is not set. Default is empty (not set).
840 <tag><tt>referenceId </tt><em>string</em></tag>
841 Reference-id. If <em>string</em> is empty no reference-id is used.
842 <tag><tt>presentResponse </tt><em>list</em></tag>
843 Present-response Tcl script.
844 <tag><tt>callback </tt><em>list</em></tag>
845 General response Tcl script. Only used if presentResponse is not specified
846 This setting is valid only for the <tt/ir/ object -- not the
850 The present-response handler should inspect the settings
851 shown in table below.
852 Note that <tt/responseStatus/ and <tt/numberOfRecordsReturned/
853 settings were also used in the search-response case.
855 As in the search response case, records returned from the
856 target are stored in the result set object.
859 <tag><tt>presentStatus </tt>returns <em>boolean</em></tag>
861 <tag><tt>responseStatus </tt>returns <em>list</em></tag>
862 Response status information.
863 <tag><tt>numberOfRecordsReturned </tt>returns <em>integer</em></tag>
864 Number of records returned.
865 <tag><tt>nextResultSetPosition </tt>returns <em>integer</em></tag>
866 Next result set position.
867 <tag><tt>referenceId </tt>returns <em>string</em></tag>
868 Reference-id of present response.
874 Search responses and present responses may result in
875 one or more records stored in the ir set object if
876 the <tt/responseStatus/ setting indicates database or
877 surrogate diagnostics (<tt/DBOSD/). The individual
878 records, indexed by an integer position offset, should then be
881 If element set names have been specified either in the
882 search requests (<tt>smallSetElementSetNames</tt> /
883 <tt>mediumSetElementSetNames</tt>) or present requests
884 (<tt>elementSetNames</tt>) the individual records in the
885 ir set object are assigned appropriate element set ids.
886 In this mode records at a given position are treated different as
887 long as they have difference element set ids.
888 To inspect records with a particular element set id in subsequent
889 operations use the <tt>recordElements</tt> setting followed by the id.
890 If you have more than one record at a given position and you do not
891 use <tt>recordElements</tt> the record selected at the given position
894 The action <tt>type</tt> followed by an integer returns information
895 about a given position in an ir set. There are three possiblities:
898 <tag><tt/SD/</tag> The item is a surrogate diagnostic record.
899 <tag><em/empty/</tag> There is no record at the specified position.
900 <tag><tt/DB/</tag> The item is a database record.
903 To handle the first case, surrogate diagnostic record, the
904 <tt/Diag/ action should be used. It returns three
905 items: error code (integer), text representation in plain english
906 (string), and additional information (string, possibly empty).
908 In the second case, no record, note that there still might
909 be a record at the position but with an id that differs from that
910 specified by <tt>recordElements</tt>.
912 In the third case, database record, the <tt/recordType/ action should
913 be used. It returns the record type at the given position.
914 Some record types are:
931 We continue our search-response example. In the case,
932 <tt/DBOSD/, we should inspect the result set items.
933 Recall that the ir set name was passed to the
934 search-response handler as argument <tt/rset/.
937 if {$type == "DBOSD"} {
938 set ret [$rset numberOfRecordsReturned]
939 for {set i 1} {$i<=$ret} {incr i} {
940 set itype [$rset type $i]
941 if {$itype == "SD"} {
942 set diag [$rset Diag $i]
943 set code [lindex $diag 0]
944 set msg [lindex $diag 1]
945 set addinfo [lindex $diag 2]
946 puts "$i: NSD $code: $msg: $addinfo"
947 } elseif {$itype == "DB"} {
948 set rtype [$rset recordType $i]
949 puts "$i: type is $rtype"
954 Each item in the result set is examined.
955 If an item is a diagnostic message it is displayed; otherwise
956 if it's a database record its type is displayed.
963 In the case, where there is a MARC record at a given position we
964 want to display it somehow. The action <tt/getMarc/ is what we need.
965 The <tt/getMarc/ is followed by a position integer and the type of
966 extraction we want to make: <tt/field/ or <tt/line/.
968 The <tt/field/ and <tt/line/ type are followed by three
969 parameters that serve as extraction masks.
970 They are called tag, indicator and field.
971 If the mask matches a tag/indicator/field of a record the information
972 is extracted. Two characters have special meaning in masks: the
973 dot (any character) and star (any number of any character).
975 The <tt/field/ type returns one or more lists of field information
976 that matches the mask specification. Only the content of fields
979 The <tt/line/ type, on the other hand, returns a Tcl list that
980 completely describe the layout of the MARC record -- including
983 The <tt/field/ type is sufficient and efficient in the case, where only a
984 small number of fields are extracted, and in the case where no
985 further processing (in Tcl) is necessary.
987 However, if the MARC record is to be edited or altered in any way, the
988 <tt/line/ extraction is more powerful -- only limited by the Tcl
993 Consider the record below:
998 008 910710c19910701nju 00010 eng
1002 100 10 $a Jack Collins
1003 245 10 $a How to program a computer
1009 Assuming this record is at position 1 in ir-set <tt/z.1/, we
1010 might extract the title-field (245 * a), with the following command:
1012 z.1 getMarc 1 field 245 * a
1017 {How to program a computer}
1020 Using the <tt/line/ instead of <tt/field/ gives:
1022 {245 {10} {{a {How to program a computer}} }}
1025 If we wish to extract the whole record as a list, we use:
1027 z.1 getMarc 1 line * * *
1032 {001 {} {{{} { 11224466 }} }}
1033 {003 {} {{{} DLC} }}
1034 {005 {} {{{} 00000000000000.0} }}
1035 {008 {} {{{} {910710c19910701nju 00010 eng }} }}
1036 {010 { } {{a { 11224466 }} }}
1037 {040 { } {{a DLC} {c DLC} }}
1038 {050 {00} {{a 123-xyz} }}
1039 {100 {10} {{a {Jack Collins}} }}
1040 {245 {10} {{a {How to program a computer}} }}
1041 {260 {1 } {{a Penguin} }}
1042 {263 { } {{a 8710} }}
1043 {300 { } {{a {p. cm.}} }}
1050 This example demonstrates how Tcl can be used to examine
1051 a MARC record in the list notation.
1053 The procedure <tt/extract-format/ makes an extraction of
1054 fields in a MARC record based on a number of masks.
1055 There are 5 parameters, <tt/r/: a
1056 record in list notation, <tt/tag/: regular expression to
1057 match the record tags, <tt/ind/: regular expression to
1058 match indicators, <tt/field/: regular expression to
1059 match fields, and finally <tt/text/: regular expression to
1060 match the content of a field.
1063 proc extract-format {r tag ind field text} {
1065 if {[regexp $tag [lindex $line 0]] && \
1066 [regexp $ind [lindex $line 1]]} {
1067 foreach f [lindex $line 2] {
1068 if {[regexp $field [lindex $f 0]]} {
1069 if {[regexp $text [lindex $f 1]]} {
1079 To match <tt/comput/ followed by any number of character(s) in the
1080 245 fields in the record from the previous example, we could use:
1082 set r [z.1 getMarc 1 line * * *]
1084 extract-format $r 245 .. . comput
1088 How to program a computer
1093 The <tt/putMarc/ action does the opposite of <tt/getMarc/. It
1094 copies a record in Tcl list notation to a ir set object and is
1095 needed if a result-set must be updated by a Tcl modified (user-edited)
1101 In <sf/IrTcl/ a SUTRS record is treated as one single string. To retrieve
1102 a SUTRS record use the <tt>getSutrs</tt> followed by an index.
1106 A GRS-1 record in <sf/IrTcl/ is represented as a list of elements.
1107 Each element specifies a tag as well as data. The data may
1108 be a subtree, which is represented as a list, and so on.
1110 The method <tt/getGrs/ is followed by a record index and
1111 optional specifiers that selects a specific sub-tree. Each element
1112 consists of 5 elements:
1115 <tag>tag-set</tag> Tag set number.
1117 <tag>value-type</tag> Type of tag value. May be either
1118 <tt/numeric/ of <tt/string/.
1120 <tag>value</tag> The value it self.
1122 <tag>data-type</tag> May be either <tt/octets/, <tt/numeric/,
1123 <tt/ext/, <tt/string/, <tt/bool/, <tt/intUnit/, <tt/empty/,
1124 <tt/notRequested/, <tt/diagnostic/ or <tt/subtree/.
1126 <tag>data</tag>The data associated with element of given type as
1127 indicated before. If data-type is <tt/numeric/ or <tt/string/
1128 then data is encoded as a single Tcl token. The data-type <tt/bool/
1129 is encoded as 0 or 1 for false and true respectively. If the
1130 data-type is <tt/subtree/ the data is a sub-list.
1131 In all other cases, the data is the empty string.
1136 Consider the GRS-1 record below as shown by the <bf/YAZ/ client program:
1139 (1,1) OID: GILS-schema
1141 (2,1) UTAH EARTHQUAKE EPICENTERS
1142 class=4,type=1,value=us
1143 (4,52) UTAH GEOLOGICAL AND MINERAL SURVEY
1144 (3,Local-Subject-Index) APPALACHIAN VALLEY; EARTHQUAKE; EPICENTER
1146 (1,19) Five files of epicenter data arranged by ...
1147 (3,Format) DIGITAL DATA SETS
1148 (3,Data-Category) TERRESTRIAL
1149 (3,Comments) Data are supplied by the University of Utah ...
1152 (2,10) UTAH GEOLOGICAL AND MINERAL SURVEY
1153 (4,2) 606 BLACK HAWK WAY
1154 (4,3) SALT LAKE CITY
1158 (2,14) (801) 581-6831
1159 (4,7) UTAH EARTHQUAKE EPICENTERS
1164 The record may be fetched from the result set, <tt/z.1/, at position 1
1171 { 1 numeric 1 oid 1.2.840.10003.13.2 }
1172 { 1 numeric 14 string 2 }
1173 { 2 numeric 1 string
1174 { UTAH EARTHQUAKE EPICENTERS} }
1175 { 4 numeric 52 string {UTAH GEOLOGICAL AND MINERAL SURVEY} }
1176 { 3 string Local-Subject-Index string
1177 {APPALACHIAN VALLEY; EARTHQUAKE; EPICENTER} }
1178 { 2 numeric 6 subtree
1179 { { 1 numeric 19 string
1180 {Five files of epicenter data arranged by ...} }
1181 { 3 string Format string {DIGITAL DATA SETS} }
1182 { 3 string Data-Category string TERRESTRIAL }
1183 { 3 string Comments string
1184 {Data are supplied by the University of Utah ...} } } }
1185 { 4 numeric 70 subtree
1186 { { 4 numeric 90 subtree
1187 { { 2 numeric 10 string
1188 {UTAH GEOLOGICAL AND MINERAL SURVEY} }
1189 { 4 numeric 2 string {606 BLACK HAWK WAY} }
1190 { 4 numeric 3 string {SALT LAKE CITY} }
1191 { 3 string State string UT }
1192 { 3 string Zip-Code string 84108 }
1193 { 2 numeric 16 string USA }
1194 { 2 numeric 14 string {(801) 581-6831} } } }
1195 { 4 numeric 7 string {UTAH EARTHQUAKE EPICENTERS} } } }
1196 { 4 numeric 1 string ESDD0006 }
1197 { 1 numeric 16 string 198903 }
1200 We can choose only to get the path (2,6) by using:
1207 { 2 numeric 6 subtree { { 1 numeric 19 string
1208 {Five files of epicenter data arranged by ...} }
1209 { 3 string Format string {DIGITAL DATA SETS} }
1210 { 3 string Data-Category string TERRESTRIAL }
1212 string {Data are supplied by the University of Utah ...} } } }
1215 To get the well known (1,19) within the subject (2,6) we use
1217 z.1 getGrs 1 (2,6) (1,19)
1221 { 2 numeric 6 subtree
1222 { { 1 numeric 19 string
1223 {Five files of epicenter data arranged by ...} } } }
1229 Explain records are retrieved like other records. The method,
1230 <tt>getExplain</tt> is followed by an index and and an optional
1231 Explain record pattern.
1233 The returned record is a canonical representation of the Explain record.
1234 An ASN.1 sequence is represented as a list. Each item in the list
1235 consists of the name of the element, followed by its value if the value
1238 The optional pattern that follows the index after <tt>getExplain</tt>
1239 consists of one or more elements, that is matched against the elements
1240 of the actual record.
1244 One of the few targets that support explain is the ATT research server
1245 at <tt>z3950.research.att.com</tt>.
1247 The targetInfo record was returned by the target and it's stored in
1248 position 1 in the result set, <tt>z.1</tt>. To retrieve the whole
1254 and we get in return
1257 {targetInfo commonInfo {name {Lucent Technologies Research Server}}
1258 recentNews icon {namedResultSets 1} {multipleDBsearch 0}
1259 {maxResultSets 100} {maxResultSize 600000} maxTerms timeoutInterval
1260 {welcomeMessage {strings { {language eng}
1262 {Salutations - this is Lucent Technologies experimental Z39.50 server.
1263 No guarentees, but free and unlimited access!}} } } }
1264 {contactInfo {name {Robert Waldstein}} {description {strings
1266 {text {Librarian system designer - no legal anythings}} } } }
1267 {address {strings { {language eng} {text {Room 3D-591
1270 N.J. USA 07974}} } } } {email wald@lucent.com} {phone {908 582-6171}} }
1271 description nicknames {usageRest {strings { {language eng}
1272 {text {None - as long as nonProfit research}} } } } paymentAddr
1273 {hours {strings { {language eng} {text {Should never be down}} } } }
1274 dbCombinations addresses commonAccessInfo }
1277 The <tt>targetInfo</tt> above indicates the the record is really a
1278 <tt>targetInfo</tt> record. The <tt>commonInfo</tt>, which is optional, is
1279 not supplied by this server. The <tt>name</tt>, however is supplied,
1280 with the value <tt>Lucent Technologies Research Server</tt>.
1282 To retrieve the <tt>contactInfo</tt> from the record above we can
1283 extract the element from the record by using Tcl's list manipulation
1284 facilities, for example by doing
1286 set ti [z.1 getExplain 1]
1287 lindex [lindex $ti 0] 12
1291 contactInfo {name {Robert Waldstein}} {description {strings
1293 {text {Librarian system designer - no legal anythings}} }
1294 } } {address {strings { {language eng} {text {Room 3D-591
1297 N.J. USA 07974}} } } } {email wald@lucent.com} {phone {908 582-6171}}
1300 We can also extract almost the same by doing
1302 z.1 getExplain 1 targetInfo contactInfo
1306 {name {Robert Waldstein}} {description {strings { {language eng}
1307 {text {Librarian system designer - no legal anythings}} } } }
1308 {address {strings { {language eng} {text {Room 3D-591
1311 N.J. USA 07974}} } } } {email wald@lucent.com} {phone {908 582-6171}}
1319 To perform scan, a scan object must be created by the <tt>ir-scan</tt>
1320 command. This command has two arguments -- name of the scan object and
1321 name of the ir object. Basically, the scan object, provides one <tt>scan</tt>
1322 action which sends a scan request to the target. The <tt>action</tt>
1323 is followed by a string describing starting point of the term list. The
1324 format used is a simple subset of the query used in search requests. Only
1325 <tt>@attr</tt> specifications and simple terms are allowed.
1326 The settings that affect the scan are:
1329 <tag><tt>stepSize </tt><em>integer</em></tag>
1330 Step size. Default is 0.
1331 <tag><tt>numberOfTermsRequested </tt><em>integer</em></tag>
1332 Number of terms requested. Default is 20.
1333 <tag><tt>preferredPositionInResponse </tt><em>integer</em></tag>
1334 Preferred position in response. Default is 1.
1335 <tag><tt>databaseNames </tt><em>list</em></tag>
1336 Database names. Note that this setting is not (yet) supported for
1337 the scan object. You must set this for the ir object instead.
1338 <tag><tt>referenceId </tt><em>string</em></tag>
1339 Reference-id. If <em>string</em> is empty no reference-id is used.
1340 <tag><tt>scanResponse </tt><em>list</em></tag>
1341 Scan-response Tcl script.
1342 <tag><tt>callback </tt><em>list</em></tag>
1343 General response Tcl script. Only used if <tt>scanResponse</tt>
1345 This setting is valid only for the <tt/ir/ object -- not the
1349 The scan object normally holds one or more scan line entries upon
1350 successful completion. The table below summarizes the settings
1351 that should be used in a response handler.
1354 <tag><tt>scanStatus </tt>returns <em>integer</em></tag>
1355 Scan status. An integer between 0 and 6.
1356 <tag><tt>numberOfTermsReturned </tt>returns <em>integer</em></tag>
1357 Number of terms returned.
1358 <tag><tt>positionOfTerm </tt>returns <em>integer</em></tag>
1359 An integer describing the position of term.
1360 <tag><tt>scanLine </tt>returns <em>list</em></tag>
1361 This function returns information about a given scan line (entry) at a given
1362 index specified by the integer. The first scan line is numbered zero;
1363 the second 1 and so on. A list is returned by the <tt>scanLine</tt>
1364 setting. The first element is <tt>T</tt> if the scan line
1365 is a normal term and <tt>SD</tt> if the scan line is a surrogate
1366 diagnostic. In the first case (normal) the scan term is second element
1367 in the list and the number of occurences is the third element.
1368 In the other case (surrogate diagnostic), the second element
1369 is the diagnostic code, the third a text representation of the error
1370 code and the fourth element is additional information.
1371 <tag><tt>referenceId </tt>returns <em>string</em></tag>
1372 Reference-id of scan response.
1377 We will scan for the terms after <tt>science</tt> in the Title index.
1378 We will assume that an ir object called <tt>z-assoc</tt> has already
1382 z-assoc callback {scan-response}
1383 ir-scan z-scan z-assoc
1384 z-scan scan "@attr 1=4 science"
1386 proc scan-response {} {
1387 set status [z-scan status]
1389 set no [z-scan numberOfTermsReturned]
1390 for {set i 0} {$i < $no} {incr i} {
1391 set line [z-scan scanLine $i]
1392 set type [lindex $line 0]
1394 puts [lindex $line 1]
1395 } elseif {$type == "SD"} {
1396 puts [lindex $line 1]
1407 Copyright © 1995-1998, Index Data.
1409 Permission to use, copy, modify, distribute, and sell this software and
1410 its documentation, in whole or in part, for any purpose, is hereby granted,
1413 1. This copyright and permission notice appear in all copies of the
1414 software and its documentation. Notices of copyright or attribution
1415 which appear at the beginning of any file must remain unchanged.
1417 2. The names of Index Data or the individual authors may not be used to
1418 endorse or promote products derived from this software without specific
1419 prior written permission.
1421 THIS SOFTWARE IS PROVIDED "AS IS" AND WITHOUT WARRANTY OF ANY KIND,
1422 EXPRESS, IMPLIED, OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY
1423 WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.
1424 IN NO EVENT SHALL INDEX DATA BE LIABLE FOR ANY SPECIAL, INCIDENTAL,
1425 INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY KIND, OR ANY DAMAGES
1426 WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER OR
1427 NOT ADVISED OF THE POSSIBILITY OF DAMAGE, AND ON ANY THEORY OF
1428 LIABILITY, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
1431 <sect>About Index Data
1434 Index Data is a consulting and software-development enterprise that
1435 specialises in library and information management systems. Our
1436 interests and expertise span a broad range of related fields, and one
1437 of our primary, long-term objectives is the development of a powerful
1438 information management
1439 system with open network interfaces and hypermedia capabilities.
1441 We make this software available free of charge, on a fairly unrestrictive
1442 license; as a service to the networking community, and to further the
1443 development of quality software for open network communication.
1445 We'll be happy to answer questions about the software, and about ourselves
1456 Phone: +45 3536 3672
1458 Email: info@indexdata.dk
1466 <tag>1 IrTcl Homepage</tag>
1467 <htmlurl url="http://www.indexdata.dk/irtcl/"
1468 name="http://www.indexdata.dk/irtcl/">
1469 <tag>2 Ousterhout, John K.:</tag>
1470 Tcl and the Tk Toolkit. Addison-Wesley Company Inc (ISBN
1471 0-201-63337-X). The Tcl/Tk toolkit home page is
1472 <tt><htmlurl url="http://www.sunscript.com"
1473 name="http://www.sunscript.com"></tt>.
1474 The primary ftp site is <tt><htmlurl url="ftp://ftp.smli.com/pub/tcl/"
1475 name="ftp://ftp.smli.com/pub/tcl/"></tt>.
1476 <tag>3 Welch, Brent B.:</tag>
1477 Practical Programming in Tcl and Tk. Prentice Hall
1478 (ISBN 0-13-616830-2).