The GNU Pascal Manual

Short Contents

Table of Contents


Next: , Up: (dir)

GNU Pascal

This manual documents how to run, install and maintain the GNU Pascal Compiler (GPC), as well as its new features and incompatibilities, and how to report bugs. It corresponds to GPC 20060325 (GCC 2.8.1, 2.95.x, 3.2.x, 3.3.x or 3.4.x).

Introduction:

Installation:

Using GNU Pascal:

Development:

Licenses:

Appendix:


Next: , Previous: Top, Up: Top

Welcome to GNU Pascal ...

...

the free 32/64-bit Pascal compiler of the GNU Compiler Collection (GNU CC or GCC). It combines a Pascal front-end with the proven GCC back-end for code generation and optimization. Other compilers in the collection currently include compilers for the Ada, C, C++, Objective C, Chill, FORTRAN, and Java languages. Unlike utilities such as p2c, this is a true compiler, not just a converter.

This version of GPC corresponds to GCC version 2.8.1, 2.95.x, 3.2.x, 3.3.x or 3.4.x.

The purpose of the GNU Pascal project is to produce a Pascal compiler (called GNU Pascal or GPC) which

Pascal was originally designed for teaching. GNU Pascal provides a smooth way to proceed to challenging programming tasks without learning a completely different language.

The current release implements Standard Pascal (ISO 7185, levels 0 and 1), most of Extended Pascal (ISO 10206, aiming for full compliance), is highly compatible to Borland Pascal (version 7.0), has some features for compatibility to other compilers (such as VAX Pascal, Sun Pascal, Mac Pascal, Borland Delphi and Pascal-SC).

It provides a lot of useful GNU extensions not found in other Pascal compilers, e.g. to ease the interfacing with C and other languages in a portable way, and to work with files, directories, dates and more, mostly independent of the underlying operating system.

Included units provide support for regular expressions, arithmetic with integer, rational and real numbers of unlimited size, internationalization, inter-process communication, message digests and more. Demo programs show the usage of these units and of many compiler features.

This manual contains

If you are familiar with Standard Pascal (ISO 7185) programming, you can probably just go ahead and try to compile your programs. Also, most of the ISO Extended Pascal Standard (ISO 10206) is implemented into GNU Pascal. The Extended Pascal features still missing from GPC are set types with variable bounds and discriminated ordinal schema as schema discriminants.

If you are a Borland Pascal programmer, you should probably start reading the QuickStart guide from BP to GNU Pascal, see Borland Pascal. If you are curious about the new features GPC offers, you can get an idea in the overview of GPC highlights (see Highlights), and read in more detail about them in the Programmer's Guide to GPC (see Programming) and in the alphabetical GPC Language Reference (see Reference).

And, please, think about how you can contribute to the GNU Pascal project, too. Please support our work by contributing yours in form of example programs, bug reports, documentation, or even actual improvements of the compiler.

All trademarks used in this manual are properties of their respective owners.


Next: , Previous: Welcome, Up: Top

1 Some of GPC's most interesting features.

The GNU Pascal Compiler (GPC) is, as the name says, the Pascal compiler of the GNU family (http://www.gnu.org/software/gcc/). This means:

The compiler supports the following language standards and quasi-standards:

Some highlights:

The demo programs mentioned above are available both on the WWW and in GPC source and binary distributions.

Disadvantages:

Co-workers welcome!

Able, committed programmers are always welcome in the GNU Pascal team. If you want to be independent of companies that you have to pay in order to get a compiler with more restrictive licensing conditions that only runs on one operating system, be invited to join the development team, Acknowledgments.


Next: , Previous: Highlights, Up: Top

2 New Features of GNU Pascal.

GPC's new or changed features since the last (non alpha/beta) GPC release are listed here. Items without further description refer to new routines, variables or options.

Features implemented for compatibility to other compilers are marked with, e.g., `(B)' for BP compatibility.

A few old and obsolete features have been dropped or replaced by cleaner, more flexible or otherwise more useful ones. This might lead to minor problems with old code, but we suppose they're rare and easy to overcome. Backward-incompatible changes are marked with `(@)'.

Have fun,

The GNU Pascal Development Team


Next: , Previous: News, Up: Top

3 The GNU Pascal Frequently Asked Questions List.

This is the Frequently Asked Questions List (FAQ) for GNU Pascal. If the FAQ and the documentation do not help you, you have detected a bug in it which should be reported, Mailing List. Please really do it, so we can improve the documentation.


Next: , Up: FAQ

3.1 GNU Pascal


Next: , Up: GNU Pascal

3.1.1 What and why?

The purpose of the GNU Pascal project is to produce a Pascal compiler (called GNU Pascal or GPC) which

Pascal was originally designed for teaching. GNU Pascal provides a smooth way to proceed to challenging programming tasks without learning a completely different language.

The current release implements Standard Pascal (ISO 7185, levels 0 and 1), most of Extended Pascal (ISO 10206, aiming for full compliance), is highly compatible to Borland Pascal (version 7.0), has some features for compatibility to other compilers (such as VAX Pascal, Sun Pascal, Mac Pascal, Borland Delphi and Pascal-SC).

It provides a lot of useful GNU extensions not found in other Pascal compilers, e.g. to ease the interfacing with C and other languages in a portable way, and to work with files, directories, dates and more, mostly independent of the underlying operating system.

Included units provide support for regular expressions, arithmetic with integer, rational and real numbers of unlimited size, internationalization, inter-process communication, message digests and more. Demo programs show the usage of these units and of many compiler features.


Next: , Previous: What and why, Up: GNU Pascal

3.1.2 What is the current version?

The current version is 20060325.

Releases are available as a source archive and precompiled binaries for several common platforms from the GPC web site, http://www.gnu-pascal.de.

For details about new features, see the section `News' on the web site. On bugs fixed recently, see the `Done' section of the To-Do list (on the same web site).

GPC uses GCC as a back-end. It supports GCC version 2.8.1, 2.95.x, 3.2.x, 3.3.x or 3.4.x. (The newest supported GCC version is usually preferable, unless it contains serious bugs in itself.)

There are no fixed time frames for new releases. Releases are made when enough interesting changes have been made and the compiler is somewhat stable.


Next: , Previous: Current version, Up: GNU Pascal

3.1.3 Is it compatible with Turbo Pascal (R)?

GPC is not a drop-in replacement for Borland's Turbo Pascal (R). Almost all BP language features are supported. Notable exceptions are the string format (as discussed below), or the `Mem' and `Port' pseudo arrays, though replacement functions for the latter on IA32 platforms exist in the `Ports' unit.

Almost all of BP's run time library is supported in GPC, either by built-in compiler features or in units with the same names as their BP counterparts.

For details about the compatibility, the few remaining incompatibilities and some useful alternatives to BP features, see the `Borland Pascal' chapter in the GPC Manual. (see Borland Pascal)


Previous: Turbo Pascal compatibility, Up: GNU Pascal

3.1.4 Which platforms are supported by GNU Pascal?

GPC uses the GCC backend, so it should run on any system that is supported by GNU CC. This includes a large variety of Unix systems, MS-DOS, OS/2 and Win32. A full list of platforms supported by GCC can be found in the file INSTALL of the GCC distribution. Not all of these have actually been tested, but it is known to run on these platforms:

ix86-gnu (GNU Hurd)
ix86-linux (Linux 2.x, ELF)
Linux/AMD64
i486-linuxaout
i486-linuxoldld
i386-freebsd1.2.0
AIX 4.2.1
AIX 4.3
DJGPP V2 (Dos)
EMX 0.9B (OS/2, Dos)
Cygwin32 beta20 and higher (MS-Windows95/98, MS-Windows NT)
mingw32 (MS-Windows95/98, MS-Windows NT)
MSYS (MS-Windows)
Mac OS/X 10.3
mips-sgi-irix5.3
mips-sgi-irix6.5
sun-sparc-sunos4.1.4
sparc-sun-solaris2.x
sun-sparc-solaris 2.5.1
sun-sparc-solaris 2.6
sun-sparc-solaris 7
sun-sparc-solaris 8
alpha-unknown-linux
alpha-dec-osf4.0b
s390-ibm-linux-gnu

OK people – send us your success stories, with canonical machine name!


Next: , Previous: GNU Pascal, Up: FAQ

3.2 Installing GPC

You find the most up-to-date installation instructions in the GPC Manual or the file `INSTALL' in source distributions, or on the GPC web site. (see Installation)

The following sections describe things you might need or want to install besides GPC itself.


Next: , Up: Installing GPC

3.2.1 What to read next

After installing GPC, please check the files in the directory /usr/local/doc/gpc:

README General Information about GPC
FAQ This FAQ :−)
NEWS Changes since the last release
BUGS How to report bugs, about the Test Suite
AUTHORS List of GPC authors
COPYING The GNU General Public License
COPYING.LIB The GNU Lesser General Public License


Next: , Previous: Documentation files, Up: Installing GPC

3.2.2 Which components do I need to compile Pascal code?

A complete Pascal compiler system should at least have:

  1. The actual compiler, GPC.
  2. An editor, assembler, linker, librarian and friends.
  3. A C library. If you have a working C compiler, you already have this.
  4. A debugger, if you want to debug your programs.

For most people, the GNU binutils and GNU debugger (`gdb') are a good choice, although some may prefer to use vendor specific tools.


Next: , Previous: Components, Up: Installing GPC

3.2.3 How do I debug my Pascal programs?

To debug your programs, (a) GNU Pascal must be able to generate executables with debug info for your platform, and (b) you must have a debugger which understands this.

The bottom line: if you can debug GCC compiled programs, you should be able to do this with GPC too.

The GNU debugger (`gdb') currently does not have a “Pascal” mode, so it is unable to display certain Pascal structures etc. When debugging, please note that the Initial Letter In Each Identifier Is In Upper Case And The Rest Are In Lower Case. If you want to display variable `foo' in the debugger, type `show Foo' or `display Foo' instead.

Although `gdb' is an excellent debugger, it's user interface is not everybody's preference. If you like to debug under X11, please refer to the comp.windows.x FAQ: “Where can I get an X-based debugger?” at:
http://www.faqs.org/faqs/x-faq/part6/section-2.html

Some useful frontends include: XXGDB, tGDB and XWPE. See:
http://www.ee.ryerson.ca:8080/~elf/xapps/Q-IV.html

Very nice, but resource consuming is the Motif based DDD:
http://sol.ibr.cs.tu-bs.de/softech/ddd/

Furthermore, RHIDE (see IDE) contains built-in debugging suport, similar to the IDE of BP.


Next: , Previous: Debugger, Up: Installing GPC

3.2.4 What additional libraries should I have?

You will need certain additional libraries when you compile some of the units. These can be found in the directory http://www.gnu-pascal.de/libs/.

Currently, there are the following libraries:

gmp
Arithmetic for integers, rationals and real numbers with arbitrary size and precision. Used by the GMP unit.
rx
Regular expression matching and substitution. Used by the RegEx unit.
ncurses
PDCurses
Screen handling. Used by the CRT unit. Depending on your system, you have the following choices:

Unix: You can compile terminal applications with ncurses and applications that run in an X11 window with PDCurses (though terminal applications can, of course, also run in an xterm under X11). ncurses is used by default. If you want to use PDCurses (a.k.a. XCurses), give the option `-DX11' when compiling CRT.

Dos with DJGPP and MS-Windows with mingw: Only PDCurses is available and will be used by default.

MS-Windows with Cygwin: PDCurses and ncurses are available. PDCurses is used by default. If you want to use ncurses, give the option `-DUSE_NCURSES' when compiling CRT.

Other systems: Please see the READMEs and installation instructions of PDCurses and ncurses to find out which one(s) can be built on your system. See the conditionals at the end of crt.inc and crtc.h (and change them if necessary) on which library is used by default.

intl
Internationalization. Used by the Intl unit. On some systems, it is part of the system library (libc).
ElectricFence
This library is not used by any GPC unit. It is a debugging tool to assist you in finding memory allocation bugs. To use it, just link it to your program, either on the command line (`-lefence') or in the source code (`{$L efence}') which you might want to put into an `{$ifdef DEBUG}' or similar since using libefence is only recommended for debugging.

The source code of the libraries is available in the main `libs' directory. Most libraries come with one or several patches which should be applied before compiling them.

Binaries for some platforms are available in the binary/platform subdirectories. If you compile the libraries for other platforms, be invited to make the binaries available to us for distribution on the web site.

There are also the following files:

terminfo-linux.tar.gz
This is a patch to enable ncurses programs to make use of the ability of Linux 2.2 and newer kernels to produce a block cursor when needed. The present patch can be installed without recompiling anything, just by copying some files into place. More details can be found in the README file included in this archive. The patch will not do any harm on older kernels. Please note that not only on Linux machines it is useful to install the patch. Installing them on any other machine will allow users who telnet in from a Linux console to profit from the block cursor capability. Besides, some Unix systems have installed older Linux terminfo entries or none at all, so it's a good thing, anyway, to give them a current version. The patch is included in the terminfo database of ncurses 5.0, so if you install ncurses 5.0 (source or binary), you don't need to get the patch separately. But you can install it on a system with an older ncurses version if you don't feel like upgrading ncurses altogether.
tsort-2.9i.zip
A little utility (extracted from util-linux-2.9i, but not Linux specific), needed for the configuration of the rx library. You need it only if you compile rx yourself (and if it's not already present on your system), not when using a rx binary.


Next: , Previous: Libraries, Up: Installing GPC

3.2.5 Contributed units

Several people have contributed units for GPC. They are usually announced on the mailing list, Mailing List. Most of them can be found in http://www.gnu-pascal.de/contrib/.


Previous: Contributed units, Up: Installing GPC

3.2.6 Can you recommend an IDE?

Users of Borland Pascal may wonder if there's a replacement for the IDE (Integrated Development Environment). Here's a few suggestions:


Next: , Previous: Installing GPC, Up: FAQ

3.3 GNU Pascal on the DJGPP (MS-DOS) platform

This chapter discusses some potential problems with GNU Pascal on MS-DOS, using DJGPP.


Next: , Up: GPC on DJGPP

3.3.1 What is DJGPP?

The following paragraph is from the site http://www.delorie.com/djgpp/:

DJGPP is a complete 32-bit C/C++ development system for Intel 80386 (and higher) PCs running DOS. It includes ports of many GNU development utilities. The development tools require a 80386 or newer computer to run, as do the programs they produce. In most cases, the programs it produces can be sold commercially without license or royalties.


Next: , Previous: What is DJGPP, Up: GPC on DJGPP

3.3.2 If you need more information

GPC/DJGPP is a DJGPP V2 application, and most of the DJGPP documentation applies for GPC too. A great source of information is the DJGPP FAQ: http://www.delorie.com/djgpp/v2faq/230b.zip

Another place to look for DJGPP documentation is the DJGPP Knowledge Base, at this URL: http://www.delorie.com/djgpp/doc/kb/


Next: , Previous: DJGPP FAQ, Up: GPC on DJGPP

3.3.3 What do I download?

As discussed in Components, other than GPC itself, you need an assembler, linker and friends, a C library and possibly a debugger. The site http://www.delorie.com/djgpp/ recommended the following files and they will help you find a mirror:

v2/djdev203.zip (C library)
v2gnu/bnu2951b.zip (assembler, ...)
v2gnu/gcc2952b.zip (gcc)
v2gnu/gdb418b.zip (debugger)
v2gnu/mak379b.zip (make)
v2gnu/txi40b.zip (texi)

This list is about 10 MB not counting GPC. You can use a binary version of GPC from the web site.


Next: , Previous: DJGPP download, Up: GPC on DJGPP

3.3.4 How do I install the compiler?

If you don't have DJGPP installed on your harddisk, create a directory for GNU Pascal (c:\gpc), and unzip the archives. Make sure you preserve the directory structure (use `pkunzip -d'). Now, add the directory where gpc.exe lives (c:\gpc\bin) to your path and set the DJGPP environment variable to point to your djgpp.env file:

     set DJGPP=c:\gpc\djgpp.env

Then, add this to your djgpp.env file:

     ---------------------------------------------------------
     [gpcpp]
     C_INCLUDE_PATH=%/>;C_INCLUDE_PATH%%DJDIR%/lang/pascal;%DJDIR%/include
     
     [gpc]
     COMPILER_PATH=%/>;COMPILER_PATH%%DJDIR%/bin
     LIBRARY_PATH=%/>;LIBRARY_PATH%%DJDIR%/lib;%DJDIR%/contrib/grx20/lib
     ---------------------------------------------------------

The GPC online documentation is in GNU info format; you need the Info reader (txi390b.zip) to read it, or use the built-in Info reader of the RHIDE or PENG IDE. To add the GPC documentation to the info directory file, edit the c:\gpc\info\dir file, and locate this section:

     ---------------------------------------------------------
     * GCC: (gcc.inf).
     The GNU C, C++, and Objective-C Compiler
     
     * GDB: (gdb.inf).
     The GNU Debugger (gdb and gdb-dpmi).
     
     ---------------------------------------------------------

To add GPC, change it to look like this:

     ---------------------------------------------------------
     * GCC: (gcc.inf).
     The GNU C, C++, and Objective-C Compiler
     
     * GPC: (gpc.inf).
     The GNU Pascal Compiler
     
     * GDB: (gdb.inf).
     The GNU Debugger (gdb and gdb-dpmi).
     
     ---------------------------------------------------------

Specific information for low-memory conditions and more can be found in the DJGPP FAQ and documentation.


Next: , Previous: Installing GPC on DJGPP, Up: GPC on DJGPP

3.3.5 I cannot read the Info documentation!

To read the Info documentation, you need the `info' program from txi390b.zip or an IDE like RHIDE or PENG.


Next: , Previous: DJGPP Info reader, Up: GPC on DJGPP

3.3.6 GPC says: no DPMI

You don't have a DPMI server installed, and DJGPP v2 requires it to run. You can either use one of the commercial DPMI servers (e.g., run `gpc' in a DOS box under MS-Windows) or download and install CWSDPMI (csdpmi3b.zip) which is a free DPMI server written for DJGPP.


Next: , Previous: DJGPP DPMI server, Up: GPC on DJGPP

3.3.7 I have troubles with assembly code

The GNU Assembler (as.exe), or gas, called by GCC accepts “AT&T” syntax which is different from “Intel” syntax. Differences are discussed in section 17.1 of the DJGPP FAQ.

A guide is available which was written by Brennan Mr. Wacko Underwood brennan@mack.rt66.com and describes how to use inline assembly programming with DJGPP, at this URL: http://www.delorie.com/djgpp/doc/brennan/brennan_att_inline_djgpp.html

There's also a GPC assembler tutorial at
http://www.gnu-pascal.de/contrib/misc/gpcasm.zip

Section 17.3 of the DJGPP FAQ discusses some methods to convert “Intel” syntax to “AT&T” syntax.

However, please note that assembler code is unportable, i.e. it will work on IA32 (“x86”) and compatible processors if written for them, but will not even compile for other processors. So by writing assembler code in your programs, you will limit their usefulness substantially.

If you think you “need” assembler code for speed – and you've checked that your assembler code actually runs faster than Pascal code compiled with suitable optimizations – you might want to put both Pascal and assembler versions of the critical sections in your program, and let, e.g., an `{$ifdef i386}' decide which one to use. This way, your program will at least compile on all processors.


Next: , Previous: Assembler syntax, Up: GPC on DJGPP

3.3.8 Tell me how to do DPMI, BIOS and other DOS related things.

DPMI, BIOS and other functions are no different than other system functions. Refer to the GPC Manual on how to access your system's C-library. This small example shows how to use DPMI, copying some structures and function prototypes of `<dpmi.h>':

     program DPMIDemo;
     
     { Only for DJGPP }
     
     {$X+}
     
     { `Byte' is `unsigned char' in C,
       `ShortCard' is `unsigned short' in C,
       `MedCard' is `unsigned long' in C,
       `Word' is `unsigned' in C,
       etc. (all these types are built-in). }
     
     type
       TDpmiVersionRet = record
         Major     : Byte;
         Minor     : Byte;
         Flags     : ShortCard;
         CPU       : Byte;
         Master_PIC: Byte;
         Slave_PIC : Byte;
       end;
     
     type
       TDpmiFreeMemInfo = record
         LargestAvailableFreeBlockInBytes,
         MaximumUnlockedPageAllocationInPages,
         MaximumLockedPageAllocationInPages,
         LinearAddressSpaceSizeInPages,
         TotalNumberOfUnlockedPages,
         TotalNumberOfFreePages,
         TotalNumberOfPhysicalPages,
         FreeLinearAddressSpaceInPages,
         SizeOfPagingFilePartitionInPages,
         Reserved1,
         Reserved2,
         Reserved3: MedCard;
       end;
     
     function DpmiGetVersion (var Version: TDpmiVersionRet): Integer;
              external name '__dpmi_get_version';
     
     function DpmiGetFreeMemoryInformation
              (var MemInfo: TDpmiFreeMemInfo): Integer;
              external name '__dpmi_get_free_memory_information';
     
     var
       Version: TDpmiVersionRet;
       MemInfo: TDpmiFreeMemInfo;
     
     begin
       if DpmiGetVersion (Version) = 0 then
         begin
           WriteLn ('CPU type:       ', Version.CPU, '86');
           WriteLn ('DPMI major:       ', Version.Major);
           WriteLn ('DPMI minor:       ', Version.Minor);
         end
       else
         WriteLn ('Error in DpmiGetVersion');
       if DpmiGetFreeMemoryInformation (MemInfo) = 0 then
         WriteLn ('Free DPMI memory: ',
                  MemInfo.TotalNumberOfFreePages, ' pages.')
       else
         WriteLn ('Error in DpmiGetMemoryInformation');
     end.


Previous: DJGPP specific code, Up: GPC on DJGPP

3.3.9 I got an exception when accessing an `array [1 .. 4000000] of Byte'.

Per default, the maximum stack size of a DJGPP application is 256K. If you need more, you have to adjust it with the stubedit program, i.e.:

     stubedit your_app.exe minstack=5000K

Another way is to add the following code to your program to define a minimum stack size (here: 2 MB). This value will be honored even if a user sets a lower value by using stubedit, so this method might be a little safer. (The linker name `_stklen' is essential; the Pascal identifier doesn't matter. The constant doesn't have to be used anywhere in the program. It is recommended to put this declaration in the main program file, not in any unit/module, so programs using a unit/module can set whatever limit they need.)

     {$ifdef __GO32__}
     const
       MinStackSize: Cardinal = $200000; attribute (name = '_stklen');
     {$endif}

Still, it might be a good idea to use pointers for large structures, and allocate the memory at runtime.

DJGPP has to allocate the stack in physical memory at program startup, so one might have to be careful with too large stack limits. Most other systems allocate stack pages on demand, so the only reason to set a limit at all might be to prevent a runaway recursion from eating up all memory ...

On Unix-like systems, you can set a resource limit, but you usually don't do it in normal programs, but rather in the shell settings (bash: `ulimit'; csh: `limit'; syscall: `setrlimit'(2)).


Next: , Previous: GPC on DJGPP, Up: FAQ

3.4 Strings


Next: , Up: Strings in GPC

3.4.1 What's this confusion about strings?

Turbo Pascal strings have a length byte in front. Since a byte has the range 0 .. 255, this limits a string to 255 characters. However, the Pascal string schema, as defined in section 6.4.3.3.3 of the ISO 10206 Extended Pascal standard, is a schema record:

     type
       String (Capacity: Integer) = record
         Length: 0 .. Capacity;
         String: packed array [1 .. Capacity + 1] of Char
       end;

The `+ 1' is a GPC extension to make it feasible to automatically add the `#0' terminator when passing or assigning them to CStrings. Thus at the expense of a little added complexity (must declare capacity, don't use `GetMem' without explicit initialization of the `Capacity' field, and the additional space requirement) you can now have very long strings.


Next: , Previous: String schema, Up: Strings in GPC

3.4.2 Overlaying strings in variant records

Q: Should the different variants in a variant record overlay in the same memory? Previous Pascals I have used have guaranteed this, and I've got low-level code that relies on this. The variants are not the same length, and they are intended not to be.

A: No, this is intentional so that the discriminants are not overwritten, and they can be properly initialized in the first place. Consider:

     record
     case Boolean of
       False: (s1: String (42));
       True:  (s2: String (99));
     end;

If the strings would overlay, in particular their discriminants would occupy the same place in memory. How should it be initialized? Either way, it would be wrong for at least one of the variants ...

So, after a discussion in the ISO Pascal newsgroup where this topic came up concerning file variables (which also require some automatic initialization and finalization), we decided to do this in GPC for all types with automatic initialization and finalization (currently files, objects and schemata, including strings, in the future this might also be Delphi compatible classes and user-defined initialized and finalized types), since the standard does not guarantee variants to overlay, anyway ...

There are two ways in GPC to get guaranteed overlaying (both non-standard, of course, since the standard does not assume anything about internal representations; both BP compatible), `absolute' declarations and variable type casts. E.g., in order to overlay a byte array `b' to a variable `v':

     var
       b: array [1 .. SizeOf (v)] of Byte absolute v;

Or you can use type-casting:

     type
       t = array [1 .. SizeOf (v)] of Byte;

then `t (v)' can be used as a byte array overlayed to `v'.


Next: , Previous: Strings in variant records, Up: Strings in GPC

3.4.3 Why does `s[0]' not contain the length?

Q: In standard Pascal you expect `s[1]' to align with the first character position of `s' and thus one character to the left is the length of `s'. Thus `s[0]' is the length of `s'. True?

A: This holds for UCSD/BP strings (which GPC does not yet implement, but that's planned). The only strings Standard Pascal knows are arrays of char without any length field.

GPC also supports Extended Pascal string schemata (see String schema), but they also don't have a length byte at “position 0”, but rather a `Length' field (which is larger than one byte).


Next: , Previous: Length byte, Up: Strings in GPC

3.4.4 Watch out when using strings as parameters

Q: Any “gotchas” with string parameters?

A: Be careful when passing string literals as parameters to routines accepting the string as a value parameter and that internally modify the value of the parameter. Inside the routine, the value parameter gets a fixed capacity – the length of the string literal that was passed to it. Any attempt to assign a longer value will not work.

This only applies if the value parameter is declared as `String'. If it is declared as a string with a given capacity (e.g., `String (255)'), it gets this capacity within the routine.


Next: , Previous: Strings as value parameters, Up: Strings in GPC

3.4.5 Support for BP compatible short strings

Q: Two different kinds of strings with the same name – `String' – does make a bit of confusion. Perhaps the oldstyle strings could be renamed `short string' ?

A: When we implement the short strings, we'll have to do such a distinction. Our current planning goes like this:

`String (n)': string schema (EP compatible)

`String [n]': short string (UCSD/BP compatible, where n must be <= 255)

`String': dependent on flags, by default undiscriminated schema, but in BP mode (or with a special switch) short string of capacity 255 (UCSD/BP compatible).

Q: So when will these short strings be available?

A: It's been planned for some years. The delay has been caused by more pressing problems.


Previous: Short strings, Up: Strings in GPC

3.4.6 What about C strings?

A C string (`char *') is an array of char, terminated with a `#0' char.

C library functions require C, not Pascal style string arguments. However, Pascal style strings are automatically converted to C style strings when passed to a routine that expects C style strings. This works only if the routine reads from the string, not if it modifies it.

E.g., this is how you could access the `system()' call in your C library (which is not necessary anymore, since `Execute' is already built-in):

     program SysCall;
     
     function System (CmdLine: CString): Integer; external name 'system';
     
     var
       Result: Integer;
     
     begin
       Result := System ('ls -l');
       WriteLn ('system() call returned: ', Result)
     end.

You could use the type `PChar' instead of `CString'. Both `CString' and `PChar' are predefined as `^Char' – though we recommend `CString' because it makes it clearer that we're talking about some kind of string rather than a single character.

A lot of library routines in Pascal for many applications exist in the GPC unit and some other units. Where available, they should be preferred (e.g. `Execute' rather than `system()', and then you won't have to worry about `CString's.)

Do not pass a C style string as a `const' or `var' argument if the C prototype says `const char *' or you will probably get a segfault.


Next: , Previous: Strings in GPC, Up: FAQ

3.5 Getting Help

Please read the GPC Manual (info files or other formats) as well as the README and BUGS files that come with GPC (usually installed in directory /usr/local/doc/gpc), plus other docs that might help (the DJGPP FAQ if you use DJGPP, etc.) before you send email to the maintainers or mailing list.

In particular, the BUGS file contains information on how to submit bug reports in the most efficient way.

The `Support' chapter of the GPC Manual tells you where to find more information about GPC and how to contact the GPC developers. (see Support)


Previous: Getting Help, Up: FAQ

3.6 Miscellaneous


Next: , Up: Miscellaneous FAQ

3.6.1 I want to contribute; where do I start?

If you want to contribute, please write to the mailing list, Mailing List.


Next: , Previous: Contributing, Up: Miscellaneous FAQ

3.6.2 Where is the GNU Pascal web site?

The GPC homepage on the web, for information and downloads, is
http://www.gnu-pascal.de.

The GPC To-Do list, listing the latest features and fixed bugs can also be found there.


Previous: GPC web site, Up: Miscellaneous FAQ

3.6.3 About this FAQ

Current Maintainer: Russ Whitaker, russ@ashlandhome.net

This is the second incarnation of the GNU Pascal FAQ list, based on the previous FAQ by J.J. van der Heijden. Comments about, suggestions for, or corrections to this FAQ list are welcome.

Please make sure to include in your mail the version number of the document to which your comments apply (you can find the version at the beginning of this FAQ list).

Many people have contributed to this FAQ, only some of them are acknowledged above. Much of the info in, and inspiration for this FAQ list was taken from the GPC mailing list traffic, so you may have (unbeknownst to you) contributed to this list.


Next: , Previous: FAQ, Up: Top

4 How to download, compile and install GNU Pascal.


Next: , Up: Installation

4.1 Where and what to download

You can download the source code of the current GNU Pascal release from

     http://www.gnu-pascal.de/current/

and binaries for some platforms from

     http://www.gnu-pascal.de/binary/

The binary archive files are named gpc-version.platform.extension – for example `gpc-2.1.alpha-unknown-linux-gnu.tar.gz' for GPC version 2.1 on an Alpha workstation running the Linux kernel with GNU C Library, or `gpc-20000616.i386-pc-msdosdjgpp' for GPC version 20000616 on an Intel IA32 compatible PC running DOS with DJGPP.

After you have downloaded the correct archive file for your platform, please read the installation notes on how to install such a binary distribution.

If you are running Dos or MS Windows, you will need additional tools – see “What else to download and where” below.

Current snapshots

GNU Pascal is subject to steady development. Alpha and beta snapshots (source only, use at your own risk) can be found at:

     http://www.gnu-pascal.de/alpha/
     http://www.gnu-pascal.de/beta/

What else to download and where

When you are using GNU Pascal on a DOS system, you will need either the DJGPP or the EMX development environment (see below). On an OS/2 system, you will need EMX. On an MS Windows 95/98/NT system you will need either the CygWin or the mingw32 ot the MSYS environment.

GNU Pascal uses the compiler back-end from the GNU Compiler Collection, GNU CC or GCC. If you want to compile GPC, you will need the source of GCC as well as the source of GPC itself. From the same place as GPC, please download GCC 2.8.1, 2.95.x, 3.2.x, 3.3.x or 3.4.x. (It is also available from any GNU mirror; see http://www.gnu.org/software/gcc/.)

Libraries

For some of GPC's units, you will need some standard libraries. In particular:

Unit Platform Library
CRT Unix/terminal ncurses >= 5.0 (1), (2)
CRT Unix/X11 PDCurses (2)
CRT Dos, MS-Windows PDCurses (3)
GMP any gmp
RegEx any rx
(debugging) Unix, MS-Windows ElectricFence (4)

Notes:

(1) ncurses version 5.0 or newer is strongly recommended because older versions contain a bug that severely affects CRT programs.

(2) You can install both ncurses and PDCurses on a Unix system, and choose at compile time whether to generate a terminal or X11 version of your program.

(3) ncurses also runs under MS-Windows with CygWin (not mingw32, however), but doesn't appear to behave much differently from PDCurses on that platform.

(4) ElectricFence is not used by any unit, but can be used for debugging memory allocation bugs by simply linking it (see the accompanying documentation).

You can find those libraries on many places on the Net. Also, many GNU/Linux distributions, DJGPP mirrors and other OS distributions already contain some of the libraries. In any case, you can find the sources of the libraries (sometimes together with patches that you should apply before building if you choose to build from the sources) and binaries for some platforms in

     http://www.gnu-pascal.de/libs/

For more information and descriptions of these libraries, see Libraries.

DJGPP

DJGPP is available from any SimTel mirror in the gnu/djgpp subdirectory; for addresses look into the DJGPP FAQ. To use GNU Pascal you need at least

We also recommend you to get:

EMX

EMX is an environment for creating 32-bit applications for DOS and OS/2. To develop EMX programs with GNU Pascal you need at least

If your DOS box has DPMI (it does if you are using MS Windows or OS/2) you will also need RSX, available from the same sites as EMX in the subdirectory rsxnt.

The GNU development tools contain the GNU C compiler which is in fact not needed to use GNU Pascal. However, the C library is needed.

CygWin

CygWin is an environment which implements a POSIX layer under MS Windows, giving it large parts of the functionality of Unix. CygWin contains development tools such as an assembler, a linker, etc. GPC needs for operation. More information about CygWin can be found at

     http://cygwin.com

mingw32

The Minimalists' GNU Win32 environment, mingw32, allows a large number of Unix programs – including GPC and GCC – to run under MS Windows 95/98/NT using native MS libraries. mingw32 ressources can be found at

     http://www.mingw.org


Next: , Previous: Download, Up: Installation

4.2 Installation instructions for a GPC binary distribution

To install a binary distribution, cd to the root directory and unpack the archive while preserving the stored directory structure. Under a Unix compatible system with GNU tar installed, the following (performed as `root') will do the job:

     # cd /
     # tar xzf archive.tar.gz

If you are using a `tar' utility other than GNU tar, it might be necessary to do the above in an explicit pipe:

     # cd /
     # gzip -c -d archive.tar.gz | tar xf -

Some binary distributions are now distributed packed with `bzip2'. You can recognize them by their file name suffix .bz2 instead of .gz. For such archives, make sure you have `bunzip2' installed and then use the following command:

     # cd /
     # tar xjf archive.tar.bz2

Or:

     # cd /
     # bunzip2 -c -d archive.tar.bz2 | tar xf -

If you want to install a GPC binary distribution in another directory than it was prepared for (for example, if you do not have root access to the computer and want to install GPC somewhere under your home directory), you can do the following:

To install a ZIP archive under DOS with `PKunzip', `cd' to the appropriate directory (usually `\' for EMX, `\DJGPP' for DJGPP), then call `PKunzip' with the `-d' option:

     C:\> cd djgpp
     C:\DJGPP> pkunzip -d archive.zip

where archive.zip is the name of the distribution file.

For DJGPP you must edit your djgpp.env in the DJGPP directory to complete the installation: Please copy the entries from `[gcc]' to create a new `[gpc]' section. The result may look as follows:

     [gcc]
     COMPILER_PATH=%/>;COMPILER_PATH%%DJDIR%/bin
     LIBRARY_PATH=%/>;LIBRARY_PATH%%DJDIR%/lib
     
     [gpc]
     COMPILER_PATH=%/>;COMPILER_PATH%%DJDIR%/bin
     LIBRARY_PATH=%/>;LIBRARY_PATH%%DJDIR%/lib

If you are using the DJGPP version of GPC but do not have a DJGPP directory, please download and install DJGPP (see Download).

Binary distributions include libgcc.a and specs, files that are normally part of GCC. If you have GCC installed, they will be replaced unless you manually install the archive.


Next: , Previous: Binary Distributions, Up: Installation

4.3 Compiling GPC

The preferred way to distribute GNU software is distribution of the source code. However, it can be a non-trivial exercise to build GNU Pascal on some non-Unix systems, so we also provide ready-to-run binaries for a number of platforms. (See Binary Distributions for how to install a binary distribution.)

GPC is based on the GNU Compiler Collection, GNU CC or GCC. You will need the GCC sources to build it. It must be the same version as the one GPC is implemented with – 2.8.1, 2.95.x, 3.2.x, 3.3.x or 3.4.x as of this writing. Although you need GCC to build the GNU Pascal compiler, you don't need GCC to compile Pascal programs once GNU Pascal is installed. (However, using certain libraries will require compiling C wrappers, so it is a good idea to install the C compiler as well.)

Because GNU Pascal shares its back-end with GCC, it should run on any system supported by GCC. A full list of platforms supported by GCC can be found in the GCC installation instructions.

The GCC source can be obtained from any mirror of the GNU FTP site, ftp://ftp.gnu.org/gnu/gcc/. The “core” distribution is sufficient for GPC.

Here is the generic procedure for installing GNU Pascal on a Unix system. See Compilation Notes for extra information needed to install GPC on DOS-like platforms.

  1. Checking the prerequisites

    Make sure that GNU make is installed and that you use it in the following steps. When unsure, you can try `make --version' and/or `gmake --version'. It should tell you that it is GNU make. If you don't have it, you can obtain it from http://www.gnu.org/software/make/.

    (In the following, we will simply speak of `make' when invoking GNU make; you might need to call `gmake' instead.)

    You also need a patch program. If such a program is not installed on your system, you can get GNU patch from http://www.gnu.org/directory/patch.html.

    For extracting the example programs from the documentation to the doc/docdemos directory a non-crippled `sed' is needed. GNU sed is known to work.

    If you have downloaded a “minimal” source distribution, most derived files have to be rebuilt. This is done automatically when building GPC, but you need additional tools:

    `bash', `bzip2', GNU `sed', GNU `awk', GNU `m4', `bison' (at least version 2.1), `flex' (version 2.5.27), `autoconf' (version 2.12), `texinfo' (at least version 4.2), `help2man'.

    Make sure that these are installed. The minimal distributions are compressed with `bzip2' instead of `gzip', so substitute it in the instructions below.

    If your bison and flex programs are installed under different names, you may have to set some or all of the following environment variables before running `configure':

              FLEX=/path/to/flex
              LEX=/path/to/flex
              BISON=/path/to/bison
              YACC=/path/to/bison
              INTLBISON=/path/to/bison
         

    If you want to build the GPC WWW pages you will also need a TeX distribution (including `pdftex' and `dvips').

    If you run into trouble during the installation process, please check whether you are using outdated versions of the required utilities and upgrade if necessary.

    The GNU versions of the packages above are available from http://www.gnu.org/software/, in a subdirectory whose name is the name of the package.

  2. Unpacking the source

    From a directory of your choice (e.g. /home/fred), unpack the GCC and GNU Pascal source distributions. This will create separate subdirectories for GCC and GPC. Let us assume gcc-3.4.3 and gpc-20041218 in this example.

              % cd /home/fred
              % bzip2 -d < gcc-core-3.4.3.tar.bz2 | tar xf -
              % gzip -c -d gpc-20041218.tar.gz | tar xf -
         

    `cd' to the GPC directory and move the contents (a subdirectory p) to the subdirectory gcc of the GCC directory:

              % mv /home/fred/gpc-20041218/p /home/fred/gcc-3.4.3/gcc/
         

    Instead of moving the directory, it is now also possible to make a symbolic link (if the OS supports symlinks). This is useful if you want to build GPC with several different GCC versions:

              % ln -s /home/fred/gpc-20041218/p /home/fred/gcc-3.4.3/gcc/p
         

    It is recommended, though not required, to use a separate directory for building the compiler, rather than compiling in the source directory. In this example, let us create /home/fred/gpc-build for this purpose:

              % mkdir /home/fred/gpc-build
         

    If you use a separate directory, you do not need to write into the GCC source directory once you have patched the GCC source (see below), and can build GPC for more than one platform from the same source tree.

    In case you are re-using a directory where you have already built GCC and/or GPC for a different target machine, do `make distclean' to delete all files that might be invalid. One of the files this deletes is Makefile; if `make distclean' complains that Makefile does not exist, it probably means that the directory is already suitably clean.

  3. Configuring and building GCC

    GNU Pascal is automatically configured with GCC. Configuration of GCC is treated in depth in the GCC installation instructions. The normal procedure is as follows:

    `cd' to the GPC build directory. From there, run the `configure' script in the GCC source directory:

              % cd /home/fred/gpc-build
              % /home/fred/gcc-3.4.3/configure --enable-languages=pascal
         

    This creates all the necessary config files, links and Makefile in the GCC object directory.

    Note 1: The configuration will prompt you for patching the GCC source for GPC support, so you need write access to that directory. All changes to GCC are surrounded by `#ifdef GPC ... #endif', so they should not interfere when you build a C compiler from this source tree.

    Note 2: The `--enable-languages=pascal' option means that we only want to build the Pascal compiler and not, for instance, the C++ compiler.

    Note 3: The standard base directory for installing GCC and GPC is /usr/local. If you want to install files to an alternate directory dir, specify `--prefix=dir' when you run configure. For installing into a system directory such as /usr/local you will, of course, need appropriate permissions (often root). Therefore, if you want to install GPC on a system where you don't have those permissions, you must specify a prefix (e.g., `$HOME/usr').

  4. Putting other GNU tools in place

    Some environments require other GNU tools (such as the GNU assembler or linker) instead of the standard system tools for GCC to work. (See the GCC installation instructions for details.) If this is the case for your system, install the required tools in the GPC build directory under the names as, ld, or whatever is appropriate. This will enable the compiler to find the proper tools for compilation of the program enquire (a part of GCC) and to install the GNU tools to a place where they are found by GCC but do not interfere with the standard system tools.

    Alternatively, you can do subsequent compilation using a value of the PATH environment variable such that the necessary GNU tools come before the standard system tools.

  5. Compiling GPC

    Once you are satisfied with the configuration as determined by configure, you can build the compiler:

              % make
         

    Notice that this procedure will build the C compiler (and maybe some other compilers) too, because that is used to compile the GPC runtime library.

    Optionally, you may supply CFLAGS, LDFLAGS or RTSFLAGS. CFLAGS is used for compiler and RTS, RTSFLAGS are for RTS only, i.e.: `make CFLAGS="-O2" RTSFLAGS=-Wall'

    Note: The documentation may fail to build from *.texi sources if GCC 2.95.x tries to use an older version of `makeinfo' supplied in GCC package itself. This can be prevented by supplying explicit instruction to use your system's `makeinfo':

              % make MAKEINFO=`which makeinfo`
         

    optionally followed by the rest of arguments.

  6. Completing the installation

    When everything has been compiled, you can check the installation process with:

              % make -n install
         

    To complete the installation, run the command `make install'. You need write access to the target directories (/usr/local/bin, /usr/local/lib, /usr/local/info, /usr/local/doc, and /usr/local/man in this example), so this is usually done as `root':

              % su -c "make install"
         

    If you want to install only the Pascal compiler (for example if you already have the correct version of GCC installed), `cd' to the `gcc' subdirectory of the build directory (e.g. /home/fred/gpc-build/gcc) and run `make pascal.install'. This installation process does not overwrite existing copies of libgcc.a or specs, should they exist.

    However, if you do not have the exactly matching GCC version installed, you might need some additional files (otherwise GPC will complain about missing files at runtime). You can install them by doing `make pascal.install-with-gcc' in the gcc subdirectory of the build directory.

    There is a (partial) translation of the GPC manual into Croatian available now. It is not installed by default. If you want to install it, do a `pascal.install-hr' in the `gcc' directory. This will install the manpage gpc-hr.1 and the info documentation gpc-hr.info*. Other formats like PS, PDF and HTML can be built manually (it's also easy to add appropriate make targets for them when needed).

    Also from the `gcc' subdirectory you can do some more “exotic” builds. For instance, you can build the GPC WWW pages by typing `make pascal.html' or a binary distribution by typing `make pascal.bindist'. See the Makefile in that directory for more examples.


Next: , Previous: Compiling GPC, Up: Installation

4.4 Compilation notes for specific platforms


Next: , Up: Compilation Notes

4.4.1 MS-DOS with DJGPP

The only compiler that is capable of compiling the GNU Compiler Collection (GNU CC or GCC) under MS-DOS is GCC itself. In order to compile GPC or GCC for MS-DOS with DJGPP you will therefore need either a working copy of DJGPP installed, or you will have to cross-build from a non-MS-DOS system.

Building GPC under MS-DOS with DJGPP follows the same scheme as building GPC under a Unix-like system: Place the p subdirectory in the gcc directory and follow the instructions for compiling GCC. This requires `bash' and many other tools installed, and you must be very careful at many places to circumvent the limitations of the DOS platform.

Our preferred way to build GPC for DJGPP is to cross-build it from a Unix-like platform – which is much easier. For instructions, see Cross-Compilers and Crossbuilding.


Next: , Previous: MS-DOS with DJGPP, Up: Compilation Notes

4.4.2 MS-DOS or OS/2 with EMX

EMX is a free 32-bit DOS extender which adds some properties of Unix to MS-compatible DOS and IBM's OS/2 operating systems.

As of this writing, we are not aware of current versions of GCC for EMX, and EMX support in GPC has not been maintained. Please contact us if you know about recent development in EMX and are interested in continuing EMX support in GPC.


Previous: MS-DOS or OS/2 with EMX, Up: Compilation Notes

4.4.3 MS Windows 95/98/NT

There are two ports of the GNU development tools to MS Windows 95/98/NT: CygWin and mingw32.

The CygWin environment implements a POSIX layer under MS Windows, giving it large parts of the functionality of Unix. Thus, compiling GCC and GPC under the CygWin environment can be done following the instructions for compiling it under a Unix-like system (see Compiling GPC).

The Minimalists' GNU Win32 environment, mingw32, uses the native crtdll.dll library of MS Windows. It is much smaller than CygWin, but it is not self-hosting and must be crossbuilt from another system (see Crossbuilding).


Next: , Previous: Compilation Notes, Up: Installation

4.5 Building and Installing a cross-compiler

GNU Pascal can function as a cross-compiler for many machines. Information about GNU tools in a cross-configuration can be found at `ftp://ftp.cygnus.com/pub/embedded/crossgcc/'.

If you want a cross-compiler targetting Linux you may use Dan Kegel's crosstool from `http://www.kegel.com/crosstool/'

Since GNU Pascal generates assembler code, you need a cross-assembler that GNU Pascal can run, in order to produce object files. If you want to link on other than the target machine, you need a cross-linker as well. It is straightforward to install the GNU binutils to act as cross-tools – see the installation instructions of the GNU binutils for details.

You also need header files and libraries suitable for the target machine that you can install on the host machine. Please install them under prefix/platform/include/, for instance /usr/local/i386-pc-msdosdjgpp/include/ for a cross-compiler from a typical Unix-like environment to MS-DOS with DJGPP.

Configuration and compilation of the compiler can then be done using the scripts cfgpc and mkgpc which are included in the source distribution in the subdirectory p/script. Please call them with the `-h' option for instructions.


Previous: Cross-Compilers, Up: Installation

4.6 Crossbuilding a compiler

Using a cross-compiler to build GNU Pascal results in a compiler binary that runs on the cross-target platform. This is called “crossbuilding”. A possible reason why anybody would want to do this, is when the platform on which you want to run the GNU Pascal compiler is not self-hosting. An example is mingw32.

To crossbuild GNU Pascal, you have to install a cross-compiler for your target first, see Cross-Compilers.

As when building a cross-compiler, configuration and compilation of the compiler can be done using the scripts cfgpc and mkgpc which are included in the source distribution in the subdirectory p/script. Please call them with the `-h' option for instructions.


Next: , Previous: Installation, Up: Top

5 Command Line Options supported by GNU Pascal.

GPC is a command-line compiler, i.e., to compile a program you have to invoke gpc passing it the name of the file you want to compile, plus options.

GPC supports all command-line options that GCC knows, except for many preprocessor options. For a complete reference and descriptions of all options, see GCC Command Options. Below, you will find a list of the additional options that GPC supports, and a list of GPC's most important options (including some of those supported by GCC as well).

You can mix options and file names on the command line. For the most part, the order doesn't matter. Order does matter, e.g., when you use several options of the same kind; for example, if you specify `-L' more than once, the directories are searched in the order specified. Note: Since many options have multiletter names; multiple single-letter options may not be grouped as is possible with many other programs: `-dr' is very different from `-d -r'.

Many options have long names starting with `--' or, completely equivalent `-f'. E.g., `--mixed-comments' is the same as `-fmixed-comments'. Some options tell GPC when to give warnings, i.e. diagnostic messages that report constructs which are not inherently erroneous but which are risky or suggest there may have been an error. Those options start with `-W'.

Most GPC specific options can also be changed during one compilation by using compiler directives in the source, e.g. `{$X+}' or `{$extended-syntax}' for `--extended-syntax' (see Compiler Directives).

GPC understands the same environment variables GCC does (see Environment Variables Affecting GCC). In addition, GPC recognizes `GPC_EXEC_PREFIX' with the same meaning that `GCC_EXEC_PREFIX' has to GCC. GPC also recognizes `GCC_EXEC_PREFIX', but `GPC_EXEC_PREFIX' takes precedence.

Some of the long options (e.g., `--unit-path') take an argument. This argument is separated with a `=' sign, e.g.:

     --unit-path=/home/foo/units


Next: , Up: Invoking GPC

5.1 GPC options besides those of GCC.

The following table lists the command line options GPC understands in addition to those understood by GCC.

--debug-tree
(For GPC developers.) Show the internal representation of a given tree node (name or address).
--debug-gpi
(For GPC developers.) Show what is written to and read from GPI files (huge output!).
--debug-automake
(For GPC developers.) Give additional information about the actions of automake.
--debug-source
Output the source while it is being processed to standard error.
--no-debug-source
Do not output the source while it is being processed (default).
--disable-debug-info
Inhibit `-g' options (temporary work-around, this option may disappear in the future).
--progress-messages
Output source file names and line numbers while compiling.
--no-progress-messages
Do not output source file names and line numbers while compiling (default).
--progress-bar
Output number of processed lines while compiling.
--no-progress-bar
Do not output number of processed lines while compiling (default).
--automake-gpc
Set the Pascal compiler invoked by automake.
--automake-gcc
Set the C compiler invoked by automake.
--automake-g++
Set the C++ compiler invoked by automake.
--amtmpfile
(Internal switch used for automake).
--autolink
Automatically link object files provided by units/modules or `{$L ...}' (default).
--no-autolink
Do not automatically link object files provided by units/modules/`{$L ...}'.
--automake
Automatically compile changed units/modules/`{$L ...}' files and link the object files provided.
--no-automake
Same as `--no-autolink'.
--autobuild
Automatically compile all units/modules/`{$L ...}' files and link the object files provided.
--no-autobuild
Same as `--no-autolink'.
--maximum-field-alignment
Set the maximum field alignment in bits if `pack-struct' is in effect.
--ignore-packed
Ignore `packed' in the source code (default in `--borland-pascal').
--no-ignore-packed
Do not ignore `packed' in the source code (default).
--ignore-garbage-after-dot
Ignore anything after the terminating `.' (default in `--borland-pascal').
--no-ignore-garbage-after-dot
Complain about anything after the terminating `.' (default).
--extended-syntax
same as `--ignore-function-results --pointer-arithmetic --cstrings-as-strings -Wno-absolute' (same as `{$X+}').
--no-extended-syntax
Opposite of `--extended-syntax' (same as `{$X-}').
--ignore-function-results
Do not complain when a function is called like a procedure.
--no-ignore-function-results
Complain when a function is called like a procedure (default).
--pointer-arithmetic
Enable pointer arithmetic.
--no-pointer-arithmetic
Disable pointer arithmetic (default).
--cstrings-as-strings
Treat CStrings as strings.
--no-cstrings-as-strings
Do not treat CStrings as strings (default).
-Wabsolute
Warn about variables at absolute adresses and `absolute' variable with non-constant addresses (default).
-Wno-absolute
Do not warn about variables at absolute adresses and `absolute' variable with non-constant addresses.
--short-circuit
Guarantee short-circuit Boolean evaluation (default; same as `{$B-}').
--no-short-circuit
Do not guarantee short-circuit Boolean evaluation (same as `{$B+}').
--mixed-comments
Allow comments like `{ ... *)' as required in ISO Pascal (default in ISO 7185/10206 Pascal mode).
--no-mixed-comments
Ignore `{' and `}' within `(* ... *)' comments and vice versa (default).
--nested-comments
Allow nested comments like `{ { } }' and `(* (* *) *)'.
--no-nested-comments
Do not allow nested comments (default).
--delphi-comments
Allow Delphi style `//' comments (default).
--no-delphi-comments
Do not allow Delphi style `//' comments.
--macros
Expand macros (default).
--no-macros
Do not expand macros (default with `--ucsd-pascal', `--borland-pascal' or `--delphi').
--truncate-strings
Truncate strings being assigned to other strings of too short capacity.
--no-truncate-strings
Treat string assignments to other strings of too short capacity as errors.
--exact-compare-strings
Do not blank-pad strings for comparisons.
--no-exact-compare-strings
Blank-pad strings for comparisons.
--double-quoted-strings
Allow strings enclosed in "\" (default).
--no-double-quoted-strings
Do not allow strings enclosed in "\" (default with dialect other than `--mac-pascal').
--longjmp-all-nonlocal-labels
Use `longjmp' for all nonlocal labels (default for Darwin/PPC).
--no-longjmp-all-nonlocal-labels
Use `longjmp' only for nonlocal labels in the main program (default except for Darwin/PPC).
--iso-goto-restrictions
Do not allow jumps into structured instructions (default).
--no-iso-goto-restrictions
Allow jumps into structured instructions (default in `--borland-pascal').
--nonlocal-exit
Allow non-local `Exit' statements (default in `--ucsd-pascal' and `--mac-pascal').
--no-nonlocal-exit
Do not allow non-local `Exit' statements (default).
--io-checking
Check I/O operations automatically (same as `{$I+}') (default).
--no-io-checking
Do not check I/O operations automatically (same as `{$I-}').
--pointer-checking-user-defined
Use user-defined procedure for validating pointers.
--no-pointer-checking-user-defined
Do not use user-defined procedure for validating pointers (default).
--pointer-checking
Validate pointers before dereferencing.
--no-pointer-checking
Do not validate pointers before dereferencing (default).
--object-checking
Check for valid objects on virtual method calls (default).
--no-object-checking
Do not check for valid objects on virtual method calls.
--range-checking
Do automatic range checks') (default).
--no-range-checking
Do not do automatic range checks (same as `{$R-}').
--range-and-object-checking
Same as `--range-checking --object-checking', same as `{$R+}'.
--no-range-and-object-checking
Same as `--no-range-checking --no-object-checking', same as `{$R-}'.
--case-value-checking
Cause a runtime error if a `case' matches no branch (default in ISO Pascal modes).
--no-case-value-checking
Do not cause a runtime error if a `case' matches no branch (default).
--stack-checking
Enable stack checking (same as `{$S+}').
--no-stack-checking
Disable stack checking (same as `{$S-} (default)').
--read-base-specifier
In read statements, allow input base specifier `n#' (default).
--no-read-base-specifier
In read statements, do not allow input base specifier `n#' (default in ISO 7185 Pascal).
--read-hex
In read statements, allow hexadecimal input with `$' (default).
--no-read-hex
In read statements, do not allow hexadecimal input with `$' (default in ISO 7185 Pascal).
--read-white-space
In read statements, require whitespace after numbers.
--no-read-white-space
In read statements, do not require whitespace after numbers (default).
--write-clip-strings
In write statements, truncate strings exceeding their field width (`Write (SomeLongString : 3)').
--no-write-clip-strings
Do not truncate strings exceeding their field width.
--write-real-blank
Output a blank in front of positive reals in exponential form (default).
--no-write-real-blank
Do not output a blank in front of positive reals in exponential form.
--write-capital-exponent
Write real exponents with a capital `E'.
--no-write-capital-exponent
Write real exponents with a lowercase `e'.
--transparent-file-names
Derive external file names from variable names.
--no-transparent-file-names
Do not derive external file names from variable names (default).
--field-widths
Optional colon-separated list of default field widths for Integer, Real, Boolean, LongInt, LongReal.
--no-field-widths
Reset the default field widths.
--pedantic
Reject everything not allowed in some dialect, e.g. redefinition of its keywords.
--no-pedantic
Don't give pedantic warnings.
--typed-address
Make the result of the address operator typed (same as `{$T+}', default).
--no-typed-address
Make the result of the address operator an untyped pointer (same as `{$T-}').
--enable-keyword
Enable a keyword, independently of dialect defaults.
--disable-keyword
Disable a keyword, independently of dialect defaults.
--implicit-result
Enable implicit `Result' for functions (default only in `--delphi').
--no-implicit-result
Disable implicit `Result' for functions.
--enable-predefined-identifier
Enable a predefined identifier, independently of dialect defaults.
--disable-predefined-identifier
Disable a predefined identifier, independently of dialect defaults.
--assertions
Enable assertion checking (default).
--no-assertions
Disable assertion checking.
--setlimit
Define the range for `set of Integer' etc..
--gpc-main
External name for the program's entry point (default: `main').
--propagate-units
Automatically re-export all imported declarations.
--no-propagate-units
Do not automatically re-export all imported declarations.
--interface-only
Compile only the interface part of a unit/module and exit (creates `.gpi' file, no `.o' file.
--implementation-only
Do not produce a GPI file; only compile the implementation part.
--executable-file-name
Name for the output file, if specified; otherwise derive from main source file name.
--unit-path
Directories where to look for unit/module sources.
--no-unit-path
Forget about directories where to look for unit/module sources.
--object-path
Directories where to look for additional object (and source) files.
--no-object-path
Forget about directories where to look for additional object (and source) files.
--executable-path
Path where to create the executable file.
--no-executable-path
Create the executable file in the directory where the main source is (default).
--unit-destination-path
Path where to create object and GPI files of Pascal units.
--no-unit-destination-path
Create object and GPI files of Pascal units in the current directory (default).
--object-destination-path
Path where to create additional object files (e.g. of C files, not Pascal units).
--no-object-destination-path
Create additional object files (e.g. of C files, not Pascal units) in the current directory (default).
--disable-default-paths
Do not add a default path to the unit and object path.
--gpi-destination-path
(Internal switch used for automake).
--uses
Add an implicit `uses' clause.
--init-modules
Initialize the named modules in addition to those imported regularly; kind of a kludge.
--cidefine
Define a case-insensitive macro.
--csdefine
Define a case-sensitive macro.
--big-endian
Tell GPC that the system is big-endian (for those targets where it can vary).
--little-endian
Tell GPC that the system is little-endian (for those targets where it can vary).
--print-needed-options
Print the needed options.
-Wwarnings
Enable warnings (same as `{$W+}').
-Wno-warnings
Disable all warnings (same as `{$W-}').
-Widentifier-case-local
Warn about an identifier written with varying case within one program/module/unit.
-Wno-identifier-case-local
Same as `-Wno-identifier-case'.
-Widentifier-case
Warn about an identifier written with varying case.
-Wno-identifier-case
Do not warn about an identifier written with varying case (default).
-Winterface-file-name
Warn when a unit/module interface differs from the file name.
-Wno-interface-file-name
Do not warn when a unit/module interface differs from the file name (default).
--methods-always-virtual
Make all methods virtual (default in `--mac-pascal').
--no-methods-always-virtual
Do not make all methods virtual (default).
--objects-are-references
Turn objects into references (default in `--mac-pascal').
--no-objects-are-references
Do not turn objects into references (default).
--objects-require-override
Require override directive for objects (default in `--mac-pascal').
--no-objects-require-override
Do not require override directive for objects (default).
--delphi-method-shadowing
Redefining methods silently shadows old definition (default in `--delphi').
--no-delphi-method-shadowing
Do not silently shadow method definitions (default).
--borland-objects
Choose Borland object model.
--mac-objects
Choose Mac object model.
--ooe-objects
Choose OOE object model.
--gnu-objects
Reset object model to default state.
--preprocessed
Treat the input file as already preprocessed.
-nostdinc
Do not search standard system.
-remap
Remap file names when including files.
-A
Ignored.
-E
Preprocess only.
-H
Print the name of include files as they are used.
-P
Do not generate #line directives.
-Wimplicit-abstract
Warn when an object type not declared `abstract' contains an abstract method (default).
-Wno-implicit-abstract
Do not warn when an object type not `declared' abstract contains an abstract method.
-Winherited-abstract
Warn when an abstract object type inherits from a non-abstract one (default).
-Wno-inherited-abstract
Do not warn when an abstract object type inherits from a non-abstract one.
-Wobject-assignment
Warn when when assigning objects or declaring them as value parameters or function results (default).
-Wno-object-assignment
Do not warn when assigning objects or declaring them as value parameters or function results (default in `--borland-pascal').
-Wimplicit-io
Warn when `Input' or `Output' are used implicitly.
-Wno-implicit-io
Do not warn when `Input' or `Output' are used implicitly (default).
-Wfloat-equal
Warn about `=' and `<>' comparisons of real numbers.
-Wno-float-equal
Do not warn about `=' and `<>' comparisons of real numbers.
-Wtyped-const
Warn about misuse of typed constants as initialized variables (default).
-Wno-typed-const
Do not warn about misuse of typed constants as initialized variables.
-Wnear-far
Warn about use of useless `near' or `far' directives (default).
-Wno-near-far
Do not warn about use of useless `near' or `far' directives.
-Wunderscore
Warn about double/leading/trailing underscores in identifiers.
-Wno-underscore
Do not warn about double/leading/trailing underscores in identifiers.
-Wsemicolon
Warn about a semicolon after `then', `else' or `do' (default).
-Wno-semicolon
Do not warn about a semicolon after `then', `else' or `do'.
-Wlocal-external
Warn about local `external' declarations.
-Wno-local-external
Do not warn about local `external' declarations.
-Wdynamic-arrays
Warn about arrays whose size is determined at run time (including array slices).
-Wno-dynamic-arrays
Do not warn about arrays whose size is determined at run time (including array slices).
-Wmixed-comments
Warn about mixed comments like `{ ... *)'.
-Wno-mixed-comments
Do not warn about mixed comments.
-Wnested-comments
Warn about nested comments like `{ { } }'.
-Wno-nested-comments
Do not warn about nested comments.
--classic-pascal-level-0
Reject conformant arrays and anything besides ISO 7185 Pascal.
--standard-pascal-level-0
Synonym for `--classic-pascal-level-0'.
--classic-pascal
Reject anything besides ISO 7185 Pascal.
--standard-pascal
Synonym for `--classic-pascal'.
--extended-pascal
Reject anything besides ISO 10206 Extended Pascal.
--object-pascal
Reject anything besides (the implemented parts of) ANSI draft Object Pascal.
--ucsd-pascal
Try to emulate UCSD Pascal.
--borland-pascal
Try to emulate Borland Pascal, version 7.0.
--delphi
Try to emulate Borland Pascal, version 7.0, with some Delphi extensions.
--pascal-sc
Be strict about the implemented Pascal-SC extensions.
--vax-pascal
Support (a few features of) VAX Pascal.
--sun-pascal
Support (a few features of) Sun Pascal.
--mac-pascal
Support (some features of) traditional Macintosh Pascal compilers.
--gnu-pascal
Undo the effect of previous dialect options, allow all features again.


Previous: GPC Command Line Options, Up: Invoking GPC

5.2 The most commonly used options to GPC

As the most simple example, calling

     gpc foo.pas

tells GPC to compile the source file foo.pas and to produce an executable of the default name which is foo.exe on EMX, a.exe on Cygwin, both a.out and a.exe on DJGPP, and a.out on most other platforms.

Users familiar with BP, please note that you have to give the file name extension `.pas': GPC is a common interface for a Pascal compiler, a C, ObjC and C++ compiler, an assembler, a linker, and perhaps an Ada and a FORTRAN compiler. From the extension of your source file GPC figures out which compiler to run. GPC recognizes Pascal sources by the extension .pas, .p, .pp or .dpr. GPC also accepts source files in other languages (e.g., .c for C) and calls the appropriate compilers for them. Files with the extension .o or without any special recognized extension are considered to be object files or libraries to be linked.

Another example:

     gpc -O2 -Wall --executable-file-name --automake --unit-path=units foo.pas

This will compile the source file foo.pas to an executable named foo (`--executable-file-name') with fairly good optimization (`-O2'), warning about possible problems (`-Wall'). If the program uses units or imports modules, they will be searched for in a directory called units (`--unit-path') and automatically compiled and linked (`--automake').

The following table lists the most commonly used options to GPC.

--automake
Check whether modules/units used must be recompiled and do the recompilation when necessary.
--unit-path=dir[:dir...]
Search the given directories for units and object files.
--object-path=dir[:dir...]
Search the given directories for object files.
--unit-destination-path=dir
Place compiled units (GPI and object files) into the directory dir. The default is the current directory.
--object-destination-path=dir
Place compiled object files (e.g., from C files, but not from Pascal units) into the directory dir. The default is the directory given with `--unit-destination-path'.
--executable-path=dir
Place the executable compiled into the directory dir. The default is the main source file's directory.
-o file
Place output in file file. This applies regardless to whatever sort of output is being produced, whether it be an executable file, an object file, an assembler file, etc.

Since only one output file can be specified, it does not make sense to use `-o' when compiling more than one input file, unless you are producing an executable file as output.

--executable-file-name[=name]
Derive the executable file name from the source file name, or use name as the executable file name. The difference to the `-o' option is that `--executable-file-name' considers the `--executable-path', while `-o' does not and accepts a file name with directory. Furthermore, `--executable-file-name' only applies to executables, not to other output formats selected.
-Ldir
Search the directory dir for libraries. Can be given multiple times.
-Idir
Search the directory dir for include files. Can be given multiple times.
-llibrary
Search the library named library when linking. This option must be placed on the command line after all source or object files or other libraries that reference the library.
-O[n]
Select the optimization level. Without optimization (or `-O0' which is the default), the compiler's goal is to reduce the compilation time and to make debugging produce the expected results. Statements are independent: if you stop the program with a breakpoint between statements, you can then assign a new value to any variable or change the program counter to any other statement in the same routine and get exactly the results you would expect from the source code.

With optimization, the compiler tries to reduce code size and execution time. The higher the value of n, the more optimizations will be done, but the longer the compilation will take.

If you use multiple `-O' options, with or without n, the last such option is the one that is effective.

-g
Produce debugging information suitable for `gdb'. Unlike some other compilers, GNU Pascal allows you to use `-g' with `-O'. The shortcuts taken by optimized code may occasionally produce surprising results: some variables you declared may not exist at all; flow of control may briefly move where you did not expect it; some statements may not be executed because they compute constant results or their values were already at hand; some statements may execute in different places because they were moved out of loops. Nevertheless it proves possible to debug optimized output. This makes it reasonable to use the optimizer for programs still in the testing phase.
-s
Remove all symbol table and relocation information from the executable. Note: this has no influence on the performance of the compiled executable.
-Wall
Give warnings for a number of constructs which are not inherently erroneous but which are risky or suggest there may have been an error. There are additional warning options not implied by `-Wall', see the GCC warning options (see Options to Request or Suppress Warnings), while `-Wall' only warns about such constructs that should be easy to avoid in programs. Therefore, we suggest using `-Wall' on most sources.

Note that some warnings (e.g., those about using uninitialized variables) are never given unless you compile with optimization (see above), because otherwise the compiler doesn't analyze the usage patterns of variables.

-Werror
Turn all warnings into errors.
-S
Stop after the stage of compilation proper; do not assemble. The output is in the form of an assembler code file for each source file. By default, the assembler file name for a source file is made by replacing the extension with `.s'.
-c
Compile and assemble the source files, but do not link. The output is in the form of an object file for each source file. By default, the object file name for a source file is made by replacing the extension with `.o'.
-static
On systems that support dynamic linking, this prevents linking with the shared libraries, i.e. forces static linking. On other systems, this option has no effect.
-Dmacro[=def]
Define the macro and conditional symbol macro as def (or as `1' if def is omitted).
-b machine
The argument machine specifies the target machine for compilation. This is useful when you have installed GNU Pascal as a cross-compiler.
-v
Print (on standard error) the commands executed to run the stages of compilation. Also print the version number of the compiler driver program and of the preprocessor and the compiler proper.
--classic-pascal-level-0
--classic-pascal
--extended-pascal
--object-pascal
--ucsd-pascal
--borland-pascal
--delphi
--pascal-sc
--mac-pascal
GNU Pascal supports the features of several different Pascal standards and dialects. The intention is to have common language, where features off all dialects are available. As result, the defualt language is the biggest dialect, with most features. Sometimies features of different dialect conflict (in such cases we usually provide more detailed switches to choose desired behaviour). These switches turn on maximal compatiblity with given dialect. In particular they tell GPC to restrict itself to the features of the specified standard. Warnings about certain dangerous constructs which would be valid in the specified dialect (e.g., assignment to a typed constant with `--borland-pascal') are suppressed.

By default, GNU Pascal allows the redefinition of some keywords. Each of these switches causes GNU Pascal to forbid the redefinition of keywords of the specified standard.

Most ISO 7185 Pascal programs should compile properly with or without `--classic-pascal'. However, without this option, some constructs behave in non-standard way. Moreover, certain GNU extensions and Pascal features from other dialects are supported as well. With this option, they are rejected.

These options are not intended to be useful; they exist only to satisfy pedants who would otherwise claim that GNU Pascal fails to support the ISO Standard or is not really compatible to Borland Pascal, or whatever. We recommend, rather, that users take advantage of the extensions of GNU Pascal and disregard the limitations of other compilers.

-pedantic-errors
Produce errors rather than warnings for portability violations. Unlike in C, this does not imply the `-pedantic' option, so you can, for instance, use `-pedantic-errors' without `-pedantic', but with `--extended-pascal'.
--gpc-main=name
Name the entry point of the main program `name' instead of `main' on the linker level. This is useful, e.g., when working with some C libraries which define their own `main' function and require the program's main entry point to be named differently. (This option should preferably be used as a compiler directive in the unit or module which links to that strange C library, rather than be given on the command-line.)


Next: , Previous: Invoking GPC, Up: Top

6 The Programmer's Guide to GPC

This chapter is still under development.

This chapter tells you how the source of a valid GNU Pascal program should look like. You can use it as tutorial about the GNU Pascal language, but since the main goal is to document all special GPC features, implementation-dependent stuff, etc., expect a steep learning curve.

This chapter does not cover how to compile your programs and to produce an executable – this is discussed above in Invoking GPC.


Next: , Up: Programming

6.1 Source Structures

A source file accepted by GNU Pascal may contain up to one program, zero or more ISO-style modules, and/or zero or more UCSD-style units. Units and modules can be mixed in one project.

One trivial example for a valid GPC source file follows. Note that the code below may either be in one source file, or else the unit and the program may be in separate source files.

     unit DemoUnit;
     
     interface
     
     procedure Hello;
     
     implementation
     
     procedure Hello;
     begin
       WriteLn ('Hello, world!')
     end;
     
     end.
     program UnitDemo;
     
     uses
       DemoUnit;
     
     begin
       Hello
     end.


Next: , Up: Source Structures

6.1.1 The Source Structure of Programs

A generic GNU Pascal program looks like the following:

     program name (Input, Output);
     
     import_part
     
     declaration_part
     
     begin
       statement_part
     end.

The program headline may be omitted in GPC, but a warning will be given except in `--borland-pascal' mode.

While the program parameters (usually `Input', `Output') are obligatory in ISO Pascal if you want to use `ReadLn' and `WriteLn', they are optional in GNU Pascal. GPC will warn about such missing parameters in `--extended-pascal' mode. However if you give parameters to the program headline, they work like ISO requires.

The import_part consists either of an ISO-style `import' specification or a UCSD/Borland-style `uses' clause. While `import' is intended to be used with interfaces exported by ISO 10206 Extended Pascal modules, and `uses' is intended to be used with units, this is not enforced. (See also uses, import.)

The declaration_part consists of label, constant, type, variable or subroutine declarations in free order. However, every identifier must be declared before it is used. The only exception are type identifiers pointing to another type identifier which may be declared below.

The statement_part consists of a sequence of statements.

As an extension, GPC supports a “declaring statement” which can be used in the statement part to declare variables (see var).


Next: , Previous: The Program, Up: Source Structures

6.1.2 Label Declaration

A label declaration has the following look:

     label
       label_name, ..., label;

A label declaration part starts with the reserved word label, which contains a list of labels.

See also

label, goto


Next: , Previous: Label Declaration, Up: Source Structures

6.1.3 Constant Declaration

A constant declaration has the following look:

     const
       constant_identifier = constant_expression;
       ...
       constant_identifier = constant_expression;

A constant declaration part starts with the reserved word const. It declares a constant_identifier which is defined by constant_expression. This expression has to be evaluatable during compilation time, i.e. it can include numbers, parentheses, predefined operators, sets and type casts (the last, however, is a Borland extension). In ISO 7185 Pascal, constant_expression must be a constant or a set. All Pascal Dialects but ISO-Pascal allow the use of these intrinsic functions in constant_expression:

Abs, Round, Trunc, Chr, Ord, Length, Pred, Succ, SizeOf, Odd.

In Borland Pascal, in the constant declaration part variables can be declared as well, which are given an initial value. These variables are called “typed constants”. It is good style to avoid this use, especially since Extended Pascal and GNU Pascal allow to initialize a variable in variable declaration part or give a type a preset value on declaration.

     const
       FiveFoo      = 5;
       StringFoo    = 'string constant';
       AlphabetSize = Ord ('Z') - Ord ('A') + 1;
     
     type
       PInteger     = ^Integer;     { Define a pointer to an Integer }
     
     const
       { Constant which holds a pointer to an Integer at address 1234 }
       AddressFoo   = PInteger (1234);

See also

Subroutine Parameter List Declaration


Next: , Previous: Constant Declaration, Up: Source Structures

6.1.4 Type Declaration

A type declaration looks like this:

     type
       type_identifier = type_definition;
       ...
       type_identifier = type_definition;

or, with preset content:

     type
       type_identifier = type_definition value constant_expression;
       ...
       type_identifier = type_definition value constant_expression;

A type declaration part begins with the reserved word type. It declares a type_identifier which is defined by type_definition. A type definition either can be an array, a record, a schema, a set, an object, a subrange, an enumerated type, a pointer to another type_identifier or simply another type_identifier which is to alias. If a schema type is to be declared, type_identifier is followed by a discriminant enclosed in parentheses:

     type_identifier (discriminant) = schema_type_definition;

If value is specified, followed by a constant satisfying the type definition, every variable of this type is initialized with constant_expression, unless it is initialized by value itself. The reserved word value can be replaced by `=', however value is not allowed in ISO-Pascal and Borland Pascal, and the replacement by `=' is not allowed in Extended Pascal.

Type declaration example

     type
       { This side is the }     { That side is the }
       { type declaration }     { type definition  }
     
       Arrayfoo            = array [0 .. 9] of Integer;  { array definition }
       Recordfoo           = record                      { record definition }
                               Bar: Integer;
                             end;
     
            { schema def with discriminants ``x, y: Integer'' }
       SchemaFoo (x, y: Integer) = array [x .. y] of Integer;
       CharSetFoo          = set of Char;              { Def of a set }
       ObjectFoo           = object                    { Def of an object }
                               procedure DoAction;
                               constructor Init;
                               destructor Done;
                             end;
       SubrangeFoo         = -123..456;                { subrange def }
     
       EnumeratedFoo       = (Pope,John,the,Second);   { enum type def }
            { Def of a pointer to another type identifier }
       PInteger            = ^arrayfoo;
            { Def of an alias name for another type identifier }
       IdentityFoo         = Integer;
            { Def of an integer which was initialized by 123 }
       InitializedFoo      = Integer value 123;

See also

Type Definition, Data Types, Variable Declaration


Next: , Previous: Type Declaration, Up: Source Structures

6.1.5 Variable Declaration

A variable declaration looks like this:

     var
       var_identifier: type_identifier;
       ...
       var_identifier: type_identifier;

or

     var
       var_identifier: type_definition;
       ...
       var_identifier: type_definition;

and with initializing value:

     var
       var_identifier: type_identifier value constant_expression;
       ...
       var_identifier: type_identifier value constant_expression;

or

     var
       var_identifier: type_definition value constant_expression;
       ...
       var_identifier: type_definition value constant_expression;

A variable declaration part begins with the reserved word var. It declares a var_identifier whose type either can be specified by a type identifier, or by a type definion which either can be an array, a record, a set, a subrange, an enumerated type or a pointer to an type identifier. If value is specified followed by a constant expression satisfying the specified type, the variable declared is initialized with constant_expression. The reserved word value can be replaced by `=', however value is not allowed in ISO-Pascal and Borland Pascal, and the replacement by `=' is not allowed in Extended Pascal.

See also

Type Definition, Type Declaration, Data Types, The Declaring Statement, Subroutine Parameter List Declaration


Next: , Previous: Variable Declaration, Up: Source Structures

6.1.6 Subroutine Declaration


Next: , Up: Subroutine Declaration
6.1.6.1 The Procedure

     procedure procedure_identifier;
     declaration_part
     begin
       statement_part
     end;

or with a parameter list:

     procedure procedure_identifier (parameter_list);
     declaration_part
     begin
       statement_part
     end;

A procedure is quite like a sub-program: The declaration_part consists of label, constant, type, variable or subroutine declarations in free order. The statement_part consists of a sequence of statements. If parameter_list is specified, parameters can be passed to the procedure and can be used in statement_part. A recursive procedure call is allowed.

See also

The Function, Subroutine Parameter List Declaration


Next: , Previous: The Procedure, Up: Subroutine Declaration
6.1.6.2 The Function

     function function_identifier: function_result_type;
     declaration_part
     begin
       statement_part
     end;

or with a parameter list:

     function function_identifier (parameter_list): result_type;
     declaration_part
     begin
       statement_part
     end;

A function is a subroutine which has a return value of type function_result_type. It is structured like the program: the declaration_part consists of label, constant, type, variable or subroutine declarations in free order. The statement_part consists of a sequence of statements. If parameter_list is specified, parameters can be passed to the function and can be used in statement_part. The result is set via an assignment:

     function_identifier := expression

Recursive function calls are allowed. Concerning the result type, ISO 7185 Pascal and Borland Pascal only allow the intrinsic types, subranges, enumerated types and pointer types to be returned. In Extended Pascal, function_result_type can be every assignable type. Of course, there are no type restrictions in GNU Pascal as well. If extended syntax is switched on, functions can be called like procedures via procedure call statement.

See also

The Procedure, Subroutine Parameter List Declaration, Data Types


Next: , Previous: The Function, Up: Subroutine Declaration
6.1.6.3 The Operator

GNU Pascal allows to define operators which can be used the infix style in expressions. For a more detailed description, see Operators


Previous: The Operator, Up: Subroutine Declaration
6.1.6.4 Subroutine Parameter List Declaration

     parameter; ...; parameter

Each parameter can start with a prefix (see below) describing how the parameters are passed, followed by a comma seperated list of one or more parameter_identifiers and an optional parameter_type.

     procedure DoIt (var x, y, z: OneType; a, b: AnotherType; var q);

To understand parameter passing, first some definitions.

actual parameter
the parameter passed in to the routine.
formal parameter
the parameter as used inside the procedure.
by value
the value of the actual parameter is copied on to the stack.
by reference
the address of the actual parameter is copied on to the stack.
L-value
(left hand of a `:=' statement) something that can be assigned to (not a constant, or const or protected variable or other immutable item).
R-value
(right hand of a `:=' statement) anything you can get the value of (could be a constant, an expression, a variable (whether const or protected or not) or just about anything.
addressable
something you can get the address of (not a field of a packed structure or a variable with `attribute (register)' (GPC extension)).
aliasing
accessing memory via two different names (e.g. a global variable passed by reference to a procedure can be accessed either as the global variable or the formal paramater). Generally this is very bad practice.

Technical note: Parameters are not always passed on the stack, they may also be passed in registers, especially on RISC machines.

The prefix defines how a variable is passed on the stack and how you can access the formal_parameter inside the procedure. The prefix can be one of:

nothing
          procedure DoIt (x: SomeType);
     

Technical: The actual parameter is passed by value or reference, but if passed by reference, it is then copied to a local copy on the stack. Aliasing has no effect on x.

What it means: you can modify `x' inside the routine, but your changes will not affect the actual parameter (and vice versa). The actual parameter can be a constant or other immutable object, or a protected or const variable.

protected
          procedure DoIt (protected x: SomeType);
     

Technical: The actual parameter is passed by value or reference, but if passed by reference, it is then copied to a local copy on the stack. Aliasing has no effect on x. protected is a Extended Pascal extension.

What it means: if you modify the actual parameter, this will not affect `x' inside the routine. The actual parameter can be a constant or other immutable object, or a protected or const variable. You are forbidden from modifying x inside the routine.

var
          procedure DoIt (var x: SomeType);
     

Technical: The actual parameter is passed by reference. Aliasing will definitely change `x'.

What it means: modifications to `x' inside the routine will change the actual parameter passed in. The actual parameter must be an addressable L-value (ie, it must be something you can take the address of and assign to).

A parameter of this kind is called variable parameter and internally corresponds to an L-value pointer (to the specified type identifier if any). This declaration is necessary if the parameter is to be modified within the routine and to hold its value still after return.

const
          procedure DoIt (const x: SomeType);
     

Technical: The actual parameter is passed by value or reference. The compiler will make a copy of the actual parameter to have something it can address if the actual parameter is not addressable. You are forbidden from modifying `x' inside the routine, and therefore you cannot modify the actual parameter. Aliasing may or may not change `x'. const is a Borland Pascal extension.

What it means: You can pass any R-value. You cannot modify `x' inside the routine. If you change the actual parameter while inside the routine, `x' will have an undefined value.

protected var
          procedure DoIt (protected var x: SomeType);
     

Technical: The actual parameter is passed by reference. The compiler will never make a copy of the actual parameter. You are forbidden from modifying `x' inside the routine, and therefore you cannot modify the actual parameter. Aliasing will definitely change `x'.

What it means: You can pass anything addressable. You cannot modify `x' inside the routine. If you change the actual parameter while inside the routine, `x' will change as well.

In GPC, the protected var mode guarantees that the parameter is always passed by reference, making it the correct choice for calling C routines with `const' pointer parameters.

If you omit the formal parameter type specification, then any type may be passed to that parameter. Generally this is a bad idea, but occasionally it can be useful, especially for low level code.

As an Extended Pascal extension, you can also declare procedural parameters directly:

     procedure parameter_identifier

or:

     function parameter_identifier: parameter_identifier_result_type

Example for parameter lists:

     program ParameterDemo;
     
     procedure Foo (var Bar; var Baz: Integer; const Fred: Integer);
     
       procedure Glork1 (function Foo: Integer; procedure Bar (Baz: Integer));
       begin
         Bar (Foo)
       end;
     
     begin
       Baz := Integer (Bar) + Fred
     end;
     
     var
       a, b, c: Integer;
     
     begin
       Foo (a, b, c)
     end.

See also

Data Types, var, const, protected


Next: , Previous: Subroutine Declaration, Up: Source Structures

6.1.7 Statements


Next: , Up: Statements
6.1.7.1 Assignment

The way an assignment looks like:

     L-value := expression;

This statement assigns any valid expression to L-value. Make sure that the result of expression is compatible with L-value, otherwise an compilation error is reported. The `:=' is called assignment operator. As long as L-value and expression are type compatible, they are assignment compatible for any definable type as well.


Next: , Previous: Assignment, Up: Statements
6.1.7.2 begin end Compound Statement

It looks like that:

     begin
       statement;
       statement;
       ...
       statement
     end

This statement joins several statements together into one compound statement which is treated as a single statement by the compiler. The finishing semicolon before `end' can be left out.


Next: , Previous: begin end Compound Statement, Up: Statements
6.1.7.3 if Statement

This statement has the following look:

     if boolean_expression then
       statement

or with an alternative statement:

     if boolean_expression then
       statement1
     else
       statement2

The `if' ... `then' statement consists of a boolean expression and a statement, which is conditionally executed if the evaluation of boolean_expression yields true.

If `if' ... `then' ... `else' is concerned, statement1 is executed depending on boolean_expression being true, otherwise statement2 is executed alternatively. Note: the statement before else must not finish with a semicolon.


Next: , Previous: if Statement, Up: Statements
6.1.7.4 case Statement

     case expression of
       selector: statement;
       ...
       selector: statement;
     end

or, with alternative statement sequence:

     case ordinal_expression of
       selector: statement;
       ...
       selector: statement;
     otherwise                   { ``else'' instead of ``otherwise'' allowed }
       statement;
       ...
       statement;
     end

or, as part of the invariant record type definition:

     type
       foo = record
         field_declarations
       case bar: variant_type of
         selector: (field_declarations);
         selector: (field_declarations);
         ...
       end;

or, without a variant selector field,

     type
       foo = record
         field_declarations
       case variant_type of
         selector: (field_declarations);
         selector: (field_declarations);
         ...
       end;

The case statement compares the value of ordinal_expression to each selector, which can be a constant, a subrange, or a list of them separated by commas, being compatible with the result of ordinal_expression. Note: duplicate selectors or range crossing is not allowed unless {$borland-pascal} is specified. In case of equality the corresponding statement is executed. If otherwise is specified and no appropriate selector matched the expression, the series of statements following otherwise is executed. As a synonym for otherwise, else can be used. The semicolon before otherwise is optional.

@@ ???? The expression must match one of the selectors in order to continue, unless an alternative statement series is specified.

For case in a variant record type definition, see Record Types.

See also

if Statement


Next: , Previous: case Statement, Up: Statements
6.1.7.5 for Statement

For ordinal index variables:

     for ordinal_variable := initial_value to final_value do
       statement

or

     for ordinal_variable := initial_value downto final_value do
       statement

For sets:

     for set_element_type_variable in some_set do
       statement

For pointer index variables:

     for pointer_variable := initial_address to final_address do
       statement

or

     for pointer_variable := initial_address downto final_address do
       statement

The for statement is a control statement where an index variable assumes every value of a certain range and for every value the index variable assumes statement is executed. The range can be specified by two bounds (which must be of the same type as the index variable, i.e. ordinal or pointers) or by a set.

For ordinal index variables:

For pointer index variables:

Since gpc provides a flat memory modell, all addresses are linear, so they can be compared. Still, such loops should be used (if at all) only for iterating through successive elements of an array.

For sets:

Please note: A modification of the index variable may result in unpredictable action.

See also

Set Types, Pointer Arithmetics, repeat Statement, for Statement


Next: , Previous: for Statement, Up: Statements
6.1.7.6 while Statement

The while loop has the following form

     while boolean_expression do
       statement

The while statement declares a loop which is executed while boolean_expression is true. Since the terminating condition is checked before execution of the loop body, statement may never be executed.

See also

repeat Statement, for Statement


Next: , Previous: while Statement, Up: Statements
6.1.7.7 repeat Statement

     repeat
       statement;
       ...
       statement;
     until boolean_expression

The repeat ... until statement declares a loop which is repeated until boolean_expression is true. Since the terminating condition is checked after execution of the loop body, the statement sequence is executed at least once.

See also

while Statement, for Statement


Next: , Previous: repeat Statement, Up: Statements
6.1.7.8 asm Inline

@@ ????

     asm (StatementList: String);

The asm inline statement is a GNU Pascal extension. It requires its parameter to be AT&T-noted assembler statements, and therefore it is not compatible with that one of Borland Pascal. statementlist is a string containing asm statements separated by semicolons.


Next: , Previous: asm Inline, Up: Statements
6.1.7.9 with Statement


Next: , Previous: with Statement, Up: Statements
6.1.7.10 goto Statement

@@ ???? This statement looks like this:

     goto label

(Under construction.)


Next: , Previous: goto Statement, Up: Statements
6.1.7.11 Procedure Call

     subroutine_name;

This statement calls the subroutine subroutine_name which can either be a procedure or, if GNU extended syntax is turned on, a function. In this case, the result is ignored.


Next: , Previous: Procedure Call, Up: Statements
6.1.7.12 The Declaring Statement

This statement allows to declare a variable within a statement part. It looks like this:

     var
       var_identifier: type_identifier;

or

     var
       var_identifier: type_definition;

and with initializing value:

     var
       var_identifier: type_identifier value expression;

or

     var
       var_identifier: type_definition value expression;

Unlike in declaration parts, the initializing expression does not have to be a constant expression. Note that every declaring statement has to start with var. The name space of the variable extends from its declaration to the end of the current matching statement sequence (which can be a statement part (of the program, a function, a procedure or an operator) or, within that part, a begin end compound statement, a repeat loop, or the else branch of a case statement). This statement is a GNU Pascal extension.

See also

Type Definition, Data Types


Previous: The Declaring Statement, Up: Statements
6.1.7.13 Loop Control Statements

These are

     Continue;

and

     Break;

These simple statements must not occur outside a loop, i.e. a `for', `while' or `repeat' statement. `Continue' transfers control to the beginning of the loop right by its call, `Break' exits the current loop turn and continues loop execution.


Previous: Statements, Up: Source Structures

6.1.8 Import Part and Module/Unit Concept


Next: , Up: Modules and Units
6.1.8.1 The Source Structure of ISO 10206 Extended Pascal Modules

@@ Description missing here

A module can have one or more `export' clauses and the name of an `export' clause doesn't have to be equal to the name of the module.

Sample module code with separate interface and implementation parts:

     module DemoModule interface;  { interface part }
     
     export DemoModule = (FooType, SetFoo, GetFoo);
     
     type
       FooType = Integer;
     
     procedure SetFoo (f: FooType);
     function  GetFoo: FooType;
     
     end.
     
     module DemoModule implementation;  { implementation part }
     
     import
       StandardInput;
       StandardOutput;
     
     var
       Foo: FooType;
     
     { Note: the effect is the same as a `forward' directive would have:
       parameter lists and result types are not allowed in the
       declaration of exported routines, according to EP. In GPC, they
       are allowed, but not required. }
     procedure SetFoo;
     begin
       Foo := f
     end;
     
     function GetFoo;
     begin
       GetFoo := Foo
     end;
     
     to begin do
       begin
         Foo := 59;
         WriteLn ('Just an example of a module initializer. See comment below')
       end;
     
     to end do
       begin
         Foo := 0;
         WriteLn ('Goodbye')
       end;
     
     end.

Alternatively the module interface and implementation may be combined as follows:

     module DemoMod2;  { Alternative method }
     
     export Catch22 = (FooType, SetFoo, GetFoo);
     
     type
       FooType = Integer;
     
     procedure SetFoo (f: FooType);
     function  GetFoo: FooType;
     
     end; { note: this `end' is required here, even if the
            module-block below would be empty. }
     
     var
       Foo: FooType;
     
     procedure SetFoo;
     begin
       Foo := f
     end;
     
     function GetFoo;
     begin
       GetFoo := Foo
     end;
     
     end.

Either one of the two methods may be used like this:

     program ModuleDemo (Output);
     
     import DemoModule;
     
     begin
       SetFoo (999);
       WriteLn (GetFoo);
     end.
     program ModDemo2 (Output);
     
     import Catch22 in 'demomod2.pas';
     
     begin
       SetFoo (999);
       WriteLn (GetFoo);
     end.

Somewhat simpler GPC modules are also supported. Please note: This is not supported in the Extended Pascal standard.

This is a simpler module support that does not require exports, imports, module headers etc.

These non-standard simple GPC modules look like the following example. They do not have an export part, do not have a separate module-block, do not use import/export features.

Instead, you have to emulate the exporting/importing yourself using `attribute' and `external name'.

     module DemoMod3;
     
     type
       FooType = Integer;
     
     var
       Foo: FooType;
     
     procedure SetFoo (f: FooType); attribute (name = 'SetFoo');
     begin
       Foo := f
     end;
     
     function GetFoo: FooType; attribute (name = 'GetFoo');
     begin
       GetFoo := Foo;
     end;
     
     end.
     program ModDemo3 (Output);
     
     {$L demomod3.pas}  { explicitly link module }
     
     { Manually do the "import" from DemoMod3 }
     type
       FooType = Integer;
     
     procedure SetFoo (f: FooType); external name 'SetFoo';
     function  GetFoo: FooType;     external name 'GetFoo';
     
     begin
       SetFoo (999);
       WriteLn (GetFoo)
     end.

Module initialization and finalization:

The to begin do module initialization and to end do module finalization constructs now work on every target.

By the way: The “GPC specific” module definition is almost identical to the PXSC standard. With an additional keyword `global' which puts a declaration into an export interface with the name of the module, it will be the same. @@This is planned.


Previous: Modules, Up: Modules and Units
6.1.8.2 The Source Structure of UCSD/Borland Pascal Units

A generic GNU Pascal unit looks like the following:

     unit name;
     
     interface
     
     import_part
     
     interface_part
     
     implementation
     
     implementation_part
     
     initialization_part
     
     end.

The name of the unit should coincide with the name of the file with the extension stripped. (If not, you can tell GPC the file name with `uses foo in 'bar.pas'', see uses.)

The import_part is either empty or contains a `uses' clause to import other units. It may also consist of an ISO-style `import' specification. Note that the implementation part is not preceeded by a second import part in GPC (see import).

The interface_part consists of constant, type, and variable declarations, procedure and function headings which may be freely mixed.

The implementation_part is like the declaration part of a program, but the headers of procedures and functions may be abbreviated: Parameter lists and function results may be omitted for procedures and functions already declared in the interface part.

The initialization_part may be missing, or it may be a `begin' followed by one or more statements, such that the unit has a statement part between this `begin' and the final `end'. Alternatively, a unit may have ISO-style module initializers and finalizers, see to begin do, to end do.

Note that GPC does not yet check whether all interface declarations are resolved in the same unit. The implementation of procedures and functions which are in fact not used may be omitted, and/or procedures and functions may be implemented somewhere else, even in a different language. However, relying on a GPC bug (that will eventually be fixed) is not a good idea, so this is not recommended. Instead, declare such routines as `external'.

A unit exports everything declared in the interface section. The exported interface has the name of the unit and is compatible with Extended Pascal module interfaces since GPC uses the same code to handle both.


Next: , Previous: Source Structures, Up: Programming

6.2 Data Types


Next: , Up: Data Types

6.2.1 Type Definition

As described in Type Declaration, a type declaration part looks like this:

     type
        type_identifier = type_definition;
        ...
        type_identifier = type_definition;

where the left side is the type declaration and the right one the type definition side. GNU Pascal offers various possibilities to implement highly specialized and problem-specific data types.


Next: , Previous: Type Definition, Up: Data Types

6.2.2 Ordinal Types

An ordinal type is one that can be mapped to a range of whole numbers. It includes integer types, character types, enumerated types and subrange types of them.

A character type is represented by the intrinsic type `Char' which can hold elements of the operating system's character set (usually ASCII). Conversion between character types and integer types is possible with the intrinsic functions Ord and Chr.

An enumerated type defines a range of elements which are referred to by identifiers. Conversion from enumerated types to integer types is possible with the intrinsic function Ord. Conversion from integer to ordinal types is only possible by type-casting or using the extended form of `Succ'.

     var
       Foo: Char;       { foo can hold a character }
       Num: '0' .. '9'; { Can hold decimal digits, is a subrange type of Char }
       Day: (Monday, Tuesday, Wednesday, Thursday,
             Friday, Saturday, Sunday);  { Can hold weekdays }

See also

Ord, Chr, Type Casts


Next: , Previous: Ordinal Types, Up: Data Types

6.2.3 Integer Types

Besides `Integer', GNU Pascal supports a large zoo of integer types. Some of them you will find in other compilers, too, but most are GNU Pascal extensions, introduced for particular needs. Many of these types are synonyms for each other. In total, GPC provides 20 built-in integer types, plus seven families you can play with. (Four of these “families” are signed and unsigned, packed and unpacked subrange types; the others are explained below.)

See also: Subrange Types.


Next: , Up: Integer Types
6.2.3.1 The CPU's Natural Integer Types

For most purposes, you will always use `Integer', a signed integer type which has the “natural” size of such types for the machine. On most machines GPC runs on, this is a size of 32 bits, so `Integer' usually has a range of `-2147483648..2147483647' (see Integer).

If you need an unsigned integer type, the “natural” choice is `Cardinal', also called `Word'. Like `Integer', it has 32 bits on most machines and thus a range of `0..4294967295' (see Cardinal, Word).

These natural integer types should be your first choice for best performance. For instance on an IA32 CPU operations with `Integer' usually work faster than operations with shorter integer types like `ShortInt' or `ByteInt' (see below).


Next: , Previous: Natural Integer Types, Up: Integer Types
6.2.3.2 The Main Branch of Integer Types

`Integer', `Cardinal', and `Word' define the three “main branches” of GPC's integer types. You won't always be able to deal with the natural size; sometimes something smaller or longer will be needed. Especially when interfacing with libraries written in other languages such as C, you will need equivalents for their integer types.

The following variants of integer types (plus one Boolean type) are guaranteed to be compatible to the respective types of GNU C as listed below (whereas `Integer', `Cardinal' and `Word' themselves are not guaranteed to be compatible to any given C type). The sizes given, however, are not guaranteed. They are just typical values currently used on some platforms, but they may be actually shorter or longer on any given platform.

signed unsigned also unsigned GNU C equivalent size in bits (example)
ByteInt ByteCard Byte [un]signed char 8
ShortInt ShortCard ShortWord [unsigned] short int 16
CInteger CCardinal CWord [unsigned] int 32
MedInt MedCard MedWord [unsigned] long int 32
LongInt LongCard LongWord [unsigned] long long int 64
SizeType size_t 32
PtrDiffType ptrdiff_t 32
PtrInt PtrCard PtrWord 32
CBoolean _Bool, bool 8

Since we don't know whether `LongInt' will always remain the “longest” integer type available – maybe GNU C will get `long long long int', one day, which we will support as `LongLongInt' – we have added the synonym `LongestInt' for the longest available singed integer type, and the same holds for `LongestCard' and `LongestWord'.


Next: , Previous: Main Branch Integer Types, Up: Integer Types
6.2.3.3 Integer Types with Specified Size

In some situations you will need an integer type of a well-defined size. For this purpose, GNU Pascal provides type attributes (see attribute). The type

     Integer attribute (Size = 42)

is guaranteed to have a precision of 42 bits. In a realistic context, you will most often give a power of two as the number of bits, and the machine you will need it on will support variables of that size. If this is the case, the specified precision will simultaneously be the amount of storage needed for variables of this type.

In short: If you want to be sure that you have a signed integer with 32 bits width, write `Integer attribute (Size = 32)', not just `Integer' which might be bigger. The same works with unsigned integer types such as `Cardinal' and `Word' and with Boolean types.

This way, you can't get a higher precision than that of `LongestInt' or `LongestCard' (see Main Branch Integer Types). If you need higher precision, you can look at the `GMP' unit (see GMP) which provides integer types with arbitrary precision, but their usage is different from normal integer types.


Next: , Previous: Integer Types with Specified Size, Up: Integer Types
6.2.3.4 Integer Types and Compatibility

If you care about ISO compliance, only use `Integer' and subranges of `Integer'.

Some of GPC's non-ISO integer types exist in Borland Pascal, too: `Byte', `ShortInt', `Word', and `LongInt'. The sizes of these types, however, are not the same as in Borland Pascal. Even for `Byte' this is not guaranteed (while probable, though).

When designing GNU Pascal, we thought about compatibility to Borland Pascal. Since GNU Pascal is (at least) a 32-bit compiler, `Integer' must have (at least) 32 bits. But what to do with `Word'? Same size as `Integer' (like in BP) or 16 bits (like in BP)? We decided to make `Word' the “natural-sized” unsigned integer type, thus making it (at least) 32 bits wide. Similarly, we decided to give `LongInt' twice the size of `Integer' (like in BP) rather than making it 32 bits wide (like in BP). So `LongInt' has 64 bits, and `ShortInt' has 16 bits on the IA32 platform.

On the other hand, to increase compatibility to Borland Pascal and Delphi, GPC provides the alias name `Comp' for `LongInt' (64 bits on IA32) and `SmallInt' for `ShortInt' (16 bits on IA32). Note that BP treats `Comp' as a “real” type and allows assignments like `MyCompVar := 42.0'. Since we don't consider this a feature, GPC does not copy this behaviour.


Previous: Integer Types and Compatibility, Up: Integer Types
6.2.3.5 Summary of Integer Types

Here is a summary of all integer types defined in GPC. The sizes and ranges are only typical values, valid on some, but not all platforms. Compatibility to GNU C however is guaranteed.

ByteInt
signed 8-bit integer type, `-128..128',
compatible to `signed char' in GNU C.
Byte
unsigned 8-bit integer type, `0..255',
compatible to `unsigned char' in GNU C.
ShortInt
signed 16-bit integer type, `-32768..32767',
compatible to `short int' in GNU C.
ShortWord
unsigned 16-bit integer type, `0..65535',
compatible to `unsigned short int' in GNU C.
Integer
signed 32-bit integer type, `-2147483648..2147483647',
compatible to `int' in GNU C.
Word
unsigned 32-bit integer type, `0..4294967295',
compatible to `unsigned int' in GNU C.
MedInt
signed 32-bit integer type, `-2147483648..2147483647',
compatible to `long int' in GNU C.
MedWord
unsigned 32-bit integer type, `0..4294967295',
compatible to `unsigned long int' in GNU C.
LongInt
signed 64-bit integer type, `-9223372036854775808..9223372036854775807',
compatible to `long long int' in GNU C.
LongWord
unsigned 64-bit integer type, `0..18446744073709551615',
compatible to `unsigned long long int' in GNU C.
LongestInt
signed 64-bit integer type, `-9223372036854775808..9223372036854775807'.
LongestWord
unsigned 64-bit integer type, `0..18446744073709551615'.
Comp
signed 64-bit integer type, `-9223372036854775808..9223372036854775807'.
SmallInt
signed 16-bit integer type, `-32768..32767'.
SizeType
integer type (usually unsigned) to represent the size of objects in memory
PtrDiffType
signed integer type to represent the difference between two positions in memory
PtrInt
signed integer type of the same size as a pointer
PtrWord
unsigned integer type of the same size as a pointer

To specify the number of bits definitely, use type attributes, attribute.

     program IntegerTypesDemo (Output);
     
     var
       ByteVar: Byte;
       ShortIntVar: ShortInt;
       Foo: MedCard;
       Big: LongestInt;
     
     begin
       ShortIntVar := 1000;
       Big := MaxInt * ShortIntVar;
       ByteVar := 127;
       Foo := 16#deadbeef
     end.

See also: Subrange Types.


Next: , Previous: Integer Types, Up: Data Types

6.2.4 Built-in Real (Floating Point) Types

GPC has three built-in floating point types to represent real numbers. Each of them is available under two names (for compatibility to other compilers and languages).

For most purposes, you will always use `Real' which is the only one of them that is part of Standard and Extended Pascal. If memory constraints apply, you might want to choose `ShortReal' for larger arrays. On the other hand, if high precision is needed, you can use `LongReal'. When interfacing with libraries written in other languages such as C, you will need the equivalents for their real types.

Note that not all machines support longer floating point types, so `LongReal' is the same as `Real' on these machines. Also, some machines may support a longer type, but not do all arithmetic operations (e.g. the `Sin' function, Sin) in a precision higher than that of `Real'. If you need higher precision, you can look at the `GMP' unit (see GMP) which provides rational and real numbers with arbitrary precision, but their usage is different from normal real types.

The following real types are guaranteed to be compatible to the real types of GNU C. The sizes given, however, are not guaranteed. They are just typical values used on any IEEE compatible floating point hardware, but they may be different on some machines.

type name alternative name GNU C equivalent size in bits (typically)
ShortReal Single float 32
Real Double double 64
LongReal Extended long double 80


Next: , Previous: Real Types, Up: Data Types

6.2.5 Strings Types

There are several ways to use strings in GNU Pascal. One of them is the use of the intrinsic string type `String' which is a predefined schema type. The schema discriminant of this type holds the maximal length, which is of type Integer, so values up to MaxInt can be specified. For `String', an assignment is defined. There are many built-in functions and procedures for comfortable strings handling.

@@ ???? String procedures and functions.

Another way to use strings is to use arrays of type `Char'. For these, an intrinsic assignment is defined as well. Besides, `String' and `Char' are assignment compatible. The preferred way, however, is `String' because of the numerous possibilities for string handling.


Next: , Previous: String Types, Up: Data Types

6.2.6 Character Types

Character types are a special case of ordinal types.

See also

Ordinal Types, Chr, Ord, Pred, Succ.


Next: , Previous: Character Types, Up: Data Types

6.2.7 Enumerated Types

     type
       enum_type_identifier = (identifier, ..., identifier);

An enumerated type is a a special case of ordinal types and defines a range of elements which are referred to by identifiers. Enumerated types are ordered by occurence in the identifier list. So, they can be used as index types in an array definition, and it is possible to define subranges of them. Since they are ordered, they can be compared to one another. The intrinsic function Ord applied to name_identifier returns the number of occurence in the identifier list (beginning with zero), Pred and Succ return the predecessor and successor of name_identifier. `Boolean' is a special case of an enumerated type.

See also

Ordinal Types, Array Types, Subrange Types, Ord, Boolean, Char, Pred, Succ.


Next: , Previous: Enumerated Types, Up: Data Types

6.2.8 File Types

Files are used to store data permanently, normally on hard drives or floppies. There are tree types of files available: text files, typed and untyped files.

Text files are used to store text in them, where typed files are used to store many entries of the same type in them, e.g. addresses. Text files and typed files are accessible by `Read' and `Write' operations and do not need the parameter `BlockSize' in `Reset' or `Rewrite'. On the other hand, untyped files are used to store any type of information in them but you need to use `BlockWrite' or `BlockRead' to store or retrieve data out of this file.

     var
       F1: Text;   { a textfile }
       F2: file of Real;   { a typed filed used to store real values in it }
       F3: File;   { an untyped file }

See also

File Routines, Write, Read, BlockRead, BlockWrite, Reset, Rewrite


Next: , Previous: File Types, Up: Data Types

6.2.9 Boolean (Intrinsic)

The intrinsic Boolean represents boolean values, i.e. it can only assume true and false (which are predefined constants). This type corresponds to the enumerated type

     type
       Boolean = (False, True);

Since it is declared this way, it follows:

     Ord (False) = 0
     Ord (True) = 1
     False < True

There are four intrinsic logical operators. The logical and, or and not. In Borland Pascal and GNU Pascal, there is a logical “exclusive or” xor.

See also

Enumerated Types, and, or, not, xor


Next: , Previous: Boolean (Intrinsic), Up: Data Types

6.2.10 Pointer (Intrinsic)

The intrinsic Pointer Type is a so-called unspecified or typeless pointer (i.e. a pointer which does not point to any type but holds simply a memory address).

See also

Pointer Types, nil


Next: , Previous: Pointer (Intrinsic), Up: Data Types

6.2.11 Type Definition Possibilities


Next: , Up: Type Definition Possibilities
6.2.11.1 Subrange Types

GNU Pascal supports Standard Pascal's subrange types:

     program SubrangeDemo;
     type
       MonthInt = 1 .. 12;
       Capital = 'A' .. 'Z';
       ControlChar = ^A .. ^Z;  { `^A' = `Chr (1)' is a BP extension }
     begin
     end.

Also possible: Subranges of enumerated types:

     program EnumSubrangeDemo;
     type
       { This is an enumerated type. }
       Days = (Mon, Tue, Wed, Thu, Fri, Sat, Sun);
     
       { This is a subrange of `Days'. }
       Working = Mon .. Fri;
     
     begin
     end.

To increase performance, variables of such a type are aligned in a way which makes them fastest to access by the CPU. As a result, `1 .. 12' occupies 4 bytes of storage on an IA32 CPU.

For the case you want to save storage at the expense of speed, GPC provides a `packed' variant of these as an extension:

     program PackedSubrangeDemo;
     type
       MonthInt = packed 1 .. 12;
     begin
     end.

A variable of this type occupies the shortest possible (i.e., addressable) space in memory – one byte on an IA32 compatible CPU.

See also: packed.


Next: , Previous: Subrange Types, Up: Type Definition Possibilities
6.2.11.2 Array Types

     type
       array_type_identifier = array [index_type] of element_type

or

     type
       array_type_identifier = array [index_type, ..., index_type] of element_type

The reserved word array defines an array type. index_type has to be an ordinal type, subrange type or an enumerated type, where several index types, separated by commas, are allowed. element_type is an arbitrary type. An element of an array is accessed by array_type_variable [index_number]. The upper and lower index bounds can be determined by the intrinsic functions High and Low.

     type
       IntArray = array [1 .. 20] of Integer;
       Foo      = array [(Mo, Tu, We, Th, Fr, Sa, Su)] of Char;
       Bar      = array [0 .. 9, 'a' .. 'z', (Qux, Glork1, Fred)] of Real;
       Baz1     = array [1 .. 10] of IntArray;
       { equal (but declared differently): }
       Baz2     = array [1 .. 10, 1 .. 20] of Integer;

See also

High, Low


Next: , Previous: Array Types, Up: Type Definition Possibilities
6.2.11.3 Record Types

     type
       record_type_identifier = record
         field_identifier: type_definition;
         ...
         field_identifier: type_definition;
       end;

or, with a variant part,

     type
       record_type_identifier = record
         field_identifier: type_definition;
         ...
         field_identifier: type_definition;
       case bar: variant_type of
         selector: (field_declarations);
         selector: (field_declarations);
         ...
       end;

or, without a variant selector field,

     type
       record_type_identifier = record
         field_identifier: type_definition;
         ...
         field_identifier: type_definition;
       case variant_type of
         selector: (field_declarations);
         selector: (field_declarations);
         ...
       end;

The reserved word record defines a structure of fields. Records can be `packed' to save memory usage at the expense of speed.

The reserved word `record' and record types are defined in ISO 7185 Pascal. According to ISO Pascal, the variant type must be an identifier. GNU Pascal, like UCSD and Borland Pascal, also allows a subrange here.

A record field is accessed by record_type_variable . field_identifier

See also: packed, case Statement.


Next: , Previous: Record Types, Up: Type Definition Possibilities
6.2.11.4 Variant Records

GPC supports variant records like in EP and BP. The following construction is not allowed in Extended Pascal, but in BP and GPC:

     program BPVariantRecordDemo;
     
     type
       PersonRec = record
         Age: Integer;
       case EyeColor: (Red, Green, Blue, Brown) of
         Red, Green : (WearsGlasses: Boolean);
         Blue, Brown: (LengthOfLashes: Integer);
       end;
     
     begin
     end.

In EP, the variant field needs a type identifier, which, of course, also works in GPC:

     program EPVariantRecordDemo;
     
     type
       EyeColorType = (Red, Green, Blue, Brown);
     
       PersonRec = record
         Age: Integer;
       case EyeColor: EyeColorType of
         Red, Green : (WearsGlasses: Boolean);
         Blue, Brown: (LengthOfLashes: Integer);
       end;
     
     begin
     end.


Next: , Previous: Variant Records, Up: Type Definition Possibilities
6.2.11.5 EP's Schema Types including `String'

Schemata are types that depend on one or more variables, called discriminants. They are an ISO 10206 Extended Pascal feature.

     type
       RealArray (n: Integer) = array [1 .. n] of Real;
       Matrix (n, m: PositiveInteger) = array [1 .. n, 1 .. m] of Integer;

The type `RealArray' in this example is called a Schema with the discriminant `n'.

To declare a variable of such a type, write:

     var
       Foo: RealArray (42);

The discriminants of every global or local schema variable are initialized at the beginning of the procedure, function or program where the schema variable is declared.

Schema-typed variables “know” about their discriminants. Discriminants can be accessed just like record fields:

     program Schema1Demo;
     type
       PositiveInteger = 1 .. MaxInt;
       RealArray (n: Integer) = array [1 .. n] of Real;
       Matrix (n, m: PositiveInteger) = array [1 .. n, 1 .. m] of Integer;
     
     var
       Foo: RealArray (42);
     
     begin
       WriteLn (Foo.n)  { yields 42 }
     end.

Schemata may be passed as parameters. While types of schema variables must always have specified discriminants (which may be other variables), formal parameters (by reference or by value) may be of a schema type without specified discriminant. In this, the actual parameter may posses any discriminant. The discriminants of the parameters get their values from the actual parameters.

Also, pointers to schema variables may be declared without a discriminant:

     program Schema2Demo;
     type
       RealArray (n: Integer) = array [1 .. n] of Real;
       RealArrayPtr = ^RealArray;
     var
       Bar: RealArrayPtr;
     begin
     end.

When applying `New' to such a pointer, you must specify the intended value of the discriminant as a parameter:

     New (Bar, 137)

As a GNU Pascal extension, the above can also be written as

     Bar := New (RealArrayPtr, 137)

The allocated variable behaves like any other schema variable:

     program Schema3Demo;
     type
       RealArray (n: Integer) = array [1 .. n] of Real;
       RealArrayPtr = ^RealArray;
     var
       Bar: RealArrayPtr;
       i: Integer;
     begin
       Bar := New (RealArrayPtr, 137);
       for i := 1 to Bar^.n do
         Bar^[i] := 42
     end.

Since the schema variable “knows” its size, pointers to schemata can be disposed just like other pointers:

     Dispose (Bar)

Schemata are not limited to arrays. They can be of any type that normally requires constant values in its definition, for instance subrange types, or records containing arrays etc. (Sets do not yet work.)

References to the schema discriminants are allowed, and the with statement is also allowed, so one can say:

     program SchemaWithDemo;
     type
       RealArray (n: Integer) = array [1 .. n] of Real;
     var
       MyArray: RealArray (42);
     begin
       WriteLn (MyArray.n);  { writes 42 }
       with MyArray do
         WriteLn (n);        { writes 42 }
     end.

Finally, here is a somewhat exotic example. Here, a `ColoredInteger' behaves just like an ordinary integer, but it has an additional property `Color' which can be accessed like a record field.

     program SchemaExoticDemo;
     
     type
       ColorType = (Red, Green, Blue);
       ColoredInteger (Color: ColorType) = Integer;
     
     var
       Foo: ColoredInteger (Green);
     
     begin
       Foo := 7;
       if Foo.Color = Red then
         Inc (Foo, 2)
       else
         Foo := Foo div 3
     end.

An important schema is the predefined `String' schema (according to Extended Pascal). It has one predefined discriminant identifier Capacity. GPC implements the String schema as follows:

     type
       String (Capacity: Cardinal) = record
         Length: 0 .. Capacity;
         Chars: packed array [1 .. Capacity + 1] of Char
       end;

The Capacity field may be directly referenced by the user, the Length field is referenced by a predefined string function Length (Str) and contains the current string length. Chars contains the chars in the string. The Chars and Length fields cannot be directly referenced by a user program.

If a formal value parameter is of type `String' (with or without discriminant), the actual parameter may be either a String schema, a fixed string (character array), a single character, a string literal or a string expression. If the actual parameter is a `String' schema, it is copied for the parameter in the usual way. If it is not a schema, a `String' schema is created automatically, the actual parameter is copied to the new variable and the Capacity field of the new variable is set to the length of the actual parameter.

Actual parameters to `var' parameters of type `String' must be `String' schemata, not string literals or character arrays.

     program StringDemo (Output);
     
     type
       SType = String (10);
       SPtr  = ^String;
     
     var
       Str : SType;
       Str2: String (100000);
       Str3: String (20) value 'string expression';
       DStr: ^String;
       ZStr: SPtr;
       Len : Integer value 256;
       Ch  : Char value 'R';
     
     { `String' accepts any length of strings }
     procedure Foo (z: String);
     begin
       WriteLn ('Capacity: ', z.Capacity);
       WriteLn ('Length  : ', Length (z));
       WriteLn ('Contents: ', z);
     end;
     
     { Another way to use dynamic strings }
     procedure Bar (SLen: Integer);
     var
       LString: String (SLen);
       FooStr: type of LString;
     begin
       LString := 'Hello world!';
       Foo (LString);
       FooStr := 'How are you?';
       Foo (FooStr);
     end;
     
     begin
       Str  := 'KUKKUU';
       Str2 := 'A longer string variable';
       New (DStr, 1000);  { Select the string Capacity with `New' }
       DStr^ := 'The maximum length of this is 1000 chars';
       New (ZStr, Len);
       ZStr^ := 'This should fit here';
       Foo (Str);
       Foo (Str2);
       Foo ('This is a constant string');
       Foo ('This is a ' + Str3);
       Foo (Ch);  { A char parameter to string routine }
       Foo ('');  { An empty string }
       Foo (DStr^);
       Foo (ZStr^);
       Bar (10000);
     end.

In the above example, the predefined procedure New was used to select the capacity of the strings. Procedure Bar also has a string whose size depends of the parameter passed to it and another string whose type will be the same as the type of the first string, using the type of construct.

All string and character types are compatible as long as the destination string is long enough to hold the source in assignments. If the source string is shorter than the destination, the destination is automatically blank padded if the destination string is not of string schema type.


Next: , Previous: Schema Types, Up: Type Definition Possibilities
6.2.11.6 Set Types

     set_type_identifier = set of set_element_type;

set_type_identifier is a set of elements from set_element_type which is either an ordinal type, an enumerated type or a subrange type. Set element representatives are joined together into a set by brackets:

     [set_element, ..., set_element]

`[]' indicates the empty set, which is compatible with all set types. Note: Borland Pascal restricts the maximal set size (i.e. the range of the set element type) to 256, GNU Pascal has no such restriction. The number of elements a set variable is holding can be determined by the intrinsic set function Card (which is a GNU Pascal extension, in Extended Pascal and Borland Pascal you can use SizeOf instead but note the element type size in bytes, then) to the set. There are four intrinsic binary set operations: the union `+', the intersection `*' and the difference `-'. The symmetric difference `><' is an Extended Pascal extension.

See also

Card, SizeOf


Next: , Previous: Set Types, Up: Type Definition Possibilities
6.2.11.7 Pointer Types

     pointer_type_identifier = ^type_identifier;

A pointer of the type pointer_type_identifier holds the address at which data of the type type_identifier is situated. Unlike other identifier declarations, where all identifiers in definition part have to be declared before, in a pointer type declaration type_identifier may be declared after pointer_type_identifier. The data pointed to is accessed by `pointer_type_variable^'. To mark an unassigned pointer, the `nil' constant (which stands for “not in list”) has to be assigned to it, which is compatible with all pointer types.

     type
       ItselfFoo = ^ItselfFoo;  { possible but mostly senseless }
     
       PInt      = ^Integer;    { Pointer to an Integer }
     
       PNode     = ^TNode;      { Linked list }
       TNode     = record
         Key     : Integer;
         NextNode: PNode;
       end;
     
     var
       Foo, Bar: PInt;
     
     begin
       Foo := Bar;  { Modify address which foo is holding }
       Foo^ := 5;   { Access data foo is pointing to }
     end.

GPC also suports pointers to procedures or function and calls through them. This is a non-standard feature.

     program ProcPtrDemo (Output);
     
     type
       ProcPtr = ^procedure (i: Integer);
     
     var
       PVar: ProcPtr;
     
     procedure WriteInt (i: Integer);
     begin
       WriteLn ('Integer: ', i : 1)
     end;
     
     begin
       { Let PVar point to function WriteInt }
       PVar := @WriteInt;
     
       { Call the function by dereferencing the function pointer }
       PVar^ (12345)
     end.

See also: Pointer (Intrinsic).


Next: , Previous: Pointer Types, Up: Type Definition Possibilities
6.2.11.8 Procedural and Functional Types

For procedures without a parameter list:

     procedure_type_identifier = procedure name_identifier;

or functions:

     function_type_identifier =
            function name_identifier: function_result_type;

For procedures with a parameter list:

     procedure_type_identifier =
            procedure name_identifier (parameter_list);

or functions:

     function_type_identifier =
            function name_identifier (parameter_list): function_result_type;

Procedural types can be used as procedures or functions respectively, but also a value can be assigned to them. Procedural types are a Borland Pascal extension. In Borland Pascal, function_result_type can only be one of these types: ordinal types, real types, pointer types, the intrinsic `String' type. In GNU Pascal every function result type for procedural types is allowed.

BP has procedural and functional types:

     type
       CompareFunction = function (Key1, Key2: String): Integer;
     
     function Sort (Compare: CompareFunction);
     begin
       ...
     end;

Standard Pascal has procedural and functional parameters:

     function Sort (function Compare (Key1, Key2: String): Integer);
     begin
       ...
     end;

Both ways have pros and cons, e.g. in BP you can save, compare, trade, etc. procedural values, or build arrays of them, while the SP way does not require a type declaration and prevents problems with uninitialized or invalid pointers (which in BP will usually crash the program).

GPC supports both ways. An important feature of Standard Pascal (but not BP) that GPC also supports is the possibility to pass local routines as procedural or functional parameters, even if the called routine is declared far remote. The called routine can then call the passed local routine and it will have access to the original caller's local variables.

     program LocalProceduralParameterDemo;
     
     procedure CallProcedure (procedure Proc);
     begin
       Proc
     end;
     
     procedure MainProcedure;
     var LocalVariable: Integer;
     
       procedure LocalProcedure;
       begin
         WriteLn (LocalVariable)
       end;
     
     begin
       LocalVariable := 42;
       CallProcedure (LocalProcedure)
     end;
     
     begin
       MainProcedure
     end.

See also: The Procedure, The Function, Subroutine Parameter List Declaration, Procedure Call.


Next: , Previous: Procedural Types, Up: Type Definition Possibilities
6.2.11.9 Object Types

Object types are used to encapsulate data and methods. Furthermore, they implement a mechanism for inheritance.

See also

OOP


Next: , Previous: Object Types, Up: Type Definition Possibilities
6.2.11.10 Initial values to type denoters

A type may be initialized to a value of expression when it is declared, like a variable, as in:

     program TypeVarInitDemo;
     type
       Int10   = Integer value 10;
       FooType = Real;
       MyType  = Char value Pred ('A');
       EType   = (a, b, c, d, e, f, g) value d;
     
     const
       Answer = 42;
     
     var
       ii : Int10;                    { Value of ii set to 10 }
       ch : MyType  value Pred ('z');
       aa : Integer value Answer + 10;
       foo: FooType value Sqr (Answer);
       e1 : EType;                    { value set to d }
       e2 : EType value g;            { value set to g }
     begin
     end.

Extended Pascal requires the type initializers to be constant expressions. GPC allows any valid expression.

Note, however, that the expressions that affect the size of storage allocated for objects (e.g. the length of arrays) may contain variables only inside functions or procedures.

GPC evaluates the initial values used for the type when an identifier is declared for that type. If a variable is declared with a type-denoter that uses a type-name which already has an initial value the latter initialization has precedence.

@@ GPC does not know how to calculate constant values for math functions in the runtime library at compile time, e.g. `Exp (Sin (2.4567))', so you should not use these kind of expressions in object size expressions. (Extended Pascal allows this.)


Previous: Type Initializers, Up: Type Definition Possibilities
6.2.11.11 Restricted Types

GPC supports `restricted' types, defined in Extended Pascal. A value of a restricted type may be passed as a value parameter to a formal parameter possessing its underlying type, or returned as the result of a function. A variable of a restricted type may be passed as a variable parameter to a formal parameter possessing the same type or its underlying type. No other operations, such as accessing a component of a restricted type value or performing arithmetic, are possible.

     program RestrictedDemo;
     
     type
       UnrestrictedRecord = record
         a: Integer;
       end;
       RestrictedRecord = restricted UnrestrictedRecord;
     
     var
       r1: UnrestrictedRecord;
       r2: RestrictedRecord;
       i: restricted Integer;
       k: Integer;
     
     function AccessRestricted (p: UnrestrictedRecord): RestrictedRecord;
     var URes: UnrestrictedRecord;
     begin
       { The parameter is treated as unrestricted, even though the actual
         parameter may be restricted }
       URes.a := p.a;
       { It is allowed to assign a function result }
       AccessRestricted := URes;
     end;
     
     begin
       r1.a := 354;
     
       { Assigning a restricted function result to a restricted variable }
       { @@ Verify if this should really be allowed????? }
       r2 := AccessRestricted (r1);
     
       { Passing a restricted value to unrestricted formal parameter is ok }
       r2 := AccessRestricted (r2);
     
       {$ifdef BUG}
       { *** The following statements are not allowed *** }
       k := r2.a;      { field access (reading) }
       r2.a := 100;    { field access (writing) }
       r1 := r2;       { assignment source is restricted }
       r2 := r1;       { assignment target is restricted }
       r1 := AccessRestricted (r2); { assigning a restricted function
                                      result to an unrestricted object }
       i  := 16#ffff;  { assignment target is restricted }
       k  := i + 2;    { arithmetic with restricted value }
       {$endif}
     end.


Previous: Type Definition Possibilities, Up: Data Types

6.2.12 Machine-dependencies in Types


Next: , Up: Machine-dependencies in Types
6.2.12.1 Endianness

Endianness means the order in which the bytes of a value larger than one byte are stored in memory. This affects, e.g., integer values and pointers while, e.g., arrays of single-byte characters are not affected. The GPC `String' schema, however, contains `Capacity' and `Length' fields before the character array. These fields are integer values larger than one byte, so the `String' schema is affected by endianness.

Endianness depends on the hardware, especially the CPU. The most common forms are:

Note: There are processors which can run in both little-endian and big-endian mode, e.g. the MIPS processors. A single program, however, (unless it uses special machine code instructions) will always run in one endianness.

Under normal circumstances, programs do not need to worry about endianness, the CPU handles it by itself. Endianness becomes important when exchanging data between different machines, e.g. via binary files or over a network. To avoid problems, one has to choose the endianness to use for the data exchange. E.g., the Internet uses big-endian data, and most known data formats have a specified endianness (usually that of the CPU on which the format was originally created). If you define your own binary data format, you're free to choose the endianness to use.

To deal with endianness, GPC predefines the symbol `__BYTES_LITTLE_ENDIAN__' on little-endian machines and `__BYTES_BIG_ENDIAN__' on big-endian machines. Besides, the Run Time System defines the constant `BytesBigEndian' as False on little-endian machines and True on big-endian machines.

There are also the symbols `__BITS_LITTLE_ENDIAN__', `__BITS_BIG_ENDIAN__', `__WORDS_LITTLE_ENDIAN__', `__WORDS_BIG_ENDIAN__' and the constants `BitsBigEndian' and `WordsBigEndian' which concern the order of bits within a byte (e.g., in packed records) or of words within multiword-numbers, but these are usually less important.

The Run Time System also contains a number of routines to convert endianness and to read or write data from/to binary files in a given endianness, independent of the CPU's endianness. These routines are described in the RTS reference (see Run Time System), under `endianness'. The demo program endiandemo.pas contains an example on how to use these routines.


Previous: Endianness, Up: Machine-dependencies in Types
6.2.12.2 Alignment

(Under construction.) @@ ????


Next: , Previous: Data Types, Up: Programming

6.3 Operators

GNU Pascal supports all operators of ISO Pascal and Borland Pascal. In addition, you can define your own operators according to the Pascal-SC (PXSC) syntax.


Next: , Up: Operators

6.3.1 Built-in Operators

The following table lists all built-in GNU Pascal operators, ordered by precedence: `<' etc. have the lowest precedence, `not' etc. the highest. As usual, the precedence of operators can be superseded with parentheses.

In an assignment statement, `:=' has lower precedence than all operators. (This is rather obvious from the syntax of assignment statements, and is merely noted for programmers familiar with C where `=' is an operator.)

     <    =    >    in   <>   >=   <=
     +    -    or   +<   -<   +>   ->
     *    /    div  mod  and  shl  shr  xor  *<   /<   *>   />
     pow  **   ><
     not  @

The Pascal-SC (PXSC) operators `+<', `-<', `+>', `->', `*<', `/<', `*>', and `/>' are not yet implemented into GNU Pascal but may be defined by the user (see below).


Previous: Built-in Operators, Up: Operators

6.3.2 User-defined Operators

GNU Pascal allows the (re-)definition of binary operators according to the Pascal-SC (PXSC) syntax. The following vector addition example illustrates how to do this:

     program OperatorDemo;
     
     type
       Vector3 = record
         x, y, z: Real;
       end;
     
     var
       a, b, c: Vector3 = (1, 2, 3);
     
     operator + (u, v: Vector3) w: Vector3;
     begin
       w.x := u.x + v.x;
       w.y := u.y + v.y;
       w.z := u.z + v.z;
     end;
     
     begin
       c := a + b
     end.

Between the closing parenthesis of the argument list and the result variable (`w' in the above example), GPC allows an optional equal sign. This is not allowed in PXSC, but it is consistent with Extended Pascal's function result variable definitions, where the equal sign is obligatory (but also optional in GPC).

The argument types needn't be equal, and the name of the operator may be an identifier instead of a known symbol. You cannot define new symbols in GPC.

The PXSC operators `+>', `+<', etc. for exact numerical calculations currently are not implemented in GPC, but you can define them. Also, the other real-type operators do not meet the requirements of PXSC; a module which fixes that would be a welcome contribution.


Next: , Previous: Operators, Up: Programming

6.4 Procedure And Function Parameters


Next: , Up: Parameters

6.4.1 Parameters declared as `protected' or `const'

All the following works in GPC:

     procedure Foo (protected a, b, c: Integer);    { 3 arguments }
     procedure Foo (a, b, c, protected: Integer);   { 4 arguments }
     procedure Foo (a, b, protected, c: Integer);   { 4 arguments }
     procedure Foo (protected: Integer);            { 1 argument  }
     procedure Foo (var protected: Integer);        { 1 argument  }
     procedure Foo (protected protected: Integer);  { 1 argument  }

Furthermore, GPC supports const, according to BP, which is equivalent to either protected or protected var, up to the compiler's discretion.


Next: , Previous: Protected Parameters, Up: Parameters

6.4.2 The Standard way to pass arrays of variable size

@@ (Under construction.)

A feature of Standard Pascal level 1.


Previous: Conformant Arrays, Up: Parameters

6.4.3 BP's alternative to Conformant Arrays

Borland Pascal “open array” formal parameters are implemented into GPC. Within the function body, they have integer type index with lower bound 0.

In constrast to conformant arrays (which are not supported by BP), open arrays allow any ordinal type as the index of the actual parameter (which is useful, e.g., if you want to be able to pass values of any enumeration type). However, they lose information about the lower bound (which is a problem, e.g., if you want to return information to the caller that relates to the actual array index, like the function `IOSelect' in the Run Time System does).


Next: , Previous: Pointer Arithmetics, Up: Programming

6.5 Accessing parts of strings (and other arrays)

GPC allows the access of parts (“slices”) of strings as defined in Extended Pascal. For example:

     program StringSliceDemo;
     
     const
       HelloWorld = 'Hello, world!';
     
     begin
       WriteLn (HelloWorld[8 .. 12])  { yields `world' }
     end.

As an extension, it also allows write access to a string slice:

     program SliceWriteDemo;
     
     var
       s: String (42) = 'Hello, world!';
     
     begin
       s[8 .. 12] := 'folks';
       WriteLn (s)  { yields `Hello, folks!' }
     end.

As a further extension, GPC allows slice access also to non-string arrays. However, the usefulness of this feature is rather limited because of Pascal's strict type checking rules: If you have, e.g., an `array [1 .. 10] of Integer' and take a slice `[1 .. 5]' of it, it will not be compatible to another `array [1 .. 5] of Integer' because distinct array types are not compatible in Pascal, even if they look the same.

However, array slice access can be used in connection with conformant or open array parameters. See the program arrayslicedemo.pas (in the demos directory) for an example.


Next: , Previous: Parameters, Up: Programming

6.6 Pointer Arithmetics

GPC allows to increment, decrement, compare, and subtract pointers or to use them in `for' loops just like the C language.

GPC implements the address operator @ (a Borland Pascal extension).

     program PointerArithmeticDemo;
     var
       a: array [1 .. 7] of Char;
       p, q: ^Char;
       i: Integer;
     
     {$X+}  { We need extended syntax for pointer arithmetic }
     
     begin
       for p := @a[1] to @a[7] do
         p^ := 'x';
     
       p := @a[7];
       q := @a[3];
       while p > q do
         begin
           p^ := 'y';
           Dec (p)
         end;
     
       p := @a[7];
       q := @a[3];
       i := q - p;    { yields 4 }
     end.

Incrementing a pointer by one means to increment the address it contains by the size of the variable it is pointing to. For typeless pointers (`Pointer'), the address is incremented by one instead.

Similar things hold when decrementing a pointer.

Subtracting two pointers yields the number of variables pointed to between both pointers, i.e. the difference of the addresses divided by the size of the variables pointed to. The pointers must be of the same type.


Next: , Previous: String Slice Access, Up: Programming

6.7 Type Casts

In some cases, especially in low-level situations, Pascal's strong typing can be an obstacle. To temporarily circumvent this, GPC defines explicit “type casts” in a Borland Pascal compatible way.

There are two kinds of type casts, value type casts and variable type casts.

Value type casts

To convert a value of one data type into another type, you can use the target type like the name of a function that is called. The value to be converted can be a variable or an expression. Both the value's type and the destination type must be ordinal or pointer types. The ordinal value (extended to pointers to mean the address) is preserved in the cast.

An example:

     program TypeCastDemo;
     
     var
       Ch: Char;
       i: Integer;
     
     begin
       i := Integer (Ch)
     end.

Another, more complicated, example:

     program TypeCst2Demo;
     
     type
       CharPtr = ^Char;
       CharArray = array [0 .. 99] of Char;
       CharArrayPtr = ^CharArray;
     
     var
       Foo1, Foo2: CharPtr;
       Bar: CharArrayPtr;
     
     {$X+} { We need extended syntax in order to use ``Succ'' on a pointer }
     
     begin
       Foo1 := CharPtr (Bar);
       Foo2 := CharPtr (Succ (Bar))
     end.

However, because of risks involved with type casts, explained below, and because type-casts are non-standard, you should try to avoid type casts whenever possible – and it should be possible in most cases. For instance, the first example above could use the built-in function “Ord” instead of the type cast:

     i := Ord (Ch);

The assignments in the second example could be written in the following way without any type casts:

     Foo1 := @Bar^[0];
     Foo2 := @Bar^[1];

Note: In the case of pointers, a warning is issued if the dereferenced target type requires a bigger alignment than the dereferenced source type (see Alignment).

Variable type casts

It is also possible to temporarily change the type of a variable (more generally, any “lvalue”, i.e. something whose address can be taken), without converting its contents in any way. This is called variable type casting.

The syntax is the same as for value type casting. The type-casted variable is still the same variable (memory location) as the original one, just with a different type. Outside of the type cast, the variable keeps its original type.

There are some important differences between value and variable type casting:

There are cases where a type-cast could be either a value or a variable cast. This is when both types are ordinal or pointer, and of the same size, and the value is an lvalue. Fortunately, in those cases, the results of both forms are the same, since the same ordinal values (or pointer addresses) are represented by the same bit patterns (when of the same size). Therefore, it doesn't matter which form of type-casting is actually used in these cases.

When dealing with objects (see OOP), it is sometimes necessary to cast a polymorphic pointer to an object into a pointer to a more specialized (derived) object (after checking the actual type). However, the `as' operator is a safer approach, so type-casts should be used there only for backward-compatibility (e.g., to BP).

See also: absolute, Alignment, Endianness, OOP, Ord, Chr, Round, Trunc.


Next: , Previous: Type Casts, Up: Programming

6.8 Object-Oriented Programming

GNU Pascal allows multiple object models. The oldest one follows the object model of Borland Pascal 7.0. The BP object extensions are almost fully implemented into GPC. This includes inheritance, virtual and non-virtual methods, constructors, destructors, pointer compatibility, extended `New' syntax (with constructor call and/or as a Boolean function), extended `Dispose' syntax (with destructor call).

The Borland object model is different from the ISO draft, but now we have also partial support of ISO draft (plus the Borland Delphi Object Extensions which are quite similar to the ISO draft). Moreover most of traditional Mac Pascal object model is covered.

The syntax for an object type declaration is as follows:

     program ObjectDemo;
     
     type
       Str100 = String (100);
     
       FooParentPtr = ^FooParent;
       FooPtr = ^Foo;
     
       FooParent = object
         constructor Init;
         destructor Done; virtual;
         procedure Bar (c: Real); virtual;
         function Baz (b, a, z: Char) = s: Str100;  { not virtual }
       end;
     
       Foo = object (FooParent)
         x, y: Integer;
         constructor Init (a, b: Integer);
         destructor Done; virtual;
         procedure Bar (c: Real); virtual;  { overrides `FooParent.Bar' }
         z: Real;  { GPC extension: data fields after methods }
         function Baz: Boolean;  { new function }
       end;
     
     constructor FooParent.Init;
     begin
       WriteLn ('FooParent.Init')
     end;
     
     destructor FooParent.Done;
     begin
       WriteLn ('I''m also done.')
     end;
     
     procedure FooParent.Bar (c: Real);
     begin
       WriteLn ('FooParent.Bar (', c, ')')
     end;
     
     function FooParent.Baz (b, a, z: Char) = s: Str100;
     begin
       WriteStr (s, 'FooParent.Baz (', b, ', ', a, ', ', z, ')')
     end;
     
     constructor Foo.Init (a, b: Integer);
     begin
       inherited Init;
       x := a;
       y := b;
       z := 3.4;
       FooParent.Bar (1.7)
     end;
     
     destructor Foo.Done;
     begin
       WriteLn ('I''m done.');
       inherited Done
     end;
     
     procedure Foo.Bar (c: Real);
     begin
       WriteLn ('Foo.Bar (', c, ')')
     end;
     
     function Foo.Baz: Boolean;
     begin
       Baz := True
     end;
     
     var
       Ptr: FooParentPtr;
     
     begin
       Ptr := New (FooPtr, Init (2, 3));
       Ptr^.Bar (3);
       Dispose (Ptr, Done);
       New (Ptr, Init);
       with Ptr^ do
         WriteLn (Baz ('b', 'a', 'z'))
     end.

Remarks:

A pointer to `FooParent' may be assigned the address of a `Foo' object. A `FooParent' formal `var' parameter may get a `Foo' object as the actual parameter. In such cases, a call to a `virtual' method calls the child's method, whereas a call to a non-`virtual' method selects the parent's one:

     var
       MyFooParent: FooParentPtr;
       SomeFoo: Foo;
     
     [...]
     
       SomeFoo.Init (4, 2);
       MyFooParent := @SomeFoo;
       MyFooParent^.bar (3.14);  { calls `foo.bar' }
       MyFooParent^.baz ('b', 'a', 'z');  { calls `fooParent.baz' }
       if SomeFoo.baz then  { calls `foo.baz' }
         WriteLn ('Baz!');

In a method, an overwritten method of a parent object can be called either prefixing it with the parent type name, or using the keyword `inherited':

     procedure Foo.Bar (c: Real);
     begin
       z := c;
       inherited bar (z)  { or: FooParent.Bar (z) }
     end;

Use `FooParent.bar (z)' if you want to be sure that this method is called, even if somebody decides not to derive `foo' directly from `fooParent' but to have some intermediate object. If you want to call the method `bar' of the immediate parent – whether it be `fooParent' or whatever – use `inherited bar (z)'.

To allocate an object on the heap, use `New' in one of the following manners:

     var
       MyFoo: FooPtr;
     
       [...]
     
       New (MyFoo, Init (4, 2));
     
       MyFooParent := New (FooPtr, Init (4, 2))

The second possibility has the advantage that `MyFoo' needn't be a `FooPtr' but can also be a `FooParentPtr', i.e. a pointer to an ancestor of `foo'.

Destructors can and should be called within Dispose:

     Dispose (MyFooParent, Fini)


Next: , Previous: OOP, Up: Programming

6.9 Compiler Directives And The Preprocessor

GPC, like UCSD Pascal and BP, treats comments beginning with a `$' immediately following the opening `{' or `(*' as a compiler directive. As in Borland Pascal, {$...} and (*$...*) are equivalent. When a single character plus a `+' or `-' follows, this is also called a compiler switch. All of these directives are case-insensitive (but some of them have case-sensitive arguments). Directives are local and can be changed during one compilation (except include files etc. where this makes no sense).

In general, compiler directives are compiler-dependent. (E.g., only the include directive {$I FileName} is common to UCSD and BP.) Because of BP's popularity, GPC supports all of BP's compiler directives (and ignores those that are unnecessary on its platforms – these are those not listed below), but it knows a lot more directives.

Some BP directives are – of course not by chance – just an alternative notation for C preprocessor directives. But there are differences: BP's conditional definitions (`{$define Foo}') go into another name space than the program's definitions. Therefore you can define conditionals and check them via {$ifdef Foo}, but the program will not see them as an identifier `Foo', so macros do not exist in Borland Pascal.

GPC does support macros, but disables this feature when the `--no-macros' option or the dialect option `--borland-pascal' or `--delphi' is given, to mimic BP's behaviour. Therefore, the following program will react differently when compiled with GPC either without special options or with, e.g., the `--borland-pascal' option (and in the latter case, it behaves the same as when compiled with BP).

     program MacroDemo;
     
     const Foo = 'Borland Pascal';
     
     {$define Foo 'Default'}
     
     begin
       WriteLn (Foo)
     end.

Of course, you should not rely on such constructs in your programs. To test if the program is compiled with GPC, you can test the `__GPC__' conditional, and to test the dialect used in GPC, you can test the dialect, e.g., with `{$ifopt borland-pascal}'.

In general, almost every GPC specific command line option (see GPC Command Line Options) can be turned into a compiler directive (exceptions are those options that contain directory names, such as `--unit-path', because they refer to the installation on a particular system, and therefore should be set system-wide, rather than in a source file):

     --foo       {$foo}
     --no-foo    {$no-foo}
     -Wbar       {$W bar}     { note the space after the `W' }
     -Wno-bar    {$W no-bar}

The following table lists some such examples as well as all those directives that do not correspond to command-line options or have syntactical alternatives (for convenience and/or BP compatibility).

     --[no-]short-circuit   $B+ $B- like in Borland Pascal:
                                    $B- means short-circuit Boolean
                                    operators; $B+ complete evaluation
     
     --[no-]io-checking     $I+ $I- like in Borland Pascal:
                                    enable/disable I/O checking
     
     --[no-]range-checking  $R+ $R- like in Borland Pascal:
                                    enable/disable range checking
     
     --[no-]stack-checking  $S+ $S- like in Borland Pascal:
                                    enable/disable stack checking
     
     --[no-]typed-address   $T+ $T- like in Borland Pascal:
                                    make the result of the address
                                    operator and the Addr function a
                                    typed or untyped pointer
     
     -W[no-]warnings        $W+ $W- enable/disable warnings. Note: in
                                    `--borland-pascal' mode, the
                                    short version is disabled because
                                    $W+/$W- has a different meaning in
                                    Borland Pascal (which can safely be
                                    ignored in GPC), but the long version
                                    is still available.
     
     --[no-]extended-syntax $X+ $X- mostly like in Borland Pascal:
                                    enable/disable extended syntax
                                    (ignore function resuls, operator
                                    definitions, `PChar', pointer
                                    arithmetic, ...)
     
     --borland-pascal               disable or warn about GPC features
     --extended-pascal              not supported by the standard or
     --pascal-sc                    dialect given, do not warn about its
     etc.                           ``dangerous'' features (especially BP).
                                    The dialect can be changed during one
                                    compilation via directives like,
                                    e.g., `{$borland-pascal}'.
     
     {$M Hello!}                    write message `Hello!' to
                                    standard error during compilation. In
                                    `--borland-pascal' mode, it is
                                    ignored it if only numbers follow
                                    (for compatibility to Borland
                                    Pascal's memory directive)
     
     {$define FOO}                  like in Borland Pascal:
     or                             define FOO (for conditional compilation)
     {$CIDefine FOO}                (case-insensitively)
     
     --cidefine=FOO                 the same on the command line
     
     {$CSDefine FOO}                define FOO case-sensitively
     
     -D FOO                         the same on the command line
     or                             Note: `--define' on the command
     --csdefine=FOO                 line is case-sensitive like in GCC,
     or                             but `{$define}' in the source code
     --define=FOO                   is case-insensitive like in BP
     
     {$define loop while True do}   define `loop' to be `while True do'
     or                             as a macro like in C. The name of the
     {$CIDefine loop ...}           macro is case-insensitive. Note:
                                    Macros are disabled in
                                    `--borland-pascal' mode because BP
                                    doesn't support macros.
     
     --cidefine="loop=..."          the same on the command line
     
     {$CSDefine loop ...}           define a case-sensitive macro
     
     --csdefine="loop=..."          the same on the command line
     or
     --define="loop=..."
     
     {$I FileName}                  like in Borland Pascal:
                                    include filename.pas
                                    (the name is converted to lower case)
     
     {$undef FOO}                   like in Borland Pascal: undefine FOO
     
     {$ifdef FOO}                   conditional compilation
       ...                          (like in Borland Pascal).
     {$else}                        Note: GPC predefines the symbol
       ...                          `__GPC__' (with two leading
     {$endif}                       and trailing underscores).
     
     {$include "filename.pas"}      include (case-sensitive)
     
     {$include <filename.pas>}      the same, but don't search in the
                                    current directory
...

and all the other C preprocessor directives.

You also can use the preprocessor directives in C style, e.g. `#include', but this is deprecated because of possible confusion with Borland Pascal style `#42' character constants. Besides, in the Pascal style, e.g. `{$include "foo.bar"}', there may be more than one directive in the same line.


Next: , Previous: Compiler Directives, Up: Programming

6.10 Routines Built-in or in the Run Time System

In this section we describe the routines and other declarations that are built into the compiler or part of the Run Time System, sorted by topics.


Next: , Up: Library Routines

6.10.1 File Routines

Extended Pascal treats files quite differently from Borland Pascal. GPC supports both forms, even in mixed ways, and provides many extensions.

@@ A lot missing here

Note that Prospero's Pascal defaults to creating the file if it does not exists! You need to use Prospero's local addition of setting b.Existing to True to work-around this. GPC does not behave like this.


Next: , Previous: File Routines, Up: Library Routines

6.10.2 String Operations

In the following description, s1 and s2 may be arbitrary string expressions, s is a variable of string type.

WriteStr (s, write-parameter-list)
ReadStr (s1, read-parameter-list)
Write to a string and read from a string. The parameter lists are identical to `Write'/`Read' from Text files. The semantics is closely modeled after file I/O.
Index (s1, s2)
If s2 is empty, return 1 else if s1 is empty return 0 else returns the position of s2 in s1 (an integer).
Length (s1)
Return the length of s1 (an integer from 0 .. s1.Capacity).
Trim (s1)
Returns a new string with spaces stripped of the end of s.
SubStr (s1, i)
SubStr (s1, i, j)
Return a new substring of s1 that contains j characters starting from i. If j is missing, return all the characters starting from i.
EQ (s1, s2)
NE (s1, s2)
LT (s1, s2)
LE (s1, s2)
GT (s1, s2)
GE (s1, s2)
Lexicographic comparisons of s1 and s2. Returns a boolean result. Strings are not padded with spaces.
s1 = s2
s1 <> s2
s1 < s2
s1 <= s2
s1 > s2
s1 >= s2
Lexicographic comparisons of s1 and s2. Returns a boolean result. The shorter string is blank padded to length of the longer one, but only in `--extended-pascal' mode.

GPC supports string catenation with the + operator or the `Concat' function. All string-types are compatible, so you may catenate any chars, fixed length strings and variable length strings.

     program ConcatDemo (Input, Output);
     
     var
       Ch  : Char;
       Str : String (100);
       Str2: String (50);
       FStr: packed array [1 .. 20] of Char;
     
     begin
        Ch := '$';
        FStr := 'demo';  { padded with blanks }
        Write ('Give me some chars to play with: ');
        ReadLn (Str);
        Str := '^' + 'prefix:' + Str + ':suffix:' + FStr + Ch;
        WriteLn (Concat ('Le', 'ng', 'th'), ' = ', Length (Str));
        WriteLn (Str)
     end.

Note: The length of strings in GPC is limited only by the range of `Integer' (at least 32 bits, i.e., 2 GB, on most platforms), or the available memory, whichever is smaller).

When trying to write programs portable to other EP compilers, it is however safe to assume a limit of about 32 KB. At least Prospero's Extended Pascal compiler limits strings to 32760 bytes. DEC Pascal limits strings to 65535 bytes.


Next: , Previous: String Operations, Up: Library Routines

6.10.3 Accessing Command Line Arguments

GPC supports access to the command line arguments with the BP compatible ParamStr and ParamCount functions.

The program below accesses the command line arguments.

     program CommandLineArgumentsDemo (Output);
     
     var
       Counter: Integer;
     
     begin
       WriteLn ('This program displays command line arguments one per line.');
       for Counter := 0 to ParamCount do
         WriteLn ('Command line argument #', Counter, ' is `',
                  ParamStr (Counter), '''')
     end.


Next: , Previous: Accessing Command Line Arguments, Up: Library Routines

6.10.4 Memory Management Routines

Besides the standard `New' and `Dispose' routines, GPC also allows BP style dynamic memory management with GetMem and FreeMem:

     GetMem (MyPtr, 1024);
     FreeMem (MyPtr, 1024);

One somehow strange feature of Borland is not supported: You cannot free parts of a variable with FreeMem, while the rest is still used and can be freed later by another FreeMem call:

     program PartialFreeMemDemo;
     
     type
       Vector = array [0 .. 1023] of Integer;
       VecPtr = ^Vector;
     
     var
       p, q: VecPtr;
     
     begin
       GetMem (p, 1024 * SizeOf (Integer));
       q := VecPtr (@p^[512]);
     
       { ... }
     
       FreeMem (p, 512 * SizeOf (Integer));
     
       { ... }
     
       FreeMem (q, 512 * SizeOf (Integer));
     end.


Next: , Previous: Memory Management Routines, Up: Library Routines

6.10.5 Operations for Integer and Ordinal Types


Next: , Previous: Operations for Integer and Ordinal Types, Up: Library Routines

6.10.6 Complex Number Operations

@@ A lot of details missing here

The following sample programs illustrates most of the Complex type operations.

     program ComplexOperationsDemo (Output);
     
     var
       z1, z2: Complex;
       Len, Angle: Real;
     
     begin
       z1 := Cmplx (2, 1);
       WriteLn;
       WriteLn ('Complex number z1 is: (', Re (z1) : 1, ',', Im (z1) : 1, ')');
       WriteLn;
       z2 := Conjugate(z1); { GPC extension }
       WriteLn ('Conjugate of z1 is: (', Re (z2) : 1, ',', Im (z2) : 1, ')');
       WriteLn;
       Len   := Abs (z1);
       Angle := Arg (z1);
       WriteLn ('The polar representation of z1 is: Length=', Len : 1,
                ', Angle=', Angle : 1);
       WriteLn;
       z2 := Polar (Len, Angle);
       WriteLn ('Converting (Length, Angle) back to (x, y) gives: (',
                Re (z2) : 1, ',', Im (z2) : 1, ')');
       WriteLn;
       WriteLn ('The following operations operate on the complex number z1');
       WriteLn;
       z2 := ArcTan (z1);
       WriteLn ('ArcTan (z1) = (', Re (z2), ', ', Im (z2), ')');
       WriteLn;
       z2 := z1 ** 3.141;
       WriteLn ('z1 ** 3.141 =', Re (z2), ', ', Im (z2), ')');
       WriteLn;
       z2 := Sin (z1);
       WriteLn ('Sin (z1) = (', Re (z2), ', ', Im (z2), ')');
       WriteLn ('(Cos, Ln, Exp, SqRt and Sqr exist also.)');
       WriteLn;
       z2 := z1 pow 8;
       WriteLn ('z1 pow 8 = (', Re (z2), ', ', Im (z2), ')');
       WriteLn;
       z2 := z1 pow (-8);
       WriteLn ('z1 pow (-8) = (', Re (z2), ', ', Im (z2), ')');
     end.


Next: , Previous: Complex Number Operations, Up: Library Routines

6.10.7 Set Operations

GPC supports Standard Pascal set operations. In addition it supports the Extended Pascal set operation symmetric difference (set1 >< set2) operation whose result consists of those elements which are in exactly one of the operannds.

It also has a function that counts the elements in the set: `a := Card (set1)'.

In the following description, S1 and S2 are variables of set type, s is of the base type of the set.

S1 := S2
Assign a set to a set variable.
S1 + S2
Union of sets.
S1 - S2
Difference between two sets.
S1 * S2
Intersection of two sets.
S1 >< S2
Symmetric difference
S1 = S2
Comparison between two sets. Returns boolean result. True if S1 has the same elements as S2.
S1 <> S2
Comparison between two sets. Returns boolean result. True if S1 does not have the same elements as S2.
S1 < S2
S2 > S1
Comparison between two sets. Returns boolean result. True if S1 is a strict subset of S2.
S1 <= S2
S2 >= S1
Comparison between two sets. Returns boolean result. True if S1 is a subset of (or equal to) S2.
s in S1
Set membership test between an element s and a set. Returns boolean result. True if s is an element of S1.

The following example demonstrates some set operations. The results of the operations are given in the comments.

     program SetOpDemo;
     
     type
       TCharSet = set of Char;
     
     var
       S1, S2, S3: TCharSet;
       Result: Boolean;
     
     begin
       S1 := ['a', 'b', 'c'];
       S2 := ['c', 'd', 'e'];
       S3 := S1 + S2;       { S3 = ['a', 'b', 'c', 'd', 'e'] }
       S3 := S1 * S2;       { S3 = ['c'] }
       S3 := S1 - S2;       { S3 = ['a', 'b'] }
       S3 := S1 >< S2;      { S3 = ['a', 'b', 'd', 'e'] }
     
       S1 := ['c', 'd', 'e'];
       Result := S1 = S2;   { False }
       Result := S1 < S2;   { False }
       Result := S1 <= S2;  { True }
     
       S1 := ['c', 'd'];
       Result := S1 <> S2;  { True }
       Result := S2 > S1;   { True }
       Result := S2 >= S1   { True }
     end.


Previous: Set Operations, Up: Library Routines

6.10.8 Date And Time Routines

procedure GetTimeStamp (var t: TimeStamp);
function Date (t: TimeStamp): packed array [1 .. DateLength] of Char;
function Time (t: TimeStamp): packed array [1 .. TimeLength] of Char;

DateLength and TimeLength are implementation dependent constants.

GetTimeStamp (t) fills the record `t' with values. If they are valid, the Boolean flags are set to True.

TimeStamp is a predefined type in the Extended Pascal standard. It may be extended in an implementation, and is indeed extended in GPC. For the full definition of `TimeStamp', see TimeStamp.


Next: , Previous: Library Routines, Up: Programming

6.11 Interfacing with Other Languages

The standardized GNU compiler back-end makes it relatively easy to share libraries between GNU Pascal and other GNU compilers. On Unix-like platforms (not on Dos-like platforms), the GNU compiler back-end usually complies to the standards defined for that system, so communication with other compilers should be easy, too.

In this chapter we discuss how to import libraries written in other languages, and how to import libraries written in GNU Pascal from other languages. While the examples will specialize to compatibility to GNU C, generalization is straightforward if you are familiar with the other language in question.


Next: , Up: Other Languages

6.11.1 Importing Libraries from Other Languages

To use a function written in another language, you need to provide an external declaration for it – either in the program, or in the interface part of a unit, or a module.

Let's say you want to use the following C library from Pascal:

     File `callc.c':
     
     #include <unistd.h>
     #include "callc.h"
     
     int foo = 1;
     
     void bar (void)
     {
       sleep (foo);
     }
     File `callc.h':
     
     /* Actually, we wouldn't need this header file, and could instead
        put these prototypes into callc.c, unless we want to use callc.c
        also from other C source files. */
     
     extern int foo;
     extern void bar (void);

Then your program can look like this:

     program CallCDemo;
     
     {$L callc.c}  { Or: `callc.o' if you don't have the source }
     
     var
       MyFoo: CInteger; external name 'foo';
     
     procedure Bar; external name 'bar';
     
     begin
       MyFoo := 42;
       Bar
     end.

Or, if you want to provide a `CallCUnit' unit:

     unit CallCUnit;
     
     interface
     
     var
       MyFoo: CInteger; external name 'foo';
     
     procedure Bar; external name 'bar';
     
     implementation
     
     {$L callc.c}  { Or: `callc.o' if you don't have the source }
     
     end.
     program CallCUDemo;
     
     uses CallCUnit;
     
     begin
       MyFoo := 42;
       Bar
     end.

You can either link your program manually with `callc.o' or put a compiler directive `{$L callc.o}' into your program or unit, and then GPC takes care of correct linking. If you have the source of the C library (you always have it if it is Free Software), you can even write `{$L callc.c}' in the program (like above). Then GPC will also link with callc.o, but in addition GPC will run the C compiler whenever callc.c has changed if `--automake' is given, too.

While it is often convenient, there is no must to give the C function `bar' the name `Bar' in Pascal; you can name it as you like (e.g., the variable `MyFoo' has a C name of `foo' in the example above).

If you omit the `name', the default is the Pascal identifier, converted to lower-case. So, in this example, the `name' could be omitted for `Bar', but not for `MyFoo'.

It is important that data types of both languages are mapped correctly onto each other. C's `int', for instance, translates to GPC's `CInteger', and C's `unsigned long' to `MedCard'. For a complete list of integer types with their C counterparts, see Integer Types.

In some cases it can be reasonable to translate a C pointer parameter to a Pascal `var' parameter. Since const parameters in GPC can be passed by value or by reference internally, possibly depending on the system, `const foo *' parameters to C functions cannot reliably be declared as `const' in Pascal. However, Extended Pascal's `protected var' can be used since this guarantees passing by reference.

Some libraries provide a `main' function and require your program's “main” to be named differently. To achive this with GPC, invoke it with an option `--gpc-main="GPCmain"' (where `GPCmain' is an example how you might want to name the program). You can also write it into your source as a directive `{$gpc-main="GPCmain"}'.


Previous: Importing Libraries from Other Languages, Up: Other Languages

6.11.2 Exporting GPC Libraries to Other Languages

The .o files produced by GPC are in the same format as those of all other GNU compilers, so there is no problem in writing libraries for other languages in Pascal. To use them, you will need to write kind of interface – a header file in C. However there are some things to take into account, especially if your Pascal unit exports objects:


Next: , Previous: Other Languages, Up: Programming

6.12 Notes for Debugging


Next: , Previous: Notes for Debugging, Up: Programming

6.13 How to use I18N in own programs

This chapter discusses shortly how to use the Internationalization (I18N) features of GNU Pascal.

Prerequisite

You need to have gettext installed. Try to compile demos/gettextdemo.pas. Furthermore, you should download a tool named `pas2po' from http://www.gnu-pascal.org/contrib/eike/.

The source

We would like to translate the messages provided with this simple example different languages (here: German) without touching the source for each language:

     program Hello1;
     
     begin
       WriteLn ('Hello, World!');
       WriteLn ('The answer of the questions is: ', 42)
     end.

Preparing the source

To do so, we must prepare the source to use gettext:

     program Hello2;
     
     uses GPC, Intl;
     
     var s: TString;
     
     begin
       Discard (BindTextDomain ('hello2', '/usr/share/locale/'));
       Discard (TextDomain ('hello2'));
       WriteLn (GetText ('Hello, World!'));
       s := FormatString (GetText ('The answer of the questions is %s'), 42);
       WriteLn (s)
     end.

`BindTextDomain' sets the path to find our message catalogs in the system. This path is system dependent. `TextDomain' tells the program to use this catalog. `GetText' looks up the given string in the catalog and returns a translated string within the current locale settings. `FormatString' replaces some format specifiers with the following argument. `%s' is the first following argument. After this step is done, we do not need to touch the sourcefile any longer. The output of this program is as follows:

     Hello, World!
     The answer of the questions is 42

Getting the translatable strings

There are lots of strings in the above example, but only those surrounded with `GetText' should be translated. We use `pas2po hello2.pas -o hello2.po' to extract the messages. The output is:

     # This file was created by pas2po with 'hello2.pas'.
     # Please change this file manually.
     # SOME DESCRIPTIVE TITLE.
     # Copyright (C) YEAR Free Software Foundation, Inc.
     # FIRST AUTHOR <EMAIL@ADDRESS>, YEAR.
     #
     #, fuzzy
     msgid ""
     msgstr ""
     "Project-Id-Version: PACKAGE VERSION\n"
     "POT-Creation-Date: 2003-04-27 20:48+0200\n"
     "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
     "Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
     "Language-Team: LANGUAGE <LL@li.org>\n"
     "MIME-Version: 1.0\n"
     "Content-Type: text/plain; charset=CHARSET\n"
     "Content-Transfer-Encoding: 8bit\n"
     
     #hello2.pas:10
     msgid "Hello, World!"
     msgstr ""
     
     #hello2.pas:11
     msgid "The answer of the questions is %s"
     msgstr ""

Now we translate the message ids into German language, and set some needful informations at their appropriate places. The following steps must be repeated for each language we would like to support:

     # This file was created by pas2po with 'hello2.pas'.
     # Copyright (C) 2003 Free Software Foundation, Inc.
     # Eike Lange  <eike@g-n-u.de>, 2003.
     msgid ""
     msgstr ""
     "Project-Id-Version: Hello2 1.0\n"
     "POT-Creation-Date: 2003-04-27 12:00+0200\n"
     "PO-Revision-Date: 2003-04-27 12:06+0200\n"
     "Last-Translator: Eike Lange <eike@g-n-u.de>\n"
     "Language-Team: de <de@li.org>\n"
     "MIME-Version: 1.0\n"
     "Content-Type: text/plain; charset=utf-8\n"
     "Content-Transfer-Encoding: 8bit\n"
     
     #hello2.pas:10
     msgid "Hello, World!"
     msgstr "Hallo, Welt!"
     
     #hello2.pas:11
     msgid "The answer of the questions is %s"
     msgstr "'%s' lautet die Antwort auf die Frage."

Please note that we swapped text and numeric arguments and added some single quotes arround the first argument. We compile the message catalog with `msgfmt -vv hello2.po -o hello2.mo' and install the file hello2.mo at /usr/share/locale/de/LC_MESSAGES/ With a german locale setting, the output should be as follows:

     Hallo, Welt!
     '42' lautet die Antwort auf die Frage.

System dependent notes:

The topmost path where message catalogs reside is system dependent:

for DJGPP:
`GetEnv ('$DJDIR') + '/share/locale''
for Mac OS X:
/usr/share/locale or /sw/share/locale
for Linux, *BSD:
/usr/share/locale or /usr/local/share/locale

See also

Gettext, FormatString, Intl.


Next: , Previous: I18N, Up: Programming

6.14 Pascal declarations for GPC's Run Time System

Below is a Pascal source of the declarations in GPC's Run Time System (RTS). A file gpc.pas with the same contents is included in the GPC distribution in a units subdirectory of the directory containing libgcc.a. (To find out the correct directory for your installation, type `gpc --print-file-name=units' on the command line.)

     { This file was generated automatically by make-gpc-pas.
       DO NOT CHANGE THIS FILE MANUALLY! }
     
     { Pascal declarations of the GPC Run Time System that are visible to
       each program.
     
       This unit contains Pascal declarations of many RTS routines which
       are not built into the compiler and can be called from programs.
       Don't copy the declarations from this unit into your programs, but
       rather include this unit with a `uses' statement. The reason is
       that the internal declarations, e.g. the linker names, may change,
       and this unit will be changed accordingly. @@In the future, this
       unit might be included into every program automatically, so there
       will be no need for a `uses' statement to make the declarations
       here available.
     
       Note about `protected var' parameters:
       Since `const' parameters in GPC may be passed by value *or* by
       reference internally, possibly depending on the system,
       `const foo *' parameters to C functions *cannot* reliably be
       declared as `const' in Pascal. However, Extended Pascal's
       `protected var' can be used since this guarantees passing by
       reference.
     
       Copyright (C) 1998-2006 Free Software Foundation, Inc.
     
       Authors: Jukka Virtanen <jtv@hut.fi>
                Peter Gerwinski <peter@gerwinski.de>
                Frank Heckenbach <frank@pascal.gnu.de>
                J.J. v.der Heijden <j.j.vanderheijden@student.utwente.nl>
                Nicola Girardi <nicola@g-n-u.de>
                Prof. Abimbola A. Olowofoyeku <African_Chief@bigfoot.com>
                Emil Jerabek <jerabek@math.cas.cz>
                Maurice Lombardi <Maurice.Lombardi@ujf-grenoble.fr>
                Toby Ewing <ewing@iastate.edu>
                Mirsad Todorovac <mtodorov_69@yahoo.com>
     
       This file is part of GNU Pascal.
     
       GNU Pascal is free software; you can redistribute it and/or modify
       it under the terms of the GNU General Public License as published
       by the Free Software Foundation; either version 2, or (at your
       option) any later version.
     
       GNU Pascal is distributed in the hope that it will be useful, but
       WITHOUT ANY WARRANTY; without even the implied warranty of
       MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
       General Public License for more details.
     
       You should have received a copy of the GNU General Public License
       along with GNU Pascal; see the file COPYING. If not, write to the
       Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA
       02111-1307, USA.
     
       As a special exception, if you link this file with files compiled
       with a GNU compiler to produce an executable, this does not cause
       the resulting executable to be covered by the GNU General Public
       License. This exception does not however invalidate any other
       reasons why the executable file might be covered by the GNU
       General Public License. }
     
     {$gnu-pascal,I-}
     {$if __GPC_RELEASE__ <> 20060325}
     {$error
     Trying to compile gpc.pas with a non-matching GPC version is likely
     to cause problems.
     
     In case you are building the RTS separately from GPC, make sure you
     install a current GPC version previously. If you are building GPC
     now and this message appears, something is wrong -- if you are
     overriding the GCC_FOR_TARGET or GPC_FOR_TARGET make variables, this
     might be the problem. If you are cross-building GPC, build and
     install a current GPC cross-compiler first, sorry. If that's not the
     case, please report it as a bug.
     
     If you are not building GPC or the RTS currently, you might have
     installed things in the wrong place, so the compiler and RTS
     versions do not match.}
     {$endif}
     
     { Command-line options must not change the layout of RTS types
       declared here. }
     {$no-pack-struct, maximum-field-alignment 0}
     
     module GPC;
     
     export
       GPC = all;
       GPC_CP = (ERead { @@ not really, but an empty export doesn't work
       } );
       GPC_EP = (ERead { @@ not really, but an empty export doesn't work
       } );
       GPC_BP = (MaxLongInt, ExitCode, ErrorAddr, FileMode, Pos);
       GPC_Delphi = (MaxLongInt, Int64, InitProc, EConvertError,
                     ExitCode, ErrorAddr, FileMode, Pos, SetString,
       StringOfChar,
                     TextFile, AssignFile, CloseFile);
     
     type
       GPC_FDR = AnyFile;
     
     { Pascal declarations of the GPC Run Time System routines that are
       implemented in C, from rtsc.pas }
     
     const
       { Maximum size of a variable }
       MaxVarSize = MaxInt div 8;
     
     { If set, characters >= #$80 are assumed to be letters even if the
       locale routines don't say so. This is a kludge because some
       systems don't have correct non-English locale tables. }
     var
       FakeHighLetters: Boolean; attribute (name = '_p_FakeHighLetters');
       external;
     
     type
       PCStrings = ^TCStrings;
       TCStrings = array [0 .. MaxVarSize div SizeOf (CString) - 1] of
       CString;
     
       Int64 = Integer attribute (Size = 64);
       UnixTimeType = LongInt;  { This is hard-coded in the compiler. Do
       not change here. }
       MicroSecondTimeType = LongInt;
       FileSizeType = LongInt;
       SignedSizeType = Integer attribute (Size = BitSizeOf (SizeType));
       TSignalHandler = procedure (Signal: CInteger);
     
       StatFSBuffer = record
         BlockSize, BlocksTotal, BlocksFree: LongInt;
         FilesTotal, FilesFree: CInteger
       end;
     
       InternalSelectType = record
         Handle: CInteger;
         Read, Write, Exception: Boolean
       end;
     
       PString = ^String;
     
       { `Max' so the range of the array does not become invalid for
         Count = 0 }
       PPStrings = ^TPStrings;
       TPStrings (Count: Cardinal) = array [1 .. Max (Count, 1)] of
       PString;
     
       GlobBuffer = record
         Result: PPStrings;
         Internal1: Pointer;
         Internal2: PCStrings;
         Internal3: CInteger
       end;
     
     { Mathematical routines }
     
     function  SinH (x: Real): Real; attribute (const); external
       name '_p_SinH';
     function  CosH (x: Real): Real; attribute (const); external
       name '_p_CosH';
     function  ArcTan2 (y: Real; x: Real): Real; attribute (const);
       external name '_p_ArcTan2';
     function  IsInfinity (x: LongReal): Boolean; attribute (const);
       external name '_p_IsInfinity';
     function  IsNotANumber (x: LongReal): Boolean; attribute (const);
       external name '_p_IsNotANumber';
     procedure SplitReal (x: LongReal; var Exponent: CInteger; var
       Mantissa: LongReal); external name '_p_SplitReal';
     
     { Character routines }
     
     { Convert a character to lower case, according to the current
       locale. }
     function  LoCase (ch: Char): Char; attribute (const); external
       name '_p_LoCase';
     function  IsUpCase (ch: Char): Boolean; attribute (const); external
       name '_p_IsUpCase';
     function  IsLoCase (ch: Char): Boolean; attribute (const); external
       name '_p_IsLoCase';
     function  IsAlpha (ch: Char): Boolean; attribute (const); external
       name '_p_IsAlpha';
     function  IsAlphaNum (ch: Char): Boolean; attribute (const);
       external name '_p_IsAlphaNum';
     function  IsAlphaNumUnderscore (ch: Char): Boolean; attribute
       (const); external name '_p_IsAlphaNumUnderscore';
     function  IsSpace (ch: Char): Boolean; attribute (const); external
       name '_p_IsSpace';
     function  IsPrintable (ch: Char): Boolean; attribute (const);
       external name '_p_IsPrintable';
     
     { Time routines }
     
     { Sleep for a given number of seconds. }
     procedure Sleep (Seconds: CInteger); external name '_p_Sleep';
     
     { Sleep for a given number of microseconds. }
     procedure SleepMicroSeconds (MicroSeconds: CInteger); external
       name '_p_SleepMicroSeconds';
     
     { Set an alarm timer. }
     function  Alarm (Seconds: CInteger): CInteger; external
       name '_p_Alarm';
     
     { Convert a Unix time value to broken-down local time.
       All parameters except Time may be Null. }
     procedure UnixTimeToTime (Time: UnixTimeType; var Year: CInteger;
       var Month: CInteger; var Day: CInteger; var Hour: CInteger; var
       Minute: CInteger; var Second: CInteger;
                                     var TimeZone: CInteger; var DST:
       Boolean; var TZName1: CString; var TZName2: CString); external
       name '_p_UnixTimeToTime';
     
     { Convert broken-down local time to a Unix time value. }
     function  TimeToUnixTime (Year: CInteger; Month: CInteger; Day:
       CInteger; Hour: CInteger; Minute: CInteger; Second: CInteger):
       UnixTimeType; external name '_p_TimeToUnixTime';
     
     { Get the real time. MicroSecond can be Null and is ignored then. }
     function  GetUnixTime (var MicroSecond: CInteger): UnixTimeType;
       external name '_p_GetUnixTime';
     
     { Get the CPU time used. MicroSecond can be Null and is ignored
       then. }
     function  GetCPUTime (var MicroSecond: CInteger): CInteger; external
       name '_p_GetCPUTime';
     
     { Signal and process routines }
     
     { Extract information from the status returned by PWait }
     function  StatusExited (Status: CInteger): Boolean; attribute
       (const); external name '_p_StatusExited';
     function  StatusExitCode (Status: CInteger): CInteger; attribute
       (const); external name '_p_StatusExitCode';
     function  StatusSignaled (Status: CInteger): Boolean; attribute
       (const); external name '_p_StatusSignaled';
     function  StatusTermSignal (Status: CInteger): CInteger; attribute
       (const); external name '_p_StatusTermSignal';
     function  StatusStopped (Status: CInteger): Boolean; attribute
       (const); external name '_p_StatusStopped';
     function  StatusStopSignal (Status: CInteger): CInteger; attribute
       (const); external name '_p_StatusStopSignal';
     
     { Install a signal handler and optionally return the previous
       handler. OldHandler and OldRestart may be Null. }
     function  InstallSignalHandler (Signal: CInteger; Handler:
       TSignalHandler; Restart: Boolean; UnlessIgnored: Boolean;
       var OldHandler: TSignalHandler; var OldRestart: Boolean): Boolean;
       external name '_p_InstallSignalHandler';
     
     { Block or unblock a signal. }
     procedure BlockSignal (Signal: CInteger; Block: Boolean); external
       name '_p_BlockSignal';
     
     { Test whether a signal is blocked. }
     function  SignalBlocked (Signal: CInteger): Boolean; external
       name '_p_SignalBlocked';
     
     { Sends a signal to a process. Returns True if successful. If Signal
       is 0, it doesn't send a signal, but still checks whether it would
       be possible to send a signal to the given process. }
     function  Kill (PID: CInteger; Signal: CInteger): Boolean; external
       name '_p_Kill';
     
     { Constant for WaitPID }
     const
       AnyChild = -1;
     
     { Waits for a child process with the given PID (or any child process
       if PID = AnyChild) to terminate or be stopped. Returns the PID of
       the process. WStatus will contain the status and can be evaluated
       with StatusExited etc.. If nothing happened, and Block is False,
       the function will return 0, and WStatus will be 0. If an error
       occurred (especially on single tasking systems where WaitPID is
       not possible), the function will return a negative value, and
       WStatus will be 0. }
     function  WaitPID (PID: CInteger; var WStatus: CInteger; Block:
       Boolean): CInteger; external name '_p_WaitPID';
     
     { Returns the process ID. }
     function  ProcessID: CInteger; external name '_p_ProcessID';
     
     { Returns the process group. }
     function  ProcessGroup: CInteger; external name '_p_ProcessGroup';
     
     { Returns the real or effective user ID of the process. }
     function  UserID (Effective: Boolean): CInteger; external
       name '_p_UserID';
     
     { Tries to change the real and/or effective user ID. }
     function  SetUserID (Real: CInteger; Effective: CInteger): Boolean;
       external name '_p_SetUserID';
     
     { Returns the real or effective group ID of the process. }
     function  GroupID (Effective: Boolean): CInteger; external
       name '_p_GroupID';
     
     { Tries to change the real and/or effective group ID. }
     function  SetGroupID (Real: CInteger; Effective: CInteger): Boolean;
       external name '_p_SetGroupID';
     
     { Low-level file routines. Mostly for internal use. }
     
     { Get information about a file system. }
     function  StatFS (Path: CString; var Buf: StatFSBuffer): Boolean;
       external name '_p_StatFS';
     function  CStringOpenDir (DirName: CString): Pointer; external
       name '_p_CStringOpenDir';
     function  CStringReadDir (Dir: Pointer): CString; external
       name '_p_CStringReadDir';
     procedure CStringCloseDir (Dir: Pointer); external
       name '_p_CStringCloseDir';
     
     { Returns the value of the symlink FileName in a CString allocated
       from the heap. Returns nil if it is no symlink or the function
       is not supported. }
     function  ReadLink (FileName: CString): CString; external
       name '_p_ReadLink';
     
     { Returns a pointer to a *static* buffer! }
     function  CStringRealPath (Path: CString): CString; external
       name '_p_CStringRealPath';
     
     { File mode constants that are ORed for BindingType.Mode, ChMod,
       CStringChMod and Stat. The values below are valid for all OSs
       (as far as supported). If the OS uses different values, they're
       converted internally. }
     const
       fm_SetUID           = 8#4000;
       fm_SetGID           = 8#2000;
       fm_Sticky           = 8#1000;
       fm_UserReadable     = 8#400;
       fm_UserWritable     = 8#200;
       fm_UserExecutable   = 8#100;
       fm_GroupReadable    = 8#40;
       fm_GroupWritable    = 8#20;
       fm_GroupExecutable  = 8#10;
       fm_OthersReadable   = 8#4;
       fm_OthersWritable   = 8#2;
       fm_OthersExecutable = 8#1;
     
     { Constants for Access and OpenHandle }
     const
       MODE_EXEC     = 1 shl 0;
       MODE_WRITE    = 1 shl 1;
       MODE_READ     = 1 shl 2;
       MODE_FILE     = 1 shl 3;
       MODE_CREATE   = 1 shl 4;
       MODE_EXCL     = 1 shl 5;
       MODE_TRUNCATE = 1 shl 6;
       MODE_APPEND   = 1 shl 7;
       MODE_BINARY   = 1 shl 8;
     
     { Check if a file name is accessible. }
     function  Access (FileName: CString; Request: CInteger): CInteger;
       external name '_p_Access';
     
     { Get information about a file. Any argument except FileName can
       be Null. }
     function  Stat (FileName: CString; var Size: FileSizeType;
       var ATime: UnixTimeType; var MTime: UnixTimeType; var CTime:
       UnixTimeType;
       var User: CInteger; var Group: CInteger; var Mode: CInteger; var
       Device: CInteger; var INode: CInteger; var Links: CInteger;
       var SymLink: Boolean; var Dir: Boolean; var Special: Boolean):
       CInteger; external name '_p_Stat';
     function  OpenHandle (FileName: CString; Mode: CInteger): CInteger;
       external name '_p_OpenHandle';
     function  ReadHandle (Handle: CInteger; Buffer: Pointer; Size:
       SizeType): SignedSizeType; external name '_p_ReadHandle';
     function  WriteHandle (Handle: CInteger; Buffer: Pointer; Size:
       SizeType): SignedSizeType; external name '_p_WriteHandle';
     function  CloseHandle (Handle: CInteger): CInteger; external
       name '_p_CloseHandle';
     procedure FlushHandle (Handle: CInteger); external
       name '_p_FlushHandle';
     function  DupHandle (Src: CInteger; Dest: CInteger): CInteger;
       external name '_p_DupHandle';
     function  SetFileMode (Handle: CInteger; Mode: CInteger; On:
       Boolean): CInteger; attribute (ignorable); external
       name '_p_SetFileMode';
     function  CStringRename (OldName: CString; NewName: CString):
       CInteger; external name '_p_CStringRename';
     function  CStringUnlink (FileName: CString): CInteger; external
       name '_p_CStringUnlink';
     function  CStringChDir (FileName: CString): CInteger; external
       name '_p_CStringChDir';
     function  CStringMkDir (FileName: CString): CInteger; external
       name '_p_CStringMkDir';
     function  CStringRmDir (FileName: CString): CInteger; external
       name '_p_CStringRmDir';
     function  UMask (Mask: CInteger): CInteger; attribute (ignorable);
       external name '_p_UMask';
     function  CStringChMod (FileName: CString; Mode: CInteger):
       CInteger; external name '_p_CStringChMod';
     function  CStringChOwn (FileName: CString; Owner: CInteger; Group:
       CInteger): CInteger; external name '_p_CStringChOwn';
     function  CStringUTime (FileName: CString; AccessTime: UnixTimeType;
       ModificationTime: UnixTimeType): CInteger; external
       name '_p_CStringUTime';
     
     { Constants for SeekHandle }
     const
       SeekAbsolute = 0;
       SeekRelative = 1;
       SeekFileEnd  = 2;
     
     { Seek to a position on a file handle. }
     function  SeekHandle (Handle: CInteger; Offset: FileSizeType;
       Whence: CInteger): FileSizeType; external name '_p_SeekHandle';
     function  TruncateHandle (Handle: CInteger; Size: FileSizeType):
       CInteger; external name '_p_TruncateHandle';
     function  LockHandle (Handle: CInteger; WriteLock: Boolean; Block:
       Boolean): Boolean; external name '_p_LockHandle';
     function  UnlockHandle (Handle: CInteger): Boolean; external
       name '_p_UnlockHandle';
     function  SelectHandle (Count: CInteger; var Events:
       InternalSelectType; MicroSeconds: MicroSecondTimeType): CInteger;
       external name '_p_SelectHandle';
     
     { Constants for MMapHandle and MemoryMap }
     const
       mm_Readable   = 1;
       mm_Writable   = 2;
       mm_Executable = 4;
     
     { Try to map (a part of) a file to memory. }
     function  MMapHandle (Start: Pointer; Length: SizeType; Access:
       CInteger; Shared: Boolean; Handle: CInteger; Offset:
       FileSizeType): Pointer; external name '_p_MMapHandle';
     
     { Unmap a previous memory mapping. }
     function  MUnMapHandle (Start: Pointer; Length: SizeType): CInteger;
       external name '_p_MUnMapHandle';
     
     { Returns the file name of the terminal device that is open on
       Handle. Returns nil if (and only if) Handle is not open or not
       connected to a terminal. If NeedName is False, it doesn't bother
       to search for the real name and just returns DefaultName if it
       is a terminal and nil otherwise. DefaultName is also returned if
       NeedName is True, Handle is connected to a terminal, but the
       system does not provide information about the real file name. }
     function  GetTerminalNameHandle (Handle: CInteger; NeedName:
       Boolean; DefaultName: CString): CString; external
       name '_p_GetTerminalNameHandle';
     
     { System routines }
     
     { Sets the process group of Process (or the current one if Process
       is 0) to ProcessGroup (or its PID if ProcessGroup is 0). Returns
       True if successful. }
     function  SetProcessGroup (Process: CInteger; ProcessGroup:
       CInteger): Boolean; external name '_p_SetProcessGroup';
     
     { Sets the process group of a terminal given by Terminal (as a file
       handle) to ProcessGroup. ProcessGroup must be the ID of a process
       group in the same session. Returns True if successful. }
     function  SetTerminalProcessGroup (Handle: CInteger; ProcessGroup:
       CInteger): Boolean; external name '_p_SetTerminalProcessGroup';
     
     { Returns the process group of a terminal given by Terminal (as a
       file handle), or -1 on error. }
     function  GetTerminalProcessGroup (Handle: CInteger): CInteger;
       external name '_p_GetTerminalProcessGroup';
     
     { Set the standard input's signal generation, if it is a terminal. }
     procedure SetInputSignals (Signals: Boolean); external
       name '_p_SetInputSignals';
     
     { Get the standard input's signal generation, if it is a terminal. }
     function  GetInputSignals: Boolean; external
       name '_p_GetInputSignals';
     
     { Internal routines }
     
     { Returns system information if available. Fields not available will
       be set to nil. }
     procedure CStringSystemInfo (var SysName: CString; var NodeName:
       CString; var Release: CString; var Version: CString; var Machine:
       CString; var DomainName: CString); external
       name '_p_CStringSystemInfo';
     
     { Returns the path of the running executable *if possible*. }
     function  CStringExecutablePath (Buffer: CString): CString; external
       name '_p_CStringExecutablePath';
     
     { Sets ErrNo to the value of `errno' and returns the description
       for this error. May return nil if not supported! ErrNo may be
       Null (then only the description is returned). }
     function  CStringStrError (var ErrNo: CInteger): CString; external
       name '_p_CStringStrError';
     
     { Mathematical routines, from math.pas }
     
     function Ln1Plus  (x: Real) = y: Real; attribute (const, name
       = '_p_Ln1Plus'); external;
     
     { String handling routines (lower level), from string1.pas }
     
     { TString is a string type that is used for function results and
       local variables, as long as undiscriminated strings are not
       allowed there. The default size of 2048 characters should be
       enough for file names on any system, but can be changed when
       necessary. It should be at least as big as MAXPATHLEN. }
     
     const
       MaxLongInt = High (LongInt);
     
       TStringSize = 2048;
       SpaceCharacters = [' ', #9];
       NewLine = "\n";  { the separator of lines within a string }
       LineBreak = {$if defined (__OS_DOS__) and not defined (__CYGWIN__)
       and not defined (__MSYS__)}
                   "\r\n"
                   {$else}
                   "\n"
                   {$endif};  { the separator of lines within a file }
     
     type
       TString    = String (TStringSize);
       TStringBuf = packed array [0 .. TStringSize] of Char;
       CharSet    = set of Char;
       Str64      = String (64);
       TInteger2StringBase = Cardinal(2) .. Cardinal(36);
       TInteger2StringWidth = 0 .. High (TString);
     
     var
       NumericBaseDigits: array [0 .. 35] of Char; attribute (const, name
       = '_p_NumericBaseDigits'); external;
       NumericBaseDigitsUpper: array [0 .. 35] of Char; attribute (const,
       name = '_p_NumericBaseDigitsUpper'); external;
     
       CParamCount: Integer; attribute (name = '_p_CParamCount');
       external;
       CParameters: PCStrings; attribute (name = '_p_CParameters');
       external;
     
     function  MemCmp      (const s1, s2; Size: SizeType): CInteger;
       external name 'memcmp';
     function  MemComp     (const s1, s2; Size: SizeType): CInteger;
       external name 'memcmp';
     function  MemCompCase (const s1, s2; Size: SizeType): Boolean;
       attribute (name = '_p_MemCompCase'); external;
     
     procedure UpCaseString    (var s: String); attribute (name
       = '_p_UpCaseString'); external;
     procedure LoCaseString    (var s: String); attribute (name
       = '_p_LoCaseString'); external;
     function  UpCaseStr       (const s: String) = Result: TString;
       attribute (name = '_p_UpCaseStr'); external;
     function  LoCaseStr       (const s: String) = Result: TString;
       attribute (name = '_p_LoCaseStr'); external;
     
     function  StrEqualCase    (const s1, s2: String): Boolean; attribute
       (name = '_p_StrEqualCase'); external;
     
     function  Pos             (const SubString, s: String): Integer;
       attribute (name = '_p_Pos'); external;
     function  PosChar         (const ch: Char; const s: String):
       Integer; attribute (name = '_p_PosChar'); external;
     function  LastPos         (const SubString, s: String): Integer;
       attribute (name = '_p_LastPos'); external;
     function  PosCase         (const SubString, s: String): Integer;
       attribute (name = '_p_PosCase'); external;
     function  LastPosCase     (const SubString, s: String): Integer;
       attribute (name = '_p_LastPosCase'); external;
     function  CharPos         (const Chars: CharSet; const s: String):
       Integer; attribute (name = '_p_CharPos'); external;
     function  LastCharPos     (const Chars: CharSet; const s: String):
       Integer; attribute (name = '_p_LastCharPos'); external;
     
     function  PosFrom         (const SubString, s: String; From:
       Integer): Integer; attribute (name = '_p_PosFrom'); external;
     function  LastPosTill     (const SubString, s: String; Till:
       Integer): Integer; attribute (name = '_p_LastPosTill'); external;
     function  PosFromCase     (const SubString, s: String; From:
       Integer): Integer; attribute (name = '_p_PosFromCase'); external;
     function  LastPosTillCase (const SubString, s: String; Till:
       Integer): Integer; attribute (name = '_p_LastPosTillCase');
       external;
     function  CharPosFrom     (const Chars: CharSet; const s: String;
       From: Integer): Integer; attribute (name = '_p_CharPosFrom');
       external;
     function  LastCharPosTill (const Chars: CharSet; const s: String;
       Till: Integer): Integer; attribute (name = '_p_LastCharPosTill');
       external;
     
     function  IsPrefix        (const Prefix, s: String): Boolean;
       attribute (name = '_p_IsPrefix'); external;
     function  IsSuffix        (const Suffix, s: String): Boolean;
       attribute (name = '_p_IsSuffix'); external;
     function  IsPrefixCase    (const Prefix, s: String): Boolean;
       attribute (name = '_p_IsPrefixCase'); external;
     function  IsSuffixCase    (const Suffix, s: String): Boolean;
       attribute (name = '_p_IsSuffixCase'); external;
     
     function  CStringLength      (Src: CString): SizeType; attribute
       (inline, name = '_p_CStringLength'); external;
     function  CStringEnd         (Src: CString): CString; attribute
       (inline, name = '_p_CStringEnd'); external;
     function  CStringNew         (Src: CString): CString; attribute
       (name = '_p_CStringNew'); external;
     function  CStringComp        (s1, s2: CString): Integer; attribute
       (name = '_p_CStringComp'); external;
     function  CStringCaseComp    (s1, s2: CString): Integer; attribute
       (name = '_p_CStringCaseComp'); external;
     function  CStringLComp       (s1, s2: CString; MaxLen: SizeType):
       Integer; attribute (name = '_p_CStringLComp'); external;
     function  CStringLCaseComp   (s1, s2: CString; MaxLen: SizeType):
       Integer; attribute (name = '_p_CStringLCaseComp'); external;
     function  CStringCopy        (Dest, Source: CString): CString;
       attribute (ignorable, name = '_p_CStringCopy'); external;
     function  CStringCopyEnd     (Dest, Source: CString): CString;
       attribute (ignorable, name = '_p_CStringCopyEnd'); external;
     function  CStringLCopy       (Dest, Source: CString; MaxLen:
       SizeType): CString; attribute (ignorable, name
       = '_p_CStringLCopy'); external;
     function  CStringMove        (Dest, Source: CString; Count:
       SizeType): CString; attribute (ignorable, name
       = '_p_CStringMove'); external;
     function  CStringCat         (Dest, Source: CString): CString;
       attribute (ignorable, name = '_p_CStringCat'); external;
     function  CStringLCat        (Dest, Source: CString; MaxLen:
       SizeType): CString; attribute (ignorable, name
       = '_p_CStringLCat'); external;
     function  CStringChPos       (Src: CString; ch: Char): CString;
       attribute (inline, name = '_p_CStringChPos'); external;
     function  CStringLastChPos   (Src: CString; ch: Char): CString;
       attribute (inline, name = '_p_CStringLastChPos'); external;
     function  CStringPos         (s, SubString: CString): CString;
       attribute (name = '_p_CStringPos'); external;
     function  CStringLastPos     (s, SubString: CString): CString;
       attribute (name = '_p_CStringLastPos'); external;
     function  CStringCasePos     (s, SubString: CString): CString;
       attribute (name = '_p_CStringCasePos'); external;
     function  CStringLastCasePos (s, SubString: CString): CString;
       attribute (name = '_p_CStringLastCasePos'); external;
     function  CStringUpCase      (s: CString): CString; attribute (name
       = '_p_CStringUpCase'); external;
     function  CStringLoCase      (s: CString): CString; attribute (name
       = '_p_CStringLoCase'); external;
     function  CStringIsEmpty     (s: CString): Boolean; attribute (name
       = '_p_CStringIsEmpty'); external;
     function  NewCString         (const Source: String): CString;
       attribute (name = '_p_NewCString'); external;
     function  CStringCopyString  (Dest: CString; const Source: String):
       CString; attribute (name = '_p_CStringCopyString'); external;
     procedure CopyCString        (Source: CString; var Dest: String);
       attribute (name = '_p_CopyCString'); external;
     
     function  NewString       (const s: String) = Result: PString;
       attribute (name = '_p_NewString'); external;
     procedure DisposeString   (p: PString); external name '_p_Dispose';
     
     procedure SetString       (var s: String; Buffer: PChar; Count:
       Integer); attribute (name = '_p_SetString'); external;
     function  StringOfChar    (ch: Char; Count: Integer) = s: TString;
       attribute (name = '_p_StringOfChar'); external;
     
     procedure TrimLeft        (var s: String); attribute (name
       = '_p_TrimLeft'); external;
     procedure TrimRight       (var s: String); attribute (name
       = '_p_TrimRight'); external;
     procedure TrimBoth        (var s: String); attribute (name
       = '_p_TrimBoth'); external;
     function  TrimLeftStr     (const s: String) = Result: TString;
       attribute (name = '_p_TrimLeftStr'); external;
     function  TrimRightStr    (const s: String) = Result: TString;
       attribute (name = '_p_TrimRightStr'); external;
     function  TrimBothStr     (const s: String) = Result: TString;
       attribute (name = '_p_TrimBothStr'); external;
     function  LTrim           (const s: String) = Result: TString;
       external name '_p_TrimLeftStr';
     
     function  GetStringCapacity (const s: String): Integer; attribute
       (name = '_p_GetStringCapacity'); external;
     
     { A shortcut for a common use of WriteStr as a function }
     function  Integer2String (i: Integer) = s: Str64; attribute (name
       = '_p_Integer2String'); external;
     
     { Convert integer n to string in base Base. }
     function  Integer2StringBase (n: LongestInt; Base:
       TInteger2StringBase): TString; attribute (name
       = '_p_Integer2StringBase'); external;
     
     { Convert integer n to string in base Base, with sign, optionally in
       uppercase representation and with printed base, padded with
       leading zeroes between `[<Sign>]<Base>#' and the actual digits to
       specified Width. }
     function  Integer2StringBaseExt (n: LongestInt; Base:
       TInteger2StringBase; Width: TInteger2StringWidth; Upper: Boolean;
       PrintBase: Boolean): TString; attribute (name
       = '_p_Integer2StringBaseExt'); external;
     
     { String handling routines (higher level), from string2.pas }
     
     type
       PChars0 = ^TChars0;
       TChars0 = array [0 .. MaxVarSize div SizeOf (Char) - 1] of Char;
     
       PPChars0 = ^TPChars0;
       TPChars0 = array [0 .. MaxVarSize div SizeOf (PChars0) - 1] of
       PChars0;
     
       PChars = ^TChars;
       TChars = packed array [1 .. MaxVarSize div SizeOf (Char)] of Char;
     
       { Under development. Interface subject to change.
         Use with caution. }
       { When a const or var AnyString parameter is passed, internally
         these records are passed as const parameters. Value AnyString
         parameters are passed like value string parameters. }
       ConstAnyString = record
         Length: Integer;
         Chars: PChars
       end;
     
       { Capacity is the allocated space (used internally). Count is the
         actual number of environment strings. The CStrings array
         contains the environment strings, terminated by a nil pointer,
         which is not counted in Count. @CStrings can be passed to libc
         routines like execve which expect an environment (see
         GetCEnvironment). }
       PEnvironment = ^TEnvironment;
       TEnvironment (Capacity: Integer) = record
         Count: Integer;
         CStrings: array [1 .. Capacity + 1] of CString
       end;
     
     var
       Environment: PEnvironment; attribute (name = '_p_Environment');
       external;
     
     { Get an environment variable. If it does not exist, GetEnv returns
       the empty string, which can't be distinguished from a variable
       with an empty value, while CStringGetEnv returns nil then. Note,
       Dos doesn't know empty environment variables, but treats them as
       non-existing, and does not distinguish case in the names of
       environment variables. However, even under Dos, empty environment
       variables and variable names with different case can now be set
       and used within GPC programs. }
     function  GetEnv (const EnvVar: String): TString; attribute (name
       = '_p_GetEnv'); external;
     function  CStringGetEnv (EnvVar: CString): CString; attribute (name
       = '_p_CStringGetEnv'); external;
     
     { Sets an environment variable with the name given in VarName to the
       value Value. A previous value, if any, is overwritten. }
     procedure SetEnv (const VarName, Value: String); attribute (name
       = '_p_SetEnv'); external;
     
     { Un-sets an environment variable with the name given in VarName. }
     procedure UnSetEnv (const VarName: String); attribute (name
       = '_p_UnSetEnv'); external;
     
     { Returns @Environment^.CStrings, converted to PCStrings, to be
       passed to libc routines like execve which expect an environment. }
     function  GetCEnvironment: PCStrings; attribute (name
       = '_p_GetCEnvironment'); external;
     
     type
       FormatStringTransformType = ^function (const Format: String):
       TString;
     
     var
       FormatStringTransformPtr: FormatStringTransformType; attribute
       (name = '_p_FormatStringTransformPtr'); external;
     
     { Runtime error and signal handling routines, from error.pas }
     
     const
       EAssert = 306;
       EAssertString = 307;
       EOpen = 405;
       EMMap = 408;
       ERead = 413;
       EWrite = 414;
       EWriteReadOnly = 422;
       ENonExistentFile = 436;
       EOpenRead = 442;
       EOpenWrite = 443;
       EOpenUpdate = 444;
       EReading = 464;
       EWriting = 466;
       ECannotWriteAll = 467;
       ECannotFork = 600;
       ECannotSpawn = 601;
       EProgramNotFound = 602;
       EProgramNotExecutable = 603;
       EPipe = 604;
       EPrinterRead = 610;
       EIOCtl = 630;
       EConvertError = 875;
       ELibraryFunction = 952;
       EExitReturned = 953;
     
       RuntimeErrorExitValue = 42;
     
     var
       { Error number (after runtime error) or exit status (after Halt)
         or 0 (during program run and after succesful termination). }
       ExitCode: Integer; attribute (name = '_p_ExitCode'); external;
     
       { Contains the address of the code where a runtime occurred, nil
         if no runtime error occurred. }
       ErrorAddr: Pointer; attribute (name = '_p_ErrorAddr'); external;
     
       { Error message }
       ErrorMessageString: TString; attribute (name
       = '_p_ErrorMessageString'); external;
     
       { String parameter to some error messages, *not* the text of the
         error message (the latter can be obtained with
         GetErrorMessage). }
       InOutResString: PString; attribute (name = '_p_InOutResString');
       external;
     
       { Optional libc error string to some error messages. }
       InOutResCErrorString: PString; attribute (name
       = '_p_InOutResCErrorString'); external;
     
       RTSErrorFD: Integer; attribute (name = '_p_ErrorFD'); external;
       RTSErrorFileName: PString; attribute (name = '_p_ErrorFileName');
       external;
     
     function  GetErrorMessage                 (n: Integer): CString;
       attribute (name = '_p_GetErrorMessage'); external;
     procedure RuntimeError                    (n: Integer); attribute
       (noreturn, name = '_p_RuntimeError'); external;
     procedure RuntimeErrorErrNo               (n: Integer); attribute
       (noreturn, name = '_p_RuntimeErrorErrNo'); external;
     procedure RuntimeErrorInteger             (n: Integer; i: MedInt);
       attribute (noreturn, name = '_p_RuntimeErrorInteger'); external;
     procedure RuntimeErrorCString             (n: Integer; s: CString);
       attribute (noreturn, name = '_p_RuntimeErrorCString'); external;
     procedure InternalError                   (n: Integer); attribute
       (noreturn, name = '_p_InternalError'); external;
     procedure InternalErrorInteger            (n: Integer; i: MedInt);
       attribute (noreturn, name = '_p_InternalErrorInteger'); external;
     procedure InternalErrorCString            (n: Integer; s: CString);
       attribute (noreturn, name = '_p_InternalErrorCString'); external;
     procedure RuntimeWarning                  (Message: CString);
       attribute (name = '_p_RuntimeWarning'); external;
     procedure RuntimeWarningInteger           (Message: CString; i:
       MedInt); attribute (name = '_p_RuntimeWarningInteger'); external;
     procedure RuntimeWarningCString           (Message: CString; s:
       CString); attribute (name = '_p_RuntimeWarningCString'); external;
     
     procedure IOError                         (n: Integer; ErrNoFlag:
       Boolean); attribute (iocritical, name = '_p_IOError'); external;
     procedure IOErrorInteger                  (n: Integer; i: MedInt;
       ErrNoFlag: Boolean); attribute (iocritical, name
       = '_p_IOErrorInteger'); external;
     procedure IOErrorCString                  (n: Integer; s: CString;
       ErrNoFlag: Boolean); attribute (iocritical, name
       = '_p_IOErrorCString'); external;
     
     function  GetIOErrorMessage = Res: TString; attribute (name
       = '_p_GetIOErrorMessage'); external;
     procedure CheckInOutRes; attribute (name = '_p_CheckInOutRes');
       external;
     
     { Registers a procedure to be called to restore the terminal for
       another process that accesses the terminal, or back for the
       program itself. Used e.g. by the CRT unit. The procedures must
       allow for being called multiple times in any order, even at the
       end of the program (see the comment for RestoreTerminal). }
     procedure RegisterRestoreTerminal (ForAnotherProcess: Boolean;
       procedure Proc); attribute (name = '_p_RegisterRestoreTerminal');
       external;
     
     { Unregisters a procedure registered with RegisterRestoreTerminal.
       Returns False if the procedure had not been registered, and True
       if it had been registered and was unregistered successfully. }
     function  UnregisterRestoreTerminal (ForAnotherProcess: Boolean;
       procedure Proc): Boolean; attribute (name
       = '_p_UnregisterRestoreTerminal'); external;
     
     { Calls the procedures registered by RegisterRestoreTerminal. When
       restoring the terminal for another process, the procedures are
       called in the opposite order of registration. When restoring back
       for the program, they are called in the order of registration.
     
       `RestoreTerminal (True)' will also be called at the end of the
       program, before outputting any runtime error message. It can also
       be used if you want to write an error message and exit the program
       (especially when using e.g. the CRT unit). For this purpose, to
       avoid side effects, call RestoreTerminal immediately before
       writing the error message (to StdErr, not to Output!), and then
       exit the program (e.g. with Halt). }
     procedure RestoreTerminal (ForAnotherProcess: Boolean); attribute
       (name = '_p_RestoreTerminal'); external;
     
     procedure AtExit (procedure Proc); attribute (name = '_p_AtExit');
       external;
     
     function  ReturnAddr2Hex (p: Pointer) = s: TString; attribute (name
       = '_p_ReturnAddr2Hex'); external;
     
     { This function is used to write error messages etc. It does not use
       the Pascal I/O system here because it is usually called at the
       very end of a program after the Pascal I/O system has been shut
       down. }
     function  WriteErrorMessage (const s: String; StdErrFlag: Boolean):
       Boolean; attribute (name = '_p_WriteErrorMessage'); external;
     
     procedure SetReturnAddress (Address: Pointer); attribute (name
       = '_p_SetReturnAddress'); external;
     procedure RestoreReturnAddress; attribute (name
       = '_p_RestoreReturnAddress'); external;
     
     { Returns a description for a signal }
     function  StrSignal (Signal: Integer) = Res: TString; attribute
       (name = '_p_StrSignal'); external;
     
     { Installs some signal handlers that cause runtime errors on certain
       signals. This procedure runs only once, and returns immediately
       when called again (so you can't use it to set the signals again if
       you changed them meanwhile). @@Does not work on all systems (since
       the handler might have too little stack space). }
     procedure InstallDefaultSignalHandlers; attribute (name
       = '_p_InstallDefaultSignalHandlers'); external;
     
     var
       { Signal actions }
       SignalDefault: TSignalHandler; attribute (const); external
       name '_p_SIG_DFL';
       SignalIgnore : TSignalHandler; attribute (const); external
       name '_p_SIG_IGN';
       SignalError  : TSignalHandler; attribute (const); external
       name '_p_SIG_ERR';
     
       { Signals. The constants are set to the signal numbers, and
         are 0 for signals not defined. }
       { POSIX signals }
       SigHUp   : Integer; attribute (const); external name '_p_SIGHUP';
       SigInt   : Integer; attribute (const); external name '_p_SIGINT';
       SigQuit  : Integer; attribute (const); external name '_p_SIGQUIT';
       SigIll   : Integer; attribute (const); external name '_p_SIGILL';
       SigAbrt  : Integer; attribute (const); external name '_p_SIGABRT';
       SigFPE   : Integer; attribute (const); external name '_p_SIGFPE';
       SigKill  : Integer; attribute (const); external name '_p_SIGKILL';
       SigSegV  : Integer; attribute (const); external name '_p_SIGSEGV';
       SigPipe  : Integer; attribute (const); external name '_p_SIGPIPE';
       SigAlrm  : Integer; attribute (const); external name '_p_SIGALRM';
       SigTerm  : Integer; attribute (const); external name '_p_SIGTERM';
       SigUsr1  : Integer; attribute (const); external name '_p_SIGUSR1';
       SigUsr2  : Integer; attribute (const); external name '_p_SIGUSR2';
       SigChld  : Integer; attribute (const); external name '_p_SIGCHLD';
       SigCont  : Integer; attribute (const); external name '_p_SIGCONT';
       SigStop  : Integer; attribute (const); external name '_p_SIGSTOP';
       SigTStp  : Integer; attribute (const); external name '_p_SIGTSTP';
       SigTTIn  : Integer; attribute (const); external name '_p_SIGTTIN';
       SigTTOu  : Integer; attribute (const); external name '_p_SIGTTOU';
     
       { Non-POSIX signals }
       SigTrap  : Integer; attribute (const); external name '_p_SIGTRAP';
       SigIOT   : Integer; attribute (const); external name '_p_SIGIOT';
       SigEMT   : Integer; attribute (const); external name '_p_SIGEMT';
       SigBus   : Integer; attribute (const); external name '_p_SIGBUS';
       SigSys   : Integer; attribute (const); external name '_p_SIGSYS';
       SigStkFlt: Integer; attribute (const); external
       name '_p_SIGSTKFLT';
       SigUrg   : Integer; attribute (const); external name '_p_SIGURG';
       SigIO    : Integer; attribute (const); external name '_p_SIGIO';
       SigPoll  : Integer; attribute (const); external name '_p_SIGPOLL';
       SigXCPU  : Integer; attribute (const); external name '_p_SIGXCPU';
       SigXFSz  : Integer; attribute (const); external name '_p_SIGXFSZ';
       SigVTAlrm: Integer; attribute (const); external
       name '_p_SIGVTALRM';
       SigProf  : Integer; attribute (const); external name '_p_SIGPROF';
       SigPwr   : Integer; attribute (const); external name '_p_SIGPWR';
       SigInfo  : Integer; attribute (const); external name '_p_SIGINFO';
       SigLost  : Integer; attribute (const); external name '_p_SIGLOST';
       SigWinCh : Integer; attribute (const); external
       name '_p_SIGWINCH';
     
       { Signal subcodes (only used on some systems, -1 if not used) }
       FPEIntegerOverflow      : Integer; attribute (const); external
       name '_p_FPE_INTOVF_TRAP';
       FPEIntegerDivisionByZero: Integer; attribute (const); external
       name '_p_FPE_INTDIV_TRAP';
       FPESubscriptRange       : Integer; attribute (const); external
       name '_p_FPE_SUBRNG_TRAP';
       FPERealOverflow         : Integer; attribute (const); external
       name '_p_FPE_FLTOVF_TRAP';
       FPERealDivisionByZero   : Integer; attribute (const); external
       name '_p_FPE_FLTDIV_TRAP';
       FPERealUnderflow        : Integer; attribute (const); external
       name '_p_FPE_FLTUND_TRAP';
       FPEDecimalOverflow      : Integer; attribute (const); external
       name '_p_FPE_DECOVF_TRAP';
     
     { Routines called implicitly by the compiler. }
     procedure GPC_Assert (Condition: Boolean; const Message: String);
       attribute (name = '_p_Assert'); external;
     function  ObjectTypeIs (Left, Right: PObjectType): Boolean;
       attribute (const, name = '_p_ObjectTypeIs'); external;
     procedure ObjectTypeAsError; attribute (noreturn, name
       = '_p_ObjectTypeAsError'); external;
     procedure DisposeNilError; attribute (noreturn, name
       = '_p_DisposeNilError'); external;
     procedure CaseNoMatchError; attribute (noreturn, name
       = '_p_CaseNoMatchError'); external;
     procedure DiscriminantsMismatchError; attribute (noreturn, name
       = '_p_DiscriminantsMismatchError'); external;
     procedure NilPointerError; attribute (noreturn, name
       = '_p_NilPointerError'); external;
     procedure InvalidPointerError (p: Pointer); attribute (noreturn,
       name = '_p_InvalidPointerError'); external;
     procedure InvalidObjectError; attribute (noreturn, name
       = '_p_InvalidObjectError'); external;
     procedure RangeCheckError; attribute (noreturn, name
       = '_p_RangeCheckError'); external;
     procedure IORangeCheckError; attribute (name
       = '_p_IORangeCheckError'); external;
     procedure SubrangeError; attribute (noreturn, name
       = '_p_SubrangeError'); external;
     procedure ModRangeError; attribute (noreturn, name
       = '_p_ModRangeError'); external;
     
     { Pointer checking with `--pointer-checking-user-defined' }
     
     procedure DefaultValidatePointer (p: Pointer); attribute (name
       = '_p_DefaultValidatePointer'); external;
     
     type
       ValidatePointerType = ^procedure (p: Pointer);
     
     var
       ValidatePointerPtr: ValidatePointerType; attribute (name
       = '_p_ValidatePointerPtr'); external;
     
     { Time and date routines, from time.pas }
     
     const
       InvalidYear = -MaxInt;
     
     var
       { DayOfWeekName is a constant and therefore does not respect the
         locale. Therefore, it's recommended to use FormatTime instead. }
       DayOfWeekName: array [0 .. 6] of String [9]; attribute (const,
       name = '_p_DayOfWeekName'); external;
     
       { MonthName is a constant and therefore does not respect the
         locale. Therefore, it's recommended to use FormatTime instead. }
       MonthName: array [1 .. 12] of String [9]; attribute (const, name
       = '_p_MonthName'); external;
     
     function  GetDayOfWeek (Day, Month, Year: Integer): Integer;
       attribute (name = '_p_GetDayOfWeek'); external;
     function  GetDayOfYear (Day, Month, Year: Integer): Integer;
       attribute (name = '_p_GetDayOfYear'); external;
     function  GetSundayWeekOfYear (Day, Month, Year: Integer): Integer;
       attribute (name = '_p_GetSundayWeekOfYear'); external;
     function  GetMondayWeekOfYear (Day, Month, Year: Integer): Integer;
       attribute (name = '_p_GetMondayWeekOfYear'); external;
     procedure GetISOWeekOfYear (Day, Month, Year: Integer; var ISOWeek,
       ISOWeekYear: Integer); attribute (name = '_p_GetISOWeekOfYear');
       external;
     procedure UnixTimeToTimeStamp (UnixTime: UnixTimeType; var
       aTimeStamp: TimeStamp); attribute (name
       = '_p_UnixTimeToTimeStamp'); external;
     function  TimeStampToUnixTime (protected var aTimeStamp: TimeStamp):
       UnixTimeType; attribute (name = '_p_TimeStampToUnixTime');
       external;
     function  GetMicroSecondTime: MicroSecondTimeType; attribute (name
       = '_p_GetMicroSecondTime'); external;
     
     { Is the year a leap year? }
     function  IsLeapYear (Year: Integer): Boolean; attribute (name
       = '_p_IsLeapYear'); external;
     
     { Returns the length of the month, taking leap years into account. }
     function  MonthLength (Month, Year: Integer): Integer; attribute
       (name = '_p_MonthLength'); external;
     
     { Formats a TimeStamp value according to a Format string. The format
       string can contain date/time items consisting of `%', followed by
       the specifiers listed below. All characters outside of these items
       are copied to the result unmodified. The specifiers correspond to
       those of the C function strftime(), including POSIX.2 and glibc
       extensions and some more extensions. The extensions are also
       available on systems whose strftime() doesn't support them.
     
       The following modifiers may appear after the `%':
     
       `_'  The item is left padded with spaces to the given or default
            width.
     
       `-'  The item is not padded at all.
     
       `0'  The item is left padded with zeros to the given or default
            width.
     
       `/'  The item is right trimmed if it is longer than the given
            width.
     
       `^'  The item is converted to upper case.
     
       `~'  The item is converted to lower case.
     
       After zero or more of these flags, an optional width may be
       specified for padding and trimming. It must be given as a decimal
       number (not starting with `0' since `0' has a meaning of its own,
       see above).
     
       Afterwards, the following optional modifiers may follow. Their
       meaning is locale-dependent, and many systems and locales just
       ignore them.
     
       `E'  Use the locale's alternate representation for date and time.
            In a Japanese locale, for example, `%Ex' might yield a date
            format based on the Japanese Emperors' reigns.
     
       `O'  Use the locale's alternate numeric symbols for numbers. This
            modifier applies only to numeric format specifiers.
     
       Finally, exactly one of the following specifiers must appear. The
       padding rules listed here are the defaults that can be overriden
       with the modifiers listed above.
     
       `a'  The abbreviated weekday name according to the current locale.
     
       `A'  The full weekday name according to the current locale.
     
       `b'  The abbreviated month name according to the current locale.
     
       `B'  The full month name according to the current locale.
     
       `c'  The preferred date and time representation for the current
            locale.
     
       `C'  The century of the year. This is equivalent to the greatest
            integer not greater than the year divided by 100.
     
       `d'  The day of the month as a decimal number (`01' .. `31').
     
       `D'  The date using the format `%m/%d/%y'. NOTE: Don't use this
            format if it can be avoided. Things like this caused Y2K
            bugs!
     
       `e'  The day of the month like with `%d', but padded with blanks
            (` 1' .. `31').
     
       `F'  The date using the format `%Y-%m-%d'. This is the form
            specified in the ISO 8601 standard and is the preferred form
            for all uses.
     
       `g'  The year corresponding to the ISO week number, but without
            the century (`00' .. `99'). This has the same format and
            value as `y', except that if the ISO week number (see `V')
            belongs to the previous or next year, that year is used
            instead. NOTE: Don't use this format if it can be avoided.
            Things like this caused Y2K bugs!
     
       `G'  The year corresponding to the ISO week number. This has the
            same format and value as `Y', except that if the ISO week
            number (see `V') belongs to the previous or next year, that
            year is used instead.
     
       `h'  The abbreviated month name according to the current locale.
            This is the same as `b'.
     
       `H'  The hour as a decimal number, using a 24-hour clock
            (`00' .. `23').
     
       `I'  The hour as a decimal number, using a 12-hour clock
            (`01' .. `12').
     
       `j'  The day of the year as a decimal number (`001' .. `366').
     
       `k'  The hour as a decimal number, using a 24-hour clock like `H',
            but padded with blanks (` 0' .. `23').
     
       `l'  The hour as a decimal number, using a 12-hour clock like `I',
            but padded with blanks (` 1' .. `12').
     
       `m'  The month as a decimal number (`01' .. `12').
     
       `M'  The minute as a decimal number (`00' .. `59').
     
       `n'  A single newline character.
     
       `p'  Either `AM' or `PM', according to the given time value; or
            the corresponding strings for the current locale. Noon is
            treated as `PM' and midnight as `AM'.
     
       `P'  Either `am' or `pm', according to the given time value; or
            the corresponding strings for the current locale, printed in
            lowercase characters. Noon is treated as `pm' and midnight as
            `am'.
     
       `Q'  The fractional part of the second. This format has special
            effects on the modifiers. The width, if given, determines the
            number of digits to output. Therefore, no actual clipping or
            trimming is done. However, if padding with spaces is
            specified, any trailing (i.e., right!) zeros are converted to
            spaces, and if "no padding" is specified, they are removed.
            The default is "padding with zeros", i.e. trailing zeros are
            left unchanged. The digits are cut when necessary without
            rounding (otherwise, the value would not be consistent with
            the seconds given by `S' and `s'). Note that GPC's TimeStamp
            currently provides for microsecond resolution, so there are
            at most 6 valid digits (which is also the default width), any
            further digits will be 0 (but if TimeStamp will ever change,
            this format will be adjusted). However, the actual resolution
            provided by the operating system via GetTimeStamp etc. may be
            far lower (e.g., ~1/18s under Dos).
     
       `r'  The complete time using the AM/PM format of the current
            locale.
     
       `R'  The hour and minute in decimal numbers using the format
            `%H:%M'.
     
       `s'  Unix time, i.e. the number of seconds since the epoch, i.e.,
            since 1970-01-01 00:00:00 UTC. Leap seconds are not counted
            unless leap second support is available.
     
       `S'  The seconds as a decimal number (`00' .. `60').
     
       `t'  A single tab character.
     
       `T'  The time using decimal numbers using the format `%H:%M:%S'.
     
       `u'  The day of the week as a decimal number (`1' .. `7'), Monday
            being `1'.
     
       `U'  The week number of the current year as a decimal number
            (`00' .. `53'), starting with the first Sunday as the first
            day of the first week. Days preceding the first Sunday in the
            year are considered to be in week `00'.
     
       `V'  The ISO 8601:1988 week number as a decimal number
            (`01' .. `53'). ISO weeks start with Monday and end with
            Sunday. Week `01' of a year is the first week which has the
            majority of its days in that year; this is equivalent to the
            week containing the year's first Thursday, and it is also
            equivalent to the week containing January 4. Week `01' of a
            year can contain days from the previous year. The week before
            week `01' of a year is the last week (`52' or `53') of the
            previous year even if it contains days from the new year.
     
       `w'  The day of the week as a decimal number (`0' .. `6'), Sunday
            being `0'.
     
       `W'  The week number of the current year as a decimal number
            (`00' .. `53'), starting with the first Monday as the first
            day of the first week. All days preceding the first Monday in
            the year are considered to be in week `00'.
     
       `x'  The preferred date representation for the current locale, but
            without the time.
     
       `X'  The preferred time representation for the current locale, but
            with no date.
     
       `y'  The year without a century as a decimal number
            (`00' .. `99'). This is equivalent to the year modulo 100.
            NOTE: Don't use this format if it can be avoided. Things like
            this caused Y2K bugs!
     
       `Y'  The year as a decimal number, using the Gregorian calendar.
            Years before the year `1' are numbered `0', `-1', and so on.
     
       `z'  RFC 822/ISO 8601:1988 style numeric time zone (e.g., `-0600'
            or `+0100'), or nothing if no time zone is determinable.
     
       `Z'  The time zone abbreviation (empty if the time zone can't be
            determined).
     
       `%'  (i.e., an item `%%') A literal `%' character. }
     function  FormatTime (const Time: TimeStamp; const Format: String) =
       Res: TString; attribute (name = '_p_FormatTime'); external;
     
     { Pseudo random number generator, from random.pas }
     
     type
       RandomSeedType = Cardinal attribute (Size = 32);
       RandomizeType  = ^procedure;
       SeedRandomType = ^procedure (Seed: RandomSeedType);
       RandRealType   = ^function: LongestReal;
       RandIntType    = ^function (MaxValue: LongestCard): LongestCard;
     
     procedure SeedRandom (Seed: RandomSeedType); attribute (name
       = '_p_SeedRandom'); external;
     
     var
       RandomizePtr : RandomizeType; attribute (name
       = '_p_RandomizePtr'); external;
       SeedRandomPtr: SeedRandomType; attribute (name
       = '_p_SeedRandomPtr'); external;
       RandRealPtr  : RandRealType; attribute (name = '_p_RandRealPtr');
       external;
       RandIntPtr   : RandIntType; attribute (name = '_p_RandIntPtr');
       external;
     
     { File name routines, from fname.pas }
     
     { Define constants for different systems:
     
       OSDosFlag:         flag to indicate whether the target system is
                          Dos
     
       QuotingCharacter:  the character used to quote wild cards and
                          other special characters (#0 if not available)
     
       PathSeparator:     the separator of multiple paths, e.g. in the
                          PATH environment variable
     
       DirSeparator:      the separator of the directories within a full
                          file name
     
       DirSeparators:     a set of all possible directory and drive name
                          separators
     
       ExtSeparator:      the separator of a file name extension
     
       DirRoot:           the name of the root directory
     
       DirSelf:           the name of a directory in itself
     
       DirParent:         the name of the parent directory
     
       MaskNoStdDir:      a file name mask that matches all names except
                          the standard directories DirSelf and DirParent
     
       NullDeviceName:    the full file name of the null device
     
       TtyDeviceName:     the full file name of the current Tty
     
       ConsoleDeviceName: the full file name of the system console. On
                          Dos systems, this is the same as the Tty, but
                          on systems that allow remote login, this is a
                          different thing and may reach a completely
                          different user than the one running the
                          program, so use it with care.
     
       EnvVarCharsFirst:  the characters accepted at the beginning of the
                          name of an environment variable without quoting
     
       EnvVarChars:       the characters accepted in the name of an
                          environment variable without quoting
     
       PathEnvVar:        the name of the environment variable which
                          (usually) contains the executable search path
     
       ShellEnvVar:       the name of the environment variable which
                          (usually) contains the path of the shell
                          executable (see GetShellPath)
     
       ShellExecCommand:  the option to the (default) shell to execute
                          the command specified in the following argument
                          (see GetShellPath)
     
       ConfigFileMask:    a mask for the option file name as returned by
                          ConfigFileName
     
       FileNamesCaseSensitive:
                          flag to indicate whether file names are case
                          sensitive }
     
     const
       UnixShellEnvVar        = 'SHELL';
       UnixShellExecCommand   = '-c';
     
     {$ifdef __OS_DOS__}
     
     {$if defined (__CYGWIN__) or defined(__MSYS__)}
       {$define __POSIX_WIN32__}
     {$endif}
     
     const
       OSDosFlag              = True;
       QuotingCharacter       = #0;
       PathSeparator          = {$ifdef __POSIX_WIN32__} ':' {$else} ';'
       {$endif};
       DirSeparator           = '\';
       DirSeparators          = [':', '\', '/'];
       ExtSeparator           = '.';
       DirRoot                = '\';
       DirSelf                = '.';
       DirParent              = '..';
       MaskNoStdDir           = '{*,.[^.]*,..?*}';
       NullDeviceName         = 'nul';
       TtyDeviceName          = 'con';
       ConsoleDeviceName      = 'con';
       EnvVarCharsFirst       = ['A' .. 'Z', 'a' .. 'z', '_'];
       EnvVarChars            = EnvVarCharsFirst + ['0' .. '9'];
       PathEnvVar             = 'PATH';
       ShellEnvVar            = 'COMSPEC';
       ShellExecCommand       = '/c';
       ConfigFileMask         = '*.cfg';
       FileNamesCaseSensitive = False;
     
     {$else}
     
     const
       OSDosFlag              = False;
       QuotingCharacter       = '\';
       PathSeparator          = ':';
       DirSeparator           = '/';
       DirSeparators          = ['/'];
       ExtSeparator           = '.';
       DirRoot                = '/';
       DirSelf                = '.';
       DirParent              = '..';
       MaskNoStdDir           = '{*,.[^.]*,..?*}';
       NullDeviceName         = '/dev/null';
       TtyDeviceName          = '/dev/tty';
       ConsoleDeviceName      = '/dev/console';
       EnvVarCharsFirst       = ['A' .. 'Z', 'a' .. 'z', '_'];
       EnvVarChars            = EnvVarCharsFirst + ['0' .. '9'];
       PathEnvVar             = 'PATH';
       ShellEnvVar            = UnixShellEnvVar;
       ShellExecCommand       = UnixShellExecCommand;
       ConfigFileMask         = '.*';
       FileNamesCaseSensitive = True;
     
     {$endif}
     
     const
       WildCardChars = ['*', '?', '[', ']'];
       FileNameSpecialChars = (WildCardChars + SpaceCharacters +
       ['{', '}', '$', QuotingCharacter]) - DirSeparators;
     
     type
       DirPtr = Pointer;
     
     { Convert ch to lower case if FileNamesCaseSensitive is False, leave
       it unchanged otherwise. }
     function  FileNameLoCase (ch: Char): Char; attribute (name
       = '_p_FileNameLoCase'); external;
     
     { Change a file name to use the OS dependent directory separator }
     function  Slash2OSDirSeparator (const s: String) = Result: TString;
       attribute (name = '_p_Slash2OSDirSeparator'); external;
     
     { Change a file name to use '/' as directory separator }
     function  OSDirSeparator2Slash (const s: String) = Result: TString;
       attribute (name = '_p_OSDirSeparator2Slash'); external;
     
     { Like Slash2OSDirSeparator for CStrings. *Note*: overwrites the
       CString }
     function  Slash2OSDirSeparator_CString (s: CString): CString;
       attribute (ignorable, name = '_p_Slash2OSDirSeparator_CString');
       external;
     
     { Like OSDirSeparator2Slash for CStrings. *Note*: overwrites the
       CString }
     function  OSDirSeparator2Slash_CString (s: CString): CString;
       attribute (ignorable, name = '_p_OSDirSeparator2Slash_CString');
       external;
     
     { Add a DirSeparator to the end of s, if there is not already one
       and s denotes an existing directory }
     function  AddDirSeparator (const s: String) = Result: TString;
       attribute (name = '_p_AddDirSeparator'); external;
     
     { Like AddDirSeparator, but also if the directory does not exist }
     function  ForceAddDirSeparator (const s: String) = Result: TString;
       attribute (name = '_p_ForceAddDirSeparator'); external;
     
     { Remove all trailing DirSeparators from s, if there are any, as
       long as removing them doesn't change the meaning (i.e., they don't
       denote the root directory. }
     function  RemoveDirSeparator (const s: String) = Result: TString;
       attribute (name = '_p_RemoveDirSeparator'); external;
     
     { Returns the current directory using OS dependent directory
       separators }
     function  GetCurrentDirectory: TString; attribute (name
       = '_p_GetCurrentDirectory'); external;
     
     { Returns a directory suitable for storing temporary files using OS
       dependent directory separators. If found, the result always ends
       in DirSeparator. If no suitable directory is found, an empty
       string is returned. }
     function  GetTempDirectory: TString; attribute (name
       = '_p_GetTempDirectory'); external;
     
     { Returns a non-existing file name in the directory given. If the
       directory doesn't exist or the Directory name is empty, an I/O
       error is raised, and GetTempFileNameInDirectory returns the empty
       string. }
     function  GetTempFileNameInDirectory (const Directory: String) =
       Result: TString; attribute (iocritical, name
       = '_p_GetTempFileNameInDirectory'); external;
     
     { Returns a non-existing file name in GetTempDirectory. If no temp
       directory is found, i.e. GetTempDirectory returns the empty
       string, an I/O error is raised, and GetTempFileName returns the
       empty string as well. }
     function  GetTempFileName: TString; attribute (iocritical, name
       = '_p_GetTempFileName'); external;
     
     { The same as GetTempFileName, but returns a CString allocated from
       the heap. }
     function  GetTempFileName_CString: CString; attribute (iocritical,
       name = '_p_GetTempFileName_CString'); external;
     
     { Returns True if the given file name is an existing plain file }
     function  FileExists      (const aFileName: String): Boolean;
       attribute (name = '_p_FileExists'); external;
     
     { Returns True if the given file name is an existing directory }
     function  DirectoryExists (const aFileName: String): Boolean;
       attribute (name = '_p_DirectoryExists'); external;
     
     { Returns True if the given file name is an existing file, directory
       or special file (device, pipe, socket, etc.) }
     function  PathExists      (const aFileName: String): Boolean;
       attribute (name = '_p_PathExists'); external;
     
     { If a file of the given name exists in one of the directories given
       in DirList (separated by PathSeparator), returns the full path,
       otherwise returns an empty string. If aFileName already contains
       an element of DirSeparators, returns Slash2OSDirSeparator
       (aFileName) if it exists. }
     function  FSearch (const aFileName, DirList: String): TString;
       attribute (name = '_p_FSearch'); external;
     
     { Like FSearch, but only find executable files. Under Dos, if not
       found, the function tries appending '.com', '.exe', '.bat' and
       `.cmd' (the last one only if $COMSPEC points to a `cmd.exe'), so
       you don't have to specify these extensions in aFileName (and with
       respect to portability, it might be preferable not to do so). }
     function  FSearchExecutable (const aFileName, DirList: String) =
       Result: TString; attribute (name = '_p_FSearchExecutable');
       external;
     
     { Replaces all occurrences of `$FOO' and `~' in s by the value of
       the environment variables FOO or HOME, respectively. If a variable
       is not defined, the function returns False, and s contains the
       name of the undefined variable (or the empty string if the
       variable name is invalid, i.e., doesn't start with a character
       from EnvVarCharsFirst). Otherwise, if all variables are found, s
       contains the replaced string, and True is returned. }
     function  ExpandEnvironment (var s: String): Boolean; attribute
       (name = '_p_ExpandEnvironment'); external;
     
     { Expands the given path name to a full path name. Relative paths
       are expanded using the current directory, and occurrences of
       DirSelf and DirParent are resolved. Under Dos, the result is
       converted to lower case and a trailing ExtSeparator (except in a
       trailing DirSelf or DirParent) is removed, like Dos does. If the
       directory, i.e. the path without the file name, is invalid, the
       empty string is returned. }
     function  FExpand       (const Path: String): TString; attribute
       (name = '_p_FExpand'); external;
     
     { Like FExpand, but unquotes the directory before expanding it, and
       quotes WildCardChars again afterwards. Does not check if the
       directory is valid (because it may contain wild card characters).
       Symlinks are expanded only in the directory part, not the file
       name. }
     function  FExpandQuoted (const Path: String): TString; attribute
       (name = '_p_FExpandQuoted'); external;
     
     { FExpands Path, and then removes the current directory from it, if
       it is a prefix of it. If OnlyCurDir is set, the current directory
       will be removed only if Path denotes a file in, not below, it. }
     function  RelativePath (const Path: String; OnlyCurDir, Quoted:
       Boolean) = Result: TString; attribute (name = '_p_RelativePath');
       external;
     
     { Is aFileName a UNC filename? (Always returns False on non-Dos
       systems.) }
     function  IsUNC (const aFileName: String): Boolean; attribute (name
       = '_p_IsUNC'); external;
     
     { Splits a file name into directory, name and extension. Each of
       Dir, BaseName and Ext may be Null. }
     procedure FSplit (const Path: String; var Dir, BaseName, Ext:
       String); attribute (name = '_p_FSplit'); external;
     
     { Functions that extract one or two of the parts from FSplit.
       DirFromPath returns DirSelf + DirSeparator if the path contains no
       directory. }
     function  DirFromPath     (const Path: String) = Dir: TString;
       attribute (name = '_p_DirFromPath'); external;
     function  NameFromPath    (const Path: String) = BaseName: TString;
       attribute (name = '_p_NameFromPath'); external;
     function  ExtFromPath     (const Path: String) = Ext: TString;
       attribute (name = '_p_ExtFromPath'); external;
     function  NameExtFromPath (const Path: String): TString; attribute
       (name = '_p_NameExtFromPath'); external;
     
     { Start reading a directory. If successful, a pointer is returned
       that can be used for subsequent calls to ReadDir and finally
       CloseDir. On failure, an I/O error is raised and (in case it is
       ignored) nil is returned. }
     function  OpenDir  (const DirName: String) = Res: DirPtr; attribute
       (iocritical, name = '_p_OpenDir'); external;
     
     { Reads one entry from the directory Dir, and returns the file name.
       On errors or end of directory, the empty string is returned. }
     function  ReadDir  (Dir: DirPtr): TString; attribute (name
       = '_p_ReadDir'); external;
     
     { Closes a directory opened with OpenDir. }
     procedure CloseDir (Dir: DirPtr); attribute (name = '_p_CloseDir');
       external;
     
     { Returns the first position of a non-quoted character of CharSet in
       s, or 0 if no such character exists. }
     function  FindNonQuotedChar (Chars: CharSet; const s: String; From:
       Integer): Integer; attribute (name = '_p_FindNonQuotedChar');
       external;
     
     { Returns the first occurence of SubString in s that is not quoted
       at the beginning, or 0 if no such occurence exists. }
     function  FindNonQuotedStr (const SubString, s: String; From:
       Integer): Integer; attribute (name = '_p_FindNonQuotedStr');
       external;
     
     { Does a string contain non-quoted wildcard characters? }
     function  HasWildCards (const s: String): Boolean; attribute (name
       = '_p_HasWildCards'); external;
     
     { Does a string contain non-quoted wildcard characters, braces or
       spaces? }
     function  HasWildCardsOrBraces (const s: String): Boolean; attribute
       (name = '_p_HasWildCardsOrBraces'); external;
     
     { Insert QuotingCharacter into s before any special characters }
     function  QuoteFileName (const s: String; const SpecialCharacters:
       CharSet) = Result: TString; attribute (name = '_p_QuoteFileName');
       external;
     
     { Remove QuotingCharacter from s }
     function  UnQuoteFileName (const s: String) = Result: TString;
       attribute (name = '_p_UnQuoteFileName'); external;
     
     { Splits s at non-quoted spaces and expands non-quoted braces like
       bash does. The result and its entries should be disposed after
       usage, e.g. with DisposePPStrings. }
     function  BraceExpand (const s: String) = Result: PPStrings;
       attribute (name = '_p_BraceExpand'); external;
     
     { Dispose of a PPStrings array as well as the strings it contains.
       If you want to keep the strings (by assigning them to other string
       pointers), you should instead free the PPStrings array with
       `Dispose'. }
     procedure DisposePPStrings (Strings: PPStrings); attribute (name
       = '_p_DisposePPStrings'); external;
     
     { Tests if a file name matches a shell wildcard pattern (?, *, []) }
     function  FileNameMatch (const Pattern, FileName: String): Boolean;
       attribute (name = '_p_FileNameMatch'); external;
     
     { FileNameMatch with BraceExpand }
     function  MultiFileNameMatch (const Pattern, FileName: String):
       Boolean; attribute (name = '_p_MultiFileNameMatch'); external;
     
     { File name globbing }
     { GlobInit is implied by Glob and MultiGlob, not by GlobOn and
       MultiGlobOn. GlobOn and MultiGlobOn must be called after GlobInit,
       Glob or MultiGlob. MultiGlob and MultiGlobOn do brace expansion,
       Glob and GlobOn do not. GlobFree frees the memory allocated by the
       globbing functions and invalidates the results in Buf. It should
       be called after globbing. }
     procedure GlobInit    (var Buf: GlobBuffer); attribute (name
       = '_p_GlobInit'); external;
     procedure Glob        (var Buf: GlobBuffer; const Pattern: String);
       attribute (name = '_p_Glob'); external;
     procedure GlobOn      (var Buf: GlobBuffer; const Pattern: String);
       attribute (name = '_p_GlobOn'); external;
     procedure MultiGlob   (var Buf: GlobBuffer; const Pattern: String);
       attribute (name = '_p_MultiGlob'); external;
     procedure MultiGlobOn (var Buf: GlobBuffer; const Pattern: String);
       attribute (name = '_p_MultiGlobOn'); external;
     procedure GlobFree    (var Buf: GlobBuffer); attribute (name
       = '_p_GlobFree'); external;
     
     type
       TPasswordEntry = record
         UserName, RealName, Password, HomeDirectory, Shell: PString;
         UID, GID: Integer
       end;
     
       PPasswordEntries = ^TPasswordEntries;
       TPasswordEntries (Count: Integer) = array [1 .. Max (1, Count)] of
       TPasswordEntry;
     
     { Finds a password entry by user name. Returns True if found, False
       otherwise. }
     function  GetPasswordEntryByName (const UserName: String; var Entry:
       TPasswordEntry) = Res: Boolean; attribute (name
       = '_p_GetPasswordEntryByName'); external;
     
     { Finds a password entry by UID. Returns True if found, False
       otherwise. }
     function  GetPasswordEntryByUID (UID: Integer; var Entry:
       TPasswordEntry) = Res: Boolean; attribute (name
       = '_p_GetPasswordEntryByUID'); external;
     
     { Returns all password entries, or nil if none found. }
     function  GetPasswordEntries = Res: PPasswordEntries; attribute
       (name = '_p_GetPasswordEntries'); external;
     
     { Dispose of a TPasswordEntry. }
     procedure DisposePasswordEntry (Entry: TPasswordEntry); attribute
       (name = '_p_DisposePasswordEntry'); external;
     
     { Dispose of a PPasswordEntries. }
     procedure DisposePasswordEntries (Entries: PPasswordEntries);
       attribute (name = '_p_DisposePasswordEntries'); external;
     
     { Returns the mount point (Unix) or drive (Dos) which is part of the
       given path. If the path does not contain any (i.e., is a relative
       path), an empty string is returned. Therefore, if you want to get
       the mount point or drive in any case, apply `FExpand' or
       `RealPath' to the argument. }
     function  GetMountPoint (const Path: String) = Result: TString;
       attribute (name = '_p_GetMountPoint'); external;
     
     type
       TSystemInfo = record
         OSName,
         OSRelease,
         OSVersion,
         MachineType,
         HostName,
         DomainName: TString
       end;
     
     { Returns system information if available. Fields not available will
       be empty. }
     function  SystemInfo = Res: TSystemInfo; attribute (name
       = '_p_SystemInfo'); external;
     
     { Returns the path to the shell (as the result) and the option that
       makes it execute the command specified in the following argument
       (in `Option'). Usually these are the environment value of
       ShellEnvVar, and ShellExecCommand, but on Dos systems, the
       function will first try UnixShellEnvVar, and UnixShellExecCommand
       because ShellEnvVar will usually point to command.com, but
       UnixShellEnvVar can point to bash which is usually a better choice
       when present. If UnixShellEnvVar is not set, or the shell given
       does not exist, it will use ShellEnvVar, and ShellExecCommand.
       Option may be Null (in case you want to invoke the shell
       interactively). }
     function  GetShellPath (var Option: String) = Res: TString;
       attribute (name = '_p_GetShellPath'); external;
     
     { Returns the path of the running executable. *Note*: On most
       systems, this is *not* guaranteed to be the full path, but often
       just the same as `ParamStr (0)' which usually is the name given on
       the command line. Only on some systems with special support, it
       returns the full path when `ParamStr (0)' doesn't. }
     function  ExecutablePath: TString; attribute (name
       = '_p_ExecutablePath'); external;
     
     { Returns a file name suitable for a global (system-wide) or local
       (user-specific) configuration file, depending on the Global
       parameter. The function does not guarantee that the file name
       returned exists or is readable or writable.
     
       In the following table, the base name `<base>' is given with the
       BaseName parameter. If it is empty, the base name is the name of
       the running program (as returned by ExecutablePath, without
       directory and extension. `<prefix>' (Unix only) stands for the
       value of the Prefix parameter (usual values include '', '/usr' and
       '/usr/local'). `<dir>' (Dos only) stands for the directory where
       the running program resides. `$foo' stands for the value of the
       environment variable `foo'.
     
               Global                    Local
       Unix:   <prefix>/etc/<base>.conf  $HOME/.<base>
     
       DJGPP:  $DJDIR\etc\<base>.ini     $HOME\<base>.cfg
               <dir>\<base>.ini          <dir>\<base>.cfg
     
       Other   $HOME\<base>.ini          $HOME\<base>.cfg
         Dos:  <dir>\<base>.ini          <dir>\<base>.cfg
     
       As you see, there are two possibilities under Dos. If the first
       file exists, it is returned. Otherwise, if the second file exists,
       that is returned. If none of them exists (but the program might
       want to create a file), if the environment variable (DJDIR or
       HOME, respectively) is set, the first file name is returned,
       otherwise the second one. This rather complicated scheme should
       give the most reasonable results for systems with or without DJGPP
       installed, and with or without already existing config files. Note
       that DJDIR is always set on systems with DJGPP installed, while
       HOME is not. However, it is easy for users to set it if they want
       their config files in a certain directory rather than with the
       executables. }
     function  ConfigFileName (const Prefix, BaseName: String; Global:
       Boolean): TString; attribute (name = '_p_ConfigFileName');
       external;
     
     { Returns a directory name suitable for global, machine-independent
       data. The function garantees that the name returned ends with a
       DirSeparator, but does not guarantee that it exists or is
       readable or writable.
     
       Note: If the prefix is empty, it is assumed to be '/usr'. (If you
       really want /share, you could pass '/' as the prefix, but that's
       very uncommon.)
     
       Unix:   <prefix>/share/<base>/
     
       DJGPP:  $DJDIR\share\<base>\
               <dir>\
     
       Other   $HOME\<base>\
         Dos:  <dir>\
     
       About the symbols used above, and the two possibilities under Dos,
       see the comments for ConfigFileName. }
     function  DataDirectoryName (const Prefix, BaseName: String):
       TString; attribute (name = '_p_DataDirectoryName'); external;
     
     { Executes a command line. Reports execution errors via the IOResult
       mechanism and returns the exit status of the executed program.
       Execute calls RestoreTerminal with the argument True before and
       False after executing the process, ExecuteNoTerminal does not. }
     function  Execute (const CmdLine: String): Integer; attribute
       (iocritical, name = '_p_Execute'); external;
     function  ExecuteNoTerminal (const CmdLine: String): Integer;
       attribute (iocritical, name = '_p_ExecuteNoTerminal'); external;
     
     { File handling routines, from files.pas }
     
     type
       TextFile = Text;
       TOpenMode = (fo_None, fo_Reset, fo_Rewrite, fo_Append,
       fo_SeekRead, fo_SeekWrite, fo_SeekUpdate);
       PAnyFile = ^AnyFile;
     
       TOpenProc   = procedure (var PrivateData; Mode: TOpenMode);
       TSelectFunc = function  (var PrivateData; Writing: Boolean):
       Integer;  { called before SelectHandle, must return a file handle
       }
       TSelectProc = procedure (var PrivateData; var ReadSelect,
       WriteSelect, ExceptSelect: Boolean);  { called before and after
       SelectHandle }
       TReadFunc   = function  (var PrivateData; var   Buffer; Size:
       SizeType): SizeType;
       TWriteFunc  = function  (var PrivateData; const Buffer; Size:
       SizeType): SizeType;
       TFileProc   = procedure (var PrivateData);
       TFlushProc  = TFileProc;
       TCloseProc  = TFileProc;
       TDoneProc   = TFileProc;
     
     { Flags that can be `or'ed into FileMode. The default value of
       FileMode is FileMode_Reset_ReadWrite. The somewhat confusing
       numeric values are meant to be compatible to BP (as far as
       BP supports them). }
     const
       { Allow writing to binary files opened with Reset }
       FileMode_Reset_ReadWrite      = 2;
     
       { Do not allow reading from files opened with Rewrite }
       FileMode_Rewrite_WriteOnly    = 4;
     
       { Do not allow reading from files opened with Extend }
       FileMode_Extend_WriteOnly     = 8;
     
       { Allow writing to text files opened with Reset }
       FileMode_Text_Reset_ReadWrite = $100;
     
     var
       FileMode: Integer; attribute (name = '_p_FileMode'); external;
     
     { Get the external name of a file }
     function  FileName (protected var f: GPC_FDR): TString; attribute
       (name = '_p_FileName'); external;
     
     procedure IOErrorFile (n: Integer; protected var f: GPC_FDR;
       ErrNoFlag: Boolean); attribute (iocritical, name
       = '_p_IOErrorFile'); external;
     
     procedure GetBinding (protected var f: GPC_FDR; var b: BindingType);
       attribute (name = '_p_GetBinding'); external;
     procedure ClearBinding (var b: BindingType); attribute (name
       = '_p_ClearBinding'); external;
     
     { TFDD interface @@ Subject to change! Use with caution! }
     procedure AssignTFDD (var f: GPC_FDR;
                           aOpenProc:    TOpenProc;
                           aSelectFunc:  TSelectFunc;
                           aSelectProc:  TSelectProc;
                           aReadFunc:    TReadFunc;
                           aWriteFunc:   TWriteFunc;
                           aFlushProc:   TFlushProc;
                           aCloseProc:   TCloseProc;
                           aDoneProc:    TDoneProc;
                           aPrivateData: Pointer); attribute (name
       = '_p_AssignTFDD'); external;
     
     procedure SetTFDD    (var f: GPC_FDR;
                           aOpenProc:    TOpenProc;
                           aSelectFunc:  TSelectFunc;
                           aSelectProc:  TSelectProc;
                           aReadFunc:    TReadFunc;
                           aWriteFunc:   TWriteFunc;
                           aFlushProc:   TFlushProc;
                           aCloseProc:   TCloseProc;
                           aDoneProc:    TDoneProc;
                           aPrivateData: Pointer); attribute (name
       = '_p_SetTFDD'); external;
     
     { Any parameter except f may be Null }
     procedure GetTFDD    (var f: GPC_FDR;
                           var aOpenProc:    TOpenProc;
                           var aSelectFunc:  TSelectFunc;
                           var aSelectProc:  TSelectProc;
                           var aReadFunc:    TReadFunc;
                           var aWriteFunc:   TWriteFunc;
                           var aFlushProc:   TFlushProc;
                           var aCloseProc:   TCloseProc;
                           var aDoneProc:    TDoneProc;
                           var aPrivateData: Pointer); attribute (name
       = '_p_GetTFDD'); external;
     
     procedure FileMove (var f: GPC_FDR; NewName: CString; Overwrite:
       Boolean); attribute (iocritical, name = '_p_FileMove'); external;
     
     const
       NoChange = -1;  { can be passed to ChOwn for Owner and/or Group to
       not change that value }
     
     procedure CloseFile (var f: GPC_FDR); attribute (name
       = '_p_CloseFile'); external;
     procedure ChMod (var f: GPC_FDR; Mode: Integer); attribute
       (iocritical, name = '_p_ChMod'); external;
     procedure ChOwn (var f: GPC_FDR; Owner, Group: Integer); attribute
       (iocritical, name = '_p_ChOwn'); external;
     
     { Checks if data are available to be read from f. This is
       similar to `not EOF (f)', but does not block on "files" that
       can grow, like Ttys or pipes. }
     function  CanRead (var f: GPC_FDR): Boolean; attribute (name
       = '_p_CanRead'); external;
     
     { Checks if data can be written to f. }
     function  CanWrite (var f: GPC_FDR): Boolean; attribute (name
       = '_p_CanWrite'); external;
     
     { Get the file handle. }
     function  FileHandle (protected var f: GPC_FDR): Integer; attribute
       (name = '_p_FileHandle'); external;
     
     { Lock/unlock a file. }
     function  FileLock (var f: GPC_FDR; WriteLock, Block: Boolean):
       Boolean; attribute (name = '_p_FileLock'); external;
     function  FileUnlock (var f: GPC_FDR): Boolean; attribute (name
       = '_p_FileUnlock'); external;
     
     { Try to map (a part of) a file to memory. }
     function  MemoryMap (Start: Pointer; Length: SizeType; Access:
       Integer; Shared: Boolean;
                          var f: GPC_FDR; Offset: FileSizeType): Pointer;
       attribute (name = '_p_MemoryMap'); external;
     
     { Unmap a previous memory mapping. }
     procedure MemoryUnMap (Start: Pointer; Length: SizeType); attribute
       (name = '_p_MemoryUnMap'); external;
     
     type
       Natural = 1 .. MaxInt;
       IOSelectEvents = (SelectReadOrEOF, SelectRead, SelectEOF,
       SelectWrite, SelectException, SelectAlways);
     
     type
       IOSelectType = record
         f: PAnyFile;
         Wanted: set of IOSelectEvents;
         Occurred: set of Low (IOSelectEvents) .. Pred (SelectAlways)
       end;
     
     { Waits for one of several events to happen. Returns when one or
       more of the wanted events for one of the files occur. If they have
       already occurred before calling the function, it returns
       immediately. MicroSeconds can specify a timeout. If it is 0, the
       function will return immediately, whether or not an event has
       occurred. If it is negative, the function will wait forever until
       an event occurs. The Events parameter can be Null, in which case
       the function only waits for the timeout. If any of the file
       pointers (f) in Events are nil or the files pointed to are closed,
       they are simply ignored for convenience.
     
       It returns the index of one of the files for which any event has
       occurred. If events have occurred for several files, is it
       undefined which of these file's index is returned. If no event
       occurs until the timeout, 0 is returned. If an error occurs or the
       target system does not have a `select' system call and Events is
       not Null, a negative value is returned. In the Occurred field of
       the elements of Events, events that have occurred are set. The
       state of events not wanted is undefined.
     
       The possible events are:
       SelectReadOrEOF: the file is at EOF or data can be read now.
       SelectRead:      data can be read now.
       SelectEOF:       the file is at EOF.
       SelectWrite:     data can be written now.
       SelectException: an exception occurred on the file.
       SelectAlways:    if this is set, *all* requested events will be
                        checked for this file in any case. Otherwise,
                        checks may be skipped if already another event
                        for this or another file was found.
     
       Notes:
       Checking for EOF requires some reading ahead internally (just like
       the EOF function) which can be avoided by setting SelectReadOrEOF
       instead of SelectRead and SelectEOF. If this is followed by, e.g.,
       a BlockRead with 4 parameters, the last parameter will be 0 if and
       only the file is at EOF, and otherwise, data will be read directly
       from the file without reading ahead and buffering.
     
       SelectAlways should be set for files whose events are considered
       to be of higher priority than others. Otherwise, if one is
       interested in just any event, not setting SelectAlways may be a
       little faster. }
     function  IOSelect (var Events: array [m .. n: Natural] of
       IOSelectType; MicroSeconds: MicroSecondTimeType): Integer;
       attribute (name = '_p_IOSelect'); external;
     
     { A simpler interface to SelectIO for the most common use. Waits for
       SelectReadOrEOF on all files and returns an index. }
     function  IOSelectRead (const Files: array [m .. n: Natural] of
       PAnyFile; MicroSeconds: MicroSecondTimeType): Integer; attribute
       (name = '_p_IOSelectRead'); external;
     
     { Bind a filename to an external file }
     procedure AssignFile   (var t: AnyFile; const FileName: String);
       attribute (name = '_p_AssignFile'); external;
     procedure AssignBinary (var t: Text; const FileName: String);
       attribute (name = '_p_AssignBinary'); external;
     procedure AssignHandle (var t: AnyFile; Handle: Integer; CloseFlag:
       Boolean); attribute (name = '_p_AssignHandle'); external;
     
     { Under development }
     procedure AnyStringTFDD_Reset (var f: GPC_FDR; var Buf:
       ConstAnyString); attribute (name = '_p_AnyStringTFDD_Reset');
       external;
     { @@ procedure AnyStringTFDD_Rewrite (var f: GPC_FDR; var Buf:
       VarAnyString); attribute (name = '_p_AnyStringTFDD_Rewrite'); }
     procedure StringTFDD_Reset (var f: GPC_FDR; var Buf: ConstAnyString;
       var s: array [m .. n: Integer] of Char); attribute (name
       = '_p_StringTFDD_Reset'); external;
     { @@ procedure StringTFDD_Rewrite (var f: GPC_FDR; var Buf:
       VarAnyString; var s: String); attribute (name
       = '_p_StringTFDD_Rewrite'); }
     
     { Returns True is a terminal device is open on the file f, False if
       f is not open or not connected to a terminal. }
     function  IsTerminal (protected var f: GPC_FDR): Boolean; attribute
       (name = '_p_IsTerminal'); external;
     
     { Returns the file name of the terminal device that is open on the
       file f. Returns the empty string if (and only if) f is not open or
       not connected to a terminal. }
     function  GetTerminalName (protected var f: GPC_FDR): TString;
       attribute (name = '_p_GetTerminalName'); external;
     
     { Command line option parsing, from getopt.pas }
     
     const
       EndOfOptions      = #255;
       NoOption          = #1;
       UnknownOption     = '?';
       LongOption        = #0;
       UnknownLongOption = '?';
     
     var
       FirstNonOption        : Integer; attribute (name
       = '_p_FirstNonOption'); external;
       HasOptionArgument     : Boolean; attribute (name
       = '_p_HasOptionArgument'); external;
       OptionArgument        : TString; attribute (name
       = '_p_OptionArgument'); external;
       UnknownOptionCharacter: Char; attribute (name
       = '_p_UnknownOptionCharacter'); external;
       GetOptErrorFlag       : Boolean; attribute (name
       = '_p_GetOptErrorFlag'); external;
     
     { Parses command line arguments for options and returns the next
       one.
     
       If a command line argument starts with `-', and is not exactly `-'
       or `--', then it is an option element. The characters of this
       element (aside from the initial `-') are option characters. If
       `GetOpt' is called repeatedly, it returns successively each of the
       option characters from each of the option elements.
     
       If `GetOpt' finds another option character, it returns that
       character, updating `FirstNonOption' and internal variables so
       that the next call to `GetOpt' can resume the scan with the
       following option character or command line argument.
     
       If there are no more option characters, `GetOpt' returns
       EndOfOptions. Then `FirstNonOption' is the index of the first
       command line argument that is not an option. (The command line
       arguments have been permuted so that those that are not options
       now come last.)
     
       OptString must be of the form `[+|-]abcd:e:f:g::h::i::'.
     
       a, b, c are options without arguments
       d, e, f are options with required arguments
       g, h, i are options with optional arguments
     
       Arguments are text following the option character in the same
       command line argument, or the text of the following command line
       argument. They are returned in OptionArgument. If an option has no
       argument, OptionArgument is empty. The variable HasOptionArgument
       tells whether an option has an argument. This is mostly useful for
       options with optional arguments, if one wants to distinguish an
       empty argument from no argument.
     
       If the first character of OptString is `+', GetOpt stops at the
       first non-option argument.
     
       If it is `-', GetOpt treats non-option arguments as options and
       return NoOption for them.
     
       Otherwise, GetOpt permutes arguments and handles all options,
       leaving all non-options at the end. However, if the environment
       variable POSIXLY_CORRECT is set, the default behaviour is to stop
       at the first non-option argument, as with `+'.
     
       The special argument `--' forces an end of option-scanning
       regardless of the first character of OptString. In the case of
       `-', only `--' can cause GetOpt to return EndOfOptions with
       FirstNonOption <= ParamCount.
     
       If an option character is seen that is not listed in OptString,
       UnknownOption is returned. The unrecognized option character is
       stored in UnknownOptionCharacter. Unless GetOptErrorFlag is set to
       False, an error message is printed to StdErr automatically. }
     function  GetOpt (const OptString: String): Char; attribute (name
       = '_p_GetOpt'); external;
     
     type
       OptArgType = (NoArgument, RequiredArgument, OptionalArgument);
     
       OptionType = record
         OptionName: CString;
         Argument  : OptArgType;
         Flag      : ^Char;  { if nil, v is returned. Otherwise, Flag^ is
       ... }
         v         : Char    { ... set to v, and LongOption is returned }
       end;
     
     { Recognize short options, described by OptString as above, and long
       options, described by LongOptions.
     
       Long-named options begin with `--' instead of `-'. Their names may
       be abbreviated as long as the abbreviation is unique or is an
       exact match for some defined option. If they have an argument, it
       follows the option name in the same argument, separated from the
       option name by a `=', or else the in next argument. When GetOpt
       finds a long-named option, it returns LongOption if that option's
       `Flag' field is non-nil, and the value of the option's `v' field
       if the `Flag' field is nil.
     
       LongIndex, if not Null, returns the index in LongOptions of the
       long-named option found. It is only valid when a long-named option
       has been found by the most recent call.
     
       If LongOnly is set, `-' as well as `--' can indicate a long
       option. If an option that starts with `-' (not `--') doesn't match
       a long option, but does match a short option, it is parsed as a
       short option instead. If an argument has the form `-f', where f is
       a valid short option, don't consider it an abbreviated form of a
       long option that starts with `f'. Otherwise there would be no way
       to give the `-f' short option. On the other hand, if there's a
       long option `fubar' and the argument is `-fu', do consider that an
       abbreviation of the long option, just like `--fu', and not `-f'
       with argument `u'. This distinction seems to be the most useful
       approach.
     
       As an additional feature (not present in the C counterpart), if
       the last character of OptString is `-' (after a possible starting
       `+' or `-' character), or OptString is empty, all long options
       with a nil `Flag' field will automatically be recognized as short
       options with the character given by the `v' field. This means, in
       the common (and recommended) case that all short options have long
       equivalents, you can simply pass an empty OptString (or pass `+-'
       or `--' as OptString if you want this behaviour, see the comment
       for GetOpt), and you will only have to maintain the LongOptions
       array when you add or change options. }
     function  GetOptLong (const OptString: String; const LongOptions:
       array [m .. n: Integer] of OptionType { can be Null };
                           var LongIndex: Integer { can be Null };
       LongOnly: Boolean): Char; attribute (name = '_p_GetOptLong');
       external;
     
     { Reset GetOpt's state and make the next GetOpt or GetOptLong start
       (again) with the StartArgument'th argument (may be 1). This is
       useful for special purposes only. It is *necessary* to do this
       after altering the contents of CParamCount/CParameters (which is
       not usually done, either). }
     procedure ResetGetOpt (StartArgument: Integer); attribute (name
       = '_p_ResetGetOpt'); external;
     
     { Set operations, from sets.pas }
     
     { All set operations are built-in identifiers and not declared in
       gpc.pas. }
     
     { Heap management routines, from heap.pas }
     
     { GPC implements both Mark/Release and Dispose. Both can be mixed
       freely in the same program. Dispose should be preferred, since
       it's faster. }
     
     { C heap management routines. NOTE: if Release is used anywhere in
       the program, CFreeMem and CReAllocMem may not be used for pointers
       that were not allocated with CGetMem. }
     function  CGetMem     (Size: SizeType): Pointer; external
       name 'malloc';
     procedure CFreeMem    (aPointer: Pointer); external name 'free';
     function  CReAllocMem (aPointer: Pointer; NewSize: SizeType):
       Pointer; external name 'realloc';
     
     type
       GetMemType     = ^function (Size: SizeType): Pointer;
       FreeMemType    = ^procedure (aPointer: Pointer);
       ReAllocMemType = ^function (aPointer: Pointer; NewSize: SizeType):
       Pointer;
     
     { These variables can be set to user-defined routines for memory
       allocation/deallocation. GetMemPtr may return nil when
       insufficient memory is available. GetMem/New will produce a
       runtime error then. }
     var
       GetMemPtr    : GetMemType; attribute (name = '_p_GetMemPtr');
       external;
       FreeMemPtr   : FreeMemType; attribute (name = '_p_FreeMemPtr');
       external;
       ReAllocMemPtr: ReAllocMemType; attribute (name
       = '_p_ReAllocMemPtr'); external;
     
       { Address of the lowest byte of heap used }
       HeapLow: PtrCard; attribute (name = '_p_HeapLow'); external;
     
       { Address of the highest byte of heap used }
       HeapHigh: PtrCard; attribute (name = '_p_HeapHigh'); external;
     
       { If set to true, `Dispose' etc. will raise a runtime error if
         given an invalid pointer. }
       HeapChecking: Boolean; attribute (name = '_p_HeapChecking');
       external;
     
     const
       UndocumentedReturnNil = Pointer (-1);
     
     function  SuspendMark: Pointer; attribute (name = '_p_SuspendMark');
       external;
     procedure ResumeMark (p: Pointer); attribute (name
       = '_p_ResumeMark'); external;
     
     { Calls the procedure Proc for each block that would be released
       with `Release (aMark)'. aMark must have been marked with Mark. For
       an example of its usage, see the HeapMon unit. }
     procedure ForEachMarkedBlock (aMark: Pointer; procedure Proc
       (aPointer: Pointer; aSize: SizeType; aCaller: Pointer)); attribute
       (name = '_p_ForEachMarkedBlock'); external;
     
     procedure ReAllocMem (var aPointer: Pointer; NewSize: SizeType);
       attribute (name = '_p_ReAllocMem'); external;
     
     { Memory transfer procedures, from move.pas }
     
     { The move operations are built-in identifiers and not declared in
       gpc.pas. }
     
     { Routines to handle endianness, from endian.pas }
     
     { Boolean constants about endianness and alignment }
     
     const
       BitsBigEndian  = {$ifdef __BITS_LITTLE_ENDIAN__}
                        False
                        {$elif defined (__BITS_BIG_ENDIAN__)}
                        True
                        {$else}
                        {$error Bit endianness is not defined!}
                        {$endif};
     
       BytesBigEndian = {$ifdef __BYTES_LITTLE_ENDIAN__}
                        False
                        {$elif defined (__BYTES_BIG_ENDIAN__)}
                        True
                        {$else}
                        {$error Byte endianness is not defined!}
                        {$endif};
     
       WordsBigEndian = {$ifdef __WORDS_LITTLE_ENDIAN__}
                        False
                        {$elif defined (__WORDS_BIG_ENDIAN__)}
                        True
                        {$else}
                        {$error Word endianness is not defined!}
                        {$endif};
     
       NeedAlignment  = {$ifdef __NEED_ALIGNMENT__}
                        True
                        {$elif defined (__NEED_NO_ALIGNMENT__)}
                        False
                        {$else}
                        {$error Alignment is not defined!}
                        {$endif};
     
     { Convert single variables from or to little or big endian format.
       This only works for a single variable or a plain array of a simple
       type. For more complicated structures, this has to be done for
       each component separately! Currently, ConvertFromFooEndian and
       ConvertToFooEndian are the same, but this might not be the case on
       middle-endian machines. Therefore, we provide different names. }
     procedure ReverseBytes            (var Buf; ElementSize, Count:
       SizeType); attribute (name = '_p_ReverseBytes'); external;
     procedure ConvertFromLittleEndian (var Buf; ElementSize, Count:
       SizeType); attribute (name = '_p_ConvertLittleEndian'); external;
     procedure ConvertFromBigEndian    (var Buf; ElementSize, Count:
       SizeType); attribute (name = '_p_ConvertBigEndian'); external;
     procedure ConvertToLittleEndian   (var Buf; ElementSize, Count:
       SizeType); external name '_p_ConvertLittleEndian';
     procedure ConvertToBigEndian      (var Buf; ElementSize, Count:
       SizeType); external name '_p_ConvertBigEndian';
     
     { Read a block from a file and convert it from little or
       big endian format. This only works for a single variable or a
       plain array of a simple type, note the comment for
       `ConvertFromLittleEndian' and `ConvertFromBigEndian'. }
     procedure BlockReadLittleEndian   (var aFile: File; var   Buf;
       ElementSize, Count: SizeType); attribute (iocritical, name
       = '_p_BlockRead_LittleEndian'); external;
     procedure BlockReadBigEndian      (var aFile: File; var   Buf;
       ElementSize, Count: SizeType); attribute (iocritical, name
       = '_p_BlockRead_BigEndian'); external;
     
     { Write a block variable to a file and convert it to little or big
       endian format before. This only works for a single variable or a
       plain array of a simple type. Apart from this, note the comment
       for `ConvertToLittleEndian' and `ConvertToBigEndian'. }
     procedure BlockWriteLittleEndian  (var aFile: File; const Buf;
       ElementSize, Count: SizeType); attribute (iocritical, name
       = '_p_BlockWrite_LittleEndian'); external;
     procedure BlockWriteBigEndian     (var aFile: File; const Buf;
       ElementSize, Count: SizeType); attribute (iocritical, name
       = '_p_BlockWrite_BigEndian'); external;
     
     { Read and write strings from/to binary files, where the length is
       stored in the given endianness and with a fixed size (64 bits),
       and therefore is independent of the system. }
     procedure ReadStringLittleEndian  (var f: File; var s: String);
       attribute (iocritical, name = '_p_ReadStringLittleEndian');
       external;
     procedure ReadStringBigEndian     (var f: File; var s: String);
       attribute (iocritical, name = '_p_ReadStringBigEndian'); external;
     procedure WriteStringLittleEndian (var f: File; const s: String);
       attribute (iocritical, name = '_p_WriteStringLittleEndian');
       external;
     procedure WriteStringBigEndian    (var f: File; const s: String);
       attribute (iocritical, name = '_p_WriteStringBigEndian');
       external;
     
     { Initialization, from init.pas }
     
     var
       InitProc: ^procedure; attribute (name = '_p_InitProc'); external;
     


Previous: Run Time System, Up: Programming

6.15 Units included with GPC

GPC distributions now include a number of useful Pascal units and a complete set of BP compatibility units – except for the `Graph' unit (which is currently distributed separately due to its license) and the OOP stuff. The main use of these units is to provide a way to port BP programs to GPC as easily as possible. Some of the units also implement functionaliy not available otherwise.

Most of the BP compatibility units – except `CRT' and `Printer' – are merely meant to let programs written for BP compile with GPC as easily as possible. They should not be used in newly written code, and for code ported from BP to GPC, it is suggested to replace them successively with the more powerful – and often easier to use – alternatives that GPC's Run Time System (see Run Time System) offers.

The following sections describe all units included with GPC (besides the `GPC' module which describes the interface to the Run Time System, Run Time System).


Next: , Up: GPC Units

6.15.1 BP compatibility: CRT & WinCRT, portable, with many extensions

The following listing contains the interface of the CRT unit.

`CRT' is a `curses' based unit for text screen handling. It is compatible to BP's `CRT' unit, even in a lot of minor details like the values of function key codes and includes some routines for compatibility with TP5's `Win' unit as well as BP's `WinCRT' and Turbo Power's `TPCrt' units, and some extensions.

The unit has been extended by many functions that were lacking in BP's unit and required assembler code or direct memory/port access to be implemented under BP. The GPC version is now fully suited for portable, real-world programming without any dirty tricks.

The unit is also available as `WinCRT', completely identical to `CRT'. The only purpose of this “feature” is to let programs written for TPW or BP, with a `uses WinCRT' directive, compile without changes. Unlike TPW/BP's `WinCRT' unit, GPC's unit is not crippled, compared to `CRT'.

To use this unit, you will need the `ncurses' (version 5.0 or newer) or `PDCurses' library which can be found in http://www.gnu-pascal.de/libs/.

     { CRT (Crt Replacement Tool)
       Portable BP compatible CRT unit for GPC with many extensions
     
       This unit is aware of terminal types. This means programs using
       this unit will work whether run locally or while being logged in
       remotely from a system with a completely different terminal type
       (as long as the appropriate terminfo entry is present on the
       system where the program is run).
     
       NOTES:
     
       - The CRT unit needs the ncurses and panel libraries which should
         be available for almost any system. For Dos systems, where
         ncurses is not available, it is configured to use the PDCurses
         and its panel library instead. On Unix systems with X11, it can
         also use PDCurses (xcurses) and xpanel to produce X11 programs.
         The advantage is that the program won't need an xterm with a
         valid terminfo entry, the output may look a little nicer and
         function keys work better than in an xterm, but the disadvantage
         is that it will only run under X. The ncurses and PDCurses
         libraries (including panel and xpanel, resp.) can be found in
         http://www.gnu-pascal.de/libs/
         (Note that ncurses is already installed on many Unix systems.)
         For ncurses, version 5.0 or newer is required.
     
         When an X11 version under Unix is wanted, give `-DX11' when
         compiling crt.pas and crtc.c (or when compiling crt.pas or a
         program that uses CRT with `--automake'). On pre-X11R6 systems,
         give `-DNOX11R6' additionally. You might also have to give the
         path to the X11 libraries with `-L', e.g. `-L /usr/X11/lib'.
     
       - A few features cannot be implemented in a portable way and are
         only available on some systems:
     
           Sound, NoSound 1)                  -----------------------.
           GetShiftState                      ------------------.    |
           TextMode etc. 2)                   -------------.    |    |
           CRTSavePreviousScreen              --------.    |    |    |
           Interrupt signal (Ctrl-C) handling ---.    |    |    |    |
                                                 |    |    |    |    |
         Linux/IA32 3) (terminal)                X    X 4) X 5) X 6) X 6)
         Other Unix (terminal)                   X    X 7) X 5) -    -
         Unix (X11 version)                      X    X    -    X    -
         Dos (DJGPP)                             X    X    X    X    X
         MS-Windows (Cygwin, mingw, MSYS)        X    -    X 8) X    -
     
         Notes:
     
         1) If you define NO_CRT_DUMMY_SOUND while compiling CRT, you
            will get linking errors when your program tries to use
            Sound/NoSound on a platform where it's not supported (which
            is useful to detect at compile time if playing sound is a
            major task of your program). Otherwise, Sound/NoSound will
            simply do nothing (which is usually acceptable if the program
            uses these routines just for an occasional beep).
     
         2) Changing to monochrome modes works on all platforms. Changing
            the screen size only works on those indicated. However, even
            on the platforms not supported, the program will react to
            screen size changes by external means (e.g. changing the
            window size with the mouse if running in a GUI window or
            resizing a console or virtual terminal).
     
         3) Probably also on other processors, but I've had no chance to
            test this yet.
     
         4) Only on a local console with access permissions to the
            corresponding virtual console memory device or using the
            `crtscreen' utility (see crtscreen.c in the demos directory).
     
         5) Only if supported by an external command (e.g., in xterms and
            on local Linux consoles). The command to be called can be
            defined in the environment variable `RESIZETERM' (where the
            variables `columns' and `lines' in the command are set to the
            size wanted). If not set, the code will try `resize -s' in an
            xterm and otherwise `SVGATextMode' and `setfont'. For this to
            work, these utilities need to be present in the PATH or
            `/usr/sbin' or `/usr/local/sbin'. Furthermore, SVGATextMode
            and setfont require root permissions, either to the
            executable of the program compiled with CRT or to resizecons
            (called by setfont) or SVGATextMode. To allow the latter, do
            "chmod u+s `which resizecons`" and/or
            "chmod u+s `which SVGATextMode`", as root once, but only if
            you really want each user to be allowed to change the text
            mode.
     
         6) Only on local consoles.
     
         7) Some terminals only. Most xterms etc. support it as well as
            other terminals that support an "alternate screen" in the
            smcup/rmcup terminal capabilities.
     
         8) Only with PDCurses, not with ncurses. Changing the number of
            screen *columns* doesn't work in a full-screen session.
     
       - When CRT is initialized (automatically or explicitly; see the
         comments for CRTInit), the screen is cleared, and at the end of
         the program, the cursor is placed at the bottom of the screen
         (curses behaviour).
     
       - All the other things (including most details like color and
         function key constants) are compatible with BP's CRT unit, and
         there are many extensions that BP's unit does not have.
     
       - When the screen size is changed by an external event (e.g.,
         resizing an xterm or changing the screen size from another VC
         under Linux), the virtual "function key" kbScreenSizeChanged is
         returned. Applications can use the virtual key to resize their
         windows. kbScreenSizeChanged will not be returned if the screen
         size change was initiated by the program itself (by using
         TextMode or SetScreenSize). Note that TextMode sets the current
         panel to the full screen size, sets the text attribute to the
         default and clears the window (BP compatibility), while
         SetScreenSize does not.
     
       - After the screen size has been changed, whether by using
         TextMode, SetScreenSize or by an external event, ScreenSize will
         return the new screen size. The current window and all panels
         will have been adjusted to the new screen size. This means, if
         their right or lower ends are outside the new screen size, the
         windows are moved to the left and/or top as far as necessary. If
         this is not enough, i.e., if they are wider/higher than the new
         screen size, they are shrinked to the total screen width/height.
         When the screen size is enlarged, window sizes are not changed,
         with one exception: Windows that extend through the whole screen
         width/height are enlarged to the whole new screen width/height
         (in particular, full-screen windows remain full-screen). This
         behaviour might not be optimal for all purposes, but you can
         always resize your windows in your application after the screen
         size change.
     
       - (ncurses only) The environment variable `ESCDELAY' specifies the
         number of milliseconds allowed between an `Esc' character and
         the rest of an escape sequence (default 1000). Setting it to a
         value too small can cause problems with programs not recognizing
         escape sequences such as function keys, especially over slow
         network connections. Setting it to a value too large can delay
         the recognition of an `ESC' key press notably. On local Linux
         consoles, e.g., 10 seems to be a good value.
     
       - When trying to write portable programs, don't rely on exactly
         the same look of your output and the availability of all the key
         combinations. Some kinds of terminals support only some of the
         display attributes and special characters, and usually not all
         of the keys declared are really available. Therefore, it's safer
         to provide the same function on different key combinations and
         to not use the more exotic ones.
     
       - CRT supports an additional modifier key (if present), called
         `Extra'. On DJGPP, it's the <Scroll Lock> key, under X11 it's
         the modifier #4, and on a local Linux console, it's the `CtrlL'
         modifier (value 64) which is unused on many keytabs and can be
         mapped to any key(s), e.g. to those keys on new keyboards with
         these ugly symbols waiting to be replaced by penguins (keycodes
         125 and 127) by inserting the following two lines into your
         /etc/default.keytab and reloading the keytab with `loadkeys'
         (you usually have to do this as root):
     
         keycode 125 = CtrlL
         keycode 127 = CtrlL
     
       Copyright (C) 1998-2006 Free Software Foundation, Inc.
     
       Author: Frank Heckenbach <frank@pascal.gnu.de>
     
       This file is part of GNU Pascal.
     
       GNU Pascal is free software; you can redistribute it and/or modify
       it under the terms of the GNU General Public License as published
       by the Free Software Foundation; either version 2, or (at your
       option) any later version.
     
       GNU Pascal is distributed in the hope that it will be useful, but
       WITHOUT ANY WARRANTY; without even the implied warranty of
       MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
       General Public License for more details.
     
       You should have received a copy of the GNU General Public License
       along with GNU Pascal; see the file COPYING. If not, write to the
       Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA
       02111-1307, USA.
     
       As a special exception, if you link this file with files compiled
       with a GNU compiler to produce an executable, this does not cause
       the resulting executable to be covered by the GNU General Public
       License. This exception does not however invalidate any other
       reasons why the executable file might be covered by the GNU
       General Public License.
     
       Please also note the license of the curses library used. }
     
     {$gnu-pascal,I-}
     {$if __GPC_RELEASE__ < 20030722}
     {$error This unit requires GPC release 20030722 or newer.}
     {$endif}
     
     unit {$ifdef THIS_IS_WINCRT} WinCRT {$else} CRT {$endif};
     
     interface
     
     uses GPC;
     
     const
       { CRT modes }
       BW40          = 0;            { 40x25 Black/White }
       CO40          = 1;            { 40x25 Color }
       BW80          = 2;            { 80x25 Black/White }
       CO80          = 3;            { 80x25 Color }
       Mono          = 7;            { 80x25 Black/White }
       Font8x8       = 256;          { Add-in for 80x43 or 80x50 mode }
     
       { Mode constants for Turbo Pascal 3.0 compatibility }
       C40           = CO40;
       C80           = CO80;
     
       { Foreground and background color constants }
       Black         = 0;
       Blue          = 1;
       Green         = 2;
       Cyan          = 3;
       Red           = 4;
       Magenta       = 5;
       Brown         = 6;
       LightGray     = 7;
     
       { Foreground color constants }
       DarkGray      = 8;
       LightBlue     = 9;
       LightGreen    = 10;
       LightCyan     = 11;
       LightRed      = 12;
       LightMagenta  = 13;
       Yellow        = 14;
       White         = 15;
     
       { Add-in for blinking }
       Blink         = 128;
     
     type
       TTextAttr = Byte;
     
     var
       { If False (default: True), catch interrupt signals (SIGINT;
         Ctrl-C), and other flow control characters as well as SIGTERM,
         SIGHUP and perhaps other signals }
       CheckBreak: Boolean = True; attribute (name = 'crt_CheckBreak');
     
       { If True (default : False), replace Ctrl-Z by #0 in input }
       CheckEOF: Boolean = False; attribute (name = 'crt_CheckEOF');
     
       { Ignored -- meaningless here }
       DirectVideo: Boolean = True;
     
       { Ignored -- curses or the terminal driver will take care of that
         when necessary }
       CheckSnow: Boolean = False;
     
       { Current (sic!) text mode }
       LastMode: CCardinal = 3; attribute (name = 'crt_LastMode');
     
       { Current text attribute }
       TextAttr: TTextAttr = 7; attribute (name = 'crt_TextAttr');
     
       { Window upper left coordinates. *Obsolete*! Please see WindowMin
         below. }
       WindMin: CCardinal = High (CCardinal); attribute (name
       = 'crt_WindMin');
     
       { Window lower right coordinates. *Obsolete*! Please see WindowMax
         below. }
       WindMax: CCardinal = High (CCardinal); attribute (name
       = 'crt_WindMax');
     
     procedure AssignCRT (var f: Text);
     function  KeyPressed: Boolean; external name 'crt_KeyPressed';
     function  ReadKey: Char; external name 'crt_ReadKey';
     
     { Not effective on all platforms, see above. See also SetScreenSize
       and SetMonochrome. }
     procedure TextMode (Mode: Integer);
     
     procedure Window (x1, y1, x2, y2: CInteger); external
       name 'crt_Window';
     procedure GotoXY (x, y: CInteger); external name 'crt_GotoXY';
     function  WhereX: CInteger; external name 'crt_WhereX';
     function  WhereY: CInteger; external name 'crt_WhereY';
     procedure ClrScr; external name 'crt_ClrScr';
     procedure ClrEOL; external name 'crt_ClrEOL';
     procedure InsLine; external name 'crt_InsLine';
     procedure DelLine; external name 'crt_DelLine';
     procedure TextColor (Color: TTextAttr);
     procedure TextBackground (Color: TTextAttr);
     procedure LowVideo;
     procedure HighVideo;
     procedure NormVideo;
     procedure Delay (MS: CCardinal); external name 'crt_Delay';
     
     { Not available on all platforms, see above }
     procedure Sound (Hz: CCardinal); external name 'crt_Sound';
     procedure NoSound; external name 'crt_NoSound';
     
     { =================== Extensions over BP's CRT =================== }
     
     { Initializes the CRT unit. Should be called before using any of
       CRT's routines.
     
       Note: For BP compatibility, CRT is initizalized automatically when
       (almost) any of its routines are used for the first time. In this
       case, some defaults are set to match BP more closely. In
       particular, the PC charset (see SetPCCharSet) is enabled then
       (disabled otherwise), and the update level (see SetCRTUpdate) is
       set to UpdateRegularly (UpdateWaitInput otherwise). This feature
       is meant for BP compatibility *only*. Don't rely on it when
       writing a new program. Use CRTInit then, and set the defaults to
       the values you want explicitly.
     
       SetCRTUpdate is one of those few routines which will not cause CRT
       to be initialized immediately, and a value set with it will
       survive both automatic and explicit initialization, so you can use
       it to set the update level without caring which way CRT will be
       initialized. (This does not apply to SetPCCharSet. Since it works
       on a per-panel basis, it has to initialize CRT first, so there is
       a panel to start with.)
     
       If you terminate the program before calling CRTInit or any routine
       that causes automatic initialization, curses will never be
       initialized, so e.g., the screen won't be cleared. This can be
       useful, e.g., to check the command line arguments (or anything
       else) and if there's a problem, write an error and abort. Just be
       sure to write the error to StdErr, not Output (because Output will
       be assigned to CRT, and therefore writing to Output will cause CRT
       to be initialized, and because errors belong to StdErr, anyway),
       and to call `RestoreTerminal (True)' before (just to be sure, in
       case some code -- perhaps added later, or hidden in the
       initialization of some unit -- does initialize CRT). }
     procedure CRTInit; external name 'crt_Init';
     
     { Changes the input and output file and the terminal description CRT
       uses. Only effective with ncurses, and only if called before CRT
       is initialized (automatically or explicitly; see the comments for
       CRTInit). If TerminalType is nil, the default will be used. If
       InputFile and/or OutputFile are Null, they remain unchanged. }
     procedure CRTSetTerminal (TerminalType: CString; var InputFile,
       OutputFile: AnyFile); attribute (name = 'crt_SetTerminal');
     
     { If called with an argument True, it causes CRT to save the
       previous screen contents if possible (see the comments at the
       beginning of the unit), and restore them when calling
       RestoreTerminal (True). After RestoreTerminal (False), they're
       saved again, and at the end of the program, they're restored. If
       called with an argument False, it will prohibit this behaviour.
       The default, if this procedure is not called, depends on the
       terminal (generally it is active on most xterms and similar and
       not active on most other terminals).
     
       This procedure should be called before initializing CRT (using
       CRTInit or automatically), otherwise the previous screen contents
       may already have been overwritten. It has no effect under XCurses,
       because the program uses its own window, anyway. }
     procedure CRTSavePreviousScreen (On: Boolean); external
       name 'crt_SavePreviousScreen';
     
     { Returns True if CRTSavePreviousScreen was called with argument
       True and the functionality is really available. Note that the
       result is not reliable until CRT is initialized, while
       CRTSavePreviousScreen should be called before CRT is initialized.
       That's why they are two separate routines. }
     function  CRTSavePreviousScreenWorks: Boolean; external
       name 'crt_SavePreviousScreenWorks';
     
     { If CRT is initialized automatically, not via CRTInit, and
       CRTAutoInitProc is not nil, it will be called before actually
       initializing CRT. }
     var
       CRTAutoInitProc: procedure = nil; attribute (name
       = 'crt_AutoInitProc');
     
     { Aborts with a runtime error saying that CRT was not initialized.
       If you set CRTAutoInitProc to this procedure, you can effectively
       disable CRT's automatic initialization. }
     procedure CRTNotInitialized; attribute (name
       = 'crt_NotInitialized');
     
     { Set terminal to shell or curses mode. An internal procedure
       registered by CRT via RegisterRestoreTerminal does this as well,
       so CRTSetCursesMode has to be called only in unusual situations,
       e.g. after executing a process that changes terminal modes, but
       does not restore them (e.g. because it crashed or was killed), and
       the process was not executed with the Execute routine, and
       RestoreTerminal was not called otherwise. If you set it to False
       temporarily, be sure to set it back to True before doing any
       further CRT operations, otherwise the result may be strange. }
     procedure CRTSetCursesMode (On: Boolean); external
       name 'crt_SetCursesMode';
     
     { Do the same as `RestoreTerminal (True)', but also clear the screen
       after restoring the terminal (except for XCurses, because the
       program uses its own window, anyway). Does not restore and save
       again the previous screen contents if CRTSavePreviousScreen was
       called. }
     procedure RestoreTerminalClearCRT; attribute (name
       = 'crt_RestoreTerminalClearCRT');
     
     { Keyboard and character graphics constants -- BP compatible! =:-}
     {$i crt.inc}
     
     var
       { Tells whether the XCurses version of CRT is used }
       XCRT: Boolean = {$ifdef XCURSES} True {$else} False {$endif};
       attribute (name = 'crt_XCRT');
     
       { If True (default: False), the Beep procedure and writing #7 do a
         Flash instead }
       VisualBell: Boolean = False; attribute (name = 'crt_VisualBell');
     
       { Cursor shape codes. Only to be used in very special cases. }
       CursorShapeHidden: CInteger = 0; attribute (name
       = 'crt_CursorShapeHidden');
       CursorShapeNormal: CInteger = 1; attribute (name
       = 'crt_CursorShapeNormal');
       CursorShapeFull:   CInteger = 2; attribute (name
       = 'crt_CursorShapeFull');
     
     type
       TKey = CCardinal;
     
       TCursorShape = (CursorIgnored, CursorHidden, CursorNormal,
       CursorFat, CursorBlock);
     
       TCRTUpdate = (UpdateNever, UpdateWaitInput, UpdateInput,
                     UpdateRegularly, UpdateAlways);
     
       TPoint = record
         x, y: CInteger
       end;
     
       PCharAttr = ^TCharAttr;
       TCharAttr = record
         ch       : Char;
         Attr     : TTextAttr;
         PCCharSet: Boolean
       end;
     
       PCharAttrs = ^TCharAttrs;
       TCharAttrs = array [1 .. MaxVarSize div SizeOf (TCharAttr)] of
       TCharAttr;
     
       TWindowXYInternalCard8 = Cardinal attribute (Size = 8);
       TWindowXYInternalFill = Integer attribute (Size = BitSizeOf
       (CCardinal) - 16);
       TWindowXY = packed record
         {$ifdef __BYTES_BIG_ENDIAN__}
         Fill: TWindowXYInternalFill;
         y, x: TWindowXYInternalCard8
         {$elif defined (__BYTES_LITTLE_ENDIAN__)}
         x, y: TWindowXYInternalCard8;
         Fill: TWindowXYInternalFill
         {$else}
         {$error Endianness is not defined!}
         {$endif}
       end;
     
     { Make sure TWindowXY really has the same size as WindMin and
       WindMax. The value of the constant will always be True, and is of
       no further interest. }
     const
       AssertTWindowXYSize = CompilerAssert ((SizeOf (TWindowXY) = SizeOf
       (WindMin)) and
                                             (SizeOf (TWindowXY) = SizeOf
       (WindMax)));
     
     var
       { Window upper and left coordinates. More comfortable to access
         than WindMin, but also *obsolete*. WindMin and WindowMin still
         work, but have the problem that they implicitly limit the window
         size to 255x255 characters. Though that's not really small for a
         text window, it's easily possible to create bigger ones (e.g. in
         an xterm with a small font, on a high resolution screen and/or
         extending over several virutal desktops). When using coordinates
         greater than 254, the corresponding bytes in WindowMin/WindowMax
         will be set to 254, so, e.g., programs which do
         `Inc (WindowMin.x)' will not fail quite as badly (but probably
         still fail). The routines Window and GetWindow use Integer
         coordinates, and don't suffer from any of these problems, so
         they should be used instead. }
       WindowMin: TWindowXY absolute WindMin;
     
       { Window lower right coordinates. More comfortable to access than
         WindMax, but also *obsolete* (see the comments for WindowMin).
         Use Window and GetWindow instead. }
       WindowMax: TWindowXY absolute WindMax;
     
       { The attribute set by NormVideo }
       NormAttr: TTextAttr = 7; attribute (name = 'crt_NormAttr');
     
       { Tells whether the current mode is monochrome }
       IsMonochrome: Boolean = False; attribute (name
       = 'crt_IsMonochrome');
     
       { This value can be set to a combination of the shFoo constants
         and will be ORed to the actual shift state returned by
         GetShiftState. This can be used to easily simulate shift keys on
         systems where they can't be accessed. }
       VirtualShiftState: CInteger = 0; attribute (name
       = 'crt_VirtualShiftState');
     
     { Returns the size of the screen. Note: In BP's WinCRT unit,
       ScreenSize is a variable. But since writing to it from a program
       is pointless, anyway, providing a function here should not cause
       any incompatibility. }
     function  ScreenSize: TPoint; attribute (name
       = 'crt_GetScreenSize');
     
     { Change the screen size if possible. }
     procedure SetScreenSize (x, y: CInteger); external
       name 'crt_SetScreenSize';
     
     { Turns colors off or on. }
     procedure SetMonochrome (Monochrome: Boolean); external
       name 'crt_SetMonochrome';
     
     { Tell which modifier keys are currently pressed. The result is a
       combination of the shFoo constants defined in crt.inc, or 0 on
       systems where this function is not supported -- but note
       VirtualShiftState. If supported, ReadKey automatically converts
       kbIns and kbDel keys to kbShIns and kbShDel, resp., if shift is
       pressed. }
     function  GetShiftState: CInteger; external
       name 'crt_GetShiftState';
     
     { Get the extent of the current window. Use this procedure rather
       than reading WindMin and WindMax or WindowMin and WindowMax, since
       this routine allows for window sizes larger than 255. The
       resulting coordinates are 1-based (like in Window, unlike WindMin,
       WindMax, WindowMin and WindowMax). Any of the parameters may be
       Null in case you're interested in only some of the coordinates. }
     procedure GetWindow (var x1, y1, x2, y2: Integer); attribute (name
       = 'crt_GetWindow');
     
     { Determine when to update the screen. The possible values are the
       following. The given conditions *guarantee* updates. However,
       updates may occur more frequently (even if the update level is set
       to UpdateNever). About the default value, see the comments for
       CRTInit.
     
       UpdateNever    : never (unless explicitly requested with
                        CRTUpdate)
       UpdateWaitInput: before Delay and CRT input, unless typeahead is
                        detected
       UpdateInput    : before Delay and CRT input
       UpdateRegularly: before Delay and CRT input and otherwise in
                        regular intervals without causing too much
                        refresh. This uses a timer on some systems
                        (currently, Unix with ncurses). This was created
                        for BP compatibility, but for many applications,
                        a lower value causes less flickering in the
                        output, and additionally, timer signals won't
                        disturb other operations. Under DJGPP, this
                        always updates immediately, but this fact should
                        not mislead DJGPP users into thinking this is
                        always so.
       UpdateAlways   : after each output. This can be very slow. (Not so
                        under DJGPP, but this fact should not mislead
                        DJGPP users ...) }
     procedure SetCRTUpdate (UpdateLevel: TCRTUpdate); external
       name 'crt_SetUpdateLevel';
     
     { Do an update now, independently of the update level }
     procedure CRTUpdate; external name 'crt_Update';
     
     { Do an update now and completely redraw the screen }
     procedure CRTRedraw; external name 'crt_Redraw';
     
     { Return Ord (key) for normal keys and $100 * Ord (fkey) for
       function keys }
     function  ReadKeyWord: TKey; external name 'crt_ReadKeyWord';
     
     { Extract the character and scan code from a TKey value }
     function  Key2Char (k: TKey): Char;
     function  Key2Scan (k: TKey): Char;
     
     { Convert a key to upper/lower case if it is a letter, leave it
       unchanged otherwise }
     function  UpCaseKey (k: TKey): TKey;
     function  LoCaseKey (k: TKey): TKey;
     
     { Return key codes for the combination of the given key with Ctrl,
       Alt, AltGr or Extra, resp. Returns 0 if the combination is
       unknown. }
     function  CtrlKey  (ch: Char): TKey; attribute (name
       = 'crt_CtrlKey');
     function  AltKey   (ch: Char): TKey; external name 'crt_AltKey';
     function  AltGrKey (ch: Char): TKey; external name 'crt_AltGrKey';
     function  ExtraKey (ch: Char): TKey; external name 'crt_ExtraKey';
     
     { Check if k is a pseudo key generated by a deadly signal trapped }
     function  IsDeadlySignal (k: TKey): Boolean;
     
     { Produce a beep or a screen flash }
     procedure Beep; external name 'crt_Beep';
     procedure Flash; external name 'crt_Flash';
     
     { Get size of current window (calculated using GetWindow) }
     function  GetXMax: Integer;
     function  GetYMax: Integer;
     
     { Get/goto an absolute position }
     function  WhereXAbs: Integer;
     function  WhereYAbs: Integer;
     procedure GotoXYAbs (x, y: Integer);
     
     { Turn scrolling on or off }
     procedure SetScroll (State: Boolean); external name 'crt_SetScroll';
     
     { Read back whether scrolling is enabled }
     function  GetScroll: Boolean; external name 'crt_GetScroll';
     
     { Determine whether to interpret non-ASCII characters as PC ROM
       characters (True), or in a system dependent way (False). About the
       default, see the comments for CRTInit. }
     procedure SetPCCharSet (PCCharSet: Boolean); external
       name 'crt_SetPCCharSet';
     
     { Read back the value set by SetPCCharSet }
     function  GetPCCharSet: Boolean; external name 'crt_GetPCCharSet';
     
     { Determine whether to interpret #7, #8, #10, #13 as control
       characters (True, default), or as graphics characters (False) }
     procedure SetControlChars (UseControlChars: Boolean); external
       name 'crt_SetControlChars';
     
     { Read back the value set by SetControlChars }
     function  GetControlChars: Boolean; external
       name 'crt_GetControlChars';
     
     procedure SetCursorShape (Shape: TCursorShape); external
       name 'crt_SetCursorShape';
     function  GetCursorShape: TCursorShape; external
       name 'crt_GetCursorShape';
     
     procedure HideCursor;
     procedure HiddenCursor;
     procedure NormalCursor;
     procedure FatCursor;
     procedure BlockCursor;
     procedure IgnoreCursor;
     
     { Simulates a block cursor by writing a block character onto the
       cursor position. The procedure automatically finds the topmost
       visible panel whose shape is not CursorIgnored and places the
       simulated cursor there (just like the hardware cursor), with
       matching attributes, if the cursor shape is CursorFat or
       CursorBlock (otherwise, no simulated cursor is shown).
     
       Calling this procedure again makes the simulated cursor disappear.
       In particular, to get the effect of a blinking cursor, you have to
       call the procedure repeatedly (say, 8 times a second). CRT will
       not do this for you, since it does not intend to be your main
       event loop. }
     procedure SimulateBlockCursor; external
       name 'crt_SimulateBlockCursor';
     
     { Makes the cursor simulated by SimulateBlockCursor disappear if it
       is active. Does nothing otherwise. You should call this procedure
       after using SimulateBlockCursor before doing any further CRT
       output (though failing to do so should not hurt except for
       possibly leaving the simulated cursor in its old position longer
       than it should). }
     procedure SimulateBlockCursorOff; external
       name 'crt_SimulateBlockCursorOff';
     
     function  GetTextColor: Integer;
     function  GetTextBackground: Integer;
     
     { Write string at the given position without moving the cursor.
       Truncated at the right margin. }
     procedure WriteStrAt (x, y: Integer; const s: String; Attr:
       TTextAttr);
     
     { Write (several copies of) a char at then given position without
       moving the cursor. Truncated at the right margin. }
     procedure WriteCharAt (x, y, Count: Integer; ch: Char; Attr:
       TTextAttr);
     
     { Write characters with specified attributes at the given position
       without moving the cursor. Truncated at the right margin. }
     procedure WriteCharAttrAt (x, y, Count: CInteger; CharAttr:
       PCharAttrs); external name 'crt_WriteCharAttrAt';
     
     { Write a char while moving the cursor }
     procedure WriteChar (ch: Char);
     
     { Read a character from a screen position }
     procedure ReadChar (x, y: CInteger; var ch: Char; var Attr:
       TTextAttr); external name 'crt_ReadChar';
     
     { Change only text attributes, leave characters. Truncated at the
       right margin. }
     procedure ChangeTextAttr (x, y, Count: Integer; NewAttr: TTextAttr);
     
     { Fill current window }
     procedure FillWin (ch: Char; Attr: TTextAttr); external
       name 'crt_FillWin';
     
     { Calculate size of memory required for ReadWin in current window. }
     function  WinSize: SizeType; external name 'crt_WinSize';
     
     { Save window contents. Buf must be WinSize bytes large. }
     procedure ReadWin (var Buf); external name 'crt_ReadWin';
     
     { Restore window contents saved by ReadWin. The size of the current
       window must match the size of the window from which ReadWin was
       used, but the position may be different. }
     procedure WriteWin (const Buf); external name 'crt_WriteWin';
     
     type
       WinState = record
         x1, y1, x2, y2, WhereX, WhereY, NewX1, NewY1, NewX2, NewY2:
       Integer;
         TextAttr: TTextAttr;
         CursorShape: TCursorShape;
         ScreenSize: TPoint;
         Buffer: ^Byte
       end;
     
     { Save window position and size, cursor position, text attribute and
       cursor shape -- *not* the window contents. }
     procedure SaveWin (var State: WinState);
     
     { Make a new window (like Window), and save the contents of the
       screen below the window as well as the position and size, cursor
       position, text attribute and cursor shape of the old window. }
     procedure MakeWin (var State: WinState; x1, y1, x2, y2: Integer);
     
     { Create window in full size, save previous text mode and all values
       that MakeWin does. }
     procedure SaveScreen (var State: WinState);
     
     { Restore the data saved by SaveWin, MakeWin or SaveScreen. }
     procedure RestoreWin (var State: WinState);
     
     { Panels }
     
     type
       TPanel = Pointer;
     
     function  GetActivePanel: TPanel; external
       name 'crt_GetActivePanel';
     procedure PanelNew                 (x1, y1, x2, y2: CInteger;
       BindToBackground: Boolean); external name 'crt_PanelNew';
     procedure PanelDelete              (Panel: TPanel); external
       name 'crt_PanelDelete';
     procedure PanelBindToBackground    (Panel: TPanel; BindToBackground:
       Boolean); external name 'crt_PanelBindToBackground';
     function  PanelIsBoundToBackground (Panel: TPanel): Boolean;
       external name 'crt_PanelIsBoundToBackground';
     procedure PanelActivate            (Panel: TPanel); external
       name 'crt_PanelActivate';
     procedure PanelHide                (Panel: TPanel); external
       name 'crt_PanelHide';
     procedure PanelShow                (Panel: TPanel); external
       name 'crt_PanelShow';
     function  PanelHidden              (Panel: TPanel): Boolean;
       external name 'crt_PanelHidden';
     procedure PanelTop                 (Panel: TPanel); external
       name 'crt_PanelTop';
     procedure PanelBottom              (Panel: TPanel); external
       name 'crt_PanelBottom';
     procedure PanelMoveAbove           (Panel, Above: TPanel); external
       name 'crt_PanelMoveAbove';
     procedure PanelMoveBelow           (Panel, Below: TPanel); external
       name 'crt_PanelMoveBelow';
     function  PanelAbove               (Panel: TPanel): TPanel; external
       name 'crt_PanelAbove';
     function  PanelBelow               (Panel: TPanel): TPanel; external
       name 'crt_PanelBelow';
     
     { TPCRT compatibility }
     
     { Write a string at the given position without moving the cursor.
       Truncated at the right margin. }
     procedure WriteString (const s: String; y, x: Integer);
     
     { Write a string at the given position with the given attribute
       without moving the cursor. Truncated at the right margin. }
     procedure FastWriteWindow (const s: String; y, x: Integer; Attr:
       TTextAttr);
     
     { Write a string at the given absolute position with the given
      attribute without moving the cursor. Truncated at the right
       margin. }
     procedure FastWrite       (const s: String; y, x: Integer; Attr:
       TTextAttr);
     
     { WinCRT compatibility }
     
     const
       cw_UseDefault = Integer ($8000);
     
     var
       { Ignored }
       WindowOrg : TPoint = (cw_UseDefault, cw_UseDefault);
       WindowSize: TPoint = (cw_UseDefault, cw_UseDefault);
       Origin    : TPoint = (0, 0);
       InactiveTitle: PChar = '(Inactive %s)';
       AutoTracking: Boolean = True;
       WindowTitle: {$ifdef __BP_TYPE_SIZES__}
                    array [0 .. 79] of Char
                    {$else}
                    TStringBuf
                    {$endif};
     
       { Cursor location, 0-based }
       Cursor    : TPoint = (0, 0); attribute (name = 'crt_Cursor');
     
     procedure InitWinCRT; attribute (name = 'crt_InitWinCRT');
     
     { Halts the program }
     procedure DoneWinCRT; attribute (noreturn, name = 'crt_DoneWinCRT');
     
     procedure WriteBuf (Buffer: PChar; Count: SizeType); attribute (name
       = 'crt_WriteBuf');
     
     function  ReadBuf (Buffer: PChar; Count: SizeType): SizeType;
       attribute (name = 'crt_ReadBuf');
     
     { 0-based coordinates! }
     procedure CursorTo (x, y: Integer); attribute (name
       = 'crt_CursorTo');
     
     { Dummy }
     procedure ScrollTo (x, y: Integer); attribute (name
       = 'crt_ScrollTo');
     
     { Dummy }
     procedure TrackCursor; attribute (name = 'crt_TrackCursor');
     


Next: , Previous: CRT, Up: GPC Units

6.15.2 BP compatibility: Dos

The following listing contains the interface of the Dos unit.

This is a portable implementation of most routines from BP's `Dos' unit. A few routines that are Dos – or even IA32 real mode – specific, are only available if `__BP_UNPORTABLE_ROUTINES__' is defined, BP Incompatibilities.

The same functionality and much more is available in the Run Time System, Run Time System. In some cases, the RTS routines have the same interface as the routines in this unit (e.g. `GetEnv', `FSplit', `FExpand', `FSearch'), in other cases, they have different names and/or easier and less limiting interfaces (e.g. `ReadDir' etc. vs. `FindFirst' etc.), and are often more efficient.

Therefore, using this unit is not recommended in newly written programs.

     { Portable BP compatible Dos unit
     
       This unit supports most of the routines and declarations of BP's
       Dos unit.
     
       Notes:
     
       - The procedures Keep, GetIntVec, SetIntVec are not supported
         since they make only sense for Dos real-mode programs (and GPC
         compiled programs do not run in real-mode, even on IA32 under
         Dos). The procedures Intr and MsDos are only supported under
         DJGPP if `__BP_UNPORTABLE_ROUTINES__' is defined (with the
         `-D__BP_UNPORTABLE_ROUTINES__' option). A few other routines are
         also only supported with this define, but on all platforms (but
         they are crude hacks, that's why they are not supported without
         this define).
     
       - The internal structure of file variables (FileRec and TextRec)
         is different in GPC. However, as far as TFDDs are concerned,
         there are other ways to achieve the same in GPC, see the GPC
         unit.
     
       Copyright (C) 1998-2006 Free Software Foundation, Inc.
     
       Authors: Frank Heckenbach <frank@pascal.gnu.de>
                Prof. Abimbola A. Olowofoyeku <African_Chief@bigfoot.com>
     
       This file is part of GNU Pascal.
     
       GNU Pascal is free software; you can redistribute it and/or modify
       it under the terms of the GNU General Public License as published
       by the Free Software Foundation; either version 2, or (at your
       option) any later version.
     
       GNU Pascal is distributed in the hope that it will be useful, but
       WITHOUT ANY WARRANTY; without even the implied warranty of
       MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
       General Public License for more details.
     
       You should have received a copy of the GNU General Public License
       along with GNU Pascal; see the file COPYING. If not, write to the
       Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA
       02111-1307, USA.
     
       As a special exception, if you link this file with files compiled
       with a GNU compiler to produce an executable, this does not cause
       the resulting executable to be covered by the GNU General Public
       License. This exception does not however invalidate any other
       reasons why the executable file might be covered by the GNU
       General Public License. }
     
     {$gnu-pascal,I-,maximum-field-alignment 0}
     {$if __GPC_RELEASE__ < 20030412}
     {$error This unit requires GPC release 20030412 or newer.}
     {$endif}
     
     module Dos;
     
     { GPC and this unit use `AnyFile' for different meanings. Export
       renaming helps us to avoid a conflict here. If you use both units,
       the meaning of the latter one will be effective, but you always
       get the built-in meaning by using `GPC_AnyFile'. }
     export Dos = all (DosAnyFile => AnyFile, FSearch, FExpand, FSplit,
       GetEnv);
     
     import GPC (MaxLongInt => GPC_Orig_MaxLongInt); System;
     
     type
       GPC_AnyFile = AnyFile;
       Byte8 = Cardinal attribute (Size = 8);
       Word16 = Cardinal attribute (Size = 16);
       Word32 = Cardinal attribute (Size = 32);
       TDosAttr = Word;
     
     const
       { File attribute constants }
       ReadOnly   = $01;
       Hidden     = $02;  { set for dot files except '.' and '..' }
       SysFile    = $04;  { not supported }
       VolumeID   = $08;  { not supported }
       Directory  = $10;
       Archive    = $20;  { means: not executable }
       DosAnyFile = $3f;
     
       { Flag bit masks -- only used by the unportable Dos routines }
       FCarry     = 1;
       FParity    = 4;
       FAuxiliary = $10;
       FZero      = $40;
       FSign      = $80;
       FOverflow  = $800;
     
       { DosError codes }
       DosError_FileNotFound = 2;
       DosError_PathNotFound = 3;
       DosError_AccessDenied = 5;
       DosError_InvalidMem   = 9;
       DosErorr_InvalidEnv   = 10;
       DosError_NoMoreFiles  = 18;
       DosError_IOError      = 29;
       DosError_ReadFault    = 30;
     
     type
       { String types. Not used in this unit, but declared for
         compatibility. }
       ComStr  = String [127];  { Command line string }
       PathStr = String [79];   { File pathname string }
       DirStr  = String [67];   { Drive and directory string }
       NameStr = String [8];    { File name string }
       ExtStr  = String [4];    { File extension string }
     
       TextBuf = array [0 .. 127] of Char;
     
       { Search record used by FindFirst and FindNext }
       SearchRecFill = packed array [1 .. 21] of Byte8;
       SearchRec = record
         Fill: SearchRecFill;
         Attr: Byte8;
         Time,
         Size: LongInt;
         Name: {$ifdef __BP_TYPE_SIZES__}
               String [12]
               {$else}
               TString
               {$endif}
       end;
     
       { Date and time record used by PackTime and UnpackTime }
       DateTime = record
         Year, Month, Day, Hour, Min, Sec: Word
       end;
     
       { 8086 CPU registers -- only used by the unportable Dos routines }
       Registers = record
       case Boolean of
         False: (ax, bx, cx, dx, bp, si, di, ds, es, Flags: Word16);
         True : (al, ah, bl, bh, cl, ch, dl, dh: Byte8)
       end;
     
     var
       { Error status variable }
       DosError: Integer = 0;
     
     procedure GetDate (var Year, Month, Day, DayOfWeek: Word);
     procedure GetTime (var Hour, Minute, Second, Sec100: Word);
     procedure GetCBreak (var BreakOn: Boolean);
     procedure SetCBreak (BreakOn: Boolean);
     { GetVerify and SetVerify are dummies except for DJGPP (in the
       assumption that any real OS knows by itself when and how to verify
       its disks). }
     procedure GetVerify (var VerifyOn: Boolean);
     procedure SetVerify (VerifyOn: Boolean);
     function  DiskFree (Drive: Byte): LongInt;
     function  DiskSize (Drive: Byte): LongInt;
     procedure GetFAttr (var f: GPC_AnyFile; var Attr: TDosAttr);
     procedure SetFAttr (var f: GPC_AnyFile; Attr: TDosAttr);
     procedure GetFTime (var f: GPC_AnyFile; var MTime: LongInt);
     procedure SetFTime (var f: GPC_AnyFile; MTime: LongInt);
     
     { FindFirst and FindNext are quite inefficient since they emulate
       all the brain-dead Dos stuff. If at all possible, the standard
       routines OpenDir, ReadDir and CloseDir (in the GPC unit) should be
       used instead. }
     procedure FindFirst (const Path: String; Attr: TDosAttr; var SR:
       SearchRec);
     procedure FindNext  (var SR: SearchRec);
     
     procedure FindClose (var SR: SearchRec);
     procedure UnpackTime (p: LongInt; var t: DateTime);
     procedure PackTime (const t: DateTime; var p: LongInt);
     function  EnvCount: Integer;
     function  EnvStr (EnvIndex: Integer): TString;
     procedure SwapVectors;
     { Exec executes a process via Execute, so RestoreTerminal is called
       with the argument True before and False after executing the
       process. }
     procedure Exec (const Path, Params: String);
     function  DosExitCode: Word;
     
     { Unportable Dos-only routines and declarations }
     
     {$ifdef __BP_UNPORTABLE_ROUTINES__}
     {$ifdef __GO32__}
     { These are unportable Dos-only declarations and routines, since
       interrupts are Dos and CPU specific (and have no place in a
       high-level program, anyway). }
     procedure Intr (IntNo: Byte; var Regs: Registers);
     procedure MsDos (var Regs: Registers);
     {$endif}
     
     { Though probably all non-Dos systems have versions numbers as well,
       returning them here would usually not do what is expected, e.g.
       testing if certain Dos features are present by comparing the
       version number. Therefore, this routine always returns 7 (i.e.,
       version 7.0) on non-Dos systems, in the assumption that any real
       OS has at least the features of Dos 7. }
     function  DosVersion: Word;
     
     { Changing the system date and time is a system administration task,
       not allowed to a normal process. On non-Dos systems, these
       routines emulate the changed date/time, but only for GetTime and
       GetDate (not the RTS date/time routines), and only for this
       process, not for child processes or even the parent process or
       system-wide. }
     procedure SetDate (Year, Month, Day: Word);
     procedure SetTime (Hour, Minute, Second, Sec100: Word);
     {$endif}
     


Next: , Previous: Dos, Up: GPC Units

6.15.3 Overcome some differences between Dos and Unix

The following listing contains the interface of the DosUnix unit.

This unit is there to overcome some of those differences between Dos and Unix systems that are not automatically hidden by GPC and the Run Time System. Currently features translation of bash style input/output redirections (`foo 2>&1') into `redir' calls for DJGPP (`redir -eo foo') and a way to read files with Dos CR/LF pairs on any system.

When necessary, new features will be added to the unit in future releases.

     { Some routines to support writing programs portable between Dos and
       Unix. Perhaps it would be a good idea not to put features to make
       Dos programs Unix-compatible (shell redirections) and vice versa
       (reading Dos files from Unix) together into one unit, but rather
       into two units, DosCompat and UnixCompat or so -- let's wait and
       see, perhaps when more routines suited for this/these unit(s) will
       be found, the design will become clearer ...
     
       Copyright (C) 1998-2006 Free Software Foundation, Inc.
     
       Author: Frank Heckenbach <frank@pascal.gnu.de>
     
       This file is part of GNU Pascal.
     
       GNU Pascal is free software; you can redistribute it and/or modify
       it under the terms of the GNU General Public License as published
       by the Free Software Foundation; either version 2, or (at your
       option) any later version.
     
       GNU Pascal is distributed in the hope that it will be useful, but
       WITHOUT ANY WARRANTY; without even the implied warranty of
       MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
       General Public License for more details.
     
       You should have received a copy of the GNU General Public License
       along with GNU Pascal; see the file COPYING. If not, write to the
       Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA
       02111-1307, USA.
     
       As a special exception, if you link this file with files compiled
       with a GNU compiler to produce an executable, this does not cause
       the resulting executable to be covered by the GNU General Public
       License. This exception does not however invalidate any other
       reasons why the executable file might be covered by the GNU
       General Public License. }
     
     {$gnu-pascal,I-}
     {$if __GPC_RELEASE__ < 20030412}
     {$error This unit requires GPC release 20030412 or newer.}
     {$endif}
     
     unit DosUnix;
     
     interface
     
     uses GPC;
     
     { This function is meant to be used when you want to invoke a system
       shell command (e.g. via Execute or Exec from the Dos unit) and
       want to specify input/output redirections for the command invoked.
       It caters for the different syntax between DJGPP (with the `redir'
       utility) and other systems.
     
       To use it, code your redirections in bash style (see the table
       below) in your command line string, pass this string to this
       function, and the function's result to Execute or the other
       routines.
     
       The function translates the following bash style redirections
       (characters in brackets are optional) into a redir call under Dos
       systems except EMX, and leave them unchanged under other systems.
       Note: `redir' comes with DJGPP, but it should be possible to
       install it on other Dos systems as well. OS/2's shell, however,
       supports bash style redirections, I was told, so we don't
       translate on EMX.
     
       [0]<     file      redirect standard input from file
       [1]>[|]  file      redirect standard output to file
       [1]>>    file      append standard output to file
       [1]>&2             redirect standard output to standard error
       2>[|]    file      redirect standard error to file
       2>>      file      append standard error to file
       2>&1               redirect standard error to standard output
       &> file            redirect both standard output and standard
                          error to file }
     function  TranslateRedirections (const Command: String) = s:
       TString;
     
     { Under Unix, translates CR/LF pairs to single LF characters when
       reading from f, and back when writing to f. Under Dos, does
       nothing because the run time system alrady does this job. In the
       result, you can read both Dos and Unix files, and files written
       will be Dos. }
     procedure AssignDos (var f: AnyFile; const FileName: String);
     
     { Translates a character from the "OEM" charset used under Dos to
       the ISO-8859-1 (Latin1) character set. }
     function  OEM2Latin1 (ch: Char): Char;
     function  OEM2Latin1Str (const s: String) = r: TString;
     
     { Translates a character from the ISO-8859-1 (Latin1) character set
       to the "OEM" charset used under Dos. }
     function  Latin12OEM (ch: Char): Char;
     function  Latin12OEMStr (const s: String) = r: TString;
     


Next: , Previous: DosUnix, Up: GPC Units

6.15.4 Higher level file and directory handling

The following listing contains the interface of the FileUtils unit.

This unit provides some routines for file and directory handling on a higher level than those provided by the RTS.

     { Some routines for file and directory handling on a higher level
       than those provided by the RTS.
     
       Copyright (C) 2000-2006 Free Software Foundation, Inc.
     
       Author: Frank Heckenbach <frank@pascal.gnu.de>
     
       This file is part of GNU Pascal.
     
       GNU Pascal is free software; you can redistribute it and/or modify
       it under the terms of the GNU General Public License as published
       by the Free Software Foundation; either version 2, or (at your
       option) any later version.
     
       GNU Pascal is distributed in the hope that it will be useful, but
       WITHOUT ANY WARRANTY; without even the implied warranty of
       MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
       General Public License for more details.
     
       You should have received a copy of the GNU General Public License
       along with GNU Pascal; see the file COPYING. If not, write to the
       Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA
       02111-1307, USA.
     
       As a special exception, if you link this file with files compiled
       with a GNU compiler to produce an executable, this does not cause
       the resulting executable to be covered by the GNU General Public
       License. This exception does not however invalidate any other
       reasons why the executable file might be covered by the GNU
       General Public License. }
     
     {$gnu-pascal,I-}
     {$if __GPC_RELEASE__ < 20030412}
     {$error This unit requires GPC release 20030412 or newer.}
     {$endif}
     
     unit FileUtils;
     
     interface
     
     uses GPC;
     
     type
       TStringProc = procedure (const s: String);
     
     { Finds all files matching the given Mask in the given Directory and
       all subdirectories of it. The matching is done using all wildcards
       and brace expansion, like MultiFileNameMatch does. For each file
       found, FileAction is executed. For each directory found (including
       `.' and `..' if they match the Mask!), DirAction is executed. If
       MainDirFirst is True, this happens before processing the files in
       the directory and below, otherwise afterwards. (The former is
       useful, e.g., if this is used to copy a directory tree and
       DirAction does a MkDir, while the latter behaviour is required
       when removing a directory tree and DirAction does a RmDir.) Both
       FileAction and DirAction can be nil in which case nothing is done
       for files or directories found, respectively. (If DirAction is
       nil, the value of DirsFirst does not matter.) Of course,
       FileAction and DirAction may also be identical. The procedure
       leaves InOutRes set in case of any error. If FileAction or
       DirAction return with InOutRes set, FindFiles recognizes this and
       returns immediately. }
     procedure FindFiles (const Directory, Mask: String; MainDirFirst:
       Boolean;
                          FileAction, DirAction: TStringProc); attribute
       (iocritical);
     
     { Creates the directory given by Path and all directories in between
       that are necessary. Does not report an error if the directory
       already exists, but, of course, if it cannot be created because of
       missing permissions or because Path already exists as a file. }
     procedure MkDirs (const Path: String); attribute (iocritical);
     
     { Removes Path if empty as well as any empty parent directories.
       Does not report an error if the directory is not empty. }
     procedure RmDirs (const Path: String); attribute (iocritical);
     
     { Copies the file Source to Dest, overwriting Dest if it exists and
       can be written to. Returns any errors in IOResult. If Mode >= 0,
       it will change the permissions of Dest to Mode immediately after
       creating it and before writing any data to it. That's useful,
       e.g., if Dest is not meant to be world-readable, because if you'd
       do a ChMod after FileCopy, you might leave the data readable
       (depending on the umask) during the copying. If Mode < 0, Dest
       will be set to the same permissions Source has. In any case, Dest
       will be set to the modification time of Source after copying. On
       any error, the destination file is erased. This is to avoid
       leaving partial files in case of full file systems (one of the
       most common reasons for errors). }
     procedure FileCopy (const Source, Dest: String; Mode: Integer);
       attribute (iocritical);
     
     { Creates a backup of FileName in the directory BackupDirectory or,
       if BackupDirectory is empty, in the directory of FileName. Errors
       are returned in IOResult (and on any error, no partial backup file
       is left), but if FileName does not exist, this does *not* count as
       an error (i.e., BackupFile will just return without setting
       IOResult then). If OnlyUserReadable is True, the backup file will
       be given only user-read permissions, nothing else.
     
       The name chosen for the backup depends on the Simple and Short
       parameters. The short names will fit into 8+3 characters (whenever
       possible), while the long ones conform to the conventions used by
       most GNU tools. If Simple is True, a simple backup file name will
       be used, and previous backups under the same name will be
       overwritten (if possible). Otherwise, backups will be numbered,
       where the number is chosen to be larger than all existing backups,
       so it will be unique and increasing in chronological order. In
       particular:
     
       Simple  Short  Backup name
       True    True   Base name of FileName plus '.bak'
       False   True   Base name of FileName plus '.b' plus a number
       True    False  Base name plus extension of FileName plus '~'
       False   False  Base name plus extension of FileName plus '.~', a
                      number and '~' }
     procedure BackupFile (const FileName, BackupDirectory: String;
       Simple, Short, OnlyUserReadable: Boolean); attribute (iocritical);
     


Next: , Previous: FileUtils, Up: GPC Units

6.15.5 Arithmetic with unlimited size and precision

The following listing contains the interface of the GMP unit.

This unit provides an interface to the GNU Multiprecision Library to perform arithmetic on integer, rational and real numbers of unlimited size and precision.

To use this unit, you will need the `gmp' library which can be found in http://www.gnu-pascal.de/libs/.

     { Definitions for GNU multiple precision functions: arithmetic with
       integer, rational and real numbers of arbitrary size and
       precision.
     
       Translation of the C header (gmp.h) of the GMP library. Tested
       with GMP 3.x and 4.x.
     
       To use the GMP unit, you will need the GMP library which can be
       found in http://www.gnu-pascal.de/libs/
     
       Copyright (C) 1998-2006 Free Software Foundation, Inc.
     
       Author: Frank Heckenbach <frank@pascal.gnu.de>
     
       This file is part of GNU Pascal.
     
       GNU Pascal is free software; you can redistribute it and/or modify
       it under the terms of the GNU General Public License as published
       by the Free Software Foundation; either version 2, or (at your
       option) any later version.
     
       GNU Pascal is distributed in the hope that it will be useful, but
       WITHOUT ANY WARRANTY; without even the implied warranty of
       MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
       General Public License for more details.
     
       You should have received a copy of the GNU General Public License
       along with GNU Pascal; see the file COPYING. If not, write to the
       Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA
       02111-1307, USA.
     
       As a special exception, if you link this file with files compiled
       with a GNU compiler to produce an executable, this does not cause
       the resulting executable to be covered by the GNU General Public
       License. This exception does not however invalidate any other
       reasons why the executable file might be covered by the GNU
       General Public License.
     
       Please also note the license of the GMP library. }
     
     {$gnu-pascal,I-}
     {$if __GPC_RELEASE__ < 20030303}
     {$error This unit requires GPC release 20030303 or newer.}
     {$endif}
     {$nested-comments}
     
     { If HAVE_GMP4 is set (the default unless HAVE_GMP3 is set, some
       interface changes made in GMP 4 are taken into account.
       I.e., if this is set wrong, programs might fail. However, this
       only affects a few routines related to random numbers. }
     {$if not defined (HAVE_GMP3)}
     {$define HAVE_GMP4}
     {$endif}
     
     {$undef GMP}  { in case it's set by the user }
     unit GMP;
     
     interface
     
     uses GPC;
     
     {$if defined (__mips) and defined (_ABIN32) and defined (HAVE_GMP3)}
     { Force the use of 64-bit limbs for all 64-bit MIPS CPUs if ABI
       permits. }
     {$define _LONG_LONG_LIMB}
     {$endif}
     
     type
       {$ifdef _SHORT_LIMB}
       mp_limb_t        = CCardinal;
       mp_limb_signed_t = CInteger;
       {$elif defined (_LONG_LONG_LIMB)}
       mp_limb_t        = LongCard;
       mp_limb_signed_t = LongInt;
       {$else}
       mp_limb_t        = MedCard;
       mp_limb_signed_t = MedInt;
       {$endif}
     
       mp_ptr           = ^mp_limb_t;
     
       {$if defined (_CRAY) and not defined (_CRAYMPP)}
       mp_size_t        = CInteger;
       mp_exp_t         = CInteger;
       {$else}
       mp_size_t        = MedInt;
       mp_exp_t         = MedInt;
       {$endif}
     
       mpz_t = record
         mp_alloc,
         mp_size: CInteger;
         mp_d:    mp_ptr
       end;
     
       mpz_array_ptr = ^mpz_array;
       mpz_array = array [0 .. MaxVarSize div SizeOf (mpz_t) - 1] of
       mpz_t;
     
       mpq_t = record
         mp_num,
         mp_den: mpz_t
       end;
     
       mpf_t = record
         mp_prec,
         mp_size: CInteger;
         mp_exp:  mp_exp_t;
         mp_d:    mp_ptr
       end;
     
       TAllocFunction    = function (Size: SizeType): Pointer;
       TReAllocFunction  = function (var Dest: Pointer; OldSize, NewSize:
       SizeType): Pointer;
       TDeAllocProcedure = procedure (Src: Pointer; Size: SizeType);
     
     var
       mp_bits_per_limb: CInteger; attribute (const); external
       name '__gmp_bits_per_limb';
     
     procedure mp_set_memory_functions (AllocFunction: TAllocFunction;
                                        ReAllocFunction:
       TReAllocFunction;
                                        DeAllocProcedure:
       TDeAllocProcedure); external name '__gmp_set_memory_functions';
     
     { Integer (i.e. Z) routines }
     
     procedure mpz_init             (var Dest: mpz_t); external
       name '__gmpz_init';
     procedure mpz_clear            (var Dest: mpz_t); external
       name '__gmpz_clear';
     function  mpz_realloc          (var Dest: mpz_t; NewAlloc:
       mp_size_t): Pointer; external name '__gmpz_realloc';
     procedure mpz_array_init       (Dest: mpz_array_ptr; ArraySize,
       FixedNumBits: mp_size_t); external name '__gmpz_array_init';
     
     procedure mpz_set              (var Dest: mpz_t; protected var Src:
       mpz_t); external name '__gmpz_set';
     procedure mpz_set_ui           (var Dest: mpz_t; Src: MedCard);
       external name '__gmpz_set_ui';
     procedure mpz_set_si           (var Dest: mpz_t; Src: MedInt);
       external name '__gmpz_set_si';
     procedure mpz_set_d            (var Dest: mpz_t; Src: Real);
       external name '__gmpz_set_d';
     procedure mpz_set_q            (var Dest: mpz_t; Src: mpq_t);
       external name '__gmpz_set_q';
     procedure mpz_set_f            (var Dest: mpz_t; Src: mpf_t);
       external name '__gmpz_set_f';
     function  mpz_set_str          (var Dest: mpz_t; Src: CString; Base:
       CInteger): CInteger; external name '__gmpz_set_str';
     
     procedure mpz_init_set         (var Dest: mpz_t; protected var Src:
       mpz_t); external name '__gmpz_init_set';
     procedure mpz_init_set_ui      (var Dest: mpz_t; Src: MedCard);
       external name '__gmpz_init_set_ui';
     procedure mpz_init_set_si      (var Dest: mpz_t; Src: MedInt);
       external name '__gmpz_init_set_si';
     procedure mpz_init_set_d       (var Dest: mpz_t; Src: Real);
       external name '__gmpz_init_set_d';
     function  mpz_init_set_str     (var Dest: mpz_t; Src: CString; Base:
       CInteger): CInteger; external name '__gmpz_init_set_str';
     
     function  mpz_get_ui           (protected var Src: mpz_t): MedCard;
       external name '__gmpz_get_ui';
     function  mpz_get_si           (protected var Src: mpz_t): MedInt;
       external name '__gmpz_get_si';
     function  mpz_get_d            (protected var Src: mpz_t): Real;
       external name '__gmpz_get_d';
     { Pass nil for Dest to let the function allocate memory for it }
     function  mpz_get_str          (Dest: CString; Base: CInteger;
       protected var Src: mpz_t): CString; external
       name '__gmpz_get_str';
     
     procedure mpz_add              (var Dest: mpz_t; protected var Src1,
       Src2: mpz_t); external name '__gmpz_add';
     procedure mpz_add_ui           (var Dest: mpz_t; protected var Src1:
       mpz_t; Src2: MedCard); external name '__gmpz_add_ui';
     procedure mpz_sub              (var Dest: mpz_t; protected var Src1,
       Src2: mpz_t); external name '__gmpz_sub';
     procedure mpz_sub_ui           (var Dest: mpz_t; protected var Src1:
       mpz_t; Src2: MedCard); external name '__gmpz_sub_ui';
     procedure mpz_mul              (var Dest: mpz_t; protected var Src1,
       Src2: mpz_t); external name '__gmpz_mul';
     procedure mpz_mul_ui           (var Dest: mpz_t; protected var Src1:
       mpz_t; Src2: MedCard); external name '__gmpz_mul_ui';
     procedure mpz_mul_2exp         (var Dest: mpz_t; protected var Src1:
       mpz_t; Src2: MedCard); external name '__gmpz_mul_2exp';
     procedure mpz_neg              (var Dest: mpz_t; protected var Src:
       mpz_t); external name '__gmpz_neg';
     procedure mpz_abs              (var Dest: mpz_t; protected var Src:
       mpz_t); external name '__gmpz_abs';
     procedure mpz_fac_ui           (var Dest: mpz_t; Src: MedCard);
       external name '__gmpz_fac_ui';
     
     procedure mpz_tdiv_q           (var Dest: mpz_t; protected var Src1,
       Src2: mpz_t); external name '__gmpz_tdiv_q';
     procedure mpz_tdiv_q_ui        (var Dest: mpz_t; protected var Src1:
       mpz_t; Src2: MedCard); external name '__gmpz_tdiv_q_ui';
     procedure mpz_tdiv_r           (var Dest: mpz_t; protected var Src1,
       Src2: mpz_t); external name '__gmpz_tdiv_r';
     procedure mpz_tdiv_r_ui        (var Dest: mpz_t; protected var Src1:
       mpz_t; Src2: MedCard); external name '__gmpz_tdiv_r_ui';
     procedure mpz_tdiv_qr          (var DestQ, DestR: mpz_t; protected
       var Src1, Src2: mpz_t); external name '__gmpz_tdiv_qr';
     procedure mpz_tdiv_qr_ui       (var DestQ, DestR: mpz_t; protected
       var Src1: mpz_t; Src2: MedCard); external
       name '__gmpz_tdiv_qr_ui';
     
     procedure mpz_fdiv_q           (var Dest: mpz_t; protected var Src1,
       Src2: mpz_t); external name '__gmpz_fdiv_q';
     function  mpz_fdiv_q_ui        (var Dest: mpz_t; protected var Src1:
       mpz_t; Src2: MedCard): MedCard; external name '__gmpz_fdiv_q_ui';
     procedure mpz_fdiv_r           (var Dest: mpz_t; protected var Src1,
       Src2: mpz_t); external name '__gmpz_fdiv_r';
     function  mpz_fdiv_r_ui        (var Dest: mpz_t; protected var Src1:
       mpz_t; Src2: MedCard): MedCard; external name '__gmpz_fdiv_r_ui';
     procedure mpz_fdiv_qr          (var DestQ, DestR: mpz_t; protected
       var Src1, Src2: mpz_t); external name '__gmpz_fdiv_qr';
     function  mpz_fdiv_qr_ui       (var DestQ, DestR: mpz_t; protected
       var Src1: mpz_t; Src2: MedCard): MedCard; external
       name '__gmpz_fdiv_qr_ui';
     function  mpz_fdiv_ui          (protected var Src1: mpz_t; Src2:
       MedCard): MedCard; external name '__gmpz_fdiv_ui';
     
     procedure mpz_cdiv_q           (var Dest: mpz_t; protected var Src1,
       Src2: mpz_t); external name '__gmpz_cdiv_q';
     function  mpz_cdiv_q_ui        (var Dest: mpz_t; protected var Src1:
       mpz_t; Src2: MedCard): MedCard; external name '__gmpz_cdiv_q_ui';
     procedure mpz_cdiv_r           (var Dest: mpz_t; protected var Src1,
       Src2: mpz_t); external name '__gmpz_cdiv_r';
     function  mpz_cdiv_r_ui        (var Dest: mpz_t; protected var Src1:
       mpz_t; Src2: MedCard): MedCard; external name '__gmpz_cdiv_r_ui';
     procedure mpz_cdiv_qr          (var DestQ, DestR: mpz_t; protected
       var Src1,Src2: mpz_t); external name '__gmpz_cdiv_qr';
     function  mpz_cdiv_qr_ui       (var DestQ, DestR: mpz_t; protected
       var Src1: mpz_t; Src2: MedCard): MedCard; external
       name '__gmpz_cdiv_qr_ui';
     function  mpz_cdiv_ui          (protected var Src1: mpz_t;
       Src2:MedCard): MedCard; external name '__gmpz_cdiv_ui';
     
     procedure mpz_mod              (var Dest: mpz_t; protected var
       Src1,Src2: mpz_t); external name '__gmpz_mod';
     procedure mpz_divexact         (var Dest: mpz_t; protected var
       Src1,Src2: mpz_t); external name '__gmpz_divexact';
     
     procedure mpz_tdiv_q_2exp      (var Dest: mpz_t; protected var Src1:
       mpz_t; Src2: MedCard); external name '__gmpz_tdiv_q_2exp';
     procedure mpz_tdiv_r_2exp      (var Dest: mpz_t; protected var Src1:
       mpz_t; Src2: MedCard); external name '__gmpz_tdiv_r_2exp';
     procedure mpz_fdiv_q_2exp      (var Dest: mpz_t; protected var Src1:
       mpz_t; Src2: MedCard); external name '__gmpz_fdiv_q_2exp';
     procedure mpz_fdiv_r_2exp      (var Dest: mpz_t; protected var Src1:
       mpz_t; Src2: MedCard); external name '__gmpz_fdiv_r_2exp';
     
     procedure mpz_powm             (var Dest: mpz_t; protected var Base,
       Exponent, Modulus: mpz_t); external name '__gmpz_powm';
     procedure mpz_powm_ui          (var Dest: mpz_t; protected var Base:
       mpz_t; Exponent: MedCard; protected var Modulus: mpz_t); external
       name '__gmpz_powm_ui';
     procedure mpz_pow_ui           (var Dest: mpz_t; protected var Base:
       mpz_t; Exponent: MedCard); external name '__gmpz_pow_ui';
     procedure mpz_ui_pow_ui        (var Dest: mpz_t; Base, Exponent:
       MedCard); external name '__gmpz_ui_pow_ui';
     
     procedure mpz_sqrt             (var Dest: mpz_t; protected var Src:
       mpz_t); external name '__gmpz_sqrt';
     procedure mpz_sqrtrem          (var Dest, DestR: mpz_t; protected
       var Src: mpz_t); external name '__gmpz_sqrtrem';
     function  mpz_perfect_square_p (protected var Src: mpz_t): CInteger;
       external name '__gmpz_perfect_square_p';
     
     function  mpz_probab_prime_p   (protected var Src: mpz_t;
       Repetitions: CInteger): CInteger; external
       name '__gmpz_probab_prime_p';
     procedure mpz_gcd              (var Dest: mpz_t; protected var Src1,
       Src2: mpz_t); external name '__gmpz_gcd';
     function  mpz_gcd_ui           (var Dest: mpz_t; protected var Src1:
       mpz_t; Src2: MedCard): MedCard; external name '__gmpz_gcd_ui';
     procedure mpz_gcdext           (var Dest, DestA, DestB: mpz_t;
       protected var SrcA, SrcB: mpz_t); external name '__gmpz_gcdext';
     function  mpz_invert           (var Dest: mpz_t; protected var Src,
       Modulus: mpz_t): CInteger; external name '__gmpz_invert';
     function  mpz_jacobi           (protected var Src1, Src2: mpz_t):
       CInteger; external name '__gmpz_jacobi';
     
     function  mpz_cmp              (protected var Src1, Src2: mpz_t):
       CInteger; external name '__gmpz_cmp';
     function  mpz_cmp_ui           (protected var Src1: mpz_t; Src2:
       MedCard): CInteger; external name '__gmpz_cmp_ui';
     function  mpz_cmp_si           (protected var Src1: mpz_t; Src2:
       MedInt): CInteger; external name '__gmpz_cmp_si';
     function  mpz_sgn              (protected var Src: mpz_t): CInteger;
       attribute (inline);
     
     procedure mpz_and              (var Dest: mpz_t; protected var Src1,
       Src2: mpz_t); external name '__gmpz_and';
     procedure mpz_ior              (var Dest: mpz_t; protected var Src1,
       Src2: mpz_t); external name '__gmpz_ior';
     procedure mpz_com              (var Dest: mpz_t; protected var Src:
       mpz_t); external name '__gmpz_com';
     function  mpz_popcount         (protected var Src: mpz_t): MedCard;
       external name '__gmpz_popcount';
     function  mpz_hamdist          (protected var Src1, Src2: mpz_t):
       MedCard; external name '__gmpz_hamdist';
     function  mpz_scan0            (protected var Src: mpz_t;
       StartingBit: MedCard): MedCard; external name '__gmpz_scan0';
     function  mpz_scan1            (protected var Src: mpz_t;
       StartingBit: MedCard): MedCard; external name '__gmpz_scan1';
     procedure mpz_setbit           (var Dest: mpz_t; BitIndex: MedCard);
       external name '__gmpz_setbit';
     procedure mpz_clrbit           (var Dest: mpz_t; BitIndex: MedCard);
       external name '__gmpz_clrbit';
     
     procedure mpz_random           (var Dest: mpz_t; MaxSize:
       mp_size_t); external name '__gmpz_random';
     procedure mpz_random2          (var Dest: mpz_t; MaxSize:
       mp_size_t); external name '__gmpz_random2';
     function  mpz_sizeinbase       (protected var Src: mpz_t; Base:
       CInteger): SizeType; external name '__gmpz_sizeinbase';
     
     { Rational (i.e. Q) routines }
     
     procedure mpq_canonicalize     (var Dest: mpq_t); external
       name '__gmpq_canonicalize';
     
     procedure mpq_init             (var Dest: mpq_t); external
       name '__gmpq_init';
     procedure mpq_clear            (var Dest: mpq_t); external
       name '__gmpq_clear';
     procedure mpq_set              (var Dest: mpq_t; protected var Src:
       mpq_t); external name '__gmpq_set';
     procedure mpq_set_z            (var Dest: mpq_t; protected var Src:
       mpz_t); external name '__gmpq_set_z';
     procedure mpq_set_ui           (var Dest: mpq_t; Nom, Den: MedCard);
       external name '__gmpq_set_ui';
     procedure mpq_set_si           (var Dest: mpq_t; Nom: MedInt; Den:
       MedCard); external name '__gmpq_set_si';
     
     procedure mpq_add              (var Dest: mpq_t; protected var Src1,
       Src2: mpq_t); external name '__gmpq_add';
     procedure mpq_sub              (var Dest: mpq_t; protected var Src1,
       Src2: mpq_t); external name '__gmpq_sub';
     procedure mpq_mul              (var Dest: mpq_t; protected var Src1,
       Src2: mpq_t); external name '__gmpq_mul';
     procedure mpq_div              (var Dest: mpq_t; protected var Src1,
       Src2: mpq_t); external name '__gmpq_div';
     procedure mpq_neg              (var Dest: mpq_t; protected var Src:
       mpq_t); external name '__gmpq_neg';
     procedure mpq_inv              (var Dest: mpq_t; protected var Src:
       mpq_t); external name '__gmpq_inv';
     
     function  mpq_cmp              (protected var Src1, Src2: mpq_t):
       CInteger; external name '__gmpq_cmp';
     function  mpq_cmp_ui           (protected var Src1: mpq_t; Nom2,
       Den2: MedCard): CInteger; external name '__gmpq_cmp_ui';
     function  mpq_sgn              (protected var Src: mpq_t): CInteger;
       attribute (inline);
     function  mpq_equal            (protected var Src1, Src2: mpq_t):
       CInteger; external name '__gmpq_equal';
     
     function  mpq_get_d            (protected var Src: mpq_t): Real;
       external name '__gmpq_get_d';
     procedure mpq_set_num          (var Dest: mpq_t; protected var Src:
       mpz_t); external name '__gmpq_set_num';
     procedure mpq_set_den          (var Dest: mpq_t; protected var Src:
       mpz_t); external name '__gmpq_set_den';
     procedure mpq_get_num          (var Dest: mpz_t; protected var Src:
       mpq_t); external name '__gmpq_get_num';
     procedure mpq_get_den          (var Dest: mpz_t; protected var Src:
       mpq_t); external name '__gmpq_get_den';
     
     { Floating point (i.e. R) routines }
     
     procedure mpf_set_default_prec (Precision: MedCard); external
       name '__gmpf_set_default_prec';
     procedure mpf_init             (var Dest: mpf_t); external
       name '__gmpf_init';
     procedure mpf_init2            (var Dest: mpf_t; Precision:
       MedCard); external name '__gmpf_init2';
     procedure mpf_clear            (var Dest: mpf_t); external
       name '__gmpf_clear';
     procedure mpf_set_prec         (var Dest: mpf_t; Precision:
       MedCard); external name '__gmpf_set_prec';
     function  mpf_get_prec         (protected var Src: mpf_t): MedCard;
       external name '__gmpf_get_prec';
     procedure mpf_set_prec_raw     (var Dest: mpf_t; Precision:
       MedCard); external name '__gmpf_set_prec_raw';
     
     procedure mpf_set              (var Dest: mpf_t; protected var Src:
       mpf_t); external name '__gmpf_set';
     procedure mpf_set_ui           (var Dest: mpf_t; Src: MedCard);
       external name '__gmpf_set_ui';
     procedure mpf_set_si           (var Dest: mpf_t; Src: MedInt);
       external name '__gmpf_set_si';
     procedure mpf_set_d            (var Dest: mpf_t; Src: Real);
       external name '__gmpf_set_d';
     procedure mpf_set_z            (var Dest: mpf_t; protected var Src:
       mpz_t); external name '__gmpf_set_z';
     procedure mpf_set_q            (var Dest: mpf_t; protected var Src:
       mpq_t); external name '__gmpf_set_q';
     function  mpf_set_str          (var Dest: mpf_t; Src: CString; Base:
       CInteger): CInteger; external name '__gmpf_set_str';
     
     procedure mpf_init_set         (var Dest: mpf_t; protected var Src:
       mpf_t); external name '__gmpf_init_set';
     procedure mpf_init_set_ui      (var Dest: mpf_t; Src: MedCard);
       external name '__gmpf_init_set_ui';
     procedure mpf_init_set_si      (var Dest: mpf_t; Src: MedInt);
       external name '__gmpf_init_set_si';
     procedure mpf_init_set_d       (var Dest: mpf_t; Src: Real);
       external name '__gmpf_init_set_d';
     function  mpf_init_set_str     (var Dest: mpf_t; Src: CString; Base:
       CInteger): CInteger; external name '__gmpf_init_set_str';
     
     function  mpf_get_d            (protected var Src: mpf_t): Real;
       external name '__gmpf_get_d';
     { Pass nil for Dest to let the function allocate memory for it }
     function  mpf_get_str          (Dest: CString; var Exponent:
       mp_exp_t; Base: CInteger;
                                     NumberOfDigits: SizeType; protected
       var Src: mpf_t): CString; external name '__gmpf_get_str';
     
     procedure mpf_add              (var Dest: mpf_t; protected var Src1,
       Src2: mpf_t); external name '__gmpf_add';
     procedure mpf_add_ui           (var Dest: mpf_t; protected var Src1:
       mpf_t; Src2: MedCard); external name '__gmpf_add_ui';
     procedure mpf_sub              (var Dest: mpf_t; protected var Src1,
       Src2: mpf_t); external name '__gmpf_sub';
     procedure mpf_ui_sub           (var Dest: mpf_t; Src1: MedCard;
       protected var Src2: mpf_t); external name '__gmpf_ui_sub';
     procedure mpf_sub_ui           (var Dest: mpf_t; protected var Src1:
       mpf_t; Src2: MedCard); external name '__gmpf_sub_ui';
     procedure mpf_mul              (var Dest: mpf_t; protected var Src1,
       Src2: mpf_t); external name '__gmpf_mul';
     procedure mpf_mul_ui           (var Dest: mpf_t; protected var Src1:
       mpf_t; Src2: MedCard); external name '__gmpf_mul_ui';
     procedure mpf_div              (var Dest: mpf_t; protected var Src1,
       Src2: mpf_t); external name '__gmpf_div';
     procedure mpf_ui_div           (var Dest: mpf_t; Src1: MedCard;
       protected var Src2: mpf_t); external name '__gmpf_ui_div';
     procedure mpf_div_ui           (var Dest: mpf_t; protected var Src1:
       mpf_t; Src2: MedCard); external name '__gmpf_div_ui';
     procedure mpf_sqrt             (var Dest: mpf_t; protected var Src:
       mpf_t); external name '__gmpf_sqrt';
     procedure mpf_sqrt_ui          (var Dest: mpf_t; Src: MedCard);
       external name '__gmpf_sqrt_ui';
     procedure mpf_neg              (var Dest: mpf_t; protected var Src:
       mpf_t); external name '__gmpf_neg';
     procedure mpf_abs              (var Dest: mpf_t; protected var Src:
       mpf_t); external name '__gmpf_abs';
     procedure mpf_mul_2exp         (var Dest: mpf_t; protected var Src1:
       mpf_t; Src2: MedCard); external name '__gmpf_mul_2exp';
     procedure mpf_div_2exp         (var Dest: mpf_t; protected var Src1:
       mpf_t; Src2: MedCard); external name '__gmpf_div_2exp';
     
     function  mpf_cmp              (protected var Src1, Src2: mpf_t):
       CInteger; external name '__gmpf_cmp';
     function  mpf_cmp_si           (protected var Src1: mpf_t; Src2:
       MedInt): CInteger; external name '__gmpf_cmp_si';
     function  mpf_cmp_ui           (protected var Src1: mpf_t; Src2:
       MedCard): CInteger; external name '__gmpf_cmp_ui';
     function  mpf_eq               (protected var Src1, Src2: mpf_t;
       NumberOfBits: MedCard): CInteger; external name '__gmpf_eq';
     procedure mpf_reldiff          (var Dest: mpf_t; protected var Src1,
       Src2: mpf_t); external name '__gmpf_reldiff';
     function  mpf_sgn              (protected var Src: mpf_t): CInteger;
       attribute (inline);
     
     procedure mpf_random2          (var Dest: mpf_t; MaxSize: mp_size_t;
       MaxExp: mp_exp_t); external name '__gmpf_random2';
     
     {$if False}  { @@ commented out because they use C file pointers }
     function  mpz_inp_str          (var Dest: mpz_t; Src: CFilePtr;
       Base: CInteger): SizeType; external name '__gmpz_inp_str';
     function  mpz_inp_raw          (var Dest: mpz_t; Src: CFilePtr):
       SizeType; external name '__gmpz_inp_raw';
     function  mpz_out_str          (Dest: CFilePtr; Base: CInteger;
       protected var Src: mpz_t): SizeType; external
       name '__gmpz_out_str';
     function  mpz_out_raw          (Dest: CFilePtr; protected var Src:
       mpz_t): SizeType ; external name '__gmpz_out_raw';
     { @@ mpf_out_str has a bug in GMP 2.0.2: it writes a spurious #0
       before the exponent for negative numbers }
     function  mpf_out_str          (Dest: CFilePtr; Base: CInteger;
       NumberOfDigits: SizeType; protected var Src: mpf_t): SizeType;
       external name '__gmpf_out_str';
     function  mpf_inp_str          (var Dest: mpf_t; Src: CFilePtr;
       Base: CInteger): SizeType; external name '__gmpf_inp_str';
     {$endif}
     
     { Available random number generation algorithms. }
     type
       gmp_randalg_t = (GMPRandAlgLC { Linear congruential. });
     
     const
       GMPRandAlgDefault = GMPRandAlgLC;
     
     { Linear congruential data struct. }
     type
       gmp_randata_lc = record
         a: mpz_t;  { Multiplier. }
         c: MedCard;  { Adder. }
         m: mpz_t;  { Modulus (valid only if M2Exp = 0). }
         M2Exp: MedCard;  { If <> 0, modulus is 2 ^ M2Exp. }
       end;
     
     type
       gmp_randstate_t = record
         Seed: mpz_t;  { Current seed. }
         Alg: gmp_randalg_t;  { Algorithm used. }
         AlgData: record  { Algorithm specific data. }
         case gmp_randalg_t of
           GMPRandAlgLC: (lc: ^gmp_randata_lc)  { Linear congruential. }
         end
       end;
     
     procedure gmp_randinit         (var State: gmp_randstate_t; Alg:
       gmp_randalg_t; ...); external name '__gmp_randinit';
     procedure gmp_randinit_lc      (var State: gmp_randstate_t; {$ifdef
       HAVE_GMP4} protected var {$endif} a: mpz_t; c: MedCard; {$ifdef
       HAVE_GMP4} protected var {$endif} m: mpz_t); external
       name '__gmp_randinit_lc';
     procedure gmp_randinit_lc_2exp (var State: gmp_randstate_t; {$ifdef
       HAVE_GMP4} protected var {$endif} a: mpz_t; c: MedCard; M2Exp:
       MedCard); external name '__gmp_randinit_lc_2exp';
     procedure gmp_randseed         (var State: gmp_randstate_t; Seed:
       mpz_t); external name '__gmp_randseed';
     procedure gmp_randseed_ui      (var State: gmp_randstate_t; Seed:
       MedCard); external name '__gmp_randseed_ui';
     procedure gmp_randclear        (var State: gmp_randstate_t);
       external name '__gmp_randclear';
     
     procedure mpz_addmul_ui        (var Dest: mpz_t; protected var Src1:
       mpz_t; Src2: MedCard); external name '__gmpz_addmul_ui';
     procedure mpz_bin_ui           (var Dest: mpz_t; protected var Src1:
       mpz_t; Src2: MedCard); external name '__gmpz_bin_ui';
     procedure mpz_bin_uiui         (var Dest: mpz_t; Src1, Src2:
       MedCard); external name '__gmpz_bin_uiui';
     function  mpz_cmpabs           (protected var Src1, Src2: mpz_t):
       CInteger; external name '__gmpz_cmpabs';
     function  mpz_cmpabs_ui        (protected var Src1: mpz_t; Src2:
       MedCard): CInteger; external name '__gmpz_cmpabs_ui';
     procedure mpz_dump             (protected var Src: mpz_t); external
       name '__gmpz_dump';
     procedure mpz_fib_ui           (var Dest: mpz_t; Src: MedCard);
       external name '__gmpz_fib_ui';
     function  mpz_fits_sint_p      (protected var Src: mpz_t): CInteger;
       external name '__gmpz_fits_sint_p';
     function  mpz_fits_slong_p     (protected var Src: mpz_t): CInteger;
       external name '__gmpz_fits_slong_p';
     function  mpz_fits_sshort_p    (protected var Src: mpz_t): CInteger;
       external name '__gmpz_fits_sshort_p';
     function  mpz_fits_uint_p      (protected var Src: mpz_t): CInteger;
       external name '__gmpz_fits_uint_p';
     function  mpz_fits_ulong_p     (protected var Src: mpz_t): CInteger;
       external name '__gmpz_fits_ulong_p';
     function  mpz_fits_ushort_p    (protected var Src: mpz_t): CInteger;
       external name '__gmpz_fits_ushort_p';
     procedure mpz_lcm              (var Dest: mpz_t; protected var Src1,
       Src2: mpz_t); external name '__gmpz_lcm';
     procedure mpz_nextprime        (var Dest: mpz_t; protected var Src:
       mpz_t); external name '__gmpz_nextprime';
     function  mpz_perfect_power_p  (protected var Src: mpz_t): CInteger;
       external name '__gmpz_perfect_power_p';
     function  mpz_remove           (var Dest: mpz_t; protected var Src1,
       Src2: mpz_t): MedCard; external name '__gmpz_remove';
     function  mpz_root             (var Dest: mpz_t; protected var Src:
       mpz_t; n: MedCard): CInteger; external name '__gmpz_root';
     procedure mpz_rrandomb         (var ROP: mpz_t; var State:
       gmp_randstate_t; n: MedCard); external name '__gmpz_rrandomb';
     procedure mpz_swap             (var v1, v2: mpz_t); external
       name '__gmpz_swap';
     function  mpz_tdiv_ui          (protected var Src1: mpz_t; Src2:
       MedCard): MedCard; external name '__gmpz_tdiv_ui';
     function  mpz_tstbit           (protected var Src1: mpz_t; Src2:
       MedCard): CInteger; external name '__gmpz_tstbit';
     procedure mpz_urandomb         ({$ifdef HAVE_GMP4} var {$endif} ROP:
       mpz_t; var State: gmp_randstate_t; n: MedCard); external
       name '__gmpz_urandomb';
     procedure mpz_urandomm         ({$ifdef HAVE_GMP4} var {$endif} ROP:
       mpz_t; var State: gmp_randstate_t; {$ifdef HAVE_GMP4} protected
       var {$endif} n: mpz_t); external name '__gmpz_urandomm';
     procedure mpz_xor              (var Dest: mpz_t; protected var Src1,
       Src2: mpz_t); external name '__gmpz_xor';
     
     procedure mpq_set_d            (var Dest: mpq_t; Src: Real);
       external name '__gmpq_set_d';
     
     procedure mpf_ceil             (var Dest: mpf_t; protected var Src:
       mpf_t); external name '__gmpf_ceil';
     procedure mpf_floor            (var Dest: mpf_t; protected var Src:
       mpf_t); external name '__gmpf_floor';
     {$ifdef HAVE_GMP4}
     function  mpf_get_si           (protected var Src: mpf_t): MedInt;
       external name '__gmpf_get_si';
     function  mpf_get_ui           (protected var Src: mpf_t): MedCard;
       external name '__gmpf_get_ui';
     function  mpf_get_d_2exp       (var Exp: MedInt; protected var Src:
       mpf_t): Real; external name '__gmpf_get_d_2exp';
     {$endif}
     procedure mpf_pow_ui           (var Dest: mpf_t; protected var Src1:
       mpf_t; Src2: MedCard); external name '__gmpf_pow_ui';
     procedure mpf_trunc            (var Dest: mpf_t; protected var Src:
       mpf_t); external name '__gmpf_trunc';
     procedure mpf_urandomb         (ROP: mpf_t; var State:
       gmp_randstate_t; n: MedCard); external name '__gmpf_urandomb';
     
     const
       GMPErrorNone = 0;
       GMPErrorUnsupportedArgument = 1;
       GMPErrorDivisionByZero = 2;
       GMPErrorSqrtOfNegative = 4;
       GMPErrorInvalidArgument = 8;
       GMPErrorAllocate = 16;
     
     var
       gmp_errno: CInteger; external name '__gmp_errno';
     
     { Extensions to the GMP library, implemented in this unit }
     
     procedure mpf_exp    (var Dest: mpf_t; protected var Src: mpf_t);
     procedure mpf_ln     (var Dest: mpf_t; protected var Src: mpf_t);
     procedure mpf_pow    (var Dest: mpf_t; protected var Src1, Src2:
       mpf_t);
     procedure mpf_sin    (var Dest: mpf_t; protected var Src: mpf_t);
     procedure mpf_cos    (var Dest: mpf_t; protected var Src: mpf_t);
     procedure mpf_arctan (var Dest: mpf_t; protected var Src: mpf_t);
     procedure mpf_pi     (var Dest: mpf_t);
     


Next: , Previous: GMP, Up: GPC Units

6.15.6 Turbo Power compatibility, etc.

The following listing contains the interface of the GPCUtil unit.

This unit provides some utility routines for compatibility to some units available for BP, like some Turbo Power units.

     { Some utility routines for compatibility to some units available
       for BP, like some `Turbo Power' units.
     
       @@NOTE - SOME OF THE ROUTINES IN THIS UNIT MAY NOT WORK CORRECTLY.
       TEST CAREFULLY AND USE WITH CARE!
     
       Copyright (C) 1998-2006 Free Software Foundation, Inc.
     
       Authors: Prof. Abimbola A. Olowofoyeku <African_Chief@bigfoot.com>
                Frank Heckenbach <frank@pascal.gnu.de>
     
       This file is part of GNU Pascal.
     
       GNU Pascal is free software; you can redistribute it and/or modify
       it under the terms of the GNU General Public License as published
       by the Free Software Foundation; either version 2, or (at your
       option) any later version.
     
       GNU Pascal is distributed in the hope that it will be useful, but
       WITHOUT ANY WARRANTY; without even the implied warranty of
       MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
       General Public License for more details.
     
       You should have received a copy of the GNU General Public License
       along with GNU Pascal; see the file COPYING. If not, write to the
       Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA
       02111-1307, USA.
     
       As a special exception, if you link this file with files compiled
       with a GNU compiler to produce an executable, this does not cause
       the resulting executable to be covered by the GNU General Public
       License. This exception does not however invalidate any other
       reasons why the executable file might be covered by the GNU
       General Public License. }
     
     {$gnu-pascal,I-}
     {$if __GPC_RELEASE__ < 20030412}
     {$error This unit requires GPC release 20030412 or newer.}
     {$endif}
     
     module GPCUtil;
     
     export GPCUtil = all
            (
             { Return the current working directory }
             GetCurrentDirectory => ThisDirectory,
     
             { Does a directory exist? }
             DirectoryExists => IsDirectory,
     
             { Does file name s exist? }
             FileExists => ExistFile,
     
             { Return just the directory path of Path. Returns
               DirSelf + DirSeparator if Path contains no directory. }
             DirFromPath => JustPathName,
     
             { Return just the file name part without extension of Path.
               Empty if Path contains no file name. }
             NameFromPath => JustFileName,
     
             { Return just the extension of Path. Empty if Path contains
               no extension. }
             ExtFromPath => JustExtension,
     
             { Return the full pathname of Path }
             FExpand => FullPathName,
     
             { Add a DirSeparator to the end of s if there is not
               already one. }
             ForceAddDirSeparator => AddBackSlash,
     
             { Return a string stripped of leading spaces }
             TrimLeftStr => TrimLead,
     
             { Return a string stripped of trailing spaces }
             TrimRightStr => TrimTrail,
     
             { Return a string stripped of leading and trailing spaces }
             TrimBothStr => Trim,
     
             { Convert a string to lowercase }
             LoCaseStr => StLoCase,
     
             { Convert a string to uppercase }
             UpCaseStr => StUpCase
            );
     
     import GPC;
     
     { Replace all occurences of OldC with NewC in s and return the
       result }
     function  ReplaceChar (const s: String; OldC, NewC: Char) = Res:
       TString;
     
     { Break a string into 2 parts, using Ch as a marker }
     function  BreakStr (const Src: String; var Dest1, Dest2: String; ch:
       Char): Boolean; attribute (ignorable);
     
     { Convert a CString to an Integer }
     function  PChar2Int (s: CString) = i: Integer;
     
     { Convert a CString to a LongInt }
     function  PChar2Long (s: CString) = i: LongInt;
     
     { Convert a CString to a Double }
     function  PChar2Double (s: CString) = x: Double;
     
     { Search for s as an executable in the path and return its location
       (full pathname) }
     function  PathLocate (const s: String): TString;
     
     { Copy file Src to Dest and return the number of bytes written }
     function  CopyFile (const Src, Dest: String; BufSize: Integer):
       LongInt; attribute (ignorable);
     
     { Copy file Src to Dest and return the number of bytes written;
       report the number of bytes written versus total size of the source
       file }
     function  CopyFileEx (const Src, Dest: String; BufSize: Integer;
       function Report (Reached, Total: LongInt): LongInt) = BytesCopied:
       LongInt; attribute (ignorable);
     
     { Turbo Power compatibility }
     
     { Execute the program prog. Dummy1 and Dummy2 are for compatibility
       only; they are ignored. }
     function  ExecDos (const Prog: String; Dummy1: Boolean; Dummy2:
       Pointer): Integer; attribute (ignorable);
     
     { Return whether Src exists in the path as an executable -- if so
       return its full location in Dest }
     function  ExistOnPath (const Src: String; var Dest: String) =
       Existing: Boolean;
     
     { Change the extension of s to Ext (do not include the dot!) }
     function  ForceExtension (const s, Ext: String) = Res: TString;
     
     { Convert Integer to PChar; uses NewCString to allocate memory for
       the result, so you must call StrDispose to free the memory later }
     function  Int2PChar (i: Integer): PChar;
     
     { Convert Integer to string }
     function  Int2Str (i: Integer) = s: TString;
     
     { Convert string to Integer }
     function  Str2Int (const s: String; var i: Integer): Boolean;
       attribute (ignorable);
     
     { Convert string to LongInt }
     function  Str2Long (const s: String; var i: LongInt): Boolean;
       attribute (ignorable);
     
     { Convert string to Double }
     function  Str2Real (const s: String; var i: Double): Boolean;
       attribute (ignorable);
     
     { Return a string right-padded to length Len with ch }
     function  PadCh (const s: String; ch: Char; Len: Integer) = Padded:
       TString;
     
     { Return a string right-padded to length Len with spaces }
     function  Pad (const s: String; Len: Integer): TString;
     
     { Return a string left-padded to length Len with ch }
     function  LeftPadCh (const s: String; ch: Char; Len: Byte) = Padded:
       TString;
     
     { Return a string left-padded to length Len with blanks }
     function  LeftPad (const s: String; Len: Integer): TString;
     
     { Uniform access to big memory blocks for GPC and BP. Of course, for
       programs that are meant only for GPC, you can use the usual
       New/Dispose routines. But for programs that should compile with
       GPC and BP, you can use the following routines for GPC. In the GPC
       unit for BP (gpc-bp.pas), you can find emulations for BP that try
       to provide access to as much memory as possible, despite the
       limitations of BP. The drawback is that this memory cannot be used
       freely, but only with the following moving routines. }
     
     type
       PBigMem = ^TBigMem;
       TBigMem (MaxNumber: SizeType) = record
         { Public fields }
         Number, BlockSize: SizeType;
         Mappable: Boolean;
         { Private fields }
         Pointers: array [1 .. Max (1, MaxNumber)] of ^Byte
       end;
     
     { Note: the number of blocks actually allocated may be smaller than
       WantedNumber. Check the Number field of the result. }
     function  AllocateBigMem (WantedNumber, aBlockSize: SizeType;
       WantMappable: Boolean) = p: PBigMem;
     procedure DisposeBigMem (p: PBigMem);
     procedure MoveToBigMem (var Source; p: PBigMem; BlockNumber:
       SizeType);
     procedure MoveFromBigMem (p: PBigMem; BlockNumber: SizeType; var
       Dest);
     { Maps a big memory block into normal addressable memory and returns
       its address. The memory must have been allocated with
       WantMappable = True. The mapping is only valid until the next
       MapBigMem call. }
     function  MapBigMem (p: PBigMem; BlockNumber: SizeType): Pointer;
     


Next: , Previous: GPCUtil, Up: GPC Units

6.15.7 Primitive heap checking

The following listing contains the interface of the HeapMon unit.

This unit provide a rather primitive means to watch the heap, i.e. check if all pointers that were allocated are released again. This is meant as a debugging help for avoiding memory leaks.

More extensive heap checking is provided by libraries like `efence' which can be used in GPC programs without special provisions.

     { A unit to watch the heap, i.e. check if all pointers that were
       allocated are released again. It is meant as a debugging help to
       detect memory leaks.
     
       Use it in the main program before all other units. When, at the
       end of the program, some pointers that were allocated, have not
       been released, the unit writes a report to StdErr or another file
       (see below). Only pointers allocated via the Pascal mechanisms
       (New, GetMem) are tracked, not pointers allocated with direct libc
       calls or from C code. After a runtime error, pointers are not
       checked.
     
       Note that many units and libraries allocate memory for their own
       purposes and don't always release it at the end. Therefore, the
       usefulness of this unit is rather limited.
     
       Copyright (C) 1998-2006 Free Software Foundation, Inc.
     
       Author: Frank Heckenbach <frank@pascal.gnu.de>
     
       This file is part of GNU Pascal.
     
       GNU Pascal is free software; you can redistribute it and/or modify
       it under the terms of the GNU General Public License as published
       by the Free Software Foundation; either version 2, or (at your
       option) any later version.
     
       GNU Pascal is distributed in the hope that it will be useful, but
       WITHOUT ANY WARRANTY; without even the implied warranty of
       MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
       General Public License for more details.
     
       You should have received a copy of the GNU General Public License
       along with GNU Pascal; see the file COPYING. If not, write to the
       Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA
       02111-1307, USA.
     
       As a special exception, if you link this file with files compiled
       with a GNU compiler to produce an executable, this does not cause
       the resulting executable to be covered by the GNU General Public
       License. This exception does not however invalidate any other
       reasons why the executable file might be covered by the GNU
       General Public License. }
     
     {$gnu-pascal,I-}
     {$if __GPC_RELEASE__ < 20030303}
     {$error This unit requires GPC release 20030303 or newer.}
     {$endif}
     
     unit HeapMon;
     
     interface
     
     uses GPC;
     
     { This unit is automatically activated when used. The following
       declarations are only needed for special purposes. }
     
     { The report generated at the end can be redirected to a certain
       file by pointing HeapMonOutput to it. If not set, the report will
       be printed to the error messages file given with `--gpc-rts'
       options if given, and StdErr otherwise. }
     var
       HeapMonOutput: ^Text = nil;
     
     { HeapMonReport can be used to print a report on non-released memory
       blocks at an arbitrary point during a program run to the file f.
       It is invoked automatically at the end, so usually you don't have
       to call it. Returns True if any non-released blocks were found,
       False otherwise. }
     function HeapMonReport (var f: Text; DoRestoreTerminal: Boolean) =
       Res: Boolean; attribute (ignorable);
     


Next: , Previous: HeapMon, Up: GPC Units

6.15.8 Internationalization

The following listing contains the interface of the Intl unit.

This unit provides national language support via locales and .mo files.

WARNING: The intl unit is NOT part of the gpc accompanying MirOS!

     { Welcome to the wonderful world of
       INTERNATIONALIZATION (i18n).
     
       This unit provides the powerful mechanism of national language
       support by accessing `.mo' files and locale information.
     
       It includes:
         locales (not xlocales) and libintl.
     
       See documentation for gettext (`info gettext') for details.
     
       Because GPC can deal with both CStrings and Pascal Strings, there
       is an interface for both types of arguments and function results
       with slightly different names.
     
       E.g. for Pascal strings:
     
         function GetText (const MsgId: String): TString;
     
       And the same as above, but with a C interface:
     
         function GetTextC (MsgId: CString): CString;
     
       `PLConv' in Pascal is very different from `struct lconv *' in C.
       Element names do not have underscores and have sometimes different
       sizes. The conversion is done automatically and has correct
       results.
     
       Furthermore, we have a tool similar to `xgettext' to extract all
       strings out of a Pascal source. It extracts the strings and writes
       a complete `.po' file to a file. See
       http://www.gnu-pascal.de/contrib/eike/
       The filename is pas2po-VERSION.tar.gz.
     
       Copyright (C) 2001-2006 Free Software Foundation, Inc.
     
       Author: Eike Lange <eike.lange@uni-essen.de>
     
       GNU Pascal is free software; you can redistribute it and/or modify
       it under the terms of the GNU Library General Public License as
       published by the Free Software Foundation, version 2.
     
       GNU Pascal is distributed in the hope that it will be useful, but
       WITHOUT ANY WARRANTY; without even the implied warranty of
       MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
       Library General Public License for more details.
     
       You should have received a copy of the GNU Library General Public
       License along with this library; see the file COPYING.LIB. If not,
       write to the Free Software Foundation, Inc., 59 Temple Place -
       Suite 330, Boston, MA 02111-1307, USA. }
     
     {$gnu-pascal,I-}
     {$if __GPC_RELEASE__ < 20030303}
     {$error This unit requires GPC release 20030303 or newer.}
     {$endif}
     
     unit Intl;
     
     interface
     
     uses GPC;
     
     type
       IntlString = String (16);
     
       { Pascal translation from OrigLConv in intlc.c }
       PLConv = ^TLConv;
       TLConv = record
         { Numeric (non-monetary) information. }
     
         { Decimal point character. }
         DecimalPoint: IntlString;
     
         { Thousands separator. }
         ThousandsSep: IntlString;
     
         { Each element is the number of digits in each group;
           elements with higher indices are farther left.
           An element with value CharMax means that no further grouping
           is done.
           An element with value Chr (0) means that the previous element
           is used for all groups farther left. }
         Grouping: IntlString;
     
         { Monetary information. }
     
         { First three chars are a currency symbol from ISO 4217.
           Fourth char is the separator.  Fifth char is Chr (0). }
         IntCurrSymbol: IntlString;
     
         { Local currency symbol. }
         CurrencySymbol: IntlString;
     
         { Decimal point character. }
         MonDecimalPoint: IntlString;
     
         { Thousands separator. }
         MonThousandsSep: IntlString;
     
         { Like `Grouping' element (above). }
         MonGrouping: IntlString;
     
         { Sign for positive values. }
         PositiveSign: IntlString;
     
         { Sign for negative values. }
         NegativeSign: IntlString;
     
         { Int'l fractional digits. }
         IntFracDigits: ByteInt;
     
         { Local fractional digits. }
         FracDigits: ByteInt;
     
         { 1 if CurrencySymbol precedes a positive value, 0 if it
           succeeds. }
         PCSPrecedes: ByteInt;
     
         { 1 iff a space separates CurrencySymbol from a positive
           value. }
         PSepBySpace: ByteInt;
     
         { 1 if CurrencySymbol precedes a negative value, 0 if it
           succeeds. }
         NCSPrecedes: ByteInt;
     
         { 1 iff a space separates CurrencySymbol from a negative
           value. }
         NSepBySpace: ByteInt;
     
         { Positive and negative sign positions:
           0 Parentheses surround the quantity and CurrencySymbol.
           1 The sign string precedes the quantity and CurrencySymbol.
           2 The sign string follows the quantity and CurrencySymbol.
           3 The sign string immediately precedes the CurrencySymbol.
           4 The sign string immediately follows the CurrencySymbol. }
         PSignPosn,
         NSignPosn: ByteInt;
       end;
     
     { Please do not assign anything to these identifiers! }
     var
       LC_CTYPE:    CInteger; external name '_p_LC_CTYPE';
       LC_NUMERIC:  CInteger; external name '_p_LC_NUMERIC';
       LC_TIME:     CInteger; external name '_p_LC_TIME';
       LC_COLLATE:  CInteger; external name '_p_LC_COLLATE';
       LC_MONETARY: CInteger; external name '_p_LC_MONETARY';
       LC_MESSAGES: CInteger; external name '_p_LC_MESSAGES';
       LC_ALL:      CInteger; external name '_p_LC_ALL';
       CharMax:     Char; external name '_p_CHAR_MAX';
     
     {@section Locales }
     
     { Set and/or return the current locale. }
     function SetLocale (Category: Integer; const Locale: String):
       TString; attribute (ignorable);
     
     { Set and/or return the current locale. Same as above, but returns
       a CString. }
     function SetLocaleC (Category: Integer; const Locale: String):
       CString; attribute (ignorable);
     
     { Return the numeric/monetary information for the current locale.
       The result is allocated from the heap. You can Dispose it when
       you don't need it anymore. }
     function LocaleConv: PLConv;
     
     {@section GetText }
     
     { Look up MsgId in the current default message catalog for the
       current LC_MESSAGES locale.  If not found, returns MsgId itself
       (the default text). }
     function GetText (const MsgId: String): TString;
     
     { Same as above, but with a C interface }
     function GetTextC (MsgId: CString): CString;
     
     { Look up MsgId in the DomainName message catalog for the current
       LC_MESSAGES locale. }
     function DGetText (const DomainName, MsgId: String): TString;
     
     { Same as above, but with a C interface }
     function DGetTextC (DomainName, MsgId: CString): CString;
     
     { Look up MsgId in the DomainName message catalog for the current
       Category locale. }
     function DCGetText (const DomainName, MsgId: String; Category:
       Integer): TString;
     
     { Same as above, but with a C interface }
     function DCGetTextC (DomainName, MsgId: CString; Category: Integer):
       CString;
     
     { Set the current default message catalog to DomainName.
       If DomainName is empty, reset to the default of `messages'. }
     function TextDomain (const DomainName: String): TString; attribute
       (ignorable);
     
     { Same as above, but with a C interface.
       If DomainName is nil, return the current default. }
     function TextDomainC (DomainName: CString): CString; attribute
       (ignorable);
     
     { Specify that the DomainName message catalog will be found
       in DirName rather than in the system locale data base. }
     function BindTextDomain (const DomainName, DirName: String):
       TString; attribute (ignorable);
     
     { Same as above, but with a C interface }
     function BindTextDomainC (DomainName, DirName: CString): CString;
       attribute (ignorable);
     


Next: , Previous: Intl, Up: GPC Units

6.15.9 `MD5' Message Digests

The following listing contains the interface of the MD5 unit.

This unit provides functions to compute `MD5' message digest of files or memory blocks, according to the definition of `MD5' in RFC 1321 from April 1992.

     { $MirOS: gcc/gcc/p/doc/generated/md5.texi,v 1.2 2009/12/27 16:26:58 tg Exp $
     
       Copyright (c) 2005
      	Free Software Foundation, Inc. <gpc@gnu.de>
       written by:
      	Thorsten "mirabilos" Glaser <tg@mirbsd.org>
      	Frank Heckenbach
     
       Licensee is hereby permitted to deal in this work without restric-
       tion, including unlimited rights to use, publicly perform, modify,
       merge, distribute, sell, give away or sublicence, provided all co-
       pyright notices above, these terms and the disclaimer are retained
       in all redistributions or reproduced in accompanying documentation
       or other materials provided with binary redistributions.
     
       Licensor offers the work "AS IS" and WITHOUT WARRANTY of any kind,
       express, or implied, to the maximum extent permitted by applicable
       law, without malicious intent or gross negligence; in no event may
       licensor, an author or contributor be held liable for any indirect
       or other damage, or direct damage except proven a consequence of a
       direct error of said person and intended use of this work, loss or
       other issues arising in any way out of its use, even if advised of
       the possibility of such damage or existence of a nontrivial bug.
     
       Replacement for the GNU md5 unit, which was licenced under the GNU
       GPL, thus propagating the requirement to be GPL'd to any code that
       used the old unit. The GNU md5 unit was the only one not under the
       LGPL or GPL with library exception clause; this fixes it. }
     
     {$gnu-pascal,I-}
     {$if __GPC_RELEASE__ < 20030303}
     {$error This unit requires GPC release 20030303 or newer.}
     {$endif}
     
     unit MD5;
     
     interface
     
     uses GPC;
     
     { Representation of a MD5 value. It is always in little endian byte
       order and therefore portable. }
     type
       Card8 = Cardinal attribute (Size = 8);
       TMD5 = array [1 .. 16] of Card8;
     
     const
       MD5StrLength = 2 * High (TMD5);
     
     type
       MD5String = String (MD5StrLength);
     
     { Computes MD5 message digest for Length bytes in Buffer. }
     procedure MD5Buffer (const Buffer; Length: SizeType; var MD5: TMD5);
       attribute (name = '_p_MD5Buffer');
     
     { Computes MD5 message digest for the contents of the file f. }
     procedure MD5File (var f: File; var MD5: TMD5); attribute
       (iocritical, name = '_p_MD5File');
     
     { Initializes a MD5 value with zeros. }
     procedure MD5Clear (var MD5: TMD5); attribute (name
       = '_p_MD5Clear');
     
     { Compares two MD5 values for equality. }
     function MD5Compare (const Value1, Value2: TMD5): Boolean; attribute
       (name = '_p_MD5Compare');
     
     { Converts an MD5 value to a string. }
     function MD5Str (const MD5: TMD5) = s: MD5String; attribute (name
       = '_p_MD5Str');
     
     { Converts a string to an MD5 value. Returns True if successful. }
     function MD5Val (const s: String; var MD5: TMD5): Boolean; attribute
       (name = '_p_MD5Val');
     
     { Composes two MD5 values to a single one. }
     function MD5Compose (const Value1, Value2: TMD5) = Dest: TMD5;
       attribute (name = '_p_MD5Compose');
     
     


Next: , Previous: MD5, Up: GPC Units

6.15.10 BP compatibility: Overlay

The following listing contains the interface of the Overlay unit.

This is just a dummy replacement for BP's `Overlay' unit, since GPC doesn't need overlays.

     { Dummy BP compatible overlay unit for GPC
     
       Copyright (C) 1998-2006 Free Software Foundation, Inc.
     
       Author: Frank Heckenbach <frank@pascal.gnu.de>
     
       This file is part of GNU Pascal.
     
       GNU Pascal is free software; you can redistribute it and/or modify
       it under the terms of the GNU General Public License as published
       by the Free Software Foundation; either version 2, or (at your
       option) any later version.
     
       GNU Pascal is distributed in the hope that it will be useful, but
       WITHOUT ANY WARRANTY; without even the implied warranty of
       MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
       General Public License for more details.
     
       You should have received a copy of the GNU General Public License
       along with GNU Pascal; see the file COPYING. If not, write to the
       Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA
       02111-1307, USA.
     
       As a special exception, if you link this file with files compiled
       with a GNU compiler to produce an executable, this does not cause
       the resulting executable to be covered by the GNU General Public
       License. This exception does not however invalidate any other
       reasons why the executable file might be covered by the GNU
       General Public License. }
     
     {$gnu-pascal,I-}
     {$if __GPC_RELEASE__ < 20030412}
     {$error This unit requires GPC release 20030412 or newer.}
     {$endif}
     
     unit Overlay;
     
     interface
     
     const
       OvrOK = 0;
       OvrError = -1;
       OvrNotFound = -2;
       OvrNoMemory = -3;
       OvrIOError = -4;
       OvrNoEMSDriver = -5;
       OvrNoEMSMemory = -6;
     
     const
       OvrEmsPages: Word = 0;
       OvrTrapCount: Word = 0;
       OvrLoadCount: Word = 0;
       OvrFileMode: Byte = 0;
     
     type
       OvrReadFunc = function (OvrSeg: Word): Integer;
     
     var
       OvrReadBuf: OvrReadFunc;
       OvrResult: Integer = 0;
     
     procedure OvrInit (aFileName: String);
     procedure OvrInitEMS;
     procedure OvrSetBuf (Size: LongInt);
     function  OvrGetBuf: LongInt;
     procedure OvrSetRetry (Size: LongInt);
     function  OvrGetRetry: LongInt;
     procedure OvrClearBuf;
     


Next: , Previous: Overlay, Up: GPC Units

6.15.11 Start a child process, connected with pipes, also on Dos

The following listing contains the interface of the Pipes unit.

This unit provides routines to start a child process and write to/read from its Input/Output/StdErr via pipes. All of this is emulated transparently under Dos as far as possible.

     { Piping data from and to processes
     
       Copyright (C) 1998-2006 Free Software Foundation, Inc.
     
       Author: Frank Heckenbach <frank@pascal.gnu.de>
     
       This file is part of GNU Pascal.
     
       GNU Pascal is free software; you can redistribute it and/or modify
       it under the terms of the GNU General Public License as published
       by the Free Software Foundation; either version 2, or (at your
       option) any later version.
     
       GNU Pascal is distributed in the hope that it will be useful, but
       WITHOUT ANY WARRANTY; without even the implied warranty of
       MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
       General Public License for more details.
     
       You should have received a copy of the GNU General Public License
       along with GNU Pascal; see the file COPYING. If not, write to the
       Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA
       02111-1307, USA.
     
       As a special exception, if you link this file with files compiled
       with a GNU compiler to produce an executable, this does not cause
       the resulting executable to be covered by the GNU General Public
       License. This exception does not however invalidate any other
       reasons why the executable file might be covered by the GNU
       General Public License. }
     
     {$gnu-pascal,I-}
     {$if __GPC_RELEASE__ < 20030303}
     {$error This unit requires GPC release 20030303 or newer.}
     {$endif}
     
     { Keep this consistent with the one in pipesc.c }
     {$if defined (MSDOS) or defined (__MINGW32__)}
     {$define NOFORK}
     {$endif}
     
     unit Pipes;
     
     interface
     
     uses GPC;
     
     const
       PipeForking = {$ifdef NOFORK} False {$else} True {$endif};
     
     type
       TProcedure = procedure;
     
       PWaitPIDResult = ^TWaitPIDResult;
       TWaitPIDResult = (PIDNothing, PIDExited, PIDSignaled, PIDStopped,
       PIDUnknown);
     
       PPipeProcess = ^TPipeProcess;
       TPipeProcess = record
         PID      : Integer;         { Process ID of process forked }
         SignalPID: Integer;         { Process ID to send the signal to.
                                       Equals PID by default }
         OpenPipes: Integer;         { Number of pipes to/from the
                                       process, for internal use }
         Signal   : Integer;         { Send this signal (if not 0) to the
                                       process after all pipes have been
                                       closed after some time }
         Seconds  : Integer;         { Wait so many seconds before
                                       sending the signal if the process
                                       has not terminated by itself }
         Wait     : Boolean;         { Wait for the process, even longer
                                       than Seconds seconds, after
                                       sending the signal (if any) }
         Result   : PWaitPIDResult;  { Default nil. If a pointer to a
                                       variable is stored here, its
                                       destination will contain the
                                       information whether the process
                                       terminated by itself, or was
                                       terminated or stopped by a signal,
                                       when waiting after closing the
                                       pipes }
         Status   : ^Integer;        { Default nil. If a pointer to a
                                       variable is stored here, its
                                       destination will contain the exit
                                       status if the process terminated
                                       by itself, or the number of the
                                       signal otherwise, when waiting
                                       after closing the pipes }
       end;
     
     var
       { Default values for TPipeProcess records created by Pipe }
       DefaultPipeSignal : Integer = 0;
       DefaultPipeSeconds: Integer = 0;
       DefaultPipeWait   : Boolean = True;
     
     { The procedure Pipe starts a process whose name is given by
       ProcessName, with the given parameters (can be Null if no
       parameters) and environment, and create pipes from and/or to the
       process' standard input/output/error. ProcessName is searched for
       in the PATH with FSearchExecutable. Any of ToInputFile,
       FromOutputFile and FromStdErrFile can be Null if the corresponding
       pipe is not wanted. FromOutputFile and FromStdErrFile may be
       identical, in which case standard output and standard error are
       redirected to the same pipe. The behaviour of other pairs of files
       being identical is undefined, and useless, anyway. The files are
       Assigned and Reset or Rewritten as appropriate. Errors are
       returned in IOResult. If Process is not Null, a pointer to a
       record is stored there, from which the PID of the process created
       can be read, and by writing to which the action after all pipes
       have been closed can be changed. (The record is automatically
       Dispose'd of after all pipes have been closed.) If automatic
       waiting is turned off, the caller should get the PID from the
       record before it's Dispose'd of, and wait for the process sometime
       in order to avoid zombies. If no redirections are performed (i.e.,
       all 3 files are Null), the caller should wait for the process with
       WaitPipeProcess. When an error occurs, Process is not assigned to,
       and the state of the files is undefined, so be sure to check
       IOResult before going on.
     
       ChildProc, if not nil, is called in the child process after
       forking and redirecting I/O, but before executing the new process.
       It can even be called instead of executing a new process
       (ProcessName can be empty then).
     
       The procedure even works under Dos, but, of course, in a limited
       sense: if ToInputFile is used, the process will not actually be
       started until ToInputFile is closed. Signal, Seconds and Wait of
       TPipeProcess are ignored, and PID and SignalPID do not contain a
       Process ID, but an internal value without any meaning to the
       caller. Result will always be PIDExited. So, Status is the only
       interesting field (but Result should also be checked). Since there
       is no forking under Dos, ChildProc, if not nil, is called in the
       main process before spawning the program. So, to be portable, it
       should not do any things that would influence the process after
       the return of the Pipe function.
     
       The only portable way to use "pipes" in both directions is to call
       `Pipe', write all the Input data to ToInputFile, close
       ToInputFile, and then read the Output and StdErr data from
       FromOutputFile and FromStdErrFile. However, since the capacity of
       pipes is limited, one should also check for Data from
       FromOutputFile and FromStdErrFile (using CanRead, IOSelect or
       IOSelectRead) while writing the Input data (under Dos, there
       simply won't be any data then, but checking for data doesn't do
       any harm). Please see pipedemo.pas for an example. }
     procedure Pipe (var ToInputFile, FromOutputFile, FromStdErrFile:
       AnyFile; const ProcessName: String; protected var Parameters:
       TPStrings; ProcessEnvironment: PCStrings; var Process:
       PPipeProcess; ChildProc: TProcedure); attribute (iocritical);
     
     { Waits for a process created by Pipe as determined in the Process
       record. (Process is Dispose'd of afterwards.) Returns True if
       successful. }
     function WaitPipeProcess (Process: PPipeProcess): Boolean; attribute
       (ignorable);
     
     { Alternative interface from PExecute }
     
     const
       PExecute_First   = 1;
       PExecute_Last    = 2;
       PExecute_One     = PExecute_First or PExecute_Last;
       PExecute_Search  = 4;
       PExecute_Verbose = 8;
     
     { PExecute: execute a chain of processes.
     
       Program and Arguments are the arguments to execv/execvp.
     
       Flags and PExecute_Search is non-zero if $PATH should be searched.
       Flags and PExecute_First is nonzero for the first process in
       chain. Flags and PExecute_Last is nonzero for the last process in
       chain.
     
       The result is the pid on systems like Unix where we fork/exec and
       on systems like MS-Windows and OS2 where we use spawn. It is up to
       the caller to wait for the child.
     
       The result is the exit code on systems like MSDOS where we spawn
       and wait for the child here.
     
       Upon failure, ErrMsg is set to the text of the error message,
       and -1 is returned. `errno' is available to the caller to use.
     
       PWait: cover function for wait.
     
       PID is the process id of the task to wait for. Status is the
       `status' argument to wait. Flags is currently unused (allows
       future enhancement without breaking upward compatibility). Pass 0
       for now.
     
       The result is the process ID of the child reaped, or -1 for
       failure.
     
       On systems that don't support waiting for a particular child, PID
       is ignored. On systems like MSDOS that don't really multitask
       PWait is just a mechanism to provide a consistent interface for
       the caller. }
     function  PExecute (ProgramName: CString; Arguments: PCStrings; var
       ErrMsg: String; Flags: Integer): Integer; attribute (ignorable);
     function  PWait (PID: Integer; var Status: Integer; Flags: Integer):
       Integer; attribute (ignorable);
     


Next: , Previous: Pipes, Up: GPC Units

6.15.12 BP compatibility (partly): `Port', `PortW' arrays

The following listing contains the interface of the Ports unit.

This unit provides access routines for the hardware ports on the IA32, as a partial replacement for BP's `Port' and `PortW' pseudo arrays.

Since port access is platform-specific, this unit cannot be used in code intended to be portable. Even on the IA32, its use can often be avoided – e.g. Linux provides a number of `ioctl' functions, and DJGPP provides some routines to achieve things that would require port access under BP. Therefore, it is recommended to avoid using this unit whenever possible.

     { Access functions for I/O ports for GPC on an IA32 platform. This
       unit is *not* portable. It works only on IA32 platforms (tested
       under Linux and DJGPP). It is provided here only to serve as a
       replacement for BP's Port and PortW pseudo arrays.
     
       Copyright (C) 1998-2006 Free Software Foundation, Inc.
     
       Author: Frank Heckenbach <frank@pascal.gnu.de>
     
       This file is part of GNU Pascal.
     
       GNU Pascal is free software; you can redistribute it and/or modify
       it under the terms of the GNU General Public License as published
       by the Free Software Foundation; either version 2, or (at your
       option) any later version.
     
       GNU Pascal is distributed in the hope that it will be useful, but
       WITHOUT ANY WARRANTY; without even the implied warranty of
       MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
       General Public License for more details.
     
       You should have received a copy of the GNU General Public License
       along with GNU Pascal; see the file COPYING. If not, write to the
       Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA
       02111-1307, USA.
     
       As a special exception, if you link this file with files compiled
       with a GNU compiler to produce an executable, this does not cause
       the resulting executable to be covered by the GNU General Public
       License. This exception does not however invalidate any other
       reasons why the executable file might be covered by the GNU
       General Public License. }
     
     {$gnu-pascal,I-}
     {$if __GPC_RELEASE__ < 20030303}
     {$error This unit requires GPC release 20030303 or newer.}
     {$endif}
     {$ifndef __i386__}
     {$error The Ports unit is only for the IA32 platform}
     {$endif}
     
     unit Ports;
     
     interface
     
     { Port access functions }
     function  InPortB  (PortNumber: ShortWord): Byte;
     function  InPortW  (PortNumber: ShortWord): ShortWord;
     procedure OutPortB (PortNumber: ShortWord; aValue: Byte);
     procedure OutPortW (PortNumber, aValue: ShortWord);
     
     { libc functions for getting access to the ports -- only for root
       processes, of course -- and to give up root privileges after
       getting access to the ports for setuid root programs. Dummies
       under DJGPP. }
     {$ifdef MSDOS}
     function  IOPerm (From, Num: MedCard; On: Integer): Integer;
       attribute (name = 'ioperm');
     function  IOPL (Level: Integer): Integer; attribute (name = 'iopl');
     function  SetEUID (EUID: Integer): Integer; attribute (name
       = 'seteuid');
     {$else}
     function  IOPerm (From, Num: MedCard; On: Integer): Integer;
       external name 'ioperm';
     function  IOPL (Level: Integer): Integer; external name 'iopl';
     function  SetEUID (EUID: Integer): Integer; external name 'seteuid';
     {$endif}
     


Next: , Previous: Ports, Up: GPC Units

6.15.13 BP compatibility: Printer, portable

The following listing contains the interface of the Printer unit.

This unit provides printer access, compatible to BP's `Printer' unit, for Dos (using printer devices) and Unix systems (using printer utilities).

For BP compatibility, the variable `Lst' is provided, but for newly written programs, it is recommended to use the `AssignPrinter' procedure on a text file, and close the file when done (thereby committing the printer job). This method allows for sending multiple printer jobs in the same program.

     { BP compatible printer unit with extensions
     
       Copyright (C) 1998-2006 Free Software Foundation, Inc.
     
       Author: Frank Heckenbach <frank@pascal.gnu.de>
     
       This file is part of GNU Pascal.
     
       GNU Pascal is free software; you can redistribute it and/or modify
       it under the terms of the GNU General Public License as published
       by the Free Software Foundation; either version 2, or (at your
       option) any later version.
     
       GNU Pascal is distributed in the hope that it will be useful, but
       WITHOUT ANY WARRANTY; without even the implied warranty of
       MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
       General Public License for more details.
     
       You should have received a copy of the GNU General Public License
       along with GNU Pascal; see the file COPYING. If not, write to the
       Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA
       02111-1307, USA.
     
       As a special exception, if you link this file with files compiled
       with a GNU compiler to produce an executable, this does not cause
       the resulting executable to be covered by the GNU General Public
       License. This exception does not however invalidate any other
       reasons why the executable file might be covered by the GNU
       General Public License. }
     
     {$gnu-pascal,I-}
     {$if __GPC_RELEASE__ < 20030303}
     {$error This unit requires GPC release 20030303 or newer.}
     {$endif}
     
     unit Printer;
     
     interface
     
     uses GPC {$ifndef __OS_DOS__}, Pipes {$endif};
     
     var
       { Dos-like systems: writing to a printer device }
     
       { The file name to write printer output into }
       PrinterDeviceName: PString = @'prn';
     
       { Unix-like systems: printing via a printer program }
     
       { The file name of the printer program. If it contains a '/', it
         will be taken as a complete path, otherwise the file name will
         be searched for in the PATH with FSearchExecutable. }
       PrinterCommand: PString = @'lpr';
     
       { Optional command line parameters for the printer program.
         Ignored when nil. }
       PrinterArguments: PPStrings = nil;
     
       { How to deal with the printer spooler after the printer pipe is
         closed, cf. the Pipes unit. }
       PrinterPipeSignal : Integer = 0;
       PrinterPipeSeconds: Integer = 0;
       PrinterPipeWait   : Boolean = True;
     
     { Text file opened to default printer }
     var
       Lst: Text;
     
     { Assign a file to the printer. Lst will be assigned to the default
       printer at program start, but other files can be assigned to the
       same or other printers (possibly after changing the variables
       above). SpoolerOutput, if not Null, will be redirected from the
       printer spooler's standard output and error. If you use this, note
       that a deadlock might arise when trying to write data to the
       spooler while its output is not being read, though this seems
       quite unlikely, since most printer spoolers don't write so much
       output that could fill a pipe. Under Dos, where no spooler is
       involved, SpoolerOutput, if not Null, will be reset to an empty
       file for compatibility. }
     procedure AssignPrinter (var f: AnyFile; var SpoolerOutput:
       AnyFile);
     


Next: , Previous: Printer, Up: GPC Units

6.15.14 Regular Expression matching and substituting

The following listing contains the interface of the RegEx unit.

This unit provides routines to match strings against regular expressions and perform substitutions using matched subexpressions. Regular expressions are strings with some characters having special meanings. They describe (match) a class of strings. They are similar to wild cards used in file name matching, but much more powerful.

To use this unit, you will need the `rx' library which can be found in http://www.gnu-pascal.de/libs/.

     {$nested-comments}
     
     { Regular expression matching and replacement
     
       The RegEx unit provides routines to match strings against regular
       expressions and perform substitutions using matched
       subexpressions.
     
       To use the RegEx unit, you will need the rx library which can be
       found in http://www.gnu-pascal.de/libs/
     
       Regular expressions are strings with some characters having
       special meanings. They describe (match) a class of strings. They
       are similar to wild cards used in file name matching, but much
       more powerful.
     
       There are two kinds of regular expressions supported by this unit,
       basic and extended regular expressions. The difference between
       them is not functionality, but only syntax. The following is a
       short overview of regular expressions. For a more thorough
       explanation see the literature, or the documentation of the rx
       library, or man pages of programs like grep(1) and sed(1).
     
       Basic           Extended        Meaning
       `.'             `.'             matches any single character
       `[aei-z]'       `[aei-z]'       matches either `a', `e', or any
                                       character from `i' to `z'
       `[^aei-z]'      `[^aei-z]'      matches any character but `a',
                                       `e', or `i' .. `z'
                                       To include in such a list the the
                                       characters `]', `^', or `-', put
                                       them first, anywhere but first, or
                                       first or last, resp.
       `[[:alnum:]]'   `[[:alnum:]]'   matches any alphanumeric character
       `[^[:digit:]]'  `[^[:digit:]]'  matches anything but a digit
       `[a[:space:]]'  `[a[:space:]]'  matches the letter `a' or a space
                                       character (space, tab)
       ...                             (there are more classes available)
       `\w'            `\w'            = [[:alnum:]]
       `\W'            `\W'            = [^[:alnum:]]
       `^'             `^'             matches the empty string at the
                                       beginning of a line
       `$'             `$'             matches the empty string at the
                                       end of a line
       `*'             `*'             matches zero or more occurences of
                                       the preceding expression
       `\+'            `+'             matches one or more occurences of
                                       the preceding expression
       `\?'            `?'             matches zero or one occurence of
                                       the preceding expression
       `\{N\}'         `{N}'           matches exactly N occurences of
                                       the preceding expression (N is an
                                       integer number)
       `\{M,N\}'       `{M,N}'         matches M to N occurences of the
                                       preceding expression (M and N are
                                       integer numbers, M <= N)
       `AB'            `AB'            matches A followed by B (A and B
                                       are regular expressions)
       `A\|B'          `A|B'           matches A or B (A and B are
                                       regular expressions)
       `\( \)'         `( )'           forms a subexpression, to override
                                       precedence, and for subexpression
                                       references
       `\7'            `\7'            matches the 7'th parenthesized
                                       subexpression (counted by their
                                       start in the regex), where 7 is a
                                       number from 1 to 9 ;-).
                                       *Please note:* using this feature
                                       can be *very* slow or take very
                                       much memory (exponential time and
                                       space in the worst case, if you
                                       know what that means ...).
       `\'             `\'             quotes the following character if
                                       it's special (i.e. listed above)
       rest            rest            any other character matches itself
     
       Precedence, from highest to lowest:
       * parentheses (`()')
       * repetition (`*', `+', `?', `{}')
       * concatenation
       * alternation (`|')
     
       When performing substitutions using matched subexpressions of a
       regular expression (see `ReplaceSubExpressionReferences'), the
       replacement string can reference the whole matched expression with
       `&' or `\0', the 7th subexpression with `\7' (just like in the
       regex itself, but using it in replacements is not slow), and the
       7th subexpression converted to upper/lower case with `\u7' or
       `\l7', resp. (which also works for the whole matched expression
       with `\u0' or `\l0'). A verbatim `&' or `\' can be specified with
       `\&' or `\\', resp.
     
       Copyright (C) 1998-2006 Free Software Foundation, Inc.
     
       Author: Frank Heckenbach <frank@pascal.gnu.de>
     
       This file is part of GNU Pascal.
     
       GNU Pascal is free software; you can redistribute it and/or modify
       it under the terms of the GNU General Public License as published
       by the Free Software Foundation; either version 2, or (at your
       option) any later version.
     
       GNU Pascal is distributed in the hope that it will be useful, but
       WITHOUT ANY WARRANTY; without even the implied warranty of
       MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
       General Public License for more details.
     
       You should have received a copy of the GNU General Public License
       along with GNU Pascal; see the file COPYING. If not, write to the
       Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA
       02111-1307, USA.
     
       As a special exception, if you link this file with files compiled
       with a GNU compiler to produce an executable, this does not cause
       the resulting executable to be covered by the GNU General Public
       License. This exception does not however invalidate any other
       reasons why the executable file might be covered by the GNU
       General Public License.
     
       Please also note the license of the rx library. }
     
     {$gnu-pascal,I-}
     {$if __GPC_RELEASE__ < 20030303}
     {$error This unit requires GPC release 20030303 or newer.}
     {$endif}
     
     unit RegEx;
     
     interface
     
     uses GPC;
     
     const
       { `BasicRegExSpecialChars' contains all characters that have
         special meanings in basic regular expressions.
         `ExtRegExSpecialChars' contains those that have special meanings
         in extended regular expressions. }
       BasicRegExSpecialChars = ['.', '[', ']', '^', '$', '*', '\'];
       ExtRegExSpecialChars   =
       ['.', '[', ']', '^', '$', '*', '+', '?', '{', '}', '|', '(', ')', '\'];
     
     type
       { The type used by the routines of the `RegEx' unit to store
         regular expressions in an internal format. The fields RegEx,
         RegMatch, ErrorInternal, From and Length are only used
         internally. SubExpressions can be read after `NewRegEx' and will
         contain the number of parenthesized subexpressions. Error should
         be checked after `NewRegEx'. It will be `nil' when it succeeded,
         and contain an error message otherwise. }
       RegExType = record
         RegEx, RegMatch: Pointer;  { Internal }
         ErrorInternal: CString;    { Internal }
         From, Length: CInteger;    { Internal }
         SubExpressions: CInteger;
         Error: PString
       end;
     
     { Simple interface to regular expression matching. Matches a regular
       expression against a string starting from a specified position.
       Returns the position of the first match, or 0 if it does not
       match, or the regular expression is invalid. }
     function  RegExPosFrom (const Expression: String; ExtendedRegEx,
       CaseInsensitive: Boolean; const s: String; From: Integer) =
       MatchPosition: Integer;
     
     { Creates the internal format of a regular expression. If
       ExtendedRegEx is True, Expression is assumed to denote an extended
       regular expression, otherwise a basic regular expression.
       CaseInsensitive determines if the case of letters will be ignored
       when matching the expression. If NewLines is True, `NewLine'
       characters in a string matched against the expression will be
       treated as dividing the string in multiple lines, so that `$' can
       match before the NewLine and `^' can match after. Also, `.' and
       `[^...]' will not match a NewLine then. }
     procedure NewRegEx (var RegEx: RegExType; const Expression: String;
       ExtendedRegEx, CaseInsensitive, NewLines: Boolean);
     
     { Disposes of a regular expression created with `NewRegEx'. *Must*
       be used after `NewRegEx' before the RegEx variable becomes invalid
       (i.e., goes out of scope or a pointer pointing to it is Dispose'd
       of). }
     procedure DisposeRegEx (var RegEx: RegExType); external
       name '_p_DisposeRegEx';
     
     { Matches a regular expression created with `NewRegEx' against a
       string. }
     function  MatchRegEx (var RegEx: RegExType; const s: String;
       NotBeginningOfLine, NotEndOfLine: Boolean): Boolean;
     
     { Matches a regular expression created with `NewRegEx' against a
       string, starting from a specified position. }
     function  MatchRegExFrom (var RegEx: RegExType; const s: String;
       NotBeginningOfLine, NotEndOfLine: Boolean; From: Integer):
       Boolean;
     
     { Finds out where the regular expression matched, if `MatchRegEx' or
       `MatchRegExFrom' were successful. If n = 0, it returns the
       position of the whole match, otherwise the position of the n'th
       parenthesized subexpression. MatchPosition and MatchLength will
       contain the position (counted from 1) and length of the match, or
       0 if it didn't match. (Note: MatchLength can also be 0 for a
       successful empty match, so check whether MatchPosition is 0 to
       find out if it matched at all.) MatchPosition or MatchLength may
       be Null and is ignored then. }
     procedure GetMatchRegEx (var RegEx: RegExType; n: Integer; var
       MatchPosition, MatchLength: Integer);
     
     { Checks if the string s contains any quoted characters or
       (sub)expression references to the regular expression RegEx created
       with `NewRegEx'. These are `&' or `\0' for the whole matched
       expression (if OnlySub is not set) and `\1' .. `\9' for the n'th
       parenthesized subexpression. Returns 0 if it does not contain any,
       and the number of references and quoted characters if it does. If
       an invalid reference (i.e. a number bigger than the number of
       subexpressions in RegEx) is found, it returns the negative value
       of the (first) invalid reference. }
     function  FindSubExpressionReferences (var RegEx: RegExType; const
       s: String; OnlySub: Boolean): Integer;
     
     { Replaces (sub)expression references in ReplaceStr by the actual
       (sub)expressions and unquotes quoted characters. To be used after
       the regular expression RegEx created with `NewRegEx' was matched
       against s successfully with `MatchRegEx' or `MatchRegExFrom'. }
     function  ReplaceSubExpressionReferences (var RegEx: RegExType;
       const s, ReplaceStr: String) = Res: TString;
     
     { Returns the string for a regular expression that matches exactly
       one character out of the given set. It can be combined with the
       usual operators to form more complex expressions. }
     function  CharSet2RegEx (const Characters: CharSet) = s: TString;
     


Next: , Previous: RegEx, Up: GPC Units

6.15.15 BP compatibility: Strings

The following listing contains the interface of the Strings unit.

This is a compatibility unit to BP's `Strings' unit to handle C style `#0'-terminated strings.

The same functionality and much more is available in the Run Time System, Run Time System, under clearer names (starting with a `CString' prefix),

Moreover, the use of `#0'-terminated C-style strings (`PChar' or `CString') is generally not recommended in GPC, since GPC provides ways to deal with Pascal-style strings of arbitrary and dynamic size in a comfortable way, as well as automatic conversion to C-style strings in order to call external C functions.

Therefore, using this unit is not recommended in newly written programs.

     { BP compatible Strings unit
     
       Copyright (C) 1999-2006 Free Software Foundation, Inc.
     
       Author: Frank Heckenbach <frank@pascal.gnu.de>
     
       This file is part of GNU Pascal.
     
       GNU Pascal is free software; you can redistribute it and/or modify
       it under the terms of the GNU General Public License as published
       by the Free Software Foundation; either version 2, or (at your
       option) any later version.
     
       GNU Pascal is distributed in the hope that it will be useful, but
       WITHOUT ANY WARRANTY; without even the implied warranty of
       MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
       General Public License for more details.
     
       You should have received a copy of the GNU General Public License
       along with GNU Pascal; see the file COPYING. If not, write to the
       Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA
       02111-1307, USA.
     
       As a special exception, if you link this file with files compiled
       with a GNU compiler to produce an executable, this does not cause
       the resulting executable to be covered by the GNU General Public
       License. This exception does not however invalidate any other
       reasons why the executable file might be covered by the GNU
       General Public License. }
     
     {$gnu-pascal,I-}
     {$if __GPC_RELEASE__ < 20030303}
     {$error This unit requires GPC release 20030303 or newer.}
     {$endif}
     
     module Strings;
     
     export Strings = all (CStringLength => StrLen, CStringEnd => StrEnd,
                           CStringMove => StrMove, CStringCopy =>
       StrCopy,
                           CStringCopyEnd => StrECopy, CStringLCopy =>
       StrLCopy,
                           CStringCopyString => StrPCopy, CStringCat =>
       StrCat,
                           CStringLCat => StrLCat, CStringComp =>
       StrComp,
                           CStringCaseComp => StrIComp, CStringLComp =>
       StrLComp,
                           CStringLCaseComp => StrLIComp, CStringChPos =>
       StrScan,
                           CStringLastChPos => StrRScan, CStringPos =>
       StrPos,
                           CStringLastPos => StrRPos, CStringUpCase =>
       StrUpper,
                           CStringLoCase => StrLower, CStringIsEmpty =>
       StrEmpty,
                           CStringNew => StrNew);
     
     import GPC;
     
     function StrPas (aString: CString): TString;
     procedure StrDispose (s: CString); external name '_p_Dispose';
     


Next: , Previous: Strings, Up: GPC Units

6.15.16 Higher level string handling

The following listing contains the interface of the StringUtils unit.

This unit provides some routines for string handling on a higher level than those provided by the RTS.

     { Some routines for string handling on a higher level than those
       provided by the RTS.
     
       Copyright (C) 1999-2006 Free Software Foundation, Inc.
     
       Author: Frank Heckenbach <frank@pascal.gnu.de>
     
       This file is part of GNU Pascal.
     
       GNU Pascal is free software; you can redistribute it and/or modify
       it under the terms of the GNU General Public License as published
       by the Free Software Foundation; either version 2, or (at your
       option) any later version.
     
       GNU Pascal is distributed in the hope that it will be useful, but
       WITHOUT ANY WARRANTY; without even the implied warranty of
       MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
       General Public License for more details.
     
       You should have received a copy of the GNU General Public License
       along with GNU Pascal; see the file COPYING. If not, write to the
       Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA
       02111-1307, USA.
     
       As a special exception, if you link this file with files compiled
       with a GNU compiler to produce an executable, this does not cause
       the resulting executable to be covered by the GNU General Public
       License. This exception does not however invalidate any other
       reasons why the executable file might be covered by the GNU
       General Public License. }
     
     {$gnu-pascal,I-}
     {$if __GPC_RELEASE__ < 20030303}
     {$error This unit requires GPC release 20030303 or newer.}
     {$endif}
     
     unit StringUtils;
     
     interface
     
     uses GPC;
     
     { Various routines }
     
     { Appends Source to s, truncating the result if necessary. }
     procedure AppendStr (var s: String; const Source: String);
     
     { Cuts s to MaxLength characters. If s is already MaxLength
       characters or shorter, it doesn't change anything. }
     procedure StrCut (var s: String; MaxLength: Integer);
     
     { Returns the number of disjoint occurences of SubStr in s. Returns
       0 if SubStr is empty. }
     function  StrCount (const SubStr: String; s: String): Integer;
     
     { Returns s, with all disjoint occurences of Source replaced by
       Dest. }
     function  StrReplace (const s, Source, Dest: String) = Result:
       TString;
     
     { Sets of characters accepted for `True' and `False' by
       Char2Boolean and StrReadBoolean. }
     var
       CharactersTrue : CharSet = ['Y', 'y'];
       CharactersFalse: CharSet = ['N', 'n'];
     
     { If ch is an element of CharactersTrue, Dest is set to True,
       otherwise if it is an element of CharactersFalse, Dest is set to
       False. In both cases True is returned. If ch is not an element of
       either set, Dest is set to False and False is returned. }
     function  Char2Boolean (ch: Char; var Dest: Boolean): Boolean;
       attribute (ignorable);
     
     { Converts a digit character to its numeric value. Handles every
       base up to 36 (0 .. 9, a .. z, upper and lower case recognized).
       Returns -1 if the character is not a digit at all. If you want to
       use it for a base < 36, you have to check if the result is smaller
       than the base and not equal to -1. }
     function  Char2Digit (ch: Char): Integer;
     
     { Encode a string in a printable format (quoted printable). All
       occurences of EscapeChar within the string are encoded. If
       QuoteHigh is True, all characters above the ASCII range are
       encoded as well (required in "7 bit" environments, as per several
       RFCs). `=' is always encoded, as required for proper decoding, as
       are all characters below space (control characters), so if you
       don't need an escape char yourself, you can pass #0 for
       EscapeChar. }
     function  QuoteStringEscape (const s: String; EscapeChar: Char;
       QuoteHigh: Boolean): TString;
     
     { Encode a string in a printable format (quoted printable and
       surrounded with `"'). All occurences of `"' within the string are
       encoded, so the result string contains exactly two `"' characters
       (at the beginning and ending). This is useful to store arbitrary
       strings in text files while keeping them as readable as possible
       (which is the goal of the quoted printable encoding in general,
       see RFC 1521, section 5.1) and being able to read them back
       losslessly (with UnQuoteString). }
     function  QuoteString (const s: String): TString;
     
     { Encode a string in a printable format suitable for StrReadEnum.
       All occurences of `,' within the string are encoded. }
     function  QuoteEnum (const s: String): TString;
     
     { Decode a string encoded by QuoteString (removing the `"' and
       expanding quoted printable encoded characters). Returns True if
       successful and False if the string has an invalid form. A string
       returned by QuoteString is always valid. }
     function  UnQuoteString (var s: String): Boolean; attribute
       (ignorable);
     
     { Decode a quoted-printable string (not enclosed in `"', unlike for
       UnQuoteString). Returns True if successful and False if the string
       has an invalid form. In the latter case, it still decodes as much
       as is valid, even after the error position. }
     function  UnQPString (var s: String): Boolean; attribute
       (ignorable);
     
     { Quotes a string as done in shells, i.e. all special characters are
       enclosed in either `"' or `'', where `"', `$' and ``' are always
       enclosed in `'' and `'' is always enclosed in `"'. }
     function  ShellQuoteString (const s: String) = Res: TString;
     
     { Replaces all tab characters in s with the appropriate amount of
       spaces, assuming tab stops at every TabSize columns. Returns True
       if successful and False if the expanded string would exceed the
       capacity of s. In the latter case, some, but not all of the tabs
       in s may have been expanded. }
     function  ExpandTabs (var s: String; TabSize: Integer): Boolean;
       attribute (ignorable);
     
     { Returns s, with all occurences of C style escape sequences (e.g.
       `\n') replaced by the characters they mean. If AllowOctal is True,
       also octal character specifications (e.g. `\007') are replaced. If
       RemoveQuoteChars is True, any other backslashes are removed (e.g.
       `\*' -> `*' and `\\' -> `\'), otherwise they are kept, and also
       `\\' is left as two backslashes then. }
     function  ExpandCEscapeSequences (const s: String; RemoveQuoteChars,
       AllowOctal: Boolean) = r: TString;
     
     { Routines for TPStrings }
     
     { Initialise a TPStrings variable, allocate Size characters for each
       element. This procedure does not dispose of any previously
       allocated storage, so if you use it on a previously used variable
       without freeing the storage yourself, this might cause memory
       leaks. }
     procedure AllocateTPStrings (var Strings: TPStrings; Size: Integer);
     
     { Clear all elements (set them to empty strings), does not free any
       storage. }
     procedure ClearTPStrings (var Strings: TPStrings);
     
     { Divide a string into substrings, using Separators as separator. A
       single trailing separator is ignored. Further trailing separators
       as well as any leading separators and multiple separators in a row
       produce empty substrings. }
     function TokenizeString (const Source: String; Separators: CharSet)
       = Res: PPStrings;
     
     { Divide a string into substrings, using SpaceCharacters as
       separators. The splitting is done according the usual rules of
       shells, using (and removing) single and double quotes and
       QuotingCharacter. Multiple, leading, and trailing separators are
       ignored. If there is an error, a message is stored in ErrMsg (if
       not Null), and nil is returned. nil is also returned (without an
       error message) if s is empty. }
     function ShellTokenizeString (const s: String; var ErrMsg: String) =
       Tokens: PPStrings;
     
     { String parsing routines }
     
     { All the following StrReadFoo functions behave similarly. They read
       items from a string s, starting at index i, to a variable Dest.
       They skip any space characters (spaces and tabs) by incrementing i
       first. They return True if successful, False otherwise. i is
       incremented accordingly if successful, otherwise i is left
       unchanged, apart from the skipping of space characters, and Dest
       is undefined. This behaviour makes it easy to use the functions in
       a row like this:
     
         i := 1;
         if StrReadInt    (s, i, Size)  and StrReadComma (s, i) and
            StrReadQuoted (s, i, Name)  and StrReadComma (s, i) and
            ...
            StrReadReal   (s, i, Angle) and (i > Length (s)) then ...
     
       (The check `i > Length (s)' is in case you don't want to accept
       trailing "garbage".) }
     
     { Just skip any space characters as described above. }
     procedure StrSkipSpaces (const s: String; var i: Integer);
     
     { Read a quoted string (as produced by QuoteString) from a string
       and unquote the result using UnQuoteString. It is considered
       failure if the result (unquoted) would be longer than the capacity
       of Dest. }
     function  StrReadQuoted (const s: String; var i: Integer; var Dest:
       String): Boolean; attribute (ignorable);
     
     { Read a string delimited with Delimiter from a string and return
       the result with the delimiters removed. It is considered failure
       if the result (without delimiters) would be longer than the
       capacity of Dest. }
     function  StrReadDelimited (const s: String; var i: Integer; var
       Dest: String; Delimiter: Char): Boolean; attribute (ignorable);
     
     { Read a word (consisting of anything but space characters and
       commas) from a string. It is considered failure if the result
       would be longer than the capacity of Dest. }
     function  StrReadWord (const s: String; var i: Integer; var Dest:
       String): Boolean; attribute (ignorable);
     
     { Check that a certain string is contained in s (after possible
       space characters). }
     function  StrReadConst (const s: String; var i: Integer; const
       Expected: String) = Res: Boolean; attribute (ignorable);
     
     { A simpler to use version of StrReadConst that expects a `,'. }
     function  StrReadComma (const s: String; var i: Integer) = Res:
       Boolean; attribute (ignorable);
     
     { Read an integer number from a string. }
     function  StrReadInt (const s: String; var i: Integer; var Dest:
       Integer): Boolean; attribute (ignorable);
     
     { Read a real number from a string. }
     function  StrReadReal (const s: String; var i: Integer; var Dest:
       Real): Boolean; attribute (ignorable);
     
     { Read a Boolean value, represented by a single character
       from CharactersTrue or CharactersFalse (cf. Char2Boolean), from a
       string. }
     function  StrReadBoolean (const s: String; var i: Integer; var Dest:
       Boolean): Boolean; attribute (ignorable);
     
     { Read an enumerated value, i.e., one of the entries of IDs, from a
       string, and stores the ordinal value, i.e., the index in IDs
       (always zero-based) in Dest. }
     function  StrReadEnum (const s: String; var i: Integer; var Dest:
       Integer; const IDs: array of PString): Boolean; attribute
       (ignorable);
     
     { String hash table }
     
     const
       DefaultHashSize = 1403;
     
     type
       THash = Cardinal;
     
       PStrHashList = ^TStrHashList;
       TStrHashList = record
         Next: PStrHashList;
         s: PString;
         i: Integer;
         p: Pointer
       end;
     
       PStrHashTable = ^TStrHashTable;
       TStrHashTable (Size: Cardinal) = record
         CaseSensitive: Boolean;
         Table: array [0 .. Size - 1] of PStrHashList
       end;
     
     function  HashString          (const s: String): THash;
     function  NewStrHashTable     (Size: Cardinal; CaseSensitive:
       Boolean) = HashTable: PStrHashTable;
     procedure AddStrHashTable     (HashTable: PStrHashTable; s: String;
       i: Integer; p: Pointer);
     procedure DeleteStrHashTable  (HashTable: PStrHashTable; s: String);
     function  SearchStrHashTable  (HashTable: PStrHashTable; const s:
       String; var p: Pointer): Integer;  { p may be Null }
     procedure StrHashTableUsage   (HashTable: PStrHashTable; var
       Entries, Slots: Integer);
     procedure DisposeStrHashTable (HashTable: PStrHashTable);
     


Next: , Previous: StringUtils, Up: GPC Units

6.15.17 BP compatibility: System

The following listing contains the interface of the System unit.

This unit contains only BP's more exotic routines which are not recommended to be used in new programs. Most of their functionality can be achieved by more standard means already.

Note: `MemAvail' and `MaxAvail', provided in this unit, cannot easily be achieved by other means. However, it is not recommended to use them on any multi-tasking system at all, where memory is a shared resource. The notes in the unit give some hints about how to avoid using them.

On special request, i.e., by defining the conditionals `__BP_TYPE_SIZES__', `__BP_RANDOM__' and/or `__BP_PARAMSTR_0__', the unit also provides BP compatible integer type sizes, a 100% BP compatible pseudo random number generator and/or BP compatible `ParamStr (0)' behaviour (the latter, however, only on some systems).

     { BP and partly Delphi compatible System unit for GPC
     
       This unit is released as part of the GNU Pascal project. It
       implements some rather exotic BP and Delphi compatibility
       features. Even many BP and Delphi programs don't need them, but
       they're here for maximum compatibility. Most of BP's and Delphi's
       System units' features are built into the compiler or the RTS.
     
       Note: The things in this unit are really exotic. If you haven't
       used BP or Delphi before, you don't want to look at this unit. :-)
     
       This unit depends on the conditional defines `__BP_TYPE_SIZES__',
       `__BP_RANDOM__', `__BP_PARAMSTR_0__' and `__BP_NO_ALLOCMEM__'.
     
       If `__BP_TYPE_SIZES__' is defined (with the `-D__BP_TYPE_SIZES__'
       option), the integer data types will be redefined to the sizes
       they have in BP or Delphi. Note that this might cause problems,
       e.g. when passing var parameters of integer types between units
       that do and don't use System. However, of the BP compatibility
       units, only Dos and WinDos use such parameters, and they have been
       taken care of so they work.
     
       If `__BP_RANDOM__' is defined (`-D__BP_RANDOM__'), this unit will
       provide an exactly BP compatible pseudo random number generator.
       In particular, the range for integer randoms will be truncated to
       16 bits like in BP. The RandSeed variable is provided, and if it's
       set to the same value as BP's RandSeed, it produces exactly the
       same sequence of pseudo random numbers that BP's pseudo random
       number generator does (whoever might need this ... ;-). Even the
       Randomize function will behave exactly like in BP. However, this
       will not be noted unless one explicitly tests for it.
     
       If `__BP_PARAMSTR_0__' is defined (`-D__BP_PARAMSTR_0__'), this
       unit will change the value of `ParamStr (0)' to that of
       `ExecutablePath', overwriting the value actually passed by the
       caller, to imitate BP's/Dos's behaviour. However *note*: On most
       systems, `ExecutablePath' is *not* guaranteed to return the full
       path, so defining this symbol doesn't change anything. In general,
       you *cannot* expect to find the full executable path, so better
       don't even try it, or your program will (at best) run on some
       systems. For most cases where BP programs access their own
       executable, there are cleaner alternatives available.
     
       If `__BP_NO_ALLOCMEM__' is defined (`-D__BP_NO_ALLOCMEM__'), the
       two Delphi compatible functions `AllocMemCount' and `AllocMemSize'
       will not be provided. The advantage is that this unit will not
       have to `Mark' the heap which makes memory de-/allocations much
       faster if the program doesn't use `Mark' otherwise.
     
       Copyright (C) 1998-2006 Free Software Foundation, Inc.
     
       Authors: Peter Gerwinski <peter@gerwinski.de>
                Prof. Abimbola A. Olowofoyeku <African_Chief@bigfoot.com>
                Frank Heckenbach <frank@pascal.gnu.de>
                Dominik Freche <dominik.freche@gmx.net>
     
       This file is part of GNU Pascal.
     
       GNU Pascal is free software; you can redistribute it and/or modify
       it under the terms of the GNU General Public License as published
       by the Free Software Foundation; either version 2, or (at your
       option) any later version.
     
       GNU Pascal is distributed in the hope that it will be useful, but
       WITHOUT ANY WARRANTY; without even the implied warranty of
       MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
       General Public License for more details.
     
       You should have received a copy of the GNU General Public License
       along with GNU Pascal; see the file COPYING. If not, write to the
       Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA
       02111-1307, USA.
     
       As a special exception, if you link this file with files compiled
       with a GNU compiler to produce an executable, this does not cause
       the resulting executable to be covered by the GNU General Public
       License. This exception does not however invalidate any other
       reasons why the executable file might be covered by the GNU
       General Public License. }
     
     {$gnu-pascal,I-}
     {$if __GPC_RELEASE__ < 20030303}
     {$error This unit requires GPC release 20030303 or newer.}
     {$endif}
     
     module System;
     
     export System = all (FileMode {$ifdef __BP_TYPE_SIZES__},
       SystemInteger => Integer, SystemWord => Word {$endif});
     
     import GPC (MaxLongInt => GPC_MaxLongInt);
     
     var
       { Chain of procedures to be executed at the end of the program }
       ExitProc: ^procedure = nil;
     
       { Contains all the command line arguments passed to the program,
         concatenated, with spaces between them }
       CmdLine: CString;
     
       {$ifdef __BP_RANDOM__}
       { Random seed, initialized by Randomize, but can also be set
         explicitly }
       RandSeed: Integer attribute (Size = 32) = 0;
       {$endif}
     
     type
       OrigInt = Integer;
       OrigWord = Word;
     
       { Delphi }
       SmallInt = Integer attribute (Size = 16);
       DWord    = Cardinal attribute (Size = 32);
     
       { Short BP compatible type sizes if wanted }
       {$ifdef __BP_TYPE_SIZES__}
       ByteBool      = Boolean attribute (Size = 8);
       WordBool      = Boolean attribute (Size = 16);
       LongBool      = Boolean attribute (Size = 32);
       ShortInt      = Integer attribute (Size = 8);
       SystemInteger = Integer attribute (Size = 16);
       LongInt       = Integer attribute (Size = 32);
       Comp          = Integer attribute (Size = 64);
       Byte          = Cardinal attribute (Size = 8);
       SystemWord    = Cardinal attribute (Size = 16);
       LongWord      = Cardinal attribute (Size = 32);  { Delphi }
       {$else}
       SystemInteger = Integer;
       SystemWord    = Word;
       {$endif}
     
       {$if False}  { @@ doesn't work well (dialec3.pas) -- when GPC gets
       short
                         strings, it will be unnecessary }
       {$ifopt borland-pascal}
       String = String [255];
       {$endif}
       {$endif}
     
     const
       MaxInt     = High (SystemInteger);
       MaxLongInt = High (LongInt);
     
     { Return the lowest-order byte of x }
     function  Lo (x: LongestInt): Byte;
     
     { Return the second-lowest-order byte of x }
     function  Hi (x: LongestInt): Byte;
     
     { Swap the lowest-order and second-lowest-order bytes, mask out the
       higher-order ones }
     function  Swap (x: LongestInt): SystemWord;
     
     { Store the current directory name (on the given drive number if
       drive <> 0) in s }
     procedure GetDir (Drive: Byte; var s: String);
     
     { Dummy routine for compatibility. @@Use two overloaded versions
       rather than varargs when possible. }
     procedure SetTextBuf (var f: Text; var Buf; ...);
     
     { Mostly useless BP compatible variables }
     var
       SelectorInc: SystemWord = $1000;
       Seg0040: SystemWord = $40;
       SegA000: SystemWord = $a000;
       SegB000: SystemWord = $b000;
       SegB800: SystemWord = $b800;
       Test8086: Byte = 2;
       Test8087: Byte = 3;  { floating-point arithmetic is emulated
                              transparently by the OS if not present
                              in hardware }
       OvrCodeList: SystemWord = 0;
       OvrHeapSize: SystemWord = 0;
       OvrDebugPtr: Pointer = nil;
       OvrHeapOrg: SystemWord = 0;
       OvrHeapPtr: SystemWord = 0;
       OvrHeapEnd: SystemWord = 0;
       OvrLoadList: SystemWord = 0;
       OvrDosHandle: SystemWord = 0;
       OvrEmsHandle: SystemWord = $ffff;
       HeapOrg: Pointer absolute HeapLow;
       HeapPtr: Pointer absolute HeapHigh;
       HeapEnd: Pointer = Pointer (High (PtrCard));
       FreeList: Pointer = nil;
       FreeZero: Pointer = nil;
       StackLimit: SystemWord = 0;
       HeapList: SystemWord = 0;
       HeapLimit: SystemWord = 1024;
       HeapBlock: SystemWord = 8192;
       HeapAllocFlags: SystemWord = 2;
       CmdShow: SystemInteger = 0;
       SaveInt00: Pointer = nil;
       SaveInt02: Pointer = nil;
       SaveInt0C: Pointer = nil;
       SaveInt0D: Pointer = nil;
       SaveInt1B: Pointer = nil;
       SaveInt21: Pointer = nil;
       SaveInt23: Pointer = nil;
       SaveInt24: Pointer = nil;
       SaveInt34: Pointer = nil;
       SaveInt35: Pointer = nil;
       SaveInt36: Pointer = nil;
       SaveInt37: Pointer = nil;
       SaveInt38: Pointer = nil;
       SaveInt39: Pointer = nil;
       SaveInt3A: Pointer = nil;
       SaveInt3B: Pointer = nil;
       SaveInt3C: Pointer = nil;
       SaveInt3D: Pointer = nil;
       SaveInt3E: Pointer = nil;
       SaveInt3F: Pointer = nil;
       SaveInt75: Pointer = nil;
       RealModeRegs: array [0 .. 49] of Byte =
         (0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
          0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
          0, 0, 0, 0, 0, 0, 0, 0);
     
     { Mostly useless BP compatible pointer functions }
     function  Ofs (const x): PtrWord;
     function  Seg (const x): PtrWord;
     function  Ptr (Seg, Ofs: PtrWord): Pointer;
     function  CSeg: PtrWord;
     function  DSeg: PtrWord;
     function  SSeg: PtrWord;
     function  SPtr: PtrWord;
     
     { Routines to handle BP's 6 byte `Real' type which is formatted like
       this:
     
       47                                                   0
       -|------- -------- -------- -------- --------|--------
        |                                           |
        +----------+                   +------------+
       47 Sign Bit |  8..46 Mantissa   | 0..7 Biased Exponent
     
       This format does not support infinities, NaNs and denormalized
       numbers. The first digit after the binary point is not stored and
       assumed to be 1. (This is called the normalized representation of
       a binary floating point number.)
     
       In GPC, this type is represented by the type `BPReal' which is
       binary compatible to BP's type, and can therefore be used in
       connection with binary files used by BP programs.
     
       The functions `RealToBPReal' and `BPRealToReal' convert between
       this type and GPC's `Real' type. Apart from that, `BPReal' should
       be treated as opaque.
     
       The variables `BPRealIgnoreOverflow' and `BPRealIgnoreUnderflow'
       determine what to do in the case of overflows and underflows. The
       default values are BP compatible. }
     
     var
       { Ignore overflows, and use the highest possible value instead. }
       BPRealIgnoreOverflow: Boolean = False;
     
       { Ignore underflows, and use 0 instead. This is BP's behaviour,
         but has the disadvantage of diminishing computation precision. }
       BPRealIgnoreUnderflow: Boolean = True;
     
     type
       BPRealInteral = Cardinal attribute (Size = 8);
       BPReal = packed record
         Format: packed array [1 .. 6] of BPRealInteral
       end;
     
     function RealToBPReal (r: Real) = BR: BPReal;
     function BPRealToReal (const BR: BPReal) = RealValue: Real;
     
     { Heap management stuff }
     
     const
       { Possible results for HeapError }
       HeapErrorRunError = 0;
       HeapErrorNil      = 1;
       HeapErrorRetry    = 2;
     
     var
       { If assigned to a function, it will be called when memory
         allocations do not find enough free memory. Its result
         determines if a run time error should be raised (the default),
         or nil should be returned, or the allocation should be retried
         (causing the routine to be called again if the allocation still
         doesn't succeed).
     
         Notes:
     
         - Returning nil can cause some routines of the RTS and units
           (shipped with GPC or third-party) to crash when they don't
           expect nil, so better don't use this mechanism, but rather
           CGetMem where needed.
     
         - Letting the allocation be retried, of course, only makes sense
           if the routine freed some memory before -- otherwise it will
           cause an infinite loop! So, a meaningful HeapError routine
           should dispose of some temporary objects, if available, and
           return HeapErrorRetry, and return HeapErrorRunError when no
           (more) of them are available. }
       HeapError: ^function (Size: SystemWord): SystemInteger = nil;
     
     { Just returns HeapErrorNil. When this function is assigned to
       HeapError, GetMem and New will return a nil pointer instead of
       causing a runtime error when the allocation fails. See the comment
       for HeapError above. }
     function  HeapErrorNilReturn (Size: SystemWord): SystemInteger;
     
     { Return the total free memory/biggest free memory block. Except
       under Win32 and DJGPP, these are expensive routines -- try to
       avoid them. Under Win32, MaxAvail returns the same as MemAvail, so
       don't rely on being able to allocate a block of memory as big as
       MaxAvail indicates. Generally it's preferable to not use these
       functions at all in order to do a safe allocation, but just try to
       allocate the memory needed using CGetMem, and check for a nil
       result. What makes these routines unrealiable is, e.g., that on
       multi-tasking systems, another process may allocate memory after
       you've called MemAvail/MaxAvail and before you get to do the next
       allocation. Also, please note that some systems over-commit
       virtual memory which may cause MemAvail to return a value larger
       than the actual (physical plus swap) memory available. Therefore,
       if you want to be "sure" (modulo the above restrictions) that the
       memory is actually available, use MaxAvail. }
     function  MemAvail: Cardinal;
     function  MaxAvail: Cardinal;
     
     { Delphi compatibility }
     
     function  CompToDouble (x: Comp): Double;
     function  DoubleToComp (x: Double): Comp;
     {$ifndef __BP_NO_ALLOCMEM__}
     function  AllocMemCount = Count: SystemInteger;
     function  AllocMemSize = Size: SizeType;
     {$endif}
     procedure Assert (Condition: Boolean);
     procedure DefaultAssertErrorProc (const Message, FileName: String;
       LineNumber: SystemInteger; ErrorAddr: Pointer);
     
     var
       AssertErrorProc: ^procedure (const Message, FileName: String;
       LineNumber: SystemInteger; ErrorAddr: Pointer) =
       @DefaultAssertErrorProc;
       NoErrMsg: Boolean = False;
     


Next: , Previous: System, Up: GPC Units

6.15.18 Some text file tricks

The following listing contains the interface of the TFDD unit.

This unit provides some tricks with text files, e.g. a “tee” file which causes everything written to it to be written to two other files.

     { Some text file tricks.
     
       Copyright (C) 2002-2006 Free Software Foundation, Inc.
     
       Author: Frank Heckenbach <frank@pascal.gnu.de>
     
       This file is part of GNU Pascal.
     
       GNU Pascal is free software; you can redistribute it and/or modify
       it under the terms of the GNU General Public License as published
       by the Free Software Foundation; either version 2, or (at your
       option) any later version.
     
       GNU Pascal is distributed in the hope that it will be useful, but
       WITHOUT ANY WARRANTY; without even the implied warranty of
       MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
       General Public License for more details.
     
       You should have received a copy of the GNU General Public License
       along with GNU Pascal; see the file COPYING. If not, write to the
       Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA
       02111-1307, USA.
     
       As a special exception, if you link this file with files compiled
       with a GNU compiler to produce an executable, this does not cause
       the resulting executable to be covered by the GNU General Public
       License. This exception does not however invalidate any other
       reasons why the executable file might be covered by the GNU
       General Public License. }
     
     {$gnu-pascal,I-}
     {$if __GPC_RELEASE__ < 20030412}
     {$error This unit requires GPC release 20030412 or newer.}
     {$endif}
     
     unit TFDD;
     
     interface
     
     uses GPC;
     
     { Write to multiple files. Everything written to Dest after calling
       this procedure will be written to both File1 and File2. Can be
       chained. }
     procedure MultiFileWrite (var Dest, File1, File2: AnyFile);
     


Next: , Previous: TFDD, Up: GPC Units

6.15.19 Trap runtime errors

The following listing contains the interface of the Trap unit.

This unit allows you to trap runtime errors, so a runtime error will not abort the program, but pass the control back to a point within the program. Use with care, and read the notes in the interface, please.

     { Trapping runtime errors
     
       The Trap unit allows you to trap runtime errors, so a runtime
       error will not abort the program, but pass the control back to a
       point within the program.
     
       The usage is simple. The TrapExec procedure can be called with a
       function (p) as an argument. p must take a Boolean argument. p
       will immediately be called with False given as its argument. When
       a runtime error would otherwise be caused while p is active, p
       will instead be called again with True as its argument. After p
       returns, runtime error trapping ends.
     
       When the program terminates (e.g. by reaching its end or by a Halt
       statement) and a runtime error was trapped during the run, Trap
       will set the ExitCode and ErrorAddr variables to indicate the
       trapped error.
     
       Notes:
     
       - After trapping a runtime error, your program might not be in a
         stable state. If the runtime error was a "minor" one (such as a
         range checking or arithmetic error), it should not be a problem.
         But if you, e.g., write a larger application and use Trap to
         prevent a sudden abort caused by an unexpected runtime error,
         you should make the program terminate regularly as soon as
         possible after a trapped error (perhaps by telling the user to
         save the data, then terminate the program and report the bug to
         you).
     
       - Since the trapping mechanism *jumps* back, it has all the
         negative effects that a (non-local!) `goto' can have! You should
         be aware of the consequences of all active procedures being
         terminated at an arbitrary point!
     
       - Nested traps are supported, i.e. you can call TrapExec again
         within a routine called by another TrapExec instance. Runtime
         errors trapped within the inner TrapExec invocation will be
         trapped by the inner TrapExec, while runtime errors trapped
         after its termination will be trapped by the outer TrapExec
         again.
     
       Copyright (C) 1996-2006 Free Software Foundation, Inc.
     
       Author: Frank Heckenbach <frank@pascal.gnu.de>
     
       This file is part of GNU Pascal.
     
       GNU Pascal is free software; you can redistribute it and/or modify
       it under the terms of the GNU General Public License as published
       by the Free Software Foundation; either version 2, or (at your
       option) any later version.
     
       GNU Pascal is distributed in the hope that it will be useful, but
       WITHOUT ANY WARRANTY; without even the implied warranty of
       MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
       General Public License for more details.
     
       You should have received a copy of the GNU General Public License
       along with GNU Pascal; see the file COPYING. If not, write to the
       Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA
       02111-1307, USA.
     
       As a special exception, if you link this file with files compiled
       with a GNU compiler to produce an executable, this does not cause
       the resulting executable to be covered by the GNU General Public
       License. This exception does not however invalidate any other
       reasons why the executable file might be covered by the GNU
       General Public License. }
     
     {$gnu-pascal,I-}
     {$if __GPC_RELEASE__ < 20030303}
     {$error This unit requires GPC release 20030303 or newer.}
     {$endif}
     
     unit Trap;
     
     interface
     
     uses GPC;
     
     var
       TrappedExitCode: Integer = 0;
       TrappedErrorAddr: Pointer = nil;
       TrappedErrorMessageString: TString = '';
     
     { Trap runtime errors. See the comment at the top. }
     procedure TrapExec (procedure p (Trapped: Boolean));
     
     { Forget about saved errors from the innermost TrapExec instance. }
     procedure TrapReset;
     


Next: , Previous: Trap, Up: GPC Units

6.15.20 BP compatibility: Turbo3

The following listing contains the interface of the Turbo3 unit.

This is a compatibility unit to BP's `Turbo3' compatibility unit to TP3. ;−) It is not meant to be used in any newly written code.

     { Turbo Pascal 3.0 compatibility unit
     
       Copyright (C) 1998-2006 Free Software Foundation, Inc.
     
       Author: Frank Heckenbach <frank@pascal.gnu.de>
     
       This file is part of GNU Pascal.
     
       GNU Pascal is free software; you can redistribute it and/or modify
       it under the terms of the GNU General Public License as published
       by the Free Software Foundation; either version 2, or (at your
       option) any later version.
     
       GNU Pascal is distributed in the hope that it will be useful, but
       WITHOUT ANY WARRANTY; without even the implied warranty of
       MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
       General Public License for more details.
     
       You should have received a copy of the GNU General Public License
       along with GNU Pascal; see the file COPYING. If not, write to the
       Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA
       02111-1307, USA.
     
       As a special exception, if you link this file with files compiled
       with a GNU compiler to produce an executable, this does not cause
       the resulting executable to be covered by the GNU General Public
       License. This exception does not however invalidate any other
       reasons why the executable file might be covered by the GNU
       General Public License. }
     
     {$gnu-pascal,I-}
     {$if __GPC_RELEASE__ < 20030412}
     {$error This unit requires GPC release 20030412 or newer.}
     {$endif}
     
     unit Turbo3;
     
     interface
     
     import GPC only (AssignTFDD);
            System (MemAvail => System_MemAvail,
                    MaxAvail => System_MaxAvail);
            CRT (LowVideo  => CRT_LowVideo,
                 HighVideo => CRT_HighVideo);
     
     var
       Kbd: Text;
       CBreak: Boolean absolute CheckBreak;
     
     procedure AssignKbd (var f: AnyFile);
     function  MemAvail: Integer;
     function  MaxAvail: Integer;
     function  LongFileSize (var f: AnyFile): Real;
     function  LongFilePos  (var f: AnyFile): Real;
     procedure LongSeek     (var f: AnyFile; aPosition: Real);
     procedure LowVideo;
     procedure HighVideo;
     


Previous: Turbo3, Up: GPC Units

6.15.21 BP compatibility: WinDos

The following listing contains the interface of the WinDos unit.

This is a portable implementation of most routines from BP's `WinDos' unit. A few routines that are Dos – or even IA32 real mode – specific, are only available if `__BP_UNPORTABLE_ROUTINES__' is defined, BP Incompatibilities.

The same functionality and much more is available in the Run Time System, Run Time System. The RTS routines usually have different names and/or easier and less limiting interfaces (e.g. `ReadDir' etc. vs. `FindFirst' etc.), and are often more efficient.

Therefore, using this unit is not recommended in newly written programs.

     { Mostly BP compatible portable WinDos unit
     
       This unit supports most, but not all, of the routines and
       declarations of BP's WinDos unit.
     
       Notes:
     
       - The procedures GetIntVec and SetIntVec are not supported since
         they make only sense for Dos real-mode programs (and GPC
         compiled programs do not run in real-mode, even on IA32 under
         Dos). The procedures Intr and MsDos are only supported under
         DJGPP if `__BP_UNPORTABLE_ROUTINES__' is defined (with the
         `-D__BP_UNPORTABLE_ROUTINES__' option). A few other routines are
         also only supported with this define, but on all platforms (but
         they are crude hacks, that's why they are not supported without
         this define).
     
       - The internal structure of file variables (TFileRec and TTextRec)
         is different in GPC. However, as far as TFDDs are concerned,
         there are other ways to achieve the same in GPC, see the GPC
         unit.
     
       Copyright (C) 1998-2006 Free Software Foundation, Inc.
     
       Author: Frank Heckenbach <frank@pascal.gnu.de>
     
       This file is part of GNU Pascal.
     
       GNU Pascal is free software; you can redistribute it and/or modify
       it under the terms of the GNU General Public License as published
       by the Free Software Foundation; either version 2, or (at your
       option) any later version.
     
       GNU Pascal is distributed in the hope that it will be useful, but
       WITHOUT ANY WARRANTY; without even the implied warranty of
       MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
       General Public License for more details.
     
       You should have received a copy of the GNU General Public License
       along with GNU Pascal; see the file COPYING. If not, write to the
       Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA
       02111-1307, USA.
     
       As a special exception, if you link this file with files compiled
       with a GNU compiler to produce an executable, this does not cause
       the resulting executable to be covered by the GNU General Public
       License. This exception does not however invalidate any other
       reasons why the executable file might be covered by the GNU
       General Public License. }
     
     {$gnu-pascal,I-,maximum-field-alignment 0}
     {$if __GPC_RELEASE__ < 20030412}
     {$error This unit requires GPC release 20030412 or newer.}
     {$endif}
     
     module WinDos;
     
     export WinDos = all (FCarry, FParity, FAuxiliary, FZero, FSign,
       FOverflow,
                          DosError, GetDate, GetTime, GetCBreak,
       SetCBreak,
                          GetVerify, SetVerify, DiskFree, DiskSize,
                          GetFAttr, SetFAttr, GetFTime, SetFTime,
                          UnpackTime, PackTime,
                          {$ifdef __BP_UNPORTABLE_ROUTINES__}
                          {$ifdef __GO32__}
                          Intr, MsDos,
                          {$endif}
                          DosVersion, SetDate, SetTime,
                          {$endif}
                          CStringGetEnv => GetEnvVar);
     
     import GPC (MaxLongInt => GPC_Orig_MaxLongInt);
            System;
            Dos (FindFirst => Dos_FindFirst,
                 FindNext  => Dos_FindNext,
                 FindClose => Dos_FindClose);
     
     const
       { File attribute constants }
       faReadOnly  = ReadOnly;
       faHidden    = Hidden;    { set for dot files except `.' and `..' }
       faSysFile   = SysFile;   { not supported }
       faVolumeID  = VolumeID;  { not supported }
       faDirectory = Directory;
       faArchive   = Archive;   { means: not executable }
       faAnyFile   = AnyFile;
     
       { Maximum file name component string lengths }
       fsPathName  = 79;
       fsDirectory = 67;
       fsFileName  = 8;
       fsExtension = 4;
     
       { FileSplit return flags }
       fcExtension = 1;
       fcFileName  = 2;
       fcDirectory = 4;
       fcWildcards = 8;
     
     type
       PTextBuf = ^TTextBuf;
       TTextBuf = TextBuf;
     
       { Search record used by FindFirst and FindNext }
       TSearchRec = record
         Fill: SearchRecFill;
         Attr: Byte8;
         Time, Size: LongInt;
         Name: {$ifdef __BP_TYPE_SIZES__}
               packed array [0 .. 12] of Char
               {$else}
               TStringBuf
               {$endif};
         Reserved: SearchRec
       end;
     
       { Date and time record used by PackTime and UnpackTime }
       TDateTime = DateTime;
     
       { 8086 CPU registers -- only used by the unportable Dos routines }
       TRegisters = Registers;
     
     { FindFirst and FindNext are quite inefficient since they emulate
       all the brain-dead Dos stuff. If at all possible, the standard
       routines OpenDir, ReadDir and CloseDir (in the GPC unit) should be
       used instead. }
     procedure FindFirst (Path: PChar; Attr: Word; var SR: TSearchRec);
     procedure FindNext  (var SR: TSearchRec);
     procedure FindClose (var SR: TSearchRec);
     function  FileSearch (Dest, FileName, List: PChar): PChar;
     function  FileExpand (Dest, FileName: PChar): PChar;
     function  FileSplit (Path, Dir, BaseName, Ext: PChar) = Res: Word;
     function  GetCurDir (Dir: PChar; Drive: Byte): PChar;
     procedure SetCurDir (Dir: PChar);
     procedure CreateDir (Dir: PChar);
     procedure RemoveDir (Dir: PChar);
     function  GetArgCount: Integer;
     function  GetArgStr (Dest: PChar; ArgIndex: Integer; MaxLen: Word):
       PChar;
     


Next: , Previous: Programming, Up: Top

7 A QuickStart Guide from Borland Pascal to GNU Pascal.

This chapter is intended to be a QuickStart guide for programmers who are familiar with Borland Pascal.

Throughout the manual, we talk of “Borland Pascal” or “BP” for short, to refer to Borland Pascal version 7 for Dos protected mode. Other versions of Borland Pascal and Turbo Pascall don't differ too much, but this one was the very last Dos version Borland has published, so in most if not all cases, you can safely substitute the version you're familiar with.

“Borland Pascal” and “Turbo Pascal” are registered trademarks of Borland Inc.


Next: , Up: Borland Pascal

7.1 BP Compatibility

GNU Pascal (GPC) is compatible to version 7 of Borland Pascal (BP) to a large extent and comes with portable replacements of the BP standard units.

However, BP is a 16-bit compiler while GPC is a 32/64-bit compiler, so the size of the `Integer' type, for instance, is 16 bits in BP, but at least 32 bits in GPC. If a BP program has been designed with portability in mind from the ground up, it may work with GPC without any change. Programs which rely on byte order, on the internals or sizes of data types or which use unportable things like interrupts and assembler code, will need to be changed. The following section lists the possible problems with solutions.

The GPC Run Time System (RTS) is fairly complete, and you can use all libraries written for GNU C from GNU Pascal, so there is much less need to use unportable constructs than there was in BP. (For example, BP's Turbo Vision library uses assembler to call a local procedure through a pointer. With GPC you can do this in Pascal just as with global procedures.) Please do not throw away the advantage of full portability by sticking to those workarounds.

We have successfully ported real-world projects (with several 10000s of lines) from BP to GPC, so this is possible for you, too.


Next: , Previous: BP Compatibility, Up: Borland Pascal

7.2 BP Incompatibilities

This sections lists the remaining incompatibilities of GPC to BP, and the problems you might encounter when porting BP programs from 16-bit Dos to other platforms, and gives solutions for them.

By incompatibilites we mean problems that can arise when trying to compile a valid BP program with GPC. Of course, there are many features in GPC that BP doesn't know, but we call them extensions unless they can break valid BP programs, so they are not mentioned here. The subsequent sections of the `Borland Pascal' chapter mention a number of useful extensions that you might want to know about but which will not break your BP code.

Some of the differences can be “overcome” by command-line switches. As a summary:

     --borland-pascal -w --uses=System -D__BP_TYPE_SIZES__ --pack-struct
     -D__BP_RANDOM__ -D__BP_UNPORTABLE_ROUTINES__ -D__BP_PARAMSTR_0__

But please read the following notes, and don't use these switches indiscriminately when not necessary. There are reasons why they are not GPC's defaults.


Next: , Up: BP Incompatibilities

7.2.1 String type

GPC's internal string format (Extended Pascal string schema) is different from BP's. BP compatible short strings will be implemented in GPC soon, but in the meantime, you'll have to live with the difference. In general, GPC's format has many advantages (no length limit of 255 characters, constant and reference parameters always know about their capacity, etc.), but you will see differences if you:


Next: , Previous: String type, Up: BP Incompatibilities

7.2.2 Qualified identifiers

GPC supports qualified identifiers, liek BP does. (In addition, it also supports Extended Pascal style qualified identifiers which behave a little differently for units and modules imported with `import' rather than `uses'.)


Next: , Previous: Qualified identifiers, Up: BP Incompatibilities

7.2.3 Assembler

GPC's inline assembler is not compatible to BP's. It uses AT&T syntax, supports a large variety of processors and works together with GPC's optimizer. So, either convert your inline assembly to AT&T syntax, or (usually better) to Pascal, or put it into an external file which you can assemble with your favourite (32 bit) assembler. A tutorial for using the GPC inline assembler is available at
http://www.gnu-pascal.de/contrib/misc/gpcasm.zip

Since many things you usually do with assembler in BP are provided by GPC's Run Time System (RTS), you will not need the inline assembler as often as in BP. (See Portability hints.)

The same applies to BP's `inline' directive for hand-written machine code. GPC's `inline' directive works for Pascal routines (see Miscellaneous), so you'll have to convert any hand-written machine code to Pascal (and thereby make it more readable, portable and easier to maintain while still getting the performance of inline code).


Next: , Previous: Assembler, Up: BP Incompatibilities

7.2.4 Move; FillChar

GPC supports `Move' and `FillChar', and they're fully BP compatible. However, some data structures have different internal formats which may become relevant when using these procedures. E.g., using `Move' on file variables does not work in GPC (there are reasons why assigning file variables with `:=' is not allowed in Pascal, and circumventing this restriction with `Move' is not a good idea). For other examples, see String type, Real type, and Endianness assumptions.


Next: , Previous: Move; FillChar, Up: BP Incompatibilities

7.2.5 Real type

GPC does not support BP's 6-byte `Real' type. It supports `Single', `Double' and `Extended' which, at least on the IA32 and some other processors, are compatible to BP.

For BP's 6-byte `Real' type, GPC's `System' unit provides an emulation, called `BPReal', as well as conversion routines to GPC's `Real' type (which is the same as `Double'), called `RealToBPReal' and `BPRealToReal'. You'll probably only need them when reading or writing binary files containing values of the BP 6-byte real type. There are no operators (e.g., `+') available for `BPReal', but since GPC supports operator overloading, you could define them yourself (e.g., convert to `Real', do the operation, and convert back). Needless to say that this is very inefficient and should not be done for any serious computations. Better convert your data after reading them from the file and before writing them back, or simply convert your data files once (the other types are more efficient even with BP on any non-prehistoric processor, anyway).


Next: , Previous: Real type, Up: BP Incompatibilities

7.2.6 Graph unit

A mostly BP compatible `Graph' unit exists as part of the `GRX' package. It is known to work under DJGPP, Cygwin, mingw, Linux/IA32 with svgalib, and should work under any Unix system with X11 (tested under Linux, Solaris, AIX, etc.).

There is a small difference in the color numbering, but it should be easy to work-around: You can't assume, e.g., that color 1 is always blue, and 2 is green, etc. On a system with 15 or more bits of color depth (i.e., 32768 or more colors, which most PCs today have), they will all be very dark shades of blue. This is not really a bug, but simply a property of modern high-color modes (whereas BP's `Graph' unit was only designed for 16 and 256 color modes).

However, the names `Blue', `Green' etc. stand for the correct colors in the `Graph' unit of GRX. They are no constants, but functions (because the color depth is in general not known until runtime), so you can't use them in contexts where constants are expected. Also, they might conflict with the identifiers of the `CRT' unit if you use both units at the same time. If you want to use computed color values in the range 0 ... 15, you can translate them to the correct colors using the `EGAColor' function.


Next: , Previous: Graph unit, Up: BP Incompatibilities

7.2.7 OOP units

The OOP stuff (Turbo Vision etc.) is not yet completed, but work on several projects is underway. If you want information about the current status or access to development source, please contact the GPC mailing list.


Next: , Previous: OOP units, Up: BP Incompatibilities

7.2.8 Keep; GetIntVec; SetIntVec

The routines `Keep', `GetIntVec' and `SetIntVec' in the `Dos' unit do not even make sense on DJGPP (32 bit Dos extender). If your program uses these, it is either a low-level Dos utility for which porting to a 32 bit environment might cause bigger problems (because the internal issues of DPMI become relevant which are usually hidden by DJGPP), or it installs interrupt handlers which will have to be thought about more carefully because of things like locking memory, knowing about and handling the differences between real and protected mode interrupts, etc. For these kinds of things, we refer you to the DJGPP FAQ (see DJGPP FAQ).


Next: , Previous: Keep; GetIntVec; SetIntVec, Up: BP Incompatibilities

7.2.9 TFDDs

The internal structure of file variables (`FileRec' and `TextRec' in BP's `Dos' unit and `TFileRec' and `TTextRec' in BP's `WinDos' unit) is different in GPC. However, as far as Text File Device Drivers (TFDDs) are concerned, GPC offers a more powerful mechanism. Please see the RTS reference (see Run Time System), under `AssignTFDD'.


Next: , Previous: TFDDs, Up: BP Incompatibilities

7.2.10 Mem; Port; Ptr; Seg; Ofs; PrefixSeg; etc.

Those few routines in the `System' unit that deal with segmented pointers (e.g., `Ptr') are emulated in such a way that such ugly BP constructs like

     PInteger (Ptr (Seg (a), Ofs (a) + 6 * SizeOf (Integer)))^ = 42

work in GPC, but they do not provide access to absolute memory addresses. Neither do `absolute' variables (which take a simple address in the program's address space in GPC, rather than a segmented address), and the `Mem' and `Port' arrays don't exist in GPC.

As a replacement for `Port' on IA32 processors, you can use the routines provided in the `Ports' unit, Ports. If you want to access absolute memory addresses in the first megabyte under DJGPP, you can't do this with normal pointers because DJGPP programs run in a protected memory environment, unless you use a dirty trick called near pointer hack. Please see the DJGPP FAQ (see DJGPP FAQ) for this and for other ways.

For similar reasons, the variable `PrefixSeg' in the `System' unit is not supported. Apart from TSRs, its only meaningful use in BP might be the setting of environment variables. GPC provides the `SetEnv' and `UnSetEnv' procedures for this purpose which you can use instead of any BP equivalents based on `PrefixSeg'. (However note that they will modify the program's own and its childs' environment, not its parent's environment. This is a property – most people call it a feature – of the environments, including DJGPP, that GPC compiled programs run in.)


Next: , Previous: Mem; Port; Ptr; Seg; Ofs; PrefixSeg; etc., Up: BP Incompatibilities

7.2.11 Endianness assumptions

GPC also runs on big-endian systems (see Endianness). This is, of course, a feature of GPC, but might affect your programs when running on a big-endian system if they make assumptions about endianness, e.g., by using type casts (or `absolute' declarations or variant records misused as type casts) in certain ways. Please see the demo program absdemo.pas for an example and how to solve it.

Endianness is also relevant (the more common case) when exchanging data between different machines, e.g. via binary files or over a network. Since the latter is not easily possible in BP, and the techniques to solve the problems are mostly the same as for files, we concentrate on files here.

First, you have to choose the endianness to use for the file. Most known data formats have a specified endianness (usually that of the processor on which the format was originally created). If you define your own binary data format, you're free to choose the endianness to use.

Then, when reading or writing values larger than one byte from/to the file, you have to convert them. GPC's Run Time System supports this by some routines. E.g., you can read an array from a little-endian file with the procedure `BlockReadLittleEndian', or write one to a big-endian file with `BlockWriteBigEndian'. Note: The endianness in the procedure names refers to the file, not the system – the routines know about the endianness of the system they run on, but you have to tell them the endianness of the file to use. This means you do not have to (and must not) use an `ifdef' to use the version matching the system's endianness.

When reading or writing records or other more complicated structures, either read/write them field by field using `BlockReadBigEndian' etc., or read/write them with the regular `BlockRead' and `BlockWrite' procedures and convert each field after reading or before writing using procedures like `ConvertFromBigEndian' or `ConvertToLittleEndian' (but remember, when writing, to undo the conversion afterwards, if you want to keep using the data – this is not necessary with `BlockWriteLittleEndian' etc.).

Especially for strings, there are ready-made procedures like `ReadStringBigEndian' or `WriteStringLittleEndian' which will read/write the length as a 64 bit value (much space for really long strings :−) in the given endianness, followed by the characters (which have no endianness problem).

All these routines are described in detail in the RTS reference (see Run Time System), under `endianness'. The demo program endiandemo.pas contains an example on how to use these routines.


Next: , Previous: Endianness assumptions, Up: BP Incompatibilities

7.2.12 - -borland-pascal - disable GPC extensions

GPC warns about some BP constructs which are especially “dirty”, like misusing typed constants as initialized variables. GPC also supports some features that may conflict with BP code, like macros. The command line option `--borland-pascal' disables both, so you might want to use it for a first attempt to compile your BP code under GPC. However, we suggest you try compiling without this switch and fixing any resulting problems as soon as you've become acquainted with GPC.


Next: , Previous: - -borland-pascal - disable GPC extensions, Up: BP Incompatibilities

7.2.13 -w - disable all warnings

Even in `--borland-pascal' mode, GPC may warn about some dangerous things. To disable all warnings, you can use the `-w' option (note: lower-case `w'!). This is not recommended at all, but you may consider it more BP compatible ...


Next: , Previous: -w - disable all warnings, Up: BP Incompatibilities

7.2.14 - -uses=System - Swap; HeapError; etc.

A few exotic BP routines and declarations (e.g., `Swap' and `HeapError') are contained in a `System' unit, System, which GPC (unlike BP) does not automatically use in each program. To use it, you can add a `uses System;' clause to your program. If you don't want to change your code, the command line option `--uses=System' will do the same.


Next: , Previous: - -uses=System - Swap; HeapError; etc., Up: BP Incompatibilities

7.2.15 -D__BP_TYPE_SIZES__ - small integer types etc.

Since GPC runs on 32 and 64 bit platforms, integer types have larger sizes than in BP. However, if you use the `System' unit (see - -uses=System - Swap; HeapError; etc.) and define the symbol `__BP_TYPE_SIZES__' (by giving `-D__BP_TYPE_SIZES__' on the command line), it will redeclare the types to the sizes used by BP. This is less efficient and more limiting, but might be necessary if your program relies on the exact type sizes.


Next: , Previous: -D__BP_TYPE_SIZES__ - small integer types etc., Up: BP Incompatibilities

7.2.16 - -pack-struct - disable structure alignment

GPC by default aligns fields of records and arrays suitably for higher performance, while BP doesn't. If you don't want the alignment (e.g., because the program relies on the internal format of your structures), give the `--pack-struct' option.


Next: , Previous: - -pack-struct - disable structure alignment, Up: BP Incompatibilities

7.2.17 -D__BP_RANDOM__ - BP compatible pseudo random number generator

GPC uses a more elaborate pseudo random number generator than BP does. Using the `Random' and `Randomize' functions works the same way, but there is no `RandSeed' variable (but a `SeedRandom' procedure). However, if you use the `System' unit (see - -uses=System - Swap; HeapError; etc.) and define the symbol `__BP_RANDOM__' (by giving `-D__BP_RANDOM__' on the command line), it will provide a 100% BP compatible pseudo random number generator, including the `RandSeed' variable, which will produce exactly the same sequence of pseudo random numbers that BP's pseudo random number generator does. Even the `Randomize' function will then behave exactly like in BP.


Next: , Previous: -D__BP_RANDOM__ - BP compatible pseudo random number generator, Up: BP Incompatibilities

7.2.18 -D__BP_UNPORTABLE_ROUTINES__ - Intr; DosVersion; etc.

A few more routines in the `Dos' and `WinDos' units besides the ones mentioned under Keep; GetIntVec; SetIntVec, like `Intr' or `DosVersion', are meaningless on non-Dos systems. By default, the `Dos' unit does not provide these routines (it only provides those that are meaningful on all systems, which are most of its routines, including the most commonly used ones). If you need the unportable ones, you get them by using the `System' unit (see - -uses=System - Swap; HeapError; etc.) and defining the symbol `__BP_UNPORTABLE_ROUTINES__' (by giving `-D__BP_UNPORTABLE_ROUTINES__' on the command line). If you use `Intr' or `MsDos', your program will only compile under DJGPP then. Other routines, e.g. `DosVersion' are emulated quite roughly on other systems. Please see the notes in the `Dos' unit (see Dos) for details.


Previous: -D__BP_UNPORTABLE_ROUTINES__ - Intr; DosVersion; etc., Up: BP Incompatibilities

7.2.19 -D__BP_PARAMSTR_0__ - BP compatible ParamStr (0) behaviour

In BP (or under Dos), `ParamStr (0)' always contains the full path of the current executable. Under GPC, by default it contains what was passed by the caller as the 0th argument – which is often the name of the executable, but that's merely a convention, and it usually does not include the path.

If you use the `System' unit (see - -uses=System - Swap; HeapError; etc.) and define the symbol `__BP_PARAMSTR_0__' (by giving `-D__BP_PARAMSTR_0__' on the command line), it will change the value of `ParamStr (0)' to that of `ExecutablePath', overwriting the value actually passed by the caller, to imitate BP's/Dos's behaviour. However note: On most systems, `ExecutablePath' is not guaranteed to return the full path, so defining this symbol doesn't change anything. In general, you cannot expect to find the full executable path, so better don't even try it, or your program will (at best) run on some systems. For most cases where BP programs access their own executable, there are cleaner alternatives available.


Next: , Previous: BP Incompatibilities, Up: Borland Pascal

7.3 IDE versus command line

On the Dos (DJGPP) and Linux platforms, you can use RHIDE for GNU Pascal; check the subdirectories of your DJGPP distribution.

Unfortunately, there is no IDE which would run on all platforms. We are working on it, but this will take some time. Please be patient – or offer your help!

Without an IDE, the GNU Pascal Compiler, GPC, is called about like the command-line version of the Borland Pascal Compiler, BPC. Edit your source file(s) with your favorite ASCII editor, then call GNU Pascal with a command line like

     C:\GNU-PAS> gpc hello.pas -o hello.exe

on your Dos or OS/2 box or

     myhost:/home/joe/gnu-pascal> gpc hello.pas -o hello

on your Unix (or Unix-compatible) system.

Don't omit the .pas suffix: GPC is a common interface for a Pascal compiler, a C, ObjC and C++ compiler, an assembler, a linker, and perhaps an Ada and a FORTRAN compiler. From the extension of your source file GPC figures out which compiler to run. GPC recognizes Pascal sources by the extension .pas, .p, .pp or .dpr.

The -o is a command line option which tells GPC how the executable has to be named. If not given, the executable will be called `a.out' (Unix) or `a.exe' (Dos). However, you can use the `--executable-file-name' to tell GPC to always call the executable like the source (with the extension removed under Unix and changed to `.exe' under Dos).

Note that GPC is case-sensitive concerning file names and options, so it will not work if you type

     C:\GNU-PAS> GPC HELLO.PAS -O HELLO.EXE

GPC is a very quiet compiler and doesn't print anything on the screen unless you request it or there is an error. If you want to see what is going on, invoke GPC with additional options:

     -Q            "don't be quiet"  (or: Quassel-Modus in German)

(with capital `Q'!) means that GPC prints out the names of procedures and functions it processes, and

     --verbose

or abbreviated

     -v

means that GPC informs you about the stages of compilation, i.e. preprocessing, compiling, assembling, and linking.

One example (this time for OS/2):

     [C:\GNU-Pascal] gpc --verbose -Q hello.pas

Throughout this chapter, we will tell you about a lot of command-line switches. They are all invoked this way.

After compilation, there will be an executable hello file in the current directory. (hello.exe on Dos or OS/2.) Just run it and enjoy. If you're new to Unix, please note that the current directory is not on the PATH in most installations, so you might have to run your program as `./hello'. This also helps to avoid name conflicts with other programs. Such conflicts are especially common with the program name `test' which happens to be a standard utility under Unix that does not print any output. If you call your program `test.pas', compile it, and then invoke `test', you will usually not run your program, but the utility which leads to mysterious problems. So, invoke your program as `./test' or, better yet, avoid the name `test' for your programs.

If there are compilation errors, GNU Pascal will not stop compilation after the first one – as Borland Pascal does – but try to catch all errors in one compilation. If you get more error messages than your screen can hold, you can catch them in a file (e.g. gpc.out) or pipe them to a program like `more' in the following way:

     gpc hello.pas 2> gpc.out

This works with OS/2 and any bash-like shell under Unix; for Dos you must get a replacement for command.com which supports this kind of redirection, or use the `redir' utility (see also the DJGPP FAQ, DJGPP FAQ.):

     C:\GNU-PAS> redir -eo gpc hello.pas -o hello.exe | more

You can also use Borland's IDE for GNU Pascal on the Dos platform: Install the GNU Pascal Compiler in the Tools menu (via Options/Tools).

     Name:       GNU Pascal
     Path:       gpc
     Arguments:  $SAVE ALL --executable-file-name $NAME($EDNAME).pas
     HotKey:     Shift+F9

Note once more that GPC is case-sensitive, so it is important to specify .pas instead of the .PAS Borland Pascal would append otherwise!

You can include more command-line arguments to GNU Pascal (e.g. `--automake'; see below) as you will learn more about them.

Since Borland Pascal will try to recompile your program if you use its Run menu function, you will need another tool to run your program:

     Name:       Run Program
     Path:       command.com
     Arguments:  /c $NAME($EDNAME)
     HotKey:     Shift+F10


Next: , Previous: IDE versus command line, Up: Borland Pascal

7.4 Comments

GPC supports comments surrounded by `{ }' and `(* *)', just like BP does. According to the ISO 7185 and ISO 10206 standards, Pascal allows comments opened with (* and closed with }. Borland Pascal does not support such mixed comments, so you might have sources where passages containing comments are “commented out” using the other kind of comment delimiters. GPC's default behaviour is (like BP) not to allow mixed comments, so you don't need to worry about this. However, if you happen to like mixed comments, you can turn them on either by a command-line option, or by a compiler directive:

     --mixed-comments     {$mixed-comments}    (*$mixed-comments*)

GPC supports nested comments (e.g., `{ foo { bar } baz }'), but they are disabled by default (compatible to BP which doesn't know nested comments at all). You can enable them with the option `--nested-comments' (or the equivalent compiler directive)

GPC also supports Delphi style comments starting with `//' and extending until the end of the line. This comment style is activated by default unless one of the `--classic-pascal', `--extended-pascal', `--object-pascal' or `--borland-pascal' dialect options is given. You can turn them on or off with the `--[no-]delphi-comments' option.


Next: , Previous: Comments, Up: Borland Pascal

7.5 BP Compatible Compiler Directives

All of BP's one-letter compiler directives (except H, P, Q, R, V) are supported by GPC, though some of them are ignored because they are not necessary under GPC. Besides, GPC supports a lot more directives. For an overview, see Compiler Directives.


Next: , Previous: BP Compatible Compiler Directives, Up: Borland Pascal

7.6 Units, GPI files and Automake

You can use units in the same way as in Borland Pascal. However, there are some additional features.

Concerning the syntax of a unit, you can, if you want, use Extended Pascal syntax to specify a unit initializer, i.e., instead of writing

     begin
       ...
     end.

at the end of the unit, you can get the same result with

     to begin do
       begin
         ...
       end;

and there also exists

     to end do
       begin
         ...
       end;

which specifies a finalization routine. You can use this instead of Borland Pascal's exit procedures, but for compatibility, the included `System' unit also provides the `ExitProc' variable. The `to begin do' and/or `to end do' parts must be followed by the final `end.'. See Modules, for information about Extended Pascal modules, an alternative to units.

When GPC compiles a unit, it produces two files: an .o object file (compatible with other GNU compilers such as GNU C) plus a .gpi file which describes the interface.

If you are interested in the internal format of GPI file, see GPI files.

If you want to compile a program that uses units, you must “make” the project. (This is the command-line switch `-M' or the IDE keystroke `F9' in BP.) For this purpose, GPC provides the command-line switch `--automake':

     gpc --automake hello.pas

If you want to force everything to be rebuilt rather than only recompile changed files (`-B' or “build” in BP), use `--autobuild' instead of `--automake':

     gpc --autobuild hello.pas

For more information about the automake mechanism, see Automake.

If you do not want to use the automake mechanism for whatever reason, you can also compile every unit manually and then link everything together.

GPC does not automatically recognize that something is a unit and cannot be linked; you have to tell this by a command line switch:

     -c            only compile, don't link.

(If you omit this switch when compiling a unit, you only get a linker error message `undefined reference to `main''. Nothing serious.)

For example, to compile two units, use:

     gpc -c myunit1.pas myunit2.pas

When you have compiled all units, you can compile a program that uses them without using `--automake':

     gpc hello.pas

However, using `--automake' is recommended, since it will recompile units that were modified.

You could also specify the program and the units in one command line:

     gpc hello.pas myunit1.pas myunit2.pas

One of the purposes of writing units is to compile them separately. However, GNU Pascal allows you to have one or more units in the same source file (producing only one .o file but separate .gpi files). You even can have a program and one or more units in one source file; in this case, no .o file is produced at all.


Next: , Previous: Units; GPI files and Automake, Up: Borland Pascal

7.7 Optimization

GNU Pascal is a 32/64 bit compiler with excellent optimization algorithms (which are identically the same as those of GNU C). There are six optimization levels, specified by the command line options `-O', `-O2', ..., `-O6'.

One example:

     program OptimizationDemo;
     
     procedure Foo;
     var
       A, B: Integer;
     begin
       A := 3;
       B := 4;
       WriteLn (A + B)
     end;
     
     begin
       Foo
     end.

When GNU Pascal compiles this program with optimization (`-O3'), it recognizes that the argument to `WriteLn' is the constant 7 – and optimizes away the variables A and B. If the variables were global, they would not be optimized away because they might be accessed from other places, but the constant 7 would still be optimized.

For more about optimization, see the GNU C documentation.


Next: , Previous: Optimization, Up: Borland Pascal

7.8 Debugging

The command line option `-g' specifies generation of debugging information for GDB, the GNU debugger. GDB comes with its own documentation. Currently, GDB does not understand Pascal syntax, so you should be familiar with C expressions if you want to use it.

See also “Notes for debugging” in the “Programming” chapter; see Notes for Debugging.

Sometimes it is nice to have a look at the assembler output of the compiler. You can do this in a debugger or disassembler (which is the only way to do it in BP), but you can also tell GPC to produce assembler code directly: When you specify the -S command line option, GPC produces an .s file instead of an .o file. The .s file contains assembler source for your program. More about this in the next section.


Next: , Previous: Debugging, Up: Borland Pascal

7.9 Objects

Objects in the Borland Pascal 7.0 notation are implemented into GNU Pascal with the following differences:


Next: , Previous: Objects, Up: Borland Pascal

7.10 Strings in BP and GPC

Strings are “Schema types” in GNU Pascal which is something more advanced than Borland-style strings. For variables, you cannot specify just String as a type like in Borland Pascal; for parameters and pointer types you can. There is no 255 characters length limit. According to Extended Pascal, the maximum string length must be in (parentheses); GNU Pascal accepts [brackets], too, however, like BP.

For more about strings and schema types see Schema Types.

GPC supports Borland Pascal's string handling functions and some more (see String Operations):

Borland Pascal GNU Pascal
Length Length
Pos Pos, Index (1)
Str Str, WriteStr (1) (2)
Val Val, ReadStr (2)
Copy Copy, SubStr, MyStr[2 .. 7] (3)
Insert Insert
Delete Delete
MyStr[0] := #7 SetLength (MyStr, 7)
=, <>, <, <=, >, >= =, <>, <, <=, >, >= (4)
EQ, NE, LT, LE, GT, GE
n/a Trim

Notes:

(1) The order of parameters of the Extended Pascal routines (`Index', `WriteStr') is different from the Borland Pascal routines.

(2) `ReadStr' and `WriteStr' allow an arbitrary number of arguments, and the arguments are not limited to numbers. `WriteStr' also allows comfortable formatting like `WriteLn' does, e.g. `WriteStr (Dest, Foo : 20, Bar, 1/3 : 10 : 2)'.

(3) `SubStr' reports a runtime error if the requested substring does not fit in the given string, `Copy' does not (like in BP).

(4) By default, the string operators behave like in BP. However, if you use the option `--no-exact-compare-strings' or `--extended-pascal', they ignore differences of trailing blanks, so, e.g., `'foo'' and `'foo '' are considered equal. The corresponding functions (`EQ', ...) always do exact comparisons.


Next: , Previous: Strings in BP and GPC, Up: Borland Pascal

7.11 Typed Constants

GNU Pascal supports Borland Pascal's “typed constants” but also Extended Pascal's initialized variables:

     var
       x: Integer value 7;

or

     var
       x: Integer = 7;

When a typed constant is misused as an initialized variable, a warning is given unless you specify `--borland-pascal'.

When you want a local variable to preserve its value, define it as `static' instead of using a typed constant. Typed constants also become static automatically for Borland Pascal compatibility, but it's better not to rely on this “feature” in new programs. Initialized variables do not become static automatically.

     program StaticDemo;
     
     procedure Foo;
     { x keeps its value between two calls to this procedure }
     var
       x: Integer = 0; attribute (static);
     begin
       WriteLn (x);
       Inc (x)
     end;
     
     begin
       Foo;
       Foo;
       Foo;
     end.

For records and arrays, GPC supports both BP style and Extended Pascal style initializers. When you initialize a record, you may omit the field names. When you initialize an array, you may provide indices with a :. However, this additional information is ignored completely, so perhaps it's best for the moment to only provide the values ...

     program BPInitVarDemo;
     const
       A: Integer = 7;
       B: array [1 .. 3] of Char = ('F', 'o', 'o');
       C: array [1 .. 3] of Char = 'Bar';
       Foo: record
         x, y: Integer;
       end = (x: 3; y: 4);
     begin
     end.


Next: , Previous: Typed Constants, Up: Borland Pascal

7.12 Bit, Byte and Memory Manipulation

The bitwise operators `shl', `shr', `and', `or', `xor' and `not' work in GNU Pascal like in Borland Pascal. As an extension, you can use them as procedures, for example

     program AndProcedureDemo;
     var x: Integer;
     begin
       and (x, $0000ffff);
     end.

as an alternative to

     program AndOperatorDemo;
     var x: Integer;
     begin
       x := x and $0000ffff;
     end.

GPC accepts the BP style notation `$abcd' for hexadecimal numbers, but you also can use Extended Pascal notation:

     program EPBaseDemo;
     const
       Binary =  2#11111111;
       Octal  =  8#177;
       Hex    = 16#ff;
     begin
     end.

and so on up to a basis of 36. Of course, you can mix the notations as you like, e.g.:

     program BPEPBaseDemo;
     begin
       WriteLn ($cafe = 2#1100101011111110)
     end.

`Inc' and `Dec' are implemented like in Borland Pascal. `Pred' and `Succ' are generalized according to Extended Pascal and can have a second (optional) parameter:

     procedure SuccDemo;
     var a: Integer = 42;
     begin
       a := Succ (a, 5);
       WriteLn (a) { 47 }
     end.

BP style `absolute' variables work in the context of overloading other variables as well as in the context of specifying an absolute address, but the latter is highly unportable and not very useful even in Dos protected mode.

     program BPAbsoluteDemo;
     
     type
       TString = String (80);
       TTypeChoice = (t_Integer, t_Char, t_String);
     
     { @@ WARNING: BAD STYLE! }
     procedure ReadVar (var x: Void; TypeChoice: TTypeChoice);
     var
       xInt: Integer absolute x;
       xChar: Char absolute x;
       xStr: TString absolute x;
     begin
       case TypeChoice of
         t_Integer: ReadLn (xInt);
         t_Char   : ReadLn (xChar);
         t_String : ReadLn (xStr);
       end
     end;
     
     var
       i: Integer;
       c: Char;
       s: TString;
     
     begin
       ReadVar (i, t_Integer);
       ReadVar (c, t_Char);
       ReadVar (s, t_String);
       WriteLn (i, ' ', c, ' ', s)
     end.

GNU Pascal knows Borland Pascal's procedures FillChar and Move. However, their use can be dangerous because it often makes implicit unportable assumptions about type sizes, endianness, internal structures or similar things. Therefore, avoid them whenever possible. E.g., if you want to clear an array of strings, don't `FillChar' the whole array with zeros (this would overwrite the Schema discriminants, see Strings), but rather use a `for' loop to assign the empty string to each string. In fact, this is also more efficient than `FillChar', since it only has to set the length field of each string to zero.


Next: , Previous: Bit; Byte and Memory Manipulation, Up: Borland Pascal

7.13 User-defined Operators in GPC

GNU Pascal allows the user to define operators according to the Pascal-SC syntax:

     program PXSCOperatorDemo;
     
     type
       Point = record
         x, y: Real;
       end;
     
     operator + (a, b: Point) c: Point;
     begin
       c.x := a.x + b.x;
       c.y := a.y + b.y;
     end;
     
     var
       a, b, c: Point = (42, 0.5);
     
     begin
       c := a + b
     end.

The Pascal-SC operators `+>', `+<', etc. for exact numerical calculations are not implemented, but you can define them.


Next: , Previous: User-defined Operators in GPC, Up: Borland Pascal

7.14 Data Types in BP and GPC


Next: , Previous: Data Types in BP and GPC, Up: Borland Pascal

7.15 BP Procedural Types

In addition to BP's procedural types, GNU Pascal has pointers to procedures:

     type
       FuncPtr = ^function (Real): Real;

The differences between procedure pointers and procedural types are only syntactical:

One can use both kinds in the same program, of course, though it is recommended to stick to one kind throughout to avoid maximum confusion.

GNU Pascal also supports Standard Pascal's procedural parameters (see Special Parameters).

Furthermore, GNU Pascal allows you to call even local procedures through procedural pointers, variables or parameters without reverting to any dirty tricks such as assembler (which is necessary in BP).

The differences between the various kinds of procedural types, pointers and parameters are demonstrated in the demo program procvardemo.pas. An example for calling local routines through procedural parameters can be found in the demo program iteratordemo.pas.


Next: , Previous: BP Procedural Types, Up: Borland Pascal

7.16 Files


Next: , Previous: Files, Up: Borland Pascal

7.17 Built-in Constants


Next: , Previous: Built-in Constants, Up: Borland Pascal

7.18 Built-in Operators in BP and GPC

Besides the operators found in Borland Pascal, GNU Pascal supports the following operators:


Next: , Previous: Built-in Operators in BP and GPC, Up: Borland Pascal

7.19 Built-in Procedures and Functions


Next: , Previous: Built-in Procedures and Functions, Up: Borland Pascal

7.20 Special Parameters


Next: , Previous: Special Parameters, Up: Borland Pascal

7.21 Miscellaneous


Next: , Previous: Miscellaneous, Up: Borland Pascal

7.22 BP and Extended Pascal

Pascal is a well-known programming language and hardly needs to be described here. Note, however, that there is a large difference between the language used by the BP compiler and the Pascal Standards.

Extended Pascal is a standardized language based on the original Standard Pascal, but with significant extensions. Unfortunately, Borland Pascal does not conform to any of the Pascal standards. Writing a program that both complies to Extended Pascal (or even Standard Pascal) and compiles with BP is almost impossible for any non-trivial task.

On the other hand, BP has some nice features that make it very powerful in the environments in which it runs. However, some of those features are of little use on non-Dos systems and would not be good candidates for standardization.

There are also several BP features which are semantically similar to features in Standard Pascal or Extended Pascal, but syntactically different.

Therefore, in order to be useful to users coming from either side, GPC supports both the standards and the BP dialect as good as possible. By default, GPC allows features from any dialect it knows. By giving a dialect option such as `--borland-pascal' or `--extended-pascal', you can tell GPC to disable the features not found in that dialect, and to adjust its warning behaviour to the dialect.

The different sets of reserved words are a little problem, but GPC solves it by making the words in question only “conditionally reserved” which works transparently without problems in most cases. Still, giving a dialect option will disable all keywords not part of this dialect.

Apart from this, there are surprisingly few real conflicts between the dialects. Therefore, you can usually compile your BP code without the `--borland-pascal' option and make use of all of GPC's features. You might be surprised, though, when GPC accepts things you didn't know were allowed. :−)

Finally, if you want to make use of some of GPC's extensions (compared to BP) and still keep the code compileable with BP without using `ifdef's all over the place, we suggest you look at the unit `gpc-bp.pas', shipped with GPC, which contains BP versions of some of GPC's features. Please read the comments at the beginning of the unit to find out more about it.


Previous: BP and Extended Pascal, Up: Borland Pascal

7.23 Portability hints

GPC offers you the possibility to make your code fully portable to each of the many platforms supported by GPC. It would be a pity not to make use of this.

This section lists some known pitfalls that often hinder otherwise well-written programs to take full advantage of GPC. If you have never used any compiler but Borland Pascal and similar compilers, some of the advices might look strange to you. But this is just the same level of strangeness that your old programs will have for you once you have understood the principles of cross-platform portability. Remember that many tricks you have always been applying almost automatically in Borland Pascal were necessary to overcome certain limitations of the Dos platform and to compensate for the compiler's missing optimization. Programming with an optimizing compiler like GPC for platforms without a 64 kB limit is a completely new experience – and perhaps it is among the reasons why you are now working with GPC in the first place?

Portability – why?

Okay – but why should I bother and make my program portable? I know that all who want to use my program are running WXYZ-OS anyway.

Yes, but that's the result of a self-fulfilling prophecy. It depends on you whether it will always remain like this or not. Consider a program ABC written for a single platform, WXYZ-OS. Naturally, only WXYZ-OS-users get interested in ABC. The author gets feedback only from WXYZ-OS users and does not see any reason to make the program cross-platform. Then people realize that if they want to run ABC they must move to WXYZ-OS. The author concludes that people only want WXYZ-OS programs, and so on.

To break out, just create a portable version of your program now. Then all OSes have equal chances to show their abilities when running your program, and your customers can choose their OS. Then, maybe, they decide to use your program just for the reason that they can be sure that it will run on all present and future platforms and not only on a specific one – who knows?

My program is a tool specifically designed to make the best of the STUV feature of WXYZ-OS. There is no point in making it portable.

How much do you know about non-WXYZ-OSes? Just ask an expert how the STUV feature is named elsewhere. Be sure, if it is of value, it exists almost everywhere.

Low-level features

I am using a lot of low-level stuff in my programs, so they cannot be portable.

You do not use those low-level routines directly in your high-level routines, do you? There should always be a layer “in-between” that encapsulates the low-level routines and present an API to your program that exactly reflects the needs of your application. This “API in between” is the point where you can exchange the low-level routines by portable calls to GPC's Run Time System.

If you do not have such a layer in-between, then the API of the low-level routines you call are your first approximation for such a layer. If you have ever thought “it would be great if that API function had that additional parameter”, then your own extended version of that API function that has that parameter can become part of your “API in between”. But then don't stop here: Certainly the API of the OS is not ideal for your program's needs. Just create more routines that encapsulate all OS-specific stuff ...

When the low-level stuff in question consists of interrupts, assembler and similar things, then the first thing you need is a portable replacement of the functionality. Fortunately, GPC covers many things already in Pascal that require assembler in Borland Pascal:


Next: , Previous: Borland Pascal, Up: Top

8 The Alphabetical GPC Language Reference

This chapter is still under development. All keywords and built-in identifiers are listed, but not all with explanations.

This chapter contains an alphabetical list of all keywords (reserved words) and built-in identifiers of the GNU Pascal compiler. For detailed and comprehensive description of syntax and reserved words, see Programming. This chapter explains only built-in procedures and functions in detail.

It does not cover extensions provided by external units and libraries which are supposed to come with their own documentation. For the interfaces of the units that come with GPC, see GPC Units.


Next: , Up: Reference

Abs

Synopsis

     function Abs (i: integer_type): integer_type;

or

     function Abs (x: real_type): real_type;

or

     function Abs (z: complex_type): real_type;

Description

Returns the absolute value of the argument. For integer or real values of `x', the definition is

     function Abs (x: integer_or_real_type): integer_or_real_type;
     begin
       if x < 0 then
         Abs := -x
       else
         Abs := x
     end;

whereas for complex values it is

     function Abs (x: Complex): Real;
     begin
       Abs := SqRt (x * Conjugate (x))
     end;

Conforming to

The function `Abs' is defined in ISO 7185 Pascal; its application to complex values is defined in ISO 10206 Extended Pascal.

Example

     program AbsDemo;
     var
       i1: Complex;
     begin
       WriteLn (Abs (42));             { 42 }
       WriteLn (Abs (-42));            { 42 }
       WriteLn (Abs (-12.1) : 0 : 1);  { 12.1 }
       i1 := Cmplx (1, 1);             { 1 + i }
       WriteLn (Abs (i1) : 0 : 3)      { 1.414, i.e. SqRt (2) }
     end.

See also

Sqr.


Next: , Previous: Abs, Up: Reference

absolute

Synopsis

     var
       variable_name: data_type absolute variable_reference;

or

     var
       variable_name: data_type absolute integer_expression;

Description

The first meaning of the `absolute' directive allows to put a variable to the address of another one and thus provides a type-casting mechanism.

In most cases, variable_reference will be just a variable name, but GPC also allows arbitrary pointer expressions here. If variable_reference has neither a constant address nor is a variable parameter, GPC prints a warning. This warning is suppressed in “extended syntax” mode which is switched on by the `--extended-syntax' option or the `{$X+}' compiler directive.

GPC also allows explicit type casts. Variant records (as defined in ISO 7185 Pascal), however, have no guaranteed overlaying and are therefore not suitable for type casts.

The second meaning of `absolute' places a variable at a specified address. This is useful on machines without virtual memory addressing for doing certain low-level operations, but should be avoided on systems with memory protection such as Unix-like systems. GPC does not check whether the specified virtual address makes any sense and does not provide a built-in mechanism to map it to a real address.

GPC warns about this second use of `absolute' unless “extended syntax” has been requested.

Conforming to

`absolute' is a Borland Pascal extension.

Borland Pascal has a slightly different syntax for the second meaning related to the addressing scheme of IA32 processors working in real mode.

Allowing arbitrary memory references instead of just variable names in the first meaning of `absolute' is a GNU Pascal extension.

Example

     program AbsoluteDemo;
     
     {$X+}
     
     const
       IOMem = $f0000000;
       MaxVarSize = MaxInt div 8;
     
     var
       Mem: array [0 .. MaxVarSize - 1] of Byte absolute 0;
     
       { This address has no actual meaning }
       MyPort: Byte absolute IOMem + $c030;
     
     { Beware: Using any of the variables above will crash
       your program unless you know exactly what you do!
       That's why GPC warns about it without the $X+ directive. }
     
     var
       x: Real;
       a: array [1 .. SizeOf (Real)] of Byte absolute x;
       i: Integer;
       b: Byte absolute a[i];  { GNU Pascal extension:
                                  non-constant memory reference. }
     
     begin
       x := 3.14;
     
       { Look at the internal representation of a real variable. }
       for i := 1 to SizeOf (Real) do
         Write (a[i] : 4);
       WriteLn;
     
       { The same again, more ugly ... }
       for i := 1 to SizeOf (Real) do
         Write (b : 4);
       WriteLn;
     
       { And yes, there's an even more ugly way to do it ... }
       for i := 1 to SizeOf (Real) do
         Write (Mem[PtrCard (@x) + i - 1] : 4);
       WriteLn
     end.

See also

Keywords, record, Type Casts.


Next: , Previous: absolute, Up: Reference

abstract

Not yet implemented.

Synopsis

Description

Abstract object type or method declaration.

Conforming to

`abstract' is an Object Pascal extension.

Example

See also

Keywords.


Next: , Previous: abstract, Up: Reference

Addr

Synopsis

     function Addr (const Foo): Pointer;

Description

`Addr' returns the address of its argument. It is equivalent to the address operator.

Note: In BP, `Addr' returns an untyped pointer. GPC does this only with `--borland-pascal'. Otherwise it returns a typed pointer. `Addr' never depends on the `--[no]-typed-address' option/compiler directive, unlike the address operator. (It is recommended you never rely on untyped pointer results, but use a type-cast if really necessary.)

Conforming to

`Addr' is a Borland Pascal extension.

Example

     program AddrDemo;
     var
       Foo: ^Integer;
       Bar: Integer;
     begin
       Foo := Addr (Bar);  { Let `Foo' point to `Bar'. }
       Bar := 17;
       Foo^ := 42;  { Change the value of `Bar' to 42 }
       WriteLn (Bar)
     end.

See also

Operators.


Next: , Previous: Addr, Up: Reference

AlignOf

Synopsis

     function AlignOf (var x): Integer;

Description

Returns the alignment of a type or variable in bytes.

Conforming to

`AlignOf' is a GNU Pascal extension.

Example

     program AlignOfDemo;
     var
       a: Integer;
       b: array [1 .. 8] of Char;
     begin
       WriteLn (AlignOf (a));  { Alignment of `Integer', e.g. 4 bytes. }
       WriteLn (AlignOf (Integer));  { The same. }
       WriteLn (AlignOf (b));  { Alignment of `Char'; usually 1 byte. }
     end.

Although the array is bigger than a single char, it is accessed char by char, so there usually is no need to align it on a 4 byte boundary or such. (This may be false on some platforms.)

See also

SizeOf, BitSizeOf, TypeOf.


Next: , Previous: AlignOf, Up: Reference

all

(Under construction.)

Synopsis

Description

`export' extension (`export foo = all').

Conforming to

`all' is a GNU Pascal extension.

Example

See also

Keywords.


Next: , Previous: all, Up: Reference

and

Synopsis

     operator and (operand1, operand2: Boolean) = Result: Boolean;

or

     operator and (operand1, operand2: integer_type) = Result: integer_type;

or

     procedure and (var operand1: integer_type; operand2: integer_type);

Description

In GNU Pascal, `and' has three built-in meanings:

  1. Logical “and” between two `Boolean'-type expressions. The result of the operation is of `Boolean' type.

    By default, `and' acts as a short-circuit operator in GPC: If the first operand is `False', the second operand is not evaluated because the result is already known to be `False'. You can change this to complete evaluation using the `--no-short-circuit' command-line option or the `{$B+}' compiler directive.

  2. Bitwise “and” between two integer-type expressions. The result is of the common integer type of both expressions.
  3. Use as a “procedure”: `operand1' is “and”ed bitwise with `operand2'; the result is stored in `operand1'.

Conforming to

The logical `and' operator is defined in ISO 7185 Pascal.

According to ISO, you cannot rely on `and' being a short-circuit operator. On the other hand, GPC's default behaviour does not contradict the ISO standard. (See and_then.) However, since it seems to be a de-facto standard among ISO Pascal compilers to evaluate both operands of `and', GPC switches to `--no-short-circuit' mode if one of the language dialect options selecting ISO Pascal, for instance `--extended-pascal', is given. Use `--short-circuit' to override.

Use of `and' as a bitwise operator for integers is a Borland Pascal extension.

Use of `and' as a “procedure” is a GNU Pascal extension.

Example

     program AndDemo;
     var
       a, b, c: Integer;
     begin
       if (a = 0) and (b = 0) then  { logical `and' }
         c := 1
       else if (a and b) = 0 then  { bitwise `and' }
         c := 2
       else
         and (c, a)  { same as `c := c and a' }
     end.

Note the difference between the logical `and' and the bitwise `and': When `a' is 2 and `b' is 4, then `a and b' is 0. Beware: `a and b = 0' has nothing to do with `(a = 0) and (b = 0)'!

Since bitwise `and' has a higher priority than the `=' operator, parentheses are needed in `if (a = 0) and (b = 0)' because otherwise `0 and b' would be calculated first, and the remainder would cause a parse error.

See also

Keywords, and_then, and then, or, xor, Operators.


Next: , Previous: and, Up: Reference

and then

Synopsis

     { `and then' is built in. A user-defined operator cannot consist of
        two words. }
     operator and then (operand1, operand2: Boolean) = Result: Boolean;

Description

`and then' is an alias for the short-circuit logical operator `and_then'.

Conforming to

While `and_then' is defined in ISO 10206 Extended Pascal, `and then' is a GNU Pascal extension.

Example

     program AndThenDemo;
     var
       p: ^Integer;
     begin
       New (p);
       ReadLn (p^);
       if (p <> nil) and then (p^ < 42) then  { This is safe. }
         WriteLn (p^, ' is less than 42')
     end.

See also

Keywords, and_then, and, or else.


Next: , Previous: and then, Up: Reference

and_then

Synopsis

     operator and_then (operand1, operand2: Boolean) = Result: Boolean;

Description

The `and_then' short-circuit logical operator performs the same operation as the logical operator `and'. But while the ISO standard does not specify anything about the evaluation of the operands of `and' – they may be evaluated in any order, or not at all – `and_then' has a well-defined behaviour: It evaluates the first operand. If the result is `False', `and_then' returns `False' without evaluating the second operand. If it is `True', the second operand is evaluated and returned.

Since the behaviour described above is the most efficient way to implement `and', GPC by default treats `and' and `and_then' exactly the same. If you want, for some reason, to have both operands of `and' evaluated completely, you must assign both to temporary variables and then use `and' – or `and_then', it does not matter.

Conforming to

`and_then' is an ISO 10206 Extended Pascal extension.

Some people think that the ISO standard requires both operands of `and' to be evaluated. This is false. What the ISO standard does say is that you cannot rely on a certain order of evaluation of the operands of `and'; in particular things like the following program can crash according to ISO Pascal, although they cannot crash when compiled with GNU Pascal running in default mode.

     program AndBug;
     var
       p: ^Integer;
     begin
       New (p);
       ReadLn (p^);
       if (p <> nil) and (p^ < 42) then  { This is NOT safe! }
         WriteLn ('You''re lucky. But the test could have crashed ...')
     end.

Example

     program And_ThenDemo;
     var
       p: ^Integer;
     begin
       New (p);
       ReadLn (p^);
       if (p <> nil) and_then (p^ < 42) then  { This is safe. }
         WriteLn (p^, ' is less than 42')
     end.

See also

Keywords, and then, and, or_else.


Next: , Previous: and_then, Up: Reference

AnsiChar

Synopsis

     type
       AnsiChar = Char;

Description

`AnsiChar' is an 8 bit char type. Currently, it is the same as `Char', but this might change in the future, once `wide chars' (16 bit chars) will be introduced into GPC. Depending on the platform, `Char' might be either `AnsiChar' or `WideChar' then.

Conforming to

`AnsiChar' is a Borland Delphi extension.

Example

     program AnsiCharDemo;
     var
       A: AnsiChar;  { There is nothing special with `AnsiChar'. }
       B: Char;
     begin
       A := 'A';
       A := B
     end.

See also

PAnsiChar, Char.


Next: , Previous: AnsiChar, Up: Reference

AnyFile

Synopsis

     type
       AnyFile  { built-in type }

Description

`AnyFile' is a built-in type that can only be used for parameters and pointer targets. Any kind of file variable (`Text', untyped and typed `file') can be passed to such a parameter and their address assigned to such a pointer. On the other side, only generic file operations are possible with `AnyFile' parameters/pointer targets.

This type is useful for implementing generic file handling routines. Also some built-in file routines use this type for their parameters, e.g. `IOSelectRead' (see Run Time System).

`BlockRead' (see BlockRead) and `BlockWrite' (see BlockWrite) treat `AnyFile' specially, in that they accept all `AnyFile's as arguments (even if the actual file is a typed or `Text' file) and always use a block size of 1 (even if the actual file is an untyped file with different block size or a typed file of a type with size not equal to one). This is the only way to reliably read/write a certain amount of data from/to an `AnyFile'.

`AnyFile' pointers cannot be allocated with `New' (because it would be unspecified which kind of file to create).

Conforming to

`AnyFile' is a GNU Pascal extension.

Example

     program AnyFileDemo;
     
     procedure Test (var f: AnyFile);
     var v: ^AnyFile;
     begin
       { Generic file operations are allowed for `AnyFile' }
       Rewrite (f);
     
       { `AnyFile' can also be accessed via pointers }
       v := @f;
       Close (v^)
     end;
     
     var
       t: Text;
       f: file;
       g: file of Integer;
     
     begin
       { Any kind of file variable can be passed as `AnyFile' }
       Test (t);
       Test (f);
       Test (g)
     end.

See also

Text, file.


Next: , Previous: AnyFile, Up: Reference

Append

Synopsis

     procedure Append (var F: any_file; [FileName: String;]
                                         [BlockSize: Cardinal]);

Description

`Append' opens a file for writing. If the file does not exist, it is created. If it does exist, the file pointer is positioned after the last element.

Like `Rewrite', `Reset' and `Extend' do, `Reset' accepts an optional second parameter for the name of the file in the filesystem and a third parameter for the block size of the file. The third parameter is allowed only (and by default also required) for untyped files. For details, see Rewrite.

Conforming to

`Append', including the `BlockSize' parameter, is a Borland Pascal extension. ISO 10206 Extended Pascal has Extend instead. The `FileName' parameter is a GNU Pascal extension.

Example

     program AppendDemo;
     var
       Sample: Text;
     begin
       Assign (Sample, 'sample.txt');
       Rewrite (Sample);
       WriteLn (Sample, 'Hello, World!');  { `sample.txt' now has one line }
       Close (Sample);
     
       { ... }
     
       Append (Sample);
       WriteLn (Sample, 'Hello again!');  { `sample.txt' now has two lines }
       Close (Sample)
     end.

See also

Assign, Reset, Rewrite, Update, Extend.


Next: , Previous: Append, Up: Reference

ArcCos

Synopsis

     function ArcCos (x: Real): Real;

or

     function ArcCos (z: Complex): Complex;

Description

`ArcCos' returns the (principal value of the) arcus cosine of the argument. The result is in the range `0 < ArcCos (x) < Pi' for real arguments.

Conforming to

`ArcCos' is a GNU Pascal extension.

Example

     program ArcCosDemo;
     begin
       { yields 3.14159 as ArcCos (0.5) = Pi / 3 }
       WriteLn (3 * ArcCos (0.5) : 0 : 5)
     end.

See also

ArcSin, ArcTan, Sin, Cos, Ln, Arg.


Next: , Previous: ArcCos, Up: Reference

ArcSin

Synopsis

     function ArcSin (x: Real): Real;

or

     function ArcSin (z: Complex): Complex;

Description

`ArcSin' returns the (principal value of the) arcus sine of the argument. The result is in the range `-Pi / 2 < ArcSin (x) < Pi / 2' for real arguments.

Conforming to

`ArcSin' is a GNU Pascal extension.

Example

     program ArcSinDemo;
     begin
       { yields 3.14159 as ArcSin (0.5) = Pi / 6 }
       WriteLn (6 * ArcSin (0.5) : 0 : 5)
     end.

See also

ArcCos, ArcTan, Sin, Cos, Ln, Arg.


Next: , Previous: ArcSin, Up: Reference

ArcTan

Synopsis

     function ArcTan (x: Real): Real;

or

     function ArcTan (z: Complex): Complex;

Description

`ArcTan' returns the (principal value of the) arcus tangent of the argument. The result is in the range `-Pi / 2 < ArcTan (x) < Pi / 2' for real arguments.

Conforming to

`ArcTan' is defined in ISO 7185 Pascal; its application to complex values is defined in ISO 10206 Extended Pascal.

Example

     program ArcTanDemo;
     begin
       { yields 3.14159 as ArcTan (1) = Pi / 4 }
       WriteLn (4 * ArcTan (1) : 0 : 5)
     end.

See also

ArcSin, ArcCos, Sin, Cos, Ln, Arg.


Next: , Previous: ArcTan, Up: Reference

Arg

Synopsis

     function Arg (z: Complex): Real;

Description

`Arg' returns the complex “argument”, i.e. the angle (in radian) in the complex plane with respect to the real axis, of its parameter `z'. The result is in the range of `-Pi < Arg (z) <= Pi'.

Conforming to

`Arg' is an ISO 10206 Extended Pascal extension.

Example

     program ArgDemo;
     var
       z: Complex;
     begin
       z := Cmplx (1, 1);  { 1 + i }
       WriteLn (Arg (z) : 0 : 5)  { yields 0.78540, i.e. Pi / 4 }
     end.

See also

ArcTan, Ln, Polar.


Next: , Previous: Arg, Up: Reference

array

Synopsis

In type definitions:

     array [index_type] of element_type

or

     array [index_type, ..., index_type] of element_type

In parameter list declarations:

     array of element_type

Description

The reserved word `array' is used to define an array type.

@@conformant/open arrays

Conforming to

Array types are defined in ISO 7185 Pascal.

Example

     program ArrayDemo;
     type
       IntArray = array [1 .. 20] of Integer;
       WeekDayChars = array [(Mon, Tue, Wed, Thu, Fri, Sat, Sun)] of Char;
       Foo = array [0 .. 9, 'a' .. 'z', (Baz, Glork1, Fred)] of Real;
       TwoDimIntArray = array [1 .. 10] of IntArray;
       { is equivalent to: }
       TwoDimIntArray2 = array [1 .. 10, 1 .. 20] of Integer;
     
     procedure PrintChars (F: array of Char);
     var
       i: Integer;
     begin
       for i := Low (F) to High (F) do
         WriteLn (F[i])
     end;
     
     var
       Waldo: WeekDayChars;
     
     begin
       Waldo := 'HiWorld';
       PrintChars (Waldo)
     end.

See also

Keywords, Array Types, High, Low


Next: , Previous: array, Up: Reference

as

(Under construction.)

Synopsis

Description

Object type membership test and conversion.

Conforming to

`as' is an Object Pascal and a Borland Delphi extension.

Example

See also

Keywords, is, TypeOf, OOP.


Next: , Previous: as, Up: Reference

asm

(Under construction.)

Synopsis

Description

See `http://www.gnu-pascal.de/contrib/misc/gpcasm.zip'.

Conforming to

`asm', as implemented in GPC, is a GNU Pascal extension. It is mostly compatible to GCC's `asm', but not compatible to that of Borland Pascal.

Example

See also

Keywords.


Next: , Previous: asm, Up: Reference

asmname

Synopsis

Description

Deprecated! Use `external name' now.

Conforming to

Example

See also

Keywords, external, name, Importing Libraries from Other Languages.


Next: , Previous: asmname, Up: Reference

Assert

Synopsis

     procedure Assert (Condition: Boolean);

or

     procedure Assert (Condition: Boolean; const Message: String);

Description

`Assert' checks the given `Condition' at run-time. If it is true, it does nothing. If it is false, it raises a runtime error, using the second argument for the message if given.

However, if the switch `--no-assertions' is given (see GPC Command Line Options), `Assert' is deactivated. It still evaluates the condition if it has side effects, but never raises a runtime error.

Conforming to

`Assert' is a Borland Delphi extension.

Example

See also

CompilerAssert.


Next: , Previous: Assert, Up: Reference

Assign

(Under contruction.)

Synopsis

     procedure Assign (var F: any_file; FileName: String);

Description

Conforming to

`Assign' is a Borland Pascal extension.

Example

See also

Reset, Rewrite, Update, Extend, Append.


Next: , Previous: Assign, Up: Reference

Assigned

(Under construction.)

Synopsis

     function Assigned (p: Pointer): Boolean;

or

     function Assigned (p: procedural_type): Boolean;

Description

The `Assigned' function returns `True' if the pointer parameter or the address of the procedural parameter is not `nil'; it returns `False' if it is `nil'.

Conforming to

`Assigned' is a Borland Pascal extension.

Example

     program AssignedDemo;
     type
       PInt = ^Integer;
     
     procedure TellIfOdd (p: PInt);
     begin
       if Assigned (p) and then Odd (p^) then
         WriteLn ('The pointer p points to an odd value.')
     end;
     
     var
       foo: Integer;
     begin
       TellIfOdd (nil);
       foo := 1;
       TellIfOdd (@foo);
       foo := 2;
       TellIfOdd (@foo)
     end.

See also

Null, nil, Pointer.


Next: , Previous: Assigned, Up: Reference

attribute

(Under construction.)

Synopsis

     declaration attribute (name);

or

     declaration attribute (name = parameter);

or

     declaration attribute (name (parameter, parameter ...));

Description

Several attributes can be given in one `attribute' directive, separated with `,', or in several `attribute' directives.

Besides the attributes that GCC supports (see Attribute Syntax), GPC allows the following attributes for variables:

For routines it allows the following additional attributes:

For types it allows the following additional attributes:

`Size' can be applied to integer and Boolean types to produce types with a specified size in bits; for example

     type
       Card16 = Cardinal attribute (Size = 16);

defines an unsigned integer type with 16 bits.

Variable and routine attributes are preceded by a `;', type attributes are not. So, e.g., in the following example, the `Size' attribute applies to the type, and the `static' attribute to the variable.

     var a: Integer attribute (Size = 64); attribute (static);

Conforming to

`attribute' is a GNU Pascal extension.

Example

     program AttributeDemo;
     
     { Demo for `iocritical' attribute. }
     
     { Program will abort with a runtime error! }
     
     {$I-}
     procedure p; attribute (iocritical);
     var t: Text;
     begin
       Reset (t)  { Will not cause a runtime error here because I/O
                    checking is off, but leave InOutRes set. }
     end;
     {$I+}
     
     begin
     
       p;
       { Since `p' was declared `iocritical', and I/O checking is now on,
         InOutRes is checked immediately after the call to p, and a
         runtime error raised. }
     
       { So this statement is never reached. }
       InOutRes := 0;
     
       { Neither this one, which would be reached without the
         `iocritical' attribute. }
       WriteLn ('never gets here')
     
     end.

See also

Keywords, external.


Next: , Previous: attribute, Up: Reference

begin

Synopsis

     begin
       statement;
       statement;
       ...
       statement
     end;

Description

The reserved word `begin' opens a `begin ... end' statement which joins several statements to one compound statement.

Conforming to

`begin' is defined in ISO 7185 Pascal and supported by all known Pascal variants.

Example

     program BeginDemo;
     begin
       if True then
         WriteLn ('single statement');
       if True then
         begin                     { clamp statement1 ... }
           WriteLn ('statement1');
           WriteLn ('statement2')
         end                       { ... to statement2 }
     end.

See also

Keywords, begin end Compound Statement, end


Next: , Previous: begin, Up: Reference

Bind

(Under construction.)

Synopsis

     procedure Bind (var F: any_file; B: BindingType);

Description

Conforming to

`Bind' is an ISO 10206 Extended Pascal extension.

Example

See also

Unbind, Binding, BindingType, bindable.


Next: , Previous: Bind, Up: Reference

bindable

(Under construction.)

Synopsis

Description

External bindability of files.

Conforming to

`bindable' is an ISO 10206 Extended Pascal extension.

Example

See also

Keywords, Bind, Unbind, Binding, BindingType.


Next: , Previous: bindable, Up: Reference

Binding

(Under construction.)

Synopsis

     function Binding (F: any_file): BindingType;

Description

Conforming to

`Binding' is an ISO 10206 Extended Pascal extension.

Example

See also

Bind, Unbind, BindingType, bindable.


Next: , Previous: Binding, Up: Reference

BindingType

(Under construction.)

Synopsis

     type
       UnixTimeType = LongInt;
       BindingType = packed record
         Bound,
         Force,                     { Can be set to allow binding to
                                      directories or inaccessible files }
         Extensions_Valid,
         Readable,
         Writable,
         Executable,
         Existing,                  { Binding points to an existing file }
         Directory,                 { Binding points to an existing
                                      directory; `Existing' is False
                                      in this case }
         Special,                   { Binding points to an existing
                                      special file (device, pipe, socket,
                                      etc.); `Existing' is False in
                                      this case }
         SymLink: Boolean;          { Binding points to a symbolic link }
         Size: FileSizeType;        { Size of file, or -1 if unknown }
         AccessTime,                { Time of last access }
         ModificationTime,          { Time of last modification }
         ChangeTime: UnixTimeType;  { Time of last change }
         User,                      { User ID of owner }
         Group,                     { Group ID of owner }
         Mode,                      { Access permissions, cf. ChMod }
         Device,                    { Device the file is on }
         INode,                     { Unix INode number }
         Links: Integer;            { Number of hard links }
         TextBinary: Boolean;       { Open a Text file in binary mode }
         Handle: Integer;           { Can be set to bind a Pascal file to
                                      a given file handle }
         CloseFlag: Boolean;        { If Handle is used, tell whether to
                                      close it when file is closed }
         Name: String (BindingNameLength)
       end;

BindingNameLength is an implementation-defined constant.

Description

Conforming to

`BindingType' is an ISO 10206 Extended Pascal extension. The fields `Bound' and `Name' are required by Extended Pascal, the other ones are GNU Pascal extensions.

Example

See also

Bind, Unbind, Binding, bindable.


Next: , Previous: BindingType, Up: Reference

BitSizeOf

Synopsis

     function BitSizeOf (var x): SizeType;

Description

Returns the size of a type or variable in bits.

Conforming to

`BitSizeOf' is a GNU Pascal extension.

Example

     program BitSizeOfDemo;
     type
       Int12 = Integer attribute (Size = 12);
     var
       a: Integer;
       b: array [1 .. 8] of Char;
       c: Int12;
       d: packed record
            x: Int12;
            y: 0 .. 3
          end;
     begin
       WriteLn (BitSizeOf (a));    { Size of an `Integer'; usually 32 bits. }
       WriteLn (BitSizeOf (Integer));  { The same. }
       WriteLn (BitSizeOf (b));    { Size of eight `Char's; usually 64 bits. }
       WriteLn (BitSizeOf (c));    { e.g. 16 bits (smallest addressable
                                      space holding a 12 bit integer). }
       WriteLn (BitSizeOf (d));    { e.g. 16 }
       WriteLn (BitSizeOf (d.x));  { 12 }
       WriteLn (BitSizeOf (d.y))   { 2 }
     end.

See also

SizeOf, AlignOf, TypeOf.


Next: , Previous: BitSizeOf, Up: Reference

BlockRead

(Under construction.)

Synopsis

     procedure BlockRead (var F: File; var Buffer; Blocks: Integer);

or

     procedure BlockRead (var F: File; var Buffer; Blocks: Integer;
                          var BlocksRead: Integer);

Description

Conforming to

`BlockRead' is a UCSD Pascal extension.

Example

See also


Next: , Previous: BlockRead, Up: Reference

BlockWrite

(Under construction.)

Synopsis

     procedure BlockWrite (var F: File; const Buffer; Blocks: Integer);

or

     procedure BlockWrite (var F: File; const Buffer; Blocks: Integer;
                           var BlocksWritten: Integer);

Description

Conforming to

`BlockWrite' is a UCSD Pascal extension.

Example

See also


Next: , Previous: BlockWrite, Up: Reference

Boolean

Synopsis

     type
       Boolean = (False, True); { built-in type }

Description

The intrinsic `Boolean' represents boolean values, i.e. it can only assume the two values `True' and `False' (which are predefined constants).

Conforming to

`Boolean' is defined in ISO 7185 Pascal and supported by all known Pascal variants.

Example

     program BooleanDemo;
     var
       a: Boolean;
     begin
       a := True;
       WriteLn (a)
     end.

See also

Boolean (Intrinsic), True, False, CBoolean, ByteBool, ShortBool, MedBool, WordBool, LongBool, LongestBool.


Next: , Previous: Boolean, Up: Reference

Break

Synopsis

     Break  { simple statement }

Description

With `Break' you can exit the body of the current loop instantly. It can only be used within a `while', `repeat' or a `for' loop.

Conforming to

`Break' is a Borland Pascal extension. Mac Pascal has `Leave' instead.

Example

     program BreakDemo;
     var
       Foo: Integer;
     begin
       while True do
         begin
           repeat
             WriteLn ('Enter a number less than 100:');
             ReadLn (Foo);
             if Foo < 100 then
               Break;  { Exits `repeat' loop }
             WriteLn (Foo, ' is not exactly less than 100! Try again ...')
           until False;
           if Foo > 50 then
             Break;  { Exits `while' loop }
           WriteLn ('The number entered was not greater than 50.')
         end
     end.

See also

Loop Control Statements, Continue, Cycle, Exit, Halt, Leave, Return, goto.


Next: , Previous: Break, Up: Reference

Byte

Synopsis

     type
       Byte  { built-in type }

Description

`Byte' is an unsigned integer type which is one “unit” wide. On most platforms one unit has 8 bits, therefore the type is named “byte” and usually has a range of `0 .. 255'. (It is the same as ByteCard.)

`Byte' in GNU Pascal is compatible to `unsigned char' in GNU C.

There are lots of other integer types in GPC, see Integer Types.

Conforming to

`Byte' is a Borland Pascal extension. (For something equivalent in ISO Pascal, see Subrange Types.)

Example

     program ByteDemo;
     var
       a: Byte;
     begin
       a := 42;
       WriteLn (a)
     end.

See also

Integer Types, Subrange Types.


Next: , Previous: Byte, Up: Reference

ByteBool

Synopsis

     type
       ByteBool = Boolean attribute (Size = BitSizeOf (Byte));

Description

The intrinsic `ByteBool' represents boolean values, but occupies the same memory space as a `Byte'. It is used when you need to define a parameter or record that conforms to some external library or system specification.

Conforming to

`ByteBool' is a Borland Pascal extension.

Example

     program ByteBoolDemo;
     var
       a: ByteBool;
     begin
       Byte (a) := 1;
       if a then WriteLn ('Ord (True) = 1')
     end.

See also

Boolean (Intrinsic), Boolean, True, False, CBoolean, ShortBool, MedBool, WordBool, LongBool, LongestBool.


Next: , Previous: ByteBool, Up: Reference

ByteCard

Synopsis

     type
       ByteCard = Cardinal attribute (Size = BitSizeOf (Byte));

Description

`ByteCard' is an unsigned integer type which is one “unit” wide. On most platforms one unit has 8 bits, therefore the type is prefixed “byte-” and usually has a range of `0 .. 255'.

`ByteCard' in GNU Pascal is compatible to `unsigned char' in GNU C.

There are lots of other integer types in GPC, see Integer Types.

Conforming to

`ByteCard' is a GNU Pascal extension.

Example

     program ByteCardDemo;
     var
       a: ByteCard;
     begin
       a := 42;
       WriteLn (a)
     end.

See also

Integer Types, Subrange Types.


Next: , Previous: ByteCard, Up: Reference

ByteInt

Synopsis

     type
       ByteInt = Integer attribute (Size = BitSizeOf (Byte));

Description

`ByteInt' is a signed integer type which is one “unit” wide. On most platforms one unit has 8 bits, therefore the type is prefixed “byte-” and usually has a range of `-128 .. 127'.

`ByteInt' in GNU Pascal is compatible to `signed char' in GNU C.

There are lots of other integer types in GPC, see Integer Types.

Conforming to

`ByteInt' is a GNU Pascal extension.

`ByteInt' in GNU Pascal corresponds to ShortInt in Borland Pascal.

Example

     program ByteIntDemo;
     var
       a: ByteInt;
     begin
       a := 42;
       WriteLn (a)
     end.

See also

Integer Types, Subrange Types.


Next: , Previous: ByteInt, Up: Reference

c

Synopsis

Description

Deprecated! Use `external' now.

Conforming to

Example

See also

Keywords, Importing Libraries from Other Languages, external.


Next: , Previous: c, Up: Reference

Card

Synopsis

     function Card (S: any_set): Integer;

Description

The function `Card (S)' returns the number of elements in the set `S'.

Conforming to

`Card' is an ISO 10206 Extended Pascal extension.

Example

     program CardDemo;
     var
       Foo: set of 1 .. 100;
     begin
       Foo := [1, 2, 3, 5, 1, 1, 1, 2, 2, 2, 3, 3, 5, 5];  { four elements }
       WriteLn ('foo consists of ', Card (Foo), ' elements')
     end.

See also

set


Next: , Previous: Card, Up: Reference

Cardinal

Synopsis

     type
       Cardinal  { built-in type }

Description

`Cardinal' is the “natural” unsigned integer type in GNU Pascal. On some platforms it is 32 bits wide and thus has a range of `0 .. 4294967295'. Use it whenever you need a general-purpose unsigned integer type and don't need to care about compatibility to other Pascal dialects.

There are lots of other integer types in GPC, see Integer Types.

Conforming to

`Cardinal' is not defined in ISO Pascal, but several Pascal compilers support it as an extension. In Borland Delphi, for instance, it is an unsigned 16-bit in version 1.0, an unsigned 31-bit integer from version 2.0 on, and an unsigned 32-bit integer from version 4.0 on.

Example

     program CardinalDemo;
     var
       a: Cardinal;
     begin
       a := 42;
       WriteLn (a)
     end.

See also

Integer Types, Subrange Types.


Next: , Previous: Cardinal, Up: Reference

case

Synopsis

     case expression of
       selector: statement;
       ...
       selector: statement;
     end;

or, with alternative statement sequence:

     case expression of
       selector: statement;
       ...
       selector: statement;
     otherwise  { ``else'' instead of ``otherwise'' is allowed }
       statement;
       ...
       statement;
     end;

or, as part of the invariant record type definition:

     foo = record
       field_declarations
     case bar: variant_type of
       selector: (field_declarations);
       selector: (field_declarations);
       ...
     end;

or, without a variant selector field,

     foo = record
       field_declarations
     case variant_type of
       selector: (field_declarations);
       selector: (field_declarations);
       ...
     end;

Description

`case' opens a case statement. For further description see case Statement.

For `case' in a variant record type definition, see Record Types.

Conforming to

The `case' statement is defined in ISO 7185 Pascal and supported by all known Pascal variants.

According to ISO 7185 Pascal, the selector type must be a named type. UCSD Pascal and Borland Pascal allow any ordinal type here.

The alternative statement execution with `otherwise' it is an Extended Pascal extension; with `else' it is a Borland Pascal extension. In GNU Pascal, both are allowed.

Example

     program CaseDemo;
     var
       Foo: String (10);
       Bar: Integer;
     begin
       WriteLn ('Enter up to ten arbitrary characters:');
       ReadLn (Foo);
       for Bar := 1 to Length (Foo) do
         begin
           Write (Foo[Bar], ' is ');
           case Foo[Bar] of
             'A' .. 'Z', 'a' .. 'z':
               WriteLn ('an English letter');
             '0' .. '9':
               WriteLn ('a number');
           otherwise
             WriteLn ('an unrecognized character')
           end
         end
     end.

See also

Keywords, if Statement, Record Types, else, otherwise


Next: , Previous: case, Up: Reference

CBoolean

(Under construction.)

Synopsis

     type
       CBoolean  { built-in type }

Description

`CBoolean' is a Boolean type. In GNU Pascal it is compatible to `_Bool' in GNU C (which is defined as `bool' in stdbool.h). This compatibility is the reason why `CBoolean' exists.

Conforming to

`CBoolean' is a GNU Pascal extension.

Example

     program CBooleanDemo;
     var
       a: CBoolean;
     begin
       a := True;
       if Ord (a) = 1 then WriteLn ('Ord (True) = 1')
     end.

See also

Boolean (Intrinsic), Integer Types, Boolean, True, False, ByteBool, ShortBool, MedBool, WordBool, LongBool, LongestBool.


Next: , Previous: CBoolean, Up: Reference

CCardinal

Synopsis

     type
       CCardinal  { built-in type }

Description

`CCardinal' is an unsigned integer type. On some platforms it is 32 bits wide and thus has a range of `0 .. 4294967295'.

`CCardinal' in GNU Pascal is compatible to `unsigned int' in GNU C.

There are lots of other integer types in GPC, see Integer Types.

Conforming to

`CCardinal' is a GNU Pascal extension.

Example

     program CCardinalDemo;
     var
       a: CCardinal;
     begin
       a := 42;
       WriteLn (a)
     end.

See also

Integer Types, Subrange Types.


Next: , Previous: CCardinal, Up: Reference

Char

Synopsis

     type
       Char  { built-in type }

Description

The built-in type `Char' holds elements of the operating system's character set (usually ASCII). The `Char' type is a special case of ordinal type. Conversion between character types and ordinal types is possible with the built-in functions `Ord' and `Chr'.

Conforming to

`Char' is defined in ISO 7185 Pascal and supported by all known Pascal variants.

Example

     program CharDemo;
     var
       a: Char;
     begin
       a := 'x';
       WriteLn (a)
     end.

See also

Character Types, Ordinal Types, Type Casts, Ord, Chr.


Next: , Previous: Char, Up: Reference

ChDir

Synopsis

     procedure ChDir (Directory: String);

Description

`ChDir' changes the current directory to Directory, if its argument is a valid parameter to the related operating system's function. Otherwise, a runtime error is caused.

Conforming to

`ChDir' is a Borland Pascal extension.

Example

     program ChDirDemo;
     var
       Foo: String (127);
     begin
       WriteLn ('Enter directory name to change to:');
       ReadLn (Foo);
       {$I-}  { Don't abort the program on error }
       ChDir (Foo);
       if IOResult <> 0 then
         WriteLn ('Cannot change to directory `', Foo, '''.')
       else
         WriteLn ('Okay.')
     end.

See also

MkDir, RmDir


Next: , Previous: ChDir, Up: Reference

Chr

Synopsis

     function Chr (AsciiCode: Integer): Char;

Description

`Chr' returns a character whose ASCII code corresponds to the value given by `AsciiCode'.

Conforming to

`Chr' is defined in ISO 7185 Pascal and supported by all known Pascal variants.

Example

     program ChrDemo;
     var
       x: Integer;
     begin
       for x := 32 to 122 do
         Write (Chr (x))
     end.

See also

Character Types, Ord, Char


Next: , Previous: Chr, Up: Reference

CInteger

Synopsis

     type
       CInteger  { built-in type }

Description

`CInteger' is a signed integer type. On some platforms it is 32 bits wide and thus has a range of `-2147483648 .. 2147483647'.

`CInteger' in GNU Pascal is compatible to `int' in GNU C.

There are lots of other integer types in GPC, see Integer Types.

Conforming to

`CInteger' is a GNU Pascal extension.

Example

     program CIntegerDemo;
     var
       a: CInteger;
     begin
       a := 42;
       WriteLn (a)
     end.

See also

Integer Types, Subrange Types.


Next: , Previous: CInteger, Up: Reference

c_language

Synopsis

Description

Deprecated! Use `external' now.

Conforming to

Example

See also

Keywords, Importing Libraries from Other Languages, external.


Next: , Previous: c_language, Up: Reference

class

Not yet implemented.

Synopsis

Description

OOE/Delphi style object class.

Conforming to

`class' is an Object Pascal and a Borland Delphi extension.

Example

See also

Keywords.


Next: , Previous: class, Up: Reference

Close

(Under construction.)

Synopsis

     procedure Close (var F: any_file);

Description

Conforming to

`Close' is a UCSD Pascal extension.

Example

See also


Next: , Previous: Close, Up: Reference

Cmplx

Synopsis

     function Cmplx (RealPart, ImaginaryPart: Real): Complex;

Description

`Cmplx' makes a complex number from `RealPart' and `ImaginaryPart'.

Conforming to

`Cmplx' is an ISO 10206 Extended Pascal extension.

Example

     program CmplxDemo;
     var
       z: Complex;
       x, y: Real;
     begin
       z := Cmplx (x, y)  { z := x + iy }
     end.

See also

Re, Im, Polar, Arg


Next: , Previous: Cmplx, Up: Reference

Comp

Synopsis

     type
       Comp = LongInt;

Description

`Comp' is a signed integer type which is longer than `Integer'. On some platforms it is 64 bits wide and thus has a range of `-9223372036854775808 .. 9223372036854775807'.

There are lots of other integer types in GPC, see Integer Types.

Conforming to

`Comp' is a Borland Pascal extension.

In some contexts, Borland Pascal treats `Comp' as a “real” type – this behaviour is not supported by GPC.

Example

     program CompDemo;
     var
       a: Comp;
     begin
       a := 42;
       WriteLn (a)
     end.

See also

Integer Types, Subrange Types.


Next: , Previous: Comp, Up: Reference

CompilerAssert

Synopsis

     procedure CompilerAssert (Condition: Boolean);

or

     function CompilerAssert (Condition: Boolean): Boolean;

or

     function CompilerAssert (Condition: Boolean;
                ResultValue: Any_Type): type of ResultValue;

Description

`CompilerAssert' checks the given `Condition' at compile-time. If it is a compile-time constant of Boolean type with the value `True', it returns `ResultValue', or if called with only one argument, it returns `True' or nothing if used as a procedure.

If `Condition' cannot be evaluated at compile-time or does not have the value `True', it causes a compile-time error.

So it can be used to make sure that certain assumptions hold before relying on them.

`CompilerAssert' does not depend on the `--[no-]assertions' options. It does not generate any run-time code.

Conforming to

`CompilerAssert' is a GNU Pascal extension.

Example

     program CompilerAssertDemo;
     
     var
       a: LongInt;
     
     const
       { Make sure that the highest value a can hold is larger than
         MaxInt, and set b to that value. }
       b = CompilerAssert (High (a) > MaxInt, High (a));
     
       { Do a similar check for the minimum value, setting c to True
         (which can be ignored). }
       c = CompilerAssert (Low (a) < Low (Integer));
     
     begin
       { Procedure-like use of CompilerAssert in the statement part. }
       CompilerAssert (MaxInt >= 100000);
     
       WriteLn (b, ' ', c)
     end.

See also

Assert.


Next: , Previous: CompilerAssert, Up: Reference

Complex

(Under construction.)

Synopsis

     type
       Internal_Complex = record  { not visible }
         RealPart, ImaginaryPart: Real
       end;
       Complex = restricted Internal_Complex;

Description

Conforming to

`Complex' is an ISO 10206 Extended Pascal extension.

Example

     program ComplexDemo;
     var
       a: Complex;
     begin
       a := Cmplx (42, 3);
       WriteLn (Re (a), ' + ', Im (a), ' i')
     end.

See also


Next: , Previous: Complex, Up: Reference

Concat

(Under construction.)

Synopsis

     function Concat (S1, S2: String): String;

or

     function Concat (S1, S2, S3: String): String;

or

     ...

Description

Conforming to

`Concat' is a UCSD Pascal extension.

Example

See also


Next: , Previous: Concat, Up: Reference

Conjugate

Synopsis

     function Conjugate (z: Complex): Complex;

Description

`Conjugate' computes the complex conjugate of the complex number `z'

Conforming to

`Conjugate' is a GNU Pascal extension.

Example

     program ConjugateDemo;
     var
       z: Complex;
     begin
       z := Cmplx (2, 3);  { z is 2 + i * 3 }
       WriteLn ('z = ', Re (z) : 0 : 5, ' + i * ', Im (z) : 0 : 5);
       z := Conjugate (z);  { z conjugate is 2 - i * 3 }
       WriteLn ('z conjugate = ', Re (z) : 0 : 5,' + i * ', Im (z) : 0 : 5)
     end.

See also

Cmplx, Re, Im, Abs


Next: , Previous: Conjugate, Up: Reference

const

(Under construction.)

Synopsis

Description

Constant declaration or constant parameter declaration.

Conforming to

`const' is defined in ISO 7185 Pascal and supported by all known Pascal variants. `const' parameters are a Borland Pascal extension. Pointers to `const' are a GNU Pascal extension.

Constant declarations allow you to define names for constant (unchanging) values, such as using `SecondsPerHour' instead of 3600. This can make your program much more readable and maintainable.

GNU Pascal allows you to define constant strings, records and arrays as well as simple numeric constants.

GNU Pascal also implements the const parameter extension which allows the compiler to pass parameters by reference while still allowing you to pass constant values as inputs. See Subroutine Parameter List Declaration for more information.

@@ Pointers to `const' @@

Example

     program ConstDemo;
     
     type
       Rec = record
         x: Integer;
         y: Integer;
       end;
     
     const
       a = 5;
       constr: Rec = (10, 12);
     
     procedure doit (const r: Rec; const s: String);
     begin
       WriteLn (r.x);
       WriteLn (r.y);
       WriteLn (s);
     end;
     
     var
       variabler: Rec;
     
     begin
       variabler.x := 16;
       variabler.y := 7;
       doit (variabler, 'Should be 16 and 7');
       doit (constr, 'Should be 10 and 12');
     end.

See also

Keywords, var, protected, Subroutine Parameter List Declaration.


Next: , Previous: const, Up: Reference

constructor

(Under construction.) ;−)

Synopsis

Description

Object constructor.

Conforming to

`constructor' is an Object Pascal and a Borland Pascal extension.

Example

See also

Keywords.


Next: , Previous: constructor, Up: Reference

Continue

Synopsis

     Continue  { simple statement }

Description

`Continue' goes on with loop iteration by jumping to the end of the current loop body. Note: `Continue' can only stand within a `while', `repeat' or a `for' loop.

Conforming to

`Continue' is a Borland Pascal extension, Mac Pascal has `Cycle' instead.

Example

     program ContinueDemo;
     var
       Foo, Bar: Integer;
     begin
       WriteLn ('Enter three numbers:');
       for Bar := 1 to 3 do
         begin
           ReadLn (Foo);
           if Foo < 5 then
             Continue;
           WriteLn ('Your number was greater than 5.')
         end
     end.

See also

Loop Control Statements, Break, Cycle, Exit, Halt, Leave, Return, goto.


Next: , Previous: Continue, Up: Reference

Copy

Synopsis

     function Copy (S: String; FirstChar, Count: Integer): String;

or

     function Copy (S: String; FirstChar: Integer): String;

Description

`Copy' returns a sub-string of `S' starting with the character at position FirstChar. If Count is given, such many characters will be copied into the sub-string. If Count is omitted, the sub-string will range to the end of S.

If `Count' is too large for the sub-string to fit in S, the result will be truncated at the end of S. If `FirstChar' exceeds the length of S, the empty string will be returned. (For a function which does not truncate but triggers a runtime error instead, see SubStr.)

Please note that GPC's strings may be longer than 255 characters. If you want to isolate the second half of a string S starting with the third character, use `Copy (S, 3)' instead of `Copy (S, 3, 255)'.

Conforming to

`Copy' is a UCSD Pascal extension. The possibility to omit the third parameter is a GNU Pascal extension.

Example

     program CopyDemo;
     var
       S: String (42);
     begin
       S := 'Hello';
       WriteLn (Copy (S, 2, 3));  { yields `ell' }
       WriteLn (Copy (S, 3));     { yields `llo' }
       WriteLn (Copy (S, 4, 7));  { yields `lo' }
       WriteLn (Copy (S, 42))     { yields the empty string }
     end.

See also

SubStr, String Slice Access.


Next: , Previous: Copy, Up: Reference

Cos

Synopsis

     function Cos (x: Real): Real;

or

     function Cos (z: Complex): Complex;

Description

`Cos' returns the cosine of the argument. The result is in the range `-1 < Cos (x) < 1' for real arguments.

Conforming to

The function `Cos' is defined in ISO 7185 Pascal; its application to complex values is defined in ISO 10206 Extended Pascal.

Example

     program CosDemo;
     begin
       { yields 0.5 since Cos (Pi / 3) = 0.5 }
       WriteLn (Cos (Pi / 3) : 0 : 5)
     end.

See also

ArcTan, Sin, Ln, Arg.


Next: , Previous: Cos, Up: Reference

CString

(Under construction.)

Synopsis

     type
       CString = ^Char;

Description

Conforming to

`CString' is a GNU Pascal extension.

Example

     program CStringDemo;
     var
       s: CString;
     begin
       s := 'Hello, world!';
       {$X+}
       WriteLn (s)
     end.

See also


Next: , Previous: CString, Up: Reference

CString2String

(Under construction.)

Synopsis

     function CString2String (S: CString): String;

Description

Conforming to

`CString2String' is a GNU Pascal extension.

Example

See also


Next: , Previous: CString2String, Up: Reference

CStringCopyString

(Under construction.)

Synopsis

     function CStringCopyString (Dest: CString; const Source: String): CString;

Description

Conforming to

`CStringCopyString' is a GNU Pascal extension.

Example

See also


Next: , Previous: CStringCopyString, Up: Reference

CurrentRoutineName

Synopsis

     function CurrentRoutineName: String;

Description

`CurrentRoutineName' returns the name of the current routine from where it's called.

Conforming to

`CurrentRoutineName' is a GNU Pascal extension.

Example

     program CurrentRoutineNameDemo;
     
     procedure FooBar;
     begin
       WriteLn (CurrentRoutineName)  { `FooBar' }
     end;
     
     begin
       WriteLn (CurrentRoutineName);  { `main program' }
       FooBar
     end.

See also


Next: , Previous: CurrentRoutineName, Up: Reference

CWord

Synopsis

     type
       CWord = CCardinal;

Description

`CCardinal' is an unsigned integer type. On some platforms it is 32 bits wide and thus has a range of `0 .. 4294967295'. It is the same as CCardinal.

`CWord' in GNU Pascal is compatible to `unsigned int' in GNU C.

There are lots of other integer types in GPC, see Integer Types.

Conforming to

`CWord' is a GNU Pascal extension.

Example

     program CWordDemo;
     var
       a: CWord;
     begin
       a := 42;
       WriteLn (a)
     end.

See also

CCardinal, Integer Types, Subrange Types.


Next: , Previous: CWord, Up: Reference

Cycle

Synopsis

     Cycle  { simple statement }

Description

`Cycle' goes on with loop iteration by jumping to the end of the current loop body. Note: `Cycle' can only stand within a `while', `repeat' or a `for' loop.

Conforming to

`Cycle' is a Mac Pascal extension. Borland Pascal has `Continue' instead.

Example

     program CycleDemo;
     var
       Foo, Bar: Integer;
     begin
       WriteLn ('Enter three numbers:');
       for Bar := 1 to 3 do
         begin
           ReadLn (Foo);
           if Foo < 5 then
             Cycle;
           WriteLn ('Your number was greater than 5.')
         end
     end.

See also

Loop Control Statements, Break, Continue, Exit, Halt, Leave, Return, goto.


Next: , Previous: Cycle, Up: Reference

Date

Synopsis

     function Date (T: TimeStamp): packed array [1 .. Date_length] of Char;

Description

Date takes a TimeStamp parameter and returns the date as a string (in the form of a packed array of Char). Date_length is an implementation defined invisible constant.

Conforming to

`Date' is an ISO 10206 Extended Pascal extension.

Example

Set TimeStamp.

See also

TimeStamp, GetTimeStamp, Time, Date And Time Routines.


Next: , Previous: Date, Up: Reference

Dec

Synopsis

For ordinal types:

     procedure Dec (var x: ordinal_type);

or

     procedure Dec (var x: ordinal_type; Amount: and_integer_type);

For pointer types:

     procedure Dec (var p: any_pointer_type);

or

     procedure Dec (var p: any_pointer_type; Amount: and_integer_type);

Description

For ordinal types, `Dec' decreases the value of `x' by one or by `amount' if specified.

If the argument `p' is pointing to a specified type (typed pointer), `Dec' decreases the address of `p' by the size of the type `p' is pointing to or by `amount' times that size respectively. If `p' is an untyped pointer (i.e. `p' is of type Pointer), `p' is decreased by one, otherwise by `amount' if specified.

Conforming to

`Dec' is a Borland Pascal extension. The combination of the second argument with application to pointers is a GNU Pascal extension.

Example

     program DecDemo;
     var
       x: Integer;
       y: array [1 .. 5] of Integer;
       p: ^Integer;
     begin
       x := 9;
       Dec (x, 10);  { yields -1 }
       {$X+}         { Turn on extended systax }
       p := @y[5];   { p points to y[5] }
       Dec (p, 3)    { p points to y[2] }
     end.

See also

Inc, Pred, Succ, Pointer Arithmetics.


Next: , Previous: Dec, Up: Reference

DefineSize

(Under construction.)

Synopsis

     procedure DefineSize (var F: any_file; NewSize: Integer);

Description

Conforming to

`DefineSize' is a GNU Pascal extension.

Example

See also


Next: , Previous: DefineSize, Up: Reference

Delete

(Under construction.)

Synopsis

     procedure Delete (var S: String; FirstChar, Count: Integer);

or

     procedure Delete (var S: String; FirstChar: Integer);

Description

Conforming to

`Delete' is a UCSD Pascal extension. The possibility to omit the third parameter is a GNU Pascal extension.

Example

See also


Next: , Previous: Delete, Up: Reference

destructor

(Under construction.)

Synopsis

Description

Object destructor.

Conforming to

`destructor' is an Object Pascal and a Borland Pascal extension.

Example

See also

Keywords.


Next: , Previous: destructor, Up: Reference

Discard

Synopsis

     Discard (Value);

Description

`Discard' does nothing, but tells the compiler that the value given as an argument is not further used. It can be applied, e.g., to routine parameters which are to be ignored, so no warning about them will be given with `-Wunused', or when calling a function and ignore its result.

An alternative for the latter case is to give the function the `ignorable' attribute. This is useful is the function's result is expected to be ignored regularly. If, however, a result is generally meaningful and only to be ignored in a particular case, using `Discard' is preferable.

Conforming to

`Discard' is a GNU Pascal extension.

Example

program DiscardDemo;

function Foo (a: Integer): Integer; begin WriteLn (a); Foo := a + 1 end;

{ Parameter `a' is there only to make the parameter list compatible to that of function `Foo'. } function Bar (a: Integer): Integer; begin Discard (a); { Tell the compiler that we intentionally do not use `a' in this function. } Bar := a + 1 end;

var c: Char; f: function (a: Integer): Integer;

begin Write ('With output? '); ReadLn (c); if LoCase (c) = 'y' then f := Foo else f := Bar; Discard (f (42)) { Call the function, but ignore its result } end.

See also


Next: , Previous: Discard, Up: Reference

Dispose

(Under construction.)

Synopsis

     Dispose (PointerVar: Pointer);

or

     Dispose (PointerVar: Pointer; tag_field_values);

or

     Dispose (ObjectPointerVar: Pointer; destructor_call);

Description

Conforming to

`Dispose' is defined in ISO 7185 Pascal and supported by most known Pascal variants, but not by UCSD Pascal. Its use for objects is a Borland Pascal extension.

Example

See also


Next: , Previous: Dispose, Up: Reference

div

Synopsis

     operator div (p, q: Integer) = r: Integer;

Description

Integer division operator.

Conforming to

`div' is defined in ISO 7185 Pascal and supported by all known Pascal variants.

Example

     program DivDemo;
     
     var
       a, b: Integer;
     
     begin
       a := 16;
       b := 7;
       WriteLn (a div b);  { `2' }
     end.

See also

Keywords.


Next: , Previous: div, Up: Reference

do

Synopsis

     for ... do
       statement

or

     while ... do
       statement

or

     with ... do
       statement

or

     to begin do
       statement

or

     to end do
       statement

Description

The `do' reserved word is used in combination with other Pascal keywords in many ways. For description and examples see the relevant reference sections: `for', `while', `with', `to begin', `to end'.

Conforming to

`do' is defined in ISO 7185 Pascal and supported by all known Pascal variants.

Example

See references.

See also

Keywords, for, while, with, to begin do, to end do.


Next: , Previous: do, Up: Reference

Double

(Under construction.)

Synopsis

     type
       Double = Real;

Description

`Double' is a synonym for the `Real' data type and supported for compatibility with other compilers.

Conforming to

`Double' is a Borland Pascal extension.

Example

     program DoubleDemo;
     var
       A: Double;  { There is nothing special with `Double'. }
       B: Real;
     begin
       A := Pi;
       A := B
     end.

See also


Next: , Previous: Double, Up: Reference

downto

Synopsis

     for variable := value1 downto value2 do
       statement

Description

The `downto' reserved word is used in combination with `for' to build a `for' loop.

Conforming to

`downto' is defined in ISO 7185 Pascal and supported by all known Pascal variants.

Example

program DowntoDemo; var i: Integer; begin for i := 10 downto 1 do WriteLn (i) end.

See also

Keywords, for.


Next: , Previous: downto, Up: Reference

else

Synopsis

As part of the if ... then ... else statement:

     if Boolean_expression then
       statement1
     else
       statement2

or, as part of the case ... else statement:

     case expression of
       selector: statement;
       ...
       selector: statement
     else  { ``otherwise'' instead of ``else'' is allowed }
       statement;
       ...
       statement
     end

Description

`else' is part of the `if ... then ... else' statement which provides a possibility to execute statements alternatively. In the case statement, `else' starts a series of statements which is executed if no selector fit in expression. In this situation, `else' is a synonym for otherwise.

Conforming to

`else' in `if' statements is defined in ISO 7185 Pascal and supported by all known Pascal variants. `else' in `case' statements is a Borland Pascal extension; ISO 10206 Extended Pascal has `otherwise' instead.

Example

     program ElseDemo;
     var
       i: Integer;
     begin
       Write ('Enter a number: ');
       ReadLn (i);
       if i > 42 then
         WriteLn ('The number is greater than 42')
       else
         WriteLn ('The number is not greater than 42')
     end.

See also

Keywords, if, case, otherwise.


Next: , Previous: else, Up: Reference

Empty

(Under construction.)

Synopsis

     function Empty (var F: any_file): Boolean;

Description

Conforming to

`Empty' is an ISO 10206 Extended Pascal extension.

Example

See also


Next: , Previous: Empty, Up: Reference

end

Synopsis

     begin
       statement;
       statement;
       ...
       statement
     end

Description

The reserved word `end' closes a `begin' ... `end'; statement which joins several statements together into one compound statement.

@@ end of a `case' statement @@ end of a record or object declaration @@ part of a `to end do' module destructor

Conforming to

`end' is defined in ISO 7185 Pascal and supported by all known Pascal variants.

Example

     program EndDemo;
     begin
       if True then
         WriteLn ('single statement');
       if True then
         begin  { clamp statement1 ... }
           WriteLn ('statement1');
           WriteLn ('statement2')
         end    { ... to statement2 }
     end.

See also

Keywords, begin end Compound Statement, begin


Next: , Previous: end, Up: Reference

EOF

(Under construction.)

Synopsis

     function EOF ([var F: any_file]): Boolean;

or

     function EOF: Boolean;

Description

Conforming to

`EOF' is defined in ISO 7185 Pascal and supported by all known Pascal variants.

Example

See also


Next: , Previous: EOF, Up: Reference

EOLn

(Under construction.)

Synopsis

     function EOLn ([var F: Text]): Boolean;

or

     function EOLn: Boolean;

Description

Conforming to

`EOLn' is defined in ISO 7185 Pascal and supported by all known Pascal variants.

Example

See also


Next: , Previous: EOLn, Up: Reference

EpsReal

(Under construction.)

Synopsis

Description

Conforming to

`EpsReal' is an ISO 10206 Extended Pascal extension.

Example

See also


Next: , Previous: EpsReal, Up: Reference

EQ

(Under construction.)

Synopsis

     function EQ (S1, S2: String): Boolean;

Description

Conforming to

`EQ' is an ISO 10206 Extended Pascal extension.

Example

See also


Next: , Previous: EQ, Up: Reference

EQPad

(Under construction.)

Synopsis

     function EQPad (S1, S2: String): Boolean;

Description

Conforming to

`EQPad' is a GNU Pascal extension.

Example

See also


Next: , Previous: EQPad, Up: Reference

Erase

(Under construction.)

Synopsis

     procedure Erase (var F: any_file);

Description

Conforming to

`Erase' is a Borland Pascal extension.

Example

See also


Next: , Previous: Erase, Up: Reference

except

Not yet implemented.

Synopsis

Conforming to

`except' is a Borland Delphi extension.

Example

See also

Keywords.


Next: , Previous: except, Up: Reference

Exclude

Synopsis

     Exclude (set_variable, ordinal_value);

Description

Remove (subtract) a single element from a set. ordinal_value must be compatible with the base type of set_variable. Exclude is equivalent to:

     set_variable := set_variable - [ordinal_value];

If set_variable does not contain ordinal_value, nothing happens.

Conforming to

`Exclude' is a Borland Pascal extension.

Example

     program ExcludeDemo;
     
     var
       Ch: Char;
       MyCharSet: set of Char;
     
     begin
       MyCharSet := ['P', 'N', 'L'];
       Exclude (MyCharSet , 'N')  { L, P }
     end.

See other examples in set and Set Operations.

See also

Keywords, Set Operations, set, in, Include.


Next: , Previous: Exclude, Up: Reference

Exit

Synopsis

     procedure Exit;

or

     procedure Exit (program);

or

     procedure Exit (Identifier);

Description

`Exit' without an argument leaves the currently executed procedure or function. Note: If `Exit' is called within the main program, it will be terminated instantly.

`Exit' with an argument that is `program' or the name of the current program, terminates the program, and is equivalent to `Halt'.

`Exit' with an argument that is the name of the current or an encompassing routine leaves that routine.

Conforming to

`Exit' is a UCSD Pascal extension. Borland Pascal only allows it without an argument.

Example

     program ExitDemo;
     
     procedure Foo (Bar: Integer);
     var
       Baz, Fac: Integer;
     begin
       if Bar < 1 then
         Exit;  { Exit `Foo' }
       Fac := 1;
       for Baz := 1 to Bar do
         begin
           Fac := Fac * Baz;
           if Fac >= Bar then
             Exit;  { Exit `Foo' }
           WriteLn (Bar,' is greater than ', Baz, '!, which is equal to ', Fac)
       end
     end;
     
     begin
       Foo (-1);
       Foo (789);
       Exit;            { Terminates program }
       Foo (987654321)  { This is not executed anymore }
     end.

See also

Break, Continue, Halt.


Next: , Previous: Exit, Up: Reference

Exp

Synopsis

     function Exp (x: Real): Real;

or

     function Exp (z: Complex): Complex;

Description

The exponential function `Exp' computes the value of e to the power of x, where the Euler number e = Exp (1) is the base of the natural logarithm.

Conforming to

The function `Exp' is defined in ISO 7185 Pascal; its application to complex values is defined in ISO 10206 Extended Pascal.

Example

     program ExpDemo;
     var
       z: Complex;
     begin
       z := Cmplx (1, - 2 * Pi);  { z = 1 - 2 pi i }
       z := Exp (z);  { yields e = Exp (1), since Exp ix = Cos x + i Sin x }
       WriteLn (Ln (Re (z)) : 0 : 5)  { prints 1 = Ln (Exp (1)) }
     end.

See also

Ln


Next: , Previous: Exp, Up: Reference

export

(Under construction.)

Synopsis

     export `interface_name' = (identifier, identifier, ...);

or

     export `interface_name' = all;

Description

Interface export for Extended Pascal modules.

`all' means to automatically export all identifiers declared in the interface module.

Conforming to

`export' is an ISO 10206 Extended Pascal extension. It also exists in Borland Pascal, but with a different meaning, not (yet) supported by GPC.

`export all' is a GNU Pascal extension.

Example

     program ExportDemo;
     
     import AllInterface in 'somemodule.pas';
     
     begin
       Bar (a);
       WriteLn (b)
     end.
     module SomeModule interface;
     
     export
       SomeInterface = (a);
       AllInterface = all;  { Same as `AllInterface = (a, b, Bar);' }
     
     var
       a, b: Integer;
     
     procedure Bar (i: Integer);
     
     end.
     
     module SomeModule implementation;
     
     procedure Bar (i: Integer);
     begin
       b := a
     end;
     
     to begin do
       a := 42;
     
     end.

See also

Keywords, Modules.


Next: , Previous: export, Up: Reference

exports

Not yet implemented.

Synopsis

Description

Library export.

Conforming to

`exports' is a Borland Pascal extension.

Example

See also

Keywords.


Next: , Previous: exports, Up: Reference

Extend

(Under construction.)

Synopsis

     procedure Extend (var F: any_file; [FileName: String;]
                                         [BlockSize: Cardinal]);

Description

`Extend' opens a file for writing. If the file does not exist, it is created. If it does exist, the file pointer is positioned after the last element.

Like `Rewrite', `Reset' and `Append' do, `Reset' accepts an optional second parameter for the name of the file in the filesystem and a third parameter for the block size of the file. The third parameter is allowed only (and by default also required) for untyped files. For details, see Rewrite.

Conforming to

`Extend' is an ISO 10206 Extended extension. Borland Pascal has Append instead. The `BlockSize' parameter is a Borland Pascal extension. The `FileName' parameter is a GNU Pascal extension.

Example

     program ExtendDemo;
     var
       Sample: Text;
     begin
       Assign (Sample, 'sample.txt');
       Rewrite (Sample);
       WriteLn (Sample, 'Hello, World!');  { `sample.txt' now has one line }
       Close (Sample);
     
       { ... }
     
       Extend (Sample);
       WriteLn (Sample, 'Hello again!');  { `sample.txt' now has two lines }
       Close (Sample)
     end.

See also

Assign, Reset, Rewrite, Update, Append.


Next: , Previous: Extend, Up: Reference

Extended

(Under construction.)

Synopsis

     type
       Extended = LongReal;

Description

Conforming to

`Extended' is a Borland Pascal extension.

Example

     program ExtendedDemo;
     var
       a: Extended;
     begin
       a := 42;
       WriteLn (a)
     end.

See also


Next: , Previous: Extended, Up: Reference

external

(Under construction.)

Synopsis

     declaration external;

or

     declaration external name linker_name;

Description

Declaration of external object.

Conforming to

`external' is a UCSD Pascal extension.

Example

See also

Keywords.


Next: , Previous: external, Up: Reference

Fail

(Under construction.)

Synopsis

Description

Conforming to

`Fail' is a Borland Pascal extension.

Example

See also


Next: , Previous: Fail, Up: Reference

False

Synopsis

     type
       Boolean = (False, True);  { built-in type }

Description

`False' is one of the two Boolean values and is used to represent a condition which is never fullfilled. For example, the expression, `1 = 2' always yields `False'. It is the opposite of `True'. `False' has the ordinal value 0.

Conforming to

`False' is defined in ISO 7185 Pascal and supported by all known Pascal variants.

Example

     program FalseDemo;
     
     var
       a: Boolean;
     
     begin
       a := 1 = 2;  { yields False }
       WriteLn (Ord (False));  { 0 }
       WriteLn (a);  { False }
       if False then WriteLn ('This is not executed.')
     end.

See also

Boolean (Intrinsic), True, Boolean.


Next: , Previous: False, Up: Reference

far

Synopsis

Description

The `far' directive can be appended to a procedure or function heading but is ignored by GPC. It is there for Borland compatibility, only. (Since the GNU compilers provide a flat memory model, the distinction between `near' and `far' pointers is void.)

Conforming to

`far' is a Borland Pascal extension.

Example

     program FarDemo;
     
     var
       p: procedure;
     
     {$W no-near-far}  { Don't warn about the uselessness of `far' }
     
     procedure Foo; far;  { `far' has no effect in GPC }
     begin
       WriteLn ('Foo')
     end;
     
     begin
       p := Foo;  { Would also work without `far' in GPC. }
       p
     end.

See also

Keywords, near.


Next: , Previous: far, Up: Reference

file

(Under construction.)

Synopsis

In type definitions:

     file of Type

or

     file

Description

Non-text file type declaration.

Conforming to

Typed files (`file of Type') are defined in ISO 7185 Pascal and supported by all known Pascal variants. Untyped files (`file') are a Borland Pascal extension.

Example

See also

Keywords, Text, AnyFile.


Next: , Previous: file, Up: Reference

FilePos

(Under construction.)

Synopsis

     function FilePos (var F: any_file): Integer;

Description

Conforming to

`FilePos' is a Borland Pascal extension.

Example

See also


Next: , Previous: FilePos, Up: Reference

FileSize

(Under construction.)

Synopsis

     function FileSize (var F: any_file): Integer;

Description

Conforming to

`FileSize' is a Borland Pascal extension.

Example

See also


Next: , Previous: FileSize, Up: Reference

FillChar

(Under construction.)

Synopsis

     procedure FillChar (var Dest; Count: SizeType; Val: Char);

or

     procedure FillChar (var Dest; Count: SizeType; Val: Byte);

Description

Conforming to

`FillChar' is a UCSD Pascal extension.

Example

See also


Next: , Previous: FillChar, Up: Reference

finalization

(Under construction.)

Synopsis

Description

Unit finalization.

It is equivalent to Extended Pascal's `to end do'.

Conforming to

`finalization' is a Borland Delphi extension.

Example

See also

Keywords, initialization, to end do.


Next: , Previous: finalization, Up: Reference

Finalize

(Under construction.)

Synopsis

     procedure Finalize (var Aynthing);

Description

`Finalize' does all necessary clean-ups for the parameter. This is normally done automatically when a variable goes out of scope, so you need to call `Finalize' only in special situations, e.g. when you deallocate a dynamic variable with `FreeMem' rather than `Dispose'.

Using a variable after applying `Finalize' to it (and without applying `Initialize' to it again) is invalid and produces undefined results.

Conforming to

`Finalize' is a Borland Delphi extension.

Example

See also

Initialize, Dispose, FreeMem.


Next: , Previous: Finalize, Up: Reference

finally

Not yet implemented.

Synopsis

Conforming to

`finally' is a Borland Delphi extension.

Example

See also

Keywords.


Next: , Previous: finally, Up: Reference

Flush

(Under construction.)

Synopsis

     procedure Flush (var F: any_file);

Description

Conforming to

`Flush' is a Borland Pascal extension.

Example

See also


Next: , Previous: Flush, Up: Reference

for

Synopsis

For ordinal index variables:

     for ordinal_variable := initial_value to final_value do
       statement

or

     for ordinal_variable := initial_value downto final_value do
       statement

For sets:

     for set_element_type_variable in some_set do
       statement

For pointer index variables:

     for pointer_variable := initial_address to final_address do
       statement

or

     for pointer_variable := initial_address downto final_address do
       statement

@@ Set member iteration

Description

The `for' statement is a count loop. For further information see for Statement.

Conforming to

`for' is defined in ISO 7185 Pascal and supported by all known Pascal variants. Iteration of Pointers is a Borland Pascal extension. Set member iteration is an ISO 10206 Extended Pascal extension.

Example

     program ForDemo;
     var
       CharSet: set of Char;
       c: Char;
       n: Integer;
       Fac: array [0 .. 10] of Integer;
       PInt: ^Integer;
     begin
       CharSet := ['g', 'p', 'c'];
       for c in CharSet do
         WriteLn (c);  { prints `c', `g', `p' in three lines }
       Fac[0] := 1;
       for n := 1 to 10 do  { computes the factorial of n for n = 0 .. 10 }
         Fac[n] := Fac[n - 1] * n;
       {$X+}
       { prints n! for n = 0 .. 10 }
       for PInt := @Fac[0] to @Fac[10] do
         WriteLn (PInt - @Fac[0], '! = ', PInt^)
     end.

See also

Keywords, Set Types, Pointer Arithmetics


Next: , Previous: for, Up: Reference

FormatString

(Under construction.)

Synopsis

Description

Conforming to

`FormatString' is a GNU Pascal extension.

Example

See also


Next: , Previous: FormatString, Up: Reference

forward

(Under construction.)

Synopsis

Description

Declaration of a routine whose definition follows below.

Conforming to

`forward' is a UCSD Pascal extension.

Example

See also

Keywords.


Next: , Previous: forward, Up: Reference

Frac

Synopsis

     function Frac (x: Real): Real;

Description

`Frac' returns the fractional part of a floating point number.

Conforming to

`Frac' is a Borland Pascal extension.

Example

     program FracDemo;
     
     begin
       WriteLn (Frac (12.345) : 1 : 5);  { 0.34500 }
       WriteLn (Int (12.345) : 1 : 5);  { 12.00000 }
       WriteLn (Round (12.345) : 1);  { 12 }
       WriteLn (Trunc (12.345) : 1);  { 12 }
     
       WriteLn (Frac (-12.345) : 1 : 5);  { -0.34500 }
       WriteLn (Int (-12.345) : 1 : 5);  { -12.00000 }
       WriteLn (Round (-12.345) : 1);  { -12 }
       WriteLn (Trunc (-12.345) : 1);  { -12 }
     
       WriteLn (Frac (12.543) : 1 : 5);  { 0.54300 }
       WriteLn (Int (12.543) : 1 : 5);  { 12.00000 }
       WriteLn (Round (12.543) : 1);  { 13 }
       WriteLn (Trunc (12.543) : 1);  { 12 }
     
       WriteLn (Frac (-12.543) : 1 : 5);  { -0.54300 }
       WriteLn (Int (-12.543) : 1 : 5);  { -12.00000 }
       WriteLn (Round (-12.543) : 1);  { -13 }
       WriteLn (Trunc (-12.543) : 1);  { -12 }
     end.

See also

Real Types, Real, Int, Round, Trunc.


Next: , Previous: Frac, Up: Reference

FrameAddress

(Under construction.)

Synopsis

Description

Conforming to

`FrameAddress' is a GNU Pascal extension.

Example

See also


Next: , Previous: FrameAddress, Up: Reference

FreeMem

Synopsis

     procedure FreeMem (var p: Pointer; Size: Cardinal);

or

     procedure FreeMem (var p: Pointer);

Description

Releases a chunk of memory previously allocated using `GetMem'. The parameter Size is optional. Its value is currently ignored.

Since Extended Pascal's schemata provide a cleaner way to implement dynamical arrays and such, we recommend using `GetMem' and `FreeMem' only for low-level applications or for interfacing with other languages.

Conforming to

`FreeMem' is a Borland Pascal extension. `FreeMem' with only one parameter is a GNU Pascal extension.

Example

See GetMem.

See also

GetMem, Schema Types, Dispose, Mark, Release.


Next: , Previous: FreeMem, Up: Reference

function

(Under construction.)

Synopsis

Description

Function declaration.

Conforming to

`function' is defined in ISO 7185 Pascal and supported by all known Pascal variants.

Example

See also

Keywords.


Next: , Previous: function, Up: Reference

GE

(Under construction.)

Synopsis

     function GE (S1, S2: String): Boolean;

Description

Conforming to

`GE' is an ISO 10206 Extended Pascal extension.

Example

See also


Next: , Previous: GE, Up: Reference

GEPad

(Under construction.)

Synopsis

     function GEPad (S1, S2: String): Boolean;

Description

Conforming to

`GEPad' is a GNU Pascal extension.

Example

See also


Next: , Previous: GEPad, Up: Reference

Get

(Under construction.)

Synopsis

     procedure Get (var F: typed_file);

Description

Conforming to

`Get' is defined in ISO 7185 Pascal and supported by all known Pascal variants except UCSD/Borland Pascal and its variants.

Example

See also


Next: , Previous: Get, Up: Reference

GetMem

Synopsis

     procedure GetMem (var p: Pointeger; Size: Cardinal);

Description

Allocates dynamical storage on the heap and returns a pointer to it in `p'.

Since Extended Pascal's schemata provide a cleaner way to implement dynamical arrays and such, we recommend using `GetMem' and `FreeMem' only for low-level applications.

Conforming to

`GetMem' is a Borland Pascal extension.

Example

The Borland-comatibility unit `Graph' from the BPcompat package supports a `GetImage' and a `PutImage' procedure which need a variable of size `ImageSize' as a buffer. Since these are “black box” routines, the buffer can't reasonably be a schema providing a dynamical array. Instead, we have to use `GetMem' and `FreeMem' for dynamical memory allocation.

     program GetMemDemo;
     var
       Buffer: Pointer;
       Size: Cardinal;
     begin
       Size := Random (10000);  { the size can be determined at run time }
       GetMem (Buffer, Size);
       { Do something with Buffer }
       FreeMem (Buffer)  { or: FreeMem (Buffer, Size) }
     end.

See also

FreeMem, New, Schema Types.


Next: , Previous: GetMem, Up: Reference

GetTimeStamp

Synopsis

     procedure GetTimeStamp (var T: TimeStamp);

Description

GetTimeStamp gets the current local date and time as a TimeStamp record containing the Year, Month, Day, Hour, Minute, Second, and so on.

Conforming to

`GetTimeStamp' is an ISO 10206 Extended Pascal extension.

Example

Set TimeStamp.

See also

TimeStamp, Date, Time, Date And Time Routines.


Next: , Previous: GetTimeStamp, Up: Reference

goto

(Under construction.)

Synopsis

     goto label

Description

The `goto' statement transfers control to statement with the label `label'.

Conforming to

`goto' is defined in ISO 7185 Pascal and supported by all known Pascal variants.

Example

See also

Keywords.


Next: , Previous: goto, Up: Reference

GT

(Under construction.)

Synopsis

     function GT (S1, S2: String): Boolean;

Description

Conforming to

`GT' is an ISO 10206 Extended Pascal extension.

Example

See also


Next: , Previous: GT, Up: Reference

GTPad

(Under construction.)

Synopsis

     function GTPad (S1, S2: String): Boolean;

Description

Conforming to

`GTPad' is a GNU Pascal extension.

Example

See also


Next: , Previous: GTPad, Up: Reference

Halt

Synopsis

     Halt;

or

     Halt (ExitCode: Integer);

Description

`Halt' terminates the program with exitcode 0. If `ExitCode', is specified, it is returned by `Halt' on exit.

Conforming to

`Halt' is an Extended Pascal and a UCSD Pascal extension.

Example

     program HaltDemo;
     begin
       WriteLn ('This string will always be this program''s output.');
       Halt;  { Terminate right here and right now. }
       WriteLn ('And this string won''t ever!')
     end.

See also

Break, Continue, Exit, Return, goto.


Next: , Previous: Halt, Up: Reference

High

Synopsis

     function High (ordinal_type_or_variable): ordinal_type;

or

     function High (array_type_or_variable): array_index_type;

or

     function High (string_variable): Integer;

Description

For ordinal types or variables of that type, `High' returns the highest value a variable of that type can assume.

For array types or variables of that type, `High' returns the highest index a variable of that type can assume. Note: the result is of the same type as the array index is. If the array has more than one dimension, `High' returns the highest index in the first dimension.

If the argument is a string variable, `High' returns the discriminant of the string type (i.e. its capacity).

Conforming to

`High' is a Borland Pascal extension.

Example

     program HighDemo;
     type
       Colors = (Red, Green, Blue);
     var
       Col: array [Colors] of (Love, Hope, Faithfulness);
       Foo: Colors;
       Bar: Integer;
       Baz: String (123);
     begin
       Foo := High (Col);             { yields Blue }
       Bar := Ord (High (Col[Foo]));  { yields Ord (Faithfulness), i.e., 2 }
       Bar := High (Integer);         { highest possible value of `Integer' }
       Bar := High (Baz)              { returns 123 }
     end.

See also

Low


Next: , Previous: High, Up: Reference

if

Synopsis

     if Boolean_expression then
       statement

or with an alternative statement:

     if Boolean_expression then
       statement1
     else
       statement2

Description

The `if ... then' statement executes statement1 depending on `Boolean expression' being true. If `else' is specified, it continues executing statement2 instead.

Conforming to

`if' is defined in ISO 7185 Pascal and supported by all known Pascal variants.

Example

     program IfDemo;
     var
       Foo, Bar: Boolean;
     begin
       Foo := True;
       Bar := False;
       if ((1 = 1) or (2 = 3)) and (Foo = not Bar) then
         begin
           { This is executed if either Foo is true but not Bar or vice versa }
           WriteLn ('Either Foo or Bar is true.');
           if Bar then
             WriteLn ('You will see this text if Bar is true.')
         end
       else  { This whole `else' branch is not executed }
         if 1 = 1 then
           if True = False then
             WriteLn ('This text is never written on screen.')
           else  { Note: This ``else'' belongs to ``if True = False'' }
             WriteLn ('This text is never written on screen as well.')
         else  { Note: This ``else'' belongs to ``if 1 = 1'' }
           WriteLn ('Nor is this.')
     end.

See also

Keywords, if Statement, else, then


Next: , Previous: if, Up: Reference

Im

Synopsis

     function Im (z: Complex): Real;

Description

`Im' extracts the imaginary part of the complex number `z'. The result is a real value.

Conforming to

`Im' is an ISO 10206 Extended Pascal extension.

Example

     program ImDemo;
     var
       z: Complex;
     begin
       z := Cmplx (1, 2);  { 1 + i * 2 }
       WriteLn (Im (z) : 0 : 5)  { 2.00000 }
     end.

See also

Cmplx, Re, Arg.


Next: , Previous: Im, Up: Reference

implementation

(Under construction.)

Synopsis

Description

Module or unit implementation part.

Conforming to

`implementation' is an Extended Pascal and a UCSD Pascal extension.

Example

See also

Keywords.


Next: , Previous: implementation, Up: Reference

import

Synopsis

     program @@fragment foo;
     
     import
       bar1;
       bar3 (baz1 => glork1) in 'baz.pas';
       bar2 only (baz2, baz3 => glork2);
       bar4 qualified;
     
     [...]

In module:

     module @@fragment Bar;
     
     import
       bar1;
       bar3 (baz1 => glork1) in 'baz.pas';
       bar2 only (baz2, baz3 => glork2);
       bar4 qualified;
     
     [...]

Description

The reserved word `import' in the import part of a program makes the program import an interface.

The `in' above tells GPC to look for the module in the specified file; otherwise the file name is derived from the name of the interface by adding first .p, then .pas – which only works if the name of the exported interface coincides with the file name.

The symbol `=>' denotes import renaming: The entity which is exported under the name `baz1' by the interface `bar3' will be known under the new name `glork1' in the program.

The `only' qualifier means that only the listed identifiers will be imported from the interface. Renaming works together with `only', too.

The `qualified' qualifier means “qualified import”: The imported identifiers will be accessible only trough a “qualified name”. The entity which is exported under the name `baz2' by the interface `bar4' will be accessible as `bar4.baz2'.

There must be at most one import part at the begining of a block. Each module or function/procedure (and also main program) can have its own import part. A single import part can import arbitrarly many interfaces.

The interfaces needn't be exported by Extended Pascal modules but may be UCSD/Borland Pascal units as well. GPC also allows `import' parts in units.

Conforming to

`import' and modules in general are an ISO 10206 Extended Pascal extension.

Example

See also

Keywords, module, unit, uses.


Next: , Previous: import, Up: Reference

in

Synopsis

As part of the set membership test, as a boolean expression:

     ordinal_value in set_expression

or, as part of a `for' loop iterating through a set:

     for ordinal_variable in set_expression do ...

Description

When `in' is used as a membership test, it acts as a binary operator taking ordinal_value as its left parameter and set_expression as its right parameter and returning a boolean result which is true if set_expression contains the element ordinal_value.

When `in' is used as part of a `for' loop, it iterates ordinal_variable over the elements contained in set_expression, that is every <