B.3   Tcl Coding Conventions

This section defines the Wind River Systems standard for all C and Tcl code and for the accompanying documentation included in source code. The conventions are intended, in part, to encourage higher quality code; every source module is required to have certain essential documentation, and the code and documentation is required to be in a format that has been found to be readable and accessible.

The conventions are also intended to provide a level of uniformity in the code produced by different programmers. Uniformity allows programmers to work on code written by others with less overhead in adjusting to stylistic differences. Also it allows automated processing of the source; tools can be written to generate reference entries, module summaries, change reports, and so on.

These conventions are divided into the following categories:

B.3.1   Tcl Module Layout

A module is any unit of code that resides in a single Tcl file. The conventions in this section define the standard module heading that must come at the beginning of every Tcl module following the standard file heading. The module heading consists of the blocks described below; the blocks are separated by one or more blank lines.

After the modification history and before the first function or executable code of the module, the following sections are included in the following order, if appropriate:

The format of these blocks is shown in the following example (which also includes the Tcl version of the file heading):

Example B-1:  Tcl File and Module Headings

# Browser.tcl - Browser Tcl implementation file 
# 
# Copyright 1994-1995 Wind River Systems, Inc. 
# 
# modification history 
# -------------------- 
# 02b,30oct95,jco  added About menu and source browser.tcl in .wind. 
# 02a,02sep95,pad  fixed communications loss with license daemon (SPR #1234). 
# 01c,05mar95,jcf  upgraded spy dialog 
# 01b,08feb95,p_m  take care of loadFlags in wtxObjModuleInfoGet. 
# 01a,06dec94,c_s  written. 
#  
# DESCRIPTION 
# This module is the Tcl code for the browser. It creates the main window and 
# initializes the objects in it, such as the task list and memory charts. 
# 
# RESOURCE FILES 
# wpwr/host/resource/tcl/shelbrws.tcl 
# wpwr/host/resource/tcl/app-config/Browser/*.tcl 
# ... 
#*/ 
 
# globals 
 
set browserUpdate         0         ;# no auto update by default

B.3.2   Tcl Procedure Layout

The following conventions define the standard layout for every procedure in a module.

