Here we'll look in detail at the marco capabilities and syntax of javapp.
First and foremost note that while javapp uses a very C-preprocesor-like syntax, it is not the same thing. I don't think anyone familiar with C's preprocessor will find the differences a problem ( indeed I hope they'll like them ), but be aware that there are subtle differences - good engineers read the manual first, but all engineers end up reading it eventually !
Note that when you process multiple files with one command the macros accumulate.
When javapp identifies a macro to replace, it does not simply replace that macro. It will also process the replaced text, replacing any macros it finds ( or defining new macros if that's what those new lines do ). You need to be aware that this does mean you could potentially loop endlessly if your macros directly or indirectly outputs a copy of itself.
Note that macros can be redefined. Unlike the C preprocessor, which will regard a redefinition as an error, javapp regards it as a deliberate choice.
There are some predefiend macros for convenience.
Macro directives start with a hash symbol ( like in C ), and whitespace before and after the hash symbol is ignored.
In general multi-line sections need a #end type of directive to denote the section end. So an #if needs a matching #endif and a #define multiline define needs a #end-def.
This is not any different from C's method or syntax. Here are two examples to demonstrate :
A basic macro
#define SomeThing A_Specific_Thing
A functional macro on one line
#define debug( msg ) fprintf( stderr, "DEBUG :: %s\n", msg )
Quite familiar to the C or C++ developer and not really very hard to understand for a java coder either. For those unfamiliar with functional macros note that the parameter names in the define declaration will be substituted by whatever you put in there when you use the macros.
One of the main reasons to use macros is to support conditional inclusion of code depending on whether specific macros are defined or not.
In the case of javapp three types of conditional test are available :
This can be illustrated in three examples :
Test for macro existence ( i i.e. macro is defined already )
#ifdef Something /* This is the macro body */ #endif
Test a macro string has a specific value
#if ThisMacro == "This string" /* Body of macro for test true */ #else /* Body of macro for test false */ #endif
Note that the == operator tests for case dependant equality, whereas the ~~ operator tests for case indepenant equality.
You can also use brackets around a test.
Boolean expressions can also be used.
#if ( FLAG_1 & FLAG_2 ) ^ ! ( FLAG_1 & FLAG_3 ) /* Body of macro */ #endif
These boolean operations are available :
First and foremost note that while javapp uses a very C-preprocesor-like syntax, it is not the same thing. I don't think anyone familiar with C's preprocessor will find the differences a problem ( indeed I hope they'll like them ), but be aware that there are subtle differences - good engineers read the manual first, but all engineers end up reading it eventually !
A simple example should illustrate this.
#define mymacrofn( p1, p2 ) while( p1 != p2 ){ p1++; p2++ ; }
Everything after the function prototype will be used for the macro.
To include other files just use
#include thisfile.inc
Note that unlike C there are no standard include files and no standard path. Include files should use an explicit path.
The include file will be parsed as if it was inlined with the original file and that means all defines are active.
There is no special extension type ( e.g. like .h for C ) for macro files or source files. Javapp will try and process any file of any name.
Again this is very much like C with differnece that an example will illustrate.
#define FANDANGO() #ifdef DANCE Fandango is a dance in this context. #else Fandango is not a dance in this context. #endif #end-def #define FOO foo-as-value #define FOOFN foofn-as-value #define FOOFN(_p1) foofn-as-single-param-function _PASNG [_p1] #define FOOFN(_p1,_p2) foofn-as-two-param-function _PASNG [_p1] and [_p2]
Unlike C we can use #if and #ifdef inside the macro body.
We can "overload" macro functions without any issue at all. Javapp will work out which one to use.
Note that for the purposes of testing macr existance, defining something as a function or a value is the same. That is the test #ifdef FOOFN works for either type of definition.
The special macro function parameter ... will substitute any parameters it finds. You can refer to specific varadic parameters. You can refer to all the parameters at once. An example will illustrate this.
#define varyme(p1, p2, ...) System.out.println( p1 ) ; System.out.println( p2 ) ; System.out.printf( "These are the varying arguments :: ", __VA_ARGS__ ) ; System.out.println( "This was the first varying argument : " + __VA_ARGS__$1 ) ; #end-def
Note that __VA_ARGS_$1 will not use the p1 or p2 parameters in this example, but the first parameter after them - that is, the first variadic paremeter.
No single application can do everything, so javapp lets you feed the output of external commands into your code. You can also feed those external commands from lines within your source file. Remember that the output of the command will also be processed by javapp.
Here's an example :
#command ls -lap
Which, for non-unix types, is the command to output a long-form listing of the local directory. You could use this to e.g. embedded code to be processed by another application and later used by Java. You could use it for documentation purposes as well. It's there to provide flexibility.