# Tcl Programming/TCL and ADP

`<font size=3>`{=html}**Tcl and ADP Reference**`</font>`{=html}

This is a reference for using Tcl with ADP pages, for people setting up
a site with the ArsDigita Community System (see
OpenACS for details). The first half is just a
Tcl overview; the second half deals with .adp pages, custom tags, and
AOLServer resources and parameters.

## Tcl Overview

### Basic Tcl Language Features

**`; or newline`**` statement separator`\
**`\`**` statement continuation if last character in line`\
**`#`**` comment out rest of line (if 1st non−whitespace char)`\
**`var`**` simple variable`\
**`var(index)`**` associative array variable`\
**`var(i,j)`**` multidimensional associative array variable`\
**`$var`**` variable substitution (also ${var}xyz)`\
**`[expr 1+2]`**` command substitution`\
**`\char`**` backslash substitution`\
**`"hello $a"`**` quoting with substitution`\
**`{hello $a}`**` quoting with no subst (deferred substitution)`\
*The only datatype in Tcl is a string. Some commands interpret arguments
as numbers/booleans; those formats are:*\'\
**`Integer`**`: 12 0xff(hex) 0377(octal)`\
**`Floating Pt`**`: 2.1 3. 6e4 7.91e+16`\
**`Boolean`**`: true false 0 1 yes no`

### Backslash Substitutions

**`\a`**` audible alert (0x7)`\
**`\b`**` backspace (0x8)`\
**`\f`**` form feed (0xC)`\
**`\n`**` newline (0xA)`\
**`\r`**` carriage return (0xD)`\
**`\t`**` horizontal tab (0x9)`\
**`\v`**` vertical tab (0xB)`\
**`\space`**` space`\
**`\newline`**` space`\
**`\ddd`**` octal value (d=0−7)`\
**`\xdd`**` hex value (d=0−9,a−f)`\
**`\c`**` replace ’\c’ with ’c’`\
**`\\`**` backslash`

### Operators and Math Functions

*The **expr** command recognizes these operators, in decreasing order of
precedence:*

    − ~ ! unary minus, bitwise NOT, logical NOT
    * / % multiply, divide, remainder
    + − add, subtract
    << >> bitwise shift left, bitwise shift right
    < > <= >= boolean comparisons
    == != boolean equals, not equals
    & bitwise AND
    ^ bitwise exclusive OR
    | bitwise inclusive OR
    && logical AND
    || logical OR
    x ? y : z if x != 0, then y, else z

*All operators support integers. All support floating point except :
`~, %, <<, >>, %, ^, and |`. Boolean operators can also be used for
string operands, in which case string comparison will be used. This
occurs if any of the operands are not valid numbers. The following
operators have \"lazy evaluation\" as in C:*\
**`&&, ||, ?:`**\
*The expr command recognizes the following math functions:*\
`abs hypot int double floor ceil fmod round`\
`cos sin tan acos asin atan atan2 cosh sinh tanh`\
`log log10 exp pow sqrt'''`

### Regular Expressions

    regex | regex match either expression
    regex* match zero or more of regex
    regex+ match one or more of regex
    regex? Match zero or one of regex
    . any single character except newline
    ^ match beginning of string
    $ match end of string
    \c match character c
    c match character c
    [abc] match set of characters
    [^abc] match characters not in set
    [a−z] match range of characters
    [^a−z] match characters not in range
    ( ) group expressions

### Pattern Globbing

    ? match any single character
    * match zero or more characters
    [abc] match set of characters
    [a−z] match range of characters
    \c match character c
    {a,b,...} match any of string a, b, etc.
    ~ home directory (for glob command)
    ~user match user’s home directory (for glob command)
    Note: for the glob command, a "." at the beginning of a file’s
    name or just after "/" must be matched explicitly and all "/"
    characters must be matched explicitly.

