Contents | < Browse | Browse >
17L. EC PreProcessor
--------------------

EC has an internal preprocessor which features macro substitution and
conditional compilation. These are not features of the E language,
rather it has been integrated with EC for speed and flexibility.

Activating the preprocessor.
Until you type:

	OPT PREPROCESS

EC will behave as normal. This OPT is necessary for any preprocessor
related feature.

Macros.
The macropreprocessor is mostly compatible with Mac2E and the C language PP
(see

You can define macros as follows:

	#define MACRONAME
	#define MACRONAME BODY
	#define MACRONAME(ARG,...) BODY
	#define MACRONAME(ARG,...) BODY \
	  REST OF BODY

MACRONAME and ARG may be ANY case, and may contain "_" and 0-9 as usual.
Whitespace may be added everywhere, except between MACRONAME and "(", because
otherwise EC can't see the difference between arguments and a body.  The BODY
may contain occurances of the ARGs.  A macro may continue on the next line by
preceding the end_of_line with a "\".  A body should not extend over more than
one statement. (a macroname with no body is useful in combination with
conditional compilation).

Macro identifiers have precedence over other identifiers.

Macro definitions defined in a module will be saved in the module only if
OPT EXPORT is on (#define can't be preceded with EXPORT). If that's a problem,
keep macros together in their own modules. Macros in modules can be used in
other code simply by importing them with MODULE and OPT PREPROCESS.


Using a macro.
Using MACRONAME anywhere in the program will insert the body of the macro
at that spot. Note that this substitution is text substitution, and has
little to do with actual E syntax. If the macros have arguments they will
be inserted at their respective places in the macrobody. If the body (or
the arguments) contain futher macros, these will be expanded after that.

example:

	#define MAX(x,y) (IF x>y THEN x ELSE y)

	WriteF('biggest = \d\n',MAX(10,a))

will equal writing:

	WriteF('biggest = \d\n',(IF 10>a THEN 10 ELSE a))

This immediately shows a danger of macros: since it simply copies
textually, writing MAX(large_computation(),1) will generate code
that executes large_computation() twice. Be aware of this.


Differences of the E PP from the C PP and Mac2E
* it doesn't support 0-arg macros, i.e. MACRONAME()
* comments part of a macro definition are not removed
* macro arguments in string constants are replaced as well. This
  can actually be quite handy, to write macros such as:
  #define debug(x) (WriteF('now evaluating: x\n') BUT x)


Conditional compilation.
This can be useful if you wish to decide at compile time which part of
your code to use. syntax:

	#ifdef MACRONAME

or

	#ifndef MACRONAME

the piece of source following this will or won't be compiled depending on
whether MACRONAME was defined. you can simply do this with:

	#define MYFLAG

or somesuch. End a conditionally compiled block with:

	#endif

Blocks like these may be nested. example:

#define DEBUG
->#define HEAVYDEBUG

#ifdef DEBUG
  WriteF('now entering bla() with x = \d\n',x)
#ifdef HEAVYDEBUG
  WriteF('now dumping memory...\n')
  /* ... */
#endif
#endif