I am working with a simple command line application that takes in ASCI text and interprets it as a command.
I have attempted to minimize the redundancy in this application via the example at http://gcc.gnu.org/onlinedocs/cpp/Concatenation.html.
eg:
Consider a C program that interprets named commands. There probably needs to be a table of commands, perhaps an array of structures declared as follows:
struct command
{
char *name;
void (*function) (void);
};
struct command commands[] =
{
{ "quit", quit_command },
{ "help", help_command },
...
};
It would be cleaner not to have to give each command name twice, once in the string constant and once in the function name. A macro which takes the name of a command as an argument can make this unnecessary. The string constant can be created with stringification, and the function name by concatenating the argument with `_command’. Here is how it is done:
#define COMMAND(NAME) { #NAME, NAME ## _command }
struct command commands[] =
{
COMMAND (quit),
COMMAND (help),
...
};
Now, let’s say that I want to have a command string and index (ie: int) value, rather than a string and function pointer.
struct command
{
char *name;
int command_idx;
};
Now, I have a means to name commands, and have some sort of index I can use later on to identify each command programatically. For example, I have a switch statement that operates on the command index. If I want to work on these indexes, I have to manually set the values first.
I can manually create an enumerated data type, but then I have define the enumerated constants in a separate enum statement. IE:
enum commands { cmd_quit = 0, cmd_help }
and in the end, I still end up having to type each command name twice: once via the COMMAND() macro, and again in my enum.
Is there any method using the C preprocessor that would allow me to create a macro creates the “command” struct (with string and int members), and auto-numbers the int value (command_idx) as I add more commands via the COMMAND() macro?
I am also aware that I can just use strcmp() calls on each possible command, and compare to the input provided by the user, but I would like to have a direct means of indexing into commands via the command_idx value, as opposed to strcmp’ing against a massive list of commands each time (ie: O(1) instead of O(n) ). I also want to avoid having to type the command name more than once at all costs.
Thanks!
You can use macro redefinition to achieve this. First, you create a file that simply lists your commands called
commands.inc:Then, in your C source you can
#include "commands.inc"multiple times, with different definitions ofCOMMAND()in effect to control how it works. For example:(Note that this particular example relies on a C99 improvement that allows a trailing
,at the end of the lists in theenumdeclaration and compound initialiser – you can easily work around that in C89 by adding a dummy entry at the end).