TCL Expressions for Dervish Chains

Dervish provides an extensive array of primitive TCL expressions to support chains. The following discussion details each TCL expression and whenever appropriate, parts of a TCL procedure are included for illustrative purposes.

For an overview of DERVISH chains, including the definition of cursors and indexes, press here.

All chain TCL extensions operate on the notion of a handle. Handles are treated as a valuable resource and are reused wherever possible. Any TCL extension that returns a handle to an object first checks to see if a handle is already bound to that object. If so, the bound handle is returned. If a handle is not bound to an object, a new handle will be created, bound to the object and returned.

In the discussions for each TCL extension, the following conventions apply:

  • All required parameters are denoted by delimiting them with < and >, example <CHAIN>
  • All optional parameters are denoted by delimiting them with [ and ]; example [pos]
  • All optional command line switches are denoted by preceeding the switch with a - (negative sign); example -increasing
  • The Dervish chain package contains contributed code as well which complements, at the TCL level, the chain manipulation extensions provided below.

    Description of TCL extensions

    Creation and Deletion

  • chainNew
  • chainDel
  • chainDestroy
  • Miscellaneous Operations

  • chainTypeSet
  • chainTypeGet
  • chainTypeDefine
  • chainSize
  • chainJoin
  • chainCopy
  • chainSort
  • chainCursorNew
  • chainCursorSet
  • chainCursorDel
  • chainCursorCount
  • chainCursorCopy
  • Chain Maintenance (addition/removal/retreival/traversal)

  • chainElementAddByPos
  • chainElementRemByPos
  • chainElementGetByPos
  • chainElementTypeGetByPos
  • chainElementAddByCursor
  • chainElementRemByCursor
  • chainElementTypeGetByCursor
  • chainWalk
  • _______________________________________________________________________________

    chainNew

    Creates a new chain and returns a handle bound to it. The type of the chain must be specified as well. If a heterogeneous chain is to be created, a type of GENERIC must be specified.

    TCL SYNTAX: chainNew <TYPE> <TYPE> - type of the chain to create RETURNS: TCL_OK Successful completion. Interp result contains the handle of the newly created chain TCL_ERROR On an error. Interp result will contain reason for the error _______________________________________________________________________________

    chainDel

    Deletes an existing chain and all chain elements. Note that the data on each chain element is not deleted. However, the chain and all it's elements will be deleted.

    TCL SYNTAX: chainDel <CHAIN> <CHAIN> handle of the chain to be deleted RETURNS: TCL_OK Successful completion. No result string TCL_ERROR Error occurred. Interp result will contain the reason _______________________________________________________________________________

    chainDestroy

    Deletes the specified chain, all chain elements, and all the data on associated with each chain element.

    Note that you can get into trouble applying this proc to a chain if there are other places where the addresses of the objects on the chain are stored (e.g. if the object appears on two chains).

    This will, in fact, only bite for types that call shMalloc more than once in their constructor (e.g. REGION). The problem is no worse than any other way of getting the same pointer into multiple handles, so don't worry too much about this warning.

    SYNOPSIS: chainDestroy <chain> <delProc> <chain> handle to the chain to be destroyed <delProc> name of a proc which deletes each element on the chain which is passed a handle to the element. If omitted, genericDel is assumed Returns: 0 : On success 1 : Otherwise _______________________________________________________________________________

    chainTypeSet

    This extension changes the existing type of the chain to the new type specified. It's the callers responsibility to ensure that all elements on the chain are of the new type. This extension does not check for that; it simply changes the type of the chain as indicated. TCL_SYNTAX: chainTypeSet <CHAIN> <TYPE> <CHAIN> handle of the chain <TYPE> new chain type RETURNS: TCL_OK Successful completion. No result string TCL_ERROR Error occurred. Interp result will contain the reason _______________________________________________________________________________

    chainTypeGet

    This extension returns the existing type of a chain as a TCL list. TCL_SYNTAX: chainTypeGet <CHAIN> <CHAIN> handle of the chain RETURNS: TCL_OK Successful completion. Interp result contains the existing type as a TCL list TCL_ERROR Error occurred. Interp result will contain the reason _______________________________________________________________________________

    chainTypeDefine

    This extension defines the chain type according to the following conventions:
    1. if the chain is empty, return the original type as a TCL list
    2. if the chain TYPE is GENERIC, but the chain contains homogeneous elements, return the type of the elements as a TCL list
    3. if the chain TYPE is GENERIC and the chain contains heterogeneous elements, the chain type is left unchanged
    TCL SYNTAX: chainTypeDefine <CHAIN> <CHAIN> handle of the chain RETURNS: TCL_OK Successful completion. Interp result contains the defined type as a TCL list TCL_ERROR Erroc occurred. Interp result will contain the reason _______________________________________________________________________________

    chainSize

    This extension returns the chain size (number of elements on the chain). TCL SYNTAX: chainSize <CHAIN> <CHAIN> handle of the chain RETURNS TCL_OK Successful completion. Interp result will contain the size TCL_ERROR Error occurred. Interp result will contain the reason _______________________________________________________________________________

    chainJoin

    This extension appends a target chain to a source chain. Both the chains must be of the same type, unless the source chain is of type GENERIC, in which case the target chain can be of any type. The target chain will be destroyed on the success of this extension. TCL SYNTAX: chainJoin <SOURCE-CHAIN> <TARGET-CHAIN> <SOUCRE-CHAIN> handle of the source chain <TARGET-CHAIN> handle of the target chain. Will be destroyed on a successful completion RETURNS: TCL_OK Successful completion. Interp result will contain <SOURCE-CHAIN> TCL_ERROR Error occurred. Interp result will contain the reason _______________________________________________________________________________

    chainCopy

    This extension copies a given chain. The copied chain does not inherit any cursor information from the parent. Interp result will contain a handle bound to the newly copied chain. TCL SYNTAX: chainCopy <CHAIN> <CHAIN> handle of the chain to copy RETURNS: TCL_OK Successful completion. Interp result will contain a handle bound to the newly created chain TCL_ERROR Error occurred. Interp result will contain the reason _______________________________________________________________________________

    chainSort

    This extension sorts a chain according to a specified criterion. The chain to be sorted must be homogeneous. Note that since sorting involves moving the chain element pointers around, cursor information set on the chain prior to a call to this extension will be lost. TCL SYNTAX: chainSort <CHAIN> <FIELD> -increasing <CHAIN> handle of the chain to sort <FIELD> field name to sort on -increasing Direction of the sort; if specified on the TCL command line, the sort is performed in an ascending fashion RETURNS: TCL_OK Successful completion. No result string TCL_ERROR Error occurred. Interp result will contain the reason _______________________________________________________________________________

    chainCursorNew

    This extension creates a new cursor on a chain. A chain can have upto 10 simultaneous active cursors. A cursor can be viewed as a context sensitive device on a chain; i.e. it holds the context of the chain. Cursors are helpful while traversing chains using chainWalk and modifying the state of the chain using chainElementAddByCursor and chainElementRemByCursor.

    This extension creates a chain cursor and initializes it to point to the first element on the chain. If the chain is empty, this extension is smart enough to wait till the first element is added, upon which time the cursor is initialized to the first element.

    TCL SYNTAX: chainCursorNew <CHAIN> <CHAIN> Handle of the chain RETURNS: TCL_OK Successful completion. Interp result will contain a handle to the newly created cursor TCL_ERROR Error occurred. Interp result will contain the reason EXAMPLE: dervish> chainNew GENERIC h1 dervish> chainCursorNew h1 h2 . . . _______________________________________________________________________________

    chainCursorSet

    This extension initializes a cursor to an element on the chain. The cursor must have been previously created using chainCursorNew. This extension will return an error if the chain is empty. TCL SYNTAX chainCursorSet <CHAIN> <CURSOR> [n] <CHAIN> Handle of the chain <CURSOR> Handle of the cursor previously created [n] Optional parameter that specifies the chain element to set the cursor to. Default value: HEAD RETURNS: TCL_OK Successful completion. Interp result will contain a handle of the nth element on the chain TCL_ERROR Error occurred. Interp result will contain the reason EXAMPLE: # The following example: # 1) declares a chain # 2) inserts two elements on it # 3) declares a cursor and sets it to the TAIL of the chain dervish> chainNew GENERIC h1 dervish> chainElementAddByPos h1 [regNew] dervish> chainElementAddByPos h1 [ptNew] dervish> chainCursorNew h1 h4 dervish> chainCursorSet h1 h4 TAIL h3 . . . _______________________________________________________________________________

    chainCursorCopy

    This extension copies an existing cursor. A new cursor is created that holds the same information as the existing one. TCL SYNTAX chainCursorCopy <CHAIN> <CURSOR> <CHAIN> Handle of the chain <CURSOR> Handle of the existing cursor RETURNS: TCL_OK Successful completion. Interp result will contain a handle of the newly created cursor TCL_ERROR Error occurred. Interp result will contain the reason _______________________________________________________________________________

    chainCursorDel

    This extension deletes a chain cursor. The cursor to be deleted should have been created with a call to the extension chainCursorNew TCL SYNTAX chainCursorDel <CHAIN> <CURSOR> <CHAIN> Handle of the chain <CURSOR> Handle of the cursor to be deleted RETURNS: TCL_OK Successful completion. No result string TCL_ERROR Error occurred. Interp result will contain the reason _______________________________________________________________________________

    chainCursorCount

    This extension returns a count of all active cursors associated with a chain. TCL SYNTAX chainCursorCount <CHAIN> <CHAIN> Handle of the chain RETURNS: TCL_OK Successful completion. Interp result contains the count TCL_ERROR Error occurred. Interp result will contain the reason _______________________________________________________________________________

    chainElementAddByPos

    This extension inserts a new element onto the chain. The new element is added relative to a fixed position which is specified on the Tcl command line. The new element can be added either before or after the specified position. The specified position and relativity are ignored when the very first element is added to a chain.

    Unless the chain is of type GENERIC, the element to be added should be of the same type as the chain's type.

    TCL SYNTAX chainElementAddByPos <CHAIN> <ELEMENT> [n] [how] <CHAIN> Handle of the chain <ELEMENT> Handle of the element to be inserted [n] New element is added in relation to element at this position Default value: "TAIL" [how] How to add the new element in relation to the nth element Default value: "AFTER" RETURNS: TCL_OK Successful completion. No result string TCL_ERROR Error occurred. Interp result will contain the reason EXAMPLE: # The following example demonstrates how to: # 1) Create a chain # 2) Add the first element to it # 3) Append the next element to the chain # 4) Add the third element in between the two existing elements dervish> chainNew GENERIC h1 dervish> chainElementAddByPos h1 [regNew] dervish> chainElementAddByPos h1 [maskNew] dervish> chainElementAddByPos h1 [ptNew] 2 BEFORE dervish> . . . _______________________________________________________________________________

    chainElementRemByPos

    This extension removes an element from the chain. The index of the element to be removed is specified on the TCL command line. Since chains are 0-indexed, this index must be in the interval [0, size of chain] TCL SYNTAX chainElementRemByPos <CHAIN> <position> <CHAIN> Handle of the chain <position> Position in chain of the desired element. One can specify either HEAD or TAIL or an integer RETURNS: TCL_OK Successful completion. Interp result contains a handle bound to the element that was removed from the chain TCL_ERROR Error occurred. Interp result will contain the reason EXAMPLE: # Assume we have a chain of 10 elements. To delete the 4th element # one would say: dervish> chainElementRemByPos h1 3 h3 # So, now we have 9 elements. To delete the first element, one would say: dervish> chainElementRemByPos h1 HEAD h5 # So, now we have 8 elements. To delete the 3rd element from head of the # chain, one would say: dervish> chainElementRemByPos h1 2 h2 dervish> . . . _______________________________________________________________________________

    chainElementGetByPos

    This extension retrieves an element from the chain. The index of the element to be retrieved is specified on the TCL command line. Since chains are 0-indexed, this index must be in the interval [0, size of chain] TCL SYNTAX chainElementGetByPos <CHAIN> <position> <CHAIN> Handle of the chain <position> Position in chain of the desired element. One can specify either HEAD or TAIL or an integer RETURNS: TCL_OK Successful completion. Interp result contains a handle bound to the retrieved element TCL_ERROR Error occurred. Interp result will contain the reason EXAMPLE: # Assume we have a chain of 10 elements. To get a handle to the 4th # element of the chain, one would say: dervish> chainElementGetByPos h1 3 h3 # To get a handle to the first element, one would say: dervish> chainElementGetByPos h1 HEAD h5 # To get a handle to the last element, one would say: dervish> chainElementGetByPos h1 TAIL h10 _______________________________________________________________________________

    chainElementTypeGetByPos

    This extension gets the type of a requested element from the chain. The type is returned as a TCL list. TCL SYNTAX chainElementTypeGetByPos <CHAIN> <position> <CHAIN> Handle of the chain <position> Position in chain of the desired element. One can specify either HEAD or TAIL or an integer RETURNS: TCL_OK Successful completion. Interp result contains a TCL list of the requested information TCL_ERROR Error occurred. Interp result will contain the reason EXAMPLE: dervish> chainNew MASK h1 dervish> chainElementAddByPos h1 [maskNew] dervish> chainElementTypeGetByPos h1 HEAD {type "MASK"} dervish> . . . _______________________________________________________________________________

    chainElementAddByCursor

    This extension adds a new element in relation to the cursor. The new element can be added either before or after the cursor. The cursor is supposed to have been correctly created and initialized. As the result of this extension, the cursor is set to the newly added element. TCL SYNTAX chainElementAddByCursor <CHAIN> <ELEMENT> <CURSOR> [how] <CHAIN> Handle of the chain <ELEMENT> Handle of the element to be added on the chain <CURSOR> Handle of the cursor [how] How to add the new element in relation to the cursor; can be one of "BEFORE" or "AFTER." Default value: "AFTER" RETURNS: TCL_OK Successful completion. No result string TCL_ERROR Error occurred. Interp result will contain the reason EXAMPLE: dervish> chainNew MASK h1 dervish> chainCursorNew h1 h2 dervish> chainElementAddByPos h1 [maskNew -name MASK1] dervish> chainCursorSet h1 h2 h3 dervish> chainElementAddByCursor h1 [maskNew -name MASK2] h2 dervish> chainElementAddByCursor h1 [maskNew -name MASK3] h2 BEFORE dervish> chainSize h1 3 . . . _______________________________________________________________________________

    chainElementRemByCursor

    This extension removes an element from a chain. The element to be removed is referenced by the cursor. On a successful removal, the cursor is set to NULL. Any attempts to retrieve the deleted element will result in failure. Since an element can be deleted while traversing a chain using chainWalk, chainElementRemByCursor saves the locations of the neighbors of the deleted element so that the chain can still be traversed. TCL SYNTAX chainElementRemByCursor <CHAIN> <CURSOR> <CHAIN> Handle of the chain <CURSOR> Handle of the cursor RETURNS: TCL_OK Successful completion. Interp result will contain a handle bound to the deleted element TCL_ERROR Error occurred. Interp result will contain the reason EXAMPLE: # Assume we have a chain (h1) with 3 elements on it. Let's # 1) create e new cursor # 2) set it to the 2nd element # 3) delete that element dervish> chainCursorNew h1 h7 dervish> chainCursorSet h1 h7 2 h3 dervish> chainElementRemByCursor h1 h7 h3 . . . _______________________________________________________________________________

    chainElementTypeGetByCursor

    This extension gets the type of the element under the cursor. TCL SYNTAX chainElementTypeGetByCursor <CHAIN> <CURSOR> <CHAIN> Handle of the chain <CURSOR> Handle of the cursor RETURNS: TCL_OK Successful completion. Interp result will contain the type of the element under the cursor as a TCL list TCL_ERROR Error occurred. Interp result will contain the reason _______________________________________________________________________________

    chainWalk

    This extension traverses a chain using a cursor. The state of a chain can be changed during traversal; i.e. new elements can be added, or existing elements deleted. Addition and deletion are done relative to the cursor, so the appropriate cursor APIs ( chainElementAddByCursor, chainElementRemByCursor) should be used.

    Direction of traversal relative to the cursor can be one of THIS (the current element is fetched), NEXT (the next element is fetched) or PREVIOUS (the previous element is fetched).

    Two TCL extensions may be used as a preamble to traversing a chain: chainCursorNew and chainCursorSet. chainCursorNew actually sets the cursor to one element before the start of the chain, so that the first chainWalk moves the cursor to the first element. chainCursorSet provides the ability to set a cursor to the start, or end of a chain. If this extension is used as a preamble to chain traversal, the cursor is actually set to one element before (after) the start (end) of the chain.

    chainWalk normally returns a handle bound to the appropriate element on the chain. On reaching the end of the chain, an empty string is returned in the interpreter.

    TCL SYNTAX chainWalk <CHAIN> <CURSOR> [whither] <CHAIN> Handle of the chain <CURSOR> Handle of the cursor [whither] Traversal direction; one of PREVIOUS, THIS, or NEXT. Defaults to NEXT RETURNS: TCL_OK Successful completion. Interp result will contain a handle bound to the chain element being traversed. On reaching the end of the chain, the interpreter will contain an empty string. TCL_ERROR Error occurred. Interp result will contain the reason EXAMPLE: # In all the examples below, assume we have a chain (h1) that has already # been populated with 3 elements. # # Example 1 demonstrates how to walk the chain using a newly created # cursor. Note that on reaching the end of the chain, if user wants # to keep on walking, the first element is returned # # Example 2 initializes the cursor to the TAIL of the chain, and loops # through the chain, applying a TCL extension to each element # on the chain # Example 1 dervish> chainCursorNew h1 h5 dervish> chainWalk h1 h5 NEXT h3 dervish> chainWalk h1 h5 NEXT h2 dervish> chainWalk h1 h5 NEXT h4 dervish> chainWalk h1 h5 NEXT dervish> dervish> chainWalk h1 h5 NEXT h3 dervish> . . . # Example 2 dervish> chainCursorSet h1 h5 TAIL dervish> while {[set elem [chainWalk h1 h5 PREVIOUS]] != ""} { >> exprPrint -header $elem >> } . . . _______________________________________________________________________________