replace a function with constant string argument with macro in C - 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

Related

Could I use preprocessor to make this one clearer?

I was writing a little source file function for my Pic32 and I got stucked on one thing.
It's basically an utility that should store incomming char data into buffer and then, if '\r' is recieved, it compares the buffer against list of commands (in array names), and if match is found, the index of the item is returned.
This part is from header:
#define NAMECNT 6
static const char names[NAMESCNT][10] = { // 6commands, max 10 char each
"korr", // 1
"adc", // 2
"fft", // 3
"data", // 4
"pr", // 5
"prsc"}; // 6
/* functions */
extern int comm(char cdata);
At the main file, there is one big switch:
switch( comm(recieved_ch) ){
case 1: foo1(); break;
case 2: foo2(); break;
...
}
Now, for the better clarity, I wanted to use instead of 1, 2, ... the original names (like case KORR: case ADC:) so I wrote deffinitions for each one of them
#define KORR 1
#define ADC 2
But I don't like that solution, because I want to use this source file in more projects and there is gonna be different list of commands for each. Is there any way how to do this?
Best thing would be to create the array names in preprocessor, but I doubt that's even possible. I was thinking about using enum type (which would have same items as list of commands names), but I am not sure how would that go.
You can use X-macros to build an enum and fill the array, then you can use the enum values in the switch:
#define VARS \
X(korr) \
X(adc) \
X(fft) \
X(data) \
X(pr) \
X(prsc)
static const char names[][10] = { // 6commands, max 10 char each
#define X(name) #name,
VARS
#undef X
};
enum evars {
#define X(name) name,
VARS
#undef X
};
extern int comm(char cdata);
int main(void)
{
char x = 1;
switch (comm(x)) {
case korr:
printf("korr");
break;
case adc:
printf("adc");
break;
/* ... and so on */
}
return 0;
}
The expansion of X is:
static const char names[][10] = {
"korr", "adc", "fft", "data", "pr", "prsc",
};
enum evars {
korr, adc, fft, data, pr, prsc,
};
Edit: As pointed out by #5gon12eder, you don't need to hardcode 6 in the first dimension of the array (you can leave it unspecified).
The preprocessor could make things clearer here, I think, using the concatentation operator ##, but it'll not yield a performance advantage. A switch statement could be optimized by the compiler, but that's implementation-dependent.
Instead of the "one big switch," use an array of function pointers. Something like
func_ptrs[comm(received_ch) - 1]();
will call the corresponding function, where foo1 is at index 0, foo2 at 1, etc. To add a command, simply append a command name to the command list and a function pointer func_ptrs.
After all, you kill two birds with one stone: you create an easy way to add commands and improve performance.
Besides, a linear search through an array of strings is pretty inefficient. A hash table would yield a performance advantage.

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

Is it OK to use a code block as an argument for a C macro?

