\" format using the mm macros
.po 1.25i
.ll 6i
.nh
.ds HF 3
.nr Hi 2
.ce
\s+5Using the Debugger \fISdb\fR With \fIUvapc\fR\s-5
.sp 2
.H 1 "Introduction"
.P 1
Although the debugger \fIsdb\fR(1) is directed more toward
the C programming language than Pascal,
\fIsdb\fR provides plenty of valuable information for
debugging Pascal if you know the right commands.
This document explains how to translate Pascal
syntax into the equivalent \fIsdb\fR
syntax for printing program data.
Refer to the chapter on \fIsdb\fR in the
\fIAT&T Unix System V Programmer's
Guide\fR to learn how to use the debugger.
For complete, but terse documentation,
see the manual page for \fIsdb\fR.
.H 1 "Invoking \fISdb\fP"
.P 1
For \fIsdb\fR to be of any use at all,
you must first compile your program with
the \fB-g\fR option of \fIuvapc\fR.
The \fB-g\fR option has no effect on the speed of compiled code, but
it does slow down the compilation process slightly,
and the extra symbolic information increases
the size of the executable file.
.P 1
If a Pascal program aborts due to an error,
the program creates a file called \fBcore\fR.
If you run \fIsdb\fR with this core file,
you can determine which functions\(dg
.FS \(dg
In this document the term \fIfunction\fR also includes Pascal procedures.
.FE
were active at the time of the abort,
and print out the variables and parameters of the
active functions.
.P 1
When running \fIsdb\fR on an executable created by \fIuvapc\fR,
\fIsdb\fR complains about not finding some
C language source files,
which are the source files for the \fIuvapc\fR
run time library.
Ignore these warnings.
.H 1 "Converting Pascal Identifiers to \fISdb\fP Identifiers"
.P 1
The spelling of an identifier in \fIsdb\fR is not always the
same as the spelling of the corresponding identifier in
the Pascal source text.
If a Pascal identifier contains upper case letters, they are lower
case in \fIsdb\fR.
If a Pascal identifier is the name of a function
declared in the outermost block,
the identifier has an appended underscore in \fIsdb\fR.
If an identifier is the name of a function declared within another
function, the \fIsdb\fR identifier is the concatenation of all
the nested function names separated by underscores.
Here are some examples.
Pascal variable \fBArrayIndex\fR is \fBarrayindex\fR in \fIsdb\fR.
If the Pascal function \fBSort\fR is declared in the outermost block,
its name is \fBsort_\fR in \fIsdb\fR.
If \fBSort\fR encloses a function called \fBSwap\fR,
then \fBSwap\fR is known as \fBsort_swap\fR in \fIsdb\fR.
.H 1 "How \fISdb\fP Outputs Constants"
.P 1
\fISdb\fR knows nothing about the boolean constants \fBfalse\fR and
\fBtrue\fR, nor does \fIsdb\fR know about user defined enumeration
constants.
If a variable is type \fBboolean\fR or is an enumerated type,
\fBsdb\fR prints the ordinal value of the variable in decimal.
The ordinal values of the constants
\fBfalse\fR and \fBtrue\fR are zero
and one respectively.
The first constant of an enumerated type
has the ordinal value zero.
Subsequent constants in the enumeration have the
value of the previous constant plus one.
.H 1 "Printing a Stack Trace"
.P 1
If you print a stack trace with the \fIsdb\fR command \fBt\fR,
you may notice some functions whose names begin with \fBRT_\fR.
All the function names in the \fIuvapc\fR run time library have this
prefix.
The function at the bottom of the stack trace is always \fBmain\fR,
the main Pascal program.
.H 1 "Printing a Simple Variable"
.P 1
Since \fIsdb\fR syntax is based on C, printing out Pascal variables
is sometimes tricky.
To print a simple variable, remember to convert the name properly.
For example, to print out Pascal variable
\fBSimple\fR, use this command:
.P 1
\fBsimple/\fR
.H 1 "Printing Arrays"
.P 1
The \fIsdb\fR syntax for printing array elements is similar
to Pascal,
but in \fIsdb\fR the beginning element of an array is always
numbered zero and subscripts are always numbers.
Suppose we have this Pascal declaration:
.P 1
\fBA : array[-3 .. 3] of integer;\fR
.P 0
To print an element of \fBA\fR you must
subtract the lower subscript bound
from the desired subscript.
This is the \fIsdb\fR command to print \fBA[-2]\fR:
.P 1
\fBa[1]/\fR
.P 0
If the array subscript type is \fBchar\fR, \fBboolean\fR,
or an enumeration,
you must supply the equivalent ordinal value of the subscript.
If the Pascal program has this declaration:
.P 1
\fBC : array ['a' .. 'z'] of integer;\fR
.P 0
and you want to print \fBC['d']\fR,
this is the correct \fIsdb\fR command:
.P 1
\fBc[3]/\fR
.P 0
You can specify a range of array elements with a semicolon:
.P 1
\fBa[1;5]/\fR
.P 0
Multi-dimensional array syntax is also similar to Pascal.
Consider this Pascal declaration:
.P 1
\fBMatrix : array[1..5, 1..20] of integer;\fR
.P 0
You can print the Pascal array element
\fBMatrix[5,4]\fR with either of the following:
.P 1
\fBmatrix[4,3]/\fR
.P 1
\fBmatrix[4][3]/\fR
.P 0
Fortunately, complex subscript translations are not always
necessary since \fIsdb\fR prints all the elements of an
array when you omit the subscript.  This command:
.P 1
\fBmatrix/\fR
.P 0
prints all 100 elements of the array, varying the second subscript
more rapidly.
.H 1 "Printing Records"
.P 1
Record field syntax in \fIsdb\fR is comparable to Pascal.
This command prints out the Pascal record field
\fBperson.MaritalStatus\fR:
.P 1
\fBperson.maritalstatus/\fR
.P 0
Omitting the field name prints all fields:
.P 1
\fBperson/\fR
.H 1 "Printing Pointers"
.P 1
Pointer syntax in \fIsdb\fR differs from Pascal.
Consider this Pascal declaration:
.P 1
\fBptr : \(uainteger;\fR
.P 0
This \fIsdb\fR command:
.P 1
\fBptr/\fR
.P 0
prints out the value stored in \fBptr\fR, which is
the memory address of the object that \fBptr\fR points to.
This address is usually a fairly large hexadecimal number.
If \fIsdb\fR outputs zero, \fBptr\fR is \fBnil\fR.
Use this command to print out \fBptr\(ua\fR:
.P 1
\fBptr[0]/\fR
.P 0
Although it looks strange,
this command makes perfectly good sense in terms of C syntax.
Suppose the Pascal pointer \fBrecptr\fR points to a record type.
To print out \fBrecptr\(ua.field\fR, use this command:
.P 1
\fBrecptr[0].field/\fR
.P 0 
or use this shorter command based on C syntax:
.P 1
\fBrecptr->field\fR
.P 0
You can combine the \fIsdb\fR syntax rules for printing arrays,
records, and pointers to navigate through complex data structures.
.H 1 "Printing \fIVariable\fP Parameters"
.P 1
Function \fIvalue\fR parameters are printed the same way
as function variables.
\fIVariable\fR (\fBvar\fR) parameters are handled a little
differently, however.
\fIUvapc\fR passes a \fIvariable\fR parameter to a function
by assigning the memory address of the \fIactual\fR
parameter to the corresponding \fIformal\fR parameter.
Thus \fIsdb\fR considers a formal \fIvariable\fR parameter
to be a pointer.
Consider the following Pascal function declaration:
.P 1
\fBfunction f (var i : integer) : integer;\fR
.P 0
Printing \fBi\fR with the
following command doesn't work:
.P 1
\fBi/\fR
.P 0
This prints out the memory address of the \fIactual\fR parameter.
To print out the value stored in the \fIactual\fR parameter,
you need to dereference \fBi\fR as follows:
.P 1
\fBi[0]/\fR
.P 0
Consider the following array \fIvariable\fR parameter declaration:
.P 1
\fBtype arr = array [1 .. 10] of integer;\fR
.P 1
\fBfunction f (var a : arr) : integer;\fR
.P 0
\fISdb\fR thinks that \fBa\fR is a pointer to an array of integers.
To print out the entire array, you need to dereference \fBa\fR:
.P 1
\fBa[0]/\fR
.P 0
To print out the Pascal array element \fBa[2]\fR use this command:
.P 1
\fBa[0][1]/\fR
.H 1 "Printing Conformant Arrays"
.P 1
Conformant array parameters are handled slightly differently
and there is no distinction between \fIvalue\fR and \fIvariable\fR
conformant array parameters in \fIsdb\fR.
Like C, \fIsdb\fR treats variable length arrays like pointers.
Consider this Pascal procedure declaration:
.P 1
\fBprocedure p (ca : array [low1 .. hi1 : integer; low2 .. hi2 : integer]
of integer);\fR
.P 0
\fISdb\fR thinks that \fBca\fR is type pointer to integer
(\fB\(uainteger\fR).
The value stored in \fBca\fR is the address of the first element
in the conformant array.
\fISdb\fR knows neither the number nor the size of the array dimensions.
To print out element \fBca[low1,low2+3]\fR (the fourth element),
use the syntax for printing out an element in a single dimensional
array variable:
.P 1
\fBca[3]/\fR
.P 0
Obviously, it makes more sense to
print out a range of elements using the semicolon syntax:
.P 1
\fBca[0;30]/\fR
.P 0
You can also print the values of conformant array
\fIbound identifiers\fR such as \fBlow1\fR and \fBhi1\fR,
because \fIuvapc\fR implements them as \fIvalue\fR parameters.
.H 1 "Printing Sets"
.P 1
Printing out variables of \fBset\fR type is difficult because
\fIsdb\fR does not know how sets are implemented.
To print sets,
\fIuvapc\fR links into your program the run time system 
function \fBRT_set_dump\fR,
which you can call from \fIsdb\fR.
\fBRT_set_dump\fR takes a single parameter, the memory
address of a set variable, and prints the set members as
a list of decimal integers.
If a set's base type is \fBchar\fR, \fBboolean\fR,
or an enumeration, the
number printed for each  set member \fIm\fR is \fBord\fR(\fIm\fR).
Before calling \fBRT_set_dump\fR,
print the memory address of the set with this command:
.P 1
\fIsetvar\fB=\fR
.P 0
where \fIsetvar\fR is a set variable, parameter, array element, record
field, etc.
Then print out the set itself with this \fIsdb\fR
function call command:
.P 1
\fBRT_set_dump(\fIsetaddr\fB)\fR
.P 0
where \fIsetaddr\fR is the memory address of \fIsetvar\fR.
If \fIsetvar\fR is a pointer to a set or if
\fIsetvar\fR is a \fIvariable\fR parameter of set type,
then the value stored in \fIsetvar\fR is the memory address
of the set (not the set itself).
You can simply pass \fIsetvar\fR to
\fBRT_set_dump\fR instead of \fIsetaddr\fR:
.P 1
\fBRT_set_dump(\fIsetvar\fB)\fR
.P 0
Unfortunately, calling a function from \fIsdb\fR has
limitations.
You can only call a function when the program is
stopped at a breakpoint.
This prevents you from printing set
variables from a core file.
After making a function call from \fIsdb\fR you cannot
resume program execution from the breakpoint;
you must restart the program at the beginning.
