ObUglyMacroHack:
When trying to do object oriented programming under ANSI-C (no weenie
using C++ here 8-), I needed to manipulate several stacks (each a different
type, one integer, one float, etc ...). So, I wrote the following C code
(at the end of this message).
-spc (love playing around with that C preprocessor)
===============[ header file ]=========================================
/***************************************************************************
*
* Because the ## in a macro definition does not expand any argument macros,
* we simply can't do a _MKPROTO(x,y) x ## y, because then
* _MKPROTO(T_PREFIX,_push) would improperly evaluate to T_PREFIX_push, which
* is what we DON'T want, therefore, we have to do a bit of nesting to get
* what we want.
*
* That's why this looks so strange ...
*
*****************************************************************************/
#define _MKKPROTO(x,y) x ## y
#define _MKPROTO(x,y) _MKKPROTO(x,y)
void _MKPROTO(T_PREFIX,_push) (T_TYPE);
T_TYPE _MKPROTO(T_PREFIX,_pop) (void);
void _MKPROTO(T_PREFIX,_drop) (void);
void _MKPROTO(T_PREFIX,_swap) (void);
void _MKPROTO(T_PREFIX,_dup) (void);
void _MKPROTO(T_PREFIX,_over) (void);
/*************************************************************/
==============[ C source file ]=================================
#include "that.header.file.h"
#define DX(x) x
/*********************************************************************/
void _MKPROTO(T_PREFIX,_push)(T_TYPE v)
{
struct dictionary *pdc = _MKPROTO(T_PREFIX,_parent);
T_TYPE *pv;
if (pdc->dc_Stackptr == 0)
{
_Error(__FILE__,__LINE__,"%s stack overflow",pdc->dc_Node.ln_Name);
_Stackerr = TRUE;
return;
}
pdc->dc_Stackptr--;
pv = (T_TYPE *)(pdc->dc_Stack);
pv[pdc->dc_Stackptr] = v;
}
/********************************************************************/
T_TYPE _MKPROTO(T_PREFIX,_pop)(void)
{
struct dictionary *pdc = _MKPROTO(T_PREFIX,_parent);
T_TYPE *pv;
T_TYPE v;
if (pdc->dc_Stackptr == pdc->dc_Stacktop)
{
_Error(__FILE__,__LINE__,"%s stack underflow",pdc->dc_Node.ln_Name);
_Stackerr = TRUE;
return(T_RETV);
}
pv = (T_TYPE *)(pdc->dc_Stack);
v = pv[pdc->dc_Stackptr];
pdc->dc_Stackptr++;
return(v);
}
/*******************************************************************/
void _MKPROTO(T_PREFIX,_drop)(void)
{
struct dictionary *pdc = _MKPROTO(T_PREFIX,_parent);
if (pdc->dc_Stackptr == pdc->dc_Stacktop)
{
_Error(__FILE__,__LINE__,"%s stack underflow",pdc->dc_Node.ln_Name);
return;
}
pdc->dc_Stackptr++;
}
/*****************************************************************/
void _MKPROTO(T_PREFIX,_swap)(void)
{
T_TYPE v1;
T_TYPE v2;
_Stackerr = FALSE;
v1 = _MKPROTO(T_PREFIX,_pop)();
if (_Stackerr) return;
v2 = _MKPROTO(T_PREFIX,_pop)();
if (_Stackerr) return;
_MKPROTO(T_PREFIX,_push)(v1);
if (_Stackerr) return;
_MKPROTO(T_PREFIX,_push)(v2);
}
/******************************************************************/
void _MKPROTO(T_PREFIX,_dup)(void)
{
T_TYPE v;
_Stackerr = FALSE;
v = _MKPROTO(T_PREFIX,_pop)();
if (_Stackerr) return;
_MKPROTO(T_PREFIX,_push)(v);
_MKPROTO(T_PREFIX,_push)(v);
}
/****************************************************************/
void _MKPROTO(T_PREFIX,_over)(void)
{
T_TYPE v1;
T_TYPE v2;
_Stackerr = FALSE;
v1 = _MKPROTO(T_PREFIX,_pop)();
if (_Stackerr) return;
_MKPROTO(T_PREFIX,_dup)();
if (_Stackerr) return;
v2 = _MKPROTO(T_PREFIX,_pop)();
if (_Stackerr) return;
_MKPROTO(T_PREFIX,_push)(v1);
if (_Stackerr) return;
_MKPROTO(T_PREFIX,_push)(v2);
}