I have a pattern that is basically some boilerplate code with a part that varies in the middle
if(condition){
struct Foo m = start_stuff();
{ m.foo = bar(1,2); m.baz = 17; } //this part varies
end_stuff();
}
Is it OK to make a macro taht takes that intermediate code block as an argument? The rules for macro expansion in C seem awfully complicated so I am not sure if there aren't any corner cases that could come and bite me in the future (in particular, I don't understand how the macro arguments are separated if my code has commas in it).
#define MY_MACRO(typ, do_stuff) do { \
if(condition){ \
struct typ m = start_stuff(); \
do_stuff; \
end_stuff(); \
} \
}while(0)
//usage
MY_MACRO(Foo, {
m.foo = bar(1,2);
m.baz = 17;
});
So far the only thing that I managed to think of is break and continue getting captured if I use looping statements in my macro and that would be an acceptable tradeoff for my particular use case.
edit: Of course, I would have used a functions if I could. The example I used in this question is simplified and doesn't showcase the bits that can only work with macro magic.
You can put a code block into a macro argument provided that it has no unguarded comma. In your example, the only comma in the argument is guarded because it is surrounded by parentheses.
Note that only parentheses guard commas. Brackets ([]) and braces ({}) do not. (And neither do angle brackets (<>) as noted in a comment.)
However, if the code block argument is the macro's last argument, you can use a variadic macro to increase flexibility. But beware: the increased flexibility also means that errors might go unnoticed. If you do this, you'll only have to make sure that the parentheses are balanced. (Again, only parentheses matter to the macro processor.)
As an alternative, you could consider using a macro that precedes your compound statement, as illustrated below. One of the pros of this is that all debuggers would still be able to step inside your compound statement, which is not the case with the compound-statement-as-macro-argument method.
//usage
MY_MACRO(Foo, condition) {
m.foo = bar(1,2);
m.baz = 17;
}
Using some goto magic (yes, 'goto' may be evil in some cases, but we have few alternatives in C), the macro can be implemented as:
#define CAT(prefix, suffix) prefix ## suffix
#define _UNIQUE_LABEL(prefix, suffix) CAT(prefix, suffix)
#define UNIQUE_LABEL(prefix) _UNIQUE_LABEL(prefix, __LINE__)
#define MY_MACRO(typ, condition) if (condition) { \
struct typ m = start_stuff(); goto UNIQUE_LABEL(enter);} \
if (condition) while(1) if (1) {end_stuff(); break;} \
else UNIQUE_LABEL(enter):
Note that this has a small performance and footprint impact when compiler optimization is disabled. Also, a debugger will seem jump back to the MY_MACRO line when running calling the end_stuff() function, which is not really desirable.
Also, you might want to use the macro inside a new block scope to avoid pollution your scope with the 'm' variable:
{MY_MACRO(Foo, condition) {
m.foo = bar(1,2);
m.baz = 17;
}}
Of course, using 'break' not inside a nested loop in the compound statement would skip the 'end_stuff()'. To allow for those to break the surrounding loop and still call 'end_stuff()', I think you'd have to enclose the compound statement with a start token and an end token as in:
#define MY_MACRO_START(typ, condition) if (condition) { \
struct typ m = start_stuff(); do {
#define MY_MACRO_EXIT goto UNIQUE_LABEL(done);} while (0); \
end_stuff(); break; \
UNIQUE_LABEL(done): end_stuff();}
MY_MACRO_START(foo, condition) {
m.foo = bar(1,2);
m.baz = 17;
} MY_MACRO_END
Note that because of the 'break' in that approach, the MY_MACRO_EXIT macro would only be usable inside a loop or switch. You could use a simpler implementation when not inside a loop:
#define MY_MACRO_EXIT_NOLOOP } while (0); end_stuff();}
I used 'condition' as a macro argument, but you may also embed it directly in the macro if desired.
You can put code block into a macro but you must be warned that it makes debugging a lot harder using a debugger. IMHO is better just to either write a function or cut'n'paste the lines of code.
How about function pointers instead (and optionally inline functions)?
void do_stuff_inner_alpha(struct Foo *m)
{
m->foo = bar(1,2); m->baz = 17;
}
void do_stuff_inner_beta(struct Foo *m)
{
m->foo = bar(9, 13); m->baz = 445;
}
typedef void(*specific_modifier_t)(struct Foo *);
void do_stuff(specific_modifier_t func)
{
if (condition){
struct Foo m = start_stuff();
func(&m); //this part varies
end_stuff();
}
}
int main(int argc, const char *argv[])
{
do_stuff(do_stuff_inner_beta);
return EXIT_SUCCESS;
}
"Is it OK?" may mean two things:
Will it work? Here the answer is generally yes, but there are pitfalls. One, as rici mentioned, is an unguarded comma. Basically, remember that macro expansion is a copy&paste operation, and the preprocessor doesn't understand the code it copies and pastes.
Is it a good idea? I'd say the answer is generally no. It makes your code unreadable and hard to maintain. In some rare cases, this may be better than alternatives, if implemented well, but that's the exception.
Note that in C++ you could use a lambda the following way:
#include <iostream>
#define MY_MACRO(body) \
setup();\
body();\
teardown();\
int main() {
int a = 1;
MY_MACRO(([&]() mutable {
std::cout << "Look, no setup" << std::endl;
a++;
}));
std::cout << "a is now " << a << std::endl;
}
If you do this, you should first consider if there should instead be a function that plainly takes the lambda:
void withSetup(std::function<void ()> callback) {
setup();
callback();
teardown();
}
int main() {
withSetup([&]() {
doStuff();
});
}
Before answering your question "is it OK to use macro" I'd like to know why you want to convert that block of code to macro. What's that you're trying to gain and at what cost?
If same block of code you're using repeatedly, it's better to convert that in a function, maybe an inline function and leave it to compiler to make it inline or not.
Should you run into crash\issue, debugging a macro is a tedious task.

