How to detail a struct content (almost) just like adebugger does ?

  • Thread starter Jérôme de Lagausie
  • Start date
J

Jérôme de Lagausie

Hello,

In one hand, I've got a set of more than 130 different structures,

mostly rather simple (a set of simple data members such as int, long, char
[], float ...)
sample :
[h2.h]
#ifndef _H2_H_
#define _H2_H_
#define MEMBER3_LENGTH 100
struct h2 {
int member1 ;
long member2 ;
char member3[MEMBER3_LENGTH] ;
....
} t_h2 ;
#endif

sometimes more complex :
sample :
[h3.h]
#ifndef _H3_H_
#define _H3_H_
struct h3_part {
int member1 ;
long member2 ;
....
} t_h3_part ;

struct h3 {
int memberx ;
t_h3_part innerstruct[3] ;
...
}
#endif


And I need to display the content of any structure, with a function looking
like something like this proto :
void display_content_of (void * data, const char which_structure[])
{
...
if (strcmp (which_structure, "t_h2") == 0)
{
t_h2 *p_h2 = (t_h2 *)data ;
show_all_members_of_h2 (p_h2) ;
}
...
}



I suppose the solution to my quest is something like what does a compiler do
(indeed, my solution is not supposed to work just at run time... It can use
include files, process them, to form a new set of files, compile them and
build the tool I need...)
Maybe yacc & lex would be helpfull, but I need some hints 'cause I don't
know them.
Maye be a solution based on "indexof" and macros exists, too, but I'm not
that confident...

Any help would be much appreciated.

Thank you.

Jerome de Lagausie
 
E

Eric Sosman

Jérôme de Lagausie said:
Hello,

In one hand, I've got a set of more than 130 different structures,

mostly rather simple (a set of simple data members such as int, long, char
[], float ...)
sample :
[h2.h]
#ifndef _H2_H_
#define _H2_H_
#define MEMBER3_LENGTH 100
struct h2 {
int member1 ;
long member2 ;
char member3[MEMBER3_LENGTH] ;
....
} t_h2 ;
#endif

sometimes more complex :
sample :
[h3.h]
#ifndef _H3_H_
#define _H3_H_
struct h3_part {
int member1 ;
long member2 ;
....
} t_h3_part ;

struct h3 {
int memberx ;
t_h3_part innerstruct[3] ;
...
}
#endif

And I need to display the content of any structure, with a function looking
like something like this proto :
void display_content_of (void * data, const char which_structure[])
{
...
if (strcmp (which_structure, "t_h2") == 0)
{
t_h2 *p_h2 = (t_h2 *)data ;
show_all_members_of_h2 (p_h2) ;
}
...
}

I suppose the solution to my quest is something like what does a compiler do
(indeed, my solution is not supposed to work just at run time... It can use
include files, process them, to form a new set of files, compile them and
build the tool I need...)
Maybe yacc & lex would be helpfull, but I need some hints 'cause I don't
know them.
Maye be a solution based on "indexof" and macros exists, too, but I'm not
that confident...

One method is to build a description for each struct type,
and pass that instead of the which_structure string. The
description gives the offsetof (not indexof) each element
you want to display, plus information about the element type
and possibly the name and display format. Here's a sketch:

typedef struct {
size_t offset;
enum { INT, LONG, ... } type;
const char *name;
const char *format;
} Element;

const Element h2_layout[] = {
{ offsetof(struct h2, member1), INT, "member1", "%d" },
{ offsetof(struct h2, member2), LONG, "member2", "%lo" },
{ offsetof(struct h3, member3), CHAR_ARRAY, "member3", "%s" },
...
{ 0, 0, NULL, NULL } /* end of description */
};

void display_content_of(const void *data, const Element *field) {
const char *ptr;
for ( ; field->name != NULL; ++field) {
printf ("%s = ", field->name);
ptr = (const char*)data + field->offset;
switch (field->type) {
case INT:
printf (field->format, *(const int*)ptr);
break;
case LONG:
printf (field->format, *(const long*)ptr);
break;
case CHAR_ARRAY:
printf (field->format, ptr);
break;
...
}
putchar ('\n');
}
}

This is more or less what a debugger does, although debuggers
usually rely on "private agreements" with the compiler to obtain
the information here encoded in arrays of Element structures.

Building the Element arrays can be tedious, and errors can
result if somebody adds a new element to an existing structure
but forgets to update the corresponding description. In a large
software project, it's probably best to write a small program that
accepts a simple language describing the desired structs, and use
this program to generate C code declaring each struct and defining
its Element array. If you arrange to run this program before
compilation, the struct definitions and their Element descriptions
will remain in agreement.
 
J

Jérôme de Lagausie

Thank you for this answer

Building the Element arrays can be tedious, and errors can
result if somebody adds a new element to an existing structure
but forgets to update the corresponding description. In a large
software project, it's probably best to write a small program that
accepts a simple language describing the desired structs, and use
this program to generate C code declaring each struct and defining
its Element array. If you arrange to run this program before
co mpilation, the struct definitions and their Element descriptions
will remain in agreement.

In fact, the solution that I presentlu use is something just like that, but
it's not satisfactory, because my "small program" doesn't accept arrays
(except char[], but these are more "string" type than an array), neither
inner structure.
In fact I even have to deal with a structure containing a tab of structure !

That's why I think that I need to "think different", and have another
approach, since my program needs to "digest" more than 130 structures...
This is more or less what a debugger does, although debuggers
usually rely on "private agreements" with the compiler to obtain
the information here encoded in arrays of Element structures.

I need to sign one of these agreements ;-)


Jerome
 
R

Rob Thorpe

Jérôme de Lagausie said:
Hello,

In one hand, I've got a set of more than 130 different structures,

mostly rather simple (a set of simple data members such as int, long, char
[], float ...)
sample :
[h2.h]
#ifndef _H2_H_
#define _H2_H_
#define MEMBER3_LENGTH 100
struct h2 {
int member1 ;
long member2 ;
char member3[MEMBER3_LENGTH] ;
....
} t_h2 ;
#endif

sometimes more complex :
sample :
[h3.h]
#ifndef _H3_H_
#define _H3_H_
struct h3_part {
int member1 ;
long member2 ;
....
} t_h3_part ;

struct h3 {
int memberx ;
t_h3_part innerstruct[3] ;
...
}
#endif


And I need to display the content of any structure, with a function looking
like something like this proto :
void display_content_of (void * data, const char which_structure[])
{
...
if (strcmp (which_structure, "t_h2") == 0)
{
t_h2 *p_h2 = (t_h2 *)data ;
show_all_members_of_h2 (p_h2) ;
}
...
}



I suppose the solution to my quest is something like what does a compiler do
(indeed, my solution is not supposed to work just at run time... It can use
include files, process them, to form a new set of files, compile them and
build the tool I need...)
Maybe yacc & lex would be helpfull, but I need some hints 'cause I don't
know them.
Maye be a solution based on "indexof" and macros exists, too, but I'm not
that confident...

Any help would be much appreciated.

Thank you.

Jerome de Lagausie


Consider using hash-tables rather than structs. It would make it a
lot easier to write code to print them out.

Also consider creating some sort of variant type. For instance a
struct where one member stores the type of the data stored in the
other member.

The alternative is to write some sort of language that you can then
process, as Eric suggests.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
474,139
Messages
2,570,805
Members
47,356
Latest member
Tommyhotly

Latest Threads

Top