S TOOLS-STx preprocessor

From STX Wiki
Jump to navigation Jump to search

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) ||

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:


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.


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
!       error case 3

!define HUGO
!   define   HUGO 

!define BUMSTI

// note that preprocessor constants are case-insensitive (unlike C)
!if defined bumsti && defined(Hugo)
        writelog 'OK 1'
        writelog 'ERROR 1'

!undef BUMSTI

!if defined (BUMSTI) && defined HUGO
        writelog 'ERROR 2'
        writelog 'OK 2'

!if ! defined BUMSTI && (defined HUGO)
        writelog 'OK 3'
        writelog 'ERROR 3'

!if defined HUGO && ! defined BUMSTI
        writelog 'OK 4'
        writelog 'ERROR 4'

!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'

        writelog 'OK 11'

!end if

!undef HUGO

!ifndef HUGO

        writelog 'OK 12'

        writelog 'ERROR 12'

!end if

!define BUMSTI

!if (defined HUGO || defined BUMSTI) && ! defined T

        writelog 'OK 13'


        writelog 'ERROR 13'


!if (defined BUMSTI || defined HUGO) && defined T

        writelog 'ERROR 14'


        writelog 'OK 14'


!  if defined hallo

! endif

// now test a few pathological cases



        writelog 'OK 15'


        writelog 'ERROR 15'

!end if


        writelog 'OK 16'


        writelog 'ERROR 16'



!define BUMSTI

!ifdef UNKNOWN

        writelog 'ERROR 17a'

!elif defined HUGO

        writelog 'ERROR 17b'

!elif defined BUMSTI

        writelog 'OK 17'

        writelog 'ERROR 17c'


!ifdef UNKNOWN

        writelog 'ERROR 18a'

!elif defined UNKNOWN

        writelog 'ERROR 18b'

!elif defined HUGO && defined BUMSTI && defined UNKNOWN

        writelog 'ERROR 18c'


        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'



]define BRACKET

]if!defined BRACKET

        writelog 'ERROR 21a'

]elif !defined BRACKET

        writelog 'ERROR 21b'

]elif defined BRACKET &&!defined BRACKET

        writelog 'ERROR 21b'


        writelog 'OK 21'


!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


        writelog 'ERROR 22c'
!       warn ERROR 22c-1

!warn This is my personal warning. // comment
!warning This is my last warning.

!include "preprocessor.inc"
//XXX !include "preprocessor.inc"

// !error This is my personal error.
// !error

exit 1 int 0