HP OpenVMS Systems Documentation

Content starts here

HP BASIC for OpenVMS
User Manual


Previous Contents Index

3.4.4 Tracing Program Execution

The SET TRACE command lets you select tracepoints, which are locations for tracing the execution of your program without stopping its execution. After setting a tracepoint, you can start execution with the GO command and then monitor the PC's path, checking for unexpected behavior. By setting a tracepoint on a routine, you can also monitor the number of times the routine is called.

As with breakpoints, every time a tracepoint is reached, the debugger issues a message and displays the source line. It can also display other information that you have specified (as shown in the last example in this section, in which the value of a specified variable is displayed). However, at tracepoints, unlike breakpoints, the program continues executing, and the debugger prompt is not displayed. For example:


DBG> SET TRACE COUNTER
DBG> GO
    .
    .
    .
trace at TEST\COUNTER
     34:  SUB COUNTER(LONG X,Y)
    .
    .
    .

When using the SET TRACE command, you specify address expressions, qualifiers, and optional clauses exactly as with the SET BREAK command.

The /LINE qualifier instructs the SET TRACE command to trace every line and is a convenient means of checking the execution path. By default, lines are traced within all called routines as well as the currently executing routine. If you do not want to trace system routines or routines in shareable images, use the /NOSYSTEM or /NOSHARE qualifiers. For example:


DBG> SET TRACE/LINE/NOSYSTEM/NOSHARE

The /SILENT qualifier suppresses the trace message and source code display. This is useful when you want to use the SET TRACE command to execute a debugger command at the tracepoint. For example:


DBG> SET TRACE\SILENT %LINE 83 DO (EXAMINE STATUS)
DBG> GO
    .
    .
    .
SCREEN_IO\CLEAR\STATUS:   'OFF'
    .
    .
    .

3.4.5 Monitoring Changes in Variables

The SET WATCH command lets you set watchpoints that will be monitored continuously as your program executes.

If the program modifies the value of a watched variable, the debugger suspends execution and displays the old and new values.


DBG> SET WATCH TOTAL

Subsequently, every time the program modifies the value of TOTAL, the watchpoint is triggered. The debugger monitors watchpoints continuously during program execution.

The next example shows what happens when your program modifies the contents of a watched variable:


DBG> SET WATCH TOTAL
DBG> GO
    .
    .
    .
watch of SCREEN_IO\TOTAL\%LINE 13
     13:   TOTAL = TOTAL + 1
    old value: 16
    new value: 17
break at SCREEN_IO.%LINE 14
     14:   CALL Pop_rtn(TOTAL)
DBG>

In this example, a watchpoint is set on the variable TOTAL and the GO command starts execution. When the value of TOTAL changes, execution is suspended. The debugger announces the event (watch of ...), identifying where TOTAL changed (line 13) and the associated source line. The debugger then displays the old and new values and announces that execution has been suspended at the start of the next line (14). (The debugger reports break at ..., but this is not a breakpoint; it is still the effect of the watchpoint.) Finally, the debugger prompts for another command.

When a change in a variable occurs at a point other than the start of a source line, the debugger gives the line number plus the byte offset from the start of the line.

3.5 Examining and Manipulating Data

This section explains how to use the EXAMINE, DEPOSIT, and EVALUATE commands to display and modify the contents of variables, and evaluate expressions in BASIC programs.

3.5.1 Displaying the Values of Variables

To display the current value of a variable, use the EXAMINE command as follows:


DBG> EXAMINE variable_name

The debugger recognizes the compiler-generated data type of the specified variable and retrieves and formats the data accordingly. The following examples show some uses of the EXAMINE command:

Examine a string variable:


DBG> EXAMINE EMPLOYEE_NAME
PAYROLL\EMPLOYEE_NAME:    "Peter C. Lombardi"
DBG>

Examine three integer variables:


DBG> EXAMINE WIDTH, LENGTH, AREA
SIZE\WIDTH:   4
SIZE\LENGTH:  7
SIZE\AREA:   28
DBG>

Examine a two-dimensional array of integers (two rows and three columns):


DBG> EXAMINE INTEGER_ARRAY
PROG2\INTEGER_ARRAY
   (0,0):       27
   (0,1):       31
   (0,2):       12
   (1,0):       15
   (1,1):       22
   (1,2):       18
DBG>

Examine element 4 of a one-dimensional string array:


DBG> EXAMINE CHAR_ARRAY(4)
PROG2\CHAR_ARRAY(4): 'm'
DBG>

Note that the EXAMINE command can be used with any kind of address expression (not just a variable name) to display the contents of a program location. The debugger associates certain default data types with untyped locations. You can override the defaults for typed and untyped locations if you want the data to be interpreted and displayed in some other data format. The debugger supports the data types and operators of BASIC including RECORDs and RFAs.

See Section 3.5.3 for an explanation of how the EXAMINE and the EVALUATE commands differ.

3.5.2 Changing the Values of Variables

To change the value of a variable, use the DEPOSIT command as follows:


DBG> DEPOSIT variable_name = value

The DEPOSIT command is like an assignment statement in BASIC.

