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_ENDIANorFPC_BIG_ENDIANto 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
constorvarparameters where appropriate. CPU16,CPU32orCPU64is 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
ptruinttype 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
sysutilsunit. - 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
systemunit) 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 |
PathDelim, PathSep and DriveDelim constants defined in the sysutils unit.3 - Compiling Delphi code using Free Pascal
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.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:
- 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.cfgor.fpc.cfgin your home directory (UNIX platforms). - The fpc.cfg file does not contain the
-Fuparameter, or a wrong one. See the build faq (PDF), especially the chapters about the fpc.cfg and the directory structure. - 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
-Fustatement 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 |more10 - 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:
- 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.
- 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
- 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.