Preprocessor¶
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
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.
$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.
$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
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
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
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
$include¶
$include
filename
Include another source file.
#
# preproc-include, demonstrate $include preprocessor directive
#
$include "preproc-define.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
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
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
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
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