Product Documentation

TDK 3.2 Documentation

ActiveState, a division of Sophos

TclChecker

The Tcl Dev Kit TclChecker helps you find errors in a Tcl script quickly before you run the script. Using the Tcl Dev Kit TclChecker can help you find problems in new scripts, in scripts from older versions of Tcl/Tk, or in scripts that you have ported from another operating system. You can use the Tcl Dev Kit TclChecker to assess the quality of a body of Tcl code or to quickly examine large Tcl files. Tcl Dev Kit TclChecker also warns about potential incompatibilities to help you upgrade applications to the latest releases of Tcl, Tk, and [incr Tcl].

Supported Tcl Versions

By default, the Tcl Dev Kit TclChecker verifies scripts written for Tcl version 8.4. You can use the Tcl Dev Kit TclChecker with the packages and versions of Tcl, Tk, and [incr Tcl] listed.

Packages and Version Numbers

Tcl

Tk

[incr Tcl]

Expect

TclX

7.3

3.6

1.5

n/a

n/a

7.4

4.0

2.0

n/a

n/a

7.5

4.1

2.1

n/a

n/a

7.6

4.2

2.2

n/a

n/a

8.0

8.0

3.0

5.28

8.0

8.1

8.1

n/a

5.29 or 5.30

8.1

8.2

8.2

3.1

5.31

8.2

8.3

8.3

3.1

5.32 - 5.38

8.2

8.4 (default)

8.4

n/a

n/a

n/a

Note: Expect command names that "collide" with command names in the Tcl/Tk core (for example, send) can cause the Tcl Dev Kit TclChecker to misinterpret an Expect script, causing it to report syntax errors. To avoid this, use the exp_ prefix for all such ambiguous commands (for example, use exp_send instead of send).

 Top

Using the Tcl Dev Kit TclChecker

The TclChecker is only available as a command-line tool. To check a file using the Tcl Dev Kit TclChecker, enter tclchecker.tcl (Windows) or tclchecker (Unix), followed by the file name you wish to check. For example:

tclchecker foo.tcl

If your code contains errors or warnings, the Tcl Dev Kit TclChecker provides feedback by default that looks similar to this:

You can specify multiple file names on the same line, for example:

tclchecker foo1.tcl foo2.tcl

To check all the files in a directory, use the asterisk ("*") with the .tcl file extension, for example:

tclchecker *.tcl

If you don't specify any files, tclchecker expects input from standard input.

For other examples of output, see Examples of Output from the Tcl Dev Kit TclChecker.

To change the font size displayed in the TclChecker, use Ctrl-plus to increase the font size or Ctrl-minus to decrease the displayed font size. If you are using Windows with a mouse wheel, you can alternatively press the Ctrl key and then rotate the mouse wheel to increase or decrease the font size displayed in the TclChecker.

 Top

One-Pass and Two-Pass Checking

By default, the Tcl Dev Kit TclChecker performs a two-pass scan of your scripts. The first pass accumulates information about user-defined procedures and user-defined [incr Tcl] classes. This information includes:

  • the number of arguments for procedure definitions and [incr Tcl] constructor definitions
  • the scope of procedures (namespace, protection level)
  • redefinition of procedures using the Tcl rename command
  • imports and exports of namespace procedures
  • class structures of inherited [incr Tcl] classes

The second pass uses this information to provide warnings and error messages concerning the usage of the user-defined procedures, including:

  • calling a procedure with the wrong number of arguments
  • calling an [incr Tcl] class constructor with the wrong number of arguments
  • redefining existing procedures, by either the rename command or by defining a procedure or class with and identical name
  • calling [incr Tcl] class procedures out of scope
  • calling class procedures with invalid permissions (private or protected)
  • variable usage (for example, attempting to use the value of an undefined variable or attempting to perform math operations on a list variable).

The Tcl Dev Kit TclChecker properly handles all variations of user-defined procedures in namespaces.

Note:The Tcl Dev Kit TclChecker does not currently check the following:

  • [incr Tcl] class methods
  • argument types passed to user-defined procedures
  • redefinition of built-in Tcl, Tk, or [incr Tcl] commands

Also, if you define a procedure multiple times, the Tcl Dev Kit TclChecker generates a usage error when calling that procedure only if the call fails to match any of procedure definitions. Because of the dynamic nature of procedure definition and redefinition, the Tcl Dev Kit TclChecker can't determine which argument list is currently valid for the given procedure call.

The Tcl Dev Kit TclChecker does not automatically scan scripts that are sourced by your script. Therefore, you must include on the command line all files that define user procedures and classes used by your script.

For a quicker but less comprehensive check of your scripts, you can use the tclchecker -onepass option to force the Tcl Dev Kit TclChecker to perform a one-pass scan of your scripts. A one-pass scan does not check for any of the potential errors or misuses of user-defined procedures and [incr Tcl] classes described above.

You can also use the tclchecker -verbose option to get a list of all commands used by the scripts you specify that are not defined in that collection of scripts. If you don't include the -verbose option, the Tcl Dev Kit TclChecker doesn't warn you about undefined procedures.

 Top

Tcl Dev Kit TclChecker Messages

The Tcl Dev Kit TclChecker examines your code and displays a message describing each error or potential mistake that it detects. Depending on the type of script that you are checking, you may want to limit the types of problems that it reports rather than see the entire output from the Tcl Dev Kit TclChecker.

Each message generated by the Tcl Dev Kit TclChecker lists the file and the line number where the error or warning occurred, a messageID, a description of the error or warning, and an error indicator, which is a caret ("^") that indicates the code fragment in which the error occurred. The messageID is the word in parentheses just after the file and line number information. It provides information about the type of problem that generated the error or warning, which are listed below. Using Tcl Dev Kit TclChecker you can specify types of errors and warning that you want to suppress, which allows you to focus to more strategic errors or warnings. The Tcl Dev Kit TclChecker provides suggestions, when possible, on ways to fix the problems that it indicates in the error or warning text.

You can limit output in the following ways:

  • Limiting errors and warnings by type: an error is either a parsing or syntax error, and warnings indicate possible problems with platform portability, upgrade, performance, or usage issues. Warnings indicate code fragments where there may be an error, but the code fragment may be appropriate in its context.
  • Specifying groups of messages to suppress, for example, you might want to suppress messages related to usage warnings.

Controlling Feedback on Errors and Warnings

Messages are grouped into two types of errors and four types of warnings.

Parsing Errors

The Tcl Dev Kit TclChecker generates a parsing error when it encounters commands that cannot be parsed by the Tcl parser, such as a missing curly brace or badly formed list. For example: the following code generates a parsing error because it is missing a quote at the end of the puts statement:

proc foo {} {
puts "hello
}

In cases like this, the Tcl Dev Kit TclChecker attempts to move past the procedure where the parsing error was found, and continue to check additional commands after the parsing error.

Syntax Errors

The Tcl Dev Kit TclChecker generates a syntax error when it encounters any errors that will cause your script to fail, such as the wrong number of arguments or invalid types or options. For example, the following code generates a syntax error is because the wrong number of arguments are supplied:

set x 3 45

Only commands defined in Tcl, Tk, or [incr Tcl] are checked for syntax errors.

Platform Portability Warnings

The Tcl Dev Kit TclChecker generates warnings when a command is used that may be nonportable between various platforms.

set file [open $dir/$file r]

In this example, the file join command should be used so that the correct directory and file separator is used, that is, "\" on Windows.

Suggestion for Upgrading

Upgrade warnings indicate features that have changed in a later version.

namespace foo {
variable bar 0
}

When [incr Tcl] was upgraded to 3.0, it inherited the Tcl namespace command. The syntax of defining a namespace has changed from older versions of [incr Tcl] because of this. With earlier versions of [incr Tcl], correct usage was:

namespace foo {body}

With [incr Tcl] 3.0 and later, correct usage is shown below:

namespace eval foo {body}

Performance Warnings

The Tcl Dev Kit TclChecker generates a warning when a performance-optimization opportunity is detected. For example: if your code included:

set x [expr $x * $y]

it would generate a performance warning because performance is improved with curly braces, as shown below:

set x [expr {$x * $y}]

Usage Warnings

The Tcl Dev Kit TclChecker generates a warning when a command is used in a manner that is possibly incorrect but is still syntactically legal. For example, the incr command expects a value and not a reference below:

incr $counter

