misra 19.10 with array initialiser - c

MISRA 19.10:
In the definition of a function-like macro each instance of a parameter shall be enclosed in parentheses unless it is used as the operand of # or ##.
I have a struct defined like this:
typedef struct
{
SUint_t affValueIndex;
const SFloat_t affLoSaturation;
const SFloat_t affHiSaturation;
const SFloat_t affCoeffTab[SDEF_ANALOG_FLOAT_FILTER_LEN];
SFloat_t affValueTab[SDEF_ANALOG_FLOAT_FILTER_LEN];
} SAnalogFloatFilter_t;
Then I do:
#define DEF_ANALOG_FILTER_COEFF_LIST {0.0287421759f, \
0.1225311874f, \
0.2123775504f, \
0.2726981726f, \
0.2123775504f, \
0.1225311874f, \
0.0287421759f}
#define SMK_ANALOG_FLOAT_FILTER_HANDLE(__name__, __coeff_list__, __hi_sat__, __low_sat__) \
SAnalogFloatFilter_t (__name__)[1] = {{0u, (__low_sat__), (__hi_sat__), __coeff_list__ , {(SFloat_t)0,}}}
static SMK_ANALOG_FLOAT_FILTER_HANDLE(CurrMonFilter,
DEF_ANALOG_FILTER_COEFF_LIST,
(SFloat_t)DEF_ANALOG_FILTER_HI_SAT,
(SFloat_t)DEF_ANALOG_FILTER_LO_SAT);
The problem is that the __ coeff_list __ parameter cannot have a parenthesis as it then expands to ({...}) (an array initialilser), to which the gcc complains:
foo.c:45:9: error: statement-expressions are not allowed outside functions nor in template-argument lists
Is there a clever way to keep the MISRA 19.10 check AND have an array initialiser in the SMK_ANALOG_FLOAT_FILTER_HANDLE macro?

This compiles for me:
typedef int SUint_t;
typedef float SFloat_t;
#define SDEF_ANALOG_FLOAT_FILTER_LEN 8
typedef struct
{
SUint_t affValueIndex;
const SFloat_t affLoSaturation;
const SFloat_t affHiSaturation;
const SFloat_t affCoeffTab[SDEF_ANALOG_FLOAT_FILTER_LEN];
SFloat_t affValueTab[SDEF_ANALOG_FLOAT_FILTER_LEN];
} SAnalogFloatFilter_t;
#define DEF_ANALOG_FILTER_COEFF_LIST (const SFloat_t[SDEF_ANALOG_FLOAT_FILTER_LEN]) \
{0.0287421759f, \
0.1225311874f, \
0.2123775504f, \
0.2726981726f, \
0.2123775504f, \
0.1225311874f, \
0.0287421759f}
#define SMK_ANALOG_FLOAT_FILTER_HANDLE(__name__, __coeff_list__, __hi_sat__, __low_sat__) \
SAnalogFloatFilter_t (__name__)[1] = {{0u, (__low_sat__), (__hi_sat__), (__coeff_list__) , {(SFloat_t)0,}}}
#define DEF_ANALOG_FILTER_HI_SAT 0.0f
#define DEF_ANALOG_FILTER_LO_SAT 0.0f
static SMK_ANALOG_FLOAT_FILTER_HANDLE(CurrMonFilter,
DEF_ANALOG_FILTER_COEFF_LIST,
(SFloat_t)DEF_ANALOG_FILTER_HI_SAT,
(SFloat_t)DEF_ANALOG_FILTER_LO_SAT);
Tested on Ubuntu 12.04.03 LTS with commands:
gcc-4.6 -c -o foo.o foo.c
and
gcc-4.8 -c -o foo.o foo.c

Related

Parametrized generic C macros

