2

I have a very similar question to: Macro and function with same name

I want a macro to only change the function call and not the function itself

#define original_function(a, b) replace_function(a, b)

uint64_t replace_function(int a, int b) {
    // some functionality
}

uint64_t original_function(int a, int b) {
    // some functionality
}

uint64_t main(uint64_t argc, uint64_t* argv) {
    original_function(10, 20);
}

this would result in changing the original function definition

#define original_function(a, b) replace_function(a, b)

uint64_t replace_function(int a, int b) {
    // some functionality
}

uint64_t replace_function(int a, int b) {
    // some functionality
}

uint64_t main(uint64_t argc, uint64_t* argv) {
    original_function(10, 20);
}

I cannot do this (which is the answer in the linked question)

uint64_t (original_function)(int a, int b) {
    // some functionality
}

//...

And I cannot put the definition after the function

uint64_t original_function(int a, int b) {
    // some functionality
}

#define original_function(a, b) replace_function(a, b)

// ...

Is it somehow possible to define in the macro to only change function calls and not function definitions? Or can I somehow define a macro to rename only the original function (not the call) so it won't be affected?

Edit: I can only change the macro not the code after that...

AJM
  • 1,317
  • 2
  • 15
  • 30
LDK
  • 197
  • 1
  • 10
  • Why can't you put the definition after the function? What error are you getting? – J...S May 29 '18 at 13:45
  • Have you thought about using function typedefs and then you can change the variable before calling it, makes for more readable code. – Neil May 29 '18 at 13:48
  • @J...S I cannot put the definition after the function because I will need to have the macro passed as argument to the compiler – LDK May 29 '18 at 13:49
  • @LDK 'Macro passed as argument to the _compiler_'? How – J...S May 29 '18 at 13:56
  • @J...S `gcc -D'original_function(a,b)=replace_function(a,b)' ... ` – LDK May 29 '18 at 13:58
  • Do not `-D'original_function(a,b)=replace_function(a,b)'` when code compiles `original_function()`. – chux - Reinstate Monica May 29 '18 at 13:59
  • @Neil thanks it migth work for others but I can really only change the macro... – LDK May 29 '18 at 13:59
  • Perhaps if the higher level goal was stated? What is desired is unusual, yet a different approach will likely solve the higher issue - if we knew it. – chux - Reinstate Monica May 29 '18 at 14:01
  • Can you use `#undef`? – Cornstalks May 29 '18 at 14:03
  • @Cornstalks I could use `#undef` but only at the very top not between the functions etc. – LDK May 29 '18 at 14:04
  • @chux I'm not sure what you mean? I can apply the marco only when I compile the whole code... – LDK May 29 '18 at 14:06
  • @chux The goal is: I have a c-file (which I cannot change) which executes a functions and through a marco passed to the compiler I want it to execute a different function... – LDK May 29 '18 at 14:09
  • "I could use #undef but only at the very top not between the functions etc." --> Why this limitation? Any goals and limitations should be appended to the post. – chux - Reinstate Monica May 29 '18 at 14:12
  • @chux Because I am passing the marco to the compiler without changing the code – LDK May 29 '18 at 14:14
  • Is the code that defines `original_function()` in one .c file and the code the uses `original_function()` in other .c files? – chux - Reinstate Monica May 29 '18 at 14:17
  • @chux no all code is in the same .c file – LDK May 29 '18 at 14:18
  • 4
    Hmmm, I suspect you are [out-of-luck](https://idioms.thefreedictionary.com/out+of+luck). – chux - Reinstate Monica May 29 '18 at 14:20
  • Is the linkage name of the original function important? If not, you could use a conditional definition of the `original_function` macro, like: `#ifndef original_function`, `#define original_function(a, b) the_original_function(a, b)`, `#endif`, and change `uint64_t original_function(int a, int b)` to `uint64_t the_original_function(int a, int b)`. – Ian Abbott May 29 '18 at 17:13
  • @IanAbbott thanks for your input but I tried it and this also just changes the name of the function definiton and name the function call – LDK May 29 '18 at 18:38
  • @LDK True. My suggestion was just to supply a default replacement when none has been provided via macro definitions on the command line. Because otherwise, you're out of luck as chux mentioned, as there is no way to temporarily undefine a macro and restore it later if you don't know the original macro definition. – Ian Abbott May 30 '18 at 10:17

1 Answers1

2

You can "pattern match" the line that the definition is on using the C preprocessor. To do this in a useful fashion, first you need an indirect SECOND macro:

#define SECOND(...) SECOND_I(__VA_ARGS__,,)
#define SECOND_I(A,B,...) B

...then it's useful to have an indirect GLUE:

#define GLUE(A,B) GLUE_I(A,B)
#define GLUE_I(A,B) A##B

...and finally, "selectively blue paint" original_function onto itself if and only if it appears on a specific line (this approach requires figuring out which line it's on, but I would suggest not being picky with this strange request):

#define original_function(a,b) \
   SECOND(GLUE(EXCEPT_FOR_LINE_,__LINE__),replace_function)(a,b)

So this macro will expand original_function with two arguments with replace_function, given that the first constructed token is not defined. But if that first token is defined, then the token expands first, after which the second argument for that is selected. Which means, you get to do this:

#define EXCEPT_FOR_LINE_6 ,original_function

...and if original_function is actually defined on line 6 (and not called on line 6), then the final expansion looks like the original... on line 6; and on all other lines it will generate a call to replace_function.

This example uses this technique on your code. And as a bonus, all of the macros above in this example are defined on the command line (per your reflected intended usage in the comments).

H Walters
  • 2,634
  • 1
  • 11
  • 13