macro expansion to achieve induction.

Jim Cromie jim.cromie@gmail.com
Thu Dec 1 20:28:00 GMT 2005




Im looking for a way to initialize an array of structs, ala:

   static struct sensor_device_attribute sda_fan_input[] = {
   __SENSOR_DEVICE_ATTR(fan1_input, S_IRUGO, show_fan_input, NULL, 0),
   __SENSOR_DEVICE_ATTR(fan2_input, S_IRUGO, show_fan_input, NULL, 1),
   __SENSOR_DEVICE_ATTR(fan3_input, S_IRUGO, show_fan_input, NULL, 2),
   };
  
but to do so more readably / compactly, and w/o fixed N-length

since macro language doesnt have foreach loops, I tried to do induction,
(f(N) -> F(1), f(N-1)) to replace the missing loop, but Im not expanding
the 2nd iteration. (as info gcc discusses)



struct cell {
  char* name;
  int id;
};

#define CELL_INIT_1(N)         { "fan" # N "_input", N }
#define CELL_INIT_N(N)         CELL_INIT_1(N), CELL_INIT_N(N-1)
#define CELL_INIT_all(N)       CELL_INIT_N(N,1)

struct cell culture[] = {
  CELL_INIT_N(3),
  { "name", 1 }
};


the above fails as folllows:
$ make macroN
cc -g    macroN.c   -o macroN
macroN.c:75: error: initializer element is not constant
macroN.c:75: error: (near initialization for `culture[1].name')
macroN.c:75: error: initializer element is not constant
macroN.c:75: error: (near initialization for `culture[1]')

the real reason is evident in -cc -E expansion:

# 71 "macroN.c"
struct cell culture[] = {
  { "fan" "3" "_input", 3 }, CELL_INIT_N(3 -1)
};

as you can see, the recursive expansion isnt happening.

I know the above is over-simplified;  the induction doesnt
currently terminate at N=0, and this would infact result in
infinite expansion.

OTGH,

info cpp, macro pitfalls, Self-Reference Macros, says :

If the self-reference were considered a use of the macro, it
would produce an infinitely large expansion.  To prevent this, the
self-reference is not considered a macro call.  It is passed into the
preprocessor output unchanged.

SO: ie Qs

Is there any way to:
a.  induce gcc/cpp to evaluate the macro as a macro,
    perhaps a builtin _enable_recursive_eval_ modifier thigny
b.  include conditionals in the macro def
    this conditional-def could serve as the hint to induce re-eval as a 
macro.
c.  its not clear how do this safely
    the condition may not properly terminate the expansion. (want a 
limiter, settable ideally)
d.  an explicit 1..N loop sounds safer.

Or is there an existing way that Ive missed ?  (I hope)

tia
Jim Cromie



More information about the Gcc-help mailing list