5.2.2 Debugging an Example Program in CSS

This section illustrates the use of the debugging facilities within CSS. We will use the example program from the previous section, with the addition of the two extra lines of code that were added in define mode. It is important to note that some important aspects of debugging like breakpoints can only be used when a program was started with the run command. Thus, do not set breakpoints if you are going to be simply calling a function on the command line.

There are three primary debugging tools in CSS: breakpoints, execution tracing, and single-stepping. Because CSS is basically an interpreted system, all of the facilities for examining variables, the stack, source code, etc. which must be added into a real debugger come for "free" in CSS.

To illustrate, we will set a breakpoint in the Decode_Number function (assuming you have loaded this code already):

css> list Decode_Number
(String) Decode_Number((Real) number) {
4         String rval = "The number, " + number + " is: ";
5         if(number < 0)
6           rval += "negative";
7         else if(number < .5)
8           rval += "less than .5";
9         else if(number < 1)
10          rval += "less than 1";
11        else
12          rval += "greater than 1";
13        return rval;
14      }
css> setbp 5
css> showbp
Decode_Number   5         if(number < 0)
css>

Note that we first listed the function (referring to it by name), and then set a breakpoint with the setbp command at line number 5. We then confirmed this breakpoint with the showbp command.

Now, when we run the program, execution will stop at line 5, and we will be returned to the css> prompt:

css> run
2 css>

which has changed to 2 css>, indicating that we are 2 levels deep into the execution of the program. To see where we are, list and status can be used:

2 css> list

Listing of Program: css_example.css
4         String rval = "The number, " + number + " is: ";
5         if(number < 0)
6           rval += "negative";
7         else if(number < .5)
8           rval += "less than .5";
9         else if(number < 1)
10          rval += "less than 1";
11        else
12          rval += "greater than 1";
13        return rval;
14      }
28      list
2 css> status

        Status of Program: css_example.css
curnt:  Decode_Number   src_ln: 5       pc:     9
debug:  0       step:   0       depth:  2       conts:  2
lines:  29      list:   28
State: shell:   1   run: 0  cont:   0  defn:   0  runlast: 0
run status:     Waiting
shell cmd:      None
2 css>

The src_ln of the status output tells us which source-code line we are at (and what function we are in). Here, we can use the interactive mode of css to determine the values of our variables:

2 css> print number
(Real) number = 0.75
2 css> print rval
(String) rval = The number, 0.75 is:

The values of all of the variables for the current "frame" (there is one frame for every call to a given function, or any expression appearing between the curly-brackets) can be viewed at once with the frame command:

2 css> frame

Elements of Spaces For Program: Decode_Number (frame = 1)

Elements of Space: Autos (3)
(String) _retv_this =                   (Real) number = 0.75
(String) rval = The number, 0.75 is:

Elements of Space: Stack (0)

Elements of Space: css_example.css.Static (3)
(String) Decode_Number((Real) number)   (void) Decode_Random((Int) n_numbers)
(String) foo = a string

Included in the frame information are the "automatic" variables (Autos), and the contents of the stack. To get information on previous frames in the execution sequence, use the command trace, which gives both a trace of processing and can give a dump of the entire stack up to this point if given a higher "trace level", which is an optional argument to the trace command. The default trace level of 0 just shows the frames, 1 also shows the stack, 2 also shows the auto variables, and 3 shows all variables. In addition, just the contents of the current stack can be viewed with the stack command (note that the saved stack is what is actually used by the program during execution).

In addition to viewing variables, it is possible to change their values:

2 css> number = 200;
2 css> print number
(Real) number = 200

Finally, to continue the program from where it was stopped by the breakpoint, use the cont command:

2 css> cont
The number, 0.75 is: greater than 1
5 css> 

Since we changed the number after it was turned into a string for the rval, but before the if statements, we got the contradictory result printed above. Also, because the breakpoint is still in effect, the program has stopped due to the Decode_Random function calling the Decode_Number function. We can continue again, or we can disable the breakpoint first, and then continue.

5 css> cont
0       The number, 0.764017 is: less than 1
5 css> unsetbp 5
5 css> showbp
5 css> cont
1       The number, -1.76456 is: negative
2       The number, 1.59942 is: greater than 1
3       The number, -1.34582 is: negative
4       The number, -1.36371 is: negative
css>

Note that the breakpoint is referred to by the source-code line number.

Another way to debug is to get a trace of the running program. This can be done by setting the debug level, which can have a value from 0 (normal, quiet operation) through 4, with higher levels giving more detail than lower levels. For most users, levels 0 and 1 are the only ones needed, since the higher levels depend on understanding the guts of the CSS machine code. Debug level 1 shows the source-code line corresponding to the currently-executing code:

css> debug 1
css> run
31      run
3       String Decode_Number(float number) {
17      void Decode_Random(int n_numbers) {
26      cout << Decode_Number(.75) << "\n";
4         String rval = "The number, " + number + " is: ";
5         if(number < 0)
5         if(number < 0)
5         if(number < 0)
7         else if(number < .5)
7         else if(number < .5)
7         else if(number < .5)
9         else if(number < 1)
9         else if(number < 1)
9         else if(number < 1)
10          rval += "less than 1";
13        return rval;
26      cout << Decode_Number(.75) << "\n";
The number, 0.75 is: less than 1
27      Decode_Random(5);
18        int i;
19        for(i=0; i<n_numbers; i++) {
.
.
.

Since running proceeds from the top to the bottom, the definitions of the functions appear in the trace even though they do not really do anything. Also, some constructs like if and for result in multiple copies of the same source-code line being printed. This kind of trace is useful for seeing what branches of the code are being taken, etc.

The final kind of debugging is single-stepping, which is like having a breakpoint after every line of source code. Execution continues after each point by simply entering a blank line:

css> debug 0
31      debug 0
css> step 1
css> run
31      run
3       String Decode_Number(float number) {
1 css>
17      void Decode_Random(int n_numbers) {
1 css>
26      cout << Decode_Number(.75) << "\n";
4         String rval = "The number, " + number + " is: ";
2 css> print number
31      print number
(Real) number = 0.75
2 css> print rval
(String) rval = The number, 0.75 is:
5         if(number < 0)
3 css>
7         else if(number < .5)
4 css>
9         else if(number < 1)
5 css>
10          rval += "less than 1";
4 css>
13        return rval;
26      cout << Decode_Number(.75) << "\n";
The number, 0.75 is: less than 1
1 css>
27      Decode_Random(5);
18        int i;
2 css>
19        for(i=0; i<n_numbers; i++) {
19        for(i=0; i<n_numbers; i++) {
20          float number = 4.0 * (drand48()-.5);
4 css>

(note that we turned debugging off, since it is redundant with single-stepping). The step command takes an argument, which is the number of lines to step over (typically 1). Then, when we run the program again, it stops after every line. If you simply want to continue running, you can just hit return and it will continue to the next line.

If at any point during debugging you want to stop the execution of the program and return to the top-level (i.e., get rid of that number in front of the prompt), use the restart command.

4 css> restart
34      restart
css>

Be sure not to confuse restart with reset, as the latter will erase the current program from memory (you can just reload it with reload, so its not so bad if you do).