% $Id: DEBUG.TEX 1.1 2000/01/24 10:18:50 ska Exp ska $
%
% Documentation of SUPPL - subsystem DEBUG
%
%	(c) Copyright 1999 Steffen Kaiser
%
%	This \LaTeX file requires \LaTeXe
%

\section{\labal{ssDebug}\subsys{debug}}

This subsystem implements functions for both to debug an user program
and to debug \suppl as well. All functionality offered to user
programs are also included into \suppl.

{\large It is not recommended to use debug features for a shipped
version of a program, because they require a lof of resources. This
applies to both \suppl and the user program.} It may be even impossible
to test a program in tiny or small memory model, because the debug
features use too many resources.

The ANSI--C macro \fct{NDEBUG} controls all debug functions, if it
is defined all debugging is turned off and is not even compiled into
the program. When \suppl is built with \fct{NDEBUG} defined, no internal
debugging feature is compiled in, but \suppl still offers all debug
functionality to an user program if it is built with \fct{NDEBUG} {\em not}
defined.

There are two types of symbols within this subsystem:
\begin{enumerate}
\item Macros that are available regardless if debugging is enabled or not.
	They offer to include the debug functions without any \verb|#ifdef|'s
	within the source code of the user program.

	When debugging is enabled, these macros expand to some functions
	doing all the work; if debugging is disabled, they expand to an
	empty string, aka nothing.

\item Functions that actually do all the work. They are available
	regardless if debugging is enabled or not, but unless the user program
	explicitely calls, these function will not be linked to the final
	program.
\end{enumerate}

Currently these sets of functions are available within the subsystem
\subsys{Debug}:
\begin{table}
\caption{\label{dbgFcts}Sets of Functions of the Subsystem \subsys{Debug}}
\begin{tableThree}{set}{control macro}{purpose}
\item heap debugging & \fct{SUPPL\_DBG\_HEAP} & These function shall help to
	debug allocation and deallocation of dynamic memory (heap) and to detect
	heap corruptions. \\
\hline
\item heap logging & \fct{SUPPL\_LOG\_MEMORY} & These functions wrap the
	standard functions to access the heap, e.g.\ \fct{malloc()} and
	\fct{free()}, and dump an entry of all input and output
	information into the standard logfile. \\
\hline
\item tracing & \fct{SUPPL\_LOG\_FUNCTION} & These functions provide macros
	to keep track which function was called when with which parameters
	from which function and what return values were produced. \\
\hline
\item assert & none & \subsys{Debug} automatically includes the \fct{assert()}
	of ANSI--C. \\
\end{tableThree}
\end{table}

The use the subsystem \subsys{Debug} within an user program, the header file
\fnam{SUPPLDBG.H} must be included into {\em every} source file. {\small
Well, the file must be included only into files, which are effected by the
settings in it, but some changes are not {\em that} visible to all programmers.
Therefore it is recommended to include the file into all sources.} Prior
the \verb|#include| statement the individual debug functions must be
explicitely enabled. Therefore it is recommended, too, to not included
\fnam{SUPPLDBG.H} directly into each source file, but to create a local
header file, which is then included into all source files.

For instance:
\begin{verbatim*}
/*
 *	Local include file to setup the debug functions of SUPPL
 */

/* Enable to debug the heap functions */
#define SUPPL_DBG_HEAP

/* Enable to log the heap functions */
#define SUPPL_LOG_MEMORY

/* Enable to trace the function calls */
#define SUPPL_LOG_FUNCTION

#include <suppldbg.h>

\end{verbatim*}

Within each source file this header file is then included as the last
one at all.

{\em Note:} If the macro \fct{NDEBUG} is defined when \fnam{SUPPLDBG.H}
is included, any definition is ignored and all control macros are
automatically removed via \verb|#undef|, so they can savely be used
within the source files to test, if the particular debug set is enabled
or not.

\subsection{Function Tracing}

