===============================================================================
Blaze Pascal - 99% Turbo Pascal 7 compatible compiler WHATSNEW.TXT
Version 7.0.2ß - November 2026
===============================================================================
Blaze Pascal still compiles Turbo Pascal 7 source and still produces the same 16-bit
DOS/Windows executables and units. Everything new in this release is either switched
OFF by default, or uses syntax that Turbo Pascal 7 would reject, so an existing TP7
program compiles exactly as before!
Contents
1. New language features at a glance
2. Compiler switches - complete reference
3. Compiler directives - complete reference
4. Compile-time macros {$I %NAME%}
5. Delphi 2/3, TMT Pascal and Virtual Pascal compatibility
6. Bug fixes in this release
7. Notes for building Blaze Pascal itself
8. Planned
===============================================================================
1. NEW LANGUAGE FEATURES AT A GLANCE
===============================================================================

- (C) 2026 by Brain Patchwork DX, LLC.
- Screenshot 2026-11-09 210500.png (44.61 KiB) Viewed 25349 times
Feature Enabled by Default Example
------------------------------ ------------------ ---------- ---------------------
Result inside functions {$X+} ON Result := N * 2;
Exit with a return value {$C+} off Exit (-1);
Read-only typed constants {$J-} writable {$J-} Const K: Word=1;
C operators += -= *= /= {$H+} off Total += Price;
TMT operators +:= -:= *:= /:= {$H+} off Total +:= Price;
Ada comments -- text {$AC+} off -- note
{$IF} {$ELSEIF} {$IFEND} {$U+} off {$IF Version >= 3}
Binary literals always - Mask := %10100001;
Octal literals always - Mode := &755;
{$MESSAGE} {$NOTE} {$HINT} always - {$NOTE Beta build}
{$WARNING} {$ERROR} {$FATAL} always - {$ERROR 'Need DPMI'}
{$INCLUDE file} always - {$INCLUDE DEFS.INC}
Compile-time date/time/file always - {$I %DATE%}
Delphi type names (Cardinal...) always - Var W: Cardinal;
MemD (TMT name for MemL) always - W := MemD [$40:$6C];
out parameters always - Procedure P (out X: Integer);
resourcestring sections always - resourcestring SOk = 'OK';
initialization / finalization always - see section 5
Several switches can be combined in one directive, e.g. {$C+,H+,U+}.
Assigned (P) needs no switch: it is a standard Turbo Pascal 7 function.
===============================================================================
2. COMPILER SWITCHES - COMPLETE REFERENCE
===============================================================================
How switches work
-----------------
A switch is a letter followed by + (on) or - (off):
{$R+} in source code
/$R+ on the command line
{$R+,Q+,S-} several at once
GLOBAL switches affect the whole module (program or unit) and must appear
before the first declaration, i.e. before the end of the module heading /
uses clause. They are marked [global] below. All other switches are LOCAL:
they can be turned on and off anywhere, even around a single statement.
{$IFOPT X+} ... {$ENDIF} tests the current state of any switch below.
The defaults shown are what Blaze Pascal (no parameters) lists on its help screen.
A *.CFG file or /$ options on the command line can change them.
$D, $K, $L, $W and $Y are not listed on the help screen; their defaults below
are the Turbo Pascal 7 defaults.
---------------------------------------------------------------------------
$A± Word alignment default A+ [global]
---------------------------------------------------------------------------
A+ aligns variables and typed constants larger than one byte on even (word)
addresses. 8086/80286 CPUs read a word in one bus cycle only when it is at
an even address, so A+ makes code faster at the cost of a few padding bytes.
A- packs data byte-by-byte (smallest size). Record fields are not affected;
use "packed record" for those.
---------------------------------------------------------------------------
$AC± Ada-style comments NEW in 7.0.2ß default AC-
---------------------------------------------------------------------------
The TMT Pascal switch. With AC+, two minus signs start a comment that runs
to the end of the line, as in Ada and TMT Pascal:
{$AC+}
Total := Total + Tax; -- tax was added in version 2
With AC- (the default), -- keeps its Turbo Pascal meaning (minus minus),
so X := Y--1 still compiles. Written with a space, as Y - -1, it is an
expression in both modes.
{$IFOPT AC+} works. Like the other new switches it is local.
---------------------------------------------------------------------------
$B± Complete boolean evaluation default B-
---------------------------------------------------------------------------
B- (short-circuit): evaluation of "and"/"or" stops as soon as the result is
known. If (P <> nil) and (P^.Count > 0) is safe because P^ is never read
when P is nil.
B+ always evaluates every operand, so functions with side effects in a
boolean expression are always called. Rarely needed.
---------------------------------------------------------------------------
$C± C-style Exit (value) NEW in 7.0.2ß default C-
---------------------------------------------------------------------------
With C+, Exit can carry the function result, like "return x" in C or
Exit(x) in Free Pascal and Delphi 2009+:
{$C+}
Function Sign (N: Integer): Integer;
begin
If N < 0 then Exit (-1);
If N = 0 then Exit (0);
Exit (1);
end;
Exit (Value) assigns Value to the function result and leaves the function
immediately. The value is type- and range-checked exactly like an
assignment "Result := Value". It works with every result type (ordinal,
real, string, pointer), inside loops, case and nested blocks.
- Plain "Exit;" is unchanged in every mode.
- Exit (x) inside a procedure gives Error 143 (Invalid procedure or
function reference).
- With C- the old Turbo Pascal meaning is kept and Exit (x) is an error.
- The Borland Pascal 7 form {$C MOVEABLE PRELOAD DISCARDABLE} (code
segment attributes for Windows/DPMI) still works: if the character after
C is not + or -, the directive is treated the TP7 way.
- Note: on the command line /$C is ignored, because the Delphi IDE passes
its own -$C+ (assertions) when it calls Blaze Pascal.
---------------------------------------------------------------------------
$D± Debug information default D+ [global]
---------------------------------------------------------------------------
D+ records line-number information in the unit (.TPU) so that run-time
errors can be located with /F<seg>:<ofs> (Find error). It does not make
the executable larger or slower; Blaze Pascal does not write debug info
into EXE files.
---------------------------------------------------------------------------
$E± 80x87 emulation default E- [global]
---------------------------------------------------------------------------
With N+, E+ links the software floating-point emulator, so programs using
Single/Double/Extended/Comp run on machines without a math co-processor.
E- requires a real 8087/80287/80387 (or a 486DX and later).
---------------------------------------------------------------------------
$F± Force FAR calls default F-
---------------------------------------------------------------------------
F+ compiles every procedure and function with the FAR call model. Needed
for procedures assigned to procedural variables, exit procedures, and
overlaid code. F- lets the compiler choose: NEAR for routines that are
only used inside their unit, FAR for routines in a unit's interface.
Individual routines can still be marked with the "far" directive.
---------------------------------------------------------------------------
$G± 80286 instructions default G+ [global]
---------------------------------------------------------------------------
G+ lets the code generator use 80286 instructions (PUSH immediate, ENTER/
LEAVE, shifts by an immediate count, ...), giving smaller and faster code.
The program then needs at least an 80286. G- generates 8086 code that
runs on any PC.
---------------------------------------------------------------------------
$H C operators += -= *= /= NEW in 7.0.2ß default H-
---------------------------------------------------------------------------
With H+, the C-style compound assignment operators are available (the same
as Free Pascal's {$COPERATORS ON}):
{$H+}
Total += Price; { Total := Total + Price }
Count -= 1; { Count := Count - 1 }
Area *= 2; { Area := Area * 2 }
Ratio /= 3; { Ratio := Ratio / 3 (real types only) }
Name += '.PAS'; { string concatenation works too }
The TMT Pascal spelling of the same operators also works with H+:
Total +:= Price; Count -:= 1; Area *:= 2; Ratio /:= 3;
"V op= E" means exactly "V := V op (E)": the whole right side is evaluated
first, so X *= A + B is X := X * (A + B). Type and range checks are the
same as for a normal assignment, so /= on an integer variable is a type
mismatch, just as I := I / 2 would be.
Note: the address of V is computed twice, so in A [F (X)] += 1 the
function F is called twice. Keep side effects out of the variable part.
With H- the character pairs are read as two separate tokens (TP7 meaning).
Delphi's {$H+} (long strings) in shared source simply enables these
operators, which is harmless. On the command line /$H is ignored.
---------------------------------------------------------------------------
$I I/O checking default I+
---------------------------------------------------------------------------
I+ checks the result of every I/O call (Reset, Rewrite, Read, Write, ...)
and stops the program with a run-time error if it failed. With I- no
check is made; call IOResult after the operation to get (and clear) the
error code:
{$I-} Reset (F); {$I+}
If IOResult <> 0 then Writeln ('File not found');
($I followed by a file name is the Include directive - see section 3.)
---------------------------------------------------------------------------
$J Writable typed constants NEW in 7.0.2ß default J+
---------------------------------------------------------------------------
A typed constant (Const Count: Integer = 0;) is really an initialized
variable. Turbo Pascal 7 always allows assigning to it; that is J+, the
default, so TP7 code is unaffected.
With J- (as in Delphi), typed constants declared while J- is active are
read-only. Reading them works; changing them gives
Error 122 (Invalid variable reference):
{$J-}
Const Limit: Integer = 10;
...
Limit := 5; { Error 122 }
Inc (Limit); { Error 122 }
The state is recorded per constant when it is declared, so {$J-} and {$J+}
can be mixed around individual const sections.
On the command line /$J is ignored (the Delphi IDE always passes -$J-).
---------------------------------------------------------------------------
$K Smart callbacks (Borland Pascal for Windows) default K- [global]
---------------------------------------------------------------------------
Accepted for compatibility with Borland Pascal 7 Windows sources. Only
meaningful for Windows targets; it has no effect on DOS programs.
---------------------------------------------------------------------------
$L Local symbol information default L+ [global]
---------------------------------------------------------------------------
With D+, L+ also records information about local variables and constants
for debuggers. (Also: {$L file.OBJ} links an object file - see section 3.)
---------------------------------------------------------------------------
$N 80x87 numeric processing default N+ [global]
---------------------------------------------------------------------------
N+ makes Real arithmetic and the Single, Double, Extended and Comp types
use 80x87 floating-point code (hardware or emulated, see $E). N- uses the
6-byte software Real only; Single/Double/Extended/Comp are not available.
---------------------------------------------------------------------------
$O Overlays allowed default O+ [global]
---------------------------------------------------------------------------
O+ generates code that is safe to place in a DOS overlay (needed for units
that will be overlaid). {$O UnitName} in the main program marks a unit to be
overlaid. Has nothing to do with optimization - see section 7.
---------------------------------------------------------------------------
$P Open string parameters default P+
---------------------------------------------------------------------------
P+ treats every "var S: String" parameter as an open string, so strings of
any declared length (String[20], String[80], ...) can be passed. P- requires
the exact string type unless $V- is used.
---------------------------------------------------------------------------
$Q Overflow checking default Q-
---------------------------------------------------------------------------
Q+ adds checks after integer +, -, *, Succ, Pred, Inc and Dec so that an
arithmetic overflow stops the program with run-time error 215 instead of
silently wrapping around. Slightly larger and slower code.
---------------------------------------------------------------------------
$R Range checking default R-
---------------------------------------------------------------------------
R+ checks array indexes, string indexes and assignments to subrange and
enumerated variables at run time (run-time error 201). Recommended while
developing; turn off for release builds if speed matters.
---------------------------------------------------------------------------
$S Stack-overflow checking default S-
---------------------------------------------------------------------------
S+ checks on entry to every procedure that enough stack space is left
(run-time error 202). Useful with deep recursion; the stack size is set
with {$M}.
---------------------------------------------------------------------------
$T Typed @ operator default T- [global]
---------------------------------------------------------------------------
T- : @X has the generic type Pointer (TP7 behaviour).
T+ : @X has the type ^T where T is the type of X, so mistakes such as
assigning the address of an Integer to a ^Real are caught.
---------------------------------------------------------------------------
$U Extended conditionals {$IF} NEW in 7.0.2ß default U-
---------------------------------------------------------------------------
With U+, the Free Pascal / Delphi conditional directives are available:
{$U+}
{$IF Defined (DPMI) and (BufferSize >= 4096)}
...
{$ELSEIF Declared (OldApi)}
...
{$ELSE}
...
{$IFEND} { {$ENDIF} is also accepted }
Expressions may use:
Values integer constants 12 $FF %1010 &17
string constants 'Ozz Nixon'
TRUE, FALSE
constants declared in the program or its units (ordinal,
Boolean, Char, enumerated and string constants)
Functions Defined (X) True if X was defined with {$DEFINE X} or /D
Undefined (X) the opposite
Declared (X) True if identifier X is declared (any kind)
Operators NOT unary - * DIV MOD SHL SHR AND
+ - OR XOR = <> < > <= >= ( )
(normal Pascal precedence; AND/OR/XOR/NOT are logical on
Boolean values and bitwise on integers; + joins strings)
An identifier that is not a known constant evaluates to 0.
{$IF} blocks nest freely with {$IFDEF}/{$IFNDEF}/{$IFOPT}. Skipped blocks are
not evaluated. {$ELSEIF} may be repeated; the first true branch is compiled.
With U- the directives give Error 17 (Invalid compiler directive), but {$IF}
blocks inside skipped {$IFDEF} sections are always nested correctly, so
source shared with FPC/Delphi compiles either way.
On the command line /$U is ignored (Delphi passes -$U-).
---------------------------------------------------------------------------
$V Var-string checking default V+
---------------------------------------------------------------------------
V+ (strict): a string passed to a var parameter must have exactly the same
declared length as the parameter. V- (relaxed) allows any string type.
---------------------------------------------------------------------------
$W Windows stack frames (Borland Pascal Windows) default W-
---------------------------------------------------------------------------
Accepted for compatibility with Borland Pascal 7 Windows sources. No
effect on DOS programs.
---------------------------------------------------------------------------
$X Extended syntax default X+ [global]
---------------------------------------------------------------------------
X+ enables the Turbo Pascal 7 extended syntax:
- functions can be called as statements, ignoring the result;
- PChar and zero-based character arrays act as null-terminated strings;
and, new in 7.0.2ß:
- Result: inside a function, Result is the function's return value. It can
be assigned AND read, unlike the function name (reading the name calls
the function recursively):
Function Sum (Const A: Array of Integer): Integer;
Var I: Integer;
begin
Result := 0;
For I := 0 to High (A) do Result := Result + A
;
end;
A variable you declare yourself called Result takes priority, so old code
using that name still works.
---------------------------------------------------------------------------
$Y Symbol reference information default Y+ [global]
---------------------------------------------------------------------------
With D+ and L+, Y+ records where every identifier is declared and used, for
browsers and IDEs.
---------------------------------------------------------------------------
$Z (reserved) default Z-
---------------------------------------------------------------------------
Reserved for a future Blaze Pascal feature. {$Z+} and {$Z-} are accepted and
currently have no effect. The Delphi / Virtual Pascal enumeration-size
forms {$Z1}, {$Z2} and {$Z4} are also accepted and currently ignored
(enumerations stay one byte when they fit, as in Turbo Pascal 7).
Spare switches: the letter Z is reserved for a future feature. The switch set
still has room for 6 more switches (with two-letter names like $AC) before
the .TPU layout would change.
===============================================================================
3. COMPILER DIRECTIVES - COMPLETE REFERENCE
===============================================================================
Conditional compilation
{$DEFINE name} {$UNDEF name} define / remove a symbol
{$IFDEF name} {$IFNDEF name} test a symbol
{$IFOPT X+} test a switch state
{$IF expr} {$ELSEIF expr} {$IFEND} NEW, needs {$U+} (see $U)
{$ELSE} {$ENDIF}
Predefined symbols: MSDOS, VER70, CPU86 and CPU87 (as in TP7), TPC32
(so source can test for this compiler), plus anything given with /D command line.
Files
{$I filename} include a source file (default extension .PAS)
{$INCLUDE filename} NEW: long form of {$I filename}
{$I %NAME%} NEW: compile-time macro - see section 4
{$L filename} link an .OBJ file (external procedures)
{$R filename} accepted and ignored (resources are not linked)
Memory and overlays
{$M stack, heapmin, heapmax} stack and heap sizes of the program
{$O UnitName} overlay a unit (main program only)
Messages NEW
{$MESSAGE 'text'} prints FILE.PAS(12) Info: text
{$MESSAGE HINT 'text'} same with Hint / WARN / ERROR / FATAL / NOTE
{$NOTE text} prints FILE.PAS(12) Note: text
{$HINT text} prints FILE.PAS(12) Hint: text
{$WARNING text} prints FILE.PAS(12) Warning: text
{$ERROR text} stops compilation with
{$FATAL text} Error 171: User defined error (text).
The text can be written plain or in quotes. Typical use:
{$IFNDEF DPMI}
{$ERROR 'This unit needs the DPMI target'}
{$ENDIF}
Compatibility
{$APPTYPE CONSOLE} accepted and ignored (Delphi source)
// line comments and /* block comments */ are accepted
"double-quoted" strings are accepted like 'single-quoted' strings
===============================================================================
4. COMPILE-TIME MACROS {$I %NAME%}
===============================================================================
As in Free Pascal, {$I %NAME%} is replaced by a string constant when the
source is compiled:
{$I %DATE%} '2026/11/09' date of compilation (YYYY/MM/DD)
{$I %TIME%} '14:05:33' time of compilation (HH:MM:SS)
{$I %FILE%} 'MYPROG.PAS' name of the current source file
{$I %LINE%} '42' current line number (as a string)
{$I %NAME%} value of environment variable NAME, or '' if not set
e.g. {$I %USERNAME%}, {$I %COMPUTERNAME%}
Example:
Const BuildStamp = 'Built ' + {$I %DATE%} + ' ' + {$I %TIME%};
begin
Writeln ('MyProg 1.0 Copyright (c) 2026 ', BuildStamp);
end.
Both comment styles work: {$I %DATE%} and (*$I %DATE%*).
The macro is expanded in place in the current source line, so the line
(after expansion) must still fit in 127 characters.
===============================================================================
5. DELPHI 2/3, TMT PASCAL AND VIRTUAL PASCAL COMPATIBILITY
===============================================================================
These help Delphi-style source compile with 7.0.2ß. None of them needs a
switch: each is either a word Turbo Pascal 7 does not know, or it is used
only where a TP7 program could not contain it.
Type names
----------
Cardinal = Word (16-bit unsigned, 0..65535 - as in Delphi 1)
SmallInt = Integer (16-bit signed)
ShortString = String (255 characters)
AnsiChar = Char
PAnsiChar = PChar
These are the same types, not new ones: a variable declared as Cardinal is
stored in the unit as System's Word, so the .TPU format is unchanged and
units stay compatible. If a program or unit declares its own type with one
of these names, that declaration is used instead.
TMT Pascal name:
MemD [Seg:Ofs] = MemL [Seg:Ofs] (32-bit memory access)
Virtual Pascal name:
SmallWord = Word
Note: Delphi 2 and later made Cardinal a 32-bit unsigned type. 7.0.2ß has no
32-bit unsigned arithmetic (Turbo Pascal 7 never had it), so Cardinal follows
the 16-bit Delphi 1 meaning. Use LongInt for larger values.
out parameters
--------------
Procedure GetSize (out Width, Height: Integer);
"out" is treated as "var": the argument is passed by reference and the
procedure sets it. (In Delphi, out only adds that the value going in is
ignored, which makes no difference for 7.0.2ß's types.)
A parameter that is itself called Out (Procedure P (Out: Integer)) still
works: "out" is only a modifier when a parameter name follows it.
resourcestring sections
-----------------------
resourcestring
SFileNotFound = 'File not found';
SDone = 'Done.';
Compiled exactly like a const section of string constants. (DOS programs
have no resources to put them in; this simply lets Delphi source compile.)
initialization / finalization
-----------------------------
A unit can now end in the Delphi way:
unit Logger;
interface
Procedure Log (Const S: String);
implementation
Var LogFile: Text;
Procedure Log (Const S: String); begin Writeln (LogFile, S) end;
initialization
Assign (LogFile, 'APP.LOG');
Rewrite (LogFile);
finalization
Close (LogFile);
end.
Allowed endings of a unit:
begin ... end. (Standard Turbo Pascal 7)
end. (no initialization)
initialization ... end.
initialization ... finalization ... end.
finalization ... end.
- initialization is the same as the unit's begin.
- finalization statements run when the program ends (normally, through
Halt, or after a run-time error), in REVERSE order of the units'
initialization - the same order Delphi uses.
- They are compiled as a hidden far procedure that the unit's initialization
installs in the ExitProc chain, exactly the way TP7 programmers install
exit procedures by hand:
__TPC32Exit := ExitProc; ExitProc := @__TPC32Fin;
and which restores ExitProc first when it runs. Hand-written exit
procedures in other units keep working and chain correctly.
- The finalization section can use everything declared in the unit's
interface and implementation sections. Errors in it are reported with
the correct file name and line number.
- The unit's final "end." must be on one line ("end" and "." together).
- In a program, initialization/finalization are not allowed (as in Delphi).
Virtual Pascal / Delphi extras
------------------------------
threadvar A threadvar section is compiled as a normal var section
(DOS programs have only one thread):
threadvar Counter: Integer;
pascal The calling-convention directive "pascal" is accepted and
ignored, because it is Turbo Pascal's own convention:
Procedure Draw (X, Y: Integer); far; pascal;
cdecl and stdcall are NOT accepted - they would need a
different parameter order and stack cleanup.
uses ... in A unit's source file can be named in the uses clause:
uses Config in 'SHARED\CONFIG.PAS', Crt;
The given file is used whenever 7.0.2ß looks for the unit's
source (with /M, /B, or when no .TPU exists). The .TPU is
still found by the unit name in the EXE/TPU directories.
{&directive} Virtual Pascal's own directives start with & and are plain
comments to TPC32, so VP sources compile unchanged.
===============================================================================
6. BUG FIXES IN THIS RELEASE
===============================================================================
- Any compile error made the compiler crash with an Access Violation
instead of printing the error. The error-recovery code jumped back with
saved CPU registers but did not restore the stack and skipped Delphi's
exception frames. Errors are now handled with a proper exception.
- Code generation did not return from intermediate-code subroutines
(GoSub/Return), which could produce wrong code for WITH statements and
expressions, and wrong ES:DI reload optimization.
- The inline assembler's expression stack had been disabled, corrupting the
stack for operands like [BX].TRec.Field, WORD PTR x, and constant
expressions in ASM blocks.
- Reading Result in an expression (Result := Result + 1) compiled as a
recursive call of the function.
- Profiler (PROFILE build) line numbers corrected throughout, and the log is
now also written when compilation stops on an error.
===============================================================================
7. NOTES FOR BUILDING TPC32 ITSELF
===============================================================================
- Regression tests: run TESTS\RUNTESTS.BAT after every change. It compiles
the test programs with TPC32, runs them in DOSBox-X, compares the output
with the expected results and reports PASS/FAIL (exit code = number of
failures). See TESTS\README.TXT for how to add tests.
- Delphi 7: dcc32 TPC32 /B (dcc32.cfg must contain -$J+)
Profiling build: dcc32 TPC32 /B -DPROFILE (writes PROFILED.LOG)
- Free Pascal: 32-bit and 64-bit targets; CPU-specific code is guarded with
{$IFDEF CPUX64} / {$IFDEF FPC}.
- The start-up banner shows the build date and time of TPC32.EXE.
===============================================================================
8. PLANNED
===============================================================================
- {$OPT+} / {$OPT-}: optional code optimizations (peephole, jump threading,
register tracking), off by default so output stays identical to TP7.
{$O} cannot be used because it controls DOS overlays.
- {$IFOPT OPT+} will work once {$OPT} exists. {$IFOPT} currently reads a
single switch letter, so it will be extended to accept the name OPT.
===============================================================================