<ANTENNA/>
|
AntennaAn Ant-to-End Solution For Wireless Java Version 1.2.1 (c) 2002-2010Erik Wetterberg Sourceforge project |
The new preprocessor backend is developed by Omry Yadan (omry at yadan dot net).
The preprocessor supports operations on variables and access to a device database (Currently only the J2ME polish devices database is supported) is accsible from the WtkPreprocess task and from an Eclipse plugin. This preprocessor is modeled after the NetBeans mobility suite preprocessor (but supports a few additional directives).
The WtkPreprocess task provides a preprocessor, similar to the ones known from C and other languages. It allows for conditional compilation and inclusion of one source file into another and is helpful when trying to maintain a single source for several devices, each having its own bugs, add-on APIs, etc.
Preprocessing source files to manage implementation differences is quite unusual in Java programming. Actually it might be considered "evil technology" by OO purists. While the latter is somewhat true - interfaces, abstract classes and loading classes by name are definitely the cleaner approach - pure OO is something you often cannot afford when developing for devices that accept only JAR files up to 30 KB. A simple interface easily costs a kilobyte or more in the JAR. Loading implementation-specific classes by name usually gets in the way of obfuscation. A conditionally compiled block, on the other hand, costs absolutely nothing (apart, maybe, from a bit of pride, in case you consider yourself an OO purist, but isn't that a small price to pay for a MIDlet that works merrily on dozens of different mobile phones?). Please note that the task only preprocesses the source files, but doesn't compile them. So you still have to run the Java compiler on the preprocessed files afterwards. Since the preprocessor doesn't filter "inactive" conditional parts by removing them, but by commenting them out instead, line numbers for compiler errors are usually the same as for the original code (unless you are using #include). In addition to conditional compilation the preprocessor replaces Ant-style properties in the source-code. The task provides the following parameters:Parameter | Type | Required | Purpose |
---|---|---|---|
version | int | no |
Preprocessor backend version.
|
device | string | no |
A device from the device database, for example "Nokia/6280". All the symbols for this device will be automatically injected into the symbols list. (supported only by backend-version 2) |
devicedbpath | dir | no | Optional path for the devices xml files |
debuglevel | Debug level | no | Turn debug level on, value should be one of [debug|info|warn|error|fatal] |
printsymbols | boolean | no | Used to debug, if true all preprocesor symbols will be printer prior to preprocessor. |
savesymbols | Filename | no | Saves all the preprocessor symbols to a file |
srcdir | file | yes | The source directory from which Java source files are being preprocessed. |
destdir | file | yes | The destination directory to which preprocessed files are written. |
newext | string | no | Specifies a new file extension for all files that have gone through the preprocessor. Useful when you save the files to preprocess with a special extension to distinguish them from normal Java files. The new extension replaces everything from (and including) the first dot in the filename up to the end, so when you specify newext=".java", a file "MyFile.j2me.pp" becomes "MyFile.java" once it goes through the peprocessor. If you don't specify this parameter, file extensions are not changed. |
indent | boolean | no | Controls indentation of comments that the preprocessor writes into the target files. Defaults to true, which results in comments having the same indentation as the the original line. Setting it to false results in comments starting at the beginning of a line. |
symbols | string | no |
A list of define symbols that are initially defined
for each file the preprocessor is invoked on.
Parsing of this list is done by the actual preprocessor backend, so the syntax changes from backend to backend.
|
encoding | string | no | Specifies the encoding to use when reading or writing source files. Defaults to the platform default encoding, if not specified. |
filter | boolean | no | When set to true, the preprocessor filters all directives and "inactive" conditional parts. The resulting file contains only the actual Java source code that goes into the compiler. Defaults to false. |
verbose | boolean | no | Turn verbose output on or off. |
if | String | no | Provides fine-grained control over task execution based on a property definition. The task will only be executed if the given property is defined. |
unless | String | no | Provides fine-grained control over task execution based on a property definition. The task will only be executed if the given property is not defined. |
KEY=VALUE : Standard define, if key is already defined it will be replaced add_if_new@KEY=fff : Sets key only if it's not defined already unset@KEY : Clears the value of KEY
Parameter | Type | Required | Purpose |
---|---|---|---|
Name | string | This or List | Symbols file name to load/td> |
List | string | This or name | Comma separated list symbols file names to load |
<wtkpreprocess verbose="true" srcdir="src" destdir="out" device="Generic/Java" symbols="LIST='1,2,3',STR='String',PI=3.1415,VERSION=${VERSION}" printsymbols="true"> <!-- Load a.symbols --> <symbols_file name="a.symbols"/> <!-- Load b.symbols --> <symbols_file name="b.symbols"/> <!-- Load c.symbols and d.symbols--> <symbols_file list="c.symbols,d.symbols"/> </wtkpreprocess>
Directive | Decription |
---|---|
#ifdef [identifier] | The identifier represents a variable of any type (boolean, string, or integer) and checks whether or not the variable is defined. If true (the variable is defined), the code that follows is processed. Nested blocks are processed as well. If false (the variable is not defined), the code that follows is commented and nested blocks are not evaluated. The directive must be closed with #endif. |
#ifndef [identifier] | Works in the same manner as ifdef, but returns "True" if the variable is not defined. The directive must be closed with #endif. |
#elifdef [identifier] | Works as a standard else if statement, but automatically checks whether or not the identifier is defined. The directive can only complement inside blocks started by ifdef/ifndef. |
#elifndef [identifier] | Works as a standard else if statement but automatically checks whether the identifier is not defined. The directive can only complement inside blocks started by ifdef/ifndef. |
#if [expression] | Evaluates an expression passed to it and fires the appropriate action. The directive must be closed with endif. |
#elif [expression] | Works as a standard else if statement and can complement only in blocks started by an if statement. The directive preprocesses the code that follows based on the result of the expression. |
#else | Works as a standard else statement only preprocesses the code that follows when none of the previous conditions in the defining block were true. Complements inside any block started with the if/ifdef/ifndef directive. |
#endif | This directive must be used to close any block started with if/ifdef/ifndef. |
#condition [expression] | Must be on the first line in a file. This directive determines if the file should be included in the build based on the result of the expression. |
#debug [level] | Determines if the line following the directive should be commented or uncommented based on the debug level set in Compiling page of the project properties. If the debug level is omitted and the debug level is not set to "Off" in the project properties, the preprocessor will automatically debug the line in question. Used for debugging purposes with expressions such as System.out.println, for example. This directive can be nested. |
#mdebug [level] | Behaves the same as #debug, but instead comments or uncomments a whole block of lines following the line it is on until it reaches #enddebug. This directive is used for debugging purposes with expressions such as System.out.println, for example. This directive can be nested. If the mdebug block partially intersects an if/ifdef/ifndef block (for example, enddebug is outside a closed if block in which mdebug is called) the preprocessor will generate errors. |
#enddebug | Must terminate #mdebug block. |
#define [identifier] | #define [identifier=value] #define [identifier value] Adds temporary abilities or variables to the preprocessor memory. Can not be used in nested blocks. Global variables defined in the project configuration properties override these temporary variables. |
#undefine [identifier] | Removes temporary abilities/variables from the memory. This declaration can also be used to remove global variables defined in the project configuration properties from the preprocessor memory, but will not remove the variables from the list of project or configuration variables. |
#expand LINE WITH MACROS |
Expand directive is used to replace build time defines in the code. You can have a line like: //#expand public static int VERSION = %VERSION%; which will, assuming you have the define VERSION=5, be replaced with the two lines: //#expand public static int VERSION = %VERSION%; public static int VERSION = 5; The reason //#expand is needed is to keep the preprocessing operation reversible (without it, it will not be possible to preprocess the same code and replace the number 5 with the correct version in case VERSION = 6 is defined). |
Operator | Decription |
---|---|
The "not" operator (!) |
This operator has the highest priority and can be used on variables and expressions with the syntax ! |
Comparison operators |
Comparison operators have the second highest priority and perform typical comparison operations. Because the operators can compare strings lexically and integers mathematically, cross-type comparisons are supported. However, they can be used only in expressions and should compare two variables, not symbols. There is also a special comparison operator which performs a "subset" relationship operation. This operator is denoted by the character @. Both left and right arguments should be strings which represent two sets of tokens delimited by specific delimiters. The operator first considers both left and right string arguments as sets and then determines if the set from the left argument is a subset of the set from the right argument. The valid word delimiters are "gif" @ "gif86, jpeg, gifaboo" = false "gif" @ "gif gif86 jpeg" = true "1 2 4;7,8" @ "0,1,2,3,4,5,6,7,8,9" = true "3 5 7 11 13" @ "0,1,2,3,4,5,6,7,8,9" = false |
Boolean operators | Boolean operators have the lowest priority relative to the rest of the operators. They also have different priorities amongst each other, just as in the Java language. Boolean operators perform typical logical operations such as &&, || and ^ on boolean expression results, or check for variable definitions and then treat those as Boolean expressions as well. Boolean operators are processed in the order: 1. && 2. ^ 3. || |