In the following examples, the DEPOSIT command assigns new values to different variables. The debugger checks that the value assigned, which may be a language expression, is consistent with the data type and dimensional constraints of the variable.

Deposit a string value (it must be enclosed in quotation marks or apostrophes):


DBG> DEPOSIT PARTNUMBER = "WG-7619.3-84"

Deposit an integer expression:


DBG> DEPOSIT WIDTH = CURRENT_WIDTH + 10

Deposit element 12 of an array of characters (you cannot deposit an entire array aggregate with a single DEPOSIT command, only an element):


DBG> DEPOSIT C_ARRAY(12) = 'K'

You can specify any kind of address expression, not just a variable name, with the DEPOSIT command (as with the EXAMINE command). You can override the defaults for typed and untyped locations if you want the data to be interpreted in some other data format.

3.5.3 Evaluating Expressions

To evaluate a language expression, use the EVALUATE command as follows:


DBG> EVALUATE lang_exp

The debugger recognizes the operators and expression syntax of the currently set language. In the following example, the value 45 is assigned to the integer variable WIDTH; the EVALUATE command then obtains the sum of the current value of WIDTH plus 7:


DBG> DEPOSIT WIDTH = 45
DBG> EVALUATE WIDTH + 7
52
DBG>

Following is an example of how the EVALUATE and the EXAMINE commands are similar. When the expression following the command is a variable name, the value reported by the debugger is the same for either command.


DBG> DEPOSIT WIDTH = 45
DBG> EVALUATE WIDTH
45
DBG> EXAMINE WIDTH
SIZE\WIDTH:   45

Following is an example of how the EVALUATE and EXAMINE commands are different:


DBG> EVALUATE WIDTH + 7
52
DBG> EXAMINE WIDTH + 7
SIZE\WIDTH:   131584

With the EVALUATE command, WIDTH + 7 is interpreted as a language expression, which evaluates to 45 + 7, or 52. With the EXAMINE command, WIDTH + 7 is interpreted as an address expression: 7 bytes are added to the address of WIDTH, and whatever value is in the resulting address is reported (in this example, 131584).

3.6 Stepping Into BASIC Routines

This section provides details of the STEP/INTO command that are specific to BASIC.

In the following example, the debugger is waiting to proceed at source line 63. If you enter a STEP command at this point, the debugger will proceed to source line 64 without stopping during the execution of the function call. To step through the source code in the DEF function deffun, you must use the STEP/INTO command. A STEP/INTO command entered while the debugger has stopped at source line 63 causes the debugger to display the source code for deffun and stop execution at source code line 3.



  1     DECLARE LONG FUNCTION deffun (LONG)
  2     DECLARE LONG A
  3     DEF LONG deffun (LONG x)
  4         deffun = x
  5     END DEF
   .
   .
   .
->63    A = deffun (6%)
  64    Print "The value of A is: "; A

The STEP/INTO command is useful for stepping into external functions and DEF functions in HP BASIC. If you use this command to step into GOSUB blocks, the debugger steps into Run-Time Library (RTL) routines, providing you with no useful information.

In the following program, the debugger has suspended execution at source line 8. If you now enter a STEP/INTO command, the debugger steps into the relevant RTL code and informs you that no source lines are available.


  1  10   RANDOMIZE
   .
   .
   .
->8       GOSUB Print_routine
  9       STOP
   .
   .
   .
  20     Print_routine:
  21         IF Competition = Done
  22           THEN PRINT "The winning ticket is #";Winning_ticket
  23           ELSE PRINT "The game goes on."
  24         END IF
  25     RETURN

As in the previous example, a STEP command alone will cause the debugger to proceed directly to source line 9.

Table 3-1 summarizes the resultant behavior of the STEP/INTO command when used to step into external functions, DEF functions, and GOSUB blocks.

Table 3-1 Resultant Behavior of the STEP/INTO Command
Action Results
STEP/INTO DEF function Steps into function
STEP/INTO DEF* function Steps into RTL
STEP/INTO external function or SUB routine 1 Steps into function
STEP/INTO GOSUB block Steps into RTL

1Unless the subroutine is compiled with the /NOSETUP qualifier or equivalent, it will appear to step into RTL code, because an environment setup RTL routine is normally called as the very first thing of the subroutine.

3.6.1 Controlling Symbol References

When using the OpenVMS Debugger, all HP BASIC variable and label names within a single program unit must be unique; otherwise, the debugger will be unable to determine the symbol to which you are referring.

3.7 Sample Debugging Session

This section shows a sample debugging session using a BASIC program that contains a logic error.

The following program compiles and links without diagnostic messages from either the compiler or the linker. However, after printing the headers, the program is caught in a loop printing the same figures indefinitely.


 1   10 !SAMPLE program for DEBUG illustration
 2      DECLARE INTEGER Number
 3      Print_headers:
 4      PRINT "NUMBER", "SQUARE", "SQUARE ROOT"
 5      PRINT
 6      Print_loop:
 7      FOR Number = 10 TO 1 STEP -1
 8        PRINT Number, Number^2, SQR(Number)
 9        Number = Number + 1
