Fun with Macros and Preprocessors

Hi all! Today I am going to describe some interesting things associated with Macros and Preprocessor. But, first of all let us understand the definition of a C preprocessor.

A C preprocessor is a macro preprocessor for C language. It provides the ability for the inclusion of header files, macro expansions, conditional compilation and line control. You must have definitely seen its most common usage which is inclusion of headers. Each time you write “#include <stdio.h>” in you C code, the preprocessor replaces it with the text of the file ‘stdio.h’ (The printf which we commonly use is defined in this file).

In Kernel codes, you will frequently find the occurrences of code pieces shown below:

#ifdef <condition-1>
#elif defined <condition-2>

This implies that if the condition-1 is satisfied the “header_inclusion” is included else if condition-2 is satisfied then “Other_header_inclusion” is included.

There are various other instances of macro expansion seen in Kernel. I was recently working on drivers/scsi/ directory for fixing missing prototype warning where I noticed a particular set of warning in file drivers/scsi/be2iscsi/be_main.c.

drivers/scsi/be2iscsi/be_main.c:153:1: warning: no previous prototype for beiscsi_log_enable_disp’ [-Wmissing-prototypes]
drivers/scsi/be2iscsi/be_main.c:153:1: warning: no previous prototype for beiscsi_log_enable_change’ [-Wmissing-prototypes]
drivers/scsi/be2iscsi/be_main.c:153:1: warning: no previous prototype for beiscsi_log_enable_store’ [-Wmissing-prototypes]
drivers/scsi/be2iscsi/be_main.c:153:1: warning: no previous prototype for beiscsi_log_enable_init’ [-Wmissing-prototypes]

The interesting part of these warnings is that when you git grep any of the above symbols, you do not see any usage of these symbols in kernel. (I was intrigued why the file is complaining about a symbol which is not present in it 😛 )
However, when you dig the code a little bit more, you realize that these symbols are defined in the file but are hidden under macros.

For instance: beiscsi_disp_param in the file defines functions named beiscsi_*_disp. Then BEISCSI_RW_ATTR calls that. So, basically BEISCSI_RW_ATTR(log_enable, …) creates all those functions.
And hence the fix to solve all these warnings was to add “static” keyword to the various macros that are defining functions in that file. (Interesting isn’t it :D)

I hope it was fun reading about the preprocessor. Will keep you posted about more such intriguing things …Bye :)