Hi folks,

Test.Assert hasn't worked for years in CIQ, which is a bit
frustrating. And it appears to be almost impossible to add debugging
System.println messages that can be easily removed (without leaving
traces such as unused string objects) in the release code (note added
later: Prettier Monkey C can do this). So, I've made an initial stab
at adding support for using a C preprocessor, which gives you
conditional compilation, macros, include files, etc.

The following was tested using Linux.

The basic idea is to create a folder named after your favorite editor
(emacs in my case) in the top level directory of your app (where bin,
docs, resources, source are). Copy the Monkey C files from the source
folder to the new folder. Rename them all from *.mc to *.c.  Add the
files to the git repository for your App. Then put the following bash
script in the folder, call it process.sh:

#!/bin/bash
#
# Run the C preprocessor on all *.c files in the current directory. We also
# comment out the lines starting with # added by the preprocessor, and try to
# maintain alignment with line numbering.
#
# Michael Ashley / m.ashley@unsw.edu.au / 27-Jan-2025

for f in *.c; do
     echo processing $f
     gcc -E -CC $f | sed -n "/^\/\//,\${/^#.*$f/d;s/^#/\/\/#/;p}" > ../source/${f%.c}.mc
     # gcc
     #   -E             run the preprocessor only
     #   -CC            leave the comments in
     # sed -n
     #   /^\/\//,\$     from the first line starting with // to the end of the file
     #   /^\#.*$f/d     delete lines starting with # and containing the filename
     #   s/^\#/\/\/\#/  comment out any lines starting with #
     #   p              print the line
done

Add a comment to the top of each *.c file beginning with //. This is
so that the above script can identify the start of the source file
from the output of gcc -E -CC.

If using emacs, you can use this as the first line of each C file:

// -*- after-save-hook: (closure (t) nil (start-process "p" nil (concat (getenv "PWD") "/process.sh"))); c-basic-offset: 4; -*-

this sets up a hook that will automatically generate Monkey C files
in the sources folder whenever a C file is saved.

I use an include file to define a debugging macro and a simple assert macro:

#define DEBUG
#define ABSORB_SEMICOLON do {} while (false)    // {} works for Monkey C, but not for Prettier Monkey C
#ifdef DEBUG
    #define INFO(message) System.println(message); ABSORB_SEMICOLON
    #define ASSERT(thing)  if (! (thing)) {throw new Test.AssertException(#thing);} ABSORB_SEMICOLON
#else 
    #define INFO(message) ABSORB_SEMICOLON
    #define ASSERT(thing) ABSORB_SEMICOLON
#endif

You include this using the usual #include "file.h".

With these simple additions you have the full power of C macros, and
assert. You do all your editing with your favorite editor, and the
changes appear automatically in VS Code if you use that (just don't
edit the files in VS Code, since that will take precedence over files
that later overwrite those on disk).