Compaq BASIC for OpenVMS
Alpha and VAX Systems
User Manual


Previous Contents Index


Chapter 4
Using the OpenVMS Debugger with BASIC

This chapter discusses OpenVMS Debugger information that is specific to the BASIC language. For more information about the OpenVMS Debugger, see the OpenVMS Debugger Reference Manual. Online help is available during debugging sessions.

The shortened name Alpha BASIC means Compaq BASIC for OpenVMS Alpha, and VAX BASIC means Compaq BASIC for OpenVMS VAX.

4.1 Overview of the Debugger

A debugger is a tool to help you locate run-time errors quickly. It is used with a program that has already been compiled and linked successfully, with no errors reported, but that does not run correctly. For example, the output might be obviously wrong, the program goes into an infinite loop, or the program terminates prematurely. The debugger enables you to observe and manipulate the program's execution interactively, step by step, until you locate the point at which the program stopped working correctly.

The OpenVMS Debugger is a symbolic debugger, which means that you can refer to program locations by the symbols (names) you used for those locations in your program---the names of variables, routines, labels, and so on. You do not have to use virtual addresses to refer to memory locations.

The debugger recognizes the syntax, expressions, data typing, and other constructs of BASIC.

4.2 Compiling and Linking to Prepare for Debugging

The following example shows how to compile and link a BASIC program (consisting of a single compilation unit named INVENTORY) so that subsequently you will be able to use the debugger:


$ BASIC/DEBUG INVENTORY
$ LINK/DEBUG INVENTORY

The /DEBUG qualifier with the BASIC command instructs the compiler to write the debug symbol records associated with INVENTORY into the object module, INVENTORY.OBJ. These records allow you to use the names of variables and other symbols declared in INVENTORY in debugger commands. (If your program has several compilation units, you must compile each unit that you want to debug with the /DEBUG qualifier.)

The /DEBUG qualifier with the LINK command instructs the linker to include all symbol information that is contained in INVENTORY.OBJ in the executable image. The qualifier also causes the OpenVMS image activator to start the debugger at run time. (If your program has several object modules, you might need to specify other modules in the LINK command.)

4.3 Viewing Your Source Code

The debugger provides two methods for viewing source code: noscreen mode and screen mode. By default when you invoke the debugger, you are in noscreen mode, but you might find that it is easier to view your source code with screen mode. Both modes are described in the following sections.

4.3.1 Noscreen Mode

Noscreen mode is the default, line-oriented mode of displaying input and output. To get into noscreen mode from screen mode, enter SET MODE NOSCREEN. See the sample debugging session in Section 4.7 for a demonstration of noscreen mode.

In noscreen mode, you can use the TYPE command to display one or more source lines. For example, the following command displays line 3 of the module that is currently executing:


DBG> TYPE 3
3:    EXTERNAL SUB TRIPLE    & 
DBG>

The display of source lines is independent of program execution. You can use the TYPE command to display source code from a module other than the one currently executing. In that case, you need to use a directory specification to specify the module. For example, the following command displays lines 16 to 21 of module TEST:


DBG> TYPE TEST\16:21

4.3.2 Screen Mode

To invoke screen mode, press PF3. In screen mode, by default the debugger splits the screen into three displays called SRC, OUT, and PROMPT.


--SRC: module SAMPLE$MAIN -scroll-source-------------------------- 
     1:  10     !SAMPLE 
     2: 
     3:         EXTERNAL SUB TRIPLE        & 
     4:                     ,PRINT_SUB 
     5: 
     6:         WHEN ERROR USE HANDLER_1 
  -> 7:           CALL TRIPLE 
     8:           CALL PRINT_SUB 
     9: 
- OUT -output--------------------------------------------- 
stepped to SAMPLE$MAIN\%LINE 7 
 
 
 
 
- PROMPT -error-program-prompt---------------------------- 
DBG> STEP 
DBG> 

The SRC display, at the top of the screen, shows the source code of the module (compilation unit) that is currently executing. An arrow in the left column points to the next line to be executed, which corresponds to the current location of the program counter (PC). The line numbers, which are assigned by the compiler, match those in a listing file.

Note

