Lola said:
I am trying the folowing preprocessor trick with gcc but it doesn't
seem to work (worked with all the compilers I have used so far):
As a general rule, I am wary of anything that can be called a
"preprocessor trick". Often, the effect is to obfuscate the code so you
need to be sure that they pay their way, so to speak.
#ifdef GLOBAL_VARS
#define EXT
#define EQ =
#else
#define EXT extern
#define EQ ;##/##/
#endif
I get the error:
In file included from src/verilog.cpp:16:
From the file name it looks like you may be using C++. You should know
that there are differences between the two preprocessors and this may
matter. In fact, the way I'd do what I think you are trying to do
relies on one of these differences.
./include/verilog.h:35:1: pasting ";" and "/" does not give a valid
preprocessing token
The error message is accurate. Presumably you know what ## does in a
macro body -- it joins two tokens into one -- and the message is
reporting that ;/ is not a valid token in C. I'd guess the first ## is
simply not meant to be there.
./include/verilog.h:35:1: pasting "/" and "/" does not give a valid
preprocessing token
This one, though accurate, is not so helpful. Comments are treated as
white space so // is not, in fact, a valid preprocessing token. What's
more (and this affects the whole intent of your "trick") comments are
removed before macros are expanded. The effect of this is that a macro
can't expand to a comment which seems to be what your trick is trying to
do.
In file included from src/verilog.cpp:16:
./include/verilog.h:35: error: expected unqualified-id before '/'
token
This is just the compiler ploughing on and not making sense of what the
erroneous macros have left behind.
gcc is quite correct to reject the code. What compilers accepted it?
Something like this:
#ifdef GLOBAL_VARS
#define EXT
#define INIT(...) = __VA_ARGS__
#else
#define EXT extern
#define INIT(...)
#endif
/* e.g. */
EXT int x INIT(42);
EXT int x[] INIT({1, 2, 3});
might suit but since the source would need to be re-written I'd probably
go for in GLOBAL macro:
#ifdef GLOBAL_VARS
#define GLOBAL(n, ...) n = __VA_ARGS__
#else
#define GLOBAL(n, ...) extern n
#endif
/* e.g. */
GLOBAL(int x, 42);
GLOBAL(int x[], {1,2,3});
The motivation seems to be based on having a large number of external
variables that you want to be able to define and to declare using just
one source. There may well be some other way to organise the code that
avoids the problem in the first place but it hard to know without seeing
the use to put these macros to.