[gnu.g++.bug] fun program

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