<HTML ><HEAD ><TITLE >Examples</TITLE ><META NAME="GENERATOR" CONTENT="Modular DocBook HTML Stylesheet Version 1.7"><LINK REL="HOME" TITLE="VB6 To Tcl mini-HOWTO" HREF="index.html"><LINK REL="PREVIOUS" TITLE="Introduction" HREF="intro.html"><LINK REL="NEXT" TITLE="Getting More Information" HREF="more.html"></HEAD ><BODY CLASS="SECT1" BGCOLOR="#FFFFFF" TEXT="#000000" LINK="#0000FF" VLINK="#840084" ALINK="#0000FF" ><DIV CLASS="NAVHEADER" ><TABLE SUMMARY="Header navigation table" WIDTH="100%" BORDER="0" CELLPADDING="0" CELLSPACING="0" ><TR ><TH COLSPAN="3" ALIGN="center" >VB6 To Tcl mini-HOWTO</TH ></TR ><TR ><TD WIDTH="10%" ALIGN="left" VALIGN="bottom" ><A HREF="intro.html" ACCESSKEY="P" >Prev</A ></TD ><TD WIDTH="80%" ALIGN="center" VALIGN="bottom" ></TD ><TD WIDTH="10%" ALIGN="right" VALIGN="bottom" ><A HREF="more.html" ACCESSKEY="N" >Next</A ></TD ></TR ></TABLE ><HR ALIGN="LEFT" WIDTH="100%"></DIV ><DIV CLASS="SECT1" ><H1 CLASS="SECT1" ><A NAME="EXAMPLES" ></A >2. Examples</H1 ><DIV CLASS="TABLE" ><A NAME="AEN45" ></A ><P ><B >Table 1. Differences</B ></P ><TABLE BORDER="1" CLASS="CALSTABLE" ><TBODY ><TR ><TD WIDTH="50%" ALIGN="CENTER" VALIGN="TOP" >VB6 </TD ><TD WIDTH="50%" ALIGN="CENTER" VALIGN="TOP" > Tcl/Tk 8.3 </TD ></TR ><TR ><TD COLSPAN="2" ALIGN="LEFT" VALIGN="TOP" >Notes/differences </TD ></TR ><TR ><TD WIDTH="50%" ALIGN="LEFT" VALIGN="TOP" ><P ><TABLE BORDER="0" BGCOLOR="#E0E0E0" WIDTH="100%" ><TR ><TD ><FONT COLOR="#000000" ><PRE CLASS="PROGRAMLISTING" >dim a as integer dim b as integer a=1 : b=0</PRE ></FONT ></TD ></TR ></TABLE > </P ></TD ><TD WIDTH="50%" ALIGN="LEFT" VALIGN="TOP" ><P ><TABLE BORDER="0" BGCOLOR="#E0E0E0" WIDTH="100%" ><TR ><TD ><FONT COLOR="#000000" ><PRE CLASS="PROGRAMLISTING" > set a 1; set b 0 </PRE ></FONT ></TD ></TR ></TABLE > </P ></TD ></TR ><TR ><TD COLSPAN="2" ALIGN="LEFT" VALIGN="TOP" >Separator for multiple commands per line. Tcl uses a semicolon. Multiple commands per line is generally considered bad form, but the semicolon is also used to implement partial-line comments, so it is illustrated here. </TD ></TR ><TR ><TD WIDTH="50%" ALIGN="LEFT" VALIGN="TOP" ><P ><TABLE BORDER="0" BGCOLOR="#E0E0E0" WIDTH="100%" ><TR ><TD ><FONT COLOR="#000000" ><PRE CLASS="PROGRAMLISTING" > ' this is a whole line </PRE ></FONT ></TD ></TR ></TABLE ></P ></TD ><TD WIDTH="50%" ALIGN="LEFT" VALIGN="TOP" ><P ><TABLE BORDER="0" BGCOLOR="#E0E0E0" WIDTH="100%" ><TR ><TD ><FONT COLOR="#000000" ><PRE CLASS="PROGRAMLISTING" > # this is a whole line </PRE ></FONT ></TD ></TR ></TABLE ></P ></TD ></TR ><TR ><TD COLSPAN="2" ALIGN="LEFT" VALIGN="TOP" >Full-line comment. Neither language requires a space after the comment marker.</TD ></TR ><TR ><TD WIDTH="50%" ALIGN="LEFT" VALIGN="TOP" ><P ><TABLE BORDER="0" BGCOLOR="#E0E0E0" WIDTH="100%" ><TR ><TD ><FONT COLOR="#000000" ><PRE CLASS="PROGRAMLISTING" >dim a as integer a=1 'this is a partial-line comment </PRE ></FONT ></TD ></TR ></TABLE ></P ></TD ><TD WIDTH="50%" ALIGN="LEFT" VALIGN="TOP" ><P ><TABLE BORDER="0" BGCOLOR="#E0E0E0" WIDTH="100%" ><TR ><TD ><FONT COLOR="#000000" ><PRE CLASS="PROGRAMLISTING" > set a 1 ;# this is a partial-line comment </PRE ></FONT ></TD ></TR ></TABLE ></P ></TD ></TR ><TR ><TD COLSPAN="2" ALIGN="LEFT" VALIGN="TOP" >Partial-line comment. Note the semicolon, used as if the comment is another command on that line.</TD ></TR ><TR ><TD WIDTH="50%" ALIGN="LEFT" VALIGN="TOP" ><P ><TABLE BORDER="0" BGCOLOR="#E0E0E0" WIDTH="100%" ><TR ><TD ><FONT COLOR="#000000" ><PRE CLASS="PROGRAMLISTING" >dim s as string s="/data/docs/vb6_to_tcl.htm" </PRE ></FONT ></TD ></TR ></TABLE ></P ></TD ><TD WIDTH="50%" ALIGN="LEFT" VALIGN="TOP" ><P ><TABLE BORDER="0" BGCOLOR="#E0E0E0" WIDTH="100%" ><TR ><TD ><FONT COLOR="#000000" ><PRE CLASS="PROGRAMLISTING" > set s {/data/docs/vb6_to_tcl.htm} </PRE ></FONT ></TD ></TR ></TABLE ></P ></TD ></TR ><TR ><TD COLSPAN="2" ALIGN="LEFT" VALIGN="TOP" >Assignment of a string quoted with braces. Most Tcl substitutions are NOT done in a string quoted with braces. If the string contains variables or other items that would be substituted, these will be deferred, but may be substituted at a later time. This is often done by commands that implement control structures, such as 'if' or 'while'. Once you start to get familiar with Tcl initially, try to thoroughly understand this process because it's important to getting 'good' in Tcl.</TD ></TR ><TR ><TD WIDTH="50%" ALIGN="LEFT" VALIGN="TOP" ><P ><TABLE BORDER="0" BGCOLOR="#E0E0E0" WIDTH="100%" ><TR ><TD ><FONT COLOR="#000000" ><PRE CLASS="PROGRAMLISTING" > (No equivalent) </PRE ></FONT ></TD ></TR ></TABLE ></P ></TD ><TD WIDTH="50%" ALIGN="LEFT" VALIGN="TOP" ><P ><TABLE BORDER="0" BGCOLOR="#E0E0E0" WIDTH="100%" ><TR ><TD ><FONT COLOR="#000000" ><PRE CLASS="PROGRAMLISTING" > set s "/data/docs/vb6_to_tcl.htm" </PRE ></FONT ></TD ></TR ></TABLE ></P ></TD ></TR ><TR ><TD COLSPAN="2" ALIGN="LEFT" VALIGN="TOP" >Assignment of a quoted string. All Tcl substitutions (variables, commands, backslashes) are available within a quoted string.</TD ></TR ><TR ><TD WIDTH="50%" ALIGN="LEFT" VALIGN="TOP" ><P ><TABLE BORDER="0" BGCOLOR="#E0E0E0" WIDTH="100%" ><TR ><TD ><FONT COLOR="#000000" ><PRE CLASS="PROGRAMLISTING" > (No equivalent) </PRE ></FONT ></TD ></TR ></TABLE ></P ></TD ><TD WIDTH="50%" ALIGN="LEFT" VALIGN="TOP" ><P ><TABLE BORDER="0" BGCOLOR="#E0E0E0" WIDTH="100%" ><TR ><TD ><FONT COLOR="#000000" ><PRE CLASS="PROGRAMLISTING" > set s /data/docs/vb6_to_tcl.htm </PRE ></FONT ></TD ></TR ></TABLE ></P ></TD ></TR ><TR ><TD COLSPAN="2" ALIGN="LEFT" VALIGN="TOP" >Assignment of an unquoted string. All Tcl substitutions (variables, commands, backslashes) are available within an unquoted string. The interpreter simply takes the string as the third word in the set command (second argument to the set command). This works if there is no whitespace or certain other characters in the string. Use judiciously, especially when dealing with arbitrary data entered by the user.</TD ></TR ><TR ><TD WIDTH="50%" ALIGN="LEFT" VALIGN="TOP" ><P ><TABLE BORDER="0" BGCOLOR="#E0E0E0" WIDTH="100%" ><TR ><TD ><FONT COLOR="#000000" ><PRE CLASS="PROGRAMLISTING" > dim s as string s = vbCrLf &"Free software is not just" &vbCrLf _ &"about being 'free of charge'" &vbCrLf _ &"but about freedom to create" &vbCrLf _ &"and use the best possible tools." &vbCrLf </PRE ></FONT ></TD ></TR ></TABLE ></P ></TD ><TD WIDTH="50%" ALIGN="LEFT" VALIGN="TOP" ><P ><TABLE BORDER="0" BGCOLOR="#E0E0E0" WIDTH="100%" ><TR ><TD ><FONT COLOR="#000000" ><PRE CLASS="PROGRAMLISTING" > set s { Free software is not just about being 'free of charge' but about freedom to create and use the best possible tools. } </PRE ></FONT ></TD ></TR ></TABLE ></P ></TD ></TR ><TR ><TD COLSPAN="2" ALIGN="LEFT" VALIGN="TOP" >Assignment of multi-line string. Note the more cluttered syntax in VB, which makes it more difficult to read than the Tcl code.</TD ></TR ><TR ><TD WIDTH="50%" ALIGN="LEFT" VALIGN="TOP" ><P ><TABLE BORDER="0" BGCOLOR="#E0E0E0" WIDTH="100%" ><TR ><TD ><FONT COLOR="#000000" ><PRE CLASS="PROGRAMLISTING" > dim s as string dim t as string s = trim(t) </PRE ></FONT ></TD ></TR ></TABLE ></P ></TD ><TD WIDTH="50%" ALIGN="LEFT" VALIGN="TOP" ><P ><TABLE BORDER="0" BGCOLOR="#E0E0E0" WIDTH="100%" ><TR ><TD ><FONT COLOR="#000000" ><PRE CLASS="PROGRAMLISTING" > set s [string trim $t] </PRE ></FONT ></TD ></TR ></TABLE ></P ></TD ></TR ><TR ><TD COLSPAN="2" ALIGN="LEFT" VALIGN="TOP" >Assignment of function return value. The third word of this set command is surrounded in square brackets. That means it is itself a command to be executed, with the result taking its place as the third word of the set command.</TD ></TR ><TR ><TD WIDTH="50%" ALIGN="LEFT" VALIGN="TOP" ><P ><TABLE BORDER="0" BGCOLOR="#E0E0E0" WIDTH="100%" ><TR ><TD ><FONT COLOR="#000000" ><PRE CLASS="PROGRAMLISTING" > dim s as string dim t as string s = lcase(trim(t)) </PRE ></FONT ></TD ></TR ></TABLE ></P ></TD ><TD WIDTH="50%" ALIGN="LEFT" VALIGN="TOP" ><P ><TABLE BORDER="0" BGCOLOR="#E0E0E0" WIDTH="100%" ><TR ><TD ><FONT COLOR="#000000" ><PRE CLASS="PROGRAMLISTING" > set s [string tolower [string trim $t]] </PRE ></FONT ></TD ></TR ></TABLE ></P ></TD ></TR ><TR ><TD COLSPAN="2" ALIGN="LEFT" VALIGN="TOP" >Assignment of function-of-function.</TD ></TR ><TR ><TD WIDTH="50%" ALIGN="LEFT" VALIGN="TOP" ><P ><TABLE BORDER="0" BGCOLOR="#E0E0E0" WIDTH="100%" ><TR ><TD ><FONT COLOR="#000000" ><PRE CLASS="PROGRAMLISTING" > dim x as double dim y as double x = (y + 10) * 5 </PRE ></FONT ></TD ></TR ></TABLE ></P ></TD ><TD WIDTH="50%" ALIGN="LEFT" VALIGN="TOP" ><P ><TABLE BORDER="0" BGCOLOR="#E0E0E0" WIDTH="100%" ><TR ><TD ><FONT COLOR="#000000" ><PRE CLASS="PROGRAMLISTING" > set x [expr {($y + 10) * 5}] </PRE ></FONT ></TD ></TR ></TABLE ></P ></TD ></TR ><TR ><TD COLSPAN="2" ALIGN="LEFT" VALIGN="TOP" >Assignment of result of a mathematical expression. The Tcl interpreter relies on the expr command to evaluate mathematical or logical expressions. Many other commands such as 'if' or 'while' also rely on expr in their implementation. When used explicitly, expr should be passed a single argument which is a string containing the expression (as shown here). That could get cumbersome in simple cases where you just want to add a certain increment to a variable. Try using the incr command for that instead.</TD ></TR ><TR ><TD WIDTH="50%" ALIGN="LEFT" VALIGN="TOP" ><P ><TABLE BORDER="0" BGCOLOR="#E0E0E0" WIDTH="100%" ><TR ><TD ><FONT COLOR="#000000" ><PRE CLASS="PROGRAMLISTING" > dim s as string s = s &"more text" </PRE ></FONT ></TD ></TR ></TABLE ></P ></TD ><TD WIDTH="50%" ALIGN="LEFT" VALIGN="TOP" ><P ><TABLE BORDER="0" BGCOLOR="#E0E0E0" WIDTH="100%" ><TR ><TD ><FONT COLOR="#000000" ><PRE CLASS="PROGRAMLISTING" > append s {more text} </PRE ></FONT ></TD ></TR ></TABLE ></P ></TD ></TR ><TR ><TD COLSPAN="2" ALIGN="LEFT" VALIGN="TOP" >Append to an existing string. This is one of the slowest operations in VB, but is typically very speedy in Tcl. Speed is important here because it is often done within loops or compound loops.</TD ></TR ><TR ><TD WIDTH="50%" ALIGN="LEFT" VALIGN="TOP" ><P ><TABLE BORDER="0" BGCOLOR="#E0E0E0" WIDTH="100%" ><TR ><TD ><FONT COLOR="#000000" ><PRE CLASS="PROGRAMLISTING" >dim s as string dim t as string dim u as string s = "I'll ask " & t & " to email " & trim(u) & " with the price" </PRE ></FONT ></TD ></TR ></TABLE ></P ></TD ><TD WIDTH="50%" ALIGN="LEFT" VALIGN="TOP" ><P ><TABLE BORDER="0" BGCOLOR="#E0E0E0" WIDTH="100%" ><TR ><TD ><FONT COLOR="#000000" ><PRE CLASS="PROGRAMLISTING" > set s "I'll ask $t to email [string trim $u] with the price" </PRE ></FONT ></TD ></TR ></TABLE ></P ></TD ></TR ><TR ><TD COLSPAN="2" ALIGN="LEFT" VALIGN="TOP" >Building a string by substitution.</TD ></TR ><TR ><TD WIDTH="50%" ALIGN="LEFT" VALIGN="TOP" ><P ><TABLE BORDER="0" BGCOLOR="#E0E0E0" WIDTH="100%" ><TR ><TD ><FONT COLOR="#000000" ><PRE CLASS="PROGRAMLISTING" > print "hello" </PRE ></FONT ></TD ></TR ></TABLE ></P ></TD ><TD WIDTH="50%" ALIGN="LEFT" VALIGN="TOP" > Displays hello. </TD ></TR ><TR ><TD COLSPAN="2" ALIGN="LEFT" VALIGN="TOP" >Print to console (VB actually prints to a form or to the debug window).</TD ></TR ><TR ><TD WIDTH="50%" ALIGN="LEFT" VALIGN="TOP" ><P ><TABLE BORDER="0" BGCOLOR="#E0E0E0" WIDTH="100%" ><TR ><TD ><FONT COLOR="#000000" ><PRE CLASS="PROGRAMLISTING" > sub my_sub (byval a as integer, byval b as string) debug.print "I'll ask " & b end sub function my_function (byval a as integer, _ optional byval b as string = "Mark") _ as string my_function = "I'll ask " & b end function </PRE ></FONT ></TD ></TR ></TABLE ></P ></TD ><TD WIDTH="50%" ALIGN="LEFT" VALIGN="TOP" ><P ><TABLE BORDER="0" BGCOLOR="#E0E0E0" WIDTH="100%" ><TR ><TD ><FONT COLOR="#000000" ><PRE CLASS="PROGRAMLISTING" > proc my_sub {a b} { puts "I'll ask $b" } proc my_function {a {b Mark}} { return "I'll ask $b" } </PRE ></FONT ></TD ></TR ></TABLE ></P ></TD ></TR ><TR ><TD COLSPAN="2" ALIGN="LEFT" VALIGN="TOP" >Procedure definition. Note that VB uses a separate syntax for subs and for functions. Tcl uses the <B CLASS="COMMAND" >proc</B > command to define either one. <B CLASS="COMMAND" >proc</B > itself is an ordinary Tcl command that executes like any other command. Its first argument is a Tcl list of the parameters of the new procedure. Its second argument is a large string containing the body of the new procedure (actual Tcl script). <EM >Important:</EM > Tcl is case sensitive in almost all operations, including all references to command names and variable names, as well as (by default) string data comparisons. So a call to <B CLASS="COMMAND" >Proc</B > would cause an error (capital P), as would a call to <TT CLASS="VARNAME" >My_Sub</TT >, or a reference to the variable <TT CLASS="VARNAME" >B</TT > within <TT CLASS="VARNAME" >my_sub</TT > (b was defined as lower case).</TD ></TR ><TR ><TD WIDTH="50%" ALIGN="LEFT" VALIGN="TOP" ><P ><TABLE BORDER="0" BGCOLOR="#E0E0E0" WIDTH="100%" ><TR ><TD ><FONT COLOR="#000000" ><PRE CLASS="PROGRAMLISTING" > dim i as integer if i < 0 then i = 0 else i = i - 1 </PRE ></FONT ></TD ></TR ></TABLE ></P ></TD ><TD WIDTH="50%" ALIGN="LEFT" VALIGN="TOP" ><P ><TABLE BORDER="0" BGCOLOR="#E0E0E0" WIDTH="100%" ><TR ><TD ><FONT COLOR="#000000" ><PRE CLASS="PROGRAMLISTING" >if {$i < 0} {set i 0} {incr i -1} # alternate form if {$i < 0} then {set i 0} else {incr i -1} # another alternate form if {$i < 0} then { set i 0 } else { incr i -1 } </PRE ></FONT ></TD ></TR ></TABLE ></P ></TD ></TR ><TR ><TD COLSPAN="2" ALIGN="LEFT" VALIGN="TOP" >'if' conditional execution. The Tcl 'if' command ignores the optional keywords 'then' and 'else' if they are present. Since both code blocks are just strings, they can be enclosed in braces and nicely formatted as shown. To avoid syntax errors, also enclose any non-trivial test expression in braces. That way substitutions (such as $i here) are deferred until the 'if' command passes the test expression to the expression parser.</TD ></TR ><TR ><TD WIDTH="50%" ALIGN="LEFT" VALIGN="TOP" ><P ><TABLE BORDER="0" BGCOLOR="#E0E0E0" WIDTH="100%" ><TR ><TD ><FONT COLOR="#000000" ><PRE CLASS="PROGRAMLISTING" >dim i as integer i = 1 while i < 2000 i = i * 2 wend 'alternate form i = 1 do while i < 2000 i = i * 2 loop </PRE ></FONT ></TD ></TR ></TABLE ></P ></TD ><TD WIDTH="50%" ALIGN="LEFT" VALIGN="TOP" ><P ><TABLE BORDER="0" BGCOLOR="#E0E0E0" WIDTH="100%" ><TR ><TD ><FONT COLOR="#000000" ><PRE CLASS="PROGRAMLISTING" > set i 1 while {$i < 2000} { set i [expr {$i * 2}] } </PRE ></FONT ></TD ></TR ></TABLE ></P ></TD ></TR ><TR ><TD COLSPAN="2" ALIGN="LEFT" VALIGN="TOP" >'while' loop. This is similar to the Tcl 'if' command in that it takes a test expression as its first argument, followed by a string of code.</TD ></TR ><TR ><TD WIDTH="50%" ALIGN="LEFT" VALIGN="TOP" ><P ><TABLE BORDER="0" BGCOLOR="#E0E0E0" WIDTH="100%" ><TR ><TD ><FONT COLOR="#000000" ><PRE CLASS="PROGRAMLISTING" > dim i as integer for i = 0 to 8 'nine passes 0-8 debug.print i next </PRE ></FONT ></TD ></TR ></TABLE ></P ></TD ><TD WIDTH="50%" ALIGN="LEFT" VALIGN="TOP" ><P ><TABLE BORDER="0" BGCOLOR="#E0E0E0" WIDTH="100%" ><TR ><TD ><FONT COLOR="#000000" ><PRE CLASS="PROGRAMLISTING" >for {set i 0} {$i < 9} {incr i} { # nine passes 0-8 puts $i } # alternate form for {set i 0} {$i <= 8} {incr i} { # again, nine passes 0-8 puts $i } # another alternate form for {set i 1} {$i <= 9} {incr i} { # nine passes 1-9 puts $i } # yet another alternate form - less readable set i 1 for {} {[incr i] <= 9} {} { # nine passes 1-9 puts $i } </PRE ></FONT ></TD ></TR ></TABLE ></P ></TD ></TR ><TR ><TD COLSPAN="2" ALIGN="LEFT" VALIGN="TOP" >'for' loop with an integer counter. In Tcl (or any other language) this is equivalent to a 'while' loop. In some languages such as VB, 'for' is not as flexible as 'while'. In Tcl this is not the case. Anything can be used as the initialization code, the test-for-continuation expression, and the increment code. Those pieces are not restricted to doing anything in particular, as you can see by the final example.</TD ></TR ><TR ><TD WIDTH="50%" ALIGN="LEFT" VALIGN="TOP" ><P ><TABLE BORDER="0" BGCOLOR="#E0E0E0" WIDTH="100%" ><TR ><TD ><FONT COLOR="#000000" ><PRE CLASS="PROGRAMLISTING" > dim c as new collection dim o as object c.add "Mark" c.add "Roy" c.add "Brian" for each o in c debug.print o next </PRE ></FONT ></TD ></TR ></TABLE ></P ></TD ><TD WIDTH="50%" ALIGN="LEFT" VALIGN="TOP" ><P ><TABLE BORDER="0" BGCOLOR="#E0E0E0" WIDTH="100%" ><TR ><TD ><FONT COLOR="#000000" ><PRE CLASS="PROGRAMLISTING" > set c [list Mark Roy Brian] foreach o $c { puts $o } </PRE ></FONT ></TD ></TR ></TABLE ></P ></TD ></TR ><TR ><TD COLSPAN="2" ALIGN="LEFT" VALIGN="TOP" >Loop through items in a data structure. In Tcl, a list data structure is used. VB has no direct equivalent to that, but a collection object is the most similar. Note that VB collections are far slower than Tcl lists in typical operations due to the overhead of using method calls to objects. Also note that there are <EM >far more powerful and creative uses</EM > of the foreach command that are not shown here. Those have no direct equivalent in VB.</TD ></TR ><TR ><TD WIDTH="50%" ALIGN="LEFT" VALIGN="TOP" ><P ><TABLE BORDER="0" BGCOLOR="#E0E0E0" WIDTH="100%" ><TR ><TD ><FONT COLOR="#000000" ><PRE CLASS="PROGRAMLISTING" > dim s as string select case s case "John" debug.print "Mellencamp" case "Steve" debug.print "Tyler" case else debug.print "Unknown" end select </PRE ></FONT ></TD ></TR ></TABLE ></P ></TD ><TD WIDTH="50%" ALIGN="LEFT" VALIGN="TOP" ><P ><TABLE BORDER="0" BGCOLOR="#E0E0E0" WIDTH="100%" ><TR ><TD ><FONT COLOR="#000000" ><PRE CLASS="PROGRAMLISTING" > switch -exact $s { John {puts Mellencamp} Steve {puts Tyler} default {puts Unknown} } </PRE ></FONT ></TD ></TR ></TABLE ></P ></TD ></TR ><TR ><TD COLSPAN="2" ALIGN="LEFT" VALIGN="TOP" >One-of-many execution. Note the Tcl version is case sensitive. In VB it often is not, depending on the 'option compare' that is in effect for the module. The <TT CLASS="OPTION" >-exact</TT > option specifies an exact string match is required, as opposed to a pattern match or regular expression match (this has no bearing on case sensitivity). Also note that there are more powerful and creative uses of the switch command that are not shown here.</TD ></TR ><TR ><TD WIDTH="50%" ALIGN="LEFT" VALIGN="TOP" ><P ><TABLE BORDER="0" BGCOLOR="#E0E0E0" WIDTH="100%" ><TR ><TD ><FONT COLOR="#000000" ><PRE CLASS="PROGRAMLISTING" > on error goto handler debug.print a 'a is undeclared. ... handler: debug.print err.number, err.description </PRE ></FONT ></TD ></TR ></TABLE ></P ></TD ><TD WIDTH="50%" ALIGN="LEFT" VALIGN="TOP" ><P ><TABLE BORDER="0" BGCOLOR="#E0E0E0" WIDTH="100%" ><TR ><TD ><FONT COLOR="#000000" ><PRE CLASS="PROGRAMLISTING" > if [catch { puts $a ;# a has not been set } my_err] { puts "error message: $my_err" puts "stack trace: $errorInfo" # these things would have been shown # by the default error handler anyway. } else { puts {All is well.} # the else block is optional. } </PRE ></FONT ></TD ></TR ></TABLE ></P ></TD ></TR ><TR ><TD COLSPAN="2" ALIGN="LEFT" VALIGN="TOP" >Error handling. In VB, handling errors concisely can be a problem, especially if different actions need to be taken based on which part of the code failed. Tcl <B CLASS="COMMAND" >catch</B > command neatly solves these problems. In addition, Tcl automatically provides a stack trace of the code that failed. In VB, the stack trace has to be explicitly built by the code, if a stack trace is desired while the application is in production (not in the IDE). This is an advantage for Tcl when debugging in the field. Note that <B CLASS="COMMAND" >catch</B > returns a boolean 1 or 0, which is typically used with 'if', as shown here.</TD ></TR ><TR ><TD WIDTH="50%" ALIGN="LEFT" VALIGN="TOP" ><P ><TABLE BORDER="0" BGCOLOR="#E0E0E0" WIDTH="100%" ><TR ><TD ><FONT COLOR="#000000" ><PRE CLASS="PROGRAMLISTING" > (No equivalent) </PRE ></FONT ></TD ></TR ></TABLE ></P ></TD ><TD WIDTH="50%" ALIGN="LEFT" VALIGN="TOP" ><P ><TABLE BORDER="0" BGCOLOR="#E0E0E0" WIDTH="100%" ><TR ><TD ><FONT COLOR="#000000" ><PRE CLASS="PROGRAMLISTING" > set i [expr $e] </PRE ></FONT ></TD ></TR ></TABLE ></P ></TD ></TR ><TR ><TD COLSPAN="2" ALIGN="LEFT" VALIGN="TOP" >Pass an arbitrary mathematical expression to the interpreter for evaluation. This could be an expression entered by the user, or composed by earlier code. This is one of the most powerful aspects of Tcl. It is not available at all in VB.</TD ></TR ><TR ><TD WIDTH="50%" ALIGN="LEFT" VALIGN="TOP" ><P ><TABLE BORDER="0" BGCOLOR="#E0E0E0" WIDTH="100%" ><TR ><TD ><FONT COLOR="#000000" ><PRE CLASS="PROGRAMLISTING" > (No equivalent) </PRE ></FONT ></TD ></TR ></TABLE ></P ></TD ><TD WIDTH="50%" ALIGN="LEFT" VALIGN="TOP" ><P ><TABLE BORDER="0" BGCOLOR="#E0E0E0" WIDTH="100%" ><TR ><TD ><FONT COLOR="#000000" ><PRE CLASS="PROGRAMLISTING" > set s [eval $c] </PRE ></FONT ></TD ></TR ></TABLE ></P ></TD ></TR ><TR ><TD COLSPAN="2" ALIGN="LEFT" VALIGN="TOP" >Pass arbitrary code to the interpreter for execution. This could be some script entered by the user, or composed by earlier code. This is one of the most powerful aspects of Tcl. It is not available at all in VB.</TD ></TR ><TR ><TD WIDTH="50%" ALIGN="LEFT" VALIGN="TOP" ><P ><TABLE BORDER="0" BGCOLOR="#E0E0E0" WIDTH="100%" ><TR ><TD ><FONT COLOR="#000000" ><PRE CLASS="PROGRAMLISTING" > (No equivalent) </PRE ></FONT ></TD ></TR ></TABLE ></P ></TD ><TD WIDTH="50%" ALIGN="LEFT" VALIGN="TOP" ><P ><TABLE BORDER="0" BGCOLOR="#E0E0E0" WIDTH="100%" ><TR ><TD ><FONT COLOR="#000000" ><PRE CLASS="PROGRAMLISTING" > source my_script.tcl </PRE ></FONT ></TD ></TR ></TABLE ></P ></TD ></TR ><TR ><TD COLSPAN="2" ALIGN="LEFT" VALIGN="TOP" >Pass an arbitrary filename to the interpreter for execution of that file as a script. This is one of the most powerful aspects of Tcl. It is not available at all in VB.</TD ></TR ><TR ><TD WIDTH="50%" ALIGN="LEFT" VALIGN="TOP" ><P ><TABLE BORDER="0" BGCOLOR="#E0E0E0" WIDTH="100%" ><TR ><TD ><FONT COLOR="#000000" ><PRE CLASS="PROGRAMLISTING" > (No equivalent) </PRE ></FONT ></TD ></TR ></TABLE ></P ></TD ><TD WIDTH="50%" ALIGN="LEFT" VALIGN="TOP" ><P ><TABLE BORDER="0" BGCOLOR="#E0E0E0" WIDTH="100%" ><TR ><TD ><FONT COLOR="#000000" ><PRE CLASS="PROGRAMLISTING" > set var_name marks_age incr $var_name </PRE ></FONT ></TD ></TR ></TABLE ></P ></TD ></TR ><TR ><TD COLSPAN="2" ALIGN="LEFT" VALIGN="TOP" >Perform operations on an arbitrarily-chosen variable. The code shown here will increment the variable <TT CLASS="VARNAME" >marks_age</TT >. Its name (the string "marks_age") is stored in the variable <TT CLASS="VARNAME" >var_name</TT >. In fact, all parts of every command are subject to one pass of substitution by the interpreter just prior to execution. So any part of any command (even the name of the command itself) can be varied based on data or any other criteria. This is one of the most powerful aspects of Tcl. It is not available at all in VB.</TD ></TR ><TR ><TD WIDTH="50%" ALIGN="LEFT" VALIGN="TOP" ><P ><TABLE BORDER="0" BGCOLOR="#E0E0E0" WIDTH="100%" ><TR ><TD ><FONT COLOR="#000000" ><PRE CLASS="PROGRAMLISTING" > dim s as string dim li as string dim f_num as integer s = "" f_num = freefile open "my_file.txt" for input as #f_num while not eof(f_num) line input #f_num, li s = s & li & vbCrLf wend close #f_num </PRE ></FONT ></TD ></TR ></TABLE ></P ></TD ><TD WIDTH="50%" ALIGN="LEFT" VALIGN="TOP" ><P ><TABLE BORDER="0" BGCOLOR="#E0E0E0" WIDTH="100%" ><TR ><TD ><FONT COLOR="#000000" ><PRE CLASS="PROGRAMLISTING" > set f [open my_file.txt r] set s [read $f] close $f </PRE ></FONT ></TD ></TR ></TABLE ></P ></TD ></TR ><TR ><TD COLSPAN="2" ALIGN="LEFT" VALIGN="TOP" >Read whole file into a variable. This VB code is very slow for even moderately large files. And it has no way to deal with newline characters in the data. The Tcl code accepts and preserves newlines in the data. It also normalizes different newline characters into a single kind of standardized newline character (by default). This code applies equally well to raw data, or Tcl lists, or Tcl arrays. The <TT CLASS="OPTION" >r</TT > in the <B CLASS="COMMAND" >open</B > command indicates 'read' mode.</TD ></TR ><TR ><TD WIDTH="50%" ALIGN="LEFT" VALIGN="TOP" ><P ><TABLE BORDER="0" BGCOLOR="#E0E0E0" WIDTH="100%" ><TR ><TD ><FONT COLOR="#000000" ><PRE CLASS="PROGRAMLISTING" > dim a(1 to 3) as string a(1) = "Mark" a(2) = "Brian" a(3) = "Roy" 'oops - need more elements redim preserve a(1 to 10) as string a(4) = "John" </PRE ></FONT ></TD ></TR ></TABLE ></P ></TD ><TD WIDTH="50%" ALIGN="LEFT" VALIGN="TOP" ><P ><TABLE BORDER="0" BGCOLOR="#E0E0E0" WIDTH="100%" ><TR ><TD ><FONT COLOR="#000000" ><PRE CLASS="PROGRAMLISTING" > array set a [list 1 Mark 2 Brian 3 Roy] set a(4) John # now some different kinds of # element names in the same array set a(Red) Hat set a(Linux,RedHat) 7.1 </PRE ></FONT ></TD ></TR ></TABLE ></P ></TD ></TR ><TR ><TD COLSPAN="2" ALIGN="LEFT" VALIGN="TOP" >Array vs. Array. VB arrays are restricted to using numbers as subscripts (subscripts, or indexes, are called 'element names' in Tcl). And the array must be declared to be a certain size - expanding it requires a (slow) 'ReDim Preserve' operation. Tcl arrays automatically expand, and they use a super-efficient hash table implementation to handle even hundreds of thousands of elements with superior speed. Tcl uses any kind of data for an element name, and different styles can even be mixed within the same array. There are no restrictions on the number of dimensions in each element. Tcl provides simple ways to iterate through the array, or through only certain elements in the array (by filter). You can also obtain a full or partial list of the element names, and do other operations more conveniently than in VB. To get just a portion of those capabilities in VB requires the use of a collection or dictionary object. Each of those comes with its own quirks and pitfalls, such as even higher overhead than a VB array.</TD ></TR ><TR ><TD WIDTH="50%" ALIGN="LEFT" VALIGN="TOP" ><P ><TABLE BORDER="0" BGCOLOR="#E0E0E0" WIDTH="100%" ><TR ><TD ><FONT COLOR="#000000" ><PRE CLASS="PROGRAMLISTING" > (No equivalent) </PRE ></FONT ></TD ></TR ></TABLE ></P ></TD ><TD WIDTH="50%" ALIGN="LEFT" VALIGN="TOP" ><P ><TABLE BORDER="0" BGCOLOR="#E0E0E0" WIDTH="100%" ><TR ><TD ><FONT COLOR="#000000" ><PRE CLASS="PROGRAMLISTING" > array set my_array $my_list set my_list [array get my_array] </PRE ></FONT ></TD ></TR ></TABLE ></P ></TD ></TR ><TR ><TD COLSPAN="2" ALIGN="LEFT" VALIGN="TOP" >List to array, and back. Easy and rapid translation between these two primary data structures means that the tools for each one can be applied to both. They multiply each other's usefulness.</TD ></TR ><TR ><TD WIDTH="50%" ALIGN="LEFT" VALIGN="TOP" ><P ><TABLE BORDER="0" BGCOLOR="#E0E0E0" WIDTH="100%" ><TR ><TD ><FONT COLOR="#000000" ><PRE CLASS="PROGRAMLISTING" >dim a(1 to 100) as string dim i as integer dim f_num as integer f_num = freefile open "my_file.txt" for output as #f_num for i=1 to 100 print #f_num, a(i) next close #f_num </PRE ></FONT ></TD ></TR ></TABLE ></P ></TD ><TD WIDTH="50%" ALIGN="LEFT" VALIGN="TOP" ><P ><TABLE BORDER="0" BGCOLOR="#E0E0E0" WIDTH="100%" ><TR ><TD ><FONT COLOR="#000000" ><PRE CLASS="PROGRAMLISTING" > set f [open my_file.txt w] puts $f [array get a] close $f </PRE ></FONT ></TD ></TR ></TABLE ></P ></TD ></TR ><TR ><TD COLSPAN="2" ALIGN="LEFT" VALIGN="TOP" >Write whole array. In this VB code, and frequently in other VB code, newlines and possibly other characters appearing in the data will cause errors during a later step (the read-back). This becomes a problem whenever your code deals with arbitrary data entered by the user. In Tcl they do not - the data is kept "clean" at all times. In addition, various combinations of carriage return (0x0D or decimal 13) and line-feed (0x0A or decimal 10) characters are automatically normalized by default. Note that these two examples don't produce identical output files. The Tcl example, like the VB, writes a plain text file. But the Tcl file will be read back in (by Tcl) and automatically have the same number of elements, same element names, etc.. The Tcl list data structure is used for this. Using it ensures that the data is formatted in a concise, non-ambiguous, textual representation. It is also readable and writable by humans.</TD ></TR ><TR ><TD WIDTH="50%" ALIGN="LEFT" VALIGN="TOP" ><P ><TABLE BORDER="0" BGCOLOR="#E0E0E0" WIDTH="100%" ><TR ><TD ><FONT COLOR="#000000" ><PRE CLASS="PROGRAMLISTING" > (No equivalent) </PRE ></FONT ></TD ></TR ></TABLE ></P ></TD ><TD WIDTH="50%" ALIGN="LEFT" VALIGN="TOP" ><P ><TABLE BORDER="0" BGCOLOR="#E0E0E0" WIDTH="100%" ><TR ><TD ><FONT COLOR="#000000" ><PRE CLASS="PROGRAMLISTING" > set f [open my_file.txt w] puts $f [array get a red*] close $f </PRE ></FONT ></TD ></TR ></TABLE ></P ></TD ></TR ><TR ><TD COLSPAN="2" ALIGN="LEFT" VALIGN="TOP" >Write certain elements of an array. In the VB, a collection or dictionary object would have to be used for this. A loop would iterate through all the elements and select them as appropriate. In the Tcl, the array's name is <TT CLASS="LITERAL" >a</TT > and a string pattern of <TT CLASS="LITERAL" >red*</TT > (case sensitive) is used as a filter to select elements at high speed.</TD ></TR ><TR ><TD WIDTH="50%" ALIGN="LEFT" VALIGN="TOP" ><P ><TABLE BORDER="0" BGCOLOR="#E0E0E0" WIDTH="100%" ><TR ><TD ><FONT COLOR="#000000" ><PRE CLASS="PROGRAMLISTING" > (No equivalent) </PRE ></FONT ></TD ></TR ></TABLE ></P ></TD ><TD WIDTH="50%" ALIGN="LEFT" VALIGN="TOP" ><P ><TABLE BORDER="0" BGCOLOR="#E0E0E0" WIDTH="100%" ><TR ><TD ><FONT COLOR="#000000" ><PRE CLASS="PROGRAMLISTING" > set my_list [lsort $my_list] </PRE ></FONT ></TD ></TR ></TABLE ></P ></TD ></TR ><TR ><TD COLSPAN="2" ALIGN="LEFT" VALIGN="TOP" >Sort a list. The sort can be reversed, or ordered by numeric value, etc. It can also order a list of sublists using an index element. Tcl contains a full suite of commands for manipulating the list data structure. See also <B CLASS="COMMAND" >lappend</B >, <B CLASS="COMMAND" >linsert</B >, <B CLASS="COMMAND" >lreplace</B >, <B CLASS="COMMAND" >lsearch</B >, <B CLASS="COMMAND" >concat</B >, <B CLASS="COMMAND" >split</B >, <B CLASS="COMMAND" >join</B >, etc. Tcl lists can also be nested arbitrarily, and the <B CLASS="COMMAND" >foreach</B > command has no trouble dealing with that.</TD ></TR ><TR ><TD WIDTH="50%" ALIGN="LEFT" VALIGN="TOP" ><P ><TABLE BORDER="0" BGCOLOR="#E0E0E0" WIDTH="100%" ><TR ><TD ><FONT COLOR="#000000" ><PRE CLASS="PROGRAMLISTING" >' requires a reference to ADO ' assume we have a connection called conn dim rs as new recordset rs.open "select id, name, age from people", _ my_connection, adOpenStatic ' processing code goes here rs.close set rs=nothing </PRE ></FONT ></TD ></TR ></TABLE ></P ></TD ><TD WIDTH="50%" ALIGN="LEFT" VALIGN="TOP" ><P ><TABLE BORDER="0" BGCOLOR="#E0E0E0" WIDTH="100%" ><TR ><TD ><FONT COLOR="#000000" ><PRE CLASS="PROGRAMLISTING" > package require tclodbc # assume we have a connection called conn conn read a "select id, name, age from people" # processing code goes here unset a ;# get rid of this array </PRE ></FONT ></TD ></TR ></TABLE ></P ></TD ></TR ><TR ><TD COLSPAN="2" ALIGN="LEFT" VALIGN="TOP" >Retrieve a simple array of data from a database table. In VB data is always retrieved in a recordset object. In Tcl it can be read into an array and/or a list, depending on your needs, and the database package in use.</TD ></TR ><TR ><TD WIDTH="50%" ALIGN="LEFT" VALIGN="TOP" ><P ><TABLE BORDER="0" BGCOLOR="#E0E0E0" WIDTH="100%" ><TR ><TD ><FONT COLOR="#000000" ><PRE CLASS="PROGRAMLISTING" > (No equivalent) </PRE ></FONT ></TD ></TR ></TABLE ></P ></TD ><TD WIDTH="50%" ALIGN="LEFT" VALIGN="TOP" ><P ><TABLE BORDER="0" BGCOLOR="#E0E0E0" WIDTH="100%" ><TR ><TD ><FONT COLOR="#000000" ><PRE CLASS="PROGRAMLISTING" >package require http set httpTrans [http::geturl $pageURL] upvar #0 $httpTrans state if {$state(status) == {ok}} { puts $state(body) } </PRE ></FONT ></TD ></TR ></TABLE ></P ></TD ></TR ><TR ><TD COLSPAN="2" ALIGN="LEFT" VALIGN="TOP" >Retrieve a document or file from a web server.</TD ></TR ><TR ><TD WIDTH="50%" ALIGN="LEFT" VALIGN="TOP" ><P ><TABLE BORDER="0" BGCOLOR="#E0E0E0" WIDTH="100%" ><TR ><TD ><FONT COLOR="#000000" ><PRE CLASS="PROGRAMLISTING" > (No equivalent) </PRE ></FONT ></TD ></TR ></TABLE ></P ></TD ><TD WIDTH="50%" ALIGN="LEFT" VALIGN="TOP" ><P ><TABLE BORDER="0" BGCOLOR="#E0E0E0" WIDTH="100%" ><TR ><TD ><FONT COLOR="#000000" ><PRE CLASS="PROGRAMLISTING" > regexp -all {src=['"](.+?)['"]} $body my_images </PRE ></FONT ></TD ></TR ></TABLE ></P ></TD ></TR ><TR ><TD COLSPAN="2" ALIGN="LEFT" VALIGN="TOP" >Complex string pattern search and extraction. Tcl uses <EM >regular expressions</EM > for this. <EM >Regular expression</EM > is a specification for a string pattern to be matched, similar in concept to the wildcard patterns used with VB's 'like' operator, except on steroids - a <EM >whole lot</EM > of steroids. Regular expressions are several times more powerful and flexible than 'like' patterns. For an informal introduction to regular expressions, see <A HREF="http://zez.org/article/articleprint/11" TARGET="_top" >http://zez.org/article/articleprint/11</A >. Tcl's regular expression parser is written in hand-optimized C code and is available to Tcl in several different commands (<B CLASS="COMMAND" >regexp</B >, <B CLASS="COMMAND" >regsub</B >, <B CLASS="COMMAND" >lsearch</B >, etc). The simpler, less powerful versions you're used to are also available for use in several different commands (<B CLASS="COMMAND" >glob</B >, <B CLASS="COMMAND" >string match</B >, <B CLASS="COMMAND" >lsearch</B >, and so on). This example would take 15 to 50 lines of VB code, depending on how robust and how tolerant of different situations it needs to be. In addition, that is some of the most difficult, error-prone, and slowest code that can be written in VB (voice of experience). Here, the code quickly obtains a list of the URLs of every image on an HTML page.</TD ></TR ><TR ><TD WIDTH="50%" ALIGN="LEFT" VALIGN="TOP" ><P ><TABLE BORDER="0" BGCOLOR="#E0E0E0" WIDTH="100%" ><TR ><TD ><FONT COLOR="#000000" ><PRE CLASS="PROGRAMLISTING" > (No equivalent) </PRE ></FONT ></TD ></TR ></TABLE ></P ></TD ><TD WIDTH="50%" ALIGN="LEFT" VALIGN="TOP" ><P ><TABLE BORDER="0" BGCOLOR="#E0E0E0" WIDTH="100%" ><TR ><TD ><FONT COLOR="#000000" ><PRE CLASS="PROGRAMLISTING" > set find {<tr>(.*?)<td>(.*?)</td><td>(.*?)</td><td>(.*?)</td>(.*?)</tr>} set replace {<tr>\1<td width=20%>\2</td><td width=40%>\3</td><td width=30%>\4</td>\5</tr>} regsub -all -nocase $exp $body $replace result puts $result </PRE ></FONT ></TD ></TR ></TABLE ></P ></TD ></TR ><TR ><TD COLSPAN="2" ALIGN="LEFT" VALIGN="TOP" >Complex string pattern search and substitution. Again, Tcl uses regular expressions. This example would take 40 lines of VB code or more, especially if it is logically organized with sufficient comments for a maintenance programmer to follow it. And again, it is some of the most difficult, error-prone, and slowest code that can be written in VB. Here the set of three cells in <EM >every row in the HTML body</EM > is altered systematically, while the contents of each cell is preserved.</TD ></TR ><TR ><TD WIDTH="50%" ALIGN="LEFT" VALIGN="TOP" ><P ><TABLE BORDER="0" BGCOLOR="#E0E0E0" WIDTH="100%" ><TR ><TD ><FONT COLOR="#000000" ><PRE CLASS="PROGRAMLISTING" > (No equivalent) </PRE ></FONT ></TD ></TR ></TABLE ></P ></TD ><TD WIDTH="50%" ALIGN="LEFT" VALIGN="TOP" ><P ><TABLE BORDER="0" BGCOLOR="#E0E0E0" WIDTH="100%" ><TR ><TD ><FONT COLOR="#000000" ><PRE CLASS="PROGRAMLISTING" > set handle [socket markhpc.dcisite.com 2000] set greeting [read $handle] close $handle </PRE ></FONT ></TD ></TR ></TABLE ></P ></TD ></TR ><TR ><TD COLSPAN="2" ALIGN="LEFT" VALIGN="TOP" >Make a connection to a network socket (act as a client) and retrieve data. The example assumes a server is listening on TCP port 2000 of the specified host.</TD ></TR ><TR ><TD WIDTH="50%" ALIGN="LEFT" VALIGN="TOP" ><P ><TABLE BORDER="0" BGCOLOR="#E0E0E0" WIDTH="100%" ><TR ><TD ><FONT COLOR="#000000" ><PRE CLASS="PROGRAMLISTING" > (No equivalent) </PRE ></FONT ></TD ></TR ></TABLE ></P ></TD ><TD WIDTH="50%" ALIGN="LEFT" VALIGN="TOP" ><P ><TABLE BORDER="0" BGCOLOR="#E0E0E0" WIDTH="100%" ><TR ><TD ><FONT COLOR="#000000" ><PRE CLASS="PROGRAMLISTING" > proc greeting {handle client_ip client_port} { puts $handle {Welcome to our greeting server!} close $handle } socket -server greeting 2000 </PRE ></FONT ></TD ></TR ></TABLE ></P ></TD ></TR ><TR ><TD COLSPAN="2" ALIGN="LEFT" VALIGN="TOP" >Implement a network server to answer the client shown above. This is the complete script. If you're using Wish (the Tcl windowing shell) this will run all day as shown. If you're using Tclsh (the console Tcl shell) add a <B CLASS="COMMAND" >vwait</B > command at the end, to make the program wait for events instead of terminating at the end of the script. That difference between the two shells is necessary and intentional, since Wish is event-driven by default, and Tclsh is not.</TD ></TR ></TBODY ></TABLE ></DIV ></DIV ><DIV CLASS="NAVFOOTER" ><HR ALIGN="LEFT" WIDTH="100%"><TABLE SUMMARY="Footer navigation table" WIDTH="100%" BORDER="0" CELLPADDING="0" CELLSPACING="0" ><TR ><TD WIDTH="33%" ALIGN="left" VALIGN="top" ><A HREF="intro.html" ACCESSKEY="P" >Prev</A ></TD ><TD WIDTH="34%" ALIGN="center" VALIGN="top" ><A HREF="index.html" ACCESSKEY="H" >Home</A ></TD ><TD WIDTH="33%" ALIGN="right" VALIGN="top" ><A HREF="more.html" ACCESSKEY="N" >Next</A ></TD ></TR ><TR ><TD WIDTH="33%" ALIGN="left" VALIGN="top" >Introduction</TD ><TD WIDTH="34%" ALIGN="center" VALIGN="top" > </TD ><TD WIDTH="33%" ALIGN="right" VALIGN="top" >Getting More Information</TD ></TR ></TABLE ></DIV ></BODY ></HTML >