4

Don't do C++ so this might be a silly question. I'm examining a header file .h where parameter IDs are supposedly defined, according to the documentation. I've come across the lines where the parameters are and they are as follows:

#define  SPCDLL_ERROR_KEYWORDS \
{ \
  keyword (NONE), \
  keyword (OPEN_FILE), \
  keyword (FILE_NVALID), \
  keyword (MEM_ALLOC), \
};

#define  PARAMETERS_KEYWORDS \
{ \
  keyword (LIMIT_LOW), \
  keyword (LIMIT_HIGH), \
  keyword (LEVEL), \
  keyword (HOLDOFF), \
};

#ifdef keyword
#undef keyword  /* prevents redefinition warning */
#endif

#define keyword(key) key

However I have searched and can't find out exactly what the keyword(key) line is doing? Is it assigning each parameter and ID based on it's order in the list? Would that make LIMIT_LOW, ID=1? Why is it not explicitly defined. Also as there are two lists of definitions of keyword how does it work?

I come from Python land where I would have defined these as two dictionaries with IDs and values for both Error_names and Parameter_vals.

If someone could explain this I would be grateful.

HolyBlackCat
  • 45,832
  • 5
  • 81
  • 134
BloodSexMagik
  • 326
  • 3
  • 10
  • 2
    That's a user-defined type – stark Mar 31 '20 at 11:14
  • That looks like an [X macro](https://stackoverflow.com/questions/6635851/real-world-use-of-x-macros). It could be used to create an enum and a corresponding array of strings from the same data, for example. (If that's true, there should be another undef and a redefinition of `keyword` later.) – M Oehm Mar 31 '20 at 11:15

2 Answers2

4

#define means you are making a macro. keyword(key) means you are making a function in that macro, which takes a parameter, key. The last key means you are taking that key parameter, and then you are doing something with it. It can be anything, you can std::cout it, or really anything else.


When you are calling that macro, you pass in the macro keyword and you put in anything for key.

You use X macros in the top of your file, and you have your keyword macro in those functions.

appledoes
  • 113
  • 9
  • Hi, This makes a lot of sense... thanks! I've found the line further down: `enum parameters_enum PARAMETER_KEYWORDS` - so thinking about that then it seems they are just enumerating through the keywords and assigning each a number (starting from 0) as an ID. Coming from py this seems a really roundbaout way to do things? Why would you not just have a single line: `enum parameters_enum {LIST OF PARAMS}` ? – BloodSexMagik Mar 31 '20 at 13:08
0

Note that the lines

keyword (SOME_CONSTANT), \

are all part of a macro. That is, they will appear wherever the macros SPCDLL_ERROR_KEYWORDS and PARAMETERS_KEYWORDS get expanded.

And, wherever that expansion takes place, it will use the keyword() definition in the last line of your code snippet. So, the expression PARAMETERS_KEYWORDS will actually expand to

{
    LIMIT_LOW,
    LIMIT_HIGH,
    LEVEL,
    HOLDOFF,
};

However, it depends on how keyword() is actually defined at the point of use, it could be defined to expand to anything that the C preprocessor is capable of producing. For instance

#define keyword(foo) 1
char foo[] = SPCDLL_ERROR_KEYWORDS;
printf("There are %d SPCDLL_ERROR keywords\n", sizeof(foo));

would produce the actual count of keyword() invocations within SPCDLL_ERROR_KEYWORDS.

I have no clue in which context these macros are actually used/useful, but such constructions typically serve some specific purpose: The effect of keyword(FOO) is basically the same as FOO by itself, but it marks the use of FOO for other uses. Such other uses can be in some other macros, or other tools that are used to process the source code. Like documentation tools, linters, automatic header generation scripts, and so on, and so forth.

The only way to find out is actually grepping for where the expression \<keyword\> is used throughout the code base. Most likely, this will let you stumble across comments that provide hints, and/or some script that actually does the additional processing.

cmaster - reinstate monica
  • 33,875
  • 7
  • 50
  • 100