2019-07-15 12:21:50 +00:00
[< back to index ](../doc_index.md )
2018-07-12 16:30:35 +00:00
# Preprocessor
The Millfork preprocessor does 2 things:
* filters lines in the input file according to current target's features
* injects the target's feature values as constants into the current file
Despite its similarity to the C preprocessor, it's much more restricted in its power:
* no file inclusion
* no macros
* separate namespaces for the preprocessor and the language (you need to use `#use` to use a preprocessor constant in the code)
2019-06-14 13:33:17 +00:00
Preprocessor directives by default start with `#` .
To avoid conflicts with C preprocessor (for users wishing to use it), it is also possible to replace `#` with `$$` .
2018-07-12 16:30:35 +00:00
### Defining feature values
Feature values are defined in the `[define]` section of the platform definition file.
Each value is a signed 64-bit integer number.
Example:
[define]
WIDESCREEN=1
You can also define feature values using the `-D` command line option.
### Built-in features
2018-08-08 11:44:30 +00:00
The following features are defined based on the chosen CPU and compilation options:
2018-12-29 19:16:05 +00:00
* `MILLFORK_VERSION` – defined since 0.3.4, contains the version of the compiler: for version x.y.z, the value is 10000x+100y+z
2018-07-30 16:16:50 +00:00
* `ARCH_6502` – 1 if compiling for 6502, 0 otherwise
2018-07-12 16:30:35 +00:00
2018-08-08 11:44:30 +00:00
* `ARCH_I80` – 1 if compiling for Intel 8080-like processor, 0 otherwise
2018-07-30 16:16:50 +00:00
2019-05-31 15:03:35 +00:00
* `ARCH_X86` – 1 if compiling for Intel 8086-like processor, 0 otherwise
2019-06-12 10:06:02 +00:00
* `CPU_65C02` , `CPU_65CE02` , `CPU_65816` , `CPU_HUC6280` , `CPU_8080` , `CPU_8085` , `CPU_GAMEBOY` , `CPU_Z80` , `CPU_8086`
2018-08-08 11:44:30 +00:00
– 1 if compiling for the exact given processor, 0 otherwise
2018-07-30 16:16:50 +00:00
2018-08-08 11:44:30 +00:00
* `CPU_6502` – 1 if compiling for any pre-65C02 6502-like processor, 0 otherwise
* `CPUFEATURE_DECIMAL_MODE` – 1 if decimal mode is enabled, 0 otherwise
* `CPUFEATURE_65C02` , `CPUFEATURE_65CE02` , `CPUFEATURE_HUC6280` , `CPUFEATURE_65816_EMULATION` , `CPUFEATURE_65816_NATIVE` ,
2019-06-12 10:06:02 +00:00
`CPUFEATURE_8080` , `CPUFEATURE_8085` , `CPUFEATURE_GAMEBOY` , `CPUFEATURE_Z80` ,
2019-09-30 22:46:15 +00:00
`CPUFEATURE_6502_ILLEGALS` , `CPUFEATURE_8085_ILLEGALS` , `CPUFEATURE_Z80_ILLEGALS` , `CPUFEATURE_Z80_NEXT` – 1 if given instruction subset is enabled, 0 otherwise
2018-08-08 11:44:30 +00:00
2019-11-04 01:28:12 +00:00
* `ENCCONV_SUPPORTED` - 1 if the module `encconv` supports the function `to_screencode` and other related funtions, 0 otherwise.
2019-09-03 23:14:14 +00:00
* `ENCODING_SAME` - 1 if the encodings `default` and `src` are the same, 0 otherwise.
2019-10-31 11:20:20 +00:00
* `NULLCHAR_SAME` - 1 if the encodings `default` and `src` have the same string terminator, 0 otherwise.
* `NULLCHAR` – the value of the `nullchar` constant
* `NULLCHAR_SRC` – the value of the `nullchar_src` constant
2019-06-28 14:28:49 +00:00
* `INIT_RW_MEMORY` – 1 if the option `ram_init_segment` is defined, 0 otherwise.
See [the ROM vs RAM guide ](../api/rom-vs-ram.md ) for more information.
2019-07-15 12:15:38 +00:00
* `BIG_ENDIAN` – 1 if the platform is big-endian, 0 otherwise (currently all supported platforms are little-endian)
* `LITTLE_ENDIAN` – 1 if the platform is little-endian, 0 otherwise (currently all supported platforms are little-endian)
2018-08-08 11:44:30 +00:00
* `OPTIMIZE_FOR_SIZE` , `OPTIMIZE_FOR_SPEED` , `OPTIMIZE_INLINE` , `OPTIMIZE_IPO`
– 1 if given optimization setting is enabled, 0 otherwise
2018-07-30 16:16:50 +00:00
2018-08-08 11:44:30 +00:00
* `SYNTAX_INTEL` , `SYNTAX_ZILOG` – 1 if given assembly syntax is chosen, 0 otherwise; doesn't take this file's pragmas into account
2018-07-30 16:16:50 +00:00
2018-08-08 11:44:30 +00:00
* `USES_ZPREG` – 1 if the zeropage pseudoregister is used, 0 otherwise
2018-07-30 16:16:50 +00:00
2019-06-12 10:06:02 +00:00
* `ZPREG_SIZE` – size of the pseudoregister in bytes, or 0 on platforms that don't use it
2018-08-08 11:44:30 +00:00
2019-06-28 14:44:41 +00:00
* `TINY_RW_MEMORY` – 1 if the main ram is 256 bytes or less, 0 otherwise
2019-06-28 14:28:49 +00:00
2018-08-08 11:44:30 +00:00
* `USES_IX_STACK` , `USES_IY_STACK` – 1 if given index register is used as a base pointer for stack-allocated variables, 0 otherwise
2019-06-12 10:06:02 +00:00
* `USES_SHADOW_REGISTERS` – 1 if interrupts preserve old registers in the shadow registers, 0 if they do it on stack
2018-07-12 16:30:35 +00:00
2019-06-12 10:06:02 +00:00
* `USES_SOFTWARE_STACK` – 1 if using software stack for variables (6502-like targets only), 0 otherwise
2018-12-14 21:01:52 +00:00
2018-07-12 16:30:35 +00:00
### Commonly used features
* `WIDESCREEN` – 1 if the horizontal screen resolution, ignoring borders, is greater than 256, 0 otherwise
2019-09-14 01:34:32 +00:00
* `CBM` – 1 if the target is an 8-bit Commodore computer (or a compatible one), 0 otherwise
2018-07-12 16:30:35 +00:00
2019-06-26 11:40:33 +00:00
* `CBM_64_COMPAT` – 1 if the target is an 8-bit Commodore computer compatible with Commodore 64, 0 otherwise
2018-07-12 16:30:35 +00:00
2018-12-17 10:13:01 +00:00
* `CBM_64_CRT` – 1 if the target is a cartridge for Commodore 64, 0 otherwise
2018-08-08 11:44:30 +00:00
* `CBM_264` – 1 if the target is an 8-bit Commodore computer from the 264 line, 0 otherwise
2018-07-12 16:30:35 +00:00
* `KEYBOARD` – 1 if the target has a keyboard, 0 otherwise
* `JOYSTICKS` – the maximum number of joysticks using standard hardware configurations, may be 0
* `HAS_BITMAP_MODE` – 1 if the target has a display mode with every pixel addressable, 0 otherwise
2018-08-08 11:44:30 +00:00
* `MOS_6510` – 1 if the target uses a MOS 6510-compatible processor (with an I/O port at $0000/$0001)
* `CPM` – 1 if the target is CP/M, 0 otherwise
2019-05-31 15:03:35 +00:00
* `IBM_PC` – 1 if the target is IBM PC, 0 otherwise
2019-06-05 11:31:43 +00:00
* `MSX` – 1 if the target is MSX, 0 otherwise
2018-12-19 18:01:53 +00:00
* `NTSC` – 1 if the target is NTSC, 0 otherwise
* `PAL` – 1 if the target is PAL, 0 otherwise
2019-04-16 14:56:23 +00:00
* `NULLPTR` – physical value of `nullptr` , default 0
2019-09-16 20:55:08 +00:00
* `VERA_VERSION` – on Commander X16, the version of the VERA chip: `7` for 0.7, `8` for 0.8
2018-07-12 16:30:35 +00:00
### Built-in preprocessor functions and operators
The `defined` function returns 1 if the feature is defined, 0 otherwise.
All the other functions and operators treat undefined features as if they were defined as 0.
2019-06-14 10:00:45 +00:00
The `if` function returns its second parameter if the first parameter is defined and non-zero, and the third parameter otherwise:
// prints 400:
#infoeval if(1, 400, 500)
// prints 500:
#infoeval if(0, 400, 500)
TODO
2018-07-12 16:30:35 +00:00
`not` , `lo` , `hi` , `+` , `-` , `*` , `|` , `&` , `^` , `||` , `&&` , `<<` , `>>` ,`==`, `!=` , `>` , `>=` , `<` , `<=`
The following Millfork operators and functions are not available in the preprocessor:
`+'` , `-'` , `*'` , `<<'` , `>>'` , `:` , `>>>>` , `nonet` , all the assignment operators
### `#if/#elseif/#else/#endif`
#if < expr >
#elseif < expr >
#else
#endif
TODO
### `#fatal/#error/#warn/#info`
2019-09-16 20:48:21 +00:00
#fatal fatal error message
2018-07-12 16:30:35 +00:00
#error error message
#warn warning message
#info informational message
Emits a diagnostic message.
`#fatal` interrupts the compilation immediately.
`#error` causes an error, but the compilation will continue.
`#warn` emits a warning. It may be treated as an error depending on compilation options.
`#info` emits a benign diagnostic message.
2018-09-28 20:41:57 +00:00
### `#infoeval`
#infoeval < expr >
Evaluates an expression and emits the result as a diagnostic message.
2018-07-12 16:30:35 +00:00
2019-06-26 11:43:15 +00:00
### `#define`
#define < ident > = < expr >
Defines a new feature value or redefines a previous feature value.
The feature value is visible only to the preprocessor, only when processing the current file,
and only in lines preprocessed after this one.
2018-07-12 16:30:35 +00:00
### `#use`
2019-06-14 10:00:45 +00:00
#use < ident > = < expr >
#use < feature >
// equivalent to #use < feature > = < feature >
Exports a value to the parser.
The parser will substitute every use of the given identifier as a variable or constant
2018-07-12 16:30:35 +00:00
with the numeric value of the feature.
2019-06-14 10:00:45 +00:00
#use CPU_MODEL = if(CPU_65816 | ARCH_X86, 16, 8)
putstrz("Your CPU is "z)
putword(CPU_MODEL)
putstrz("-bit."z)
2018-07-12 16:30:35 +00:00
The substitution will happen only within the current file.
2019-06-14 10:00:45 +00:00
To use such value in other files, consider using a normal constant:
2018-07-12 16:30:35 +00:00
#use WIDESCREEN
const byte is_widescreen = WIDESCREEN
2018-08-03 11:23:37 +00:00
### `#pragma`
Changes the behaviour of the parser for the current file.
2019-06-12 10:06:02 +00:00
The change applies to the whole file, regardless of where the directive is located.
2018-08-03 11:23:37 +00:00
* `#pragma intel_syntax` – interpret assembly using Intel syntax
* `#pragma zilog_syntax` – interpret assembly using Zilog syntax
2018-07-12 16:30:35 +00:00