schmidt@zola.ics.uci.edu (Doug Schmidt) (06/01/90)
Recently I needed to trace the dynamic function invocation behavior in
some C and C++ programs. To facilitate and automate this process I
wrote the following short program using the GNU libg++ String and
Regex classes. I've enclosed the program below for your viewing
enjoyment!
The trace instrumenter is elementary, but works fine for my coding
style, (which for C is the same produced by running GNU indent with
the -gnu option). Here's the Trace class that it utilizes:
----------------------------------------
#include <stdio.h>
#ifdef TRACE
#define T(X) X
#else
#define T
#endif
class Trace
{
private:
static int nesting;
char *name;
public:
Trace (char *n) { fprintf (stderr, "%*scalling %s\n", 3 *nesting++, "", name = n); }
~Trace (void) { fprintf (stderr, "%*sleaving %s\n", 3 * --nesting, "", name); }
};
----------------------------------------
So, for example, if you've got code like:
----------------------------------------
int
foobar (char *x)
{
// ...
}
void *
Frobber::operator int * ()
{
// ...
}
----------------------------------------
The program below automagically changes this into
----------------------------------------
int
foobar (char *x)
{
T (Trace t ("foobar");)
// ...
}
void *
Frobber::operator int *()
{
T (Trace t ("Frobber::operator int*"))
// ...
}
----------------------------------------
If anyone comes up with any improvements or corrections please let
me know!
thanks,
Doug
----------------------------------------
#include <stdio.h>
#include <std.h>
#include <String.h>
const char *const trace_class_string =
"#include <stdio.h>\n\n#ifdef TRACE\n#define T(X) X\n#else\n#define T\n#endif\n\n"
"class Trace\n{\nprivate:\n static int nesting;\n char *name;\npublic:\n"
" Trace (char *n) { fprintf (stderr, \"%*scalling %s\\n\", 3 * nesting++, \"\", name = n); }\n"
" ~Trace (void) { fprintf (stderr, \"%*sleaving %s\\n\", 3 * --nesting, \"\", name); }\n};\n\n";
int
main (int argc, char **argv)
{
const Regex RXfunc ("\\(^[a-zA-Z0-9_][^ ]*[ ]*(.*)\\)\\|\\(^[a-zA-Z_:]*operator.*(.*)\\)", 1);
const Regex RXdelimit ("[ ]*(");
String str;
cout << trace_class_string;
while (readline (cin, str, '\n', 0) > 0)
{
cout << str;
if (str.contains (RXfunc))
{
const String func_name = str.before (RXdelimit);
do
{
readline (cin, str, '\n', 0);
cout << str;
}
while (str[0] != '{');
cout << " T (Trace t (\"" << func_name << "\");)\n";
}
}
return 0;
}
--
A monk asked Kegon, ``How does an enlightened | schmidt@ics.uci.edu (ARPA)
one return to the ordinary world?'' Kegon replied, | office: (714) 856-4043
``A broken mirror never reflects again; fallen
flowers never go back to the old branches.''