This is the c pre-processor but with '#' directives changed to '$' directives, for use with the C code generated by my imp to c source-to-source translator. For now, invoke as: ./mcpp -N -k -C -I- -P testarray.c It is primarily here to convert fred[3][4] into fred[(3)-fredbase1][(4)-fredbase2] etc. and to insert array bound checks where possible. For now I am also using this preprocessor (rather than the real cpp) to convert "unless (cond)" into "if (!cond)" and "until (cond)" into "while (!cond)". However eventually those should be handled by DeMorgan's rule in the imp to c translator. #include statements (or indeed any other '#' directives) are passed through, but maybe not verbatim - they can still be expanded if they contain any '$' macros. This is important for the correct handling of #line in input files. Note that the builtin __LINE__ and __FILE__ can be suppressed, to ensure that they are replaced at the appropriate stage in the source generation sequence. Actually on my system I built two versions - one where __FILE__ was not expanded and one where it was treated normally. I don't believe I added those options to the Makefile - I think I just handled them manually when I built my own binaries. Likewise as to whether the Makefile generates a binary called "mcpp" or "gtcpp" - I'm pretty sure I just renamed the files after they were built with the defaults. I don't *think* there is anything else in a C-like source file which would trigger action by this preprocessor but I can't swear to it. Some care still needs to be taken. Note that macro calls using () brackets still work, in addition to the new feature of using [] brackets. And macname[a][b] is equivalent to macname[a, b] which is useful for handling multi-dimensional array accesses, but might cause surprises if you use comma expressions in an array index. (You would never do that, right?) I'm afraid that the facility to allow multi-dimensional arrays was added as a rather crude hack that basically just treats the string "][" as being equivalent to a comma. I would recommend checking that comments are not being removed unexpectedly if your application is something that handles C source files and which relies on the comments being present. The "-k" flag is to stop white space being removed. Here's a relatively trivial example of using gtcpp in a program to check array bounds: /* --- support code for optional array-bounds checks --- */ #ifdef ARRAY_BOUNDS static int rangecheck_inner(char *var, unsigned int idx, unsigned int lower, unsigned int upper, int line) { // inclusive bounds if (idx < lower || idx > upper) { fprintf(stderr, "Error: index of %s (%d) is not in the range %d:%d at line %d\n", var, idx, lower, upper, line); exit(EXIT_FAILURE); } return idx; } #define rangecheck(var, idx, low, high) rangecheck_inner(var, idx, low, high, __LINE__) // This debugging feature needs to use my modified 'gtcpp' pre-processor, // rather than normal macros, because I need to intercept array accesses like this[example]. $define m->vertex[x] m->vertex[rangecheck("m->vertex[" #x "]", x, 0, m->max_points)] $define m->edge[x] m->edge[rangecheck("m->edge[" #x "]", x, 0, m->max_edges)] $define node[x] node[rangecheck("node[" #x "]", x, 0, m->max_points)] $define face[x] face[rangecheck("face[" #x "]", x, 0, m->max_faces)] $define From_queue[x] From_queue[rangecheck("From_queue[" #x "]", x, 0, m->max_queue)] $define To_queue[x] To_queue[rangecheck("To_queue[" #x "]", x, 0, m->max_queue)] $define Depth_queue[x] Depth_queue[rangecheck("Depth_queue[" #x "]", x, 0, m->max_queue)] $define From_static[x] From_static[rangecheck("From_static[" #x "]", x, 0, m->max_queue)] $define queued_edge[x] queued_edge[rangecheck("queued_edge[" #x "]", x, 0, m->max_queue)] $define reached_vertex[x] reached_vertex[rangecheck("reached_vertex[" #x "]", x, 0, m->max_points)] $define loop[x] loop[rangecheck("loop[" #x "]", x, 0, m->max_points)] #else #define rangecheck(var, idx, low, high) (idx) #endif // ARRAY_BOUNDS /* --- end array bounds checking --- */ It can be used in more complex ways, especially when using flexible arrays (i.e. arrays whose upper and lower bounds can expand and contract at runtime).