Skip to content
🎉 Free Pascal v3.2.4 is out! See Release Notes
FAQ
Pascal Language Related

Pascal Language Related

1 - Considerations in porting code to other processors

Because the compiler supports multiple processor architectures, it is important to take a few precautions so that your code will execute correctly on all processors.

  • Limit your use of asm statements unless it is time critical code.
  • Try not to rely on the endianness of the specific machines when performing operations depending on data layout. In particular, reading and writing binary data to/from files will probably require byte swaps across different endianness machines (swapendian is your friend in this case). Free Pascal defines FPC_LITTLE_ENDIAN or FPC_BIG_ENDIAN to indicate the target endianness.
  • Try limiting your local variables in subroutines to 32K, as this is the limit of some processors. Use dynamic allocation instead.
  • Try limiting the size of parameters passed to subroutines to 32K, as this is the limit of some processors. Use const or var parameters where appropriate.
  • CPU16,CPU32 or CPU64 is defined indicating whether the target is a 16-bit, 32-bit or 64-bit cpu. This can help with incorporating 16-bit, 32-bit and 64-bit specific code.
  • Use the ptruint type when declaring an ordinal that will store a pointer, since pointers can be either 32-bit or 64-bit depending on the processor and operating system. For 16-bit it is memory model dependent.
2 - Considerations in porting code to other operating systems

Because the compiler supports multiple processor architectures, it is important to take a few precautions so that your code will execute correctly on all processors.

  • File sharing is implemented differently on different operating systems, so opening already opened files may fail on some operating systems (such as Windows). The only correct way to make sure to have the same file sharing behavior is to use the I/O routines provided by the sysutils unit.
  • Clean up at the end of your program, i.e. close all files on exit, and release all allocated heap memory, as some operating systems do not like it when some things are left allocated or opened.
  • Some operating systems limit the stack space that can be allocated, therefore it is important to limit subroutine nesting, and the number of local variables. Limiting total stack space usage at a given moment to at most 256 KBytes will make porting easier.
  • Do not hardcode paths to files, try to use relative paths instead.
  • Use the following constants (defined in the system unit) to get information on files, line endings, and to build paths:
Constant Description
LineEnding Indicates the characters which end a text line
LFNSupport Indicates if long filenames are supported (more than 8.3 characters)
DirectorySeparator The character or characters that separate path components
DriveSeparator The character that separates the drive specification from the rest of the path
PathSeparator The character that separates directories in the path lists (such as the search path)
FileNameCaseSensitive Boolean indicating if the filenames for this system may be case-sensitive or not
AllFilesMask String containing a wildcard expression for all files
It is also possible to use the PathDelim, PathSep and DriveDelim constants defined in the sysutils unit.
3 - Compiling Delphi code using Free Pascal

The compiler supports Delphi-style classes. Make sure you use the -S2 or -Sd command line switches (see the manuals for the meaning of these switches), or add {$mode objfpc} or {$mode delphi} to your source code. For a list of Delphi incompatibilities also check the manual.

4 - Building a unit

It works like in Turbo Pascal. The first keyword in the file must be UNIT (not case sensitive). The compiler will generate two files: XXX.PPU and XXX.O.

  • The PPU file contains the interface information for the compiler.
  • The O-file contains the machine code (an object file, whose precise structure depends on the assembler you used).

To use this unit in another unit or program, you must include its name in the USES clause of your program.

5 - Compiling the system unit

To recompile the system unit, it is recommended to have GNU make installed. Typing make in the rtl source directory will then recompile all RTL units including the system unit. You may choose to descend into the directory of your OS (e.g. rtl/linux) and do a make there.

It is possible to do all this manually, but you need more detailed knowledge of the RTL tree structure for that.

6 - How does function overloading work?

Here is a procedure overloading example in FPC or ObjFPC mode:

procedure a(i : integer);
begin
end;

procedure a(s : string);
begin
end;

begin
    a('asdfdasf');
    a(1234);