The function tracer was inspired by the DBUG package of Fred Fish included
into DMake~v3+\footnote{Available from \verb|http://|.}, but no
sources were included from it.

The purpose of this set is to trace what function was called by what
function, which parameters and return values were passed in and out, and
other, arbitary information.

At run-time the range of functions, which really are logged can be
limited in various ways.

\subsubsection{Introdactionary Example}

The following example shall demonstrate the use of the function tracer,
which includes full logging of arguments and return values:
\begin{verbatim*}
int function1(int arg1, char *arg2, void *arg3)
{	int var1;
	char *var2;

	DBG_ENTER("function1", "usr")
	DBG_ARGUMENTS( ("Argument #1=%d, Argument #2='%s'", arg1, arg2) )

	assert(arg2);

	if(!arg3)
		DBG_RETURN_I(256)

	if(!*arg2) {
		DBG_STRING("String is empty")
		DBG_RETURN_I(-5)
	}

	if(arg1 >= strlen(arg2)) {
		DBG_INFO( ("Length exceeds the size of the string: %d", strlen(arg2)) )
		DBG_RETURN_I(-8)
	}

	arg3 = strdup(&arg2[arg1]);
	if(!arg3) {
		DBG_STRING("Out of memory")
		DBG_RETURN_I(-46)
	}

	DBG_RETURN_VALUES( ("Argument #3 := '%s'", arg3) )

	DBG_RETURN_I(0)
}
\end{verbatim*}

All functions beginning with \fct{DBG\_} are tracer functions of \suppl,
and please already note that there is {\em\bf no} semicolon trailing
the macros.

\begin{itemize}
\item \fct{DBG\_ENTER} informs the tracer that a new function was entered,
it explicitely passes the name of the function and a function class to
the tracer; the name of the file the function is defined in,
the line number of \fct{DBG\_ENTER} and the library this function
is part of are implicitly passed to the tracer.
\item \fct{DBG\_ARGUMENTS} logs the values of the parameters, it is an
	usual \fct{printf()}-style function.
\item \fct{assert} is the standard function described in the ANSI--C
	standard. It is automatically included within the header file
	\fnam{SUPPLDBG.H} and terminates the program, if the expression
	evaluates to zero.
\item \fct{DBG\_RETURN\_I} informs the tracer about:
	\begin{enumerate}
	\item the fact that the current function is about to be exited, and
	\item the return value of the function.
	\end{enumerate}
\item \fct{DBG\_STRING} logs the specified string unchangedly.
\item \fct{DBG\_INFO} logs the specified string unchangedly, but
	accepts a \fct{printf()}-style syntax.
\item \fct{DBG\_RETURN\_VALUES} logs return values other than the
	values of \fct{return}-statements.
\end{itemize}

Basically, two sets of functions {\em must} be called in order to let
the function tracer work as expected:
\begin{enumerate}
\item \fct{DBG\_ENTER} to enter a function and
\item one of \fct{DBG\_RETURN*} macros to leave the function.
\end{enumerate}

\subsubsection{Function Class}

Similiar functions are grouped into function classes. This way all
functions belonging to the same function class can be enabled and
disabled at once. Which class a function is grouped to is totally
up to the programmer, though, it is recommended to keep the names
of the classes less then four characters.

The names of classes are case-sensitive.

The following function classes are reserved to \suppl:
\begin{table}
\begin{tableTwo}{class}{reserved for:}
\item env & environment handling subsystem of \suppl \\
\item mcb & MCB handling subsystem of \suppl \\
\item mem & memory and heap functions \\
\item str & string functions \\
\item ini & INI file handling subsystem of \suppl \\
\item cmd & command line handling subsystem of \suppl \\
\item err & error wrappers of \suppl \\
\item dfn & filename functions of \suppl \\
\item fil & FILE wrappers of \suppl \\
\item lmt & long mathematics wrappers of \suppl \\
\item nls & NLS implementation of \suppl \\
\item log & syslog and general logging except debugging \\
\item msc & miscelaneous stuff of \suppl \\
\item usr & user program, never used by \suppl \\
\end{tableThree}
\caption{\label{fctClasses}Function Classes Reserved to \suppl}
\end{table}

More classes may be added to this list in the future, though, all
names used within \suppl will have exactly three lowercase letters.
Therefore it is recommended to create the names of new classes for
an user program with at least one non-letter or an uppercase letter.

\subsubsection{Information Class}

When information is logged into the logfile, a class is associated
with it. The class described which kind of information it is and is
used to selectively suppress unwanted information.

Because the class becomes part of the log entry, too, it can be used
to select entries when the logfile is checked by an evaluting processor.

The following information classes are currently in use by \suppl:
\begin{table}
\begin{tabular}{|l|p{3cm}|p{6cm}|}
\hline
{\bf class} & {\bf used by:} & {\bf meaning} \\
\hline
\hline
\item arg & \fct{DBG\_ARGUMENTS}
	& argument(s) passed into the function \\
\item rv  & \fct{DBG\_RETURN\_VALUES} and all \fct{DBG\_RETURN*} macros
	& return value(s) passed out the function \\
\item fct & \fct{DBG\_ENTER} and \fct{DBG\_EXIT}/\fct{DBG\_LEAVE}\footnote{All
\fct{DBG\_RETURN*} macros contain a \fct{DBG\_LEAVE} macro, too} 
	& actual function entry/exit information \\
\item inf & \fct{DBG\_STRING} and \fct{DBG\_INFO} 
	& informative information \\
\hline
\end{tabular}
\caption{\label{infClasses}Information Classes reserved to \suppl}
\end{table}

More classes may be added to this list in the future, though, all names
used within \suppl will have up to lowercase letters only.  Therefore it
is recommended to create the names of new classes for an user program
with at least one non-letter or an uppercase letter, e.g.  to pass them
to the central function
\fct{DBG\_PRINT(info\_class, (dynamic\_parameter\_list))}
to acutal log one entry into the logfile.

\subsubsection{Design}

The function tracer keeps track of when which function is called passing
which arguments and generating which return values.

Because there is no portable way to let the compiler automatically add
the necessary hooks to the functions, the programmer must add them
manually. A set of macros is provided, which expand to nothing, when
the function tracer is disabled, or to a real function or a
compound statement. These macros must never be trailed by a
semicolon as functions usual do.

All these macros are prefixed by \fct{DBG\_} to easily distinguish
them from other subsystems and the user program. Functions called by
the macros are prefixed by \fct{suppl\_log\_}, they are also available
if the tracer is disabled otherwise, thus, they can be used for
other purposes as well.

Usually all macros expand to functions that generate one entry
into the logfile. This logfile is create once the first entry is
to be written, the name is derived from the name of the executable
of the current application and the file is created within the
current working directory. Once the logfile has been created, it
is kept open the whole life-time of the program.

When the standard macros are used, each entry looks like this:
\begin{verbatim*}
19:14:21.15         0:	|	|>dfnstat() "dfn" lib:SUPPL in dfnstat.c:92
19:14:21.15         1:	|	|arg: fnam="t.exe"
19:14:21.15         2:	|	|	|>invokeDOS() "portable" lib:SUPPL in invokedo.c:110
19:14:21.15         3:	|	|	|arg: AX=0x4300
19:14:21.15         4:	|	|	|rv: 0
19:14:21.15         5:	|	|	|<invokeDOS()
19:14:21.15         6:	|	|rv: 0x4021
19:14:21.15         7:	|	|<dfnstat()
\end{verbatim*}

The first field contains the current time the logentry was issued.\newline
The second field continueously counts the lines.\newline
If indention is enabled, then a number of tabbed \verb:|: characters
appear to indicate the nesting level of the function; otherwise the
nesting level is visualized as a number in brackets.\newline
Then the actual logentry begins.\newline
The \verb|>| entries are generated by \fct{DBG\_ENTER}, the \verb|<|
entries by \fct{DBG\_EXIT} or \fct{DBG\_LEAVE}.\newline
All other entries are prefixed by their information class and one
colon.

The above example was generated by:
\begin{verbatim*}
/* Test of DBG_*() and dfnstat() */
#include <stdio.h>

#define SUPPL_LOG_FUNCTION
#include "suppldbg.h"

#include "dfn.h"

main(int argc, char **argv)
{ 
	DBG_ENTER("main", "usr")
	DBG_CHANGE_STATE("l+;C+,+SUPPL")

	printf("%s = 0x%x\n", argv[1], dfnstat(argv[1]));

	DBG_RETURN_U( 0)
}
\end{verbatim*}

The above source reveals one problem that the topmost function(s) count(s)
as indention level(s), but, because logging is disabled by default, not
even the entry lines are written to the logfile.

\paragraphe{The function tracer is controlled by status settings},
which are organized as push- and popable states. When a state is
pushed via \fct{DBG\_PUSH\_STATE}, the topmost state is duplicated and
inherits all settings from the now second topmost state. The topmost
state can be modified via \fct{DBG\_CHANGE\_STATE}. Because the
initial state statically created by \suppl disables anything, nothing
is logged until logging is enabled via \fct{DBG\_CHANGE\_STATE}. Though,
even if logging is disabled, the function tracer is active and keeps
track of the nesting level. The topmost state can be discarded via
\fct{DBG\_POP\_STATE}, except if the topmost state is the only state
as well.

This mechanism allows to heavily change the logging properties for
a part of the program without to know much about the internals of
the function tracer.

\subsubsection{Controlling the State of the Function Tracer}

The currently active state of the function tracer can be modifed
by calling the \fct{DBG\_CHANGE\_STATE} macro. Its parameters
were designed to be easily useable from outside the program. That
means it is recommended to offer a command line option that changes
the state. Therefore the parameter of \fct{DBG\_CHANGE\_STATE}
is an ASCII string as one can type in on command line.

The general syntax of the control string is:
\verb|?***,***,...;?***,***,...;...|, where \verb|?| encodes
what status to change and \verb|***| how (aka arguments). Multiple arguments
can be delimited by one comma, multiple stati by a semicolon.

The following status codes are currently implemented:
\begin{table}
\begin{tableTwo}{code}{meaning}
\verb|l|	&	globally enable or disable logging; the argument must be
				either \verb|+| to enable, or \verb|-| to disable logging\newline
				default: logging disabled\\
\verb|i|	&	enable or disable to indent the output; the argument must be
				either \verb|+| to enable, or \verb|-| to disable indentian\newline
				If disbaled the nesting level is inserted as number, otherwise
				as a repetive count of "|  " strings.\newline
				default: enabled\\
\verb|d|	& 	sets the maximum nesting level\newline default: no limit\newline
				only one argument accepted\\
\verb|f|	&	enumerates all files to be logged, each filename
				is prefixed by '+' enable, or '-' disable file.
				Wildcards are not allowed. The filename must be specified
				the same way as the compiler named them in its \fct{\_\_FILE\_\_}
				macro, this is usually the fully-qualified filename.\newline
				'+' alone logs everything (clears every previous settings),
				'-' alone logs nothing (clears every previous settings).\newline
				default: log nothing.\\
\verb|c|	&	functions to be logged;
				Syntax the same as \verb|f|, but the string must
				case-sensitively match the string passed as the first
				argument to \fct{DBG\_ENTER()}\newline
				default: log nothing\\
\verb|C|	&	information and function classes to be logged. Syntax as \verb|f|.\newline default: log nothing\\
\end{tableTwo}
\caption{\label{statusCodes}Status Codes}
\end{table}

\paragraphe{There are four dependencies checked in order to log an entry}
into the logfile:
\begin{enumerate}
\item the global log flag is enabled,
\item the function is logged,
\item the maximum nesting level is not reached, and
\item the class of the information to be issued is enabled.
\end{enumerate}

The status of if the function is logged is derived from the following rules:
\begin{itemize}
\item If the function is part of a library, the library must be
	explicitely enabled with code \verb|C|. It is {\em not} sufficient
	to enable everything via \verb|C+|.
\item If the compiler passed in the name of the file the function is
	located in and this name is explicitly or implicitly enabled
	via \verb|f|, logging is enabled.
\item If at least one of the arguments of \fct{DBG\_ENTER} (name of
	function or function class) is explicitly disabled, logging is
	disabled.
\item Otherwise, if at least one of the arguments of \fct{DBG\_ENTER} (name of
	function or function class) is explicitly or implicitly enabled, logging is
	enabled.
\end{itemize}

All compares are case-sensitive.

So the call \fct{DBG\_CHANGE\_STATE(\"{}l+;C+,+SUPPL\"{})} of the above example,
\begin{enumerate}
\item enables the global logging,
\item enables all function and information classes and
\item enables the \suppl library.
\end{enumerate}

\subsubsection{Programming Interface}

The programming interface of the function tracer consists of macros and
functions. The macros expand to nothing, if logging is disabled, otherwise
they invoke the necessary functions. In this section only the macros are
described, because they are the recommended interface. If the user
program makes direct use of the log functions, the result might
collide with each other.

In order to enable the function tracer, the macro \fct{SUPPL\_LOG\_FUNCTION}
must be defined prior including the header file \fnam{SUPPLDBG.H}.
If the file is part of a library, the macro \fct{DBG\_LIBRARY} must
be defined with the value of the name of the library as a string, too.
The macro \fct{SUPPL\_LOG\_NO\_INFO} disables the two macros
\fct{DBG\_INFO} and \fct{DBG\_STRING}.

\paragraphe{\fct{DBG\_ENTER(fct\_name, fct\_class)}} increments the
nesting level by one and calculates the local function logging flag.
To keep track of the nesting level and logging flags, \fct{DBG\_ENTER}
must store local data. Therefore, this macro does not only consists
of a call to a function, but contains a definition of a variable, too.
This macro must be the very first statement of a function therefore.

In cases, this cannot achieved two macros are available that seperate
the variable definition, \fct{DBG\_ENTER1}, and the function call,
\fct{DBG\_ENTER2(fct\_name, fct\_class)}.

This macros do not automactically log the arguments.

\paragraphe{\fct{DBG\_EXIT(void)} and \fct{DBG\_LEAVE(expr)}} both
terminate the function. \fct{DBG\_EXIT} terminates a \fct{(void)}
function, whereas \fct{DBG\_LEAVE(expr)} expands to
\verb|return expr;|, in order to leave a non-void function.

Prior terminating the function both macros decrement the nesting
level by one, restore the locally cached data and test if the
entry/exit macros were called in sequence.

\fct{DBG\_LEAVE} is automatically called by all of the \fct{DBG\_RETURN*}
macros, also it does not automatically log the return value.

\paragraphe{\fct{DBG\_PRINT(inf\_class, expr )}} logs any \fct{printf()}-style
expression of the specified information class.

\paragraphe{\fct{DBG\_ARGUMENTS( expr )}} logs the \fct{printf()}-style
argument list with the information class \verb|arg|. In fact, it is
equal to: \verb|DBG_PRINT("arg", expr )|.

\paragraphe{\fct{DBG\_RETURN\_VALUES( expr )}} logs the \fct{printf()}-style
argument list with the information class \verb|rv|. In fact, it is
equal to: \verb|DBG_PRINT("rv", expr )|.

\paragraphe{\fct{DBG\_INFO( expr )}} logs the \fct{printf()}-style
argument list with the information class \verb|inf|. In fact, it is
equal to: \verb|DBG_PRINT("inf", expr )|. If the macro \fct{SUPPL\_DBG\_NO\_INFO} is defined prior including the header file \fnam{SUPPLDBG.H}, this macro expands to nothing.

\paragraphe{\fct{DBG\_STRING(string)}} logs the \fct{(char*)} string
with the information class \verb|inf|. In fact, it is
equal to: \verb|DBG_PRINT("inf", ("%s", string) )|. If the macro \fct{SUPPL\_DBG\_NO\_INFO} is defined prior including the header file \fnam{SUPPLDBG.H}, this macro expands to nothing.

\paragraphe{\fct{DBG\_RETURN\_B*(expr)} and \fct{DBG\_RETURN\_*(expr)}}
both combine the macros \fct{DBG\_RETURN\_VALUES} and \fct{DBG\_LEAVE},
thus, log the return value and terminate the function. The asterisk
stands for the code of the type of the expression:
\begin{table}
\begin{tabular}{|c|c|l|}
\hline
{\bf code } & {\bf type} & {\bf \fct{printf()}-format string} \\
\hline
\hline
C	& \fct{(char)}			&	\verb|"%c"| \\
S	& \fct{(char*)}			&	\verb|"\"%s\""| \\
I	& \fct{(int)}			&	\verb|"%d"| \\
U	& \fct{(unsigned int)}	&	\verb|"%u"| \\
X	& \fct{(unsigned)}		&	\verb|"0x%x"| \\
L	& \fct{(long)}			&	\verb|"%ld"| \\
UL	& \fct{(unsigned long)}	&	\verb|"%lu"| \\
F	& \fct{(double)}		&	\verb|"%f"| \\
G	& \fct{(double)}		&	\verb|"%g"| \\
P	& \fct{(void*)}			&	\verb|"%p"| \\
\hline
\end{tabular}
\caption{\label{rvTypes}Type Codes of \fct{DBG\_RETURN\_*} macros}
\end{table}

The \fct{DBG\_RETURN\_B*} macros guarantee that the expression
is evaluated only once.

\paragraphe{\fct{DBG\_RETURN(fmt\_string, expr)}} logs the return
value of the function via \verb|DBG_PRINT("rv", (fmt_string, expr) )| and
terminate the function via \verb|DBG_LEAVE(expr)|.

\paragraphe{\fct{DBG\_LONG\_RETURN(type, fmt\_string, expr)}} evaluates
the expression and stores the result into a local temporary variable and
then logs the return value of the function via
\verb|DBG_PRINT("rv", (fmt_string, tmp_var) )| and terminate the function via
\verb|DBG_LEAVE(tmp_var)|.
