Page Numbers: Yes First Page: 33 X: 527 Y: 10.5"
Margins: Binding: 13
Odd Heading: Not-on-first-page
Debugger
Even Heading:
Debugger
Appendix E: Debugger
The common facilities available in the Mesa debugger include setting breakpoints, tracing program execution, displaying the runtime state, and interpreting Mesa statements. It will be easiest to understand how to access these facilities by going through a simple example using many of the common commands.
Installing the debugger
Install the debugger from the command line of the Alto Executive by typing XDebug. To load programs into the debugger at the same time as installing the debugger, list the names of the programs on the command line; use the "L" switch to load programs with code links (to save space). For example, typing XDebug Foo/L (to the Alto Executive) loads Foo with code links and installs the debugger. Installing the debugger with the /b switch will video reverse the display (i.e., white characters on a black background).
Fonts
The Debugger requires a strike font named MesaFont.strike or SysFont.strike; a version of Gacha10 is available on <Mesa>MesaFont.strike. Strike fonts can be found where alto fonts are stored. (Strike fonts that include kerning are not supported.)
Memory Bank Management
When running on machines with more than 64K of memory, the client system supplies space to the Debugger for the Debugger’s bitmap (unless all but one bank has been disabled; see below); the client can disable this option by using the /k switch.
It is also possible for the Debugger to be installed with more than one bank of memory available for code swapping; this is done by reducing the amount of memory available to the client using the RunMesa bank switches or the Alto Executive MesaBanks.~ command (in Executive version 11 or later).
MesaBanks.~
This command establishes the default memory allocation available to client programs. Arguments can be in two forms: a sixteen bit octal mask (followed by an optional /b switch) indicating the available banks; a one in bit position n of the mask (counting from the left) indicates that bank n is available. Form two is a series of decimal bank numbers each followed by the /x switch; each bank mentioned is excluded from use by the client. Note that a request to exclude bank zero will be ignored. If no argument is present, the command will display the current value of the bank mask.
The MesaBanks.~ command establishes the available memory for each .image or .bcd program invoked directly by the Alto Executive. The default may be overridden by explicitly using RunMesa to invoke the program and optionally specifying bank switches on its command line, before the .image file name. The bank switches have the same format as the arguments to MesaBanks.~ (except that the /b switch is required in the case of a bitmask). In the absense of any bank switches, RunMesa always assumes that all banks are available to the client.
Using these facilities, it is possible to set up the defaults so that the Debugger has extra banks of memory at the expense of the client program. For example, on a three bank Alto, the following commands might be used to set the default and then install the Debugger:
MesaBanks.~ 2/x
RunMesa.run 1/x XDebug.image
Under this arrangement, the client would use banks zero and one, and the Debugger would use banks zero and two (because bank zero is swapped onto Swatee, it can be used by both). Actually, because the client (by default) is also allocating space for the Debugger’s display bitmap, the client actually has only one-and-one-half banks, and the Debugger has two-and-one-half; this can be changed by running the client with the /k switch, resulting in two banks available to each.
Note that the MesaBanks.~ command affects all Mesa programs invoked by the Alto Executive, including the Compiler and Binder. So the above example would run the Compiler in only two banks, not three; this can be changed by saying RunMesa Compiler on the command line, which, because there are no bank switches specified, defaults to all banks available (not really necessary in this case, since the Compiler runs almost as well in two banks as in three). On the next new session, the Debugger is smart enough to notice that the Compiler (or whoever) has smashed what it thought was in bank two. (It is also smart enough not to use any memory that the client owns, so that the 1/x switch on the command line above is actually unnecessary.)
Since there are a lot of options here, some "standard" examples of client and Debugger configurations might be helpful:
Two Banks: Normally, do nothing; client and Debugger will each have one-and-one-half banks. For small clients and better Debugger performance, use RunMesa 1/x Mesa.image Client.bcd, which will give the client one bank and the Debugger two. (If you were to use MesaBanks.~ 1/x in this case, the Compiler would also be restricted to one bank).
Three Banks: As in the three bank example above.
Four Banks: Use MesaBanks.~ 3/x to give the client and the Debugger two-and-one-half banks each and the Compiler three; use MesaBanks.~ 2/x 3/x and Client/k to increase the Debugger’s allocation to three banks and restrict the client to two. Obviously, this can be adjusted based on the size of the client and the desired performance of the Debugger.
Files
The debugger itself is contained in the file XDebug.image. There are several other files that are used by the debugger and should not be edited or deleted from your disk. These are the swapping files used by the debugger: Swatee (to hold the user’s core image), MesaDebugger (to hold the debugger’s core image), and Debug.log (used as a record of your debugging session). If you don’t want your swatee to be used, create the file MesaCore and the debugger will use that instead.
Signals and errors
See the Mesa Debugger Documentation for details on the common signal and error messages you might receive and suggestions for recovery.
Sample program
The configuration we are going to use as an example is taken from the Mesa Language Manual (Chapter 7). The following files should be retrieved from Mesa>Doc: LexiconClient.mesa, Lexicon.mesa, LexiconDefs.mesa, LexiconClient.bcd, Lexicon.bcd, LexiconDefs.bcd, Lex.config, Lex.bcd, and Lex.ts (a sample typescript of the debugging session that follows).
The sample configuration Lex consists of two modules, Lexicon and LexiconClient. After the modules have been compiled and the configuration has been successfully bound, you are ready to load and debug the program.
Entering the debugger
Let us assume that the configuration has been loaded and started (by typing Lex to the Alto Executive), and you have interrupted the program and entered the debugger for the first time (by holding down Control-Swat after the program has started). You get a herald that indicates which version of the debugger you are using and when it was built, followed by the current date and time, a message indicating why you entered the debugger (in this case, interrupting the program), and a prompt for the first command:
Alto/Mesa Debugger 6.0m of 12-Sep-80 23:21
12-Sep-80 23:41
*** interrupt ***

