.\" -*-nroff-*- .TH trace 3 "21 October 1999" mLib .SH "NAME" trace \- configurable tracing output .\" @trace .\" @trace_block .\" @trace_on .\" @trace_level .\" @tracing .\" @traceopt .\" @NTRACE .\" @T .\" IF_TRACING .SH "SYNOPSIS" .nf .B "#include " .BI "void trace(unsigned " l ", const char *" f ", ...);" .BI "void trace_block(unsigned " l ", const char *" s , .BI " const void *" b ", size_t " sz ); .BI "void trace_on(FILE *" fp ", unsigned " l ); .BI "void trace_level(unsigned " l ); .BI "unsigned tracing(void);" .BI "unsigned traceopt(trace_opt *" t ", const char *" p , .BI " unsigned " f ", unsigned " bad ); .BI T( statements\fR... ) .BI "IF_TRACING(unsigned " l ", " statements\fR... ) .fi .SH "DESCRIPTION" The .B header declares some functions and macros for handling trace output. The emphasis for this system is primarily on user configurability of what gets traced rather than where the output goes. That's a project for later. .SS "Trace levels" Each trace message is assigned a .I level by the programmer. A tracing level is set during program initialization, usually by the user. A trace message is output if there is a trace destination set, and the result of a bitwise AND between the message level and the overall tracing level is nonzero. The idea is that the programmer assigns a different bit to each group of trace messages, and allows a user to select which ones are wanted. .SS "Producing trace output" The basic function is .BR trace . It is passed an integer message level and a .BR printf (3)-style format string together with arguments for the placeholders and emits the resulting message. .PP The function .B trace_block formats an arbitrary block of memory as a hex dump. The arguments are, in order, the message level, a pointer to the header string for the hex dump, the base address of the block to dump, and the size of the block in bytes. .SS "Configuring trace output" The tracing destination is set with the function .BR trace_on : it is passed a .B stdio stream and a trace level to set. The stream may be null to disable tracing completely (which is the default). The trace level may be set on its own using .BR trace_level , which takes the new level as its single argument. The function .B tracing returns the current trace level, or zero if there is no trace destination set. .SS "Parsing user trace options" The function .B traceopt may be used to allow a user to set the trace level. It is passed a table describing the available trace level bits, and some other information, and returns a new trace level. The table consists of a number of .B trace_opt structures, each of which describes a bit or selection of bits which may be controlled. The structure contains the following members, in order: .TP .B "char ch;" The character used to select this bit or collection of bits. .TP .B "unsigned f;" The level bits for this option. .TP .B "const char *help;" A help string describing this option. .PP The table is terminated by an entry whose .B ch member is zero. .PP The arguments to .B traceopt are: .TP .BI "trace_opt *" t Pointer to the trace options table. .TP .BI "const char *" p Pointer to the user's option string. .TP .BI "unsigned " f The default trace options, or the previously-set options. .TP .BI "unsigned " bad A bitmask of level bits which should be disallowed. .PP If the option string .I p is a null pointer or contains only a .RB ` ? ' character, a help message is printed and the default is returned. Only trace options which contain non-bad bits are displayed. Otherwise the string contains option characters together with .RB ` + ' and .RB ` \- ' which respectively turn on or off the following options; the default is to turn options on. Again, only options which contain non-bad bits are allowed. .PP The `bad bit' mechanism is provided for setuid programs which in their normal configuration deal with privileged information which mustn't be given out to users. However, if run by someone with appropriate privilege such options are safe and may be useful for debugging. The program can set the .I bad mask to prevent access to secret information when running setuid, or to zero when not. .SS "Macro support for tracing" The tracing macros are intended to make insertion of tracing information unobtrusive and painless. If the .B NTRACE macro is defined, all of the tracing macros are disabled and generate no code; otherwise they do their normal jobs. .PP The .B T macro simply expands to its argument. It may be wrapped around small pieces of code which is only needed when compiling with tracing enabled. (Larger blocks, of course, should use .RB ` #ifndef NTRACE '/` #endif ' pairs for clarity's sake.) .PP For slightly larger code chunks which do some processing to generate trace output, the .B IF_TRACING macro is useful. Its first argument is a message level; if the trace level is set such that the message will be printed, the code in the second argument is executed. If code is being compiled without tracing, of course, the entire contents of the macro is ignored. .SH "SEE ALSO" .BR mLib (3). .SH "AUTHOR" Mark Wooding,