Preprocessor

_images/unicon.png

Index Unicon

Unicon features a simple preprocessor, supporting file inclusion, conditional compilation, symbolic constants, source line number (and reported filename) override, and an error messaging directive.

The internal Unicon preprocessor does not support the list of features included in the IPL program ipp.icn. There is no $elif for instance, nor $if constant-expression. The macro substitution features are also not supported. ipp will work with most, if not all, Unicon sources, but it is not the same as the internal Unicon preprocessor. ipp may have more features, but the simpler, internal Unicon preprocessor is more accessible, built into the compiler. As a Unicon programmer, you have the option of using ipp (it ships with the Unicon source kit along with the IPL), but it is probably best to stick with the internal mechanisms.

Unicon preprocessor

Preprocessor directives are lines that begin with a dollar sign and are processed before the translation stage begins.

Please note, that all of the code examples for the Unicon preprocessor are short, and contrived.

$define

$define symbol [value]

Define a preprocessor symbol, for testing with $ifdef, $ifndef and as a text replacement. Occurrences of symbol will be replaced by value. Note the values cannot have arguments, the replacement is literal.

#
# preproc-define, demonstrate $define preprocessor directive
#
procedure main()
$define STUB 1
$ifndef STUB 
    write("skip over some code")
$else
    write("Unicon, cui non; sold, in Italian")
$endif
end

examples/preproc-define.icn

Sample output:

prompt$ unicon -E -s preproc-define.icn
#line 0 "/tmp/uni89715035"
#line 0 "preproc-define.icn"










procedure main();




    write("Unicon, cui non; sold, in Italian");

end

$else

$else

$else marks the beginning of an optional, alternate source code block for processing an $ifdef or $ifndef conditional compile directive sequence. As nesting is allowed, $else matches to the closest previous $ifdef or $ifndef.

See $ifdef, $ifndef for examples.

$endif

$endif

$endif marks the end of a conditional compile source block when processing an $ifdef or $ifndef sequence. As nesting is allowed, $endif closes the closest previous $ifdef, $ifndef sequence.

See $ifdef, $ifndef for examples.

$error

$error text

$error causes the compiler to output an error with the supplied text as the message.

#
# preproc-error, demonstrate $error preprocessor directive
#
procedure main()
$ifdef _MSDOS
    write("MSDOS available, GetSpace and FreeSpace")
    A := GetSpace(64) | stop("GetSpace failed")
    FreeSpace(A)
$else
$error MSDOS features required for this program
$endif
end

examples/preproc-error.icn

Sample output:

prompt$ unicon -E -s preproc-error.icn
File preproc-error.icn; Line 17 # $error: MSDOS features required for this program

$ifdef

$ifdef symbol

$ifdef tests for a preprocessor symbol and, if defined, will emit source lines up to the next matching $else (or $endif, when no else directive is present). If not defined, the preprocessor will scan ahead to a matching $else, if present, and then output source lines up to the matching $endif directive. Nesting is allowed. All $ifdef directives must end with an $endif.

#
# preproc-ifdef, demonstrate $ifdef preprocessor directive
#
procedure main()
$ifdef _POSIX
    write("POSIX available, pid is ", getpid())
$else
    write("No POSIX features with this ", &version)
$endif
end

examples/preproc-ifdef.icn

Sample output:

prompt$ unicon -E -s preproc-ifdef.icn
#line 0 "/tmp/uni21181049"
#line 0 "preproc-ifdef.icn"










procedure main();

    write("POSIX available, pid is ", getpid());



end
prompt$ unicon -s preproc-ifdef.icn -x
POSIX available, pid is 12617

Attention

Please be advised that this contrived example is not a preferred way to do feature testing in Unicon. The builtin &features keyword can be used at runtime for these type of conditional code fragments.

if &features == "ms windows" then ...
procedure main()
  if &features == "POSIX" then
    write("POSIX available, pid is ", getpid())
  else
    write("No POSIX features with this ", &version)
end

The runtime penalty is slight, and .u code is highly portable. Runtime platform tests are encouraged, preprocessor conditionals (for feature testing) less so.

$ifndef

$ifndef symbol

$ifndef is the opposite of $ifdef. The $ifndef directive tests for a preprocessor symbol and if not defined, will emit source lines up to the next matching $else (or $endif, when no else directive is present). If the symbol is defined, the preprocessor will scan ahead to a matching $else, if present, and then output source lines up to the matching $endif directive. Nesting is allowed. All $ifndef directives must end with an $endif.

#
# preproc-ifndef, demonstrate $ifndef preprocessor directive
#
procedure main()
$ifndef _MSDOS
    write("No MSDOS features with this ", &version)
$else
    write("MSDOS available, GetSpace and FreeSpace")
    A := GetSpace(64) | stop("GetSpace failed")
    FreeSpace(A)
$endif
end

examples/preproc-ifndef.icn

Sample output:

prompt$ unicon -E -s preproc-ifndef.icn
#line 0 "/tmp/uni90038522"
#line 0 "preproc-ifndef.icn"










procedure main();

    write("No MSDOS features with this ", &version);





end
prompt$ unicon -s preproc-ifndef.icn -x
No MSDOS features with this Unicon Version 13.1.  August 19, 2019

Note

Please be advised that this contrived example is not a preferred way to do feature testing in Unicon. The builtin &features keyword can be used at runtime for these type of conditional code fragments. See the $ifdef entry for a runtime alternative.

$include

$include filename

Include another source file.

#
# preproc-include, demonstrate $include preprocessor directive
#
$include "preproc-define.icn"

