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.''