Each procedure is preceded by the procedure documentation, a series of Tcl comments that includes the following blocks. The documentation contains no blank lines, but each block is delimited with a line containing a single pound symbol (#) in the first column.

RETURNS: 
A list of 11 items: vxTicks taskId status priority pc sp errno 
timeout entry priNormal name
If the return value is meaningless enter N/A:

RETURNS: N/A

ERRORS: 
"Cannot find symbol in symbol table"
If no error statement is invoked in the procedure, enter N/A.

ERRORS: N/A

The procedure documentation ends with an empty Tcl comment starting in column one.

The procedure declaration follows the procedure heading and is separated from the documentation block by a single blank line. The format of the procedure and parameter declarations is shown in VxWorks Programmer's Guide: Coding Conventions.

The following is an example of a standard procedure layout.

Example B-2:  Standard Tcl Procedure Layout

##################################################################### 
# 
# browse - browse an object, given its ID 
# 
# This routine is bound to the "Show" button, and is invoked when 
# that button is clicked.  If the argument (the contents of... 
# 
# SYNOPSIS 
# .tS 
# browse [objAddr | symbol | &symbol] 
# .tE 
# 
# PARAMETERS 
# .IP <objAddr> 
# the address of an object to browse 
# .IP <symbol> 
# a symbolic address whose contents is the address of 
# an object to browse 
# .IP <&symbol> 
# a symbolic address that is the address of an object to browse 
# 
# RETURNS: N/A 
# 
# ERRORS: N/A 
#
proc browse {args} { ... }

B.3.3   Tcl Code Outside Procedures

Tcl allows code that is not in a procedure. This code is interpreted immediately when the file is read by the Tcl interpreter. Aside from the global-variable initialization done in the globals block near the top of the file, collect all such material at the bottom of the file.

However, it improves clarity--when possible--to collect any initialization code in an initialization procedure, leaving only a single call to that procedure at the bottom of the file. This is especially true for dialog creation and initialization, and more generally for all commands related to graphic objects.

Tcl code outside procedures must also have a documentation heading, including the following blocks:

The following is a sample heading for Tcl code outside all procedures.

Example B-3:  Heading for Out-of-Procedure Tcl Code

##################################################################### 
# 01Spy.tcl - Initialization code 
# 
# This code is executed when the file is sourced. It executes the module 
# entry routine which does all the necessary initialization to get a 
# runnable spy utility. 
#  
 
# Call the entry point for the module 
 
spyInit

B.3.4   Declaration Formats

Include only one declaration per line. Declarations are indented in accordance with Indentation, and begin at the current indentation level. The remainder of this section describes the declaration formats for variables and procedures.

Variables

For global variables, the Tcl set command appears first on the line, separated from the identifier by a tab character. Complete the declaration with a meaningful comment at the end of the same line. Variables, values, and comments should be aligned, as in the following example:

set     rootMemNBytes     0  ;# memory for TCB and root stack 
set     rootTaskId        0  ;# root task ID 
set     symSortByName    1  ;# boolean for alphabetical sort

Procedures

The procedure name and list of parameters appear on the first line, followed by the opening curly brace. The declarations of global variables used inside the procedure begin on the next line, one on each separate line. The rest of the procedure code begins after a blank line. For example:

proc lstFind {list node} { 
    global firstNode 
    global lastNode 
 
    ... 
}

B.3.5   Code Layout

The maximum length for any line of code is 80 characters. If more than 80 characters are required, use the backslash character to continue on the next line.

The rest of this section describes conventions for the graphic layout of Tcl code, covering the following elements:

Vertical Spacing

  • A for statement where the initial, conditional, and loop statements can be written on a single line:

for {set i 0} {$i < 10} {incr i 3} {

  • A switch statement whose actions are short and nearly identical (see the switch statement format in Indentation).

The if statement is not an exception. The conditionally executed statement always goes on a separate line from the conditional expression:

if {$i > $count} { 
    set i $count 
}

Horizontal Spacing

set status [fooGet $foo [expr $i + 3] $value] 
if {&value & &mask} {

set a [expr ($b + $c) * \ 
            ($d + $e)] 
set status [fooList $foo $a $b $c \ 
                    $d $e] 
if {($a == $b) && \ 
    ($c == $d)} { 
    ... 
}

Indentation

while { condition }{ 
    statements 
} 
 
foreach i $elem { 
    statements 
}

  • procedure declarations
  • conditionals (see below)
  • looping constructs
  • switch statements
  • switch patterns

if { condition } { 
    statements 
} else { 
    statements 
}
The form of the conditional statement with an elseif is:

if { condition } { 
    statements 
} elseif { condition } { 
    statements 
} else { 
    statements 
}

switch [flags] value { 
    a   { 
        statements 
        } 
    b   { 
        statements 
        } 
    default { 
        statements 
        } 
}
If the actions are very short and nearly identical in all cases, an alternate form of the switch statement is acceptable:

switch [flags] value { 
    a   {set x $aVar} 
    b   {set x $bVar} 
    c   {set x $cVar} 
}

Comments

  • Begin single-line comments with the pound symbol as in the following:

# This is the correct format for a single-line comment 
 
set foo 0

  • Multi-line comments have each line beginning with the pound symbol as in the example below. Do not use a backslash to continue a comment across lines.

# This is the CORRECT format for a multiline comment 
# in a section of code. 
 
set foo 0 
 
# This is the INCORRECT format for a multiline comment \ 
in a section of code. 
 
set foo 0

set day    night    ;# This is a global variable

B.3.6   Naming Conventions

The following conventions define the standards for naming modules, routines and variables. The purpose of these conventions is uniformity and readability of code.

aVariableName

B.3.7   Tcl Style

The following conventions define additional standards of programming style:

CORRECT:
                if {$id != 0} {
CORRECT:
                if {[expr $id] != 0} {
INCORRECT:
                if {[expr $id != 0]} {

CORRECT:
                incr index
CORRECT:
                incr index -4
INCORRECT:
                set index [expr $index + 1]

source [wtxPath host resource tcl]wtxcore.tcl 
set backenddir [wtxPath host [wtxHostType] lib backend]*

CORRECT:
                if [catch "dataFetch $list" result] { 
                        if {$result == "known problem"} { 
                            specialCaseHandle 
                        } else { 
                            error $result 
                        }
INCORRECT:
                catch "dataFetch $list" result

CORRECT:
                if {$id != 0} { 
                        ... 
                    } else { 
                        ... 
                    }
INCORRECT:
                if {$id !=0} then { 
                        ... 
                    } { 
                        ... 
                    }

The following illustrates a complex return value consisting of a description:

# Return a list of 11 items: vxTicks taskId status priority pc 
# sp errno timeout entry priNormal name 
 
return [concat [lrange $tiList 0 1] [lrange $tiList 3 end]]
The following illustrates and simple return value:

# This code checks whether the VxMP component is installed: 
 
if [catch "wtxSymFind -name smObjPoolMinusOne" result] { 
    if {[wtxErrorName $result] == "SYMTBL_SYMBOL_NOT_FOUND"} { 
        return -1       # VxMP is not installed 
    } else { 
        error $result 
    } 
} else { 
    return 0             # VxMP is installed 
}

if {$defaultTaskId == 0} { 
    error "No default task has been established." 
}
Because every error message and error code must be described in the procedure header in the ERRORS: block, it is sometimes useful to call error in order to replace an underlying error message with an error expressed in terms directly relevant to the current procedure. For example:

if [catch "wtxObjModuleLoad $periodModule" status] { 
    error "Cannot add period support module to Target ($status)" 
}