examples/preproc-include.icn

Sample output:

prompt$ unicon -E -s preproc-include.icn
#line 0 "/tmp/uni10194789"
#line 0 "preproc-include.icn"

#line 10 "preproc-define.icn"
procedure main();




    write("Unicon, cui non; sold, in Italian");

end

$line

$line line-number [“filename”]

Override view of current source line (and optionally file). Subsequent lines are treated by the compiler as commencing at the given line number in the current or given filename, which must be quoted.

This directive is mainly of use for machine generated sources; for programs that generate (or manipulate) source programs, such as ulex or flex/bison.

This first sample is a compile time override example:

#
# preproc-line, demonstrate $line override preprocessor directive
#
# This feature is mainly for use with machine generated sources
#
procedure main()
$ifdef _MSDOS
    write("MSDOS available, GetSpace and FreeSpace")
    A := GetSpace(64) | stop("GetSpace failed")
    FreeSpace(A)
$else
# error will be reported as coming from line 2 of sample.icn
$line 1 "sample.icn"
$error MSDOS features required for this program
$endif
end

examples/preproc-line.icn

Sample output:

prompt$ unicon -E -s preproc-line.icn
File sample.icn; Line 2 # $error: MSDOS features required for this program

Now to see how it effects the runtime reporting:

#
# preproc-line, demonstrate $line override preprocessor directive
#
# This feature is mainly for use with machine generated sources
#
procedure main()
# preprocessor will add blank lines and report runtime error as line 21
$line 20
    a := 1 + []
end

examples/preproc-line-2.icn

Sample preprocessor output:

prompt$ unicon -E -s preproc-line-2.icn
#line 0 "/tmp/uni10194789"
#line 0 "preproc-line-2.icn"












procedure main();







    a := 1 + [];
end

There will a runtime error reported when this program runs, with the reported line number influenced by $line directive.

prompt$ unicon -s preproc-line-2.icn -x

Run-time error 102
File preproc-line-2.icn; Line 21
numeric expected
offending value: list_1 = []
Traceback:
   main()
   {1 + list_1 = []} from line 21 in preproc-line-2.icn

One last time; the $line directive is of most use with machine generated sources.

$undef

$undef symbol

Undefine a preprocessor symbol.

#
# preproc-undef, demonstrate $undef preprocessor directive
#
procedure main()
$define STUB 1
$ifndef STUB 
    write("skip over some code")
$else
    write("Unicon, cui non; sold, in Italian")
$undef STUB
$endif

$ifndef STUB 
    write("don't skip over this code")
$else
    write("do skip over this code")
$endif
end

examples/preproc-undef.icn

Sample output:

prompt$ unicon -E -s preproc-undef.icn
#line 0 "/tmp/uni90038522"
#line 0 "preproc-undef.icn"










procedure main();




    write("Unicon, cui non; sold, in Italian");




    write("don't skip over this code");



end

#line

#line line-number filename

#line is an internal (not meant for programmers at the source level) directive keyword that manages post preprocessor line and filename semantics for the compiler proper.

You will see the directive with unicon -E output but it is not for general use.

Predefined symbols

Predefined symbols (for use with $ifdef, and $ifndef) are provided for each platform, and for any optional features compiled into the running version of Unicon.

Testable symbols include:

Symbol Feature
_MULTITASKING multiple programs
_X_WINDOW_SYSTEM X Windows
_GRAPHICS graphics
_PIPES pipes
_ARM_FUNCTIONS Archimedes extensions
_MS_WINDOWS MS Windows
_MVS MVS
_MSDOS_386 MS-DOS/386
_EVENT_MONITOR event monitoring
_POSIX POSIX
_KEYBOARD_FUNCTIONS keyboard functions
_OS2 OS/2
_MACINTOSH Macintosh
_VMS VMS
_DYNAMIC_LOADING dynamic loading
_EBCDIC EBCDIC
_EXTERNAL_FUNCTIONS external functions
_SYSTEM_FUNCTION system function
_CMS CMS
_MSDOS MS-DOS
_PORT PORT
_V9 Version 9
_CONSOLE_WINDOW console window
_DOS_FUNCTIONS MS-DOS extensions
_MESSAGING messaging
_MS_WINDOWS_NT MS Windows NT
_RECORD_IO record I/O
_ACORN Acorn Archimedes
_DBM DBM
_CO_EXPRESSIONS co-expressions
_AMIGA Amiga
_ASCII ASCII
_WIN32 Win32
_UNIX UNIX
_PRESENTATION_MGR Presentation Manager
_LARGE_INTEGERS large integers

Substitution symbols

There some predfined symbols that will cause substitution during the preprocessor pass.

Symbol Replacement
__DATE__ Current date in YYYY/MM/DD form
__TIME__ Current time is hh:mm:ss form
#
# preproc-symbols, demonstrate preprocessor substitution symbols
#
procedure main()
    write(__DATE__)
    write(__TIME__)
end

examples/preproc-symbols.icn

Sample output:

prompt$ unicon -E -s preproc-symbols.icn
#line 0 "/tmp/uni10194789"
#line 0 "preproc-symbols.icn"










procedure main();
    write("2019/10/27");
    write("04:47:44");
end

EBCDIC transliterations

Some legacy keyboards do not include {, }, [, or ] characters, vital for Unicon programming. The preprocessor will replace:

  • $( with {
  • $) with }
  • $< with [
  • $> with ]

This transliteration only applies to EBCDIC system builds.


Index | Previous: Keywords | Next: Development Tools