Porting from TP7
Porting Turbo Pascal to Free Pascal
This document contains some information about differences between Free Pascal and Turbo Pascal 7.0 (and to some extent Delphi). This list is not complete.
More documentation can be found in the Wiki, plus Porting low-level DOS code for TP/BP to GO32v2 with FPC, and the documentation.
Assembler
- The default assembler uses another syntax, but you can turn on the Intel styled assembler reader (which is what Turbo Pascal uses) using the
-Rintelcommand line option or by adding{$asmmode intel}in your source. - The 32 bit memory model requires a complete recoding of your assembler blocks in case you come from TP.
Run time library
- The
swap(),lo()andhi()intrinsics are overloaded for all integer types, rather than that they always assume a 16 bit operand. So for a 32 bit type,swapwill swap the lower and upper 16 bits, and similarlylo()resp.hi()will also return the lower resp. upper 16 bits rather than 8 bits. - To use the
PORTarray, add the Ports unit to you uses clause (only available under Dos/Go32v2 and Linux) - You can access the realmode memory using
MEM[seg:ofs], as well as MemW and MemL (only available under Dos/Go32v2) - Ofs() returns a ptrint instead of a word
- The
OVERLAYunit isn’t available - Turbo Vision support is provided by Free Vision; a clone because the original Turbo Vision is still not freely available (copyright not released by Borland).
Preprocessor / Syntax
- If you use the
-Socommand line switch (or add{$mode TP}in your source), the compiler use its Turbo Pascal compatibility mode, which will disable several of FPC’s advanced features (such as procedure overloading) to enable better compatibility with Turbo Pascal. - Nested comments are allowed, but give a Warning when found (disabled in TP mode)
Syntax
-
FARandNEARare ignored -
To get the address of a procedure to assign it to a procedure variable you must use the @-operator (in TP and Delphi mode, procedure variables work like in TP)
procedure p; begin end; var proc : procedure; begin proc:=@p; end; -
INLINEis supported by the compiler, but is used to inline Pascal code rather than machine code. -
The headers of forward declared functions/procedures always have to be completely rewritten in the definition, otherwise the compiler thinks that they are overloaded (not required if you use TP or Delphi mode).
-
There are some extra reserved words.
-
Most Delphi extensions up to Delphi 7 are supported (and also some from later Delphi versions).
Semantics
-
Records are by default aligned to the size of a cpu word; use
packed recordor{$PACKRECORDS 1}to get TP7 compatible records. A word of warning: use packed only if you absolutely need to, as non-alignment of fields may not work on non-Intel processors (and will slow down data access in all cases).type r1=record a : byte; b : word; end; r2=packed record a : byte; b : word; end; begin writeln(sizeof(r1)); { outputs 4 } writeln(sizeof(r2)); { outputs 3 } end. -
To get TP/Delphi-compatible set layouts, use the {$packset 1} directive (in FPC 2.5.1 and later, this is the default in TP/Delphi modes).
-
Function results can also be complex types like arrays or records (not in TP mode).
-
It is possible to handle the function result in a function like a variable (not in TP/Delphi mode):
function a : longint; begin a:=12; while a>4 do begin {...} end; end; -
The above example would work with TP/Delphi, but they would assume that the
a>4is a recursive call. To perform a recursive call in FPC you must append()to the function name (not required in TP/Delphi mode):function a : longint; begin a:=12; { v---- this is a recursive call } if a()>4 then begin {...} end; end; -
The exit procedure can also used with a function result as parameter:
function a : longint; begin a:=12; if a>4 then exit(a*67); end; -
Forward defined functions always have to be defined with the full header (not in TP/Delphi mode):
procedure x(v : longint);forward; procedure x; { this overloads the procedure x !!!!} begin { ... } end; { write instead: } procedure x(v : longint); begin { ... } end;
Others
- The command line parameters are different
- Not all compiler switches are fully implemented
- The units are not binary compatible
- The Overflow check also affects inc() and dec().
- The Range check not only checks array index for legal values, but also values to be in the possible range of variables. Thus if you need {$Q-} somewhere, you may need to add {$R-}.
- The search order for unit-directories and include-directories is reversed, it starts with the last directory. If you have two units with the same name, Free Pascal may use a different one than Turbo Pascal does.
- The round function does not round up at 0.5, but to the nearest even number (although SetRoundMode can be used to control the behaviour somewhat)
- the dos unit Findfirst() call must always be followed by a Findclose to release some resource.