How to append to the name of an argument in C macro - c

I have a weird use case in which I need to modify the name of a variable that was passed in C
#define SET_PROTOBUF_REPEATED(msg_ptr, field_name, src_data, src_data_length)
{
/*
msg_ptr->field_name.len = src_data_length;
*/
// I want to do this
// msg_ptr->n_field_name = src_data_length
/*
msg_ptr->field_name.data = malloc(src_data_length);
memcpy(msg_ptr->field_name.data, src_data, src_data_length);
*/
msg_ptr->field_name = malloc(src_data_length);
memcpy(msg_ptr->field_name, src_data, src_data_length);
}
Because I am using repeated type in a protocol buffer message, the variable length is defined as
n_variable_name
instead of
variable_name.len
eg.
variable_name = frequency
// the length have to be n_frequency
The reason I want to have a macro that do this is because I have a lot of protobuf messages repeating the functionality of the function above. For the sake of readability and modularity I think it is a good idea to define a new function that take care of this.
Any advice would be much appreciated
Thanks

The canonical way to write a multi-line macro is to wrap it inside a do ... while(0) statement. This ensures that the macro works as a single statement. Eg.:
#define macro(a,b,c) \
do { \
(a) = (b)*(c); \
} while (0) /* No trailing semi-colon */
...
macro (x, y, z);
for (i = 0; i < n; i++)
macro (x, y, z); /* This wouldn't work properly without do...while(0) */
You should put parenthesis around your macro parameters to avoid surprises when someone passes unexpected arguments, such as macro (t, 1+2, 3+4); You also need a helper macro to concatenate the parameters. Perhaps you're looking for something like this:
#define CONCAT(x,y) x ## y
#define SET_PROTOBUF_REPEATED(msg_ptr, field_name, src_data, src_data_length) \
do { \
(msg_ptr)->CONCAT(n_,field_name) = (src_data_length); \
\
(msg_ptr)->(field_name) = malloc((src_data_length)); \
memcpy((msg_ptr)->(field_name), (src_data), (src_data_length)); \
} while (0)

Related

Complex one-line conditional checksum definitions

