Hi Bruno, > In Gnulib, we usually avoid extensive use of multi-line macros, because > it hampers debuggability. Here, however, one needs macros, in order to > accommodate the TYPE argument, which is not necessarily compatible to 'void > *'. > Nevertheless, we would try to put as much code as possible into functions. > The STACK_INIT macro, for example, could be implemented as a function.
How? This would mean that the function stack_init has to take a void * argument, which has to be cast to struct { void *base; ... } and we have to hope that this structure is guaranteed to be compatible to struct { type *base; ... } by the C standard. > > #define STACK_CLEAR(stack) \ > > free ((stack).base) > > Shouldn't this one also set .size and .allocated to 0 ? A stack can be uninitialized or initialized. An uninitialized stack is initialized by STACK_INIT. It is cleared (and uninitialized) by STACK_CLEAR. An uninitialized stack does not have to maintain any invariant. The only way to use it is to initialize it again. Thus, setting .size and .allocated seems pointless. > > #define STACK_POP(stack) \ > > (stack).base [--(stack).size] > > > > #define STACK_DISCARD(stack) \ > > (--(stack).size) > > > > #define STACK_TOP(stack) \ > > (stack).base[(stack).size - 1] > > In these three macros, I would consider to abort() when (stack).size == 0. In the form of assure of the assure module? Or, to facilitate optimization, better assume from verify module? In non-debug builds, I want to make sure that no superfluous checks are made. Marc