Force function to accept specific definitions only?

I would like to force a functions parameters to accept only specific definitions. For example, consider #define OUTPUT 1, #define INPUT 0 and void restrictedFunction(int parameter); .
How would I force restrictedFunction(int parameter) to accept only OUTPUT or INPUT?
I would also like to take into consideration that another definition may have the same value, for example, #define LEFT 1 and #define RIGHT 0.
So in this case I would like restrictedFunction(int parameter) to be able to accept only OUTPUT and INPUT specifically.
typedef enum { INPUT = 0, OUTPUT = 1 } IO_Type;
void restrictedFunction(IO_Type parameter) { ... }
It doesn't absolutely force the use of the values (the compiler will let someone write restrictedFunction(4)), but it is about as good as you'll get.
If you truly want to force the correct type, then:
typedef enum { INPUT = 0, OUTPUT = 1 } IO_Type;
typedef struct { IO_Type io_type } IO_Param;
void restrictedFunction(IO_Param parameter) { ... }
In C99 or later, you could call that with:
restrictedFunction((IO_Param){ INPUT });
This is a compound literal, creating a structure on the fly. It is not entirely clear that the structure type really buys you very much, but it will force the users to think a little and may improve the diagnostics from the compiler when they use it wrong (but they can probably use restrictedFunction((IO_Param){ 4 }); still).
What this means is that your restrictedFunction() code should be ready to validate the argument:
void restrictedFunction(IO_Type io_type)
{
switch (io_type)
{
case INPUT:
...do input handling...
break;
case OUTPUT:
...do output handling...
break;
default:
assert(io_type != INPUT && io_type != OUTPUT);
...or other error handling...
break;
}
}
You could use an enum.
typedef enum TrafficDirection { INPUT = 0, OUTPUT = 1 } TrafficDirection;
restrictedFunction(TrafficDirection direction);
of course, this isn't perfect. You can still pass any int to it as long as you use a cast.
restrictedFunction((TrafficDirection) 4);
You don't get quite as much protection as you might like, but you can do:
enum func_type { INPUT, OUTPUT };
void restrictedFunction( enum func_type parameter );
You can use a wrapper to validate the argument:
#define restrictedFunction(x) do { \
static_assert((x) == INPUT || (x) == OUTPUT); \
assert(!strcmp(#x, "INPUT") || !strcmp(#x, "OUTPUT")); \
restrictedFunction(x); \
} while(0)
Notes:
This assumes restrictedFunction() returns a void. If it returns a value which you actually use, you'll need something like gcc's compound statement http://gcc.gnu.org/onlinedocs/gcc/Statement-Exprs.html. Or--better--you can use BUILD_BUG_ON_ZERO (see What is ":-!!" in C code?), which I keep forgetting about, because it doesn't seem to work with C++.
The do ... while(0) is to "swallow the semi-colon"; not really relevant here.
static_assert() is a compile-time assert; there are many variants available. Here is a link to one, https://stackoverflow.com/a/9059896/318716, if you don't have your own handy.
assert() is the standard run-time assert.
With gcc 4.1.2, and my version of static_assert(), you can replace the run-time assert() with a compile-time assert when the two !strcmp()'s are replaced with ==; see example below. I haven't tested this with other compilers.
x is only used once in the macro expansion, since the first four references are only used at compile-time.
When your actually define your function, you'll have to add parentheses to disable the macro expansion, as in:
void (restrictedFunction)(int x){ ... }
Also, if your code has a special case (whose code doesn't?) where you need to call restrictedFunction() with the argument foo, you'll need to write:
(restrictedFunction)(foo);
Here is a complete example, which puts a wrapper around the standard library function exit():
#include <stdlib.h>
#define CONCAT_TOKENS(a, b) a ## b
#define EXPAND_THEN_CONCAT(a,b) CONCAT_TOKENS(a, b)
#define ASSERT(e) enum{EXPAND_THEN_CONCAT(ASSERT_line_,__LINE__) = 1/!!(e)}
#define ASSERTM(e,m) enum{EXPAND_THEN_CONCAT(m##_ASSERT_line_,__LINE__)=1/!!(e)}
#define exit(x) do { \
ASSERTM((x) == EXIT_SUCCESS || (x) == EXIT_FAILURE, value); \
ASSERTM(#x == "EXIT_SUCCESS" || #x == "EXIT_FAILURE", symbol); \
exit(x); \
} while(0)
int main(void) {
exit(EXIT_SUCCESS); // good
exit(EXIT_FAILURE); // good
exit(0); // bad
exit(3); // doubly bad
}
If I try to compile it, I get:
gcc foo.c -o foo
foo.c: In function 'main':
foo.c:17: error: enumerator value for 'symbol_ASSERT_line_17' is not an integer constant
foo.c:18: warning: division by zero
foo.c:18: error: enumerator value for 'value_ASSERT_line_18' is not an integer constant
foo.c:18: error: enumerator value for 'symbol_ASSERT_line_18' is not an integer constant

Portable instrumentation

GCC has a nice feature about instrumentation which let you call a routine every time a function is called, or every time a function returns.
Now, I want to create my own system to make it portable to other compilers, and also to allow to instrumentalize the functions I want (which can vary in number of parameters), so I was thinking in two macro for both situations. I am thinking in making some kind of profile that it is activated only with a define clause.
#define FUNCT(t,function_name,...) \
(t) function_name(...) { \
(void) *func_pointer = &(function_name); \
start_data(func_pointer, myclock());
#define RETURN(x) {stop_data(func_pointer, myclock()); return (x);}
FUNCT(BOOL, LMP, const int prof, const int nmo))
if (nmo <= 5 ||
prof > (prof_l / 3)) {
.... do long operations....
RETURN(FALSE);
}
... do more....
RETURN(TRUE);
}
but I can’t get it to work. Can someone help me with this? or is this a difficult task to accomplish?
Other alternative that comes to my mind is let the function declare without a macro, and if it is anyway to know the function pointer without knowing its name, something like in VB when you call a Form with Me, with it is a generic alias. is it possible?
Use gcc -E to debug your macros. Using the code you posted:
$ gcc -E t.c
# ... skip stuff ....
(BOOL) LMP(...) { (void) *func_pointer = &(LMP);
start_data(func_pointer, myclock());)
if (nmo <= 5 ||
prof > (prof_l / 3)) {
.... do long operations....
{stop_data(func_pointer, myclock()); return (FALSE);};
}
... do more....
{stop_data(func_pointer, myclock()); return (TRUE);};
}
(I added some whitespace to make it readable.)
You can see two problems immediately: function arguments didn't get expanded as you thought they would, and there's an extra ) from somewhere.
To get the expanded variadic arguments, use __VA_ARGS__, not .... The stray ) is at the call site.
So:
#define FUNCT(t,function_name,...) \
(t) function_name(__VA_ARGS__) { \
(void) *func_pointer = &(function_name); \
start_data(func_pointer, myclock());
#define RETURN(x) {stop_data(func_pointer, myclock()); return (x);}
FUNCT(BOOL, LMP, const int prof, const int nmo)
if (nmo <= 5 ||
prof > (prof_l / 3)) {
.... do long operations....
RETURN(FALSE);
}
... do more....
RETURN(TRUE);
}
As to whether this is worth trying (variadic macros came with C99, not all compilers implement that standard, and support might vary from compiler to compiler), I'm not certain. You are probably better off using each compiler's native profiling tools - you'll get better results with hopefully less overhead.
It is much easier to instrument your functions at the calling side instead of the function side. A macro can have the same name as a function. Declare your replacement function somewhere
double myfunc_wrapper(int someArg) {
double ret = 0;
// do something before
...
// now call it
ret = (myfunc)(someArg);
// Then do something after
....
return ret;
}
Just to be sure put the () arround the call itself to be sure that always a function is called and not a macro.
And then "overload" your function with a macro
#define myfunc(...) mfunc_wrapper(__VA_ARGS__)
with that idea you can replace your function on the fly in the compilation units that interes you.
in addition to Mat, there is a ergonimical problem with using #define RETURN(x) {...}:
if (test)
RETURN (TRUE);
else
RETURN (FALSE);
will evaluate to
if (test)
{...}
; // <syntactical error
else
{...}
;

Resources