Copyright (c) 2012-2016 Hyperion Entertainment and contributors.
AmigaOS Manual: ARexx Debugging
ARexx provides tracing and source-level debugging facilities. Tracing displays selected statements in a program as the program executes. When a clause is traced, its line number, source text, and related information are displayed on the console.
The internal interrupt system enables an ARexx program to detect certain synchronous or asynchronous events and to take special actions when they occur. Events such as a syntax error or an external halt request that would normally cause the program to exit can instead be trapped so that corrective actions can be taken.
The tracing action selects which source clauses will be traced and has two modifier flags that control command inhibition and interactive tracing. Trace options can be shortened to one letter. The Trace options are:
- All clauses are traced.
- No tracing is performed and the program cannot be forced into interactive tracing.
- All command clauses are traced before being sent to the external host. Non-zero return codes are displayed on the console.
- Commands that generate a non-zero return code are traced after the clause is executed.
- All clauses are traced and intermediate results are displayed during expression evaluation. These include the values retrieved for variables, expanded compound names, and the results of function calls.
- All label clauses are traced as they are executed. A label will be displayed each time a transfer of control takes place
- NORMAL (Default)
- Command clauses with return codes that exceed the current error failure level are traced after execution and an error message is displayed.
- Tracing is turned off.
- All clauses are traced before execution and the final result of each expression is displayed. Values assigned to variables by ARG, PARSE or PULL instructions are also displayed. This option is recommended for general-purpose testing.
- This is a special option that traces all clauses and checks for errors, but suppresses the actual execution of the statements. If is helpful as a preliminary screening step for a newly-created program.
The tracing mode can be set using either the TRACE instruction or the TRACE() built-in function. Tracing can be selectively disabled from within a program to skip previously tested parts of a program.
Each trace line displayed on the console is indented to show the effective control (nesting) level at that clause and is identified by a special three-character code, as shown in Table 6-1. The source for each clause is preceded by its line number in the program.
Expression results or intermediates are enclosed in double quotes so that leading and trailing blanks will be apparent.
|+++||Command or syntax error|
|>C>||Expanded compound name|
|>F>||Result of a function call|
|>O>||Result of a dyadic operation|
|>P>||Result of a prefix operation|
|>V>||Value of a variable|
|>>>||Expression or template result|
|>.>||"Place holder" token value|
The tracing output from a program is always directed to one of two logical streams. The interpreter first checks for a stream named STDERR and directs the output there if the stream exists.
Otherwise, the trace output goes to the standard output stream STDOUT and will be interleaved with the normal console output of the program. The STDERR and STDOUT streams can be opened and closed under program control, so the programmer has complete control over the destination of tracing output.
In some cases a program may not have a predefined output stream. For example, a program invoked from a host application that did not provide input and output streams would not have an output console. To provide a tracing facility for such programs, the resident process can open a special global tracing console for use by any active program. When this console opens, the interpreter automatically opens a stream named STDERR for each ARexx program in which STDERR is not currently defined. The program then diverts its tracing output to the new stream.
A global tracing console can be opened using the TCO command utility. ARexx programs will automatically divert their tracing output to the new window, which is opened as a standard AmigaDOS console. The user can move it and resize it as required.
The tracing console also serves as the input stream for programs during interactive tracing. When a program pauses for tracing input, the input must be entered at the trace console. Any number of programs may use the tracing console simultaneously, although it is recommended that only one program at a time be traced.
The global console can be closed using the TCC command. The closing is delayed until all read requests to the console have been satisfied. Only when all of the active programs indicate that they are no longer using the console will it actually be closed.
ARexx provides a tracing mode called command inhibition that suppresses host commands. In this mode command clauses are evaluated in the normal manner, but the command is not actually sent to the external host, and the return code is set to zero. This provides a way to test programs that issue potentially destructive commands, such as erasing files or formatting disks. Command inhibition does not apply to command clauses that are entered interactively. These commands are always performed, but the value of the special variable RC is left unchanged.
Command inhibition may be used in conjunction with any trace option. It is controlled by the "!" character, which may appear by itself or may precede any of the alphabetic options in a TRACE instruction. Each occurrence of the "!" character "toggles" the inhibition mode currently in effect. Command inhibition is cleared when tracing is set to OFF.
Interactive tracing is a debugging facility that allows the user to enter source statements while a program is executing. These statements may be used to examine or modify variable values, issue commands, or otherwise interact with the program. Any valid language statements can be entered interactively, with the same rules and restrictions that apply to the INTERPRET instruction. In particular, compound statements such as DO and SELECT must be complete within the entered line.
Interactive tracing can be used with any of the trace options. While in interactive tracing mode, the interpreter pauses after each traced clause and prompts for input with the code "+++". At each pause, three types of user responses are possible:
- If a null line is entered, the program continues to the next pause point.
- If a "=" character is entered, the preceding clause is executed again.
- Any other input is treated as a debugging statement and is scanned and executed.
The interpreter pauses after traceable clauses. Tracing options determine the location of the pauses. The interpreter does not pause after the instructions CALL, DO, ELSE, IF, THEN, and OTHERWISE. When any clause generates an execution error, the interpreter exits the program.
Interactive tracing is controlled by the "?" character, either by itself or in combination with an alphabetic trace option. Any number of "?" characters may precede an option. Each occurrence toggles the mode currently in effect. For example, if the current trace option was NORMAL, "TRACE ?R" would set the option to RESULTS and select interactive tracing mode. A subsequent "TRACE ?" would turn off interactive tracing.
The ARexx interpreter provides error processing during debugging. Errors found during interactive debugging are reported, but do not terminate the program. This special processing only applies to statements entered interactively.
ARexx also disables the internal interrupt flags during interactive debugging. This prevents an accidental transfer of control due to an error or uninitialized variable. However, if a "SIGNAL label" instruction is entered, the transfer will take place and any remaining interactive input will be abandoned. The SIGNAL instruction can still be used to alter the interrupt flags, and the new setting will take effect when the interpreter returns to normal processing.
Each ARexx task initializes its command failure level to the client's failure level (usually 10) to suppress printing of nuisance command errors. The failure level can be changed using OPTIONS FAILAT. Command errors (RC > 0) and failure (RC >= FAILAT) can be separately trapped using SIGNAL ON ERROR and SIGNAL ON FAILURE.
The External Tracing Flag
ARexx has an external tracing flag used to force programs into interactive tracing mode. When this tracing flag is set, using the TS command utility, any program not already in interactive tracing mode will enter it immediately. The internal trace option is set to RESULTS unless it is currently set to INTERMEDIATES or SCAN, in which case it remains unchanged. Programs invoked while the external tracing flags is set will begin executing in interactive tracing mode.
The external tracing flag provides a way to regain control over looping or unresponsive programs. Once a program enters interactive tracing mode, the user can step through the program statements and diagnose the problem. External tracing is a global flag, so all currently-active programs are affected by it. The tracing flag remains set until it is cleared using the TE command utility. Each program maintains an internal copy of the last state of the tracing flag and sets its tracing option to OFF when it observes that the tracing flag has been cleared. Programs in BACKGROUND tracing mode do not respond to the external tracing flag.
ARexx maintains an internal interrupt system used to detect and trap certain error conditions. When an interrupt is enabled and its corresponding condition arises, a transfer of control to the label specific to that interrupt occurs. This allows a program to retain control in circumstances that might otherwise cause the program to terminate. The interrupt conditions can be caused by either synchronous events, like a syntax error, or asynchronous events, like a Ctrl+C break request.
|These internal interrupts are completely separate from the hardware interrupt system managed by the EXEC operating system.|
The name assigned to each interrupt is actually the label to which control will be transferred. Thus, a SYNTAX interrupt will transfer control to the label "SYNTAX:". Interrupts can be enabled or disabled using the SIGNAL instruction. For example, the instruction "SIGNAL ON SYNTAX" would enable the SYNTAX interrupt.
The interrupts supported by ARexx are:
- This traps (detects and treats as a signal and not as normal output) a Ctrl+C break request generated by AmigaDOS. If the interrupt is not enabled, the program terminates immediately with the error message "Execution halted" and returns with the error code set to 2.
- This traps a Ctrl+D break request issued by AmigaDOS. The break request is ignored if the interrupt is not enabled.
- This traps a Ctrl+E break request issued by AmigaDOS. The break request is ignored if the interrupt is not enabled.
- This traps a Ctrl+F break request issued by AmigaDOS. The break request is ignored if the interrupt is not enabled.
- This interrupt is generated by any host command that returns a non-zero code.
- An external halt request is trapped if this interrupt is enabled. Otherwise, the program terminates immediately with the error message "Execution halted".
- Errors detected by the I/O system are trapped if this interrupt is enabled.
- An interrupt occurs if an uninitialized variable is used while this condition is enabled. The usage could be within an expression, in the UPPER instruction, or with the VALUE() built-in function.
- A syntax or execution error is generated by this interrupt. Not all such errors can be trapped. Certain errors occur before a program is executed and those detected by the ARexx external interface cannot be trapped by the SYNTAX interrupt.
When an interrupt forces a transfer of control, all of the currently active control ranges are dismantled and the interrupt that caused the transfer is disabled. This disabling prevents a possible recursive interrupt loop. Only the control structures in the current environment are affected, so an interrupt generated within a function will not affect the caller's environment.
Two special variables are affected when an interrupt occurs:
- Always set to the current line number before the transfer of control takes place. This allows the determination of which source line is executed.
- Set to the error code that caused the condition. For ERROR interrupts, this value will be a command return code and can usually be interpreted as an error severity level. The value for SYNTAX interrupts is always an ARexx error code.
Interrupts are useful for error-recovery actions. This involves informing external programs that an error occurred or reporting further diagnostics to isolate the problem. Program 15 issues a "message" command to an external host called "MyEdit" whenever a syntax error is detected.
Program 15. Interrupt.rexx
/*A macro program for 'MyEdit'*/ SIGNAL ON SYNTAX /*Enable interrupt*/ (normal processing) EXIT SYNTAX: /*Syntax error detected*/ ADDRESS 'MyEdit' 'message' 'error' RC errortext (RC) EXIT 10