I'm playing around with building a psuedo-generic type in C. Essentially, I'm trying to clone Rust's Option<T> with a predefined, constrained list of types allowable as T.
Obviously, C isn't really suited for this -- I'm doing this primarily to see how far I can go (as opposed to something I'd expect to use in real production code). To that end, any ugly hacks are fair game.
What I have so far builds out a separate set of inner-type-specific functions for all provided types. It looks something like this:
Header:
#pragma once
#define ALL_OPTIONS \
OPTION_INSTANCE(option_bool, bool) \
OPTION_INSTANCE(option_double, double) \
OPTION_INSTANCE(option_int, int)
#define OPTION_INSTANCE(name, inner) \
typedef struct { \
bool is_some; \
inner val; \
} name##_t;
ALL_OPTIONS
#undef OPTION_INSTANCE
#define OPTION_INSTANCE(name, inner) \
name##_t name##_some(inner val); \
name##_t name##_none(void); \
bool name##_is_some(name##_t self); \
bool name##_is_none(name##_t self); \
ALL_OPTIONS
#undef OPTION_INSTANCE
Implementation:
#include "option.h"
#define OPTION_INSTANCE(name, inner) \
name##_t name##_some(inner val) { \
return (name##_t) { \
.is_some = true, \
.val = val, \
}; \
} \
\
name##_t name##_none(void) { \
return (name##_t) { \
.is_some = false, \
}; \
} \
\
bool name##_is_some(name##_t self) { \
return self.is_some; \
} \
\
bool name##_is_none(name##_t self) { \
return !self.is_some; \
}
ALL_OPTIONS
#undef OPTION_INSTANCE
Note that in my actual code I have many more functions defined for the generated types.
This works well enough, though primarily all I've done is reduce implementation boilerplate. The next step would be to implement option_is_some (no type qualification) which can accept any option_<inner>_t
I can do that well enough with a manual macro, leveraging C11 generics:
#define option_is_some(self) \
_Generic((self), \
option_bool_t: option_bool_is_some, \
option_double_t: option_double_is_some, \
option_int_t: option_int_is_some, \
)(self)
but this necessarily duplicates the list of types defined in ALL_OPTIONS. What I'd really like to do would be something like
#define OPTION_INSTANCE(name, inner) \
name##_t: name##_is_some,
#define option_is_some(self) \
_Generic((self), \
ALL_OPTIONS \
default: false \
)(self)
#undef OPTION_INSTANCE
but that fails, since ALL_OPTIONS is expanded when option_is_some is used (where OPTION_INSTANCE will be undefined).
So, I'm looking for alternatives. I'd happily move to a radically different method of defining a generic list of types (instead of the ALL_OPTIONS hack) -- however, I do want to preserve the property that adding a new supported inner type only requires a change in a single location.
Just access the member in the macro itself:
#define option_is_some(self) ((self).is_some)
Overall, your implementation is strange. Do not have a central ALL_OPTIONS place - do one option at a time, separately from each other. Files are split into headers and source files in C.
#define OPTION_HEADER(name, inner) \
typedef struct { \
bool is_some; \
inner val; \
} name##_t; \
\
name##_t name##_some(inner val); \
name##_t name##_none(void); \
bool name##_is_some(name##_t self); \
bool name##_is_none(name##_t self);
#define OPTION_SOURCE(name, inner) \
name##_t name##_some(inner val) { \
return (name##_t) { \
.is_some = true, \
.val = val, \
}; \
} \
etc...
#define OPTION_HEADER_AND_SOURCE(name, ...) \
OPTION_HEADER(name, __VA_ARGS__)
OPTION_SOURCE(name, __VA_ARGS__)
Then you would just do the options:
OPTION_HEADER_AND_SOURCE(option_bool, bool)
OPTION_HEADER_AND_SOURCE(option_double, double)
OPTION_HEADER_AND_SOURCE(option_int, int)
You can take a look at other projects that I've found: https://github.com/tylov/STC and https://github.com/glouw/ctl that use macro-ish templates to implement in C various container known from C++.

Generic multiline macro with parameters

