next previous contents
Next: Example Previous: Miscellaneous Features Up: Contents

Debugging Maisie Programs

Debugging support for Maisie programs is provided in two ways. First, by appropriately inserting two special Maisie constructs, called printmsg and trace, in the Maisie program, the user can monitor the execution of the program. The second alternative is to use the traditional source-level debuggers like dbx available with UNIX to step through the Maisie program. Rest of the section describes these features in detail.


Printing Messages in the Message Queue

It may be useful to examine the messages in an entity's message queue at a given point during execution. Maisie provides a function called printmsg() which prints out all messages in the message queue of the calling entity that are of type . The messages are printed in the order of the ranker associated with the last resume-condition in which mtype() is used, or by default in increasing timestamp order. If is omitted, all messages in the message queue are printed in increasing timestamp order. In the following examples, the first one prints all messages in timestamp order; the second prints all request messages in the message queue.


Example:

printmsg(); /* print all messages */ printmsg(request); /* print request messages */



Trace Facility

Maisie provides a simple trace facility to aid program debugging.



Trace Statement


	trace-st	::= trace value when condition;
	value		::= a C expression of type int
	condition	::= a C boolean expression (side-effect free)

An entity evaluates each condition in its body whenever a message is received. Depending on the value, the entity reacts differently.

The following examples illustrate the use of the trace facility. The statement in the first example causes the values of all non-array local variables of the receiving entity to be printed to stdout whenever a message is received. The second example illustrates that when the received message is of type request, its content is printed to stdout. The trace-statement in the third example prints out all messages but only when the variable myid is equal to 2.

Example:

trace 2; trace 1 when mtype(request); trace 1 when (myid == 2);

An entity definition may have more than one trace statement. The trace conditions are evaluated in the order that they appear in the entity body. The trace value specified in the first condition which evaluates to true determines the level of tracing to be performed for the entity. If all conditions evaluate to false, nothing will be printed.

Remarks:

  1. For efficiency, Maisie disables the trace facility by default. To use the facility, compile the program with the '-trace' flag.


Trace Message

Maisie defines a message type trace_msg for every entity. The message has a single parameter, trace_val, of type int. The value of trace_val determines the level at which tracing is to be performed in the receiving entity. The trace information will be printed for every subsequent message received by the entity. The level of tracing can only be changed by receiving another trace_msg message. The trace statement and message operate independently. If the two trace levels are different for a given entity instance, the larger of the two defines the tracing level.



Source Level Debugging

A Maisie program is translated into a C program which is then compiled using a C compiler. It is possible to debug at the level of Maisie source using a standard Unix C debugger. The program needs to be compiled using the '-g' flag. The entity parameters and local variables are renamed according to the following conventions:


Example:

entity XX { a } int a; /* a ==> zzp0->a */ { int b[5],i; /* b ==> zzp1->b, i unchanged */ int search(); /* search ==> _XX_search */ for(i =0; i < 5 ; ++) { int j; /* j ==> zzp2->j */ ... } } int XX::search(v) /* ==> _XX_search(v) */ int v; /* v unchanged */ { int i; /* i unchanged */ for(i =0; i < 5 ; ++) if(v == b[i ]) /* b ==> zzp1->b */ ... }

Below, we show a sample Maisie program, and how it is compiled, executed, and debugged in a dbx session. As seen in the program, line 8 will cause the program execution to have segmentation violation due to an incorrect array reference. Lines 34-37 show that parameter a of entity XX and local variable b may not be accessed directly. However, as seen in the listing, a has been renamed to zzp0->a, and variable b has been renamed to zzp1->b, and entity XX is actually the function XX.

     [1]  #include "maisie.h" 
     [2] 
     [3]  entity XX{ a } 
     [4]    int a; 
     [5]  { int b[5],i; 
     [6]    for(i=0; i< 5; i++) 
     [7]       b[i] = i; 
     [8]    b[a] ++; 
     [9]  }
     [10] 
     [11] entity driver{} 
     [12] { 
     [13]    new XX{10000}; 
     [14] }
Debugging: The sample program (sample.m)

     [24]  % mc -P -g sample.m
     [25]  % a.out
     [26]  Segmentation fault
     [27]  % dbx a.out
     [28]  Reading symbolic information...
     [29]  Read 1482 symbols
     [30]  (dbx) run
     [31]  Running: a.out 
     [32]  signal SEGV (no mapping at the fault address) in ...
     [33]    8   b[a] ++;
     [34]  (dbx) print b
     [35]  "b" is not defined
     [36]  (dbx) print a
     [37]  "a" is not defined
     [38]  (dbx) print zzp1->b
     [39]  zzp1->b = (0, 1, 2, 3, 4)
     [40]  (dbx) p zzp0->a
     [41]  `sample`XX`zzp0->a = 10000
Debugging: Using dbx

Common Maisie Runtime Errors

Runtime errors/warnings are detected by Maisie and appropriate messages are send to stderr. Some of the common errors/warnings are:



next previous contents
Next: Example Previous: Miscellaneous Features Up: Contents

Richard A. Meyer
Wed Apr 24 12:50:23 PDT 1996