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