Warning and Error Flags

You can control which types of errors and warnings the Tcl Dev Kit TclChecker lists by specifying one of the -W flags on the command line.

Flag

Description

-W1

Display parsing and syntax errors.

-W2

Display parsing and syntax errors, and usage warnings.

-W3

Display parsing and syntax errors, portability warnings, upgrade warnings, performance warnings, and usage warnings.

-Wall

Displays all messages and errors. This is the default.

As an example, the first time you check your script you might want to display only errors but not warnings. You might first run the Tcl Dev Kit TclChecker with the -W1 flag, which only displays parsing and syntax errors, but does not display any warnings. After examining the output from running with the -W1 flag and fixing any errors that were reported, you might run with the -W2 flag to see a variety of additional warnings.

Suppressing Specific Messages

Each warning or error message has an associated messageID. You can filter out the display specific warnings or errors by specifying -suppress to prevent that type of messageID from being displayed. You might want to filter out certain messages because they point out items that do not apply to the script that you are checking, for example: if you are porting a script to only one platform, you do not care whether your script has portability issues.

In the following example, the messageID is "nonPortCmd":

foo:tcl:53 (nonPortCmd) use of non-portable command
registry values $key
^

You can suppress this type of message by specifying -suppress nonPortCmd on the command line, for example:

tclchecker -suppress nonPortcmd foo.tcl

Tip: You can suppress multiple messageID types at the same time by specifying -suppress with the multiple instances of messageIDs in quotation marks, for example:

tclchecker -suppress "nonLiteralExpr badOption" foo.tcl

You can also specify -suppress with the messageID for each instance of the message ID that you want to filter, for example:

tclchecker -suppress nonLiteralExpr -suppress badOption foo.tcl

For a complete list of all the messageIDs, see Tcl Dev Kit TclChecker Messages.

 Top

Examples of Output from the Tcl Dev Kit TclChecker

To provide examples of the Tcl Dev Kit TclChecker output, here is the sample script, foo.tcl, that is checked in the examples that follow:

set $y 3
set x [expr $y + 5]
set x y z

if {$x > 6}
{
puts out "world"
}

proc foo {args bar} {
puts "hello, world"
}

proc p {{a 0} b} {
puts -nonew "hello"
}

Specifying Verbose Feedback

You can specify the -verbose argument when you run the Tcl Dev Kit TclChecker. When you specify -verbose, the Tcl Dev Kit TclChecker displays the error information in three lines and the version and summary information when the Tcl Dev Kit TclChecker exits, for example:

tclchecker -verbose foo.tcl

The feedback from the command line with -verbose specified looks similar to this:

scanning: C:/Tcl/jen/foo.tcl
checking: C:/Tcl/jen/foo.tcl
foo.tcl:6 (warnVarRef) variable reference used where variable name expected
set $y 3
    ^
foo.tcl:7 (warnExpr) use curly braces to avoid double substitution
expr $y + 5
     ^
foo.tcl:7 (undefinedVar) use of undefined variable "y"
expr $y + 5
      ^
foo.tcl:7 (warnExpr) use curly braces to avoid double substitution
expr $y + 5
     ^
foo.tcl:7 (undefinedVar) use of undefined variable "y"
expr $y + 5
      ^
foo.tcl:8 (numArgs) wrong # args
set x y z
^
foo.tcl:10 (noScript) missing a script after "if"
if {$x > 6}
        ^
foo.tcl:11 (warnUndefProc) undefined procedure:
puts out "world"

