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<E.TCL.DEPTH> = 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<E.TCL.DEPTH> FILENAME = @ENVIRON.SET<E.TCL.SAVE> @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<CTR> IF FIELD( NEXT_COMMAND, " ", 1) EQ "LIST" THEN NEW_STACK<-1> = NEXT_COMMAND END NEXT @TCL.STACK = NEW_STACK