====== The TCL Command Stack=====
^Published By^Date^Version^Knowledge Level^Keywords^
|Revelation Technologies|19 MAR 1991|2.1X|INTERMEDIATE|FILTERING, COMMANDS, COMMAND, STACK, TCL|
If you press [F2] at the TCL window, you will probably see the TCL "command
stack" a list of the last 100 or so commands that you have executed. Few
developers realize that they have virtually complete control over what the
system displays in the resulting popup. This technical bulletin describes
the contents, behavior, and manipulation of the TCL command stack.
==== Contents of the Command Stack ====
The command stack contains all commands that have passed through the TCL
processor. Commands are listed in reverse order (most recent first). Entries
in the command stack come from a variety of sources:
* Commands you have executed at the TCL window.
* Commands you have executed at the SQL window these will have "SQL" as the first word of the command.
* Commands that were part of a TCL "batch" command.
* TCL commands that were executed from within an R/BASIC program using one or more PERFORM or EXECUTE statements.
* Commands that were executed via the "X" or "E" codes and commands.
* Commands generated by system windows, such as the Recordcopy window, the Attach window, and many more.
The command stack contains all commands you have entered, even if the
command was unrecognized or contained invalid words. The one exception is if
a commanding contain unbalanced quotation marks: the command is cancelled
and is not added to the stack.
In addition to these user-generated entries in the command stack, you will
also find commands that the system has executed on its own. Most typically,
these are of two types:
* Commands executed during the login sequence. These will consist of various ATTACH commands (ex: ATTACH INDEXING, ATTACH DOS), plus any commands indicated as part of a user's login sequence.
* Commands generated automatically by the system as part of its housekeeping The most common of these are:\\ - The occasional DELETELIST commands that are used to clear entries from the Query Table (ex: DELETELIST %%10:00:00**01*JAN*1991%%)\\ - The commands used to maintain indexes (ex: DELETEFILE !MYDATA).\\ - The commands used to maintain transaction files if you are using transaction processing.
The TCL stack is maintained as a system variable called @TCL.STACK. This is
a dynamic array, with each command separated by field marks (@FM) and the
most recent commands at the front.
==== Number of Entries in the Command Stack ====
The system maintains the command stack automatically. However, you can
control the number of commands that the system maintains.
=== From the Environment ===
In the Environment window, the setting at the "Number of saved commands"
prompt determines how many commands are kept in the stack. There is no
specific maximum number, but the stack cannot exceed 64K. Because of the
manner in which the system maintains the stack, the minimum number of
commands available is two, even if you set the prompt to zero.
Even though there is little practical limit on how long the TCL stack can
be, it is impractical for several reasons to maintain a very large stack.
One reason is that the command stack takes up string space, so the longer
the current command stack, the more memory it consumes. In addition, a
needlessly long command stack occupies disk space when it is saved each time
you log out (see below for more details on saving the command stack between
sessions.)
=== From R/BASIC ===
From within an R/BASIC program you can control the number of entries in the
command stack by resetting the third field of the system array @ENVIRON.SET.
For example, this code fragment re-sets the depth of the command stack to
25:
$INSERT INCLUDE, ENVIRON.CONSTANTS
@ENVIRON.SET = 25
The change is effective immediately, although the number of entries in the
popup does not change until after another TCL command has been executed.
**Note**: You cannot completely disable the command stack by changing the
environment settings that affect it. To make the TCL stack completely
inaccessible, you must disable the Options key for the TCL window, which is
not recommended.
==== Saving and Restoring the Command Stack ====
When you log out of Advanced Revelation, the current command stack is saved
to disk. When you next log in, it is fetched from disk and restored so that
you can continue on with the stack from last time.
**Note**: The command stack is only saved if you log off using the TCL OFF
command or the Logoff window. It is not saved if you log out using the
R/BASIC LOGOFF command or the debugger OFF command.
You can control where the command stack is saved. Specify a file name at the
"File for saved lists" prompt in the General Environment window
(Management-Environment-General from the Main menu). This prompt should
actually read "File for saved commands". If this prompt is blank, the
command stack is not saved between sessions.
The system attempts to maintain a separate command stack for each user.
While you are logged in, of course, you maintain your stack in local RAM, so
it is unique to your workstation. When you log out, the command stack is
written to file using this key:
COMMAND.STACK*username
where "username" is the name that appears as the user name in the WHO window
(or in the R/BASIC variable @USERNAME). This is also the name that the
system uses when restoring your command stack during the next login
sequence.
=== "Lost" Command Stacks ===
You may find on logging into your application that the system has not
restored the command stack properly. This happens most typically when as
part of your application you attach various data volumes.
When you log out and Advanced Revelation saves your command stack to the
file designated in the environment, it saves the stack to the version of the
file that is currently attached. For example, if @ENVIRON.SET<4> ("File for
saved lists") points to the LISTS file, the TCL logout sequence will store
the command stack in the LISTS file currently attached. If that LISTS file
happens to be, for example, on a volume called MYDATA, then that is where
the command stack is saved.
However, when you next log into Advanced Revelation, the system will look
for a command stack in the LISTS file before it runs any login sequences,
including those that might attach data volumes. Essentially, this means that
the system can only find your last command stack if it was stored in the
LISTS file on the REVBOOT volume. If there is no LISTS file in REVBOOT, no
command stack will be restored at all. If there is a LISTS file on REVBOOT,
the system restores whatever commands it finds in the record key
COMMAND.STACK*username.
=== Custom Command Stack File ===
One way to overcome the problem of the "lost" command stack is to make sure
that the file in which you save the command stack is always in the REVBOOT
volume. You may find it impractical to keep your LISTS files in the REVBOOT
volume. In that case, you may wish to create a special file for this
purpose, perhaps called COMMAND.STACKS. Create this file on the REVBOOT
volume.
You can make this the default for new accounts by adding the name
COMMAND.STACKS to the list of files to be created for new accounts. This
list is stored in the SYSTEM file (SYSPROG account) in the record
NEW.ACCOUNT.FILE.LIST. By updating this list, you tell Advanced Revelation
what files to create when it is creating a new account. Then change the
environment setting for all users so the "File for saved lists" prompt
points to this new file.
**Note**: You may be tempted to make this file a global file. However, the name
of the saved command stack does not include an account name. As a
consequence, if you have the same users defined for different accounts (for
example, if the user MIKE is allowed to log into several different
accounts), these users will overwrite one another's stacks as they save them
to one global file.
=== Manually Restoring the Command Stack ===
Another way around the problem of the "lost" command stack is to restore the
command stack manually by modifying the variable @TCL.STACK. A short R/BASIC
process such as this one loads the command stack from the current version of
the command stacks file:
$INSERT INCLUDE,ENVIRON.CONSTANTS
STACK_CNT = @ENVIRON.SET
FILENAME = @ENVIRON.SET
@TCL.STACK<-1> = XLATE(FILENAME,ï "COMMAND.STACK*" :@USERNAME,'','X')
@TCL.STACK = FIELD(@TCL.STACK, @FM, 1,ï STACK_CNT)
Run this process after you have attached all the data volumes for you
application, and you will properly restore your old command stack. This code
adds your old stack onto the bottom of the new one, and adjusts it to the
depth specified in the environment. If you do not want to have the TCL
commands from the current login sequence (probably a series of ATTACH
commands) put into the command stack, change the fourth line by removing the
"<-1>" that immediately follows @TCL.STACK and removing the checks for the
length of the stack.
==== Manipulating the Command Stack ====
Because you can alter the contents of the variable @TCL.STACK, you can
manipulate it as part of your application. Two examples are described below.
=== "Hiding" Commands in the Command Stack ===
If your programs execute PERFORM or EXECUTE statements, or use the "X" or
"E" codes and commands, you may want to "hide" the resulting TCL commands
from the user. For example, perhaps your application executes a MAKEFILE
command, but you do not want to let your user see the details of this
command.
The easiest way to "hide" commands in other words, keep them from appearing
in the command stack is to save off and then restore the command stack
around your commands. This is a simple example:
SAVE_STACK = @TCL.STACK
PERFORM "MAKEFILE MYDATA SECURITY (S)"
@TCL.STACK = SAVE_STACK
Here, a new file is created, and no message is posted. If the user manages
to get to TCL and press the Options key, there will still be no evidence of
the creation of this new file.
It is possible to simply delete the topmost entries in the command stack in
this manner:
@TCL.STACK = DELETE(@TCL.STACK,1,0,0)
However, this may not always produce the correct results. Under some
circumstances, the system may itself execute TCL commands (as, for instance,
to clear an entry from the Query Table), so your command may not be the most
recent one on the stack.
=== Filtering Commands ===
In your application, you may want to allow only limited access to the
command stack. For example, if you are working in a report writer, you may
want to let the user see the last reports that were run (for example, the
most recent LIST commands), but not any other commands. In that instance,
you can assemble the commands from the command stack that meet your
requirements, and make these a part of a popup or other display. The program
fragment in Figure 1 illustrates the technique.
==== Examples ====
=== Figure 1 ===
NEW_STACK = ""
STACK_CNT = COUNT(@TCL.STACK, @FM) + (@TCL.STACK NE "")
FOR CTR = 1 TO STACK_CNT
NEXT_COMMAND = @TCL.STACK
IF FIELD( NEXT_COMMAND, " ", 1) EQ "LIST" THEN
NEW_STACK<-1> = NEXT_COMMAND
END
NEXT
@TCL.STACK = NEW_STACK