{
^
foo.tcl:15 (argAfterArgs) argument specified after "args"
proc foo {args bar} {
         ^
foo.tcl:19 (nonDefAfterDef) non-default arg specified after default
proc p {{a 0} b} {
       ^

Packages Checked | Version
-----------------|--------
blend              1.2
tcl                8.4
tk                 8.4
expect             5.38
[incr Tcl]         3.1
oratcl             2.5
sybtcl             3.0
tclCom             1.0
tclDomPro          1.0
tclX               8.2
xmlAct             1.0
xmlGen             1.0
xmlServer          1.0

Number of Errors:   4
Number of Warnings: 6

Commands that were called but never defined:
--------------------------------------------

puts out "world"

Specifying Quiet Feedback

You can specify the -quiet argument when you run the Tcl Dev Kit TclChecker. When you specify -quiet, the Tcl Dev Kit TclChecker displays the basic error information on one line with the messageID, instead of the three-line output that includes the code body and the error indicator, for example:

tclchecker -quiet foo.tcl

The output with the -quiet argument appears as follows:

foo.tcl:6 (warnVarRef) variable reference used where variable name expected
foo.tcl:7 (warnExpr) use curly braces to avoid double substitution
foo.tcl:7 (undefinedVar) use of undefined variable "y"
foo.tcl:7 (warnExpr) use curly braces to avoid double substitution
foo.tcl:7 (undefinedVar) use of undefined variable "y"
foo.tcl:8 (numArgs) wrong # args
foo.tcl:10 (noScript) missing a script after "if"
foo.tcl:11 (warnUndefProc) undefined procedure:
puts out "world"

foo.tcl:15 (argAfterArgs) argument specified after "args"
foo.tcl:19 (nonDefAfterDef) non-default arg specified after default

Specifying the Tcl or Tk Version

To specify a version of Tcl or Tk other than the default, use the -use command line switch. For example, to check a file written for Tcl7.5 and Tk4.1, enter:

tclchecker -use "Tcl7.5" -use "Tk4.1" foo.tcl

Valid -use arguments are package names followed by a version number. Supported package names are "Tcl", "Tk", "Expect", "ITcl", "Tclx", and other package for which a ".pcx" file is available. Option specifications for unsupported packages are ignored. Packages and Version Numbers lists the versions supported for each package. If you do not specify a version for a package, the Tcl Dev Kit TclChecker uses the first version of the package it locates.

When specifying older versions of Tcl and any extension (including Tk), the versions of Tcl and any specified extension must be compatible, as listed in Packages and Version Numbers. The following example includes incompatible versions and should not be used:

tclchecker -use "Tcl7.5" -use "Tk4.0" foo.tcl

The correct version pair is:

tclchecker -use "Tcl7.5" -use "Tk4.1" foo.tcl

Overriding Specified Packages

The -use option allows a package version specification, and overrides package require statements in source Tcl code. For example, -use Tk4.1 will scan against version 4.1 of Tk, even if the package require statement specifies a different version of Tk.

Note: The -use command is ignored if a package require statement does not exist. The checker does not load packages it does not require.

Error Checking

The command line in the following example requests -W1 error checking, which includes only parsing and syntax errors:

tclchecker -W1 foo.tcl

The feedback from the command line with -W1 specified looks similar to this:

scanning: C:/Tcl/jen/foo.tcl
checking: C:/Tcl/jen/foo.tcl
foo.tcl:8 (numArgs) wrong # args
set x y z
^
foo.tcl:10 (noScript) missing a script after "if"
if {$x > 6}
              ^
foo.tcl:15 (argAfterArgs) argument specified after "args"
proc foo {args bar} {
         ^
foo.tcl:19 (nonDefAfterDef) non-default arg specified after default
proc p {{a 0} b} {
       ^

Error and Warning Checking

The command line in following example requests -W2 error checking, which includes parsing errors, syntax errors, upgrade warnings, and performance warnings.

tclchecker -W2 foo.tcl

The feedback from the command line with -W2 specified looks similar to this:


scanning: C:/Tcl/jen/foo.tcl
checking: C:/Tcl/jen/foo.tcl
foo.tcl:8 (numArgs) wrong # args
set x y z
^
foo.tcl:10 (noScript) missing a script after "if"
if {$x > 6}
           ^
foo.tcl:15 (argAfterArgs) argument specified after "args"
proc foo {args bar} {
         ^
foo.tcl:19 (nonDefAfterDef) non-default arg specified after default
proc p {{a 0} b} {
       ^

Checking for All Warnings and Errors

The command line in following example requests -W3 error checking, which includes parsing errors, syntax errors, upgrade, portability, and performance warnings.

tclchecker -W3 foo.tcl

The feedback from the command line with -W3 specified looks similar to this:


scanning: C:/Tcl/jen/foo.tcl
checking: C:/Tcl/jen/foo.tcl
foo.tcl:6 (warnVarRef) variable reference used where variable name expected
set $y 3
    ^
foo.tcl:7 (warnExpr) use curly braces to avoid double substitution
expr $y + 5
     ^
foo.tcl:7 (undefinedVar) use of undefined variable "y"
expr $y + 5
      ^
foo.tcl:7 (warnExpr) use curly braces to avoid double substitution
expr $y + 5
     ^
foo.tcl:7 (undefinedVar) use of undefined variable "y"
expr $y + 5
      ^
foo.tcl:8 (numArgs) wrong # args
set x y z
^
foo.tcl:10 (noScript) missing a script after "if"
if {$x > 6}
           ^
foo.tcl:11 (warnUndefProc) undefined procedure:
puts out "world"

{
^
foo.tcl:15 (argAfterArgs) argument specified after "args"
proc foo {args bar} {
         ^
foo.tcl:19 (nonDefAfterDef) non-default arg specified after default
proc p {{a 0} b} {
       ^

 Top

Component Message List

Error Messages from message.tcl

Message ID Category Message String
argAfterArgs Error Argument specified after "args"
An argument has been specified after the args keyword in a procedure argument list. The args argument is treated like a normal parameter and does not collect the remaining parameters into a single list.
argsNotDefault Error "args" cannot be defaulted
The args keyword cannot be initialized to contain a default value. Although the Tcl interpreter does not complain about this usage, the default value is ignored.
arrayReadAsScalar Error Array variable "variable" read as if a scalar
You cannot assign an array variable to a scalar variable. The Tcl Dev Kit TclChecker is aware of the internal variables tcl_platform and Tk::priv, and will generate this error when you attempt to assign these variables to a scalar.
badArrayIndex Error invalid array index "index"
This error occurs when you try to read from the tcl_platform internal variable with an invalid index key. The tcl_platform variable is initialized at run-time by the system definition, and should not be manually altered.
badBoolean Error Invalid Boolean value
The command expects the string to specify a Boolean value. The string can be "1", "0", "true", "false", "yes", "no", "on", or "off" in any unique abbreviation and case.
badByteNum Error Invalid number, should be between 0 and 255
The type should be a integer between 0 and 255.
badColorFormat Error Invalid color name
The command expects the string to specify a color value. The string can be any of the following forms:
  • colorname
  • #RGB
  • #RRGGBB
  • #RRRGGGBBB
  • #RRRRGGGGBBBB

colorname can be any of the valid textual names for a color defined in the server's color database file, such as "red" or "PeachPuff". If the color name is not a Tcl defined color, a warning is flagged stating that the color may not be portable across all platforms; see nonPortColor. The RGB characters represent hexadecimal digits that specify the red, green, and blue intensities of the color.

badCursor Error Invalid cursor spec
The command expects the string to specify a cursor to use. The string can take any of the following forms:
  • ""
  • name
  • name fgColor
  • @sourceFile fgColor
  • name fgColor bgColor
  • @sourceFile maskFile fgColor bgColor

If the name form is used, and the name of the cursor is not defined on all platforms, a warning is flagged stating that the cursor is not portable; see nonPortCursor. None of the forms that specify a color or multiple files are portable across all systems; they are flagged as being non-portable; nonPortCmd.

badFloat Error Invalid floating-point value
The command expects the string to consist of a floating-point number, which is: white space; a sign; a sequence of digits; a decimal point; a sequence of digits; the letter "e"; and a signed decimal exponent. Any of the fields may be omitted, except that the digits either before or after the decimal point must be present and if the "e" is present then it must be followed by the exponent number.
badIndex Error Invalid index: should be integer or "end"
The command expects the string to specify an index value. The string can be an integer or "end".
badIndexExpr Error Invalid index: should be integer or "end" or "end-integer"
When reading an index, you must specify the exact integer position, or the position relative to the end of the index using the "end" or "end-index_number" strings.
badInt Error Invalid integer
The command expects the string to specify an integer value. The string can be optionally signed and optionally preceded by white space. If the first two characters of the string are "0x" then string is expected to be in hexadecimal form; if the first character of string is "0" then the string is expected to be in octal form; otherwise, the string is expected to be in decimal form.
badKey Error Invalid keyword "key " must be: words
The command expects the key string to be a key that matches one of the strings in the options list.
badLevel Error Invalid level
The command expects the string to be an integer or a "#" character followed by an integer.
badList Error Invalid list: error-info
The command expects the string to be a valid Tcl list. The reason the string is not a valid Tcl list is displayed in the message associated with the error.
badListLength Error Invalid list length: Expected % x == y
The command expects the string to be a valid Tcl list with a length n satisfying the condition "n % x == y". For example: "n % 2 == 0" is the condition for lists of even length.
badMathOp Error Invalid expr operator: "operator"
When working with mathematical expressions, you must use valid operators for the "expr" command. See "expr" in the Tcl Commands Manual section of the ActiveTcl User Guide.
badMode Error Access mode must include either RDONLY, WRONLY, or RDWR
When specifying access modes for a Tcl channel, at least one of the three read-write access modes (RDONLY, WRONLY, or RDWR) must be specified with optional modifiers (APPEND, CREAT, EXCL, NOCTTY, NONBLOCK or TRUNC).
badNatNum Error Invalid value "value": must be an integer > 0
The command expects the string to specify an integer greater than zero. The string can be any non-negative integer.
badOption Error Invalid option "option" must be: options
The command expects the option string to be an option that matches one of the strings in options.
badPixel Error Invalid pixel value
The command expects the string to specify a pixel value. The string must be an integer pixel or floating-point millimeter, optionally followed by one of the following characters: "c", "i", "m", or "p".
badResource Error Invalid resource name
The command expects the string to specify a resource value. If the string length is not four characters, an error is flagged.
badSwitch Error Invalid switch: "switch"
The command expects the string to be a switch that matches one of the strings in list of switch options.
badVersion Error Invalid version number
The command expects a list of strings that specifies a package version. A valid package version string is any number of integers separated by periods ("."), for example, "1.2.3".
badWholeNum Error Bad value "value": must be a non-negative integer
The command expects the string to specify a whole value. The string can be any non-negative integer.
internalError Error Internal error: error
This message indicates a bug in the Tcl Dev Kit TclChecker. Please file a bug report, including the steps necessary to reproduce the error, at http://bugs.activestate.com/Tcl Dev Kit.
invalidUsage Upgrade Error Invalid usage, use "foo" instead
All functions internal to the Tk binding have been moved to the "Tk::" namespace and have been made private. In Tcl 8.4 mode, this error reports use of a command that is now invalid.
mismatchOptions Error The specified options cannot be used in tandem
Two or more options were specified that cannot be used at the same time. The command should be re-written to use only one of the switches. This commonly occurs when an overloaded command performs completely different operations based on the switches.
noExpr Error Missing an expression
Similar to the numArgs message. The Tcl Dev Kit TclChecker flags this error message when an expression is missing in an if statement.
nonDefAfterDef Error Non-default arg specified after default
A non-defaulted argument has been specified after a defaulted argument in a procedure argument list. Although the Tcl interpreter does not complain about this usage, the default values are ignored.
nonPortChannel Non-Portable Warning Use of a non-portable file descriptor, use "file" instead
A channel was specified that is not supported on all platforms. In most cases, this is when "file0", "file1", or "file2" is used instead of "stdin", "stdout", or "stderr".
nonPortCmd Non-Portable Warning Non-portable command
A command was specified that is not supported on all platforms.
nonPortColor Non-Portable Warning Non-portable color name
A color was specified that is not supported on all platforms.
nonPortCursor Non-Portable Warning Non-portable cursor usage
A cursor was specified that is not supported on all platforms.
nonPortFile Non-Portable Warning Use of non-portable file name, use "file join"
A file name was specified that is not supported on all platforms. This warning is flagged, then the string is a combination of words, variables, or commands separated by system-specific file separators (for example, "$dir\$file"). Use the file join command to add the system-specific file separators (for example, "[file join $dir $file]").
nonPortOption Non-Portable Warning Use of non-portable option
An option was specified that is not supported on all platforms. Generally, the option has no effect on the systems that do not support this option.
nonPortVar Non-Portable Warning Use of non-portable variable
A variable was used that is not supported on all platforms. In most cases, this is when the tcl_precision variable is used.
nonPublicVar Non-Public Warning use of private variable
This error indicates that the program is trying to use the contents of the Tk::priv variable. This variable is internal and should not be used.
noScript Error Missing a script after "control"
Similar to the numArgs message. The Tcl Dev Kit TclChecker flags this error message when an expression is missing in an if statement.
noSwitchArg Error Missing argument for switch switch
The command was called with a switch that expected an argument. If no argument was given for the switch, this error is flagged.
numArgs Error Wrong # args
An incorrect number of arguments were specified for a command. Due to the dynamic nature of Tcl, this error might be flagged unnecessarily. For example, if the command is called within an eval body with variables that will expand to be multiple arguments. The Tcl Dev Kit TclChecker sees only the one argument, but this may expand to match the required number of arguments when the command is evaluated.
numListElts Error Wrong # of list elements
Some commands expect lists with a fixed number of elements. This error indicates that an incorrect number of elements has been specified. See the documentation for the specific command in the ActiveTcl User Guide.
obsoleteCmd Error Deprecated usage, use "command" instead
The specified command, option or variable does not exist and is no longer supported in the version of the system you are checking. Use the suggested alternative command, option, or variable to upgrade the script.
parse Error Parse error: error-info
The Tcl Dev Kit TclChecker could not parse the script completely due to a parsing error. The reason for the parsing error is displayed in the message associated with the error.
procNumArgs Error Wrong # args for the user-defined proc: procName
You are using the wrong number of arguments to call the Tcl procedure procName . Compare the number of arguments used to call the procedure to the number of arguments in the definition of procName.
tooManyFieldArg Error Too many fields in argument specifier
A defaulted procedure argument has been specified with multiple values. An argument can have only one default value. If the value is to be a list, quotes or curly braces must be used.
warnBehaviour Upgrade Warning Behaviour has changed
This warning indicates use of a variable whose behaviour has changed between the current Tcl version and previous versions.
warnBehaviourCmd Upgrade Warning Behaviour of command has changed
This warning indicates use of a command whose behaviour has changed between the current Tcl version and previous versions.
warnDeprecated Upgrade Warning Deprecated usage, use "command" instead
The specified command, option or variable does not exist and is no longer supported in the version of the system you are checking. Use the suggested alternative command, option or variable to upgrade the script.
warnExportPat Warning Export patterns should not be qualified
Each export pattern can contain glob -style special characters, but it must not include any namespace qualifiers. That is, the pattern can only specify commands in the current (exporting) namespace.
warnExpr Performance Warning Use curly braces to avoid double substitution
The expr command performs two levels of substitution on all expressions that are not inside curly braces. To avoid the second substitution, and to improve the performance of the command, place the expression inside curly braces.

There are cases where the second level of substitution is required and this warning will not apply. The Tcl Dev Kit TclChecker does not discern between these cases.

warnExtraClose Usage Warning Unmatched closing character
A close bracket or close brace without a matching open bracket or open brace was detected. This frequently indicates an error introduced when a subcommand or script is deleted without deleting the final close brace or bracket.
warnGlobalNsNonsense Warning Global into a namespace is undefined
Using the global command within a namespace eval is an undefined operation.
warnGlobalVarColl Warning Namespace variable "foo" may collide with global variable of same name
When writing to the variable via set it is undetermined if a global or namespace variable is created.
warnIfKeyword Warning Deprecated usage, use else or elseif
When using the if command, it is legal to omit the else and elseif keywords. However, omission of these keywords tends to produce error-prone code; thus, a warning is flagged.
warnInternalCmd Warning Usage of internal command, may change without notice
This message indicates that you are using commands internal to an extension. It is safer to use public APIs wherever possible.
warnNamespacePat Warning glob chars in wrong portion of pattern
Each namespace pattern is qualified with the name of an exporting namespace and may have glob -style special characters in the command name at the end of the qualified name. The warning is flagged if glob characters appears in a namespace name.
warnPattern Warning Possible unexpected substitution in pattern
Glob patterns use brackets to specify a list of characters to match. If brackets are used and the word is not properly quoted, Tcl will interpret this as a subcommand to be evaluated, rather than a pattern. This warning is flagged to avoid possible usage errors of this nature.
warnReadonlyVar Warning Variable is considered read-only
The Tcl Dev Kit TclChecker is hard-coded to recognize certain variables as internal to Tcl/Tk. The value of these variables should not be changed. These variables include:
  • tcl_platform (Tcl)
  • tkPriv (Tk 8.3)
  • tk::Priv (Tk 8.4)
warnRedefine Usage Warning userProc1 redefines userProc2 in file fileName on line lineNum
A procedure or class is being defined, imported, inherited, or renamed into a scope where a procedure or class of the same name already exists.
warnReserved Upgrade Warning Keyword is reserved for use in version
When checking scripts using older versions of Tcl, Tk or [incr Tcl], this warning is flagged if a command is used that does not exist in the systems that you are checking against, but does exist in later versions. This warning helps to prevent scripts from defining commands that will eventually collide with later versions.
warnShadowVar Warning Shadowing a previous definition
This usage of the variable may hide or kill a previous definition of the same name.
warnUndefinedUpvar Warning Upvar'd variable "foo" missing in caller scope "proc"
The named procedure (in)directly calls the current scope, but is not defining the variable expected by the upvar.
warnUndefinedVar Warning Use of undefined variable: "foo"
The named variable is not known in the current scope.
warnUndefFunc Warning Unknown math function: "function"
The specified function is not defined as part of the "expr" command. See the "expr" command reference in the ActiveTcl User Guide for a list of valid functions.
warnUndefProc Warning The procedure was called but was never defined
The procedure was not defined in any of the files that were specified on the command line of the current invocation of the Tcl Dev Kit TclChecker. The procedure may get defined dynamically or in a file that was not specified on the Tcl Dev Kit TclChecker command line. This warning is triggered only for the first use of the undefined procedure in the files being checked.
warnUnsupported Error Unsupported command, option or variable: use command
The specified command, option or variable still exists but is no longer supported. Use the suggested alternative command, option, or variable to upgrade the script.
warnUpvarNsNonsense Error Non-global upvar into a namespace is undefined
You cannot import procedure-local variables into a namespace scope.
warnVarRef Warning Variable reference used where variable name expected
Some commands expect a variable name for an argument, for example, incr . If the argument is a variable reference, this warning is flagged to report possible usage errors.
winAlpha Error Window name cannot begin with a capital letter
The window name for any Tcl widget cannot begin with a capital letter.
winBeginDot Error Window name must begin with "."
The path name for any Tcl widget must begin with a period (".")
winNotNull Error Window name cannot be an empty string
A window name or path cannot be an empty string.

Error Messages from blt.tcl

Message ID Category Message String
blt::badIntRange Error Invalid integer range, should be an integer between "value1" and "value2"
In some cases, legal integer ranges are defined as part of the command. This error indicates that an integer value outside the legal range has been used.
blt::badSignal Error Invalid mnemonic signal
The bgexec command has an option "-killsignal" (Unix only), which accepts a valid mnemonic value. See the blt man pages for command specifications.
blt::badSignalInt Error Invalid signal integer, should be between 1 and 32
The bgexec command has an option "-killsignal" (Unix only), which accepts a valid signal integer value. See the blt man pages for command specifications.

Error Messages from coreTcl.tcl

Message ID Category Message String
coreTcl::badBinaryFmt Error Bad format for binary command: "command"
This error indicates that the string provided for the binary command's format switch is invalid. See the documentation for the "binary" command in the ActiveTcl User Guide.
coreTcl::badCharMap Error String map list should have an even number of elements
The map list must have an even number of elements.
coreTcl::badFormatFmt Error Bad format for format command: "command"
This error indicates that the string provided for the format or scan command's format switch is invalid. See the documentation for the "format" or "scan" command in the ActiveTcl User Guide.
coreTcl::badRegexp Error Bad regexp pattern: "pattern"
The specified regular expression is not valid.
coreTcl::badSerialMode Error Bad serial mode
When using the fconfigure command, if you are using the -mode switch, you must specify a valid -mode string. See "fconfigure" in the ActiveTcl User Guide for information about command switches.
coreTcl::badTraceOp Error Bad operation operation should be one or more of rwu
The command expects the trace operation string to be one or more of the following characters: "r", "w", or "u".
coreTcl::errBadBrktExp Error The bracket expression is missing a close bracket
The bracket expression is missing a close bracket. Common errors of this type are caused when the closing bracket is interpreted as a character to match on. For example [] and [^] will generate this error because the close bracket is interpreted as a character to match, or not match, respectively. The correct expressions would be: []] and [^]].
coreTcl::serverAndPort Error Option -myport is not valid for server sockets
The socket command specified the -server option and the -myport option on the same command line. These are conflicting options and cannot be used together.
coreTcl::socketArgOpt Error No argument given for "option" option
This error message is not used.
coreTcl::socketAsync Error Cannot use -server option and -async option
The socket command specified the -server option and the -async option on the same command line. These are conflicting options and cannot be used together.
coreTcl::socketBadOpt Error Invalid option "option", must be -async, -myaddr, -myport or -server
This error message is not used.
coreTcl::socketServer Error Cannot use -async option for server sockets
The socket command specified the -async option and the -server option on the same command line. These are conflicting options and cannot be used together.
coreTcl::warnAIPattern Upgrade Warning auto_import pattern is used to restrict loading in later versions of Tcl
When using the auto_import command, be aware of functionality changes between Tcl 8.4 and earlier versions.
coreTcl::warnEscapeChar Upgrade Warning "\<char>" is a valid escape sequence in later versions of Tcl.
The new regular expression package introduced in Tcl 8.1 added many new special character sequences, called "escape characters." When upgrading to 8.1 or later, the escape characters will change the semantics of the expression. To maintain the behavior of previous versions of Tcl, add another backslash before the character. (This warning is displayed only if you specify the -use option with Tcl 8.0 or earlier.)
coreTcl::warnMemoryCmd Warning Memory is debugging command
The "memory" command is only available when the core is compiled using the TCL_MEM_DEBUG mode.
coreTcl::warnNotSpecial Upgrade Warning "\<char>" has no meaning. Did you mean "\\<char>" or "<char>"?
The backslash character is used to quote special characters in an expression so their literal value can be used. The character following the backslash in this expression has no affect on the character. Consider simplifying the expression.
coreTcl::warnQuoteChar Upgrade Warning "\" in bracket expressions are treated as quotes
The new regular expression package introduced in Tcl 8.1 changed the semantics of the backslash character inside of bracket expressions. Previously they were treated as literal characters. Now they are treated as a quote character. To maintain the behavior of previous versions of Tcl, add another backslash before the existing backslash (for example, [*-\] becomes [*-\\]). (This warning is displayed only if you specify the -use option with Tcl 8.0 or earlier.)
coreTcl::warnY2K Warning %y generates a year without a century. consider using %Y to avoid Y2K errors
To avoid possible Y2K errors, use the "%Y" field descriptor to generate years with centuries (for example, "1999" instead of "99").

Error Messages from coreTk.tcl

Message ID Category Message String
coreTk::badBindSubst Error Bind script contains unknown -placeholders
This error indicates that a placeholder character specified with the "bind" command is invalid. Refer to the ActiveTcl User Guide for "bind" command specifications.
coreTk::badColormap Error Invalid colormap "colormap": must be "new" or a window name
The command expects the string to specify a colormap to use. If the string is "new", a new colormap is created. Otherwise, the string should be a valid window path name.
coreTk::badEvent Error Invalid event type or keysym
The command expects the string to specify an event type. If the string is not composed of a valid event and one or more related modifiers, an error is reported.
coreTk::badGeometry Error Invalid geometry specifier
The command expects the string to specify a geometry value. The string must have one of the following forms:
  • W x H
  • ± X x ± Y
  • W x H ± X x ± Y

...where the width (W) and height (H) values are positive integers, and the X (X) and Y (Y) coordinates are positive or negative integers.

coreTk::badGridMaster Error Cannot determine master window
The grid command flags an error if a valid window name was never specified in the command.
coreTk::badGridRel Error Must specify window before shortcut
When using the relative placement shortcuts in the grid command (that is, "-", "x", or "^") an error is reported if the span column shortcut ("-") is used immediately after one of the other shortcuts.
coreTk::badPalette Error Invalid palette spec
The command expects the string to be a valid palette specification. The palette string may be either a single decimal number, specifying the number of shades of gray to use, or three decimal numbers separated by slashes ("/"), specifying the number of shades of red, green and blue to use, respectively.
coreTk::badPriority Error Invalid priority keyword or value
The command expects the string to specify a priority value. The string must contain one of the following values: "widgetDefault", "startupFile", "userDefault", "interactive", or an integer between 0 and 100.
coreTk::badScreen Error Invalid screen value
The command expects the string to specify a screen value. The string must have the following form:
?name ?:display ?.screen ?

...where name is any string and display and screen are integers.

coreTk::badSticky Error Invalid stickiness value: should be zero or more of nswe
The grid command expects the string to specify valid sticky coordinates. The string can contain any combination of the following characters: "n", "s", "e". or "w".
coreTk::badTab Error Invalid tab list
The command expects a list of strings that define tab stops. If the Tcl interpreter cannot parse the list, an error is flagged. The tab list must consist of a list of screen distances giving the positions of the tab stops. Each position can optionally be followed in the next list element by one of the keywords "left", "right", "center", or "numeric", which specifies how to justify text relative to the tab stop.
coreTk::badTabJust Error Invalid tab justification "tab-item": must be left right center or numeric
The command expects the justification string to be one of the following: "left", "right", "center", or "numeric".
coreTk::badVirtual Error Virtual event is badly formed
The command expects the string to specify a virtual event. The string must have the following form:
<<word>>

...where word is any non-empty string.

coreTk::badVisual Error Invalid visual
The command expects the string to specify a visual. The string can have the following form:
  • class depth
  • default
  • windowName
  • number
  • best ?depth ?

The class string must be one of "directcolor", "grayscale", "pseudocolor", "staticcolor", "staticgray", or "truecolor", or any unique abbreviation. The depth value must be a valid integer.

coreTk::badVisualDepth Error Invalid visual depth
If the depth specified by a visual string is not a valid integer, then this error is flagged.
coreTk::noEvent Error No events specified in binding
coreTk::nonPortBitmap Non-Portable Warning Use of non-portable bitmap
A bitmap was specified that is not supported on all platforms.
coreTk::nonPortKeysym Non-Portable Warning Use of non-portable keysym
A keysym was specified that is not supported on all platforms.
The command expects an event but could not find one while parsing the command line.
coreTk::noVirtual Error Virtual event not allowed in definition of another virtual event
Virtual events are not allowed in event sequences. If a virtual event (any event that begins with "<<" and ends with ">>") is found, then this message is flagged.
coreTk::warnConsoleCmd Warning Usage of internal console command, may change without notice
The "console" command is internal; its functionality may change between Tcl versions.
coreTcl::warnTkCmd Warning Usage of internal tk command, may change without notice
The "tk" command is internal; its functionality may change between Tcl versions.

Error Messages from expect.tcl

Message ID Category Message String
expect::warnAmbiguous Usage Warning Ambiguous switch, use delimiter to avoid conflicts
The word being checked starts with a "-" but does not match any of the known switches. Use delimiter to explicitly declare the end of the switch pattern.

Error Messages from incrTcl.tcl

Message ID Category Message String
incrTcl::badMemberName Error Missing class specifier for body declaration
An [incr Tcl] member name was not correctly qualified. When defining the body for a class procedure, class method, or class variable, it is necessary to reference the procedure or variable with the fully qualified name.
incrTcl::classNumArgs Error Wrong # args for class constructor: className
The wrong number of arguments are being used to instantiate the [incr Tcl] class className . Compare the number of arguments used to instantiate the class to the number of arguments in the constructor defined by className.
incrTcl::classOnly Error Command "command" only defined in class body
The specified command is only valid in the context of an [incr Tcl] class body.
incrTcl::nsOnly Error Command "command" only defined in namespace body
The specified command is only valid in the context of an [incr Tcl] namespace body.
incrTcl::nsOrClassOnly Error Command "command" only defined in class or namespace body
The specified command is only valid in the context of an [incr Tcl] class or namespace body.
incrTcl::procOutScope Error Proc only defined in class className
An [incr Tcl] class procedure is being called from the wrong scope, or is improperly qualified. This commonly occurs when calling inherited procedures.
incrTcl::procProtected Error Calling protectionLevel proc: procName
You are calling an inaccessible procedure with a protection level of protectionLevel. This error is flagged when the procedure being called does not have permission to call this procedure.
incrTcl::warnUnsupported Error Command deprecated and is no longer valid
The incrTcl command is not supported in the current version of Tcl.

Error Messages from oratcl.pcx

Message ID Category Message String
oratcl::badConnectStr Error Invalid Oracle connect string
Refer to the "oratcl" manpages or the Oracle documentation for information about connect string syntax.
oratcl::badOnOff Error Invalid "on" or "off" value
The "oraautocom" command requires a literal "on" or "off" value. Refer to the "oratcl" manpages or the Oracle documentation for more information.
oratcl::badSubstChar Error Invalid Oracle substitution character
An invalid substitution character has been passed with the "orafetch" command. Refer to the "oratcl" manpages or the Oracle documentation for more information.
oratcl::missingColon Error varName must be preceded by ':'
Variable names must begin with colons. Refer to the "oratcl" manpages or the Oracle documentation for more information.

Error Messages from tclX.tcl

Message ID Category Message String
tclX::badLIndex Error Invalid infants: should be integer, "len" or "end"
The command expects the string to specify an index value. The string can be an integer, "len", or "end".
tclX::badProfileOpt Error Option "option" not valid when turning off profiling
Using the TclX profiling tools, option is not valid. Most likely the option is valid only when turning on profiling.
tclX::badTlibFile Error The filename must have a ".tlib" suffix
The command expected a filename with a .tlib suffix. The word should be changed to match the pattern filename.tlib.
tclX::optionRequired Error Expected option1, got "option2"
A specific option was expected, but the following option was found.

Error Messages from xmlAct.pcx

Message ID Category Message String
xmlAct::badXMLaction Error Invalid action, must be start children, end, or all

 Top

TclChecker Definition Files (PCX Files)

Overview

This section provides a general overview on TclChecker definition files, including how to name and load them for use with the tclchecker tool. Later, this document provides information for building custom TclChecker definition files using the PCX API.

TclChecker definition files are used with the tclchecker tool to analyze Tcl code for errors. TclChecker definition files have a ".pcx" extension. For each Tcl package you wish to analyze using tclchecker, there must be a corresponding ".pcx" file. This file declares the method by which the commands contained in the source Tcl package are checked. TclChecker definition files are written using the PCX API.

Note: This document uses the terms "TclChecker definition file", "PCX file", and "checker package" to identify the file used by the tclchecker tool to check Tcl code.

PCX files also contain definitions extending the rules used by tclchecker to analyze Tcl package sources. Fundamentally, each PCX file contains a Tcl script, which is executed by the tclchecker when the file is loaded.

Warning: Tcl code contained in PCX files is trusted. This means that PCX files are run directly by the Tcl interpreter and are not parsed with the tclchecker tool. When a PCX file is executed it should restrict itself to the PCX API. Because this code is executed without restriction it can potentially redefine everything in the program being checked (including functions, variables etc.).

Embedded PCX Files

The Tcl Dev Kit TclChecker comes with embedded PCX files for standard Tcl packages. Examples include: 'Tk', 'Expect', and 'Blt'. To view an embedded PCX file, use the Tcl Dev Kit Virtual Filesystem Explorer tool to navigate to the "pcx" directory (located, by default, in <installdir>bin/tclchecker.tcl/data/pcx), and then save the PCX file to an existing folder.

To use tclchecker on packages without an embedded PCX definition file, you must create a custom PCX file. For more information, see Using the PCX API.

Naming PCX Files

When creating custom PCX files for use with a Tcl package, the name of the PCX file must match the Tcl package name exactly. For example, if a Tcl package is loaded using the command package require FoO, then the PCX file containing the checker definitions for this package must also be named FoO.pcx (case must match exactly).

Note: For platforms with case-insensitive filesystems (such as Windows), all package names must be unique. For example, filenames like 'expect.pcx' and 'Expect.pcx' should not be used as they are considered the same file.

Loading PCX Files

Tcl searches various paths for PCX files. These paths are determined on startup. The first time a PCX file is required in a package through the package require command, the paths are scanned and a list that maps package names to PCX files is created.

Note: Subdirectories in the search path are not scanned as the checker does not search recursively.

To disable the usage of all PCX files during Tcl Dev Kit TclChecker sessions, specify the option -nopcx. Otherwise, PCX files are loaded on demand as needed. A file is determined to be needed if the code scanned by the checker contains a valid require statement for that package.

To specify additional locations where the Tcl Dev Kit TclChecker should look for PCX files, specify the option -pcx directory. The Tcl Dev Kit TclChecker will look for PCX files in the following locations and order (unless the -nopcx option is specified):

  1. PCX files (.pcx) wrapped in tclchecker.exe.
  2. The lib directory of the Tcl Dev Kit installation.
  3. In all package paths specified in the TclApp Preferences.
  4. The directory specified by the environment variable TCLDEVKIT_LOCAL.
  5. The search paths specified with the -pcx directory command-line option.

Note: If multiple PCX files with the same name occur in more than one location, the last file encountered by the checker is loaded. If the files contain conflicting settings, the setting encountered in the last PCX file is used.

Using the PCX API

This section outlines how to build a custom PCX file for use with the Tcl Dev Kit TclChecker. The PCX file for 'Tk' is used to demonstrate the format of a standard checker package.

PCX File Format

A PCX file contains two types of declarations, these are:

Every PCX file must begin and end with the following two pcx:: declarations:

  • The pcx::register declaration must be the first pcx:: command called after loading the PCX API.
  • The pcx::complete command must be the last command called in the PCX file.

Otherwise, declarations can be placed in any order within a PCX file. For readability purposes, however, it is recommended you separate PCX declarations into the following three sections:

  1. Management Header: The first part of a PCX file is the management header. This section contains general declarations as the information is declared through commands executed when loaded.
  2. Rule Definitions: The second part of a PCX file contains rule definitions. Rule definitions map commands and variables to actions. Rule definitions are conditional declarations.
  3. Supporting Code: The final part of a PCX file contains supporting code. This section contains a set of procedures defined in the namespace declared by the pcx::register command. These are checker commands used in rule definitions and other arbitrary commands to support them. These conditional declarations are defined during loading and are used only after rule definitions are activated.

Management Header

The PCX file management header contains the declarations that are global to the PCX checker package.

Tk Package Example: The PCX management header from the Tk package.

  # ### ######### ###########################
  ## Requisites

  package require pcx      ; # PCX API
  package require analyzer ; # Analyzer API (checker commands definitions).

  # ### ######### ###########################
  ## Tcl core version dependencies of the package this checker is for.

  pcx::register coreTk Tk
  pcx::tcldep   3.6 needs tcl 7.3
  pcx::tcldep   4.0 needs tcl 7.4
  pcx::tcldep   4.1 needs tcl 7.5
  pcx::tcldep   4.2 needs tcl 7.6
  pcx::tcldep   8.0 needs tcl 8.0
  pcx::tcldep   8.1 needs tcl 8.1
  pcx::tcldep   8.2 needs tcl 8.2
  pcx::tcldep   8.3 needs tcl 8.3
  pcx::tcldep   8.4 needs tcl 8.4

  # ### ######### ###########################

Description:

  • First, the pcx package is loaded to provide access to all tclchecker APIs.
  • The analyzer package is then required. It is automatically loaded by the pcx::register command. The analyzer package loads the APIs used for custom TclChecker commands. Note: The analyzer package is required in this example for clarity. Because this package is automatically loaded, it does not need to be specified in your custom PCX file.
  • The pcx::register coreTk Tk statement declares that this PCX file uses the ::coreTk namespace internally, and that the Tk package is associated with this file.
  • A series of pcx::tcldep statements then declare which version pairs of Tcl and Tk are supported by the PCX file. The first column of numbers (second column from the left) declares which Tk packages are supported. The last column of numbers (rightmost column) declares the minimum Tcl version required to support the PCX file. The text 'needs tcl' is required, and is checked. Note: If no version pairs are declared then tclchecker assumes the default version of Tcl.

Rule Definitions

Rule definitions comprise the second part of a PCX checker file. Rule definitions map commands and variables to actions. Rules are defined in PCX files and are associated with a function or variable in a corresponding source package. A rule executes an action when tclchecker encounters the variable or function in the Tcl source specified in the corresponding PCX file. Possible actions include: printing custom warning or error messages, or indicating incorrect usage of a variable or function. The latter example requires use of the analyzer API to write custom checker commands.

There are two interfaces available for defining rules, simple and advanced. The simple interface uses the pcx::init function to initialize rule definitions. The advanced interface provides greater flexibility for rule definition as all initialization must be done through a custom init procedure. Both have comparable APIs; the simple interface serves as a wrapper for the advanced interface.

There are four types of rules in both the simple and advanced interfaces. These are:

  • Scanning Rules: Define the commands that are checked for generating the list of user-defined procedures, namespaces, and class contexts. The tclchecker tool applies scanning rules during the first phase of source file scanning.
  • Analysis Rules: Check the correctness of function and procedure arguments in the second phase of source file scanning. Analysis rules run with tclchecker in std mode.
  • Variable Rules: Run when tclchecker encounters a specified variable within a source file.
  • Operator/Math Rules: Run when tclchecker encounters a specified math function or operator within an expression.

Simple Rule Definition

The simple rule interface uses the pcx::init procedure to automatically load rules and package versions. The pcx::init function performs the calls into the advanced interface. The simple interface commands for defining the four types of rules are: pcx::scan, pcx::check, pcx::var, and pcx::mathop. See Initializing Rules for more information on the pcx::init command.

The pcx::scan command defines tclchecker scanning rules. Command syntax follows:

pcx::scan  [ver] [cmd] <def>
  • [ver] is the package version the rule defines.
  • [cmd] is the name of the command to be checked.
  • <def> is the rule definition. This parameter is optional, if not specified then the analysis command is used during scanning.

The pcx::check command defines tclchecker analysis rules. Command syntax follows:

pcx::check [ver] [mode] [cmd] [def]
  • [ver] is the package version the rule defines.
  • [mode] is always std.
  • [cmd] is the name of the command to be checked.
  • [def] is the rule definition.

The pcx::var command defines variable (var) rules. Command syntax follows:

pcx::var [ver] [varname]
  • [ver] is the package version the rule defines.
  • [varname] is the fully qualified name of the variable. The full namespace must be included.

The pcx::mathop command defines operator/math rules. Command syntax follows:

pcx::mathop [ver] [opname] [oparity]
  • [ver] is the package version the rule defines.
  • [opname] is the name of the math function or operator.
  • [oparity] is the number of arguments expected by the math function or operator.

Versioning with the Simple Interface

Versioning with the simple interface is a less intensive method of defining the relationship between rules and package versions. This is because the pcx::init function scans for version number information and initializes the correct version of the rule with the corresponding package version. If pcx::init does not find a rule matching the provided package version, pcx::init then initializes the rule with the largest version number below the specified version. For example, if a PCX file contains rule definitions for package versions 8.0, 8.1, 8.2, 8.4 and the package being loaded has version 8.3, then the rule for version 8.2 is loaded.

Limitation: It is impossible to rename or delete commands and variables from a PCX file in future package versions using the simple interface. This is because once a rule is defined for a command and a package version, all future packages will load a rule for that command. For example, if package version 8.2 contains the command Foo with a matching 8.2 version rule defined in the PCX file, and this command is removed in version 8.3, then using that PCX file will still load rule 8.2 for the Foo command. To handle this limitation of the simple interface, the PCX developer must use the advanced interface described in the following section.

Advanced Rule Definition

The advanced rule interface uses a custom init procedure to define rules and package versions. The advanced interface commands pcx::checkers, pcx::scanners, pcx::variables, and pcx::mathoperators must be placed within the body of the init function to be correctly defined. Beyond this requirement, there are no restrictions on how definitions are stored. Lastly, defining rules with the advanced interface handles the limitation of the simple interface where commands could not be renamed between package versions. This is accomplished through using the version passed to the init function to ensure that the correct rule is activated. See Initializing Rules for more information on custom init commands.

  • The pcx::scanners command accepts a serialized array that maps command names to scanner definitions.
  • The pcx::checkers command accepts a serialized array that maps command names to checker definitions.
  • The pcx::variables command takes a list of variables to define.
  • The pcx::mathoperators command takes a list of math functions to define, in the form [name]/[arity].

See Appendix A: PCX API Commands for the full advanced interface definition.

Defining Custom Messages and Initializing Rules

This section demonstrates, through the 'Tk' package, how to define custom messages and initialize rules.

Defining Custom Messages

Tk Package Example: Defining new messages.

# ### ######### ###########################
## Package specific message types and their human-readable translations.

pcx::message badColormap {invalid colormap "%1$s": must be "new" or a window name} err

# ### ######### ###########################

Description:

  • The pcx::message command defines new message codes for the errors and warnings generated by the PCX file. The syntax is as follows:
  • pcx::message [code] [text] [types]
    
    • The [code] parameter is the ID of the new message.
      Note: For the pcx::message command the messageID must be specified without a namespace prefix. This is because pcx::message automatically adds the name of the checker package as a prefix to the messageID. However, when the message ID is used to display a message with the logError command the prefix has to be specified. For example, coreTk::badColorMap
    • The [text] parameter is the human readable string displayed by tclchecker. This string may contain placeholders of the form '%<digit>$s'. When the message is displayed, these placeholders will be replaced with the additional arguments given to the 'logError' call. The <digit> placeholder specifies which argument to use starting from '1'.
    • The [types] parameter is a list of message types used by message filtering mechanism in tclchecker. Legal type codes are 'err', 'warn', or 'upgrade'.

Initializing Rules

Tk Package Example: Initializing rules in the PCX file.

# ### ######### ###########################
proc ::coreTk::init {ver} {
    ::pcx::init coreTk $ver
  }

# ### ######### ###########################

Description:

  • The namespace ::coreTk is used to declare all messages and rules. Rule definitions and messages must be declared in the namespace reserved for the PCX checker definition. Namespaces are defined in the management header.
  • The init command activates the rule definitions for the specified version of the source package. If the PCX file does not declare a custom init command, tclchecker will define the command as shown above. Important: The pcx::init command should always be called from the init function to ensure that simple rule definitions are loaded.

PCX API Summary

Simple API: Advanced API: Rule Type: Definition: Notes:
pcx::scan pcx::scanners Scanning Scan command rules. Always taken.
pcx::check pcx::checkers Analysis in std mode. Analysis command rules. Always taken.
pcx::var pcx::variables Variable Variables declared by the package. Always taken.
pcx::mathop pcx::mathoperators Variable Math functions declared by the package. Always taken.

Supporting Code

The final section of a PCX checker package contains supporting code. Supporting code consists of a series of procedure and variable definitions for more complicated rule definitions. All supporting code must be defined in the namespace reserved for the PCX checker package. A procedure can be a custom checker command, or a regular command supporting checker commands. Checker commands must follow additional restrictions for correct interoperation with tclchecker.

See Using the Analyzer API for information on checker command syntax.

For information on available checker commands, see Appendix B: Analyzer API Commands.


Using the Analyzer API

The Analyzer API is used to write custom checker commands. A checker command is a fundamental building block for checking a Tcl source file command. Checker commands ensure that arguments passed to a function in the Tcl source file are correct. Whenever tclchecker files check the invocation of a command, they consult an internal database that maps command names to checker commands. The tclchecker tool retrieves the checker command associated with the command that occurs in the source package and evaluates it according to the configuration in the checker package (PCX file). The database does not directly map to a command, but rather to the command prefix. This means it is possible to use a single generic checker command for many commands, with suitable parameterization.

Checker commands take at least two arguments. The first arguments are user-defined. The second-last argument is a list containing the arguments passed to the function being checked. The last argument is the index of the current argument being checked. The interface for a checker command is as follows:

proc checkFoo {... token index} {body}

Description:

  • It is convention to name the checker command after the function it checks, prefixed with the word 'check'. For example, checkFoo is a checker command for a 'Foo' function.
  • The token parameter is the list of arguments from the function being checked. This list describes the command and its components in detail, as generated by the parser package.
  • The index parameter indicates which item in the token list is currently being checked.
  • The body is the checker command code. Generally, checker command code will contain calls into the analyzer interface to process the argument list.

For information on available checker commands, see Appendix B: Analyzer API Commands.

Chaining and Grouping Checker Commands

The checker command interface can be used to write generic checker commands, as well as checker commands which call other checker commands to perform the actual task. The latter usage requires the chaining or grouping of checker commands.

Chaining: A primary checker command performs some tasks, and then passes the remaining tasks to a subsequent checker command. The subsequent command is explicitly specified as an argument to the primary checker command. Other subsequent checker commands may follow.

Grouping: A primary checker command has several other checker commands as arguments. The primary command then calls the subsequent commands in various patterns.

Appendix A: PCX API Commands

register <namespace> ?<pkg>?

Reserves <namespace> for PCX definitions of package <pkg>. Defines <namespace> as the name of the new checker package. If <pkg> is missing, <namespace> replaces it.

tcldep <namespace> <version> ?<tclver>?

Declares the <namespace> for the checker package. Use <version> to list supported source packages. Use ?<tclver>? to map source package versions to required Tcl versions.

load <pkg>

Ensures presence of a PCX file for the package in memory. Use when a PCX file uses a definition of another file. For example, Blt asks for Tk.

scanners {<cmd> <def> ...}

Advanced API. Accepts a serialized array that maps command names to scanner definitions.

checkers {<cmd> <def> ...}

Advanced API. Activates the checker definitions for the listed commands. Accepts a serialized array that maps command names to checker definitions.

variables {<var> ...}

Advanced API. Activates variable definitions in the checker. Takes a list of variables to define.

mathoperators {<op> ...}

Advanced API. Activates operator/math definitions in the checker. Takes a list of math functions to define, each in the form <opname>/<oparity>.

topDefinition <cmd>

Returns the current scanner/checker definition for the command. Empty if there is no definition for the command. Used by checker packages to conditionally define commands, and to copy an existing definition for use in a new one.

init <namespace> <ver>

Common setup command for definitions. Uses checkers, scanners, and variables to activate definitions stored <namespace> variables in. Activates the definitions of version <ver>.

scan <ver> <cmd> ?<def>?

Simple API. Defines tclchecker scanning rules.

check <ver> <mode> <cmd> <def>

Simple API. Defines tclchecker analysis rules.

var <ver> <varname>

Simple API. Defines variable rules.

mathop <ver> <opname> <oparity>

Simple API. Defines operator/math rules.

isActive <namespace> <vervar>

Tests if the checker package in <namespace> has active definitions. Returns a boolean: 'true' if active, 'false' otherwise. The active version is stored in the second argument, a variable name.

getCheckVersion <pkg>

Returns the version of the checked package <pkg>, or '-1' if the package is not checked. Used in new checker commands to place conditions on checks.

Appendix B: Analyzer API Commands

Use the Analyzer API to build custom checker commands.


checkContext cIndex strip chainCmd

Pushes a context on the context stack, then calls the chained checker.

cIndex: Index of the word containing the context information.

strip: Boolean, set if word containing context name has to have the head stripped off.

For scan commands.

checkUserProc pInfo

Checks a "proc" for the correct number of arguments.

pInfo: Proc declaration (argument lists)

checkRedefined

Checks if the procedure in the word to check is defined more than once.

checkBody

Check a script in a single word (procedure body, control commands).

checkWord

Check if the word contains subcommands, etc. and invokes their checker commands.

checkExpr

Check the expression for subcommands, etc.

checkCommand

Checks each word (checkWord) in the command.

checkSimpleArgs min max checkers

Checks that the number of arguments is between min and max. If that is not the case we default to checkCommand to check all words. If the number of words is in the specified range we go through the list of checkers and execute them. Each checker is started where its predecessor left off. If there are words left to check after the last checker was executed the execution of the last checker is repeated until there are no words left.

A value of -1 for max means that the number of arguments has no finite upper bound.

This is the basic sequential composition operator.

checkTailArgs head tail backup

Similar to the previous checker, but not quite. "backup" is the number of fixed tail arguments for the command. These are checked through the execution of tailCmd. All other arguments are checked with headCmd. The head arguments are checked before the tail arguments.

If the head checker did not process an argument, checkWord will be used instead. This happens until all head arguments are processed.

checkTailArgsFirst head tail backup

See checkTailArgs, but the tail arguments are checked before the head arguments.

checkSwitchArg switch min num cmds

This command checks switch arguments similar to the checkSimpleArgs checker. It checks to see if the minimum number of words can be found in the current command, and then checks "num" args. This checker is designed to be used inside custom checkers to assist checking switch arguments (e.g., the "expect" command.)

checkOption optionTable default

This is the primary composition operator for handling of subcommands (here called "options").

The optionTable is a list of 2-tuples mapping from subcommand names to checkers for the arguments after the subcommand.

If none of the options match, the 'default' checker is used. If the default is empty an error will be generated for that case.

Defaults to checkCommand if the subcommand word is not literal.

checkWidgetOptions allowsingle commonopts widgetopts

Convenience wrapper to checkConfigure, see below.

checkKeyword exact keywords

Checks that the next word is on the list of allowed keywords. If exact is not set, unique abbreviations of the keywords are allowed too. Falls back to checkWord for non-literals.

checkSwitches exact switches chain

Similar to checkKeyword. Differences:

  • switches is a list of switch/action pairs. If a switch does not take an argument the action can be empty. "--" is a terminator.

    If a switch with an action is found the checker in the action is executed for the switch argument.

  • After processing the switches the chained checker is called to process the arguments after the switches (if a checker to chain to was specified).

checkHeadSwitches exact backup switches chaincmd

Similar to checkSwitches. Does not check for switches beyond the 'backup' tail arguments of the command. Ignores arguments behind the switches.

checkHeadSwitches exact backup switches chaincmd

Similar to checkSwitches. Does not check for switches beyond the 'backup' tail arguments of the command. Ignores arguments behind the switches.

checkSwitchesArg exact switches chain

Similar to checkSwitches. Difference: Decouples the execution of checkers for a switch from the notion that a switch takes an argument. This allows for switches without arguments, yet needing a checker, for example to warn about portability problems with said switch.

checkConfigure allowsingle options

Options is a list of switch/action pairs. If allowsingle is set, a single argument is ok. Otherwise an error is generated. Checks the arguments for options and values as defined in the table.

checkFloatConfigure

See checkConfigure above, but does not check the option values.

checkNumArgs chainlist

A list of 2-tuples. First element of a tuple is the number of arguments triggering the checker specified as the second element of that tuple.

checkListValues min max checkers

Basic behavior as checkSimpleArgs, but for checking a list, not a command.

checkLevel chaincmd

Checks that next word is a valid level designator (#n, n) and then invokes the chained checker.

checkProcCall argstoadd

Number of non-literal arguments to append to the proc call. Ignored.

checkEvalArgs

See checkBody, but script is distributed over a list of arguments (examples: eval, after, ...).

checkRestrictedSwitches exact switches chain

See checkSwitches for basic behavior. Difference: Stops at first unrecognized switch, and does not log unrecognized switches as error.

checkVarName
checkVarNameRdAll
checkVarNameWrite
checkVarNameDecl

These commands check the validity of variable names.

  • checkVarName assumes that the command is reading the variable in scalar mode.
  • checkVarNameRdAll is like checkVarName with the scalar mode disabled, thereby including arrays.
  • checkVarNameWrite checks that the variable can be written.
  • checkVarNameDecl checks for the portability and supported status of the variable name (the checks done by checkVarNameDecl are done by all checkVarName functions).

checkBoolean, checkInt, checkFloat, checkWholeNum, checkIndex, checkIndexExpr, checkByteNum, checkList, checkProcName, checkFileName, checkChannelID, checkArgList, checkNamespace, checkNamespacePattern, checkExportPattern, checkPattern, checkAccessMode, checkResourceType, checkVersion, checkWinName, checkColor, checkPixels, checkCursor, checkRelief

Checking that the next words is of a specific type:

  • WholeNum === integer >= 0
  • Index === integer, or "end"
  • IndexExpr === integer, or "end", or "end"-integer
  • ByteNum === integer, in range 0 ... 255
  • List === parsable by list command
  • ArgList === List, nothing after 'args', no non-default args after defaulted args, 'args' not defaulted

warn mid detail chain

Generates an error/warn message and then invokes the chained checker.

getTokenType <word>

Type of token.

getTokenChildren <word>

A list of tokens.

getTokenNumChildren <word>

Length of the token list.

getTokenString <word>

String in the script for the token.

isLiteral <word>

Tests if the word is literal and without any substitutions.

getLiteral <word> <varname>

If a literal word, the exact literal value of the token. The value is stored in the named variable.

getLiteralPos <word> <pos>

Returns offset in the script for the position in the word.

getLiteralRange <word> <r>

Extended to a range, where range = {start size}

 Top