end.
You must be careful. If one of your overloaded functions is in the interface part of your unit, then all overloaded functions must be in the interface part. If you leave one out, the compiler will complain with a “This overloaded function can’t be local” message. Overloaded functions must differ in their parameters; it is not enough if only their return types are different.
7 - Calling C functions

It is possible to call functions written in C and compiled by the GNU C compiler (GCC). E.g., for calling the C function strcmp, declare the following (the cint type is declared in the ctypes unit):

function strcmp(s1 : pchar;s2 : pchar) : cint;cdecl;external;
8 - Integrated Assembler syntax

The default assembler syntax (AT&T style) is different from the one in Borland Pascal (Intel style). FPC however supports both styles. See the documentation for more info on how to use different assembler styles.

A description of the AT&T syntax can be found in the GNU Assembler documentation.

9 - Unit system not found errors

System is Pascal’s base unit and is implicitly used by all programs. This unit defines several standard procedures and structures, and must be found to be able to compile any Pascal program by FPC.

The location of the system and other unit files is passed on to the compiler by the -Fu switch. This switch can be specified on the command line, but is usually located in the fpc.cfg configuration file.

If the compiler cannot find this unit, there are three possible causes:

  1. The fpc.cfg file is not in the same directory as the compiler executable (msdos,go32v2, win32 and OS/2) or cannot be found as /etc/fpc.cfg or .fpc.cfg in your home directory (UNIX platforms).
  2. The fpc.cfg file does not contain the -Fu parameter, or a wrong one. See the build faq (PDF), especially the chapters about the fpc.cfg and the directory structure.
  3. The unit files ARE found, but are the wrong version or for a different platform. Correct fpc.cfg to point to the right versions or reinstall the right versions (this can e.g. happen if you try to use a snapshot compiler while the -Fu statement in the used fpc.cfg still points to the RTL that came with the official release compiler).

A handy trick can be executing fpc programname -vtu. This will show where the compiler is currently looking for the unit files. You might want to pipe this through more (Dos, OS/2, Windows) or less (UNIX), since it can generate more than one screen information:

fpc programname -vt |more
10 - There is a new language extension that would be really useful. Will you include it?

Occasionally somebody asks for a new language extension on the mail list, and the discussions that follow have a recurring pattern. An extension is quite a big deal for the FPC team, and there are some criteria that are used to select if an extension is “worth” the trouble. The most important pre-selection criteria are:

  1. Compatibility must not be compromised in any way. Existing codebases on at least the Pascal level must keep running. This is often more difficult than most people think.
  2. The extension must have real value. Anything that is only a shorter notation does not apply, unless it is out of compatibility with an existing Pascal/Delphi codebase. Practically it means it must make something possible that cannot be done otherwise or be a compatibility item
  3. The change must fit in with the scope of the project: implementing a Pascal compiler with support for RAD and a generic DB system. This excludes features like inline SQL, and large garbage collected object frameworks.

Exceptions to the second rule are sometimes made for platform-specific reasons (e.g. interfacing to some other language or OS). The first rule is often a problem, because issues are not easily recognizable unless one has tried to make extensions before. Best is to make a thoroughly written proposal that the developers can review, including

  • an explanation of the feature
  • why it is needed, what does it make possible?
  • how you would implement it?
  • many examples of typical use, and tests for possible problem cases

Try to be verbose and really try to view this from the viewpoint of somebody who has to implement it, and try to make examples that span multiple units and procedures, and review what happens. Be critical, try to punch holes in your own reasoning and find possible problematic cases, and document them.

Besides these pre-selection rules and documentation, the other important question is who is going to do the work. Keep in mind that the FPC developers are volunteers with todo-lists that are booked till the next decade. You cannot expect they will drop everything from their hands and implement the feature because you need it urgently, or think it is nice. If you are not willing to implement it yourself, submit patches and maintain it in the future, chances are slim. Remarks as “this will attract a lot of users because…” are considered with a lot of skepticism, since that applies to any new development.