tracecc and trana - program tracing |
dklibs.pdf tracecc.pdf |
Purpose of the programs
Tracecc is a debugging preprocessor for C, C++, Objective-C and Java.
it processes .ctr, .cpt, .mtr and .jtr files to produce .c, .cpp, .m or
.java files.
Input file may contain tracecc special instructions. Depending on the
tracecc options and preferences the special instructions are converted
into C code or skipped.
Debug special instructions are converted to C code writing debug messages
if tracecc is run in debug mode.
The trana program can beautify the debug messages for an easier inspection.
Example input file
#include <stdio.h> $(trace-include) static void run_function(int arg) { int i; $? "+ run_function %d", arg for(i = 0; i < 10; i++) { $? ". in the loop, everything ok" } $? "- run_function" } int main(int argc, char *argv[]) { int condition = 0; $(trace-init example.deb) for(i = 0; i < 5; i++) { run_function(i); } if(condition) { $? ". everything ok" } else { $? "! error: condition not set" } $(trace-end) }Tracecc special instructions are started by a dollar sign ($). Several instruction types are possible:
$(fct-name argument(s)) $! fct-name argument(s) |
Tracecc builtin function. Examples are:
|
$? format arguments | Debug instruction. If tracecc is running in debug mode, this is
converted into a printf/fprintf instruction. It is recommended to start debug messages for invoking a function by "+", for returning from a function by "-", for normal conditions by "." and for error conditions by "!". |
List of tracecc builtin functions
- trace-include
is converted to "#include <dktrace.h>" in debug mode, to an empty line otherwise. - trace-init
filename
opens the trace output file and enables trace messages when in debug mode, does nothing otherwise. - trace-end
closes the trace output file and disables further trace messages when in debug mode, does nothing otherwise. - trace-off
trace-on
can be used to turn debug message output temporarily off and back on. These functions only have effect if tracecc is run in debug mode. - timestamp-on
timestamp-off
enables/disables output of time stamps together with debug messages. These functions only have effect if tracecc is run in debug mode. - lineno-on
lineno-off
turn output of line numbers together with debug messages on or off. These functions only have effect if tracecc is run in debug mode. - string-file
filename
reads the specified text file line by line and converts it into an array of strings. - byte-file
filename
reads the specified file and converts it into an array of bytes. - pipe
command
|command
executes the specified shell command and transfers the command's standard output into the destination C file. - trace-code
code
!code
transfers the given C code into the C destination file only when tracecc is run in debug mode.
Creating a debug version, debug output to stdout
By running
tracecc -r -d -s x.ctr x.cwe create an output file like
#include <stdio.h> #include <dktrace.h> static void run_function(int arg) { int i; /* TRACE BEGIN */ { fputs("x.ctr:7: ", stdout); } { printf("+ run_function %d", arg); } { fputc('\n', stdout); } fflush(stdout); /* TRACE END */ for(i = 0; i < 10; i++) { /* TRACE BEGIN */ { fputs("x.ctr:9: ", stdout); } { printf(". in the loop, everything ok"); } { fputc('\n', stdout); } fflush(stdout); /* TRACE END */ } /* TRACE BEGIN */ { fputs("x.ctr:11: ", stdout); } { printf("- run_function"); } { fputc('\n', stdout); } fflush(stdout); /* TRACE END */ } int main(int argc, char *argv[]) { int condition = 0; for(i = 0; i < 5; i++) { run_function(i); } if(condition) { /* TRACE BEGIN */ { fputs("x.ctr:22: ", stdout); } { printf(". everything ok"); } { fputc('\n', stdout); } fflush(stdout); /* TRACE END */ } else { /* TRACE BEGIN */ { fputs("x.ctr:24: ", stdout); } { printf("! error: condition not set"); } { fputc('\n', stdout); } fflush(stdout); /* TRACE END */ } }
Debug output to file
By running
tracecc -r -d x.ctr x.cwe create an output file like
#include <stdio.h> #include <dktrace.h> static void run_function(int arg) { int i; /* TRACE BEGIN */ { if(dktrace_file()) { fputs("x.ctr:7: ", dktrace_file()); } } { if(dktrace_file()) { fprintf(dktrace_file(), "+ run_function %d", arg); } } { if(dktrace_file()) { fputc('\n', dktrace_file()); } } { if(dktrace_file()) { fflush(dktrace_file()); } } /* TRACE END */ for(i = 0; i < 10; i++) { /* TRACE BEGIN */ { if(dktrace_file()) { fputs("x.ctr:9: ", dktrace_file()); } } { if(dktrace_file()) { fprintf(dktrace_file(), ". in the loop, everything ok"); } } { if(dktrace_file()) { fputc('\n', dktrace_file()); } } { if(dktrace_file()) { fflush(dktrace_file()); } } /* TRACE END */ } /* TRACE BEGIN */ { if(dktrace_file()) { fputs("x.ctr:11: ", dktrace_file()); } } { if(dktrace_file()) { fprintf(dktrace_file(), "- run_function"); } } { if(dktrace_file()) { fputc('\n', dktrace_file()); } } { if(dktrace_file()) { fflush(dktrace_file()); } } /* TRACE END */ } int main(int argc, char *argv[]) { int condition = 0; dktrace_init("example.deb"); for(i = 0; i < 5; i++) { run_function(i); } if(condition) { /* TRACE BEGIN */ { if(dktrace_file()) { fputs("x.ctr:22: ", dktrace_file()); } } { if(dktrace_file()) { fprintf(dktrace_file(), ". everything ok"); } } { if(dktrace_file()) { fputc('\n', dktrace_file()); } } { if(dktrace_file()) { fflush(dktrace_file()); } } /* TRACE END */ } else { /* TRACE BEGIN */ { if(dktrace_file()) { fputs("x.ctr:24: ", dktrace_file()); } } { if(dktrace_file()) { fprintf(dktrace_file(), "! error: condition not set"); } } { if(dktrace_file()) { fputc('\n', dktrace_file()); } } { if(dktrace_file()) { fflush(dktrace_file()); } } /* TRACE END */ } dktrace_end(); }The program uses dktrace_-functions, so we must use the dktrace library when linking the executable.
Generating non-debug output
By running
tracecc -r x.ctr x.cwe create an output file like
#include <stdio.h> static void run_function(int arg) { int i; for(i = 0; i < 10; i++) { } } int main(int argc, char *argv[]) { int condition = 0; for(i = 0; i < 5; i++) { run_function(i); } if(condition) { } else { } }
Tracecc options
- -v, --version
shows the program version. - -h, --help
shows a help text. - -r, --reset
ignores all permanent options temporarily (for this one program invokation). - -u, --unconfigure
removes all permanent options. - -c <options>, --configure <options>
configures permanent options. - -C, --show-configuration
shows the permanent options. - -d, --debug-enable
enables debug mode. - -d-, --debug-enable=off
disables debug mode. - -s, --debug-stdout
writes debug messages to standard output. - -s-, --debug-stdout
writes debug messages to the debug file. - -t, --debug-timestamp
adds a time stamp to debug messages. - -t-, --debug-timestamp=off
disables output of time stamps for debug messages. - -l, --linenumbers
adds "#line..." preprocessor directives to the C destination file. - -l-, --linenumbers=off
disables "#line..." preprocessor directives. - -m, --make
enables make-mode. When run on directories in this mode conversions are only run for those source files newer than their destination files. - -m-, --make=off
disables make mode. - -p, --cpp-comments
lets C++ comments pass through. - -p-, --cpp-comments=off
converts C++ comments to C comments. - -k, --keyword
adds the "trace" keyword to each debug output line. - -k-, --keyword=off
does not add the "trace" keyword. - -b
box-width
sets the width of comment boxes.
In the source file a comment box is written in special instructions like these:$* This is a comment describing a function. This comment is converted into a pretty box. $*
The conversion result looks like this:/* ********************************************************************* */ /* * * */ /* * This is a comment describing a funtion. * */ /* * It is converted into a pretty box. * */ /* * * */ /* ********************************************************************* */
Beautifying debug output for inspection
The trana program modifies debug output to allow an easier inspection
using editors capable of folding (i.e. Vim).
Folding in editors means that the editor does not show the complete
text, parts of the text are hidden, a short summary line is printed
instead. By typing special keys or choosing menu items the
user can switch between full text and summary.
Folding can be based on insertion level or special text segments
called "fold markers".
The trana program can either insert leading spaces or fold markers
depending on the options specified on the command line.
The syntax to run trana is
trana <options> trana <options> <input-file> trana <options> <input-file> <output-file>If
Additionally the following options are available:
- -m, --marker
add fold markers to the output. - -m-, --marker=off
does not add fold markers to the output. - -t, --trace-only
write only lines containing the "trace" keyword to the output. - -t-, --trace-only=off
does not restrict output to lines containing the "trace" keyword. - -n, --numeric
print a numeric indent level at the beginning of each line. - -n-, --numeric=off
does not print a numeric indent level. - -p, --position
transfers the source location to the output (this is enabled by default). - -p-, --position=off
does not transfer source location to the output.
Inspecting output using Vim
When inspecting trana output using Vim one should set up folding either by indent level:
:setlocal sw=2 :setlocal foldmethod=indentor by markers:
:setlocal foldmethod=markerIn on-text-mode (not command-mode) one can use the key sequences zo to open a fold, zc to close a fold. The sequence zr opens all folds one level, zm closes one fold level.