| 9.3.2 `sic_syntax.c' The syntax of the commands in the shell I am writing is defined by a set of syntax handlers which are loaded into `libsic' at startup. I can get the C preprocessor to do most of the repetitive code for me, and just fill in the function bodies: | #if HAVE_CONFIG_H # include <sic/config.h> #endif #include "sic.h" /* List of builtin syntax. */ #define syntax_functions \ SYNTAX(escape, "\") \ SYNTAX(space, " \f\n\r\t\v") \ SYNTAX(comment, "#") \ SYNTAX(string, "\"") \ SYNTAX(endcmd, ";") \ SYNTAX(endstr, "") /* Prototype Generator. */ #define SIC_SYNTAX(name) \ int name (Sic *sic, BufferIn *in, BufferOut *out) #define SYNTAX(name, string) \ extern SIC_SYNTAX (CONC (syntax_, name)); syntax_functions #undef SYNTAX /* Syntax handler mappings. */ Syntax syntax_table[] = { #define SYNTAX(name, string) \ { CONC (syntax_, name), string }, syntax_functions #undef SYNTAX { NULL, NULL } }; | This code writes the prototypes for the syntax handler functions, and creates a table which associates each with one or more characters that might occur in the input stream. The advantage of writing the code this way is that when I want to add a new syntax handler later, it is a simple matter of adding a new row to the syntax_functions macro, and writing the function itself. |