.ta 5n 10n 15n 20n 25n 30n 35n 40n 45n 50n 55n 60n .if n .po 1.25i .if t .po 1.0i .hy 14 .de hd 'sp 3 'if \\n%-1 'tl ''- % -'' 'sp 2 .if \\n(vq>0 .xj .nr vq 0 'ns .. .de fo .nr vk 0 .nr dn 0 .nr wf \\n(.pu-\\n(nlu-\\n(vmu-1v .if \\n(vs>0 .if \\n(wf>0 .xn .if \\n(vs>0 .if \\n(wf<=0 .xo .ch fo -\\n(vmu .nr vs 0 .nr vo \\n(vmu 'bp .. .de fe .br .di .ev .if \\n(vs=1 .nr dn +1v .nr vo +\\n(dnu .nr dn 0 .if \\n(vou>=\\n(.pu-\\n(nlu-.5v .nr vo \\n(.pu-\\n(nlu-.5v .if \\n(vou<\\n(vmu .nr vo \\n(vmu .ch fo -\\n(vou .. .de xj .nr vs 1 .nr vn 1 .di .ev 1 .da zb .ns .za .zc .fe .rm za .rm zc .. .de xn .ev 1 'in 0 'ti 0 .ie \\n(vn \l\|6.0i\(ru\| .el \l\|15\(ru\| .nr vn 0 .br .ns .zb .br .di .rm zb .nr vq \\n(dnu .nr dn 0 .nr vs 0 .ev .. .de xo .ev 1 .di zc .zb .br .di .rm zb .nr vq \\n(dnu .nr dn 0 .nr vs 0 .nr vn 1 .ev .. .de xp .di za .. .nr vm 6v .nr vo \n(vmu .wh 0 hd .wh -1.0i fo .ch fo 15i .wh -\n(vmu xp .ch fo -\n(vmu .if n .ll 6.5i .if t .ll 6.0i .if n .lt 6.5i .if t .lt 6.0i .ev 1 .if n .ll 6.5i .if t .ll 6.0i .if n .lt 6.5i .if t .lt 6.0i .ev .nr ap 1 .af ap A .sp 6 .ps +2 .ce \fBAn Introduction to Pdx\fP .ps -2 .sp 1 .ce \fIMark Linton\fR .sp 1 .ce September 27, 1981 .sp 1 .br .nr wg 2v .ie \n(.h=\n(vk .nr wg -\n(vhu .el .nr vh 0 .if \n(wg>0 \{\ .sp \n(wgu .nr vh +\n(wgu \} .nr vk \n(.h .ne 6 \fBIntroduction\fP .br .nr wg 1v .ie \n(.h=\n(vk .nr wg -\n(vhu .el .nr vh 0 .if \n(wg>0 \{\ .sp \n(wgu .nr vh +\n(wgu \} .nr vk \n(.h .ti +5n \fIPdx\fP is a tool for debugging Pascal programs that are translated by the Berkeley Pascal translator \fIpi\fP [Joy, Graham, and Haley 80]. This tutorial introduces \fIpdx\fP and the basic ways that it can be used. For a complete reference, consult the \fIpdx\fP manual page. .br .nr wg 2v .ie \n(.h=\n(vk .nr wg -\n(vhu .el .nr vh 0 .if \n(wg>0 \{\ .sp \n(wgu .nr vh +\n(wgu \} .nr vk \n(.h .ne 6 \fBGetting Started\fP .br .nr wg 1v .ie \n(.h=\n(vk .nr wg -\n(vhu .el .nr vh 0 .if \n(wg>0 \{\ .sp \n(wgu .nr vh +\n(wgu \} .nr vk \n(.h .ti +5n Suppose the program we are working on is in a file called ``prog.p''. Before using \fIpdx\fP, we must translate it with \fIpi\fP. \fIPdx\fP cannot be used if \fIpi\fP reports any errors during translation. To enter \fIpdx\fP, we type the following: (in examples, the user types is in boldface, what \fIpdx\fP prints is in normal type). .br .nr wg 1v .ie \n(.h=\n(vk .nr wg -\n(vhu .el .nr vh 0 .if \n(wg>0 \{\ .sp \n(wgu .nr vh +\n(wgu \} .nr vk \n(.h .in +8n .nf .ne 5 % \fBpdx\fP > .br .nr wg 1v .ie \n(.h=\n(vk .nr wg -\n(vhu .el .nr vh 0 .if \n(wg>0 \{\ .sp \n(wgu .nr vh +\n(wgu \} .nr vk \n(.h .in -8n .fi The ``>'' is a prompt from \fIpdx\fP. Like the shell or editor, \fIpdx\fP prints the prompt when it is waiting for a command. .br .nr wg 2v .ie \n(.h=\n(vk .nr wg -\n(vhu .el .nr vh 0 .if \n(wg>0 \{\ .sp \n(wgu .nr vh +\n(wgu \} .nr vk \n(.h .ne 6 \fBRunning the Program\fP .br .nr wg 1v .ie \n(.h=\n(vk .nr wg -\n(vhu .el .nr vh 0 .if \n(wg>0 \{\ .sp \n(wgu .nr vh +\n(wgu \} .nr vk \n(.h .ti +5n Once in \fIpdx\fP, we can begin executing our program by typing the command ``run''. Programs don't usually work the first time; with one of two things happening: .if n .nr In 5 .if t .nr In 8 .in +\n(Inn .br .nr wg 1v .ie \n(.h=\n(vk .nr wg -\n(vhu .el .nr vh 0 .if \n(wg>0 \{\ .sp \n(wgu .nr vh +\n(wgu \} .nr vk \n(.h .ti -5n \h'1n'1.\h'2n'\c The program tries to do something that isn't allowed in Pascal, such as dividing by 0. .br .nr wg 1v .ie \n(.h=\n(vk .nr wg -\n(vhu .el .nr vh 0 .if \n(wg>0 \{\ .sp \n(wgu .nr vh +\n(wgu \} .nr vk \n(.h .ti -5n \h'1n'2.\h'2n'\c The program runs but produces incorrect results. .in -\n(Inn .br .nr wg 1v .ie \n(.h=\n(vk .nr wg -\n(vhu .el .nr vh 0 .if \n(wg>0 \{\ .sp \n(wgu .nr vh +\n(wgu \} .nr vk \n(.h Let's consider the first case. Suppose ``prog.p'' contains the declarations .br .nr wg 1v .ie \n(.h=\n(vk .nr wg -\n(vhu .el .nr vh 0 .if \n(wg>0 \{\ .sp \n(wgu .nr vh +\n(wgu \} .nr vk \n(.h .in +8n .nf .ne 5 var sum, count : integer; avg : real; .br .nr wg 1v .ie \n(.h=\n(vk .nr wg -\n(vhu .el .nr vh 0 .if \n(wg>0 \{\ .sp \n(wgu .nr vh +\n(wgu \} .nr vk \n(.h .in -8n .fi and the statement .br .nr wg 1v .ie \n(.h=\n(vk .nr wg -\n(vhu .el .nr vh 0 .if \n(wg>0 \{\ .sp \n(wgu .nr vh +\n(wgu \} .nr vk \n(.h .in +8n .nf .ne 5 avg := sum / count; .br .nr wg 1v .ie \n(.h=\n(vk .nr wg -\n(vhu .el .nr vh 0 .if \n(wg>0 \{\ .sp \n(wgu .nr vh +\n(wgu \} .nr vk \n(.h .in -8n .fi at line 15. Suppose further that when the program is run ``count'' has the value 0. Running under \fIpdx\fP, the following would be printed: .br .nr wg 1v .ie \n(.h=\n(vk .nr wg -\n(vhu .el .nr vh 0 .if \n(wg>0 \{\ .sp \n(wgu .nr vh +\n(wgu \} .nr vk \n(.h .in +8n .nf .ne 5 > \fBrun\fP .sp 1 error at line 15: real divide by zero 15 avg := sum / count; > .br .nr wg 1v .ie \n(.h=\n(vk .nr wg -\n(vhu .el .nr vh 0 .if \n(wg>0 \{\ .sp \n(wgu .nr vh +\n(wgu \} .nr vk \n(.h .in -8n .fi .br .nr wg 2v .ie \n(.h=\n(vk .nr wg -\n(vhu .el .nr vh 0 .if \n(wg>0 \{\ .sp \n(wgu .nr vh +\n(wgu \} .nr vk \n(.h .ne 6 \fBPrinting Out Variables\fP .br .nr wg 1v .ie \n(.h=\n(vk .nr wg -\n(vhu .el .nr vh 0 .if \n(wg>0 \{\ .sp \n(wgu .nr vh +\n(wgu \} .nr vk \n(.h .ti +5n When a program stops because of an execution error, \fIpdx\fP prints the error and the line in the program where the error occurred. We can then examine the program's ``state'', that is, print out the values of any variables that might be of interest. In the above example, we might want to know the value of \fIsum\fP, so we say .br .nr wg 1v .ie \n(.h=\n(vk .nr wg -\n(vhu .el .nr vh 0 .if \n(wg>0 \{\ .sp \n(wgu .nr vh +\n(wgu \} .nr vk \n(.h .in +8n .nf .ne 5 > \fBprint sum\fP 5 > .br .nr wg 1v .ie \n(.h=\n(vk .nr wg -\n(vhu .el .nr vh 0 .if \n(wg>0 \{\ .sp \n(wgu .nr vh +\n(wgu \} .nr vk \n(.h .in -8n .fi The print command can be given any number of Pascal expressions separated by commas. .br .nr wg 1v .ie \n(.h=\n(vk .nr wg -\n(vhu .el .nr vh 0 .if \n(wg>0 \{\ .sp \n(wgu .nr vh +\n(wgu \} .nr vk \n(.h .ne 3 .ti +5n We can print the values of all variables by using the ``dump'' command. Continuing our example, we might get .br .nr wg 1v .ie \n(.h=\n(vk .nr wg -\n(vhu .el .nr vh 0 .if \n(wg>0 \{\ .sp \n(wgu .nr vh +\n(wgu \} .nr vk \n(.h .in +8n .nf .ne 5 > \fBdump\fP sum = 5 count = 0 avg = 0.0 > .br .nr wg 1v .ie \n(.h=\n(vk .nr wg -\n(vhu .el .nr vh 0 .if \n(wg>0 \{\ .sp \n(wgu .nr vh +\n(wgu \} .nr vk \n(.h .in -8n .fi Frequently there are many variables active so that we want to print the list of a file for perusal. This is done by saying .br .nr wg 1v .ie \n(.h=\n(vk .nr wg -\n(vhu .el .nr vh 0 .if \n(wg>0 \{\ .sp \n(wgu .nr vh +\n(wgu \} .nr vk \n(.h .in +8n .nf .ne 5 > \fBdump > out\fP .br .nr wg 1v .ie \n(.h=\n(vk .nr wg -\n(vhu .el .nr vh 0 .if \n(wg>0 \{\ .sp \n(wgu .nr vh +\n(wgu \} .nr vk \n(.h .in -8n .fi where ``out'' is the name of file which does not exist. .br .nr wg 1v .ie \n(.h=\n(vk .nr wg -\n(vhu .el .nr vh 0 .if \n(wg>0 \{\ .sp \n(wgu .nr vh +\n(wgu \} .nr vk \n(.h .ne 3 .ti +5n There are two other commands useful for printing information about variables. The command ``whatis'' prints out the declaration of a variable. Using the above example, .br .nr wg 1v .ie \n(.h=\n(vk .nr wg -\n(vhu .el .nr vh 0 .if \n(wg>0 \{\ .sp \n(wgu .nr vh +\n(wgu \} .nr vk \n(.h .in +8n .nf .ne 5 > \fBwhatis\fP sum var sum : integer; .br .nr wg 1v .ie \n(.h=\n(vk .nr wg -\n(vhu .el .nr vh 0 .if \n(wg>0 \{\ .sp \n(wgu .nr vh +\n(wgu \} .nr vk \n(.h .in -8n .fi .br .nr wg 1v .ie \n(.h=\n(vk .nr wg -\n(vhu .el .nr vh 0 .if \n(wg>0 \{\ .sp \n(wgu .nr vh +\n(wgu \} .nr vk \n(.h .ne 3 .ti +5n It is possible for a program to have the same name given to two or more different variables when they are local to different procedures. \fIPi\fP distinguishes the variables according to which procedure it is looking at; however, when debugging it is possible that both procedures are active (for example, one procedure could call the other). .br .nr wg 1v .ie \n(.h=\n(vk .nr wg -\n(vhu .el .nr vh 0 .if \n(wg>0 \{\ .sp \n(wgu .nr vh +\n(wgu \} .nr vk \n(.h .ne 3 .ti +5n \fIPdx\fP normally allows printing of any variable declared within the most recently called procedure or any variables accessible to this procedure. A variable in an active procedure that is not normally accessible can be printed by preceding its name with the procedure it is in and a ``.''. It can sometimes become difficult to remember the variable that a given name is currently associated with. The ``which'' command is useful in resolving this confusion. It prints the variable name along with the procedure that it is contained in. .br .nr wg 1v .ie \n(.h=\n(vk .nr wg -\n(vhu .el .nr vh 0 .if \n(wg>0 \{\ .sp \n(wgu .nr vh +\n(wgu \} .nr vk \n(.h .ne 3 .ti +5n Usually we want to know not only what the values of variables are, but how the program got to where it is. The ``where'' command lists the procedures that were called for the program to reach its current point. It might print, for example, .br .nr wg 1v .ie \n(.h=\n(vk .nr wg -\n(vhu .el .nr vh 0 .if \n(wg>0 \{\ .sp \n(wgu .nr vh +\n(wgu \} .nr vk \n(.h .in +8n .nf .ne 5 > \fBwhere\fP LastCalled(parameters), line 15 OneBeforeThat(parameters), line 30 MainProgram, line 45 > .br .nr wg 1v .ie \n(.h=\n(vk .nr wg -\n(vhu .el .nr vh 0 .if \n(wg>0 \{\ .sp \n(wgu .nr vh +\n(wgu \} .nr vk \n(.h .in -8n .fi .br .nr wg 2v .ie \n(.h=\n(vk .nr wg -\n(vhu .el .nr vh 0 .if \n(wg>0 \{\ .sp \n(wgu .nr vh +\n(wgu \} .nr vk \n(.h .ne 6 \fBExecution Tracing\fP .br .nr wg 1v .ie \n(.h=\n(vk .nr wg -\n(vhu .el .nr vh 0 .if \n(wg>0 \{\ .sp \n(wgu .nr vh +\n(wgu \} .nr vk \n(.h .ti +5n Now let's look at the possibility that our program doesn't get an execution error but doesn't produce the correct results. To figure out what and where something is going wrong, we wish to ``watch'' execution information more closely. The \fBtrace\fP command in \fIpdx\fP allows us to do this. There are five classes of information that we can watch: .if n .nr In 5 .if t .nr In 8 .in +\n(Inn .br .nr wg 1v .ie \n(.h=\n(vk .nr wg -\n(vhu .el .nr vh 0 .if \n(wg>0 \{\ .sp \n(wgu .nr vh +\n(wgu \} .nr vk \n(.h .ti -3n -\h'2n'\c The execution of a particular source line. .br .nr wg 1v .ie \n(.h=\n(vk .nr wg -\n(vhu .el .nr vh 0 .if \n(wg>0 \{\ .sp \n(wgu .nr vh +\n(wgu \} .nr vk \n(.h .ti -3n -\h'2n'\c A call to a particular procedure or function. .br .nr wg 1v .ie \n(.h=\n(vk .nr wg -\n(vhu .el .nr vh 0 .if \n(wg>0 \{\ .sp \n(wgu .nr vh +\n(wgu \} .nr vk \n(.h .ti -3n -\h'2n'\c The value of an expression at a particular source line. .br .nr wg 1v .ie \n(.h=\n(vk .nr wg -\n(vhu .el .nr vh 0 .if \n(wg>0 \{\ .sp \n(wgu .nr vh +\n(wgu \} .nr vk \n(.h .ti -3n -\h'2n'\c The value of a variable whenever it changes; and the line at which it changes. .br .nr wg 1v .ie \n(.h=\n(vk .nr wg -\n(vhu .el .nr vh 0 .if \n(wg>0 \{\ .sp \n(wgu .nr vh +\n(wgu \} .nr vk \n(.h .ti -3n -\h'2n'\c The execution of all source lines. .in -\n(Inn .br .nr wg 1v .ie \n(.h=\n(vk .nr wg -\n(vhu .el .nr vh 0 .if \n(wg>0 \{\ .sp \n(wgu .nr vh +\n(wgu \} .nr vk \n(.h It should be noted that the last two kinds of information are expensive to obtain and will cause your program to run much more slowly than normal. They should be used sparingly. .br .nr wg 1v .ie \n(.h=\n(vk .nr wg -\n(vhu .el .nr vh 0 .if \n(wg>0 \{\ .sp \n(wgu .nr vh +\n(wgu \} .nr vk \n(.h .ne 3 .ti +5n These forms of tracing can be combined and there is no limit to the number of things you can trace at any given time. .br .nr wg 1v .ie \n(.h=\n(vk .nr wg -\n(vhu .el .nr vh 0 .if \n(wg>0 \{\ .sp \n(wgu .nr vh +\n(wgu \} .nr vk \n(.h .ne 3 .ti +5n To trace the execution of a particular source line, type .br .nr wg 1v .ie \n(.h=\n(vk .nr wg -\n(vhu .el .nr vh 0 .if \n(wg>0 \{\ .sp \n(wgu .nr vh +\n(wgu \} .nr vk \n(.h .in +8n .nf .ne 5 > \fBtrace\fP \fIline-number\fP .br .nr wg 1v .ie \n(.h=\n(vk .nr wg -\n(vhu .el .nr vh 0 .if \n(wg>0 \{\ .sp \n(wgu .nr vh +\n(wgu \} .nr vk \n(.h .in -8n .fi The next time the \fBrun\fP command is given \fIpdx\fP will execute the program, printing the specified line each time it is about to be executed. .br .nr wg 1v .ie \n(.h=\n(vk .nr wg -\n(vhu .el .nr vh 0 .if \n(wg>0 \{\ .sp \n(wgu .nr vh +\n(wgu \} .nr vk \n(.h .ne 3 .ti +5n To trace every call to a procedure, type .br .nr wg 1v .ie \n(.h=\n(vk .nr wg -\n(vhu .el .nr vh 0 .if \n(wg>0 \{\ .sp \n(wgu .nr vh +\n(wgu \} .nr vk \n(.h .in +8n .nf .ne 5 > \fBtrace\fP \fIprocedure-name\fP .br .nr wg 1v .ie \n(.h=\n(vk .nr wg -\n(vhu .el .nr vh 0 .if \n(wg>0 \{\ .sp \n(wgu .nr vh +\n(wgu \} .nr vk \n(.h .in -8n .fi For each call to the named procedure during execution, \fIpdx\fP will print the name of the procedure, the procedure and line it was called from, and what parameters (if any) it was called with. .br .nr wg 1v .ie \n(.h=\n(vk .nr wg -\n(vhu .el .nr vh 0 .if \n(wg>0 \{\ .sp \n(wgu .nr vh +\n(wgu \} .nr vk \n(.h .ne 3 .ti +5n To see the value of an expression at a particular line, type .br .nr wg 1v .ie \n(.h=\n(vk .nr wg -\n(vhu .el .nr vh 0 .if \n(wg>0 \{\ .sp \n(wgu .nr vh +\n(wgu \} .nr vk \n(.h .in +8n .nf .ne 5 > \fBtrace\fP \fIexpression\fP \fBat\fP \fIsource-line-number\fP .br .nr wg 1v .ie \n(.h=\n(vk .nr wg -\n(vhu .el .nr vh 0 .if \n(wg>0 \{\ .sp \n(wgu .nr vh +\n(wgu \} .nr vk \n(.h .in -8n .fi To see whenever the value of a variable is changed, we type .br .nr wg 1v .ie \n(.h=\n(vk .nr wg -\n(vhu .el .nr vh 0 .if \n(wg>0 \{\ .sp \n(wgu .nr vh +\n(wgu \} .nr vk \n(.h .in +8n .nf .ne 5 > \fBtrace\fP \fIvariable\fP .br .nr wg 1v .ie \n(.h=\n(vk .nr wg -\n(vhu .el .nr vh 0 .if \n(wg>0 \{\ .sp \n(wgu .nr vh +\n(wgu \} .nr vk \n(.h .in -8n .fi .br .nr wg 1v .ie \n(.h=\n(vk .nr wg -\n(vhu .el .nr vh 0 .if \n(wg>0 \{\ .sp \n(wgu .nr vh +\n(wgu \} .nr vk \n(.h .ne 3 .ti +5n Finally, to have each source line printed as it's about to be executed, we simply say .br .nr wg 1v .ie \n(.h=\n(vk .nr wg -\n(vhu .el .nr vh 0 .if \n(wg>0 \{\ .sp \n(wgu .nr vh +\n(wgu \} .nr vk \n(.h .in +8n .nf .ne 5 \fBtrace\fP .br .nr wg 1v .ie \n(.h=\n(vk .nr wg -\n(vhu .el .nr vh 0 .if \n(wg>0 \{\ .sp \n(wgu .nr vh +\n(wgu \} .nr vk \n(.h .in -8n .fi After issuing a trace command, \fIpdx\fP displays all currently active traces. Each command is identified with a number in parentheses. To turn off a trace, give the command .br .nr wg 1v .ie \n(.h=\n(vk .nr wg -\n(vhu .el .nr vh 0 .if \n(wg>0 \{\ .sp \n(wgu .nr vh +\n(wgu \} .nr vk \n(.h .in +8n .nf .ne 5 > \fBdelete\fP \fIcommand-number\fP .br .nr wg 1v .ie \n(.h=\n(vk .nr wg -\n(vhu .el .nr vh 0 .if \n(wg>0 \{\ .sp \n(wgu .nr vh +\n(wgu \} .nr vk \n(.h .in -8n .fi Tracing information will be printed every time the program is run until it is explicitly turned off by giving the \fBdelete\fP command. .br .nr wg 1v .ie \n(.h=\n(vk .nr wg -\n(vhu .el .nr vh 0 .if \n(wg>0 \{\ .sp \n(wgu .nr vh +\n(wgu \} .nr vk \n(.h .ne 3 .ti +5n To display the information that you are currently tracing, say .br .nr wg 1v .ie \n(.h=\n(vk .nr wg -\n(vhu .el .nr vh 0 .if \n(wg>0 \{\ .sp \n(wgu .nr vh +\n(wgu \} .nr vk \n(.h .in +8n .nf .ne 5 > \fBstatus\fP .br .nr wg 1v .ie \n(.h=\n(vk .nr wg -\n(vhu .el .nr vh 0 .if \n(wg>0 \{\ .sp \n(wgu .nr vh +\n(wgu \} .nr vk \n(.h .in -8n .fi .br .nr wg 2v .ie \n(.h=\n(vk .nr wg -\n(vhu .el .nr vh 0 .if \n(wg>0 \{\ .sp \n(wgu .nr vh +\n(wgu \} .nr vk \n(.h .ne 6 \fBStopping and Continuing\fP .br .nr wg 1v .ie \n(.h=\n(vk .nr wg -\n(vhu .el .nr vh 0 .if \n(wg>0 \{\ .sp \n(wgu .nr vh +\n(wgu \} .nr vk \n(.h .ti +5n Sometimes, when debugging, we want to stop our program, look at some data, and then continue execution. The \fBstop\fP command allows the suspension of execution. To continue execution from where it was suspended, the \fBcont\fP command is used. There are four ways to describe when execution should be stopped: .in +5n .if n .nr In 5 .if t .nr In 8 .in +\n(Inn .ta \n(Inn .br .nr wg 1v .ie \n(.h=\n(vk .nr wg -\n(vhu .el .nr vh 0 .if \n(wg>0 \{\ .sp \n(wgu .nr vh +\n(wgu \} .nr vk \n(.h .ti -\n(Inn \&\fBstop\fP \fBif\fP \fIcondition\fP .br \c Execution is stopped if the specified condition becomes true. The condition can be any Pascal boolean expression. .br .nr wg 1v .ie \n(.h=\n(vk .nr wg -\n(vhu .el .nr vh 0 .if \n(wg>0 \{\ .sp \n(wgu .nr vh +\n(wgu \} .nr vk \n(.h .ti -\n(Inn \&\fBstop\fP \fBat\fP \fIsource-line-number\fP .br \c Execution is stopped when the \fIline\fP is about to executed. .br .nr wg 1v .ie \n(.h=\n(vk .nr wg -\n(vhu .el .nr vh 0 .if \n(wg>0 \{\ .sp \n(wgu .nr vh +\n(wgu \} .nr vk \n(.h .ti -\n(Inn \&\fBstop\fP \fBin\fP \fIprocedure\fP .br \c Execution is stopped when the \fIprocedure\fP is called. .br .nr wg 1v .ie \n(.h=\n(vk .nr wg -\n(vhu .el .nr vh 0 .if \n(wg>0 \{\ .sp \n(wgu .nr vh +\n(wgu \} .nr vk \n(.h .ti -\n(Inn \&\fBstop\fP \fIvariable\fP .br \c Execution is stopped when the \fIvariable\fP is about to be changed. .in -\n(Inn .br .nr wg 1v .ie \n(.h=\n(vk .nr wg -\n(vhu .el .nr vh 0 .if \n(wg>0 \{\ .sp \n(wgu .nr vh +\n(wgu \} .nr vk \n(.h .in -5n Execution is also stopped by an interrupt, i.e. by typing the RUB or DEL key. .br .nr wg 1v .ie \n(.h=\n(vk .nr wg -\n(vhu .el .nr vh 0 .if \n(wg>0 \{\ .sp \n(wgu .nr vh +\n(wgu \} .nr vk \n(.h .ne 3 .ti +5n Execution can be momentarily continued by the commands \fBnext\fP and \fBstep\fP. The \fBnext\fP command stops after one source line has been executed. The \fBstep\fP command stops at the next source line to be executed. These are only different when the current source line contains a call to a procedure or function. \fBStep\fP will stop at the beginning of the subprogram, \fBnext\fP will not. As in tracing, stops are set until explicitly unset with the \fBdelete\fP command. .br .nr wg 2v .ie \n(.h=\n(vk .nr wg -\n(vhu .el .nr vh 0 .if \n(wg>0 \{\ .sp \n(wgu .nr vh +\n(wgu \} .nr vk \n(.h .ne 6 \fBSource Program Manipulation\fP .br .nr wg 1v .ie \n(.h=\n(vk .nr wg -\n(vhu .el .nr vh 0 .if \n(wg>0 \{\ .sp \n(wgu .nr vh +\n(wgu \} .nr vk \n(.h .ti +5n \fIPdx\fP allows you to view your program during debugging. For example, to print lines 10 to 20 from ``prog.p'', you would type .br .nr wg 1v .ie \n(.h=\n(vk .nr wg -\n(vhu .el .nr vh 0 .if \n(wg>0 \{\ .sp \n(wgu .nr vh +\n(wgu \} .nr vk \n(.h .in +8n .nf .ne 5 > \fBlist\fP 10,20 .br .nr wg 1v .ie \n(.h=\n(vk .nr wg -\n(vhu .el .nr vh 0 .if \n(wg>0 \{\ .sp \n(wgu .nr vh +\n(wgu \} .nr vk \n(.h .in -8n .fi If you actually wish to change your program, or look at it in a more sophisticated manner, the command .br .nr wg 1v .ie \n(.h=\n(vk .nr wg -\n(vhu .el .nr vh 0 .if \n(wg>0 \{\ .sp \n(wgu .nr vh +\n(wgu \} .nr vk \n(.h .in +8n .nf .ne 5 > \fBedit\fP .br .nr wg 1v .ie \n(.h=\n(vk .nr wg -\n(vhu .el .nr vh 0 .if \n(wg>0 \{\ .sp \n(wgu .nr vh +\n(wgu \} .nr vk \n(.h .in -8n .fi will invoke the editor on your program. You can also say .br .nr wg 1v .ie \n(.h=\n(vk .nr wg -\n(vhu .el .nr vh 0 .if \n(wg>0 \{\ .sp \n(wgu .nr vh +\n(wgu \} .nr vk \n(.h .in +8n .nf .ne 5 > \fBedit\fP \fIprocedure\fP .br .nr wg 1v .ie \n(.h=\n(vk .nr wg -\n(vhu .el .nr vh 0 .if \n(wg>0 \{\ .sp \n(wgu .nr vh +\n(wgu \} .nr vk \n(.h .in -8n .fi and \fIpdx\fP will invoke the editor on your program and position the current line on the first line of the \fIprocedure\fP. .br .nr wg 1v .ie \n(.h=\n(vk .nr wg -\n(vhu .el .nr vh 0 .if \n(wg>0 \{\ .sp \n(wgu .nr vh +\n(wgu \} .nr vk \n(.h .ne 3 .ti +5n If you change your program and wish to start debugging the new version, you should give the command .br .nr wg 1v .ie \n(.h=\n(vk .nr wg -\n(vhu .el .nr vh 0 .if \n(wg>0 \{\ .sp \n(wgu .nr vh +\n(wgu \} .nr vk \n(.h .in +8n .nf .ne 5 > \fBpi\fP .br .nr wg 1v .ie \n(.h=\n(vk .nr wg -\n(vhu .el .nr vh 0 .if \n(wg>0 \{\ .sp \n(wgu .nr vh +\n(wgu \} .nr vk \n(.h .in -8n .fi This command runs \fIpi\fP on your program, and automatically reads in the new information that \fIpdx\fP needs from the new \fIobj\fP file. .br .nr wg 2v .ie \n(.h=\n(vk .nr wg -\n(vhu .el .nr vh 0 .if \n(wg>0 \{\ .sp \n(wgu .nr vh +\n(wgu \} .nr vk \n(.h .ne 6 \fBCommand Aliasing\fP .br .nr wg 1v .ie \n(.h=\n(vk .nr wg -\n(vhu .el .nr vh 0 .if \n(wg>0 \{\ .sp \n(wgu .nr vh +\n(wgu \} .nr vk \n(.h .ti +5n The \fBalias\fP command is used to create a new name for a command. This is especially useful for saving typing by defining abbreviations as aliases. For example, if you gave the command .br .nr wg 1v .ie \n(.h=\n(vk .nr wg -\n(vhu .el .nr vh 0 .if \n(wg>0 \{\ .sp \n(wgu .nr vh +\n(wgu \} .nr vk \n(.h .in +8n .nf .ne 5 > \fBalias\fP r run .br .nr wg 1v .ie \n(.h=\n(vk .nr wg -\n(vhu .el .nr vh 0 .if \n(wg>0 \{\ .sp \n(wgu .nr vh +\n(wgu \} .nr vk \n(.h .in -8n .fi then you could use ``r'' to run your program. .br .nr wg 2v .ie \n(.h=\n(vk .nr wg -\n(vhu .el .nr vh 0 .if \n(wg>0 \{\ .sp \n(wgu .nr vh +\n(wgu \} .nr vk \n(.h .ne 6 \fBWhere to go from here\fP .br .nr wg 1v .ie \n(.h=\n(vk .nr wg -\n(vhu .el .nr vh 0 .if \n(wg>0 \{\ .sp \n(wgu .nr vh +\n(wgu \} .nr vk \n(.h .ti +5n If you feel comfortable what we've discussed here, you're ready to read the \fIpdx\fP manual page. It contains a complete, but brief, description of the commands discussed here along with some other commands that you might find useful. .br .nr wg 2v .ie \n(.h=\n(vk .nr wg -\n(vhu .el .nr vh 0 .if \n(wg>0 \{\ .sp \n(wgu .nr vh +\n(wgu \} .nr vk \n(.h .ne 6 \fBReferences\fP .br .nr wg 1v .ie \n(.h=\n(vk .nr wg -\n(vhu .el .nr vh 0 .if \n(wg>0 \{\ .sp \n(wgu .nr vh +\n(wgu \} .nr vk \n(.h .ti +5n .ti -5n .if n .nr In 5 .if t .nr In 8 .in +\n(Inn .ta \n(Inn .br .nr wg 1v .ie \n(.h=\n(vk .nr wg -\n(vhu .el .nr vh 0 .if \n(wg>0 \{\ .sp \n(wgu .nr vh +\n(wgu \} .nr vk \n(.h .ti -\n(Inn \&[Joy, Graham and Haley 80] .br \c Joy, W., Graham, S., and Haley, C., ``Berkeley Pascal User's Manual'', version 2.0, EECS Dept., Univ. of Calif. at Berkeley, October 1980. .in -\n(Inn .br .nr wg 1v .ie \n(.h=\n(vk .nr wg -\n(vhu .el .nr vh 0 .if \n(wg>0 \{\ .sp \n(wgu .nr vh +\n(wgu \} .nr vk \n(.h