10      NEXT Number
11      PRINT
12      END

The following text shows the terminal dialogue for a debugging session, which helps locate the error in the program SAMPLE. The callouts are keyed to explanatory notes that follow the dialogue.


$ BASIC/LIST/DEBUG SAMPLE (1)
$ LINK/DEBUG SAMPLE (2)
$ RUN SAMPLE

              VAX DEBUG Version n.n

%DEBUG-I-INITIAL, language is BASIC module set to 'SAMPLE$MAIN' (3)
DBG>STEP 2 (4)
NUMBER         SQUARE       SQUARE ROOT
stepped to SAMPLE$MAIN\%line 7
     7:         FOR Number = 10 TO 1 STEP -1 (5)
DBG> STEP 4 (6)
10        100          3.16228
stepped to  SAMPLE$MAIN\%LINE 7
     7:         FOR Number = 10 TO 1 STEP -1
DBG> EXAMINE Number (7)
SAMPLE$MAIN\NUMBER:     10 (8)
DBG> STEP 4 (9)
10        100          3.16228
stepped to  SAMPLE$MAIN\%LINE 7
     7:         FOR Number = 10 TO 1 STEP -1
DBG> EXAMINE Number (10)
SAMPLE$MAIN\NUMBER:     10 (11)
DBG> DEPOSIT Number = 9 (12)
DBG> STEP 4 (13)
9          81          3
stepped to  SAMPLE$MAIN\%LINE 7
     7:         FOR Number = 10 TO 1 STEP -1
DBG> EXAMINE Number (14)
SAMPLE$MAIN\NUMBER:     9 (15)
DBG> STEP (16)
9          81          3
stepped to  SAMPLE$MAIN\%LINE 8
     8:           PRINT Number, Number^2, SQR(Number) (17)
DBG> STEP (18)
stepped to SAMPLE$MAIN\%LINE 9
     9:         Number = Number + 1 (19)
DBG> EXIT (20)

The following explains the terminal dialogue in the above example:

  1. Compile SAMPLE.BAS with the /LIST and /DEBUG qualifiers. The listing file can be useful while you are in the debugging session.
  2. Link SAMPLE.BAS with the /DEBUG qualifier.
  3. The debugger identifies itself and displays the debugger prompt after you invoke the debugger with the RUN command.
  4. Step through 2 executable statements to the FOR statement.
  5. The headers print successfully and the program reaches the FOR statement.
  6. Step through one iteration of the loop.
  7. Request the contents of the variable Number.
  8. The debugger shows the contents of the loop index to be 10.
  9. Step through another iteration of the loop.
  10. Examine the value of the loop index again.
  11. The debugger shows that the loop index is still 10. The loop index has not changed from its initial setting in the FOR statement.
  12. Deposit the correct value into Number.
  13. Step through another iteration of the loop.
  14. Examine the contents of Number again.
  15. Observe that the number has not been changed yet.
  16. Step through just one statement to discover what is interfering with the value of Number during execution of the loop.
  17. Observe that this statement does not affect the value of Number.
  18. Step through another statement in the loop.
  19. Observe that this statement counteracts the change in the loop index.
  20. Exit from the debugger. You can now edit the program to delete line 9 and reprocess the program. Alternatively, you could use the EDIT command while in the debugger environment.

This debugging session shows that the FOR...NEXT loop index (Number) is not being changed correctly. An examination of the statements in the loop shows that the variable Number is being decreased by one during each execution of the FOR statement, but incremented by one with each execution of the loop statements. From this you can determine that the loop index will not change at all and the program will loop indefinitely. To correct the problem, you must delete the incorrect statement and recompile the source program.

3.8 Hints for Using the OpenVMS Debugger

A STEP at a statement that causes an exception might never return control to the debugger. The debugger cannot determine what statement in the BASIC source code will execute after the exception occurs. Therefore, set explicit breaks if STEP is used on statements that cause exceptions.

The following hints should help when you use the STEP command to debug programs that handle errors:

  • When you STEP at a statement that takes an error, the debugger will not regain control unless the program reaches an explicit breakpoint or the next statement that would have executed if no error had occurred. Set explicit breaks if you want the program to stop in any other place.
  • Use of the STEP command at a statement that takes an error does not return control to the debugger when the program reaches the error handler code. If you want the program to break when program execution enters an error handler, explicitly set a breakpoint at the error handler. This applies to both ON ERROR handlers and WHEN handlers.
  • If you are within a WHEN handler, a STEP at a statement that terminates execution within the WHEN handler (CONTINUE, RETRY, END WHEN, END HANDLER, EXIT HANDLER) will not stop unless program flow reaches a point where an explicit breakpoint is set.
  • STEP at a RESUME statement in an ON ERROR handler results in the program execution stopping at the first line of non-error-handler code.
  • Use SET BREAK/EXCEPTION at the beginning of the debugging session to prevent unexpected errors from occurring. This breakpoint is not necessary if you have set explicit breakpoints at all error handlers. However, use of this command will break at all exceptions, allowing you to check that you have the proper breakpoints to stop program execution following the exception.


Previous Next Contents Index