.\"	Logging
.\"
.\"	$Id$
.bp
.NH
THE LOGGING MACHINE.
.PP
Since messages and warnings provided by \fBint\fP include source code file
names and line numbers, they alone often suffice to identify the error.
If, however, the necessity arises, much more extensive debugging information
can be obtained by activating the the Logging Machine.
This Logging Machine, which monitors all actions of the EM machine, is the
subject of this chapter.
.NH 2
Implementation.
.PP
When inspecting the source code of \fBint\fP, many lines in the
following format will show up:
.DS
LOG(("@<\fIletter\fP><\fIdigit\fP> message", args));
.DE
or
.DS
LOG(("\ <\fIletter\fP><\fIdigit\fP> message", args));
.DE
The double parentheses are needed, because \fILOG()\fP is
declared as a define, and has a printf-like argument structure.
.PP
The <\fIletter\fP> classifies the log message and corresponds to an entry in
the \fIlogmask\fP, which holds a threshold for each class of messages.
The following classes exist:
.TS
tab(@);
l l l.
\(bu  A\-Z@the flow of instructions:
@A:    array
@B:    branch
@C:    convert
@F:    floating point arithmetic
@I:    integer arithmetic
@L:    load
@M:    miscellaneous
@P:    procedure call
@R:    pointer arithmetic
@S:    store
@T:    compare
@U:    unsigned arithmetic
@X:    logical
@Y:    sets
@Z:    increment/decrement/zero
\(bu  d@stack dumping.
\(bu  g@gda & heap manipulation.
\(bu  s@stack manipulation.
\(bu  r@reading the loadfile.
\(bu  q@floating point calculations during reading the loadfile.
\(bu  x@the instruction count, contents and file position.
\(bu  m@monitor calls.
\(bu  p@procedure calls and returns.
\(bu  t@traps.
\(bu  w@warnings.
.TE
.LP
When the interpreter reaches a LOG(()) statement it scans its first argument;
if \fIletter\fP
occurs in the logmask, and if \fIdigit\fP is lower or equal to the
threshold in the logmask, the message is given.
Depending on the first character, the message will be preceded by a
position indication (with the @) or will be printed as is (with the
space).
The \fIletter\fP is determines the message class
and the \fIdigit\fP is used to distinguish various levels
of logging, with a lower digit indicating a more important message.
We will call the <\fIletter\fP><\fIdigit\fP> combination the \fBid\fP of
the logging.
.LP
In general, the lower the \fIdigit\fP following the \fIletter\fP,
the more important the message.
E.g. m5 reports about unsuccessful monitor calls only, m9 also reports
about successful monitors (which are obviously less interesting).
New logging messages can be added to the source code on relevant places.
.LP
Reasonable settings for the logmask are:
.TS
tab(@);
l l l.
  @A\-Z9d4twx9@advised setting when trouble shooting (default).
  @A\-Zx9@shows the flow of instructions & global information.
  @pm9@shows the procedure & monitor calls.
  @tw9@shows warning & trap information.
.TE
.PP
An EM interpreter without a Logging Machine can be obtained by undefining the
macro \fICHECKING\fP in the file \fIchecking.h\fP.
.NH 2
Controlling the Logging machine.
.PP
The actions of the Logging Machine are controlled by a set of internal
variables (one of which is the log mask).
These variables can be set through assignments on the command line, as
explained int the manual page \fIint.1\fP, q.v.
Since there are a great many logging statements in the program, of which only a
few will be executed in any call of the interpreter, it is important to be able
to decide quickly if a given \fIid\fP has to be checked at all.
To this end all logging statements are guarded (in the #define) by a test for
the boolean variable \fIlogging\fP.
This variable will only be set if the command line assignments show the
potential need for logging (\fImust_log\fP) and the instruction count
(\fIinr\fP) is at least equal to \fIlog_start\fP (which derives from the
parameter \fBLOG\fP).
.LP
The log mask can be set by the assignment
.DS
"LOGMASK=\fIlogstring\fP"
.DE
which sets the current logmask to \fIlogstring\fP.
A logstring has the following form:
.DS
[ [ \fIletter\fP | \fIletter\fP \- \fIletter\fP ]+ \fIdigit\fP ]+
.DE
E.g. LOGMASK=A\-D8x9R7c0hi4 will print all messages belonging to loggings
with \fBid\fPs:
\fIA0..A8,B0..B8,C0..C8,D0..D8,x0..x9,R0..R7,c0,h0..h4,i0..i4\fP.
.PP
The logging variable STOP can be used to prevent run-away logging
past the point where the user expects an error to occur.
STOP=\fInr\fP will stop the interpreter after instruction number \fInr\fP.
.PP
To simplify the use of the logging machine, a number of abbreviations have been
defined.
E.g., AT=\fInr\fP can be thought of as an abbreviation of LOG=\fInr\-1\fP
STOP=\fInr+1\fP; this causes three stack dumps, one before the suspect
instruction, one on it and one after it; then the interpreter stops.
.PP
Logging results will appear in a special logging file (default: \fIint.log\fP).
.NH 2
Dumps.
.PP
There are three routines available to examine the memory contents:
.TS
tab(@);
l l l.
  @\fIstd_all()\fP@dumps the contents of the stack (\fId1\fP or \fId2\fP must be in the logmask).
  @\fIgdad_all()\fP@dumps the contents of the gda (\fI+1\fP must be in the logmask).
  @\fIhpd_all()\fP@dumps the contents of the heap (\fI*1\fP must be in the logmask).
.TE
.LP
These routines can be used everywhere in the program to examine the
contents of memory.
The internal variables allow the
gda and heap to be dumped only once (according to the
corresponding internal variable).
The stack is dumped after each
instruction if the log mask contains d1 or d2; d2 gives a full formatted
dump, d1 produces a listing of the Return Status Blocks only.
An attempt is made to format the stack correctly, based on the shadow
bytes, which identify the Return Status Block.
.LP
Remember to set the correct \fBid\fP in the LOGMASK, and to give
LOG the correct value.
If dumping is needed before the first instruction, then LOG must  be
set to 0.
.LP
The dumps of the global data area and the heap are controlled internally by
the id-s +1 and *1 resp.; the corresponding logmask entries are set
automatically by setting the GDA and HEAP variables.
.NH 2
Forking.
.PP
As mentioned earlier, a call to \fIfork()\fP, causes an image of the current
program to start running.
To prevent a messy logfile, the child process gets its own logfile
(and message file, tally file, etc.).
These logfiles are distinguished from the parent logfile by the a
postfix, e.g.,
\fIlogfile_1\fP for the first child, \fIlogfile_2\fP for the second child,
\fIlogfile_1_2\fP for the second child of the first child, etc.
.br
\fINote\fP: the implementation of this feature is shaky; it works for the log
file but should also work for other files and for the names of the logging
variables.
