S TOOLS-STx preprocessor
The STx preprocessor may be used for conditionally skipping parts of an STx macro depending on which preprocessor constants have been defined (and which haven't). In the STx script examples directory, you will find a script called "preprocessor.sts" showing several ways of using the preprocessor.
Every STx preprocessor command must start either with the character "!" (exclamation mark), or with the character "]" (closed square bracket). Although not strictly enforced (the preprocessor only issues a warning otherwise), either character should be placed in the very first column of the respective line.
For defining and undefining a preprocessor constant, there are the preprocessor commands "define" and "undef":
! define CONSTANT1 ! define CONSTANT2 ! undef CONSTANT1
Like STx item names, STx preprocessor constants are case-insensitive, meaning that "CONSTANT1", "constant1", and "CoNsTaNt1" are the same constant.
Note that (for the time being), the only property of preprocessor constants is their being defined or being undefined. It is currently not possible (since it would currently make no sense) to assign a value to a constant.
The conditional "ifdef", "elif", "else", and "endif" preprocessor statements cause the macro interpreter conditionally to skip part of the macro source code. See for yourself:
! ifdef CONSTANT writelog 'This statement will be executed if CONSTANT is defined' ! else writelog 'This statement will be executed unless CONSTANT is defined' ! endif
With the "if" command, there is also support for complex conditions:
! if defined(CONS1) || defined(CONS2) && defined(CONS3) writelog 'This statement will be executed if either CONS1 or both of CONS2 and CONS3 are defined' ! elif defined CONS4 && ! defined CONS5 writelog 'This statement will be executed if the preceding statement is not, and if CONS4 is defined and CONS5 is not ! else writelog 'This statement will be executed if neither of the preceding statements were' ! endif
Note that you may, but need not enclose the argument of the "defined" function (i.e. the name of a constant) in brackets. Also note that you may build up complex expressions with the &&, ||, and the ! operator. Also also note that you may group expressions with brackets:
! if (defined(CONS1) || defined CONS2) && (defined(CONS3) || defined(CONS4))
If you do not use brackets, "&&" will take precedence over "||", as it normally does (and contrary to what STx normally does due to historical reasons).
There are a few additional preprocessor statements you may find useful:
!include
With the "include" statement, you may textually merge some other files into the current macro (just like with the "#include" preprocessor statement in C, or with COBOL copy books). Note that it is (for obvious reasons) not possible for a file to include itself, or to include a file that includes a file that, in turn, includes a file including the first file. If you try to, macro interpretation will abort with an error message. If the file name supplied to the "include" statement is not an absolute path, the preprocessor will first look for the respective relative path in the current directory and, on failure, will look for it in directory where the including file is situated. Note that, for the time being, file inclusion may not be nested for more than forty-two levels.
!showdef
Without arguments, this command will print a list of all preprocessor constants currently defined. With an argument supplied, the command will show if the argument is a preprocessor constant that is currently defined.
!warn msg
This statement causes the STx script loader to display a user-defined warning message. Execution of the script is not impaired by issuing a warning.
!error msg
This statement causes the STx script loader to issue a user-defined error message and to cancel loading the macro.
The STx preprocessor was introduced in version 3.8.0.
STx preprocessor example script
The following script demonstrates the STx preprocessing functionality.
//{{3.8 3219}{2007.03.14 20.46.53} - automatically created version information - do not change or delete this line}
[Macro preprocessor]
/*
Script for testing the new preprocessor and for showing its abilities
Christian Gottschall, 15.3.2007
*/
!ifndef HUGO
! warn case 1
!elif defined(HUGO2)
! error case 2
!else
! error case 3
!endif
!define HUGO
! define HUGO
!define BUMSTI
// note that preprocessor constants are case-insensitive (unlike C)
!if defined bumsti && defined(Hugo)
writelog 'OK 1'
!else
writelog 'ERROR 1'
!endif
!undef BUMSTI
!if defined (BUMSTI) && defined HUGO
writelog 'ERROR 2'
!else
writelog 'OK 2'
!endif
!if ! defined BUMSTI && (defined HUGO)
writelog 'OK 3'
!else
writelog 'ERROR 3'
!endif
!if defined HUGO && ! defined BUMSTI
writelog 'OK 4'
!else
writelog 'ERROR 4'
!endif
!undef BUMSTI
!undef BUMSTI
!ifdef HUGO
! ifndef BUMSTI
writelog 'OK 5'
! else
writelog 'ERROR 5'
! endif
! ifdef BUMSTI
writelog 'ERROR 6'
! else
writelog 'OK 6'
! ifdef HUGO
writelog 'OK 7'
! ifdef BUMSTI
writelog 'ERROR 8'
! else
writelog 'OK 8'
! endif
! else
! ifndef BUMSTI
writelog 'ERROR 9'
! else
writelog 'ERROR 10'
! endif
writelog 'ERROR 7'
! endif
writelog 'OK 9'
! end if
writelog 'OK 10'
!end if
!ifndef HUGO
writelog 'ERROR 11'
!else
writelog 'OK 11'
!end if
!undef HUGO
!ifndef HUGO
writelog 'OK 12'
!else
writelog 'ERROR 12'
!end if
!define BUMSTI
!if (defined HUGO || defined BUMSTI) && ! defined T
writelog 'OK 13'
!else
writelog 'ERROR 13'
!endif
!if (defined BUMSTI || defined HUGO) && defined T
writelog 'ERROR 14'
!else
writelog 'OK 14'
!endif
! if defined hallo
! endif
// now test a few pathological cases
!defineBLUBBER
!if(definedBLUBBER)
writelog 'OK 15'
!else
writelog 'ERROR 15'
!end if
!ifdefinedBLUBBER&&!definedUNDEFINED&&definedBLUBBER&&!!definedBLUBBER||!definedBLUBBER&&definedBLUBBER
writelog 'OK 16'
!else
writelog 'ERROR 16'
!endif
!showdef
!define BUMSTI
!ifdef UNKNOWN
writelog 'ERROR 17a'
!elif defined HUGO
writelog 'ERROR 17b'
!elif defined BUMSTI
writelog 'OK 17'
!else
writelog 'ERROR 17c'
!endif
!ifdef UNKNOWN
writelog 'ERROR 18a'
!elif defined UNKNOWN
writelog 'ERROR 18b'
!elif defined HUGO && defined BUMSTI && defined UNKNOWN
writelog 'ERROR 18c'
!else
writelog 'OK 18'
! ifdef XXXXX1
writelog 'ERROR 19a'
! elif defined XXXXXX2
writelog 'ERROR19b'
! elif!defined XXXXX3
writelog 'OK 19'
! if defined YYYYYYY1
writelog 'ERROR 20a'
! elif defined BUMSTI
writelog 'OK 20'
! elif defined BUMSTI
writelog 'ERROR 20b'
! elif!defined(BUMSTI)
writelog 'ERROR 20c'
! else
writelog 'ERROR 20d'
! endif
! elif defined XXXXX4
writelog 'ERROR 19c'
! else
writelog 'ERROR 19d'
!endif
!endif
]define BRACKET
]if!defined BRACKET
writelog 'ERROR 21a'
]elif !defined BRACKET
writelog 'ERROR 21b'
]elif defined BRACKET &&!defined BRACKET
writelog 'ERROR 21b'
]else
writelog 'OK 21'
]endif
!if defined UndefdThing
writelog 'ERROR 22a'
! warn ERROR 22a-1
!else if defined BRACKET
writelog 'OK 22'
! warn OK 22-1
!else if !defined UndefdThing
writelog 'ERROR 22b'
! warn ERROR 22b-1
!else
writelog 'ERROR 22c'
! warn ERROR 22c-1
!endif
!warn
!warn This is my personal warning. // comment
!warning
!warning This is my last warning.
!include "preprocessor.inc"
//XXX !include "preprocessor.inc"
// !error This is my personal error.
// !error
exit 1 int 0