>
Setting the context
In order to get to a context from which you can set breakpoints in one of the modules in Lex, let’s first check to see which configurations have been loaded by saying:
>List Configurations [confirm]
which responds with:
Lex
Mesa
Nucleus
If we check the context at this point, you can see that the current module is NubControl in the Mesa configuration,
>CUrrent context
Module: DebugNub, G: 172764B, L: 166160B, PSB: 3700B
Configuration: Mesa.
We need to set the current configuration to be Lex,
>SEt Root configuration: Lex
and find out which modules are in this configuration,
>Display Configuration Lex
Lexicon, G: 150404B~
LexiconClient, G: 150424B
Notice the ~ indicating that Lexicon hasn’t been started yet. Now we can set the context to be Lexicon, so that we can set some breakpoints
>SEt Module context: Lexicon
Setting breakpoints by selections
Let’s load the source text for Lexicon into a window so we can set breakpoints by pointing at the text. This may be done in one of two ways: either display the stack and ask to see the source (this loads and positions the source file for the current module into the source window of the debugger),
>Display Stack
Lexicon, G: 150404B~ >s Cross jumped!
--Lexicon.mesa
>q
or load the file into a source window by 1) selecting the file name Lexicon (the extension defaults to .mesa), 2) moving into a source window (there is always at least one around), and 3) choosing the Load command from the menu. Note the message warning that Lexicon was compiled with the cross jumping switch turned on. Additional source windows can be created, destroyed, and moved around as needed, using the appropriate menu commands.
Now move into the window containing the source file, and put this window on top. This can be done by either clicking the red mouse button in the left or right sections of the window header, or by selecting the window menu command Top.
Suppose we want to set a breakpoint on the exit of the procedure NewNode. Scroll the window until this procedure is visible, then select the word RETURN inside this procedure. Hold down the menu button (yellow button) and choose the SetBreak command. This sets a breakpoint on the exit of the procedure (similarly, selecting the word PROCEDURE or PROC sets a breakpoint on the entry to the procedure).
Suppose you want to set a breakpoint in the end of one of the conditional IF-THEN-ELSE statements in the procedure InsertString. This can be done by selecting any place in the statement ELSE n.llink ← NewNode[];. Confirmation of where the breakpoint has been set is given by the moving the selection to the first character of the statement: ELSE <>n.llink ← NewNode[]; (Note that in all cases, the closest enclosing statement is the place at which the breakpoint is actually set).
Setting breakpoints by type-in
You may also set entry and exit breakpoints in the program using keyboard commands. For any breakpoint, you may specify a condition that must be satisfied in order for the breakpoint to be taken. If, for instance, you want to set a breakpoint on the entry to the procedure FindString, and enter the debugger only if root is not NIL, say:
>Break Entry procedure: FindString Breakpoint #3.
>ATtach Condition #: 3, condition: root # NIL.
Inserting comments
Saving some comments along with the commands is a good idea, so that it is easier to remember what happened when looking back at the typescript file. For instance you might now say,
>--This breakpoint was set to skip checking for a lexicon if we
>--know the tree is empty.
Proceeding
It is now time to proceed and run the program. This is done by executing the following command:
>Proceed [confirm].
If we try to add the lexeme "xxxxx" to the tree, we will then reach our breakpoints.
Examine and change the state
You next enter the debugger at the first breakpoint with the herald:
>Break #1 at exit from NewNode, L: 165424B, PC: 274B (in Lexicon, G: 150404B)
to indicate where you are. At this point you might display the stack and look at the variables,
>Display Stack
NewNode, L: 165424B, PC: 274B (in Lexicon, G: 150404B) >v
n = 147374B↑
>q
or look at the several levels of the stack,
>Display Stack
NewNode, L: 165424B, PC: 274B (in Lexicon, G: 150404B) >n
InsertString, L: 165434B, PC: 162B (in Lexicon, G: 150404B) >n
AddString, L: 165444B, PC: 137B (in Lexicon, G: 150404B) >n
CommandProc, L: 170420B, PC: 470B (in LexiconClient, G: 150424B) >n
LexiconClient, L: 165464B, PC: 257B (in LexiconClient, G: 150424B) >n
No symbols for L: 172614B, PC: 702B (in MesaNub, G: 172670B) >q
or ask to see what the node n (in NewNode) looks like (invoke the interpreter by typing SP),
> n↑
[llink:NIL, rlink:NIL, string:(5,5)"xxxxx"]
.
Let’s say we wanted to set both the left link and right link of n to point to n itself and then check the value of n. This may be done by saying,
> n.llink ← n; n.rlink ← n; n; n↑
which responds with,
147374B↑
[llink:147374B↑, rlink:147374B↑, string:(5,5)"xxxxx"].
If at this point we want to see the value of the variable root in the module LexiconClient (a variable in the current configuration but not in the current module), this may be done by saying,
>Find variable: root
which responds with the value of root, and where it was found:
NIL (in Lexicon, G: 150404B).
More breakpoint commands
The following command lists all of the breakpoints that have been set:
>LIst Breaks [Confirm]
1 -- Break at exit from NewNode (in Lexicon, G: 150404B).
2 -- Break in InsertString (in Lexicon, G: 150404B).
Cross jumped!
ELSE <>n.llink ← NewNode[];
3 -- Break at entry to FindString (in Lexicon, G: 150404B). Condition: root # NIL;
If you decide that you are no longer interested in any of these breakpoints you can
>Clear All Breaks [confirm]
which removes all breakpoints and restores the instructions.
Look at the user world
If you are interested in seeing the state of the user display, you can look at the user world by saying
>Userscreen [confirm].
When you want to return to the debugger, hit either the Swat key or FR5; this brings you back into the debugger, ready to execute more commands.
Setting tracepoints
Suppose next you want to set a trace on the entry to the procedure LexicalCompare so that you can simply see the two strings being compared and go on. You may do so by saying,
>Trace Entry procedure: LexicalCompare Breakpoint #4.
Now we should proceed
>Proceed [confirm]
and try to add a new lexeme, say "yyy".
When the tracepoint is reached, you get the herald indicating why you entered the debugger, where you are, and a dump of the input parameters of the procedure:
Trace #4 at entry to LexicalCompare, L: 165750B, PC: 276B (in Lexicon, G: 150404B)
>Display Stack
LexicalCompare, L: 165750B, PC: 276B (in Lexicon, G: 150404B) >P
s1 = (3,80)"yyy"
s2 = (5,5)"xxxxx"
>
leaving you in Display Stack. Type ’q’ to terminate the Display Stack command, and then continue executing your program
>Proceed [confirm].
This represents a brief introduction to the use of most of the debugger’s commands that you will commonly need. See the Mesa Debugger Documentation for further details; the best teachers are experienced Mesa programmers and lots of practice!!!