how come #include "*.cpp" works?
mwoehlke
mwoehlke@tibco.com
Wed May 24 16:03:00 GMT 2006
mwoehlke wrote:
> I'm writing a program to dump structures from core dumps generated from
> symbol-less binaries (i.e. no easy looking at structures, etc, in gdb).
> It works great; you give it a structure name and an address and it
> reads, decodes, and prints the structure, as well as referenced objects
> like strings (the idea being to dump whole hierarchies of structures at
> once).
>
> Anyway... what I do is have an "OBJ" ABC and subclass it for each type
> of structure I want this program to be able to understand. What I want
> to do is have some system that entails the fewest *lines* of code
> (macros to turn one line into lots of *actual* code are OK) that can a:
> construct an object by name, and b: provide me a list of names of
> classes which can be created (i.e. if you enter an invalid one, it will
> tell you valid ones). Any thoughts? (Maybe dropping a hippo on the code
> will make it as small as I want it to be? ;-))
Below is what I ultimately wound up using. Thanks again to Dave Korn for
the assistance in coming up with this solution!
The final requirements for this solution are:
1: An updated list of class headers in Makefile.
2: Classes must be declared with 'CREATABLE_CLASS(name)' instead of
'class name : virtual public OBJECT'.
3: A create_<name> function must be written. If all objects were
constructed the same, this could have been lumped into the declaration
CREATABLE_CLASS macro, however not all constructors take the same
arguments, which is why 'create_<name>' takes an argc/argv pair. IOW
this requirement cannot be eliminated.
The list-in-code (including pointers to create functions) is maintained
via (1), which is the only "overhead" other than (3) and the actual
class declaration... and if I really wanted to, I could get rid of this
as well (but to be worth it, I would want/need a way to determine what
files are actually used to build the executable, and I think this is one
case where I /prefer/ to update the list by hand).
Thus, except for Makefile, it achieves the objective of having a list
which is entirely generated and does not need to be maintained by hand.
=== For declaring an object
#define CREATABLE_CLASS(name) \
extern class OBJECT* create_##name( int argc, const char* argv[] ); \
class name : virtual public OBJECT
=== Example declaration
CREATABLE_CLASS( STRING )
{
public:
STRING( long ptr, long lim = MAX_STR );
virtual ~STRING();
...
protected:
char* _data;
};
=== For creating object.def (in Makefile)
objects.def : $(classes)
cat $(classes) | grep CREATABLE_CLASS > $@
(This requires '$(classes)' to be kept up to date, but that's OK because
'$(classes)' becomes part of '$(objects)', which defines the
prerequisites for the executable - i.e. this isn't really adding any
work, although I suppose I could go one step further and generate the
object prerequisites as well; this would certainly be do-able)
=== So main.cpp doesn't need the headers for every class
#undef CREATABLE_CLASS
#define CREATABLE_CLASS(name) \
extern class T_OBJ* create_##name( int argc, const char* argv[] );
#include "objects.def"
=== And finally for the list
#undef CREATABLE_CLASS
#define CREATABLE_CLASS(name) { #name, create_##name },
typedef OBJECT *(*OBJ_CREATOR)( int argc, const char* argv[] );
typedef struct {
const char* name;
OBJ_CREATOR create;
} OBJECT_LIST_ENTRY;
OBJECT_LIST_ENTRY createable_object[] = {
#include "objects.def"
{ NULL, NULL }
};
(The last '{ NULL, NULL }' entry is needed to have something after the
comma that the macro generates.)
--
Matthew
Doom doom dooM doo-DooM dOOm DOom doOM... DOOM! -- Gir
More information about the Cygwin-talk
mailing list