dklibs

SourceForge.net Logo
Dirk Krause's libraries

tracecc and trana - program tracing

dklibs.pdf
tracecc.pdf
Purpose of the programs
Example input file
List of tracecc builtin functions
Creating a debug version, debug output to stdout
Debug output to file
Generating non-debug output
Tracecc options
Beautifying debug output for inspection
Inspecting output using Vim

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:
  • 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.
There are more functions available, see below.
$? 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

Creating a debug version, debug output to stdout

By running

  tracecc -r -d -s x.ctr x.c
we 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.c
we 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.c
we 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

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 input-file or output-file are not specified, standard input is read, output goes to standard output. The options -c/--configure, -C/--show-configuration, -u/--unconfigure, -r/--reset, -h/--help and -v/--version work like described above for tracecc.
Additionally the following options are available:

Inspecting output using Vim

When inspecting trana output using Vim one should set up folding either by indent level:

  :setlocal sw=2
  :setlocal foldmethod=indent
or by markers:
  :setlocal foldmethod=marker
In 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.