I'm trying to implement a generic stack in C, with the help of a big macro (not the best way, but that's not the point here).
This macro contains functions declarations, structures and functions calls, with a TYPE type that would be replaced by what needed:
#define STACK(TYPE) \
( \
struct stack \
{ \
size_t size; \
struct container *top; \
}; \
\
struct container \
{ \
TYPE data; \
struct container *next; \
}; \
\
struct stack *stack_init(void) \
{ \
struct stack *s = malloc(sizeof (struct stack)); \
if (!s) \
return NULL; \
return s; \
} \
... ...
)
This header file would be called in any .c file with this line
#include "utils_stack.h"
STACK(int)
Thing is, after trying every possible form of syntax gcc told me to try, I can't find a way to get it to work. I tried with parenthesis, brackets, both, none...
The code just simply won't work. Here is the error I get with the above syntax for example:
error: expected identifier or ‘(’ before ‘struct’
While trying to run gcc with the -E flag, I clearly see that TYPE is being replaced by int.
So here is my question, How do I need to write my macro to be able to... use it ?
Thank you in advance
As mentioned in the comment, this should work, just remove the parentheses:
#include <stdio.h>
#include <malloc.h>
#define STACK(TYPE) \
struct stack \
{ \
size_t size; \
struct container *top; \
}; \
\
struct container \
{ \
TYPE data; \
struct container *next; \
}; \
\
struct stack *stack_init(void) \
{ \
struct stack *s = malloc(sizeof (struct stack)); \
if (!s) \
return NULL; \
return s; \
} \
STACK(int)
int main()
{
struct stack *s;
s = stack_init();
// ...
}
Use parentheses if you define function-like macros, like:
#define maxint(a,b) \
({int _a = (a), _b = (b); _a > _b ? _a : _b; })
See gcc statement expresions for details.

BACnet Stack Makefile

I updated this post on 8/23 to reflect the working solution.
I'm working with the c BACnet Stack on sourceforge. http://sourceforge.net/projects/bacnet/
I'm trying to modify the demo server included in the library. The server does almost exactly what I want it to, except that I need to connect it to some other c programs that I wrote.
My problem right now is that I can't figure out how to add my own c programs into the demo server. There are several nested Makefiles in the demo. I've tried adding my file into these Makefiles, but the compiler (gcc) doesn't like it.
The latest error is:
No rule to make target ../../demo/object/test.o', needed bybacserv'. Stop.
I am not a c expert. I've been working with it my spare time for about a year. I understand the basics of a Makefile, but the Makefiles in this demo are apparently beyond me.
Is there anyone familiar with this library that might give me a little help?
Are there any better documentation than what is on the sourceforge website?
In this example I'm simply trying to add test.c to ai.c.
/demo/server/Makefile
OBJECT_SRC = \
$(BACNET_OBJECT)/device.c \
$(BACNET_OBJECT)/ai.c \
$(BACNET_OBJECT)/ao.c \
$(BACNET_OBJECT)/av.c \
$(BACNET_OBJECT)/bi.c \
$(BACNET_OBJECT)/bo.c \
$(BACNET_OBJECT)/bv.c \
$(BACNET_OBJECT)/csv.c \
$(BACNET_OBJECT)/lc.c \
$(BACNET_OBJECT)/lsp.c \
$(BACNET_OBJECT)/ms-input.c \
$(BACNET_OBJECT)/mso.c \
$(BACNET_OBJECT)/msv.c \
$(BACNET_OBJECT)/nc.c \
$(BACNET_OBJECT)/trendlog.c \
$(BACNET_OBJECT)/test.c \ <-- New entry
$(BACNET_OBJECT)/bacfile.c
/lib/Makefile
CORE_SRC = \
$(BACNET_CORE)/apdu.c \
$(BACNET_CORE)/npdu.c \
$(BACNET_CORE)/bacdcode.c \
$(BACNET_CORE)/bacint.c \
$(BACNET_CORE)/bacreal.c \
$(BACNET_CORE)/bacstr.c \
$(BACNET_CORE)/bacapp.c \
$(BACNET_CORE)/bacprop.c \
$(BACNET_CORE)/bactext.c \
$(BACNET_CORE)/datetime.c \
$(BACNET_CORE)/indtext.c \
$(BACNET_CORE)/key.c \
$(BACNET_CORE)/keylist.c \
$(BACNET_CORE)/proplist.c \
$(BACNET_CORE)/debug.c \
$(BACNET_CORE)/bigend.c \
$(BACNET_CORE)/arf.c \
$(BACNET_CORE)/awf.c \
$(BACNET_CORE)/cov.c \
$(BACNET_CORE)/dcc.c \
$(BACNET_CORE)/iam.c \
$(BACNET_CORE)/ihave.c \
$(BACNET_CORE)/rd.c \
$(BACNET_CORE)/rp.c \
$(BACNET_CORE)/rpm.c \
$(BACNET_CORE)/timesync.c \
$(BACNET_CORE)/whohas.c \
$(BACNET_CORE)/whois.c \
$(BACNET_CORE)/wp.c \
$(BACNET_CORE)/wpm.c \
$(BACNET_CORE)/abort.c \
$(BACNET_CORE)/reject.c \
$(BACNET_CORE)/bacerror.c \
$(BACNET_CORE)/ptransfer.c \
$(BACNET_CORE)/memcopy.c \
$(BACNET_CORE)/filename.c \
$(BACNET_CORE)/tsm.c \
$(BACNET_CORE)/bacaddr.c \
$(BACNET_CORE)/address.c \
$(BACNET_CORE)/bacdevobjpropref.c \
$(BACNET_CORE)/bacpropstates.c \
$(BACNET_CORE)/alarm_ack.c \
$(BACNET_CORE)/event.c \
$(BACNET_CORE)/getevent.c \
$(BACNET_CORE)/get_alarm_sum.c \
$(BACNET_CORE)/readrange.c \
$(BACNET_CORE)/timestamp.c \
$(BACNET_CORE)/test.c \ <-- Do not include test.c in this Makefile at all
$(BACNET_CORE)/version.c
new file locations:
test.c is located in /src <-- Should be located in /demo/object
test.h is located in /include <-- This works ok here
test.h
#ifndef _TEST_INCLUDE_
#define _TEST_INCLUDE_
void printit();
#endif
test.c
#include <stdio.h> <-- Needed to add #include <stdio.h>
#include "test.h"
void printit (){
printf("it....");
}
/demo/object/ai.c
...
#include "handlers.h"
#include "timestamp.h"
#include "test.h"
#include "ai.h"
...
void Analog_Input_Init(
void)
{
unsigned i;
#if defined(INTRINSIC_REPORTING)
unsigned j;
#endif
printit(); //*****************************************************************
for (i = 0; i < MAX_ANALOG_INPUTS; i++) {
printf("Initializing AI:%u\n",i);
AI_Descr[i].Present_Value = 0.0f;
AI_Descr[i].Out_Of_Service = false;
AI_Descr[i].Units = UNITS_PERCENT;
AI_Descr[i].Reliability = RELIABILITY_NO_FAULT_DETECTED;
#if defined(INTRINSIC_REPORTING)
AI_Descr[i].Event_State = EVENT_STATE_NORMAL;
/* notification class not connected */
AI_Descr[i].Notification_Class = BACNET_MAX_INSTANCE;
/* initialize Event time stamps using wildcards
and set Acked_transitions */
for (j = 0; j < MAX_BACNET_EVENT_TRANSITION; j++) {
datetime_wildcard_set(&AI_Descr[i].Event_Time_Stamps[j]);
AI_Descr[i].Acked_Transitions[j].bIsAcked = true;
}
/* Set handler for GetEventInformation function */
handler_get_event_information_set(OBJECT_ANALOG_INPUT,
Analog_Input_Event_Information);
/* Set handler for AcknowledgeAlarm function */
handler_alarm_ack_set(OBJECT_ANALOG_INPUT, Analog_Input_Alarm_Ack);
/* Set handler for GetAlarmSummary Service */
handler_get_alarm_summary_set(OBJECT_ANALOG_INPUT,
Analog_Input_Alarm_Summary);
#endif
}
}
I would say that your test.o cannot be made by gcc. The Makefile does specify to create it, though :
.c.o:
${CC} -c ${CFLAGS} $*.c -o $#
I noticed that $(BACNET_OBJECT) in /demo/server/Makefile refers to the path /demo/object
You should try to add test.c there.
And i believe you don't need to add test.c in /lib/Makefile
Long time i didnt do any C, but didnt you forget to #include <stdio.h> for printf in test.c ?

How to eliminate a redundant macro parameter

A while ago, I wrote a set of X-macros for a largish project. I needed to maintain coherent lists of both strings and enumerated references/hash values/callback functions etc. Here is what the function callback looks like
#define LREF_LOOKUP_TABLE_TEXT_SIZE 32
#define _LREF_ENUM_LIST(_prefix,_ref,...) _prefix ## _ ## _ref,
#define _LREF_BASE_STRUCT_ENTRY(_prefix,_ref) .text= #_ref "\0", .position= _LREF_ENUM_LIST(_prefix, _ref)
#define _LREF_FUNCTION_STRUCT_LIST(_prefix,_ref,...) {_LREF_BASE_STRUCT_ENTRY(_prefix,_ref) _prefix ## _ ## _ref ## _callback},
#define _LREF_ENUM_TYPEDEF(_prefix) \
typedef enum _prefix \
{ \
_ ## _prefix ## s(_prefix,_LREF_ENUM_LIST) \
_LREF_ENUM_LIST(_prefix,tblEnd) \
} e_ ## _prefix
#define _LREF_LOOKUP_TABLE_TYPEDEF(_prefix, _extras) \
typedef struct _prefix ## _lookup \
{ \
const char text[LREF_LOOKUP_TABLE_TEXT_SIZE]; \
e_ ## _prefix position; \
_extras \
} _prefix ##_lookup_t
#define LREF_GENERIC_LOOKUP_TABLE(_prefix, _type, _tabledef, _listdef, _extras) \
_LREF_ENUM_TYPEDEF(_prefix); \
_LREF_LOOKUP_TABLE_TYPEDEF(_prefix,_tabledef); \
_extras \
_LREF_LOOKUP_TABLE_DECLARATION(_prefix,_listdef, _type)
#define LREF_FUNCTION_LOOKUP_TABLE(_prefix, _type) \
_ ## _prefix ## s(_prefix, _LREF_FUNCTION_DEF ) \
LREF_GENERIC_LOOKUP_TABLE( _prefix, \
_type, \
void* (*function) (void*);, \
_LREF_FUNCTION_STRUCT_LIST, )
This sits in a header file and allows me to write things like:
#define _cl_tags(x,_) \
_(x, command_list) \
_(x, command) \
_(x, parameter) \
_(x, fixed_parameter) \
_(x, parameter_group) \
_(x, group) \
_(x, map) \
_(x, transform)
LREF_FUNCTION_LOOKUP_TABLE(cl_tag, static);
This keeps processing routines short. For example, loading a configuration file with the above tags is simply:
for (node_tag = cl_tag_lookup_table; node_tag->position != cl_tag_tblEnd; node_tag++)
{
if (strcasecmp(test_string, node_tag->text) == 0)
{
func_return = node_tag->function((void*)m_parser);
}
}
My question is this: I hate that I have to include the second parameter in my #define. I want to be able to write #define _cl_tags(_) instead of #define _cl_tags(x,_). As you can see, the x is only used to pass the prefix (cl_tag) down. But this is superfluous as the prefix is a parameter to the initial macro.
The solution to this would be easy if my preprocessor would expand the outer-most macros first. Unfortunately, GCC's preprocessor works through the inner-most macros, i.e. parameter values, before expanding the outermost macro.
I am using gcc 4.4.5
Clarification
By C89 (and C99) standard, the following definitions
#define plus(x,y) add(y,x)
#define add(x,y) ((x)+(y))
with the invocation
plus(plus(a,b),c)
should yield
plus(plus(a,b),c)
add(c,plus(a,b))
((c)+(plus(a,b))
((c)+(add(b,a))
((c)+(((b)+(a))))
gcc 4.4.5 gives
plus(plus(a,b),c)
plus(add(b,a),c)
plus(((b)+(a)),c)
add(c,((b)+(a)))
((c)+(((b)+(a))))
Here's what I would do (have done similarly):
Put these in a utility header file:
/*
* Concatenate preprocessor tokens A and B without expanding macro definitions
* (however, if invoked from a macro, macro arguments are expanded).
*/
#define PPCAT_NX(A, B) A ## B
/*
* Concatenate preprocessor tokens A and B after macro-expanding them.
*/
#define PPCAT(A, B) PPCAT_NX(A, B)
Then define this before including your LREF macro header file:
#define LREF_TAG cl_tag
Then, in your LREF macro header file,
#define LREF_PFX(x) PPCAT(LREF_TAG, x)
#define LREF_SFX(x) PPCAT(x, LREF_TAG)
Then replace every instance of _prefix ## foo with LREF_PFX(foo) and foo ## _prefix with LREF_SFX(foo).
(When pasting more than two tokens together, just use nested PPCAT's.)
Your invocation would become
#define LREF_TAG cl_tag
#define _cl_tags(_) \
_(command_list) \
_(command) \
_(parameter) \
_(fixed_parameter) \
_(parameter_group) \
_(group) \
_(map) \
_(transform)
LREF_FUNCTION_LOOKUP_TABLE(static);
This answer just addresses the 'clarification'. Here is the correct behaviour:
#define plus(x,y) add(y,x)
#define add(x,y) ((x)+(y))
Initial: plus(plus(a,b),c)
Pass 1a: plus(add(b,a),c)
Pass 1b: add(c,add(b,a))
Pass 2a: add(c,((b)+(a)))
Pass 2b: ((c)+(((b)+(a))))
The rules are that each macro is replaced once non-recursively (starting from the inner-most when they are nested); and then a new pass (aka. "rescan") happens repeating the same procedure, this continues until a pass performs no replacement.
I'm not sure what point you were trying to make though, as you give the same final conclusion for both GCC and what you expected to happen.

Problem definition of struct in Macro

I'm working on macros in C, trying to simulate the objet behavior but using C and I'm having a problem with the definition of a variable defined from a struct in another struct in a macro. That's my code... it works:
#include <stdio.h>
#include <stdlib.h>
#define STACK_MAX_CAPACITY 10
#define DECLARE_STACK(Type) \
typedef struct MetaPile_##Type; \
\
typedef struct Pile_##Type_t{ \
Type q[STACK_MAX_CAPACITY]; \
int pos; \
} Pile_##Type; \
\
typedef struct MetaPile_##Type_t{ \
void (* push) ( Pile_##Type* p, Type val ); \
void (*init) (Pile_##Type* p); \
} MetaPile_##Type; \
\
void init_##Type( Pile_##Type* p ){ \
p->pos = 0; \
int i; \
for(i=0; i<STACK_MAX_CAPACITY; i++){ \
p->q[i]=0; \
} \
} \
\
void push_##Type( Pile_##Type* p, Type val ) { \
if(p->pos < STACK_MAX_CAPACITY){ \
p->q[p->pos]=val; \
p->pos++; \
} \
} \
MetaPile_##Type TheMetaPile_##Type; \
void initTheMetaPile_##Type(){ \
TheMetaPile_##Type.init = &init_##Type; \
TheMetaPile_##Type.push = &push_##Type; \
} \
\
DECLARE_STACK(int)
int main(){
int i;
initTheMetaPile_int();
Pile_int pi;
TheMetaPile_int.init(&pi);
push_int(&pi, 2);
push_int(&pi, 3);
push_int(&pi, 4);
push_int(&pi, 5);
push_int(&pi, 6);
for(i=0; i<STACK_MAX_CAPACITY; i++){
printf("%d",pi.q[i]);
}
return 0;
}
The first structure define an array of a dinamic type thanks to the macro (Pile_##Type) that represents the attributs side of an objet, and another structure (MetaPile_##Type) that will manage the "methods" of the objet, via fonction pointers. The fonction init works as a constructor and initialises my "objet" pi.
Now what I want is to have a reference in Pile_##Type of a variable of type MetaPile_##Type (called for exemple myClass) in order to be able to make pi->myClass->push and call the fonction push_int. But when I make:
typedef struct Pile_##Type_t{ \
Type q[STACK_MAX_CAPACITY]; \
int pos; \
MetaPile_##Type myClass; \
} Pile_##Type; \
I have a misunderstandable mistake...
D:\main.c|40|warning: useless keyword or type name in empty declaration|
D:\main.c|40|error: syntax error before "MetaPile_int"|
D:\main.c|40|warning: no semicolon at end of struct or union|
D:\main.c|40|warning: type defaults to `int' in declaration of `Pile_int'|
D:\main.c|40|warning: data definition has no type or storage class|
D:\main.c|40|error: syntax error before '*' token|
D:\main.c|40|error: syntax error before '*' token|
D:\main.c|40|error: syntax error before '*' token|
D:\main.c||In function `init_int':|
D:\main.c|40|error: `p' undeclared (first use in this function)|
D:\main.c|40|error: (Each undeclared identifier is reported only once|
D:\main.c|40|error: for each function it appears in.)|
D:\main.c|40|error: syntax error before '*' token|
D:\main.c||In function `push_int':|
D:\main.c|40|error: `p' undeclared (first use in this function)|
D:\main.c|40|error: `val' undeclared (first use in this function)|
D:\main.c||In function `main':|
D:\main.c|47|error: syntax error before "pi"|
D:\main.c|49|error: `pi' undeclared (first use in this function)|
||=== Build finished: 12 errors, 4 warnings ===|
I don't know what's worong with the defintion of myClass, I've used * also but the error persits. Thanks if somebody can help.
Your problem is not the usage of macros, this only distracts you.
typedef struct MetaPile_int;
is just syntactically incorrect. A simple forward declaration of a struct looks like this:
struct MetaPile_int;
But if you just want to make your life easier do it like this:
typedef struct MetaPile_int MetaPile_int;
This is a forward declaration of the struct and a definition of the identifier MetaPile_int at the same time.
To get it working try it without putting it in a macro, first. Or use a compiler that helps you trace errors in macros such as clang.
Remove the typedef struct MetaPile_##Type; line - what's that supposed to do (besides causing your errors, that is)?
You try to insert a full struct (MetaPile_##Type) before declaring it, change the order of them like that [ in MetaPile_##Type you only use pointers to Pile_##Type_t, and the size of pointers is known]:
Edit:
This declaration works for me fine:
#define DECLARE_STACK(Type) \
struct Pile_##Type_t; \
\
typedef struct MetaPile_##Type_t{ \
void (* push) ( Pile_##Type_t* p, Type val ); \
void (*init) (Pile_##Type_t* p); \
} MetaPile_##Type; \
\
typedef struct Pile_##Type_t{ \
Type q[STACK_MAX_CAPACITY]; \
int pos; \
MetaPile_##Type myClass; \
} Pile_##Type; \
\
void init_##Type( Pile_##Type* p ){ \
p->pos = 0; \
int i; \
for(i=0; i<STACK_MAX_CAPACITY; i++){ \
p->q[i]=0; \
} \
} \
\
void push_##Type( Pile_##Type* p, Type val ) { \
if(p->pos < STACK_MAX_CAPACITY){ \
p->q[p->pos]=val; \
p->pos++; \
} \
} \
MetaPile_##Type TheMetaPile_##Type; \
void initTheMetaPile_##Type(){ \
TheMetaPile_##Type.init = &init_##Type; \
TheMetaPile_##Type.push = &push_##Type; \
} \
\
and it should do the work.

Resources