### Control Flow

    break
    Abort innermost containing loop command
    case
    Obsolete, see switch
    continue
    Skip to next iteration of innermost containing loop.
    exit[returnCode]
    Terminate the process, return returnCode (an integer which
    defaults to 0) to the system as the exit status.
    for start test next body
    Looping command where start, next, and body are Tcl command
    strings and test is an expression string to be passed to expr
    command.
    foreach varname list body
    The Tcl command string body is evaluated for each item in the
    string list where the variable varname is set to the item’s value.
    if expr1 [then] body1 [elseif expr2 [then] body2...] [[else] bodyN]
    If expression string expr1 evaluates true, Tcl command string
    body1 is evaluated. Otherwise if expr2 is true, body2 is
    evaluated, and so on. If none of the expressions evaluate to
    true, then bodyN is executed.
    return [−code code] [−errorinfo info] [−errorcode code] [string]
    Return immediately from current procedure with string as return
    value.
    switch [options] string pattern1 body1 [ pattern2 body2 ...]
    The string argument is matched against each of the pattern
    arguments in order. As soon as it finds a pattern that matches
    string, it evaluates the corresponding Tcl command string body. If
    no match is found and the last pattern is the keyword default, its
    command string is evaluated
    while test body
    Evaluates the Tcl command string body as long as expression string
    test evaluates to true.

### Lists

Note: list indices start at 0 and the word end may be used to reference
the last element in the list.

    concat [arg arg ...]
    Returns concatenation of each string
    join list [joinString]
    Returns string created by joining all elements of list with
    joinString.
    lappend varName [value value ...]
    Appends each value to the end of the list stored in varName.
    lindex list index
    Returns value of element at index in list.
    linsert list index element [element ...]
    Returns new list formed by using each arg as an element.
    llength list
    Returns number of elements in list.
    lrange list first last
    Returns new list from slice of list at indices first through last
    inclusive.
    lsearch [mode] list pattern
    Returns index of first element in list that matches pattern (−1
    for no match). Mode may be −exact, −glob(default) or −regexp.
    lsort [switches] list
    Returns new list formed by sorting list according to switches.
    These are:
    −ascii string comparison (default)
    −integer integer comparisons
    −real floating−point comparisons
    −increasing sort in increasing order (default)
    −decreasing sort in decreasing order
    −command cmd Use command which takes two arguments and returns
    an integer less than, equal to, or greater than zero.
    split string [splitChars]
    Returns a list formed by splitting string at each character in
    splitChars.

### Strings

    append varName [value value ...]
    Appends each of the given values to the string stored in varName.

    format formatString [arg arg ...]
    Returns a formatted string generated in the ANSI C sprintf manner.

    regexp [switches] exp string [matchVar] [subMatchVar ...]
    Returns 1 if the regular expression exp matches part or all of
    string, 0 otherwise. If specified, matchVar will be wet to all
    the characters in the match and the following subMatchVar’s will
    be set to matched parenthesized subexpressions. The −nocase
    switch can be specified to ignore case in matching. The −indices
    switch can be specified so that matchVar and subMatchVar will be
    set to the start and ending indice3s in string of their
    corresponding match.

    regsub [switches] exp string subSpec varName
    Replaces the first portion of string that matches the regular
    expression exp with subSpec and places results in varName. Returns
    count of number of replacements made. The −nocase switch can be
    specified to ignore case in matching. The −all switch will cause
    all matches to be substituted for.

    scan string formatString varName [varName ...]
    Extracts values into given variables using ANSI C sscanf behavior.
    string compare string1 string2
    Return −1, 0, or 1, depending on whether string1 is
    lexicographically less than, equal to, or greater than string2.
    string first string1 string2
    Return index in string2 of first occurrence of string1 (−1 if not
    found).

    string index string charIndex
    Returns the charIndex’th character in string.

    string last string1 string2
    Return index in string2 of last occurrence of string1 (−1 if not
    found).

    string length string
    Returns number of characters in string.

    string match pattern string
    Returns 1 if glob pattern matches string, 0 otherwise.

    string range string first last
    Returns characters from string at indices first through last
    inclusive.

    string tolower string
    Returns new string formed by converting all chars in string to
    lower case.

    string toupper string
    Returns new string formed by converting all chars in string to
    upper case.

    string trim string [chars]
    Returns new string formed by removing from string any leading or
    trailing characters present in the set chars.

    string trimleft string [chars]
    Same as string trim for leading characters only.

    string trimright string [chars]
    Same as string trim for trailing characters only.

    string wordend string index
    Returns index of character just after last one in word at index in
    string.

    string wordstart string index
    Returns index of first character of word at index in string.

    subst [−nobackslashes] [−nocommands] [−novariables] string
    Returns result of backslash, command, and variable substitutions
    on string. Each may be turned off by switch.

