2

While testing a C software, I'd like to use macros to generate function calls. Using codewarrior 5.2 (very old) compiler -because I don't have choice, I don't know if this is standard behavior.

in macros.h

#define RUNTEST(i)              \
  testcase_index = i;             \
  __PREFIX__##_testCase_##i()

in test_foo.c

#include "macros.h"
#define __PREFIX__ foo

RUNTEST(10);

Apparently __PREFIX__ is not expanded, and preprocessor generates a call to __PREFIX___testcase_10(), which of course will fail at linking time. Copying everything in the same file doesn't seem to change anything.

Is there a simple way out?

Alternative

I also tried #define __PREFIX__() foo to force macro expansion. In that case, it almost works, and now generates foo _testcase_10() (with a space), which of course won't compile.

Community
  • 1
  • 1
PPC
  • 1,734
  • 1
  • 21
  • 41
  • 3
    Possible duplicate of [How to concatenate twice with the C preprocessor and expand a macro as in "arg ## \_ ## MACRO"?](https://stackoverflow.com/questions/1489932/how-to-concatenate-twice-with-the-c-preprocessor-and-expand-a-macro-as-in-arg) – H Walters Jun 19 '19 at 02:17
  • 1
    @HWalters I think you're right. I tried writing out an answer and it ended up pretty close to that other question linked – CoffeeTableEspresso Jun 19 '19 at 03:37

1 Answers1

2

I've done a simplified version of your question here (without assigning to the testcase index):

.h:

#define PASTER(x, y) x##_testCase_##y
#define EVAL(x, y) PASTER(x, y)
#define RUNTEST(i) EVAL(__PREFIX__, i)

.c

#define __PREFIX__ foo

// whatever

RUNTEST(1);

Explanation:

From the C standard:

6.10.3.1 Argument substitution

After the arguments for the invocation of a function-like macro have been identified, argument substitution takes place. A parameter in the replacement list, unless preceded by a # or ## preprocessing token or followed by a ## preprocessing token (see below), is replaced by the corresponding argument after all macros contained therein have been expanded. Before being substituted, each argument’s preprocessing tokens are completely macro replaced as if they formed the rest of the preprocessing file; no other preprocessing tokens are available.

So now that we have this, I'll walk through the expansion of RUNTEST(1):

EVAL(__PREFIX__, i)
PASTER(foo, 1)
foo##_testCase_##1
foo_testCase_1
Community
  • 1
  • 1
CoffeeTableEspresso
  • 2,614
  • 1
  • 12
  • 30
  • FYI, nit pick... when `RUNTEST(1)` is invoked, first step is a.s. (as shown in your 6.10.3.1 citation). That produces `EVAL(__PREFIX__, 1)`. _Then_ after pastes/stringifications (of which there's none here), `EVAL(__PREFIX__, 1)` is scanned during rescan-and-further-replacement (6.10.3.4). – H Walters Jun 19 '19 at 03:42