This is ../p/doc/info/gpc.info, produced by makeinfo version 4.7 from
gpc.texi.

INFO-DIR-SECTION GNU programming tools
START-INFO-DIR-ENTRY
* GPC: (gpc).                   The GNU Pascal Compiler.
END-INFO-DIR-ENTRY
INFO-DIR-SECTION Individual utilities
START-INFO-DIR-ENTRY
* GPC: (gpc)Invoking GPC.       The GNU Pascal Compiler.
END-INFO-DIR-ENTRY

   This file documents the GNU Pascal Compiler.

   Permission is granted to make and distribute verbatim copies of this
manual provided the copyright notice and this permission notice are
preserved on all copies.

   Copyright (C) 1988-2005 Free Software Foundation, Inc.

   Permission is granted to copy and distribute modified versions of
this manual under the conditions for verbatim copying, provided also
that the sections entitled "GNU General Public License", "The GNU
Project", "The GNU Manifesto" and "Funding for free Software" are
included exactly as in the original, and provided that the entire
resulting derived work is distributed under the terms of a permission
notice identical to this one.

   Permission is granted to copy and distribute translations of this
manual into another language, under the above conditions for modified
versions, except that the sections entitled "GNU General Public
License", "The GNU Project", "The GNU Manifesto" and "Funding for Free
Software" and this permission notice, may be included in translations
approved by the Free Software Foundation instead of in the original
English.


File: gpc.info,  Node: Run Time System,  Next: GPC Units,  Prev: 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-2005 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__ <> 20050331}
     {$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 = 2 .. 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;
       const s: String); 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;


File: gpc.info,  Node: GPC Units,  Prev: 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 (*note 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,
*Note Run Time System::).

* Menu:

* CRT::          BP compatibility: CRT & WinCRT, portable, with many extensions
* Dos::          BP compatibility: Dos
* DosUnix::      Overcome some differences between Dos and Unix
* FileUtils::    Higher level file and directory handling
* GMP::          Arithmetic with unlimited size and precision
* GPCUtil::      Turbo Power compatibility, etc.
* HeapMon::      Primitive heap checking
* Intl::         Internationalization
* MD5::          `MD5' Message Digests
* Overlay::      BP compatibility: Overlay
* Pipes::        Start a child process, connected with pipes, also on Dos
* Ports::        BP compatibility (partly): `Port', `PortW' arrays
* Printer::      BP compatibility: Printer, portable
* RegEx::        Regular Expression matching and substituting
* Strings::      BP compatibility: Strings
* StringUtils::  Higher level string handling
* System::       BP compatibility: System
* TFDD::         Some text file tricks
* Trap::         Trap runtime errors
* Turbo3::       BP compatibility: Turbo3
* WinDos::       BP compatibility: WinDos


File: gpc.info,  Node: CRT,  Next: Dos,  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-2005 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');


File: gpc.info,  Node: Dos,  Next: DosUnix,  Prev: 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, *Note BP
Incompatibilities::.

   The same functionality and much more is available in the Run Time
System, *Note 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-2005 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}


File: gpc.info,  Node: DosUnix,  Next: FileUtils,  Prev: 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-2005 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;


File: gpc.info,  Node: FileUtils,  Next: GMP,  Prev: 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-2005 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);


File: gpc.info,  Node: GMP,  Next: GPCUtil,  Prev: 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-2005 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);


File: gpc.info,  Node: GPCUtil,  Next: HeapMon,  Prev: 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-2005 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;


File: gpc.info,  Node: HeapMon,  Next: Intl,  Prev: 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-2005 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);


File: gpc.info,  Node: Intl,  Next: MD5,  Prev: 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.

     { 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-2005 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);


File: gpc.info,  Node: MD5,  Next: Overlay,  Prev: 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.

     { Functions to compute MD5 message digest of files or memory blocks,
       according to the definition of MD5 in RFC 1321 from April 1992.

       Copyright (C) 1995, 1996, 2000-2005 Free Software Foundation, Inc.

       Author: Frank Heckenbach <frank@pascal.gnu.de>

       Based on the C code written by Ulrich Drepper
       <drepper@gnu.ai.mit.edu>, 1995 as part of glibc.

       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 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 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);

     { Computes MD5 message digest for the contents of the file f. }
     procedure MD5File (var f: File; var MD5: TMD5); attribute
       (iocritical);

     { Initializes a MD5 value with zeros. }
     procedure MD5Clear (var MD5: TMD5);

     { Compares two MD5 values for equality. }
     function MD5Compare (const Value1, Value2: TMD5): Boolean;

     { Converts an MD5 value to a string. }
     function MD5Str (const MD5: TMD5) = s: MD5String;

     { Converts a string to an MD5 value. Returns True if successful. }
     function MD5Val (const s: String; var MD5: TMD5): Boolean;

     { Composes two MD5 values to a single one. }
     function MD5Compose (const Value1, Value2: TMD5) = Dest: TMD5;


File: gpc.info,  Node: Overlay,  Next: Pipes,  Prev: 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-2005 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;


File: gpc.info,  Node: Pipes,  Next: Ports,  Prev: 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-2005 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);


File: gpc.info,  Node: Ports,  Next: Printer,  Prev: 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-2005 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}


File: gpc.info,  Node: Printer,  Next: RegEx,  Prev: 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-2005 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);


File: gpc.info,  Node: RegEx,  Next: Strings,  Prev: 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-2005 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;


File: gpc.info,  Node: Strings,  Next: StringUtils,  Prev: 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, *Note 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-2005 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';


File: gpc.info,  Node: StringUtils,  Next: System,  Prev: 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-2005 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);


File: gpc.info,  Node: System,  Next: TFDD,  Prev: 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-2005 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;


File: gpc.info,  Node: TFDD,  Next: Trap,  Prev: 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-2005 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);


File: gpc.info,  Node: Trap,  Next: Turbo3,  Prev: 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-2005 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;


File: gpc.info,  Node: Turbo3,  Next: WinDos,  Prev: 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-2005 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;