## The Tcl \<\--\> ADP interface

### Including TCL code in ADP pages

*Inline replacement:*
`<%= tcl code that evaluates to the text you want embedded %>`

*State changing Code:*
`<% tcl commands to change tcl environment (set vars, do db queries, etc) %>`

*Example:* `Two plus two is <%= [expr 2+2] %>`

### Defining custom tags

``` tcl
ns_register_adptag "codeexample" "/codeexample" tcl_adp_codeexample

proc tcl_adp_codeexample {string tagset} {
return "<blockquote>
<code><pre>${string}</pre></code>
</blockquote>
"
}
```

### Using AOLServer Parameters

    [ad_parameter UsersCanCreateRoomsP chat]

### Resourcing tcl in AOLserver

*source−file.tcl − to source a particular file.*

    set_the_usual_form_variables
    ns_eval [list source $file]
    ns_return 200 text/html ok
    wget −O − "http://localhost:8000/source−
    file.tcl?file=/web/server1/tcl/myfile.tcl"

*Note: this does not work for registered tag changes. To cause a reload
of everything:*

    <%
    set dir [ns_info tcllib]
    set list [exec ls $dir]
    foreach file $list {
    source $dir/$file
    ns_puts "sourced: $file
    "}%>

### Using ns_set

*When one queries a database, the variable that is set is an ns_set:*

    # ask AOLserver to give us a database connection
    set db [ns_db gethandle]
    set sql_query "select first_names, last_name
    from users
    where user_id = $user_id"
    # actually send the query to the RDBMS; tell AOLserver we
    # expect exactly one row back
    set selection [ns_db 1row $db $sql_query]
    <pre>
    ''Getting information out of an ns_set:''
    <pre>
    set first_names [ns_set get $selection "first_names"]
    set last_name [ns_set get $selection "last_name"]
    ns_return 200 text/plain "User #$user_id is $first_names $last_name"

### Dealing with Form Variables

*Importing form variables into a tcl or adp page*
`set_the_usual_form_variables` *Manipulating Forms Directly:*
`ns_getform`

### Decode

*Do logic w/o breaking out of an ns_write. Just like SQL !*
`[util_decode unknown val1 res1 val2 res2 valN resN defaultresult]`

### Dealing With .ini file Parameters

*ad_parameter* `ad_parameter name { subsection "" } { default "" }`

    Returns the value of a configuration parameter set in one of the .ini files in
    /web/yourdomain/parameters. If the parameter doesn’t exist, returns the
    default specified as the third argument (or empty string if not default is
    specified). Note that AOLserver reads these files when the server starts up and
    stores parameters in an in−memory hash table. The plus side of this is that
    there is no hit to the file system and no need to memoize a call to
    ad_parameter. The minus side is that you have to restart the server if you
    want to test a change made to the .ini file.

*ad_parameter_section* `ad_parameter_section { subsection "" }`

    Returns all the vars in a parameter section as an ns_set. Relies on
    undocumented AOLserver Tcl API call ns_configsection (analogous C API
    call is documented). Differs from the API call in that it returns an empty
    ns_set if the parameter section does not exist.

### Converting tcl to adp

*inclusion of sub−files*

    # Source user−new.adp. We would redirect to it, but we don’t want
    # the password exposed!
    # source "[ns_url2file "/register/user−new.tcl"]"
    # return
    ns_adp_include user−new.adp
    ns_adp_break

