Menu

Macros

StephenG

Macros in javapp

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.

Contents

Predefined Symbols

There are some predefiend macros for convenience.

  • __LINE__ outputs the current line number in the source file.
  • __FILE__ outputs the current filename being processed.

Basics

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.

Basic Defines

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.

Basic Conditional 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 :

  • macro exists
  • macro as a string has a specific value
  • boolean expression resolves to true

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 :

  • & logical and
  • | logical or
  • ^ logical exclusive or ( an xor )
  • ! the not operation on a single expression or value

Basic Functional macros

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.

Including Files

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.

Multiline functional macros

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.

Variadic parameters

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.

Invoking external processors

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.


Related

Wiki: Home

Want the latest updates on software, tech news, and AI?
Get latest updates about software, tech news, and AI from SourceForge directly in your inbox once a month.