BASIC line numbers are treated as text by the debugger. In this chapter, line numbers refer to the sequential line numbers generated by the compiler. When a program includes or appends code from another file, the included lines of code are also numbered in sequence by the compiler. These line numbers are on the extreme left of a listing file. An explanation of the listing file format is in Chapter 3.

The PROMPT display, at the bottom of the screen, shows the debugger prompt (DBG>), your input, debugger diagnostic messages, and program output. In the example, the debugger commands that have been issued are shown.

The OUT display, in the center of the screen, captures the debugger's output in response to the commands that you issue.

The SRC and OUT displays are scrollable so that you can see whatever information scrolls beyond the display window's edge. Press KP8 to scroll up and KP2 to scroll down. Press KP3 to change the display to be scrolled (by default, the SRC display is scrolled). Scrolling a display does not affect program execution.

If the debugger cannot locate source lines for the currently executing module, it tries to display source lines in the next module down on the call stack for which source lines are available and issues the following message:


%DEBUG-I-SOURCESCOPE, Source lines not available for .0\%PC. 
        Displaying source in a caller of the current routine. 

Source lines might not be available for the following reasons:

4.4 Controlling and Monitoring Program Execution

This section discusses the following:

4.4.1 Starting and Resuming Program Execution

There are two commands for starting or resuming program execution: GO and STEP. The GO command starts execution. The STEP command lets you execute a specified number of source lines or instructions.

GO Command

The GO command starts program execution, which continues until forced to stop. You will probably use the GO command most often in conjunction with breakpoints, tracepoints, and watchpoints. If you set a breakpoint in the path of execution and then enter the GO command (or press the keypad comma key that executes the GO command), execution will be suspended when the program reaches that breakpoint. If you set a tracepoint, the path of execution through that tracepoint will be monitored. If you set a watchpoint, execution will be suspended when the value of the watched variable changes.

You can also use the GO command to test for an exception condition or an infinite loop. If an exception condition that is not handled by your program occurs, the debugger will take over and display the DBG> prompt so that you can issue commands. If you are using screen mode, the pointer in the source display will indicate where execution stopped. You can then use the SHOW CALLS command (see Section 4.4.2) to identify the currently active routine calls (the call stack).

In the case of an infinite loop, the program will not terminate, so the debugger prompt will not reappear. To obtain the prompt, interrupt the program by pressing Ctrl/Y and then issue the DCL command DEBUG. You can then look at the source display and a SHOW CALLS display to locate the PC.

STEP Command

The STEP command (which you can use either by entering STEP or by pressing KP0) allows you to execute a specified number of source lines or instructions, or to execute the program to the next instruction of a particular kind, for example, to the next CALL instruction.

By default, the STEP command executes a single source line at a time. In the following example, the STEP command executes one line, reports the action ("stepped to..."), and displays the line number (27) and source code of the next line to be executed:


DBG> STEP
stepped to TEST\COUNTER\%LINE 27 
     27:   X = X + 1 
DBG>

The PC is now at the first machine code instruction for line 27 of the module TEST; line 27 is in COUNTER, a routine within the module TEST. TEST\COUNTER\%LINE 27 is a directory specification. The debugger uses directory specifications to refer to symbols. (However, you do not need to use a path name in referring to a symbol, unless the symbol is not unique; in that case, the debugger will issue an error message.) See the OpenVMS Debugger Reference Manual or online help for more information about resolving multiple-defined symbols.

You can specify a number of lines for the STEP command to execute. In the following example, the STEP command executes three lines:


DBG> STEP 3

Note that only those source lines for which code instructions were generated by the compiler are recognized as executable lines by the debugger. The debugger skips over any other lines---for example, comment lines.

Also, if a line has more than one statement on it, the debugger will execute all the statements on that line as part of the single step.

You can specify different stepping modes, such as stepping by instruction rather than by line (SET STEP INSTRUCTION). To resume to the default behavior, enter the SET STEP LINE command. Also by default, the debugger steps over called routines---execution is not suspended within a called routine, although the routine is executed. By entering the SET STEP INTO command, you tell the debugger to suspend execution within called routines as well as within the currently executing module. To resume the default behavior, enter the SET STEP OVER command.