Taking up this code:
typedef enum CHECKSUM { DENY = 0, ALLOW = 1 } checksum;
#define terminal(x, str) static checksum* terminal_##x; { if(!strcmp(#str, "static")) { static checksum local = ALLOW; terminal_##x = &local; } else { checksum local = DENY; terminal_##x = &local; } }
What I want that code to do is define a macro function with two parameters x for name and str for a specific type. The macro function declares a static checksum* with the name terminal_ concatenated with the name x. Then it opens a new scope and stringify the specific type str and use a strcmp to check if it equals static. If so.. then it declares a variable type static checksum, initialized with ALLOW and makes the declared pointer to point to it, if it is not equal then it declares a variable type checksum, initialized with DENY and set the pointer to point to it.
Then we can call the macro like that:
int main(void)
{
int i = 0;
while(*terminal_name == ALLOW) { terminal(name, static) if(i > 200) { *terminal_name = DENY; } i++; }
return 0;
// Note that this is only an example usage. The real usage of this is far more long and complicated.
}
The code is well compiled on C89 and it causes no errors nor warnings. On a first view.. it works.
But as you can see by yourself.. it looks really suspicious.
Is that the correct way I am doing it?
Please ask if you are in trouble understanding something.
It's hard to say if the macro is reasonable or a bad idea without knowing more about your program.
Stylistically, you can use backslashes to split the macro up into multiple lines. That'll make it a lot more readable and less "suspicious".
#define terminal(x, str) \
static checksum* terminal_##x; \
{ \
if (!strcmp(#str, "static")) { \
static checksum local = ALLOW; \
terminal_##x = &local; \
} \
else { \
checksum local = DENY; \
terminal_##x = &local; \
} \
}
Using strcmp to decide whether to use static or not really rubs me the wrong way. That's a runtime check influencing a compile-time decision. I would suggest making two separate macros, say LOCAL_TERMINAL and STATIC_TERMINAL, rather than keying off of a macro argument.
#define LOCAL_TERMINAL (x) checksum terminal_##x = DENY
#define STATIC_TERMINAL(x) static checksum terminal_##x = ALLOW

replace a function with constant string argument with macro in C

In a project I work on we have some utility functions which taking 2 arguments,one is address to write and second is value to write.
Lets use a simple example:
enum {
ADDR1 = 0x1000,
ADDR2 = 0x1500,
....
};
void Hardware_write_reg(ADDR,val)
{
switch ADDR {
case ADDR1 : abc.x = val; break;
case ADDR2 : abc.f = val; break;
.....
.....
}
This function "Hardware_write_reg" are called in many number of times in many files throughout the project with different ADDR and values as arguments.
Now,I need to remove the calls to "Hardware_write_reg" and write directly to struct members.
An example,Function1() below need to be changed
Before change:
Function1()
{
Hardware_write_reg(ADDR1,val1);
Hardware_write_reg(ADDR2,val4);
Hardware_write_reg(ADDR7,val6);
.....
}`
After change:
Function1()
{
abc.x = val1;
abc.f = val4;
abc.s = val6;
.....
}
I cannot do it manually,because many numerous calls to Hardware_write_reg() in multiple files.
I tried with C Macro,like this;but could not get expected result
#define Hardware_write_reg(ADDR1,A) do{\
abc.x = ((A));\
}while(0)
#define Hardware_write_reg(ADDR2,B) do{\
abc.f = ((B));\
}while(0)
Basically,I want to replace (at compile time)
1) Hardware_write_reg(ADDR1,val1); function call to abc.x = val1; with a macro
2) Hardware_write_reg(ADDR2,val2); function call to abc.f = val2; with a macro
3)....
Any help from C-Guru's would be appreciated!
You could define a bunch of macros which does
#define target_ADDR1 abc.x
#define target_ADDR2 abc.f
#define CONCAT2(a, b) a##b
#define Hardware_write_reg(ADDR,val) CONCAT2(target_,ADDR) = val
so that
Hardware_write_reg(ADDR1,42);
is replaced by
target_ADDR1 = 42;
and thus
abc.x = 42;
is what you get.
Disclaimer: I haven't tested it, but I am quite sure this should work.
Instead of programatically solving this you can try regular expression replacement which included in most of the text editors today. but here the problem is for each case in switch you have to modify regex for a bit. And you should not have any other Hardware_write_reg in your code.
search
Hardware_write_reg(ADDR1,val([0-9]+));
replace with
abc.x = val\1;
Also if you have many cases you can generate regex and replacement with a small script.
The only thing I could imagine that works for this case is you put the assignment operations into a switch statement
#define Hardware_write_reg(ADDR,A) do{\
switch((ADDR)) { \
case ADDR1: abc.x = ((A));\
case ADDR2: abc.f = ((A));\
...
} \
} while(0)
As the C Macros cannot guess the values of ADDR during compile time and hence cannot put appropriate structure member for each ADDR.
As you want replace the function call with the actual assignment statement. So it seems like the only way you can do it is to Find/Replace in the code. For this you can write a regular expression and find a replace using that. For instance for ADDR1:
Find the Regular Expression:
(Hardware_write_reg)[(](ADDR1)[,]([\w]*)[)];
And Replace it with:
abc.x = $3;
The above regular expressions are compatible in eclipse

getting the variable values in #define definition

Here is what I am trying to do.
step1) I want to call a macro with a conditional statement(simple are compounded) like
for eg:
MACRO1(a==1)
MACRO1((i!=NULL) && (j>10))
step2) Here is how i am defining this macro
#define MACRO1(condition) \
if(!(condition)) ??????????????????????????
Here in the definition of the macro, if the condition statement fails. I want to print the variable values so that I will be useful to know the exact reason.
I used #condition in the definition, but it just printing the condition, instead of the values of the variables used in the condition. Please help.
You could do something along these lines:
#define MACRO1(condition, msg) \
if(!(condition)) { printf msg; }
and use it as follows:
MACRO1(a==1, ("a: %d\n", a))
MACRO1((i != NULL) && (j>10), ("i: %p, j: %d\n", i, j));
The C preprocessor is just a simple substitution engine, without the capability of analyzing the contents of expressions.
You shouldn't define macros that look like a function, but behave differently, in particular in your case may change control flow: an else that follows a macro that contains an if can apply to something different than the programmer (yourself after a week) thinks. Protect the if such that a dangling else will not apply to it
#define MACRO1(COND, ...) \
do { \
if (!(COND)) printf(stderr, "condition " #COND ": " __VA_ARGS_); \
} while (0)
This macro should always be called with a format string as second argument and the names of the variables that you want to see
MACRO1((toto != 78.0), "toto=%9\n", toto);
this should print you something like
condition (toto != 78.0): toto=3.14
There is no way that I know of to separate the variables from the condition.
However, you can pass them in as extra parameters:
#define MACRO(condition, printsyntax, ...) \
if(!(condition)) {\
printf("condition %s not met! (" printsyntax ")\n", #condition, __VA_ARGS__); \
};
You would use it as:
MACRO((i!=NULL) && (j>10), "i=%p, j=%d", i, j)
with an example result being:
condition (i!=NULL) && (j>10) not met! (i=(nil), j=11)
The compiler will splice together the constant strings into one string for the printf,
the condition will automatically be printed and the rest of the arguments are your job to get right.
Edit
After Jens' remark about the else I modified the code a bit to not allow for such structures without using do{}while();.

Preprocessor Directives to define function macros with multiple if/else if statements

I am using Preprocessor Directives to define function macros in C. Can I have multiple if/else if statements in a function macro?
If yes how do I write it?
#define WRITE(str,id) #str(id)
// HERES where I am having difficulty
#define DRAW_GENERIC_WINDOW(windowID, type) if type==1 WRITE(draw_text,windowID) else if type==2 WRITE(draw_image,windowID) else if type==3 WRITE(draw_hyperlink,windowID)
// usage
DRAW_GENERIC_WINDOW(112, 1);
DRAW_GENERIC_WINDOW(178, 2);
DRAW_GENERIC_WINDOW(988, 3);
// At compile time the above should be converted to...
draw_text(112);
draw_image(178);
draw_hyperlink(988);
I am aware how to perform a single if else statement in a Function Macro but not how to do it with multiple if/else if's:
// if else eg
#define DRAW_GENERIC_WINDOW(windowID, type) ((type)==(1))?WRITE(draw_text,windowID):WRITE(draw_image,windowID)
Note: Before you ask "Why the hell are you programming like this?" :P its because I am writting in a language that is very similar to C called 4dm, except there are no structs, pointers or the ability to declare new data types. So I am forced to resort to Preprocessor Directives in order to achieve some form of virtual functions(used when I dont know the type of window - image, hyperlink, etc. - that I am working with).
Try it out like this:
#define WRITE(str,id) str(id)
// HERES where I am having difficulty
#define DRAW_GENERIC_WINDOW(windowID, type) if (type==1) \
WRITE(draw_text,windowID) \
else if (type==2) \
WRITE(draw_image,windowID) \
else if (type==3) \
WRITE(draw_hyperlink,windowID)
// usage
DRAW_GENERIC_WINDOW(112, 1);
DRAW_GENERIC_WINDOW(178, 2);
DRAW_GENERIC_WINDOW(988, 3);
Just use the token pasting operator ## as basic pattern matching, like this:
#define DRAW_GENERIC_WINDOW(windowID, type) DRAW_GENERIC_WINDOW_ ## type(windowID)
#define DRAW_GENERIC_WINDOW_1 draw_text
#define DRAW_GENERIC_WINDOW_2 draw_image
#define DRAW_GENERIC_WINDOW_3 draw_hyperlink
Then use it like this:
DRAW_GENERIC_WINDOW(112, 1); // expands to draw_text(112, 1);
DRAW_GENERIC_WINDOW(178, 2); // expands to draw_image(178);
DRAW_GENERIC_WINDOW(988, 3); // expands to draw_hyperlink(988);

Variable no of argument in C Macro

I am writing some hardware specific code, where I want to use C Macros, the macro definition would be something like this:-
#define VALIDATE_RESOURCE_AND_ALLOCATE(MODE,RESOURCE1) if(a[MODE][RESOURCE1] != x1) || \
(a[MODE][RESOURCE1] != y1)) \
a[MODE][RESOURCE1]=x3;
Since sometimes I can have more then 1 resource to allocate, such as:-
#define VALIDATE_RESOURCE_AND_ALLOCATE_1(MODE,RESOURCE1,RESOURCE2) if(a[MODE][RESOURCE1] != x1) || \
(a[MODE][RESOURCE1] != y1)) \
a[MODE][RESOURCE1]=x3;
if(a[MODE][RESOURCE2] != x1) || \
(a[MODE][RESOURCE2] != y1)) \
a[MODE][RESOURCE2]=x3;
Is there any way I can write a macro, which covers both cases, as it takes variable number of arguments?
I have used variable number of arguments, in macro for printf macros, but then how I will address those arguments, by their respective name, for example, if I modify the MACRO definition such as:0-
#define VALIDA_RESOURCE_AND_ALLOCATE(MODE,.....)
How will I identify RESOURCE1, RESOURCE2?
Your macros have a lot of repeated code in them. Simplifying them helps make a solution more apparent:
#define VALIDATE_RESOURCE_AND_ALLOCATE_1(MODE,RESOURCE1,RESOURCE2) do {\
VALIDATE_RESOURCE_AND_ALLOCATE(MODE, RESOURCE1); \
VALIDATE_RESOURCE_AND_ALLOCATE(MODE, RESOURCE2); \
} while(0)
Here, it's clearer that this is simply a repeated invocation of the first macro while iterating through a list of arguments.
Assuming you know that the data types being used here will always be consistent, you can try something like this (untested and written off of the top of my head):
#ifdef HARDWARE_PLATFORM_A
static sometype args[] = {
RESOURCE1,
RESOURCE2,
/* ... etc, etc */
};
#elif defined HARDWARE_PLATFORM_B
static sometype args[] = {
RESOURCE10,
RESOURCE11,
/* ... etc, etc */
};
/* repeat for all hardware platforms */
#endif
void initialization_function (void) {
int i;
for (i = 0; i < (sizeof(args) / sizeof(args[0])); ++i) {
VALIDATE_RESOURCE_AND_ALLOCATE(MODE, args[i]);
}
}
where sometype is the data type of the arguments that you will be using for RESOURCE1, RESOURCE2, etc.
Given the complexity of what you are trying to do, you'd be a lot better off writing a function to do the iteration instead of a macro. You can still use a macro to create the RESOURCE list, but don't try to get the pre-processor to do the iteration for you. If you need to avoid the overhead of a function call (since you tagged this as 'embedded'), you can declare the functions inline and the result should be as efficient as using a macro. In the process, though, you'll gain things like type safety.
While it might be technically possible to do this with a macro, it would be a nasty hack that would most likely bring more problems than benefits. Doing complex procedural tasks with the pre-processor rarely turns out well.
The other alternative that you have is to use a code generator that takes a list of RESOURCE arguments from a file and generates a .c file containing the initialization code. The code generator would be written in a language much more powerful than the C pre-processor (almost any scripting language could be used here). This probably wouldn't be worth the trouble unless you had a long list of RESOURCEs, though.
One way you could accomplish it is don't pass in a variable number of arguments, but stick with two and make the second one be a list that can be used in an initialization. For example (trailing backslashes left off for clarity):
#define VALIDATE_RESOURCE_AND_ALLOCATE(MODE, LIST)
{
int resources[] = LIST;
int count;
for(count = 0; count < sizeof(resources)/sizeof(int); count++) {
/* do stuff here for each resources[count] */
}
}
And then you can simply call it as such:
VALIDATE_RESOURCE_AND_ALLOCATE(MODE, { RESOURCE1, RESOURCE2 } )
Note: there is more than one way to skin this cat, so pick your favorite answer and go with it :-)
Would this be too silly? ;-)
#define VALIDATE_RESOURCE_AND_ALLOCATE(MODE,RESOURCE1,RESOURCE2) \
if(a[MODE][RESOURCE1] != x1) || (a[MODE][RESOURCE1] != y1)) \
a[MODE][RESOURCE1]=x3; \
if((RESOURCE1 != RESOURCE2) && (a[MODE][RESOURCE2] != x1) || (a[MODE][RESOURCE2] != y1))) \
a[MODE][RESOURCE2]=x3;
and Call it as below for single resource
VALIDATE_RESOURCE_AND_ALLOCATE(M1,R1,R1)
and like below for two?
VALIDATE_RESOURCE_AND_ALLOCATE(M1,R1,R2)

Resources