4.4.2 Determining the Current Location of the Program Counter

The SHOW CALLS command lets you determine the current location of the program counter (PC) (for example, after returning to the debugger following a Ctrl/Y interrupt). The command shows a traceback that lists the sequence of calls leading to the currently executing routine. For example:


DBG> SHOW CALLS
 module name      routine name       line     rel PC    abs PC 
 
*TEST             PRODUCT              18    00000009  0000063C 
*TEST             COUNTER              47    00000009  00000647 
*MY_PROG          MY_PROG              21    0000000D  00000653 
DBG>

For each routine (beginning with the currently executing routine), the debugger displays the following information:

This example indicates that execution is currently at line 18 of routine PRODUCT (in module TEST), which was called from line 47 of routine COUNTER (in module TEST), which was called from line 21 of routine MY_PROG (in module MY_PROG).

4.4.3 Suspending Program Execution

The SET BREAK command lets you select breakpoints, which are locations at which the program will stop running. When you reach a breakpoint, you can enter commands to check the call stack, examine the current values of variables, and so on.

A typical use of the SET BREAK command is shown in the following example:


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

In this example, the SET BREAK command sets a breakpoint on the subprogram COUNTER; the GO command starts execution. When the subprogram COUNTER is encountered, execution is suspended, the debugger announces that the breakpoint at COUNTER has been reached (break at ...), displays the source line (34) where execution is suspended, and prompts you for another command. At this breakpoint, you can step through the subprogram COUNTER, using the STEP command, and use the EXAMINE command (see Section 4.5.1) to check on the current values of X and Y.

When using the SET BREAK command, you can specify program locations using various kinds of address expressions (for example, line numbers, routine names, instructions, virtual memory addresses). With high-level languages, you typically use routine names, labels, or line numbers, possibly with directory specifications to ensure uniqueness.

Routine names and labels should be specified as they appear in the source code. Line numbers may be derived from either a source code display or a listing file. When specifying a line number, use the prefix %LINE. (Otherwise, the debugger will interpret the line number as a memory location.) For example, the next command sets a breakpoint at line 41 of the currently executing module; the debugger will suspend execution when the PC is at the start of line 41:


DBG> SET BREAK %LINE 41

Note that you can set breakpoints only on lines that resulted in machine code instructions. The debugger warns you if you try to do otherwise (for example, on a comment line). If you want to pick a line number in a module other than the one currently executing, you need to specify the module's name in a directory specification. For example:


DBG> SET BREAK SCREEN_IO\%LINE 58

You do not always have to specify a particular program location, such as line 58 or COUNTER, to set a breakpoint. You can set breakpoints on events, such as exceptions. You can use the SET BREAK command with a qualifier, but no parameter, to break on every line, or on every CALL instruction, and so on. For example:


DBG> SET BREAK/LINE
DBG> SET BREAK/CALL

You can conditionalize a breakpoint (with a WHEN clause) or specify that a list of commands be executed at the breakpoint (with a DO clause on the debugger command). For example, the next command sets a breakpoint on the label LOOP3. The DO (EXAMINE TEMP) clause causes the value of the variable TEMP to be displayed whenever the breakpoint is triggered.


DBG> SET BREAK LOOP3 DO (EXAMINE TEMP)
DBG> GO
    .
    .
    . 
break at COUNTER\LOOP3 
     37:    LOOP3: FOR I = 1 TO 10 
COUNTER\TEMP:   284.19 
DBG>

To display the currently active breakpoints, enter the SHOW BREAK command:


DBG> SHOW BREAK
breakpoint at SCREEN_IO\%LINE 58 
breakpoint at COUNTER\LOOP3 
   do (EXAMINE TEMP) 
    .
    .
    .
DBG>

To cancel a breakpoint, enter the CANCEL BREAK command, specifying the program location exactly as you did when setting the breakpoint. The CANCEL BREAK/ALL command cancels all breakpoints.

4.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' 
    .
    .
    .

4.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.

4.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.

4.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 4.5.3 for an explanation of how the EXAMINE and the EVALUATE commands differ.


Previous Next Contents Index