This chapter is still under development.
This chapter tells you how the source of a valid GNU Pascal program should look like. You can use it as tutorial about the GNU Pascal language, but since the main goal is to document all special GPC features, implementation-dependent stuff, etc., expect a steep learning curve.
This chapter does not cover how to compile your programs and to produce an executable -- this is discussed above in section Command Line Options supported by GNU Pascal..
A source file accepted by GNU Pascal may contain up to one program, zero or more ISO-style modules, and/or zero or more UCSD-style units. Units and modules can be mixed in one project.
One trivial example for a valid GPC source file follows. Note that the code below may either be in one source file, or else the unit and the program may be in separate source files.
unit DemoUnit;
interface
procedure Hello;
implementation
procedure Hello;
begin
WriteLn ('Hello, world!')
end;
end.
program UnitDemo;
uses
DemoUnit;
begin
Hello
end.
A generic GNU Pascal program looks like the following:
program name (Input, Output); import part declaration part begin statement part end.
The program headline may be omitted in GPC, but a warning
will be given except in `--borland-pascal' mode.
While the program parameters (usually `Input', `Output') are obligatory in ISO Pascal if you want to use `ReadLn' and `WriteLn', they are optional in GNU Pascal. GPC will warn about such missing parameters in `--extended-pascal' mode. However if you give parameters to the program headline, they work like ISO requires.
The import part consists either of an ISO-style `import' specification or a UCSD/Borland-style `uses' clause. While `import' is intended to be used with interfaces exported by ISO-10206 Extended Pascal modules, and `uses' is intended to be used with units, this is not enforced. (See also section uses, section import.)
The declaration part consists of label, constant, type, variable or subroutine declarations in free order. However, every identifier must be declared before it is used. The only exception are type identifiers pointing to another type identifier which may be declared below.
The statement part consists of a sequence of statements.
As an extension, GPC supports a "declaring statement" which can be used in the statement part to declare variables (see section var).
A label declaration has the following look:
label label name, ..., label;
A label declaration part starts with the reserved word label,
which contains a list of labels.
See also section label, section goto
A constant declaration has the following look:
const constant identifier = constant expression; ... constant identifier = constant expression;
A constant declaration part starts with the reserved word const.
It declares a constant identifier which is defined by
constant expression. This expression has to be evaluatable during
compilation time, i.e. it can include numbers, parentheses, predefined
operators, sets and type casts (the last, however, is a Borland extension).
In ISO-7185 Pascal, constant expression must be a constant or
a set. All Pascal Dialects but ISO-Pascal allow the use of these
intrinsic functions in constant expression:
section Abs, section Round, section Trunc,
section Chr, section Ord,
section Length, section Pred, section Succ,
section SizeOf, section Odd.
In Borland Pascal, in the constant declaration part variables can be declared as well, which are given an initial value. These variables are called "typed constants". It is good style to avoid this use, especially since Extended Pascal and GNU Pascal allow to initialize a variable in variable declaration part or give a type a preset value on declaration.
const
FiveFoo = 5;
StringFoo = 'string constant';
AlphabetSize = Ord ('Z') - Ord ('A') + 1;
type
PInteger = ^Integer; { Define a pointer to an Integer }
const
{ Constant which holds a pointer to an Integer at address 1234 }
AddressFoo = PInteger (1234);
const i : Integer = 0;If you want to use it as a constant only, that's perfectly fine. However, if you modify `i', we suggest to translate the declaration to an initialized variable. The EP syntax is:
var i : Integer value 0;GPC supports this as well as the following mixtureof dialects:
var i : Integer = 0;Furthermore, you can also assign initialization values to types:
program InitTypeDemo; type MyInteger = Integer value 42; var i : MyInteger; begin WriteLn (i) end.Here, all variables of type MyInteger are automatically initialized to 0 when created.
program BPArrayInitDemo;
const
MyStringsCount = 5;
type
Ident = String [20];
const
MyStrings : array [1 .. MyStringsCount] of Ident =
('export', 'implementation', 'import',
'interface', 'module');
begin
end.
And the following way in EP:
program EPArrayInitDemo;
{$W no-field-name-problem} { avoid a warning by GPC }
const
MyStringsCount = 5;
type
Ident = String (20);
var
MyStrings : array [1 .. MyStringsCount] of Ident value
[1 : 'export'; 2 : 'implementation'; 3 : 'import';
4 : 'interface'; 5 : 'module'];
begin
end.
There seem to be pros and cons to each style. GPC supports both as
well as just about any thinkable mixture of them.
Some folks don't like having to specify an index since it requires
renumbering if you want to add a new item to the middle. However, if
you index by an enumerated type, you might be able to avoid major
renumbering by hand.
See also section Subroutine Parameter List Declaration
A type declaration looks like this:
type type identifier = type definition; ... type identifier = type definition;
or, with preset content:
type type identifier = type definition value constant expression; ... type identifier = type definition value constant expression;
A type declaration part begins with the reserved word type.
It declares a type identifier which is defined by type definition.
A type definition either can be an array, a record, a schema, a set, an
object, a subrange, an enumerated type, a pointer to another type identifier
or simply another type identifier which is to alias.
If a schema type is to be declared, type identifier is followed by a
discriminant enclosed in parentheses:
type identifier (discriminant) = schema type definition;
If value is specified, followed by a constant satisfying
the type definition, every variable of this type is initialized with
constant expression, unless it is initialized by value itself.
The reserved word value can be replaced by `=', however
value is not allowed in ISO-Pascal and Borland Pascal, and the
replacement by `=' is not allowed in Extended Pascal.
Type declaration example:
type
{ This side is the } { That side is the }
{ type declaration } { type definition }
arrayfoo = array [0..9] of Integer; { array definition }
recordfoo = record { record definition }
bar : Integer;
end;
{ schema def with discriminant ``x,y : Integer'' }
schemafoo (x,y : Integer) = array [x..y] of Integer;
charsetfoo = set of Char; { Def of a set }
objectfoo = object { Def of an object }
procedure DoAction;
constructor Init;
destructor Done;
end;
subrangefoo = -123..456; { subrange def }
enumeratedfoo = (Pope,John,the,Second); { enum type def }
{ Def of a pointer to another type identifier }
pinteger = ^arrayfoo;
{ Def of an alias name for another type identifier }
identityfoo = Integer;
{ Def of an integer which was initialized by 123 }
initializedfoo = Integer value 123;
See also section Type Definition, section Data Types, section Variable Declaration
A variable declaration looks like this:
var variable identifier: type identifier; ... variable identifier: type identifier;
or
var variable identifier: type definition; ... variable identifier: type definition;
and with initializing value:
var variable identifier: type identifier value constant expression; ... variable identifier: type identifier value constant expression;
or
var variable identifier: type definition value constant expression; ... variable identifier: type definition value constant expression;
A variable declaration part begins with the reserved word var.
It declares a variable identifier whose type
either can be specified by a type identifier, or by a type definion which
either can be an array, a record, a set, a subrange, an enumerated type
or a pointer to an type identifier.
If value is specified followed by a constant expression satisfying
the specified type, the variable declared is initialized with
constant expression.
The reserved word value can be replaced by `=', however
value is not allowed in ISO-Pascal and Borland Pascal, and the
replacement by `=' is not allowed in Extended Pascal.
See also section Type Definition, section Type Declaration, section Data Types, section The Declaring Statement, section Subroutine Parameter List Declaration
procedure procedure identifier; declaration part begin statement part end;
or with a parameter list:
procedure procedure identifier (parameter list); declaration part begin statement part end;
A procedure is quite like a sub-program: The declaration part consists of label, constant, type, variable or subroutine declarations in free order. The statement part consists of a sequence of statements. If parameter list is specified, parameters can be passed to the procedure and can be used in statement part. A recursive procedure call is allowed.
See also section The Function, section Subroutine Parameter List Declaration
function function identifier: function result type; declaration part begin statement part end;
or with a parameter list:
function function identifier (parameter list): funcion result type; declaration part begin statement part end;
A function is a subroutine which has a return value of type function result type. It is structured like the program: the declaration part consists of label, constant, type, variable or subroutine declarations in free order. The statement part consists of a sequence of statements. If parameter list is specified, parameters can be passed to the function and can be used in statement part. The return value is set via an assignment:
function identifier := expression
Recursive function calls are allowed. Concerning the result type, ISO-7185 Pascal and Borland Pascal only allow the intrinsic types, subranges, enumerated types and pointer types to be returned. In Extended Pascal, function result type can be every assignable type. Of course, there are no type restrictions in GNU Pascal as well. If extended syntax is switched on, functions can be called like procedures via procedure call statement.
See also section The Procedure, section Subroutine Parameter List Declaration, section Data Types
GNU Pascal allows to define operators which can be used the infix style in expressions. For a more detailed description, see section Operators
parameter; ...; parameter
Value parameters are declared this way:
parameter identifier: parameter type
where parameters of the same type be listed, separated by commata:
parameter identifier, ..., parameter identifier: parameter type
If var is specified before a parameter, which is an USCD extension,
the compiler is told to pass the argument by reference, i.e. the parameter
passed to is expected to be an L-value whose type is parameter type
if specified, else it is compatible with any type:
var parameter identifier: parameter type
or without type specification:
var parameter identifier
This declaration is necessary if the parameter is to be modified within a block and to hold its value still after return. Otherwise, the parameter remains unchanged after block exit, since it is passed by value, and therefore it is called value parameter.
A parameter of this kind is called variable parameter and corresponds to an L-value pointer (to type identifier if specified). As a Borland Pascal extension, there are also constant parameters which are not allowed to be changed in the related statement part. Like variable parameters, the type needs not to be declared; in this case parameter identifier is treated as a typeless parameter.
const parameter identifier: parameter type
or without any further type specification:
const parameter identifier
As an Extended Pascal extension, there is a way to declare procedural parameters directly:
procedure parameter identifier
or without type specification:
function parameter identifier: parameter identifier result type
Example for parameter lists:
procedure Foo (var Bar; var Baz: Integer; const Fred: Integer);
procedure Glork1 (function Foo: Integer; procedure Bar (Baz: Integer));
begin
Bar (Foo)
end;
begin
baz := Integer (Bar) + Fred
end;
See also section Data Types
The way an assignment looks like:
L-value := expression;
This statement assigns any valid expression to L-value. Make sure that the result of expression is compatible with L-value, otherwise an compilation error is reported. The `:=' is called assignment operator. As long as L-value and expression are type compatible, they are assignment compatible for any definable type as well.
It looks like that:
begin statement; statement; ... statement end
This statement joins several statements together into one compound statement which is treated as a single statement by the compiler. The finishing semicolon before `end' can be left out.
This statement has the following look:
if boolean expression then statement
or with an alternative statement:
if boolean expression then statement1 else statement2
The `if' ... `then' statement consists of a boolean expression and a statement, which is conditionally executed if the evaluation of boolean expression yields true.
If `if' ... `then' ... `else' is concerned, statement1 is executed depending on boolean expression being true, otherwise statement2 is executed alternatively. Note: the statement before else must not finish with a semicolon.
case expression of selector: statement; ... selector: statement; end
or, with alternative statement sequence:
case ordinal expression of
selector: statement;
...
selector: statement;
otherwise { ``else'' instead of ``otherwise'' allowed }
statement;
...
statement;
end
or, as part of the invariant record type definition:
type
foo = record
field declarations
case bar: variant type of
selector: (field declarations);
selector: (field declarations);
...
end;
or, without a variant selector field,
type
foo = record
field declarations
case variant type of
selector: (field declarations);
selector: (field declarations);
...
end;
The case statement compares the value of ordinal expression
to each selector, which can be a constant, a subrange, or a list of
them separated by commata, being compatible with the result of
ordinal expression.
Note: duplicate selectors or range crossing is not allowed unless
{$borland-pascal} is specified. In case of
equality the corresponding statement is executed. If otherwise
is specified and no appropriate selector matched the expression, the
series of statements following otherwise is executed. As a synonym
for otherwise, else can be used. The semicolon before
otherwise is optional.
@@ ???? The expression must match one of the selectors in order to continue, unless an alternative statement series is specified.
For case in a variant record type definition, see section Record Types.
See also section if Statement
For ordinal index variables:
for ordinal variable := initial value to final value do statement
or
for ordinal variable := initial value downto final value do statement
For sets:
for set element type variable in some set do statement
For pointer index variables:
for pointer variable := initial address to final address do statement
or
for pointer variable := initial address downto final address do statement
The for statement is a control statement where an index variable assumes every value of a certain range and for every value the index variable assumes statement is executed. The range can be specified by two bounds (which must be of the same type as the index variable, i.e. ordinal or pointers) or by a set.
For ordinal index variables: If `to' is specified, the index counter is increased by one as long as initial value is less or equal to final value, if `downto' is specified, it is decreased by one as long as initial value is greater or equal to final value.
For pointer index variables: If `to' is specified, the index counter is increased by the size of the type the index variable points to (if it is a typed pointer, otherwise by one if it is typeless) as long as initial address is less or equal to final address, if `downto' is specified, it is decreased by a corresponding value as long as initial address is greater or equal to final address. Since gpc provides a flat memory modell, all addresses are linear, so they can be compared.
For sets: statement is executed with the index variable (which must be ordinal and of the same type as the set elements) assuming every element in some set, however note that a set is a not-ordered structure.
Note: A modification of the index variable may result in unpredictable action.
See also section Set Types, section Pointer Arithmetics, section repeat Statement, section for Statement
The while loop has the following form
while boolean expression do statement
The while statement declares a loop which is executed while
boolean expression is true. Since the terminating condition is checked
before execution of the loop body, statement may never be executed.
See also section repeat Statement, section for Statement
repeat statement; ... statement; until boolean expression
The repeat ... until statement declares a loop which is
repeated until boolean expression is true. Since the terminating
condition is checked after execution of the loop body, the statement
sequence is executed at least once.
See also section while Statement, section for Statement
@@ ????
asm (StatementList : String);
The asm inline statement is a GNU extension. It requires its paramenter
to be AT&T-noted assembler statements, and therefore it is not compatible with
that one of Borland Pascal. statementlist is a string containing asm
statements seperated by semicola.
@@ ???? This statement looks like this:
goto label
(Under construction.)
subroutine name;
This statement calls the subroutine subroutine name which can either be a procedure or, if GNU extended syntax is turned on, a function. In this case, the return value is ignored.
This statement allows to declare a variable within a statement part. It looks like this:
var variable identifier: type identifier;
or
var variable identifier: type definition;
and with initializing value:
var variable identifier: type identifier value expression;
or
var variable identifier: type definition value expression;
Unlike in declaration parts, the initializing expression has not to be
a constant expression. Note that every declaring statement has to start
with var. The name space of variable identifier extends from
its declaration to the end of the current matching statement sequence
(which can be a statement part (of the program, a function, a procedure or
an operator) or, within that part, a begin end compound statement, a repeat
loop, or the else branch of a case statement). This statement is a
GNU extension.
See also section Type Definition, section Data Types
These are
Continue;
and
Break;
These simple statements must not occur outside a loop, i.e. a for, while or repeat statement. `Continue' transfers control to the beginning of the loop right by its call, `Break' exits the current loop turn and continues loop execution.
@@ Description missing here
A module can have one or more `export' clauses and the name of an `export' clause doesn't have to be equal to the name of the module.
Sample module code with separate interface and
implementation parts:
module DemoModule interface; { interface part }
export DemoModule = (FooType, SetFoo, GetFoo);
type
FooType = Integer;
procedure SetFoo (f : FooType);
function GetFoo : FooType;
end.
module DemoModule implementation; { implementation part }
import
StandardInput;
StandardOutput;
var
Foo : FooType;
{ Note: the effect is the same as a `forward' directive would have:
parameter lists and return types are not allowed in the
declaration of exported routines, according to EP. In GPC, they
are allowed, but not required. }
procedure SetFoo;
begin
Foo := f
end;
function GetFoo;
begin
GetFoo := Foo
end;
to begin do
begin
foo := 59;
WriteLn ('Just an example of a module initializer. See comment below')
end;
to end do
begin
Foo := 0;
WriteLn ('Goodbye')
end;
end.
Alternatively the module interface and implementation may be combined as follows:
module DemoMod2; { Alternative method }
export Catch22 = (FooType, SetFoo, GetFoo);
type
FooType = Integer;
procedure SetFoo (f : FooType);
function GetFoo : FooType;
end; { note: this end is required here, even if the
module-block below would be empty. }
var
Foo : FooType;
procedure SetFoo;
begin
Foo := f
end;
function GetFoo;
begin
GetFoo := Foo
end;
end.
Either one of the two methods may be used like this:
program ModuleDemo (Output);
import DemoModule;
begin
SetFoo (999);
WriteLn (GetFoo);
end.
program ModDemo2 (Output);
import Catch22 in 'demomod2.pas';
begin
SetFoo (999);
WriteLn (GetFoo);
end.
Somewhat simpler GPC modules are also supported. Note: This is not supported in the Extended Pascal standard.
This is a simpler module support that does not require exports, imports, module headers etc.
These non-standard simple GPC modules look like (does not have an export part, does not have a separate module-block, does not use import/export features.)
module DemoMod3;
type
FooType = Integer;
var
Foo : FooType;
procedure SetFoo (f : FooType);
begin
Foo := f
end;
function GetFoo : FooType;
begin
GetFoo := Foo;
end;
end.
program ModDemo3 (Output);
{ Manually do the "import" from DemoMod3 }
type
FooType = Integer;
procedure SetFoo (f : FooType); external;
function GetFoo : FooType; external;
begin
SetFoo (999);
WriteLn (GetFoo)
end.
Module initialization and finalization:
The to begin do module initialization and to end do
module finalization constructs now work on every target.
By the way: The "GPC specific" module definition is almost identical to the PXSC standard. With an additional keyword `global' which puts a declaration into an export interface with the name of the module, it will be the same. @@This is planned.
A generic GNU Pascal unit looks like the following:
unit name; interface import part interface part implementation implementation part initialization part end.
The name of the unit should coincide with the name of the file with the extension stripped. (If not, you can tell GPC the file name with `uses foo in 'bar.pas'', see section uses.)
The import part is either empty or contains a `uses' clause to import other units. It may also consist of an ISO-style `import' specification. Note that the implementation part is not preceeded by a second import part in GPC (see section import).
The interface part consists of constant, type, and variable declarations, procedure and function headings which may be freely mixed.
The implementation part is like the declaration part of a program, but the headers of procedures and functions may be abbreviated: Parameter lists and function return values may be omitted for procedures and functions already declared in the interface part.
The initialization part may be missing, or it may be a `begin' followed by one or more statements, such that the unit has a statement part between this `begin' and the final `end'. Alternatively, a unit may have ISO-style module initializers and finalizers, see section to begin do, section to end do.
Note that GPC does not yet check whether all interface declarations are resolved in the same unit. Procedures and functions which are in fact not used may be omitted, and/or procedures and functions may be implemented somewhere else, even in a different language. However, relying on a GPC bug (that will eventually be fixed) is not a good idea, so this is not recommended.
A unit exports everything declared in the interface section. The exported interface has the name of the unit and is compatible with Extended Pascal module interfaces since GPC uses the same code to handle both.
As described in section Type Declaration, a type declaration part looks like this:
type type identifier = type definition; ... type identifier = type definition;
where the left side is the type declaration and the right one the type definition side. GNU Pascal offers variant possibilities to implement highly specialized and problem-specific data types.
An ordinal type is a range of whole numbers. It includes integer types, character types and subrange types of them.
A character type is represented by the intrinsic type `Char' which
can hold elements of the operating system's character set (usually ASCII).
Conversion between character types and ordinal types is possible with the
intrinsic functions Ord and Chr or type casting techniques.
type
Foo: Char; { foo can hold a character }
Num: '0' .. '9'; { Can hold decimal ciphers, is a subrange type of Char }
See also section Ord, section Chr, section Type Casts
Besides `Integer', GNU Pascal supports a large zoo of integer types. Some of them you will find in other compilers, too, but most are GNU extensions, introduced for particular needs. Many of these types are synonyms for each other. In total, GPC provides 20 built-in integer types, plus seven families you can play with. (Four of these "families" are signed and unsigned, packed and unpacked subrange types; the others are explained below.)
See also: section Subrange Types.
For most purposes, you will always use `Integer', a signed integer type which has the "natural" size of such types for the machine. On most machines GPC runs on, this is a size of 32 bits, so `Integer' usually has a range of `-2147483648..2147483647' (see section Integer).
If you need an unsigned integer type, the "natural" choice is `Cardinal', also called `Word'. Like `Integer', it has 32 bits on most machines and thus a range of `0..4294967295' (see section Cardinal, section Word).
These natural integer types should be your first choice for best performance. For instance on an Intel x86 CPU operations with `Integer' usually work faster than operations with shorter integer types like `ShortInt' or `ByteInt' (see below).
`Integer', `Cardinal', and `Word' define the three "main branches" of GPC's integer types. You won't always be able to deal with the natural size; sometimes something smaller or longer will be needed. Especially when interfacing with libraries written in other languages such as C, you will need equivalents for their integer types.
The following variants of `Integer', `Cardinal' and `Word' are guaranteed to be compatible to the integer types of GNU C. The sizes given, however, are not guaranteed. They are just typical values currently used on most platforms, but they may be actually shorter or increase in the future.
In some situations you will need an integer type of a well-defined size. For this purpose, GNU Pascal provides three families of signed and unsinged integer types. The type
Integer (42)
is guaranteed to have a precision of 42 bits. In a realistic context, you will most often give a power of two as the number of bits, and the machine you will need it on will support variables of that size. If this is the case, the specified precision will simultaneously be the amount of storage needed for variables of this type.
In short: If you want to be sure that you have a signed integer with 32 bits width, write `Integer (32)', not just `Integer' which might be bigger. The same works with `Cardinal' and `Word' if you need unsigned integer types of well-known size.
This way, you can't get a higher precision than that of `LongestInt' or `LongestCard' (see section The Main Branch of Integer Types). If you need higher precision, you can look at the `GMP' unit (see section Arithmetic with unlimited size and precision) which provides integer types with arbitrary precision, but their usage is different from normal integer types.
If you care about ISO compliance, only use `Integer' and subranges of `Integer'.
Some of GPC's non-ISO integer types exist in Borland Pascal, too: `Byte', `ShortInt', `Word', and `LongInt'. The sizes of these types, however, are not the same as in Borland Pascal. Even for `Byte' this is not guaranteed (while probable, though).
When designing GNU Pascal, we thought about compatibility to Borland Pascal. Since GNU Pascal is (at least) a 32-bit compiler, `Integer' must have (at least) 32 bits. But what to do with `Word'? Same size as `Integer' (like in BP) or 16 bits (like in BP)? We decided to make `Word' the "natural-sized" unsigned integer type, thus making it (at least) 32 bits wide. Similarly, we decided to give `LongInt' twice the size of `Integer' (like in BP) rather than making it 32 bits wide (like in BP). So `LongInt' has 64 bits, and `ShortInt' has 16 bits on the Intel x86 platforms.
On the other hand, to increase compatibility to Borland Pascal and Delphi, GPC provides the alias name `Comp' for `LongInt' (64 bits on Intel x86) and `SmallInt' for `ShortInt' (16 bits on Intel x86). Note that BP treats `Comp' as a "real" type and allows assignments like `MyCompVar := 42.0'. Since we don't consider this a feature, GPC does not copy this behaviour.
Here is a summary of all integer types defined in GPC. The sizes and ranges are only typical values, valid on some, but not all platforms. Compatibility to GNU C however is guaranteed.
To specify the number of bits, use
program IntegerTypesDemo (Output); var ByteVar : Byte; ShortIntVar : ShortInt; Foo : MedCard; Big : LongestInt; begin ShortIntVar := 1000; Big := MaxInt * ShortIntVar; ByteVar := 127; Foo := 16#deadbeef end.
See also: section Subrange Types.
GPC has three built-in floating point types to represent real numbers. Each of them is available under two names (for compatibility to other compilers and languages).
For most purposes, you will always use `Real' which is the only one of them that is part of Standard and Extended Pascal. If memory constraints apply, you might want to choose `ShortReal' for larger arrays. On the other hand, if high precision is needed, you can use `LongReal'. When interfacing with libraries written in other languages such as C, you will need the equivalents for their real types.
Note that not all machines support longer floating point types, so `LongReal' is the same as `Real' on these machines. Also, some machines may support a longer type, but not do all arithmetic operations (e.g. the `Sin' function, section Sin) in a precision higher than that of `Real'. If you need higher precision, you can look at the `GMP' unit (see section Arithmetic with unlimited size and precision) which provides rational and real numbers with arbitrary precision, but their usage is different from normal real types.
The following real types are guaranteed to be compatible to the real types of GNU C. The sizes given, however, are not guaranteed. They are just typical values used on any IEEE compatible floating point hardware, but they may be different on some machines.
There are several ways to use strings in GNU Pascal. One of them is
the use of the intrinsic string type `String' which is a
predefined schema type. The schema discriminant of this type holds
the maximal length, which is of type Integer, so values up to
MaxInt can be specified. For `String', an assignment is
defined. There are many built-in functions and procedures for
comfortable strings handling.
@@ ???? String procedures and functions.
Another way to use strings is to use arrays of type `Char'. For these, an intrinsic assignment is defined as well. Besides, `String' and `Char' are assignment compatible. The preferred way, however, is `String' because of the numerous possibilities for string handling.
Character types are a special case of ordinal types. See section Ordinal Types
@@ ???? I think that's something for someone who might know what he is doing
The intrinsic Boolean represents boolean values, i.e. it can only assume true and false (which are predefined constants). This type corresponds to the enumerated type
type Boolean = (False, True);
Since it is declared this way, it follows:
Ord (False) = 0 Ord (True) = 1 False < True
There are four intrinsic logical operators. The logical and,
or and not. In Borland Pascal and GNU Pascal, there is
a logical "exclusive or" xor.
See also section Enumerated Types, section and, section or, section not, section xor
The intrinsic Pointer Type is a so-called unspecified or typeless pointer (i.e. a pointer which does not point to any type but holds simply a memory address).
See also section Pointer Types, section nil
GNU Pascal supports Standard Pascal's subrange types:
program SubrangeDemo;
type
MonthInt = 1 .. 12;
Capital = 'A' .. 'Z';
ControlChar = ^A .. ^Z; { `^A' = `Chr (1)' is a BP extension }
begin
end.
Also possible: Subranges of enumerated types:
program EnumSubrangeDemo;
type
{ This is an enumerated type. }
Days = (Mon, Tue, Wed, Thu, Fri, Sat, Sun);
{ This is a subrange of `Days'. }
Working = Mon .. Fri;
begin
end.
To increase performance, variables of such a type are aligned in a way which makes them fastest to access by the CPU. As a result, `1 .. 12' occupies 4 bytes of storage on an Intel x86 compatible CPU.
For the case you want to save storage at the expense of speed, GPC provides a `packed' variant of these as an extension:
program PackedSubrangeDemo; type MonthInt = packed 1 .. 12; begin end.
A variable of this type occupies the shortest possible (i.e., addressable) space in memory -- one byte on an Intel x86 compatible CPU.
See also: section packed.
type enum type identifier = (name identifier, ..., name identifier);
An enumerated type defines a range of elements which are referred to by
identifiers. Enumerated types are ordered by occurence in the identifier
list. So, they can be used as index types in an array
definition, and it is possible to define subranges of them. Since they are
ordered, they can be compared to one another. The intrinsic function
Ord applied to name identifier returns the number of occurence
in the identifier list (beginning with zero), Pred and Succ
return the predecessor and successor of name identifier.
See also section Array Types, section Subrange Types, section Ord, section Pred, section Succ
type array type identifier = array [index type] of element type
or
type array type identifier = array [index type, ..., index type] of element type
The reserved word array defines an array type. index type
has to be an ordinal type, subrange type or an enumerated type, where
several index types, separated by commata, are allowed. element type
is an arbitrary type. An element of an array is accessed
by array type variable [ index number ]. The upper and
lower index bounds can be determined by the intrinsic functions High
and Low.
type
IntArray = array [1 .. 20] of Integer;
Foo = array [(Mo, Tu, We, Th, Fr, Sa, Su)] of Char;
Bar = array [0 .. 9, 'a' .. 'z', (Qux, Glork1, Fred)] of Real;
Baz1 = array [1..10] of IntArray;
{ equal (but declared differently): }
Baz2 = array [1 .. 10, 1 .. 20] of Integer;
See also section High, section Low
type
record type identifier = record
field identifier : type definition;
...
field identifier : type definition;
end;
or, with a variant part,
type
record type identifier = record
field identifier : type definition;
...
field identifier : type definition;
case bar: variant type of
selector: (field declarations);
selector: (field declarations);
...
end;
or, without a variant selector field,
type
record type identifier = record
field identifier : type definition;
...
field identifier : type definition;
case variant type of
selector: (field declarations);
selector: (field declarations);
...
end;
The reserved word record defines a structure of fields.
Records can be `packed' to save memory usage at the expense of speed.
The variants of a variant record share one location in memory (inside the record) and thus can be used to emulate type casting without violating ISO-7185 Standard Pascal.
The reserved word `record' and record types are defined in ISO-7185 Standard Pascal. According to ISO Pascal, the variant type must be an identifier. GNU Pascal, like UCSD and Borland Pascal, also allows a subrange here.
A record field is accessed by record type variable . field identifier
See also: section packed, section case Statement.
GPC supports variant records like in EP and BP. The following construction is not allowed in Extended Pascal, but in BP and GPC:
program BPVariantRecordDemo;
type
PersonRec = record
Age : Integer;
case EyeColor : (Red, Green, Blue, Brown) of
Red, Green : (WearsGlasses : Boolean);
Blue, Brown : (LengthOfLashes : Integer);
end;
begin
end.
In EP, the variant field needs a type identifier, which, of course, also works in GPC:
program EPVariantRecordDemo;
type
EyeColorType = (Red, Green, Blue, Brown);
PersonRec = record
Age : Integer;
case EyeColor : EyeColorType of
Red, Green : (WearsGlasses : Boolean);
Blue, Brown : (LengthOfLashes : Integer);
end;
begin
end.
Schemata are types that depend on one or more variables, called discriminants. They are an ISO-10206 Extended Pascal feature.
type RealArray (n: Integer) = array [1 .. n] of Real; Matrix (n, m: PositiveInteger) = array [1 .. n, 1 .. m] of Integer;
The type `RealArray' in this example is called a Schema with the discriminant `n'.
To declare a variable of such a type, write:
var Foo: RealArray (42);
The discriminants of every global or local schema variable are initialized at the beginning of the procedure, function or program where the schema variable is declared.
Schema-typed variables "know" about their discriminants. Discriminants can be accessed just like record fields:
program Schema1Demo;
type
PositiveInteger = (*@@ 1 .. MaxInt *) Integer;
RealArray (n: Integer) = array [1 .. n] of Real;
Matrix (n, m: PositiveInteger) = array [1 .. n, 1 .. m] of Integer;
var
Foo: RealArray (42);
begin
WriteLn (Foo.n) { yields 42 }
end.
Schemata may be passed as parameters. While types of schema variables must always have specified discriminants (which may be other variables), formal parameters (by reference or by value) may be of a schema type without specified discriminant. In this, the actual parameter may posses any discriminant. The discriminants of the parameters get their values from the actual parameters.
Also, pointers to schema variables may be declared without a discriminant:
program Schema2Demo; type RealArray (n: Integer) = array [1 .. n] of Real; RealArrayPtr = ^RealArray; var Bar: RealArrayPtr; begin end.
When applying `New' to such a pointer, you must specify the intended value of the discriminant as a parameter:
New (Bar, 137)
As a GNU Pascal extension, the above can also be written as
Bar := New (RealArrayPtr, 137)
The allocated variable behaves like any other schema variable:
program Schema3Demo;
type
RealArray (n: Integer) = array [1 .. n] of Real;
RealArrayPtr = ^RealArray;
var
Bar: RealArrayPtr;
i: Integer;
begin
Bar := New (RealArrayPtr, 137);
for i := 1 to Bar^.n do
Bar^ [i] := 42
end.
Since the schema variable "knows" its size, pointers to schemata can be disposed just like other pointers:
Dispose (Bar)
Schemata are not limited to arrays. They can be of any type that normally requires constant values in its definition, for instance subrange types, or records containing arrays etc. (Sets do not yet work.)
References to the schema discriminants are allowed, and the
with statement is also allowed, so one can say:
program SchemaWithDemo;
type
RealArray (n : Integer) = array [1 .. n] of Real;
var
MyArray : RealArray (42);
begin
WriteLn (MyArray.n); { writes 42 }
with MyArray do
WriteLn (n); { writes 42 }
end.
Finally, here is a somewhat exotic example. Here, a `ColoredInteger' behaves just like an ordinary integer, but it has an additional property `Color' which can be accessed like a record field.
program SchemaExoticDemo;
type
ColorType = (Red, Green, Blue);
ColoredInteger (Color : ColorType) = Integer;
var
Foo : ColoredInteger (Green);
begin
Foo := 7;
if Foo.Color = red then
Inc (Foo, 2)
else
Foo := Foo div 3
end.
An important schema is the predefined `String' schema
(according to Extended Pascal). It has one predefined discriminant
identifier Capacity. GPC implements the String schema
as follows:
type
String (Capacity : Cardinal) = record
Length : 0 .. Capacity;
Chars : packed array [1 .. Capacity + 1] of Char
end;
The Capacity field may be directly referenced by the user,
the Length field is referenced by a predefined string
function Length (Str) and contains the current string length.
Chars contains the chars in the string. The Chars and
Length fields cannot be directly referenced by a user
program.
If a formal value parameter is of type `String' (with or
without discriminant), the actual parameter may be either a
String schema, a fixed string (character array), a single
character, a string literal or a string expression. If the actual
parameter is a `String' schema, it is copied for the parameter
in the usual way. If it is not a schema, a `String' schema is
created automatically, the actual parameter is copied to the new
variable and the Capacity field of the new variable is set to
the length of the actual parameter.
Actual parameters to `var' parameters of type `String' must be `String' schemata, not string literals or character arrays.
program StringDemo (Output);
type
SType = String (10);
SPtr = ^String;
var
Str : SType;
Str2 : String (100000);
Str3 : String (20) value 'string expression';
DStr : ^String;
ZStr : SPtr;
Len : Integer value 256;
Ch : Char value 'R';
{ `String' accepts any length of strings }
procedure foo (z : String);
begin
WriteLn ('Capacity : ', z.Capacity);
WriteLn ('Length : ', Length (z));
WriteLn ('Contents : ', z);
end;
{ Another way to use dynamic strings }
procedure Bar (SLen : Integer);
var
LString : String (SLen);
FooStr : type of LString;
begin
LString := 'Hello world!';
Foo (LString);
FooStr := 'How are you?';
Foo (FooStr);
end;
begin
Str := 'KUKKUU';
Str2 := 'A longer string variable';
New (DStr, 1000); { Select the string Capacity with `New' }
DStr^ := 'The maximum length of this is 1000 chars';
New (ZStr, Len);
ZStr^ := 'This should fit here';
Foo (Str);
Foo (Str2);
Foo ('This is a constant string');
Foo ('This is a ' + Str3);
Foo (Ch); { A char parameter to string routine }
Foo (''); { An empty string }
Foo (DStr^);
Foo (ZStr^);
Bar (10000);
end.
In the above example, the predefined procedure New was used
to select the capacity of the strings. Procedure Bar also has
a string whose size depends of the parameter passed to it and
another string whose type will be the same as the type of the first
string, using the type of construct.
All string and character types are compatible as long as the destination string is long enough to hold the source in assignments. If the source string is shorter than the destination, the destination is automatically blank padded if the destination string is not of string schema type.
set type identifier = set of set element type;
set type identifier is a set of elements from set element type which is either an ordinal type, an enumerated type or a subrange type. Set element representatives are joined together into a set by brackets:
[set element, ..., set element]
`[]' indicates the empty set, which is compatible with all set types. Note: Borland Pascal restricts the maximal set size (i.e. the range of the set element type) to 256, GNU Pascal has no such restriction. The number of elements a set variable is holding can be determined by the intrinsic set function Card (which is a GNU Pascal extension, in Extended Pascal and Borland Pascal you can use SizeOf instead but note the element type size in bytes, then) to the set. There are four intrinsic binary set operations: the union `+', the intersection `*' and the difference `-'. The symmetric difference `><' is an Extended Pascal extension.
See also section Card, section SizeOf
pointer type identifier = ^type identifier;
A pointer of the type pointer type identifier holds the address at which data of the type type identifier is situated. Unlike other identifier declarations, where all identifiers in definition part have to be declared before, in a pointer type declaration type identifier may be declared after pointer type identifier. The data pointed to is accessed by pointer type variable ^ . To mark an unassigned pointer, the "nil" constant (which stands for "not in list") has to be assigned to it, which is compatible with all pointer types.
type
ItselfFoo = ^ItselfFoo; { possible but senseless }
PInt = ^Integer; { Pointer to an Integer }
PNode = ^TNode; { Linked list }
TNode = record
Key : Integer;
NextNode : PNode;
end;
var
Foo, Bar : PInt;
begin
Foo := Bar; { Modify address which foo is holding }
Foo^ := 5; { Access data foo is pointing to }
end.
GPC also suports pointers to procedures or function and calls through them. This is a non-standard feature.
program ProcPtrDemo (Output);
type
ProcPtr = ^procedure (Integer);
var
PVar : ProcPtr;
procedure WriteInt (i : Integer);
begin
WriteLn ('Integer: ', i : 1)
end;
begin
{ Let PVar point to function WriteInt }
PVar := @WriteInt;
{ Call the function by dereferencing the function pointer }
PVar^ (12345)
end.
See also: section Pointer (Intrinsic).
For procedures without a parameter list:
procedure type identifier = procedure name identifier;
or functions:
function type identifier =
function name identifier: function result type;
For procedures with a parameter list:
procedure type identifier =
procedure name identifier (parameter list);
or functions:
function type identifier =
function name identifier (parameter list): function result type;
Procedural types can be used as procedures or functions respectively, but also a value can be assigned to them. Procedural types are a Borland Pascal extension. In Borland Pascal, function result type can only be one of these types: ordinal types, enumerated types, real types, pointer types, the intrinsic Boolean, or the intrinsic String. In GNU Pascal every function result type for procedural types is allowed.
BP has procedural and functional types:
type CompareFunction = function (Key1, Key2 : String) : Integer; function Sort (Compare : CompareFunction); begin ... end;
Standard Pascal has procedural and functional parameters:
function Sort (function Compare (Key1, Key2 : String) : Integer); begin ... end;
Both ways have pros and cons, e.g. in BP you can save, compare, trade, etc. procedural values, or build arrays of them, while the SP way does not require a type declaration and prevents problems with uninitialized or invalid pointers (which in BP will usually crash the program).
GPC supports both ways. An important feature of Standard Pascal (but not BP) that GPC also supports is the possibility to pass local routines as procedural or functional parameters, even if the called routine is declared far remote. The called routine can then call the passed local routine and it will have access to the original caller's local variables.
program LocalProceduralParameterDemo;
procedure CallProcedure (procedure Proc);
begin
Proc
end;
procedure MainProcedure;
var LocalVariable : Integer;
procedure LocalProcedure;
begin
WriteLn (LocalVariable)
end;
begin
LocalVariable := 42;
CallProcedure (LocalProcedure)
end;
begin
MainProcedure
end.
See also: section The Procedure, section The Function, section Subroutine Parameter List Declaration, section Procedure Call.
Under construction.
See also section Object-Orientated Programming
A type may be initialized to a value of expression when it is declared, like a variable, as in:
program TypeVarInitDemo;
type
Int10 = Integer value 10;
FooType = Real;
MyType = Char value Pred ('A');
EType = (a, b, c, d, e, f, g) value d;
const
Answer = 42;
var
ii : Int10; { Value of ii set to 10 }
ch : MyType value Pred ('z');
aa : Integer value Answer + 10;
foo : FooType value Sqr (Answer);
e1 : EType; { value set to d }
e2 : EType value g; { value set to g }
begin
end.
Extended Pascal requires the type initializers to be constant expressions. GPC allows any valid expression.
Note, however, that the expressions that affect the size of storage allocated for objects (e.g. the length of arrays) may contain variables only inside functions or procedures.
GPC evaluates the initial values used for the type when an identifier is declared for that type. If a variable is declared with a type-denoter that uses a type-name which already has an initial value the latter initialization has precedence.
@@ GPC does not know how to calculate constant values for math functions in the runtime library at compile time, e.g. `Exp (Sin (2.4567))', so you should not use these kind of expressions in object size expressions. (Extended Pascal allows this.)
GPC supports `restricted' types, defined in Extended Pascal. A value of a restricted type may be passed as a value parameter to a formal parameter possessing its underlying type, or returned as the result of a function. A variable of a restricted type may be passed as a variable parameter to a formal parameter possessing the same type or its underlying type. No other operations, such as accessing a component of a restricted type value or performing arithmetic, are possible.
program RestrictedDemo;
type
UnrestrictedRecord = record
a : Integer;
end;
RestrictedRecord = restricted UnrestrictedRecord;
var
r1 : UnrestrictedRecord;
r2 : RestrictedRecord;
i : restricted Integer;
k : Integer;
function AccessRestricted (p : UnrestrictedRecord) : RestrictedRecord;
var URes : UnrestrictedRecord;
begin
{ The parameter is treated as unrestricted, even though the actual
parameter may be a restricted object }
URes.a := p.a;
{ It is legal to assign a return value }
AccessRestricted := URes;
end;
begin
r1.a := 354;
{ Assigning a restricted return value to a restricted object }
{ @@ Verify if this should really be allowed????? }
r2 := AccessRestricted (r1);
{ Passing a restricted object to unrestericted formal parameter is ok }
r2 := AccessRestricted (r2);
{$ifdef BUG}
{ *** The following statements are illegal *** }
r2.a := 100; { field access }
r1 := r2; { assignment source is restricted }
r2 := r1; { assignment target is restricted }
r1 := AccessRestricted (r2); { assigning a restricted return
value to an unrestricted object }
i := 16#ffff; { assignment target is restricted }
k := i + 2; { arithmetic with restricted value }
{$endif}
end.
Endianness means the order in which the bytes of a value larger than one byte are stored in memory. This affects, e.g., integer values and pointers while, e.g., arrays of single-byte characters are not affected. The GPC `String' schema, however, contains `Capacity' and `Length' fields before the character array. These fields are integer values larger than one byte, so the `String' schema is affected by endianness.
Endianness depends on the hardware, especially the CPU. The most common forms are:
$deadbeef is stored on memory
address $1234 on a little-endian machine, the following bytes
will occupy the memory positions:
$deadbeef is stored on memory
address $1234 on a big-endian machine, the following bytes
will occupy the memory positions:
Note: There are processors which can run in both little-endian and big-endian mode, e.g. the MIPS processors. A single program, however, (unless it uses special machine code instructions) will always run in one endianness.
Under normal circumstances, programs do not need to worry about endianness, the CPU handles it by itself. Endianness becomes important when exchanging data between different machines, e.g. via binary files or over a network. To avoid problems, one has to choose the endianness to use for the data exchange. E.g., the Internet uses big-endian data, and most known data formats have a specified endianness (usually that of the CPU on which the format was originally created). If you define your own binary data format, you're free to choose the endianness to use.
To deal with endianness, GPC predefines the symbol `__BYTES_LITTLE_ENDIAN__' on little-endian machines and `__BYTES_BIG_ENDIAN__' on big-endian machines. Besides, the Run Time System defines the constant `BytesBigEndian' as False on little-endian machines and True on big-endian machines.
There are also the symbols `__BITS_LITTLE_ENDIAN__', `__BITS_BIG_ENDIAN__', `__WORDS_LITTLE_ENDIAN__', `__WORDS_BIG_ENDIAN__' and the constants `BitsBigEndian' and `WordsBigEndian' which concern the order of bits within a byte (e.g., in packed records) or of words within multiword-numbers, but these are usually less important.
The Run Time System also contains a number of routines to convert endianness and to read or write data from/to binary files in a given endianness, independent of the CPU's endianness. These routines are described in the RTS reference (see section Pascal declarations for GPC's Run Time System), under `endianness'. The demo program `endiandemo.pas' contains an example on how to use these routines.
(Under construction.) @@ ????
GNU Pascal supports all operators of ISO Pascal and Borland Pascal. In addition, you can define your own operators according to the Pascal-SC (PXSC) syntax.
The following table lists all built-in GNU Pascal operators, ordered by precedence: `<' etc. have the lowest precedence, `not' etc. the highest. As usual, the precedence of operators can be superseded with parentheses.
In an assignment statement, `:=' has lower precedence than all operators. (This is rather obvious from the syntax of assignment statements, and is merely noted for programmers familiar with C where `=' is an operator.)
< = > in <> >= <= + - or +< -< +> -> * / div mod and shl shr xor *< /< *> /> pow ** >< not & @
The Pascal-SC (PXSC) operators `+<', `-<', `+>', `->', `*<', `/<', `*>', and `/>' are not yet implemented into GNU Pascal but may be defined by the user (see below).
GNU Pascal allows the (re-)definition of binary operators according to the Pascal-SC (PXSC) syntax. The following vector addition example illustrates how to do this:
program OperatorDemo;
type
Vector3 = record
x, y, z: Real;
end;
var
a, b, c: Vector3 = (1, 2, 3);
operator + (u, v: Vector3) w: Vector3;
begin
w.x := u.x + v.x;
w.y := u.y + v.y;
w.z := u.z + v.z;
end;
begin
c := a + b
end.
Between the closing parenthesis of the argument list and the result variable (`w' in the above example), GPC allows an optional equal sign. This is not allowed in PXSC, but it is consistent with Extended Pascal's function return variable definitions, where the equal sign is obligatory (but also optional in GPC).
The argument types needn't be equal, and the name of the operator may be an identifier instead of a known symbol. You cannot define new symbols in GPC.
The PXSC operators `+>', `+<', etc. for exact numerical calculations currently are not implemented in GPC, but you can define them. Also, the other real-type operators do not meet the requirements of PXSC; a module which fixes that would be a welcome contribution.
All the following works in GPC:
procedure Foo (protected a, b, c : Integer); { 3 arguments }
procedure Foo (a, b, c, protected : Integer); { 4 arguments }
procedure Foo (a, b, protected, c : Integer); { 4 arguments }
procedure Foo (protected : Integer); { 1 argument }
procedure Foo (var protected : Integer); { 1 argument }
procedure Foo (protected protected : Integer); { 1 argument }
Furthermore, GPC supports const, according to BP, which is
equivalent to either protected or protected var, up to
the compiler's discretion.
@@ (Under construction.)
A feature of Standard Pascal level 1.
Borland Pascal "open array" formal parameters are implemented into GPC. Within the function body, they have integer type index with lower bound 0.
In constrast to conformant arrays (which are not supported by BP), open arrays allow any ordinal type as the index of the actual parameter (which is useful, e.g., if you want to be able to pass values of any enumeration type). However, they lose information about the lower bound (which is a problem, e.g., if you want to return information to the caller that relates to the actual array index, like the function `IOSelect' in the Run Time System does).
GPC allows to increment, decrement, compare, and subtract pointers or to use them in `for' loops just like the C language.
GPC implements the address operator @ (a Borland Pascal
extension).
program PointerArithmeticDemo;
var
a: array [1 .. 7] of Char;
p, q: ^Char;
i: Integer;
{$X+} { We need extended syntax for pointer arithmetic }
begin
for p := @A [1] to @A [7] do
p^ := 'x';
p := @A [ 7 ];
q := @A [ 3 ];
while p > q do
begin
p^ := 'y';
Dec (p)
end;
p := @A [7];
q := @A [3];
i := q - p; { yields 4 }
end.
Incrementing a pointer by one means to increment the address it contains by the size of the variable it is pointing to. For typeless pointers (`Pointer'), the address is incremented by one instead.
Similar things hold when decrementing a pointer.
Subtracting two pointers yields the number of variables pointed to between both pointers, i.e. the difference of the addresses divided by the size of the variables pointed to. The pointers must be of the same type.
In some cases, especially when interfacing with other languages, Pascal's strong typing can be an obstacle. To temporarily circumvent this, GPC (and other Pascal compilers) defines explicit "type casts".
There are two kinds of type casts, value type casts and variable type casts.
Value type casts
To convert a value of one data type into another type, you can use the target type like the name of a function that is called. The value to be converted can be a variable or an expression.
An example:
program TypeCastDemo; var Ch: Char; i: Integer; begin i := Integer (Ch) end.
Another, more complicated, example:
program TypeCst2Demo;
type
CharPtr = ^Char;
CharArray = array [0 .. 99] of Char;
CharArrayPtr = ^CharArray;
var
Foo1, Foo2: CharPtr;
Bar: CharArrayPtr;
{$X+} { We need extended syntax in order to use ``Succ'' on a pointer }
begin
Foo1 := CharPtr (Bar);
Foo2 := CharPtr (Succ (Bar))
end.
However, because of risks involved with type casts, explained below, you should try to avoid type casts whenever possible -- and it should be possible in most cases. For instance, the first example above could use the built-in function "Ord" instead of the type cast:
i := Ord (Ch);
The assignments in the second example could be written in the following way without any type casts:
Foo1 := @Bar^[0]; Foo2 := @Bar^[1];
Value type casting only works between certain types: either between different ordinal types (including integer types), or between different real types, or between different pointer types. In each case, the current value, i.e. the ordinal or numeric value or the address pointed to, respectively, is preserved in the cast.
Note: It is also possible to cast from an integer into a real type. This is a consequence of the fact that integer values are generally automatically converted to real values when needed.
@@ ???? to dereference DOES NOT EXIST Note: In the case of pointers, a warning is issued if the dereferenced target type requires a bigger alignment than the dereferenced source type (see section Alignment).
Variable type casts
It is also possible to temporarily change the type of a variable, without converting its contents in any way. This is called variable type casting.
The syntax is the same as for value type casting. This can be confusing, as the example below shows.
The type-casted variable is still the same variable (memory location) as the original one, just with a different type. Outside of the type cast, the variable keeps its original type.
There are some important differences between value and variable type casting:
program TrapsOfTypeCastsDemo;
{ Declare a real type and an integer type of the same size, and some
variables of these types we will need. }
type
RealType = ShortReal;
IntegerType = Integer (BitSizeOf (RealType));
var
i, i1, i2, i3, i4, i5: IntegerType;
r, r1, r2, r3, r4: RealType;
begin
{ First part: Casting integer into real types. }
{ Start with some integer value }
i := 42;
{ First attempt to cast. Here, an lvalue is casted, so this must
be a variable type cast. Therefore, the bit pattern of the value
of i is transferred unchanged into r1 which results in a silly
value of r1. }
IntegerType (r1) := i;
{ Second try. Here we cast an expression -- though a trivial one --,
rather than a variable. So this can only be a value type cast.
Therefore, the numeric value is preserved, i.e. r2 = 42.0 . }
r2 := RealType (i + 0);
{ Third way. In this last example, a variable is casted, and the
result is used as an expression, not as an lvalue. So this
could be either a value or variable type cast. However, there
is a rule that value type casting is preferred if possible.
So r3 will contain the correct numeric value, too. }
r3 := RealType (i);
{ Of course, you do not need any casts at all here. A simple
assignment will work because of the automatic conversion from
integer to real types. So r4 will also get the correct result. }
r4 := i;
{ Now the more difficult part: Casting real into integer types. }
{ Start with some real value. }
r := 41.9;
{ Like the first attempt above, this one does a variable type cast,
preserving bit patterns, and leaving a silly value in i1. }
{ RealType (i1) := r; }
{ The second try from above does not work, because an expression of
type real is to be casted into an integer which is not allowed. }
{ i2 := IntegerType (r + 0); }
{ Third way. This looks just like the third way in the first part
which was a value type cast.
But -- surprise! Since value type casting is not possible from
real into integer, this really does a variable type casting,
and the value of i3 is silly again! This difference in behaviour
shows some of the hidden traps in type casting. }
i3 := IntegerType (r);
{ As often, it is possible to avoid type casts altogether and
convert real types into integers easily by other means, i.e. by
using the built-in functions ``Round'' or ``Trunc'', depending
on the mode of rounding one wants. }
i4 := Round (r); { 42 }
i5 := Trunc (r); { 41 }
end.
When dealing with objects (see section Object-Orientated Programming), it is often necessary -- and safe -- to cast a pointer to an object into a pointer to a more specialized (derived) object. In future releases, GPC will provide an operator `as' for a safer approach to this problem.
See also: section absolute, section Alignment, section Endianness, section Object-Orientated Programming, section Ord, section Chr, section Round, section Trunc.
GNU Pascal follows the object model of Borland Pascal 7.0. The BP object extensions are almost fully implemented into GPC. This includes inheritance, virtual and non-virtual methods, constructors, destructors, pointer compatibility, extended `New' syntax (with constructor call and/or as a Boolean function), extended `Dispose' syntax (with destructor call).
The Borland object model is different from the ISO draft, but it will not be too difficult now to implement that too (plus the Borland Delphi Object Extensions which are quite similar to the ISO draft).
The syntax for an object type declaration is as follows:
program ObjectDemo;
type
Str100 = String (100);
FooParentPtr = ^fooParent;
FooPtr = ^foo;
FooParent = object
constructor Init;
destructor Done; virtual;
procedure Bar (c: Real); virtual;
function Baz (b, a, z: Char): Str100; { not virtual }
end;
Foo = object (FooParent)
x, y: Integer;
constructor Init (a, b: Integer);
destructor Done; virtual;
procedure Bar (c: Real); virtual; { overrides `FooParent.Bar' }
z: Real; { GPC extension: data fields after methods }
function Baz: Boolean; { new function }
end;
constructor FooParent.Init;
begin
WriteLn ('FooParent.Init')
end;
destructor FooParent.Done;
begin
WriteLn ('I''m also done.')
end;
procedure FooParent.Bar (c : Real);
begin
WriteLn ('FooParent.Bar (', c, ')')
end;
function FooParent.Baz (b, a, z : Char) = s : Str100;
begin
WriteStr (s, 'FooParent.Baz (', b, ', ', a, ', ', z, ')')
end;
constructor Foo.Init (a, b : Integer);
begin
inherited Init;
x := a;
y := b;
z := 3.4;
FooParent.Bar (1.7)
end;
destructor Foo.Done;
begin
WriteLn ('I''m done.');
inherited Done
end;
procedure Foo.Bar (c: Real);
begin
WriteLn ('Foo.Bar (', c, ')')
end;
function Foo.Baz: Boolean;
begin
Baz := True
end;
var
Ptr: FooParentPtr;
begin
Ptr := New (FooPtr, Init (2, 3));
Ptr^.Bar (3);
Dispose (Ptr, Done);
New (Ptr, Init);
with Ptr^ do
WriteLn (Baz ('b', 'a', 'z'))
end.
Remarks:
A pointer to `FooParent' may be assigned the address of a `Foo' object. A `FooParent' formal `var' parameter may get a `Foo' object as the actual parameter. In such cases, a call to a `virtual' method calls the child's method, whereas a call to a non-`virtual' method selects the parent's one:
var
MyFooParent: FooParentPtr;
SomeFoo: Foo;
[...]
SomeFoo.Init (4, 2);
MyFooParent := @SomeFoo;
MyFooParent^.bar (3.14); { calls `foo.bar' }
MyFooParent^.baz ('b', 'a', 'z'); { calls `fooParent.baz' }
if SomeFoo.baz then { calls `foo.baz' }
WriteLn ('Baz!');
In a method, an overwritten method of a parent object can be called either prefixing it with the parent type name, or using the keyword `inherited':
procedure Foo.Bar (c : Real);
begin
z := c;
inherited bar (z) { or: FooParent.Bar (z) }
end;
Use `FooParent.bar (z)' if you want to be sure that this method is called, even if somebody decides not to derive `foo' directly from `fooParent' but to have some intermediate object. If you want to call the method `bar' of the immediate parent -- whether it be `fooParent' or whatever -- use `inherited bar (z)'.
To allocate an object on the heap, use `New' in one of the following manners:
var MyFoo: FooPtr; [...] New (MyFoo, Init (4, 2)); MyFooParent := New (FooPtr, Init (4, 2))
The second possibility has the advantage that `MyFoo' needn't be a `FooPtr' but can also be a `FooParentPtr', i.e. a pointer to an ancestor of `foo'.
Destructors can and should be called within Dispose:
Dispose (MyFooParent, Fini)
GPC, like UCSD Pascal and BP, treats comments beginning with a
`$' immediately following the opening `{' or `(*' as
a compiler directive. As in Borland Pascal, {$...} and
(*$...*) are equivalent. When a single character plus a
`+' or `-' follows, this is also called a compiler switch.
All of these directives are case-insensitive (but some of them have
case-sensitive arguments). Directives are local and can be changed
during one compilation (except include files etc. where this makes
no sense).
In general, compiler directives are compiler-dependent. (E.g., only
the include directive {$I FileName} is common to UCSD and
BP.) Because of BP's popularity, GPC supports all of BP's compiler
directives (and ignores those that are unnecessary on its platforms
-- these are those not listed below), but it knows a lot more
directives.
Some BP directives are -- of course not by chance -- just an
alternative notation for C preprocessor directives. But there are
differences: BP's conditional definitions
(`{$define Foo}') go into another name space than the
program's definitions. Therefore you can define conditionals and
check them via {$ifdef Foo}, but the program will not see
them as an identifier `Foo', so macros do not exist in Borland
Pascal.
GPC does support macros, but disables this feature when the `--no-macros' option or the dialect option `--borland-pascal' or `--delphi' is given, to mimic BP's behaviour. Therefore, the following program will react differently when compiled with GPC either without special options or with, e.g., the `--borland-pascal' option (and in the latter case, it behaves the same as when compiled with BP).
program MacroDemo;
const Foo = 'Borland Pascal';
{$define Foo 'Default'}
begin
WriteLn (Foo)
end.
Of course, you should not rely on such constructs in your programs. To test if the program is compiled with GPC, you can test the `__GPC__' conditional, and to test the dialect used in GPC, you can test conditionals like `__BORLAND_PASCAL__'.
In general, almost every GPC specific command line option (see section GPC options besides those of GCC.) can be turned into a compiler directive (exceptions are those options that contain directory names, such as `--unit-path', because they refer to the installation on a particular system, and therefore should be set system-wide, rather than in a source file):
--foo {$foo}
--no-foo {$no-foo}
-Wbar {$W bar} { note the space after the `W' }
-Wno-bar {$W no-bar}
The following table lists some such examples as well as all those directives that do not correspond to command-line options or have syntactical alternatives (for convenience and/or BP compatibility).
--[no-]short-circuit $B+ $B- like in Borland Pascal:
$B- means short-circuit Boolean
operators; $B+ complete evaluation
--[no-]io-checking $I+ $I- like in Borland Pascal:
enable/disable I/O checking
--[no-]stack-checking $S+ $S- like in Borland Pascal:
enable/disable stack checking
--[no-]typed-address $T+ $T- like in Borland Pascal:
make the result of the address
operator and the Addr function a
typed or untyped pointer
-W[no-]warnings $W+ $W- enable/disable warnings. Note: in
`--borland-pascal' mode, the
short version is disabled because
$W+/$W- has a different meaning in
Borland Pascal (which can safely be
ignored in GPC), but the long version
is still available.
--[no-]extended-syntax $X+ $X- mostly like in Borland Pascal:
enable/disable extended syntax
(ignore function return values,
operator definitions, `PChar',
pointer arithmetic, ...)
--borland-pascal disable or warn about GPC features
--extended-pascal not supported by the standard or
--pascal-sc dialect given, do not warn about its
etc. ``dangerous'' features (especially BP).
The dialect can be changed during one
compilation via directives like,
e.g., `{$borland-pascal}'.
{$M Hello!} write message `Hello!' to
standard error during compilation. In
`--borland-pascal' mode, it is
ignored it if only numbers follow
(for compatibility to Borland
Pascal's memory directive)
{$define FOO} like in Borland Pascal:
or define FOO (for conditional compilation)
{$CIDefine FOO} (case-insensitively)
--cidefine=FOO the same on the command line
{$CSDefine FOO} define FOO case-sensitively
-D FOO the same on the command line
or Note: `--define' on the command
--csdefine=FOO line is case-sensitive like in GCC,
or but `{$define}' in the source code
--define=FOO is case-insensitive like in BP
{$define loop while True do} define `loop' to be `while True do'
or as a macro like in C. The name of the
{$CIDefine loop ...} macro is case-insensitive. Note:
Macros are disabled in
`--borland-pascal' mode because BP
doesn't support macros.
--cidefine="loop=..." the same on the command line
{$CSDefine loop ...} define a case-sensitive macro
--csdefine="loop=..." the same on the command line
or
--define="loop=..."
{$I FileName} like in Borland Pascal:
include `filename.pas'
(the name is converted to lower case)
{$undef FOO} like in Borland Pascal: undefine FOO
{$ifdef FOO} conditional compilation
... (like in Borland Pascal).
{$else} Note: GPC predefines the symbol
... `__GPC__' (with two leading
{$endif} and trailing underscores).
{$include "filename.pas"} include (case-sensitive)
{$include <filename.pas>} the same, but don't search in the
current directory
...and all the other C preprocessor directives.
You also can use the preprocessor directives in C style, e.g. `#include', but this is deprecated because of possible confusion with Borland Pascal style `#42' character constants. Besides, in the Pascal style, e.g. `{$include "foo.bar"}', there may be more than one directive in the same line.
In this section we describe the routines and other declarations that are built into the compiler or part of the Run Time System, sorted by topics.
Extended Pascal treats files quite differently from Borland Pascal. GPC supports both forms, even in mixed ways, and provides many extensions.
@@ A lot missing here
function FileSize(filename : String) : LongInt;
var
f : bindable file [0..MaxInt] of char;
b : BindingType;
begin
unbind(f);
b := binding (f);
b.Name := filename;
bind(f, b);
b := binding(f);
SeekRead(f, 0);
if empty(f)
then file_size := 0
else file_size := LastPosition(f) + 1;
unbind(f);
end;
Prospero's Extended Pascal has a bug in this case. Replace the
MaxInt in the type definition of f by a sufficiently large
integer. GNU Pascal works correct in this case.
Put as
soon as possible and a Get as late as possible. This should
avoid most of the problems sometimes considered to be the most
stupid feature of Pascal. When passing a file buffer as parameter
the buffer is validated when the parameter is passed.
program DirectAccessFileDemo; type DFile = file [1 .. 100] of Integer; var F : DFile; P, N : 1 .. 100; begin Rewrite (F); P := 42; N := 17; SeekWrite (F, P); Write (F, N) end.The following direct access routines may be applied to a direct access file:
SeekRead (F, N); { Open file in inspection mode, seek to record N }
SeekWrite (F, N); { Open file in generation mode, seek to record N }
SeekUpdate (F, N); { Open file in update mode, seek to record N }
Update (F); { Writes F^, position not changed. F^ kept. }
p := Position (F); { Return current record number }
p := LastPosition (F); { Return the last record number in file }
Get may be applied.
If the file is open for generation or update, Put may be applied.
program AssignTextDemo;
var
t : Text;
Line : String (4096);
begin
Assign (t, 'mytext.txt');
Reset (t);
while not EOF (t) do
begin
ReadLn (t, Line);
WriteLn (Line)
end
end.
program BindingDemo (Input, Output, f);
var
f : bindable Text;
b : BindingType;
procedure BindFile (var f : Text);
var
b : BindingType;
begin
Unbind (f);
b := Binding (f);
repeat
Write ('Enter a file name: ');
ReadLn (b.Name);
Bind (f, b);
b := Binding (f);
if not b.Bound then
WriteLn ('File not bound -- try again.')
until b.Bound
end;
begin
BindFile (f);
{ Now the file f is bound to an external file. We can use the
implementation defined fields of BindingType to check if the
file exists and is readable, writable or executable. }
b := Binding (f);
Write ('The file ');
if b.Existing then
WriteLn ('exists.')
else
WriteLn ('does not exist.');
Write ('It is ');
if not b.Readable then Write ('not ');
Write ('readable, ');
if not b.Writable then Write ('not ');
Write ('writable and ');
if not b.Executable then Write ('not ');
WriteLn ('executable.')
end.
Note that Prospero's Pascal defaults to creating the file if it does
not exists! You need to use Prospero's local addition of setting
b.Existing to True to work-around this. GPC does not
behave like this.
In the following description, s1 and s2 may be
arbitrary string expressions, s is a variable of string type.
WriteStr (s, write-parameter-list)
ReadStr (s1, read-parameter-list)
Text files. The semantics is closely modeled after file I/O.
Index (s1, s2)
s2 is empty, return 1 else if s1 is empty return 0
else returns the position of s2 in s1 (an integer).
Length (s1)
s1 (an integer from 0 .. s1.Capacity).
Trim (s1)
s.
SubStr (s1, i)
SubStr (s1, i, j)
s1 that contains j
characters starting from i. If j is missing, return
all the characters starting from i.
EQ (s1, s2)
NE (s1, s2)
LT (s1, s2)
LE (s1, s2)
GT (s1, s2)
GE (s1, s2)
s1 and s2. Returns
a boolean result. Strings are not padded with spaces.
s1 = s2
s1 <> s2
s1 < s2
s1 <= s2
s1 > s2
s1 >= s2
s1 and s2. Returns a
boolean result. The shorter string is blank padded to length of the
longer one, but only in `--extended-pascal' mode.
GPC supports string catenation with the + operator or the
`Concat' function. All string-types are compatible, so you may
catenate any chars, fixed length strings and variable length
strings.
program ConcatDemo (Input, Output);
var
Ch : Char;
Str : String (100);
Str2 : String (50);
FStr : packed array [1 .. 20] of Char;
begin
Ch := '$';
FStr := 'demo'; { padded with blanks }
Write ('Give me some chars to play with: ');
ReadLn (Str);
Str := '^' + 'prefix:' + Str + ':suffix:' + FStr + Ch;
WriteLn (Concat ('Le', 'ng', 'th'), ' = ', Length (Str));
WriteLn (Str)
end.
Note: The length of strings in GPC is limited only by the range of `Integer' (at least 32 bits, i.e., 2 GB), or the available memory, whichever is smaller. :-)
When trying to write programs portable to other EP compilers, it is however save to assume a limit of about 32 KB. At least Prospero's Extended Pascal compiler limits strings to 32760 bytes. DEC Pascal limits strings to 65535 bytes.
GPC supports access to the command line arguments with the
BP compatible ParamStr and ParamCount functions.
ParamStr [0] is the program name,
ParamStr [1] .. ParamStr [ParamCount] are the arguments.
The program below accesses the command line arguments.
program CommandLineArgumentsDemo (Output);
var
Counter : Integer;
begin
WriteLn ('This program displays command line arguments one per line.');
for Counter := 0 to ParamCount do
WriteLn ('Command line argument #', Counter, ' is `',
ParamStr (Counter), '''')
end.
Besides the standard `New' and `Dispose' routines, GPC
also allows BP style dynamic memory management with GetMem
and FreeMem:
GetMem (MyPtr, 1024); FreeMem (MyPtr, 1024);
GPC also supports function style call to GetMem:
MyPtr := GetMem (1024);
(see also: New in context of Object Orientated Programming)
One somehow strange feature of Borland is not supported:
You cannot free parts of a variable with FreeMem, while the
rest is still used and can be freed later by another FreeMem
call:
program PartialFreeMemDemo;
type
Vector = array [0 .. 1023] of Integer;
VecPtr = ^Vector;
var
p, q : VecPtr;
begin
GetMem (p, 1024 * SizeOf (Integer));
q := VecPtr (@p^ [512]);
{ ... }
FreeMem (p, 512 * SizeOf (Integer));
{ ... }
FreeMem (q, 512 * SizeOf (Integer));
end.
shl and
shr exist in GPC as well as bitwise and, or,
xor and not for integer values.
2#100101 and (1 shl 5) = 2#100000GPC also supports
and, or, xor and not
as procedures:
program BitOperatorProcedureDemo;
var x : Integer;
begin
x := 7;
and (x, 14); { sets x to 6 }
xor (x, 3); { sets x to 5 }
end.
Inc and Dec exist in GPC.
program IncDecDemo;
var
i : Integer;
c : Char;
begin
Inc (i); { i := i + 1; }
Dec (i, 7); { i := i - 7; }
Inc (c, 3); { c := Succ (c, 3); }
end.
Min, Max:
These are a GNU extension and work for reals as well as for ordinal
types. Mixing reals and integers is okay, the result is real then.
@@ A lot of details missing here
+, -, *, / and
unary -, +
pow and **)
Sqr, ArcTan, SqRt, Exp,
Ln, Sin, Cos)
Re, Im and Arg functions
Cmplx or Polar
The following sample programs illustrates most of the Complex
type operations.
program ComplexOperationsDemo (Output);
var
z1, z2 : Complex;
Len, Angle : Real;
begin
z1 := Cmplx (2, 1);
WriteLn;
WriteLn ('Complex number z1 is: (', Re (z1) : 1, ',', Im (z1) : 1, ')');
WriteLn;
z2 := Conjugate(z1); { GPC extension }
WriteLn ('Conjugate of z1 is: (', Re (z2) : 1, ',', Im (z2) : 1, ')');
WriteLn;
Len := Abs (z1);
Angle := Arg (z1);
WriteLn ('The polar representation of z1 is: Length=', Len : 1,
', Angle=', Angle : 1);
WriteLn;
z2 := Polar (Len, Angle);
WriteLn ('Converting (Length, Angle) back to (x, y) gives: (',
Re (z2) : 1, ',', Im (z2) : 1, ')');
WriteLn;
WriteLn ('The following operations operate on the complex number z1');
WriteLn;
z2 := ArcTan (z1);
WriteLn ('arctan (z1) = (', Re (z2), ', ', Im (z2), ')');
WriteLn;
z2 := z1 ** 3.141;
WriteLn ('z1 ** 3.141 =', Re (z2), ', ', Im (z2), ')');
WriteLn;
z2 := Sin (z1);
WriteLn ('Sin (z1) = (', Re (z2), ', ', Im (z2), ')');
WriteLn ('(Cos, Ln, Exp, SqRt and Sqr exist also.)');
WriteLn;
z2 := z1 pow 8;
WriteLn ('z1 pow 8 = (', Re (z2), ', ', Im (z2), ')');
WriteLn;
z2 := z1 pow (-8);
WriteLn ('z1 pow (-8) = (', Re (z2), ', ', Im (z2), ')');
end.
@@ A lot missing here
GPC supports Standard Pascal set operations. In addition it supports the Extended Pascal set operation symmetric difference
(set1 >< set2) operation whose result consists of those
elements which are in exactly one of the operannds.
It also has a function that counts the elements in the set: `a := Card (set1)'.
procedure GetTimeStamp (var t : TimeStamp);
function Date (t : TimeStamp) : packed array [1 .. DateLength] of Char;
function Time (t : TimeStamp) : packed array [1 .. TimeLength] of Char;
DateLength and TimeLength are implementation dependent
constants.
GetTimeStamp (t) fills the record `t' with values. If
they are valid, the Boolean flags are set to True.
TimeStamp is a predefined type in the Extended Pascal
standard. It may be extended in an implementation, and is indeed
extended in GPC. For the full definition of `TimeStamp', see
section TimeStamp.
The standardized GNU compiler back-end makes it relatively easy to share libraries between GNU Pascal and other GNU compilers. On Unix-like platforms (not on Dos-like platforms), the GNU compiler back-end usually complies to the standards defined for that system, so communication with other compilers should be easy, too.
In this chapter we discuss how to import libraries written in other languages, and how to import libraries written in GNU Pascal from other languages. While the examples will specialize to compatibility to GNU C, generalization is straightforward if you are familiar with the other language in question.
To use a function written in another language, you need to provide an external declaration for it -- either in the program, or in the interface part of a unit, or an interface module.
Let's say you want to use the following C library from Pascal:
File `callc.c':
#include <unistd.h>
#include "callc.h"
int foo = 1;
void bar (void)
{
sleep (foo);
}
File `callc.h': /* Actually, we wouldn't need this header file, and could instead put these prototypes into callc.c, unless we want to use callc.c also from other C source files. */ extern int foo; extern void bar (void);
Then your program can look like this:
program CallCDemo;
{$L callc.c} { Or: `callc.o' if you don't have the source }
var
foo : Integer; asmname 'foo'; external;
procedure Bar; asmname 'bar';
begin
foo := 42;
Bar
end.
Or, if you want to provide a `CallCUnit' unit:
unit CallCUnit;
interface
var
foo : Integer; asmname 'foo'; external;
procedure Bar; asmname 'bar';
implementation
{$L callc.c} { Or: `callc.o' if you don't have the source }
end.
program CallCUDemo; uses CallCUnit; begin foo := 42; Bar end.
You can either link your program manually with `callc.o' or put a compiler directive `{$L callc.o}' into your program or unit, and then GPC takes care of correct linking. If you have the source of the C library (you always have it if it is Free Software), you can even write `{$L callc.c}' in the program (like above). Then GPC will also link with `callc.o', but in addition GPC will run the C compiler whenever `callc.c' has changed if `--automake' is given, too.
While it is convenient for most applications, there is no must to give the C function `bar' the name `Bar' in Pascal; you can name it as you like.
For external functions completely written in lowercase there is the shortcut `C' or `C_language' for `asmname 'bar''. For external functions written with one uppercase letter and the others in lowercase, you can use `external' or `extern' instead of `asmname 'Bar''. Since GPC internally converts all identifiers to this notation, `external' is the natural choice when importing other Pascal functions.
Caution: This syntax (`C', `asmname' and such) is subject to change.
It is important that data types of both languages are mapped correctly onto each other. C's `int', for instance, translates to GPC's `Integer', and C's `unsigned long' to `MedCard'. For a complete list of integer types with their C counterparts, see section Integer Types.
In some cases it can be reasonable to translate a C pointer parameter to a Pascal `var' parameter. Since const parameters in GPC can be passed by value or by reference internally, possibly depending on the system, `const foo *' parameters to C functions cannot reliably declared as `const' in Pascal. However, Extended Pascal's `protected var' can be used since this guarantees passing by reference.
Some libraries provide a `main' function and require your program's "main" to be named differently. To achive this with GPC, invoke it with an option `--gpc-main="GPCmain"' (where `GPCmain' is an example how you might want to name the program). You can also write it into your source as a directive `{$gpc-main="GPCmain"}'.
The `.o' files produced by GPC are in the same format as those of all other GNU compilers, so there is no problem in writing libraries for other languages in Pascal. To use them, you will need to write kind of interface -- a header file in C. However there are some things to take into account, especially if your Pascal unit exports objects:
procedure FooBAR; asmname 'FooBAR';
{ Works like a `forward' declaration }
procedure FooBAR;
begin
WriteLn ('FooBAR')
end;
This one can be imported from C with `extern void FooBar()'.
type
VMT = record
ObjectSize: PtrInt; { Size of object in bytes }
NegObjectSize: PtrInt; { Negated size }
Methods: array [1 .. n] of procedure;
{ Pointers to the virtual methods. The entries are of the
repective procedure or function types. }
end;
You can call a virtual method of an object from C if you explicitly declare
this `struct' and explicitly dereference the `Fun' array. The VMT
of an object `FooBAR' is an external (in C sense) variable `vmt_Foobar'
internally.
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.)
{
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 `asmnames', 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 declared as `const' in
Pascal. However, Extended Pascal's `protected var' can be used since
this guarantees passing by reference.
Copyright (C) 1998-2001 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-}
module GPC interface;
export
GPC = all;
GPC_SP = (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, Pos);
GPC_Delphi = (MaxLongInt, Int64, InitProc, EConvertError,
ExitCode, ErrorAddr, Pos, SetString, StringOfChar,
TextFile, AssignFile, CloseFile);
const
MaxLongInt = High (LongInt);
{ Maximum size of a variable }
MaxVarSize = MaxInt div 8;
type
Int64 = Integer (64);
var
InitProc : ^procedure; external; asmname '_p_initproc';
{ ====================== MEMORY MANAGEMENT ======================= }
{ Heap manipulation, from heap.c }
{ 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; asmname 'malloc';
procedure CFreeMem (aPointer : Pointer); asmname 'free';
function CReAllocMem (aPointer : Pointer; NewSize : SizeType) :
Pointer; asmname '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; asmname '_p_getmem_ptr'; external;
FreeMemPtr : FreeMemType; asmname '_p_freemem_ptr'; external;
ReAllocMemPtr : ReAllocMemType; asmname '_p_reallocmem_ptr';
external;
{ Points to the lowest byte of heap used }
HeapBegin : Pointer; asmname '_p_heap_begin'; external;
{ Points to the highest byte of heap used }
HeapHigh : Pointer; asmname '_p_heap_high'; external;
const
UndocumentedReturnNil = Pointer (- 1);
{ 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));
asmname '_p_foreachmarkedblock';
procedure ReAllocMem (var aPointer : Pointer; NewSize : SizeType);
asmname '_p_reallocmem';
{ Routines to handle endianness, from endian.pas }
{ Boolean constants about endianness and alignment }
const
BitsBigEndian = {$ifdef __BITS_LITTLE_ENDIAN__} False
{$else}{$ifdef __BITS_BIG_ENDIAN__} True
{$else}{$error Bit endianness is not defined!}
{$endif}{$endif};
BytesBigEndian = {$ifdef __BYTES_LITTLE_ENDIAN__} False
{$else}{$ifdef __BYTES_BIG_ENDIAN__} True
{$else}{$error Byte endianness is not defined!}
{$endif}{$endif};
WordsBigEndian = {$ifdef __WORDS_LITTLE_ENDIAN__} False
{$else}{$ifdef __WORDS_BIG_ENDIAN__} True
{$else}{$error Word endianness is not defined!}
{$endif}{$endif};
NeedAlignment = {$ifdef __NEED_ALIGNMENT__} True
{$else} False {$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); asmname '_p_reversebytes';
procedure ConvertFromLittleEndian (var Buf; ElementSize, Count :
SizeType); asmname '_p_convertlittleendian';
procedure ConvertFromBigEndian (var Buf; ElementSize, Count :
SizeType); asmname '_p_convertbigendian';
procedure ConvertToLittleEndian (var Buf; ElementSize, Count :
SizeType); asmname '_p_convertlittleendian';
procedure ConvertToBigEndian (var Buf; ElementSize, Count :
SizeType); asmname '_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'. }
(*@@iocritical*)procedure BlockReadLittleEndian (var aFile : File;
var Buf; ElementSize, Count : SizeType);
asmname '_p_blockread_littleendian';
(*@@iocritical*)procedure BlockReadBigEndian (var aFile : File;
var Buf; ElementSize, Count : SizeType);
asmname '_p_blockread_bigendian';
{ 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'. }
(*@@iocritical*)procedure BlockWriteLittleEndian (var aFile : File;
const Buf; ElementSize, Count : SizeType);
asmname '_p_blockwrite_littleendian';
(*@@iocritical*)procedure BlockWriteBigEndian (var aFile : File;
const Buf; ElementSize, Count : SizeType);
asmname '_p_blockwrite_bigendian';
{ 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. }
(*@@iocritical*)procedure ReadStringLittleEndian (var f : File; var
s : String); asmname '_p_ReadStringLittleEndian';
(*@@iocritical*)procedure ReadStringBigEndian (var f : File; var
s : String); asmname '_p_ReadStringBigEndian';
(*@@iocritical*)procedure WriteStringLittleEndian (var f : File;
const s : String); asmname '_p_WriteStringLittleEndian';
(*@@iocritical*)procedure WriteStringBigEndian (var f : File;
const s : String); asmname '_p_WriteStringBigEndian';
{ =================== STRING HANDLING ROUTINES =================== }
{ String handling routines, from string.pas }
type
AnyFile = Text; (*@@ create `AnyFile' parameters*)
PAnyFile = ^AnyFile;
{ 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
TStringSize = 2048;
SpaceCharacters = [' ', #9];
NewLine = "\n"; { the separator of lines within a string }
LineBreak = {$ifdef __OS_DOS__} "\r\n" {$else} "\n" {$endif};
{ the separator of lines within a file }
type
TString = String (TStringSize);
TStringBuf = packed array [0 .. TStringSize] of Char;
PString = ^String;
CharSet = set of Char;
PCStrings = ^TCStrings;
TCStrings = array [0 .. MaxVarSize div SizeOf (CString)] of
CString;
var
CParamCount : Integer; asmname '_p_argc'; external;
CParameters : PCStrings; asmname '_p_argv'; external;
function MemCmp (const s1, s2; Size : SizeType) : Integer;
asmname 'memcmp';
function MemComp (const s1, s2; Size : SizeType) : Integer;
asmname 'memcmp';
function MemCompCase (const s1, s2; Size : SizeType) : Boolean;
asmname '_p_memcmpcase';
procedure UpCaseString (var s : String);
asmname '_p_upcase_string';
procedure LoCaseString (var s : String);
asmname '_p_locase_string';
function UpCaseStr (const s : String) : TString;
asmname '_p_upcase_str';
function LoCaseStr (const s : String) : TString;
asmname '_p_locase_str';
function IsUpCase (ch : Char) : Boolean;
attribute (const); asmname '_p_isupcase';
function IsLoCase (ch : Char) : Boolean;
attribute (const); asmname '_p_islocase';
function IsAlpha (ch : Char) : Boolean;
attribute (const); asmname '_p_isalpha';
function IsAlphaNum (ch : Char) : Boolean;
attribute (const); asmname '_p_isalphanum';
function IsAlphaNumUnderscore (ch : Char) : Boolean;
attribute (const); asmname '_p_isalphanumunderscore';
function IsSpace (ch : Char) : Boolean;
attribute (const); asmname '_p_isspace';
function IsPrintable (ch : Char) : Boolean;
attribute (const); asmname '_p_isprintable';
function StrEqualCase (const s1, s2 : String) : Boolean;
asmname '_p_strequalcase';
function Pos (const SubString, aString : String) :
Integer; asmname '_p_pos';
function LastPos (const SubString, aString : String) :
Integer; asmname '_p_lastpos';
function PosCase (const SubString, aString : String) :
Integer; asmname '_p_poscase';
function LastPosCase (const SubString, aString : String) :
Integer; asmname '_p_lastposcase';
function CharPos (const Chars : CharSet; const aString :
String) : Integer; asmname '_p_charpos';
function LastCharPos (const Chars : CharSet; const aString :
String) : Integer; asmname '_p_lastcharpos';
function PosFrom (const SubString, aString : String; From :
Integer) : Integer; asmname '_p_posfrom';
function LastPosTill (const SubString, aString : String; Till :
Integer) : Integer; asmname '_p_lastpostill';
function PosFromCase (const SubString, aString : String; From :
Integer) : Integer; asmname '_p_posfromcase';
function LastPosTillCase (const SubString, aString : String; Till :
Integer) : Integer; asmname '_p_lastpostillcase';
function CharPosFrom (const Chars : CharSet; const aString :
String; From : Integer) : Integer; asmname '_p_charposfrom';
function LastCharPosTill (const Chars : CharSet; const aString :
String; Till : Integer) : Integer; asmname '_p_lastcharpostill';
function IsPrefix (const Prefix, s : String) : Boolean;
asmname '_p_isprefix';
function IsSuffix (const Suffix, s : String) : Boolean;
asmname '_p_issuffix';
function IsPrefixCase (const Prefix, s : String) : Boolean;
asmname '_p_isprefixcase';
function IsSuffixCase (const Suffix, s : String) : Boolean;
asmname '_p_issuffixcase';
function CStringLength (Src : CString) : SizeType;
asmname '_p_strlen';
function CStringEnd (Src : CString) : CString;
asmname '_p_strend';
function CStringNew (Src : CString) : CString;
asmname '_p_strdup';
function CStringComp (s1, s2 : CString) : Integer;
asmname '_p_strcmp';
function CStringCaseComp (s1, s2 : CString) : Integer;
asmname '_p_strcasecmp';
function CStringLComp (s1, s2 : CString; MaxLen : SizeType) :
Integer; asmname '_p_strlcmp';
function CStringLCaseComp (s1, s2 : CString; MaxLen : SizeType) :
Integer; asmname '_p_strlcasecmp';
function CStringCopy (Dest, Source : CString) : CString;
asmname '_p_strcpy';
function CStringCopyEnd (Dest, Source : CString) : CString;
asmname '_p_strecpy';
function CStringLCopy (Dest, Source : CString; MaxLen :
SizeType) : CString; asmname '_p_strlcpy';
function CStringMove (Dest, Source : CString; Count :
SizeType) : CString; asmname '_p_strmove';
function CStringCat (Dest, Source : CString) : CString;
asmname '_p_strcat';
function CStringLCat (Dest, Source : CString; MaxLen :
SizeType) : CString; asmname '_p_strlcat';
function CStringChPos (Src : CString; Ch : Char) : CString;
asmname '_p_strscan';
function CStringLastChPos (Src : CString; Ch : Char) : CString;
asmname '_p_strrscan';
function CStringPos (aString, SubString : CString) :
CString; asmname '_p_strpos';
function CStringLastPos (aString, SubString : CString) :
CString; asmname '_p_strrpos';
function CStringCasePos (aString, SubString : CString) :
CString; asmname '_p_strcasepos';
function CStringLastCasePos (aString, SubString : CString) :
CString; asmname '_p_strrcasepos';
function CStringUpCase (s : CString) : CString;
asmname '_p_strupper';
function CStringLoCase (s : CString) : CString;
asmname '_p_strlower';
function CStringIsEmpty (s : CString) : Boolean;
asmname '_p_strempty';
function NewCString (const Source : String) : CString;
asmname '_p_newcstring';
function CStringCopyString (Dest : CString; const Source :
String) : CString; asmname '_p_cstringcopystring';
procedure CopyCString (Source : CString; var Dest : String);
asmname '_p_copycstring';
function NewString (const s : String) : PString;
asmname '_p_newstring';
procedure DisposeString (p : PString); asmname '_p_dispose';
procedure SetString (var s : String; Buffer : PChar; Count :
Integer); asmname '_p_set_string';
function StringOfChar (Ch : Char; Count : Integer) = s :
TString; asmname '_p_string_of_char';
procedure TrimLeft (var s : String); asmname '_p_trimleft';
procedure TrimRight (var s : String); asmname '_p_trimright';
procedure TrimBoth (var s : String); asmname '_p_trimboth';
function TrimLeftStr (const s : String) : TString;
asmname '_p_trimleft_str';
function TrimRightStr (const s : String) : TString;
asmname '_p_trimright_str';
function TrimBothStr (const s : String) : TString;
asmname '_p_trimboth_str';
function GetStringCapacity (const s : String) : Integer;
asmname '_p_get_string_capacity';
{ A shortcut for a common use of WriteStr as a function }
function Integer2String (i : Integer) : TString;
asmname '_p_Integer2String';
type
TChars = packed array [1 .. 1] of Char;
PChars = ^TChars;
{ 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; asmname '_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;
asmname '_p_getenv';
function CStringGetEnv (EnvVar : CString) : CString;
asmname '_p_cstringgetenv';
{ 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);
asmname '_p_setenv';
{ Un-sets an environment variable with the name given in VarName. }
procedure UnSetEnv (const VarName : String); asmname '_p_unsetenv';
{ Returns @Environment^.CStrings, converted to PCStrings, to be
passed to
libc routines like execve which expect an environment. }
function GetCEnvironment : PCStrings; asmname '_p_getcenvironment';
{ ================= RUNTIME ERROR HANDLING ETC. ================== }
{ Error handling functions, from error.pas }
const
EAssert = 381;
EOpen = 405;
EOpenRead = 442;
EOpenWrite = 443;
EOpenUpdate = 444;
EReading = 464;
EWriting = 466;
ERead = 413;
EWrite = 414;
EWriteReadOnly = 422;
EMMap = 408;
EIOCtl = 630;
EConvertError = 875;
ELibraryFunction = 952;
var
{ Error number (after runtime error) or exit status (after Halt)
or
0 (during program run and after succesful termination). }
ExitCode : Integer; asmname '_p_exitcode'; external;
{ Contains the address of the code where a runtime occurred, nil
if no runtime error occurred. }
ErrorAddr : Pointer; asmname '_p_erroraddr'; external;
{ Error message }
ErrorMessageString : TString; asmname '_p_errormessagestring';
external;
function GetErrorMessage (n : Integer) : CString;
asmname '_p_errmsg';
procedure RuntimeError (n : Integer);
attribute (noreturn); asmname '_p_error';
procedure RuntimeErrorInteger (n : Integer; i : MedInt);
attribute (noreturn); asmname '_p_error_integer';
procedure RuntimeErrorCString (n : Integer; s :
CString); attribute (noreturn);
asmname '_p_error_string';
procedure InternalError (n : Integer);
attribute (noreturn); asmname '_p_internal_error';
procedure InternalErrorInteger (n : Integer; i : MedInt);
attribute (noreturn); asmname '_p_internal_error_integer';
procedure RuntimeWarning (Message : CString);
asmname '_p_warning';
procedure RuntimeWarningInteger (Message : CString; i :
MedInt); asmname '_p_warning_integer';
procedure RuntimeWarningCString (Message : CString; s :
CString); asmname '_p_warning_string';
procedure DebugStatement (const FileName : String;
Line : Integer); asmname '_p_debug_statement';
(*iocritical*)procedure IOError (n :
Integer); asmname '_p_io_error';
(*iocritical*)procedure IOErrorInteger (n :
Integer; i : MedInt); asmname '_p_io_error_integer';
(*iocritical*)procedure IOErrorCString (n :
Integer; s : CString); asmname '_p_io_error_string';
(*iocritical*)procedure IOErrorFile (n :
Integer; protected var f : AnyFile); asmname '_p_io_error_file';
function GetIOErrorMessage : TString;
asmname '_p_get_io_error_message';
procedure CheckInOutRes; asmname '_p_check_inoutres';
{ 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); asmname '_p_RegisterRestoreTerminal';
{ 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; asmname '_p_UnregisterRestoreTerminal';
{ 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);
asmname '_p_RestoreTerminal';
{ 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. }
(*@@IO critical*)function Execute (const CmdLine : String) :
Integer; asmname '_p_execute';
(*@@IO critical*)function ExecuteNoTerminal (const CmdLine :
String) : Integer; asmname '_p_executenoterminal';
procedure AtExit (procedure Proc); asmname '_p_atexit';
procedure SetReturnAddress (Address : Pointer);
asmname '_p_SetReturnAddress';
procedure RestoreReturnAddress; asmname '_p_RestoreReturnAddress';
{ ==================== SIGNALS AND PROCESSES ===================== }
function ProcessID : Integer; asmname '_p_pid';
{ Extract information from the status returned by PWait }
function StatusExited (Status : Integer) : Boolean; attribute
(const); asmname '_p_WIfExited';
function StatusExitCode (Status : Integer) : Integer; attribute
(const); asmname '_p_WExitStatus';
function StatusSignaled (Status : Integer) : Boolean; attribute
(const); asmname '_p_WIfSignaled';
function StatusTermSignal (Status : Integer) : Integer; attribute
(const); asmname '_p_WTermSig';
function StatusStopped (Status : Integer) : Boolean; attribute
(const); asmname '_p_WIfStopped';
function StatusStopSignal (Status : Integer) : Integer; attribute
(const); asmname '_p_WStopSig';
type
TSignalHandler = procedure (Signal : Integer);
{ OldHandler and OldRestart may be null }
function InstallSignalHandler (Signal : Integer; Handler :
TSignalHandler;
Restart, UnlessIgnored : Boolean;
var OldHandler : TSignalHandler; var
OldRestart : Boolean) : Boolean; asmname '_p_sigaction';
procedure BlockSignal (Signal : Integer; Block : Boolean);
asmname '_p_BlockSignal';
function SignalBlocked (Signal : Integer) : Boolean;
asmname '_p_SignalBlocked';
var
{ Signal actions }
SignalDefault : TSignalHandler; asmname '_p_SIG_DFL'; external;
SignalIgnore : TSignalHandler; asmname '_p_SIG_IGN'; external;
SignalError : TSignalHandler; asmname '_p_SIG_ERR'; external;
{ Signals. The constants are set to the signal numbers, and
are 0 for signals not defined. }
{ POSIX signals }
SigHUp : Integer; asmname '_p_SIGHUP'; external;
SigInt : Integer; asmname '_p_SIGINT'; external;
SigQuit : Integer; asmname '_p_SIGQUIT'; external;
SigIll : Integer; asmname '_p_SIGILL'; external;
SigAbrt : Integer; asmname '_p_SIGABRT'; external;
SigFPE : Integer; asmname '_p_SIGFPE'; external;
SigKill : Integer; asmname '_p_SIGKILL'; external;
SigSegV : Integer; asmname '_p_SIGSEGV'; external;
SigPipe : Integer; asmname '_p_SIGPIPE'; external;
SigAlrm : Integer; asmname '_p_SIGALRM'; external;
SigTerm : Integer; asmname '_p_SIGTERM'; external;
SigUsr1 : Integer; asmname '_p_SIGUSR1'; external;
SigUsr2 : Integer; asmname '_p_SIGUSR2'; external;
SigChld : Integer; asmname '_p_SIGCHLD'; external;
SigCont : Integer; asmname '_p_SIGCONT'; external;
SigStop : Integer; asmname '_p_SIGSTOP'; external;
SigTStp : Integer; asmname '_p_SIGTSTP'; external;
SigTTIn : Integer; asmname '_p_SIGTTIN'; external;
SigTTOu : Integer; asmname '_p_SIGTTOU'; external;
{ Non-POSIX signals }
SigTrap : Integer; asmname '_p_SIGTRAP'; external;
SigIOT : Integer; asmname '_p_SIGIOT'; external;
SigEMT : Integer; asmname '_p_SIGEMT'; external;
SigBus : Integer; asmname '_p_SIGBUS'; external;
SigSys : Integer; asmname '_p_SIGSYS'; external;
SigStkFlt : Integer; asmname '_p_SIGSTKFLT'; external;
SigUrg : Integer; asmname '_p_SIGURG'; external;
SigIO : Integer; asmname '_p_SIGIO'; external;
SigPoll : Integer; asmname '_p_SIGPOLL'; external;
SigXCPU : Integer; asmname '_p_SIGXCPU'; external;
SigXFSz : Integer; asmname '_p_SIGXFSZ'; external;
SigVTAlrm : Integer; asmname '_p_SIGVTALRM'; external;
SigProf : Integer; asmname '_p_SIGPROF'; external;
SigPwr : Integer; asmname '_p_SIGPWR'; external;
SigInfo : Integer; asmname '_p_SIGINFO'; external;
SigLost : Integer; asmname '_p_SIGLOST'; external;
SigWinCh : Integer; asmname '_p_SIGWINCH'; external;
{ Signal subcodes (only used on some systems, -1 if not used) }
FPEIntegerOverflow : Integer; asmname '_p_FPE_INTOVF_TRAP';
external;
FPEIntegerDivisionByZero : Integer; asmname '_p_FPE_INTDIV_TRAP';
external;
FPESubscriptRange : Integer; asmname '_p_FPE_SUBRNG_TRAP';
external;
FPERealOverflow : Integer; asmname '_p_FPE_FLTOVF_TRAP';
external;
FPERealDivisionByZero : Integer; asmname '_p_FPE_FLTDIV_TRAP';
external;
FPERealUnderflow : Integer; asmname '_p_FPE_FLTUND_TRAP';
external;
FPEDecimalOverflow : Integer; asmname '_p_FPE_DECOVF_TRAP';
external;
{ Returns a description for a signal }
function StrSignal (Signal : Integer) : TString;
asmname '_p_strsignal';
{ 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, Signal : Integer) : Boolean; asmname '_p_kill';
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 : Integer; var WStatus : Integer; Block :
Boolean) : Integer; asmname '_p_waitpid';
{ 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, ProcessGroup : Integer) :
Boolean; asmname '_p_setpgid';
{ 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 (Terminal, ProcessGroup :
Integer) : Boolean; asmname '_p_tcsetpgrp';
{ Returns the process group of a terminal given by Terminal (as a
file handle), or -1 on error. }
function GetTerminalProcessGroup (Terminal : Integer) : Integer;
asmname '_p_tcgetpgrp';
{ Returns the file name of the terminal device that is open on the
file f. Returns nil if (and only if) f is not open or not
connected to a terminal. }
function GetTerminalName (protected var f : AnyFile) : CString;
asmname '_p_ttyname';
{ Set the standard input's signal generation, if it is a terminal. }
procedure SetInputSignals (Signals : Boolean);
asmname '_p_set_isig';
{ Get the standard input's signal generation, if it is a terminal. }
function GetInputSignals : Boolean; asmname '_p_get_isig';
{ Returns the real or effective user ID of the process. }
function UserID (Effective : Boolean) : Integer; asmname '_p_uid';
{ Returns the real or effective group ID of the process. }
function GroupID (Effective : Boolean) : Integer; asmname '_p_gid';
{ ================= COMMAND LINE OPTION PARSING ================== }
const
EndOfOptions = #255;
NoOption = #1;
UnknownOption = '?';
LongOption = #0;
UnknownLongOption = '?';
var
FirstNonOption : Integer; asmname '_p_first_non_option';
external;
HasOptionArgument : Boolean;
asmname '_p_has_option_argument'; external;
OptionArgument : TString; asmname '_p_option_argument';
external;
UnknownOptionCharacter : Char;
asmname '_p_unknown_option_character'; external;
GetOptErrorFlag : Boolean; asmname '_p_getopt_error_flag';
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;
asmname '_p_getopt';
type
OptArgType = (NoArgument, RequiredArgument, OptionalArgument);
OptionType = record
Name : 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; var LongOptions :
array [m .. n : Integer] of OptionType { can be null };
var LongIndex : Integer { can be null };
LongOnly : Boolean) : Char; asmname '_p_getopt_long';
{ 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);
asmname '_p_ResetGetOpt';
{ =========================== PEXECUTE =========================== }
const
PExecute_First = 1;
PExecute_Last = 2;
PExecute_One = PExecute_First or PExecute_Last;
PExecute_Search = 4;
PExecute_Verbose = 8;
{
PExecute: execute a program.
Program and Arguments are the arguments to execv/execvp.
Flags and PExecute_Search is non-zero if $PATH should be searched
(It's not clear that GCC passes this flag correctly). 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;
asmname '_p_pexecute';
function PWait (PID : Integer; var Status : Integer; Flags :
Integer) : Integer; asmname 'pwait';
{ ==================== TIME HANDLING ROUTINES ==================== }
{ Time and date routines for Extended Pascal, from time.pas }
const
DateLength = 11; { from types.h }
TimeLength = 8; { from types.h }
InvalidYear = - MaxInt;
type
UnixTimeType = LongInt; { This is hard-coded in the compiler. Do
not change here. }
MicroSecondTimeType = LongInt;
DateString = packed array [1 .. DateLength] of Char;
TimeString = packed array [1 .. TimeLength] of Char;
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];
asmname '_p_downame'; 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]; asmname '_p_monthname';
external;
function GetDayOfWeek (Day, Month, Year : Integer) : Integer;
asmname '_p_dayofweek';
procedure UnixTimeToTimeStamp (UnixTime : UnixTimeType; var
aTimeStamp : TimeStamp); asmname '_p_unix_time_to_time_stamp';
function TimeStampToUnixTime (protected var aTimeStamp :
TimeStamp) : UnixTimeType; asmname '_p_time_stamp_to_unix_time';
function GetMicroSecondTime : MicroSecondTimeType;
asmname '_p_get_micro_second_time';
{ Is the year a leap year? }
function IsLeapYear (Year : Integer) : Boolean;
asmname '_p_is_leap_year';
{ Returns the length of the month, taking leap years into account. }
function MonthLength (Month, Year : Integer) : Integer;
asmname '_p_month_length';
procedure Sleep (Seconds : Integer); asmname '_p_sleep';
procedure SleepMicroSeconds (MicroSeconds : Integer);
asmname '_p_sleep_microseconds';
function Alarm (Seconds : Integer) : Integer; asmname '_p_alarm';
procedure UnixTimeToTime (UnixTime : UnixTimeType; var Year, Month,
Day, Hour, Minute, Second : Integer);
asmname '_p_unix_time_to_time';
function TimeToUnixTime (Year, Month, Day, Hour, Minute, Second :
Integer) : UnixTimeType; asmname '_p_time_to_unix_time';
{ Get the real time. MicroSecond can be null and is ignored then. }
function GetUnixTime (var MicroSecond : Integer) : UnixTimeType;
asmname '_p_get_unix_time';
{ Get the CPU time used. MicroSecond can be null and is ignored
then.
Now, GetCPUTime can measure long CPU times reliably on most
systems
(e.g. Solaris where it didn't work before). }
function GetCPUTime (var MicroSecond : Integer) : Integer;
asmname '_p_get_cpu_time';
{
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) : TString; asmname '_p_format_time';
{ ==================== FILE HANDLING ROUTINES ==================== }
{ File handling routines and their support, mostly from files.pas
and file.c }
type
FileSizeType = LongInt;
procedure GetBinding (protected var aFile : AnyFile; var
aBinding : BindingType); asmname '_p_binding';
procedure ClearBinding (var aBinding : BindingType);
asmname '_p_clearbinding';
{ TFDD interface @@ Subject to change! Use with caution! }
type
TOpenMode = (foNone, foReset, foRewrite, foAppend, foSeekRead,
foSeekWrite, foSeekUpdate);
TOpenProc = procedure (var PrivateData; Mode : TOpenMode);
TSelectFunc = function (var PrivateData; Writing : Boolean) :
Integer; { called before select(), must return a handle }
TSelectProc = procedure (var PrivateData; var ReadSelect,
WriteSelect, ExceptSelect : Boolean); { called before and after
select() }
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;
procedure AssignTFDD (var f : AnyFile;
OpenProc : TOpenProc;
SelectFunc : TSelectFunc;
SelectProc : TSelectProc;
ReadFunc : TReadFunc;
WriteFunc : TWriteFunc;
FlushProc : TFlushProc;
CloseProc : TCloseProc;
DoneProc : TDoneProc;
PrivateData : Pointer);
asmname '_p_assign_tfdd';
procedure SetTFDD (var f : AnyFile;
OpenProc : TOpenProc;
SelectFunc : TSelectFunc;
SelectProc : TSelectProc;
ReadFunc : TReadFunc;
WriteFunc : TWriteFunc;
FlushProc : TFlushProc;
CloseProc : TCloseProc;
DoneProc : TDoneProc;
PrivateData : Pointer); asmname '_p_set_tfdd';
{ Any parameter except f may be null }
procedure GetTFDD (var f : AnyFile;
var OpenProc : TOpenProc;
var SelectFunc : TSelectFunc;
var SelectProc : TSelectProc;
var ReadFunc : TReadFunc;
var WriteFunc : TWriteFunc;
var FlushProc : TFlushProc;
var CloseProc : TCloseProc;
var DoneProc : TDoneProc;
var PrivateData : Pointer);
asmname '_p_get_tfdd';
type
Natural = 1 .. MaxInt;
IOSelectEvents = (SelectReadOrEOF, SelectRead, SelectEOF,
SelectWrite, SelectException, SelectAlways);
const
IOSelectEventMin = (*Low (IOSelectEvents);*)SelectReadOrEOF;
IOSelectEventMax = Pred (SelectAlways);
type
IOSelectType = record
f : PAnyFile;
Wanted : set of IOSelectEvents;
Occurred : set of IOSelectEventMin .. IOSelectEventMax
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 for which 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;
asmname '_p_ioselect';
{ 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;
asmname '_p_ioselectread';
procedure AssignFile (var T : AnyFile; const Name : String);
asmname '_p_assign';
procedure AssignBinary (var T : Text; const Name : String);
asmname '_p_assign_binary';
procedure AssignHandle (var T : AnyFile; Handle : Integer);
asmname '_p_assign_handle';
{ BP compatible seeking routines }
function SeekEOF (var f : Text) : Boolean; asmname '_p_seekeof';
function SeekEOLn (var f : Text) : Boolean; asmname '_p_seekeoln';
{ Under development }
procedure AnyStringTFDD_Reset (var f : AnyFile; var Buf :
ConstAnyString); asmname '_p_anystring_tfdd_reset';
(*procedure AnyStringTFDD_Rewrite (var f : AnyFile; var Buf :
VarAnyString); asmname '_p_anystring_tfdd_rewrite';*)
procedure StringTFDD_Reset (var f : AnyFile; var Buf :
ConstAnyString; const s : String); asmname '_p_string_tfdd_reset';
(*procedure StringTFDD_Rewrite (var f : AnyFile; var Buf :
VarAnyString; var s : String); asmname '_p_string_tfdd_rewrite';*)
(*@@iocritical*)procedure FileMove (var f : AnyFile; NewName :
CString; Overwrite : Boolean); asmname '_p_mv';
{ Flags that can be ORed into FileMode. The default value of
FileMode is FileMode_Reset_ReadWrite. The somewhat confusing
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;
{ File mode constants that are ORed for BindingType.Mode and ChMod.
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;
type
TextFile = Text;
StatFSBuffer = record
BlockSize, BlocksTotal, BlocksFree : LongestInt;
FilesTotal, FilesFree : Integer
end;
const
NoChange = -1; { can be passed to ChOwn for Owner and/or Group to
not change that value }
procedure CloseFile ( var aFile : (*@@Any*)File);
asmname '_p_close';
(*@@IO critical*) procedure ChMod ( var aFile :
AnyFile; Mode : Integer); asmname '_p_chmod';
(*@@IO critical*) procedure ChOwn ( var aFile :
AnyFile; Owner, Group : Integer); asmname '_p_chown';
(*@@IO critical*) procedure StatFS (Path : CString; var Buf :
StatFSBuffer); asmname '_p_statfs';
{ Checks if data are available to be read from aFile. This is
similar to
`not EOF (aFile)', but does not block on "files" that can grow,
like TTYs
or pipes. }
function CanRead (var aFile : AnyFile) : Boolean;
asmname '_p_canread';
{ Get the file handle. }
function FileHandle (protected var aFile : AnyFile) : Integer;
asmname '_p_filehandle';
{ Lock files }
function FileLock (var aFile : AnyFile; WriteLock, Block :
Boolean) : Boolean; asmname '_p_filelock';
function FileUnlock (var aFile : AnyFile) : Boolean;
asmname '_p_fileunlock';
const
mm_Readable = 1;
mm_Writable = 2;
mm_Executable = 4;
function MemoryMap (Start : Pointer; Length : SizeType; Access :
Integer; Shared : Boolean;
var aFile : AnyFile; Offset : FileSizeType) :
Pointer; asmname '_p_mmap';
procedure MemoryUnMap (Start : Pointer; Length : SizeType);
asmname '_p_munmap';
{ File name routines, from filename.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 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__}
const
OSDosFlag = True;
QuotingCharacter = #0;
PathSeparator = {$ifdef __CYGWIN32__} ':' {$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;
{ `+ 1' is a waste, but it is so the size of the array is not
zero for Count = 0 }
PPStrings = ^TPStrings;
TPStrings (Count : Cardinal) = array [1 .. Count + 1] of ^String;
GlobBuffer = record
Result : PPStrings;
Internal1 : Pointer;
Internal2 : PCStrings;
Internal3 : Integer
end;
{ Convert ch to lower case if FileNamesCaseSensitive is False, leave
it unchanged otherwise. }
function FileNameLoCase (ch : Char) : Char;
asmname '_p_filenamelocase';
{ Change a file name to use the OS dependent directory separator }
function Slash2OSDirSeparator (const s : String) : TString;
asmname '_p_slash2osdirseparator';
{ Change a file name to use '/' as directory separator }
function OSDirSeparator2Slash (const s : String) : TString;
asmname '_p_osdirseparator2slash';
{ Like Slash2OSDirSeparator for CStrings -- NOTE: overwrites the
CString }
function Slash2OSDirSeparator_CString (s : CString) : CString;
asmname '_p_slash2osdirseparator_cstring';
{ Like OSDirSeparator2Slash for CStrings -- NOTE: overwrites the
CString }
function OSDirSeparator2Slash_CString (s : CString) : CString;
asmname '_p_osdirseparator2slash_cstring';
{ 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) : TString;
asmname '_p_adddirseparator';
{ Like AddDirSeparator, but also if the directory does not exist }
function ForceAddDirSeparator (const s : String) : TString;
asmname '_p_forceadddirseparator';
{ 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) : TString;
asmname '_p_removedirseparator';
{ Returns the current directory using OS dependent directory
separators }
function GetCurrentDirectory : TString;
asmname '_p_get_current_directory';
{ 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;
asmname '_p_get_temp_directory';
{ Returns a non-existing file name in the directory given. If the
directory doesn't exist or the Directory name is empty, a runtime
error is raised, and GetTempFileNameInDirectory returns the empty
string. }
(*@@iocritical*)function GetTempFileNameInDirectory (const
Directory : String) : TString;
asmname '_p_get_temp_file_name_in_directory';
{ Returns a non-existing file name in GetTempDirectory. If no temp
directory is found, i.e. GetTempDirectory returns the empty
string, a runtime error is raised, and GetTempFileName returns the
empty string as well. }
(*@@iocritical*)function GetTempFileName : TString;
asmname '_p_get_temp_file_name';
{ The same as GetTempFileName, but returns a CString allocated from
the heap. }
(*@@iocritical*)function GetTempFileName_CString : CString;
asmname '_p_get_temp_file_name_cstring';
{ Get the external name of a file }
function FileName (protected var f : AnyFile) : TString;
asmname '_p_file_name';
{ Returns true if the given file name is an existing plain file }
function FileExists (const aFileName : String) : Boolean;
asmname '_p_file_exists';
{ Returns True if the given file name is an existing directory }
function DirectoryExists (const aFileName : String) : Boolean;
asmname '_p_directory_exists';
{ 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;
asmname '_p_path_exists';
{ 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;
asmname '_p_fsearch';
{ 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) :
TString; asmname '_p_fsearch_executable';
{ 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;
asmname '_p_expand_environment';
{ 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;
asmname '_p_fexpand';
{ 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;
asmname '_p_fexpandquoted';
{ 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) : TString; asmname '_p_relative_path';
{ Is aFileName a UNC filename? (Always returns False on non-Dos
systems.) }
function IsUNC (const aFileName : String) : Boolean;
asmname '_p_IsUNC';
{ Splits a file name into directory, name and extension. Each of
Dir, Name and Ext may be null. }
procedure FSplit (const Path : String; var Dir, Name, Ext : String);
asmname '_p_fsplit';
{ 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) : TString;
asmname '_p_dir_from_path';
function NameFromPath (const Path : String) : TString;
asmname '_p_name_from_path';
function ExtFromPath (const Path : String) : TString;
asmname '_p_ext_from_path';
function NameExtFromPath (const Path : String) : TString;
asmname '_p_name_ext_from_path';
{ 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. }
(*@@iocritical*)function OpenDir (const Name : String) : DirPtr;
asmname '_p_opendir';
{ 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; asmname '_p_readdir';
{ Closes a directory opened with OpenDir. }
(*@@iocritical*)procedure CloseDir (Dir : DirPtr);
asmname '_p_closedir';
{ 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; asmname '_p_findnonquotedchar';
{ 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; asmname '_p_findnonquotedstr';
{ Does a string contain non-quoted wildcard characters? }
function HasWildCards (const s : String) : Boolean;
asmname '_p_haswildcards';
{ Does a string contain non-quoted wildcard characters, braces or
spaces? }
function HasWildCardsOrBraces (const s : String) : Boolean;
asmname '_p_haswildcardsorbraces';
{ Insert QuotingCharacter into s before any special characters }
function QuoteFileName (const s : String; const SpecialCharacters :
CharSet) : TString; asmname '_p_quote_filename';
{ Remove QuotingCharacter from s }
function UnQuoteFileName (const s : String) : TString;
asmname '_p_unquote_filename';
{ 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) : PPStrings;
asmname '_p_braceexpand';
{ 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);
asmname '_p_DisposePPStrings';
{ Tests if a file name matches a shell wildcard pattern (?, *, []) }
function FileNameMatch (const Pattern, Name : String) : Boolean;
asmname '_p_filenamematch';
{ FileNameMatch with BraceExpand }
function MultiFileNameMatch (const Pattern, Name : String) :
Boolean; asmname '_p_multifilenamematch';
{ 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); asmname '_p_globinit';
procedure Glob (var Buf : GlobBuffer; const Pattern :
String); asmname '_p_glob';
procedure GlobOn (var Buf : GlobBuffer; const Pattern :
String); asmname '_p_globon';
procedure MultiGlob (var Buf : GlobBuffer; const Pattern :
String); asmname '_p_multiglob';
procedure MultiGlobOn (var Buf : GlobBuffer; const Pattern :
String); asmname '_p_multiglobon';
procedure GlobFree (var Buf : GlobBuffer); asmname '_p_globfree';
type
TPasswordEntry = record
UserName, RealName, Password, HomeDirectory, Shell : TString;
UID, GID : Integer
end;
PPasswordEntries = ^TPasswordEntries;
TPasswordEntries (Count : Integer) = array [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) : Boolean;
asmname '_p_getpasswordentrybyname';
{ Finds a password entry by UID. Returns True if found, False
otherwise. }
function GetPasswordEntryByUID (UID : Integer; var Entry :
TPasswordEntry) : Boolean; asmname '_p_getpasswordentrybyuid';
{ Returns all password entries, or nil if none found. }
function GetPasswordEntries : PPasswordEntries;
asmname '_p_getpasswordentries';
{ 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;
asmname '_p_GetMountPoint';
type
TSystemInfo = record
OSName,
OSRelease,
OSVersion,
MachineType,
HostName,
DomainName : TString
end;
{ Returns system information if available. Fields not available will
be empty. }
function SystemInfo : TSystemInfo; asmname '_p_SystemInfo';
{ Returns the path to the shell (as the return value) 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) : TString;
asmname '_p_GetShellPath';
{ 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; asmname '_p_executable_path';
{ 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
Name 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>
Dos: $DJDIR\etc\<base>.ini $HOME\<base>.cfg
<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, Name : String; Global :
Boolean) : TString; asmname '_p_config_file_name';
{ 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>/
Dos: $DJDIR\share\<base>\
<dir>\
About the symbols used above, and the two possibilities under Dos,
see the comments for ConfigFileName. }
function DataDirectoryName (const Prefix, Name : String) : TString;
asmname '_p_data_directory_name';
{ ==================== MATHEMATICAL ROUTINES ===================== }
function IsInfinity (x : Extended) : Boolean; attribute (const);
asmname '_p_isinf';
function IsNotANumber (x : Extended) : Boolean; attribute (const);
asmname '_p_isnan';
procedure SplitReal (x : Extended; var Exponent : Integer; var
Mantissa : Extended); asmname '_p_frexp';
function SinH (x : Double) : Double; asmname '_p_sinh';
function CosH (x : Double) : Double; asmname '_p_cosh';
function Arctan2 (y, x : Double) : Double;
asmname '_p_arctan2';
type
RandomSeedType = Cardinal (32);
RandomizeType = ^procedure;
SeedRandomType = ^procedure (Seed : RandomSeedType);
RandRealType = ^function : LongestReal;
RandIntType = ^function (MaxValue : LongestCard) : LongestCard;
var
RandomizePtr : RandomizeType; asmname '_p_randomize_ptr';
external;
SeedRandomPtr : SeedRandomType; asmname '_p_seedrandom_ptr';
external;
RandRealPtr : RandRealType; asmname '_p_randreal_ptr'; external;
RandIntPtr : RandIntType; asmname '_p_randint_ptr'; external;
procedure SeedRandom (Seed : RandomSeedType);
asmname '_p_seedrandom';
end.
GPC distributions now include a number of useful Pascal units and a complete set of BP compatibility units -- except for the `Graph' unit (which is currently distributed separately due to its license) and the OOP stuff. The main use of these units is to provide a way to port BP programs to GPC as easily as possible. Some of the units also implement functionaliy not available otherwise.
Most of the BP compatibility units -- except `CRT' and `Printer' -- are merely meant to let programs written for BP compile with GPC as easily as possible. They should not be used in newly written code, and for code ported from BP to GPC, it is suggested to replace them successively with the more powerful -- and often easier to use -- alternatives that GPC's Run Time System (see section Pascal declarations for GPC's 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, section Pascal declarations for GPC's Run Time System).
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 ftp://agnes.dida.physik.uni-essen.de/gnu-pascal/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
ftp://agnes.dida.physik.uni-essen.de/gnu-pascal/libs/
(Note that ncurses is already installed on many Unix systems.) For
ncurses, version 5.0 or newer is strongly recommended because
older versions contain a bug that severely affects CRT programs.
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/x86 3) (terminal) X X 4) X 5) X 6) X 6)
Other Unix (terminal) X X 7) X 5) - -
Unix (X11 version) X X - 8) X -
Dos (DJGPP) X X X X X
MS-Windows (Cygwin or mingw) X - X 9) 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) But the user can resize the window.
9) 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.
Copyright (C) 1998-2001 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__ < 20000412}
{$error This unit requires GPC release 20000412 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; asmname 'crt_CheckBreak';
{ If True (default : False), replace Ctrl-Z by #0 in input }
CheckEOF : Boolean = False; asmname 'crt_CheckEOF';
{ Ignored -- meaningless in this context }
DirectVideo : Boolean = True;
{ Ignored -- curses or the terminal driver will take care of that
when necessary }
CheckSnow : Boolean = False;
{ Current (sic!) text mode }
LastMode : Word = 3; asmname 'crt_LastMode';
{ Current text attribute }
TextAttr : TTextAttr = 7; asmname 'crt_TextAttr';
{ Window upper left coordinates. *Obsolete*! Please see WindowMin
below. }
WindMin : Word = not Word (0); asmname 'crt_WindMin';
{ Window lower right coordinates. *Obsolete*! Please see WindowMax
below. }
WindMax : Word = not Word (0); asmname 'crt_WindMax';
procedure AssignCRT (var F : Text);
function KeyPressed : Boolean; asmname 'crt_keypressed';
function ReadKey : Char; asmname 'crt_readkey';
{ Not effective on all platforms, see above. See also SetScreenSize
and SetMonochrome. }
procedure TextMode (Mode : Integer);
procedure Window (x1, y1, x2, y2 : Integer); asmname 'crt_window';
procedure GotoXY (x, y : Integer); asmname 'crt_gotoxy';
function WhereX : Integer; asmname 'crt_wherex';
function WhereY : Integer; asmname 'crt_wherey';
procedure ClrScr; asmname 'crt_clrscr';
procedure ClrEOL; asmname 'crt_clreol';
procedure InsLine; asmname 'crt_insline';
procedure DelLine; asmname 'crt_delline';
procedure TextColor (Color : TTextAttr);
procedure TextBackground (Color : TTextAttr);
procedure LowVideo;
procedure HighVideo;
procedure NormVideo;
procedure Delay (MS : Word); asmname 'crt_delay';
{ Not available on all platforms, see above }
procedure Sound (Hz : Word); asmname 'crt_sound';
procedure NoSound; asmname '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; asmname '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); asmname 'crt_SetTerminal';
{ If called, 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. Should be called before
initializing CRT (using CRTInit or automatically), otherwise the
previous screen contents may already have been overwritten. Note
that on some terminals (e.g., xterms and similar), this is the
default behaviour. Ignored under XCurses, because the program it
uses its own window, anyway. }
procedure CRTSavePreviousScreen; asmname 'crt_save_previous_screen';
{ Returns True if CRTSavePreviousScreen was called and is available.
Note that CRTSavePreviousScreenWorks does not work reliably until
CRT is initialized, while CRTSavePreviousScreen should be called
before CRT is initialized. That's why they are two separate
routines. }
function CRTSavePreviousScreenWorks : Boolean;
asmname 'crt_save_previous_screen_works';
{ 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; asmname 'crt_auto_init_proc';
{ 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; asmname 'crt_not_initialized';
{ 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);
asmname 'crt_set_curses_mode';
{ 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;
asmname '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};
asmname 'crt_XCRT';
{ If True (default: False), the Beep procedure and writing #7 do a
Flash instead }
VisualBell : Boolean = False; asmname 'crt_VisualBell';
type
TKey = Word;
TCursorShape = (CursorIgnored, CursorHidden, CursorNormal,
CursorFat, CursorBlock);
TCRTUpdate = (UpdateNever, UpdateWaitInput, UpdateInput,
UpdateRegularly, UpdateAlways);
TPoint = record
X, Y : Integer
end;
PCharAttr = ^TCharAttr;
TCharAttr = record
Ch : Char;
Attr : TTextAttr;
PCCharSet : Boolean
end;
PCharAttrs = ^TCharAttrs;
TCharAttrs = array [1 .. MaxVarSize div SizeOf (TCharAttr)] of
TCharAttr;
TWindowXY = packed record
{$ifdef __BYTES_BIG_ENDIAN__}
Fill : Integer (BitSizeOf (Word) - 16);
Y, X : Word (8)
{$else}
X, Y : Word (8);
Fill : Integer (BitSizeOf (Word) - 16)
{$endif}
end;
{ Make sure TWindowXY really has the same size as WindMin and
WindMax. If not, compilation will abort here with `division by
zero'. Otherwise, the value of the constant will always be 1, and
is of no further interest. }
const
AssertTWindowXYSize = 1 / Ord ((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; asmname 'crt_NormAttr';
{ Tells whether the current mode is monochrome }
IsMonochrome : Boolean = False; asmname '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 : Integer = 0; asmname '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; asmname 'crt_GetScreenSize';
{ Change the screen size if possible. }
procedure SetScreenSize (x, y : Integer);
asmname 'crt_SetScreenSize';
{ Turns colors off or on. }
procedure SetMonochrome (Monochrome : Boolean);
asmname '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 : Integer; asmname '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);
asmname '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);
asmname 'crt_setupdatelevel';
{ Do an update now, independently of the update level }
procedure CRTUpdate; asmname 'crt_update_immediately';
{ Do an update now and completely redraw the screen }
procedure CRTRedraw; asmname 'crt_redraw';
{ Return Ord (key) for normal keys and $100 * Ord (fkey) for
function keys }
function ReadKeyWord : TKey; asmname '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; asmname 'crt_ctrlkey';
function AltKey (ch : Char) : TKey; asmname 'crt_altkey';
function AltGrKey (ch : Char) : TKey; asmname 'crt_altgrkey';
function ExtraKey (ch : Char) : TKey; asmname '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; asmname 'crt_beep';
procedure Flash; asmname '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); asmname 'crt_setscroll';
{ Read back whether scrolling is enabled }
function GetScroll : Boolean; asmname '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);
asmname 'crt_setpccharset';
{ Read back the value set by SetPCCharSet }
function GetPCCharSet : Boolean; asmname 'crt_getpccharset';
{ Determine whether to interpret #7, #8, #10, #13 as control
characters (True, default), or as graphics characters (False) }
procedure SetControlChars (UseControlChars : Boolean);
asmname 'crt_setcontrolchars';
{ Read back the value set by SetControlChars }
function GetControlChars : Boolean; asmname 'crt_getcontrolchars';
procedure SetCursorShape (Shape : TCursorShape);
asmname 'crt_setcursorshape';
function GetCursorShape : TCursorShape;
asmname '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; asmname '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;
asmname '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; 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 : Integer; CharAttr :
PCharAttrs); asmname 'crt_writecharattrat';
{ Write a char while moving the cursor }
procedure WriteChar (Ch : Char);
{ Read a character from a screen position }
procedure ReadChar (x, y : Integer; var Ch : Char; var Attr :
TTextAttr); asmname '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);
asmname 'crt_fillwin';
{ Calculate size of memory required for ReadWin in current window. }
function WinSize : SizeType; asmname 'crt_winsize';
{ Save window contents. Buf must be WinSize bytes large. }
procedure ReadWin (var Buf); asmname '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); asmname '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; asmname 'crt_GetActivePanel';
procedure PanelNew (x1, y1, x2, y2 : Integer;
BindToBackground : Boolean); asmname 'crt_PanelNew';
procedure PanelDelete (Panel : TPanel);
asmname 'crt_PanelDelete';
procedure PanelBindToBackground (Panel : TPanel; Bind : Boolean);
asmname 'crt_PanelBindToBackground';
function PanelIsBoundToBackground (Panel : TPanel) : Boolean;
asmname 'crt_PanelIsBoundToBackground';
procedure PanelActivate (Panel : TPanel);
asmname 'crt_PanelActivate';
procedure PanelHide (Panel : TPanel);
asmname 'crt_PanelHide';
procedure PanelShow (Panel : TPanel);
asmname 'crt_PanelShow';
function PanelHidden (Panel : TPanel) : Boolean;
asmname 'crt_PanelHidden';
procedure PanelTop (Panel : TPanel);
asmname 'crt_PanelTop';
procedure PanelBottom (Panel : TPanel);
asmname 'crt_PanelBottom';
procedure PanelMoveAbove (Panel, Above : TPanel);
asmname 'crt_PanelMoveAbove';
procedure PanelMoveBelow (Panel, Below : TPanel);
asmname 'crt_PanelMoveBelow';
function PanelAbove (Panel : TPanel) : TPanel;
asmname 'crt_PanelAbove';
function PanelBelow (Panel : TPanel) : TPanel;
asmname '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
WindowOrg : TPoint = (cw_UseDefault, cw_UseDefault); { Ignored }
WindowSize : TPoint = (cw_UseDefault, cw_UseDefault); { Ignored }
Cursor : TPoint = (0, 0); { Cursor location, 0-based }
asmname 'crt_cursor_pos';
Origin : TPoint = (0, 0); { Ignored }
InactiveTitle : PChar = '(Inactive %s)'; { Ignored }
AutoTracking : Boolean = True; { Ignored }
WindowTitle : {$ifdef __BP_TYPE_SIZES__}
array [0 .. 79] of Char
{$else}
TStringBuf
{$endif}; { CRT window title, ignored }
procedure InitWinCrt; asmname 'crt_initwincrt';
{ Halts the program }
procedure DoneWinCrt; attribute (noreturn);
asmname 'crt_donewincrt';
procedure WriteBuf (Buffer : PChar; Count : SizeType);
asmname 'crt_writebuf';
function ReadBuf (Buffer : PChar; Count : SizeType) : SizeType;
asmname 'crt_readbuf';
{ 0-based coordinates! }
procedure CursorTo (x, y : Integer); asmname 'crt_cursorto';
{ Dummy }
procedure ScrollTo (x, y : Integer); asmname 'crt_scrollto';
{ Dummy }
procedure TrackCursor; asmname 'crt_trackcursor';
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 x86 real mode -- specific, are only available if `__BP_UNPORTABLE_ROUTINES__' is defined, section BP Incompatibilities.
The same functionality and much more is available in the Run Time System, section Pascal declarations for GPC's 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 x86 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-2001 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-}
{$if __GPC_RELEASE__ < 20000412}
{$error This unit requires GPC release 20000412 or newer.}
{$endif}
unit Dos;
interface
uses GPC, System;
type
Byte8 = Cardinal (8);
TDosAttr = Word;
GPC_AnyFile = AnyFile; { in order to have AnyFile parameters,
while AnyFile is redefined below }
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 }
{$local W-} AnyFile = $3f; {$endlocal}
{ 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 = {$ifdef __BP_TYPE_SIZES__} packed {$endif} 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);
asmname '_p_getdate';
procedure GetTime (var Hour, Minute, Second, Sec100 : Word);
asmname '_p_gettime';
procedure GetCBreak (var BreakOn : Boolean); asmname '_p_getcbreak';
procedure SetCBreak (BreakOn : Boolean); asmname '_p_setcbreak';
{ 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);
asmname '_p_getverify';
procedure SetVerify (VerifyOn : Boolean); asmname '_p_setverify';
function DiskFree (Drive : Byte) : LongInt; asmname '_p_diskfree';
function DiskSize (Drive : Byte) : LongInt; asmname '_p_disksize';
procedure GetFAttr (var F (*@@anyfile : GPC_AnyFile*); var Attr :
TDosAttr); asmname '_p_getfattr';
procedure SetFAttr (var F (*@@anyfile : GPC_AnyFile*); Attr :
TDosAttr); asmname '_p_setfattr';
procedure GetFTime (var F (*@@anyfile : GPC_AnyFile*); var aTime :
LongInt); asmname '_p_getftime';
procedure SetFTime (var F (*@@anyfile : GPC_AnyFile*); aTime :
LongInt); asmname '_p_setftime';
{ 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); asmname '_p_findfirst';
procedure FindNext (var SR : SearchRec); asmname '_p_findnext';
procedure FindClose (var SR : SearchRec); asmname '_p_findclose';
procedure UnpackTime (P : LongInt; var T : DateTime);
asmname '_p_unpacktime';
procedure PackTime (const T : DateTime; var P : LongInt);
asmname '_p_packtime';
function FSearch (const aFileName, DirList : String) : TString;
asmname '_p_fsearch';
function FExpand (const Path : String) : TString;
asmname '_p_fexpand';
procedure FSplit (const Path : String; var Dir, Name, Ext :
String); asmname '_p_fsplit';
function EnvCount : Integer;
function EnvStr (EnvIndex : Integer) : TString;
function GetEnv (const EnvVar : String) : TString;
asmname '_p_getenv';
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 DJGPP}
{ 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);
asmname '_p_intr';
procedure MsDos (var Regs : Registers); asmname '_p_msdos';
{$endif}
{ Though probably all non-Dos system 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; asmname '_p_dosversion';
{ 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); asmname '_p_setdate';
procedure SetTime (Hour, Minute, Second, Sec100 : Word);
asmname '_p_settime';
{$endif}
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-2001 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__ < 20000412}
{$error This unit requires GPC release 20000412 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) : 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 Name : String);
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-2001 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__ < 20000412}
{$error This unit requires GPC release 20000412 or newer.}
{$endif}
unit FileUtils;
interface
uses GPC;
type
TStringProc = procedure (const Name : 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.
}
(*@@iocritical*)procedure FindFiles (const Directory, Mask : String;
MainDirFirst : Boolean;
FileAction, DirAction : TStringProc);
asmname '_p_findfiles';
{
Creates the directory given by Path and all directories in between
that are necessary. Does not report an error if Path already
exists and is a directory, but, of course, if it cannot be created
because of missing permissions or because Path already exists as a
file.
}
(*@@iocritical*)procedure MkDirs (const Path : String);
asmname '_p_mkdirs';
{
Removes Path if empty as well as any empty parent directories.
Does not report an error if Path is not empty.
}
(*@@iocritical*)procedure RmDirs (const Path : String);
asmname '_p_rmdirs';
{
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 would 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 coyping.
}
(*@@iocritical*)procedure FileCopy (const Source, Dest : String;
Mode : Integer); asmname '_p_filecopy';
{
Creates a backup of FileName in the directory BackupDirectory or,
if BackupDirectory is empty, in the directory of FileName. Errors
are returned in IOResult, 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 '~'
}
(*@@iocritical*)procedure BackupFile (const FileName,
BackupDirectory : String; Simple, Short, OnlyUserReadable :
Boolean); asmname '_p_backupfile';
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 ftp://agnes.dida.physik.uni-essen.de/gnu-pascal/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 2.0.2 and 3.0.1.
To use the GMP unit, you will need the GMP library which can be
found in ftp://agnes.dida.physik.uni-essen.de/gnu-pascal/libs/ .
Copyright (C) 1998-2001 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__ < 20000412}
{$error This unit requires GPC release 20000412 or newer.}
{$endif}
{$nested-comments}
{ If this define is set, routines new in GMP 3.x will be made
available. The define will have no effect on the other interface
changes between GMP 2.x and 3.x, i.e. the other routines will work
correctly even if this define is set incorrectly, except on 64 bit
machines, Crays and other systems where the types are different
between the GMP versions. Otherwise, the only possible problem if
setting the define while using GMP 2.x are linking errors if you
actually use any of the new routines. }
{$ifndef HAVE_GMP2}
{$define HAVE_GMP3}
{$endif}
unit gmp;
interface
uses GPC;
{$if defined (__mips) && defined (_ABIN32) && 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 = Cardinal;
mp_limb_signed_t = Integer;
{$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) && !defined (_CRAYMPP) && defined
(HAVE_GMP3)}
mp_size_t = Integer;
mp_exp_t = Integer;
{$else}
mp_size_t = MedInt;
mp_exp_t = MedInt;
{$endif}
mpz_t = record
mp_alloc,
mp_size : {$if defined (__MP_SMALL__) && defined (HAVE_GMP3)}
ShortInt
{$else}
Integer
{$endif};
mp_d : mp_ptr
end;
mpz_array_ptr = ^mpz_array;
mpz_array = array [0 .. MaxVarSize div SizeOf (mpz_t)] of mpz_t;
mpq_t = record
mp_num,
mp_den : mpz_t
end;
mpf_t = record
mp_prec,
mp_size : Integer;
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);
procedure mp_set_memory_functions (AllocFunction : TAllocFunction;
ReAllocFunction :
TReAllocFunction;
DeAllocProcedure :
TDeAllocProcedure); asmname '__gmp_set_memory_functions';
function mp_bits_per_limb : Integer; asmname '_p_mp_bits_per_limb';
{**************** Integer (i.e. Z) routines. ****************}
procedure mpz_init (var Dest : mpz_t);
asmname '__gmpz_init';
procedure mpz_clear (var Dest : mpz_t);
asmname '__gmpz_clear';
function mpz_realloc (var Dest : mpz_t; NewAlloc :
mp_size_t) : Pointer; asmname '__gmpz_realloc';
procedure mpz_array_init (Dest : mpz_array_ptr; ArraySize,
FixedNumBits : mp_size_t); asmname '__gmpz_array_init';
procedure mpz_set (var Dest : mpz_t; protected var
Src : mpz_t); asmname '__gmpz_set';
procedure mpz_set_ui (var Dest : mpz_t; Src : MedCard);
asmname '__gmpz_set_ui';
procedure mpz_set_si (var Dest : mpz_t; Src : MedInt);
asmname '__gmpz_set_si';
procedure mpz_set_d (var Dest : mpz_t; Src : Double);
asmname '__gmpz_set_d';
procedure mpz_set_q (var Dest : mpz_t; Src : mpq_t);
asmname '__gmpz_set_q';
procedure mpz_set_f (var Dest : mpz_t; Src : mpf_t);
asmname '__gmpz_set_f';
function mpz_set_str (var Dest : mpz_t; Src : CString;
Base : Integer) : Integer; asmname '__gmpz_set_str';
procedure mpz_init_set (var Dest : mpz_t; protected var
Src : mpz_t); asmname '__gmpz_init_set';
procedure mpz_init_set_ui (var Dest : mpz_t; Src : MedCard);
asmname '__gmpz_init_set_ui';
procedure mpz_init_set_si (var Dest : mpz_t; Src : MedInt);
asmname '__gmpz_init_set_si';
procedure mpz_init_set_d (var Dest : mpz_t; Src : Double);
asmname '__gmpz_init_set_d';
function mpz_init_set_str (var Dest : mpz_t; Src : CString;
Base : Integer) : Integer; asmname '__gmpz_init_set_str';
function mpz_get_ui (protected var Src : mpz_t) :
MedCard; asmname '__gmpz_get_ui';
function mpz_get_si (protected var Src : mpz_t) : MedInt;
asmname '__gmpz_get_si';
function mpz_get_d (protected var Src : mpz_t) : Double;
asmname '__gmpz_get_d';
{ Pass nil for Dest to let the function allocate memory for it }
function mpz_get_str (Dest : CString; Base : Integer;
protected var Src : mpz_t) : CString; asmname '__gmpz_get_str';
procedure mpz_add (var Dest : mpz_t; protected var
Src1, Src2 : mpz_t); asmname '__gmpz_add';
procedure mpz_add_ui (var Dest : mpz_t; protected var
Src1 : mpz_t; Src2 : MedCard); asmname '__gmpz_add_ui';
procedure mpz_sub (var Dest : mpz_t; protected var
Src1, Src2 : mpz_t); asmname '__gmpz_sub';
procedure mpz_sub_ui (var Dest : mpz_t; protected var
Src1 : mpz_t; Src2 : MedCard); asmname '__gmpz_sub_ui';
procedure mpz_mul (var Dest : mpz_t; protected var
Src1, Src2 : mpz_t); asmname '__gmpz_mul';
procedure mpz_mul_ui (var Dest : mpz_t; protected var
Src1 : mpz_t; Src2 : MedCard); asmname '__gmpz_mul_ui';
procedure mpz_mul_2exp (var Dest : mpz_t; protected var
Src1 : mpz_t; Src2 : MedCard); asmname '__gmpz_mul_2exp';
procedure mpz_neg (var Dest : mpz_t; protected var
Src : mpz_t); asmname '__gmpz_neg';
procedure mpz_abs (var Dest : mpz_t; protected var
Src : mpz_t); asmname '__gmpz_abs';
procedure mpz_fac_ui (var Dest : mpz_t; Src : MedCard);
asmname '__gmpz_fac_ui';
procedure mpz_tdiv_q (var Dest : mpz_t; protected var
Src1, Src2 : mpz_t); asmname '__gmpz_tdiv_q';
procedure mpz_tdiv_q_ui (var Dest : mpz_t; protected var
Src1 : mpz_t; Src2 : MedCard); asmname '__gmpz_tdiv_q_ui';
procedure mpz_tdiv_r (var Dest : mpz_t; protected var
Src1, Src2 : mpz_t); asmname '__gmpz_tdiv_r';
procedure mpz_tdiv_r_ui (var Dest : mpz_t; protected var
Src1 : mpz_t; Src2 : MedCard); asmname '__gmpz_tdiv_r_ui';
procedure mpz_tdiv_qr (var DestQ, DestR : mpz_t; protected
var Src1, Src2 : mpz_t); asmname '__gmpz_tdiv_qr';
procedure mpz_tdiv_qr_ui (var DestQ, DestR : mpz_t; protected
var Src1 : mpz_t; Src2 : MedCard); asmname '__gmpz_tdiv_qr_ui';
procedure mpz_fdiv_q (var Dest : mpz_t; protected var
Src1, Src2 : mpz_t); asmname '__gmpz_fdiv_q';
function mpz_fdiv_q_ui (var Dest : mpz_t; protected var
Src1 : mpz_t; Src2 : MedCard) : MedCard;
asmname '__gmpz_fdiv_q_ui';
procedure mpz_fdiv_r (var Dest : mpz_t; protected var
Src1, Src2 : mpz_t); asmname '__gmpz_fdiv_r';
function mpz_fdiv_r_ui (var Dest : mpz_t; protected var
Src1 : mpz_t; Src2 : MedCard) : MedCard;
asmname '__gmpz_fdiv_r_ui';
procedure mpz_fdiv_qr (var DestQ, DestR : mpz_t; protected
var Src1, Src2 : mpz_t); asmname '__gmpz_fdiv_qr';
function mpz_fdiv_qr_ui (var DestQ, DestR : mpz_t; protected
var Src1 : mpz_t; Src2 : MedCard) : MedCard;
asmname '__gmpz_fdiv_qr_ui';
function mpz_fdiv_ui (protected var Src1 : mpz_t; Src2 :
MedCard) : MedCard; asmname '__gmpz_fdiv_ui';
procedure mpz_cdiv_q (var Dest : mpz_t; protected var
Src1, Src2 : mpz_t); asmname '__gmpz_cdiv_q';
function mpz_cdiv_q_ui (var Dest : mpz_t; protected var
Src1 : mpz_t; Src2 : MedCard) : MedCard;
asmname '__gmpz_cdiv_q_ui';
procedure mpz_cdiv_r (var Dest : mpz_t; protected var
Src1, Src2 : mpz_t); asmname '__gmpz_cdiv_r';
function mpz_cdiv_r_ui (var Dest : mpz_t; protected var
Src1 : mpz_t; Src2 : MedCard) : MedCard;
asmname '__gmpz_cdiv_r_ui';
procedure mpz_cdiv_qr (var DestQ, DestR : mpz_t; protected
var Src1,Src2 : mpz_t); asmname '__gmpz_cdiv_qr';
function mpz_cdiv_qr_ui (var DestQ, DestR : mpz_t; protected
var Src1 : mpz_t; Src2 : MedCard) : MedCard;
asmname '__gmpz_cdiv_qr_ui';
function mpz_cdiv_ui (protected var Src1 : mpz_t;
Src2:MedCard) : MedCard; asmname '__gmpz_cdiv_ui';
procedure mpz_mod (var Dest : mpz_t; protected var
Src1,Src2 : mpz_t); asmname '__gmpz_mod';
procedure mpz_divexact (var Dest : mpz_t; protected var
Src1,Src2 : mpz_t); asmname '__gmpz_divexact';
procedure mpz_tdiv_q_2exp (var Dest : mpz_t; protected var
Src1 : mpz_t; Src2 : MedCard); asmname '__gmpz_tdiv_q_2exp';
procedure mpz_tdiv_r_2exp (var Dest : mpz_t; protected var
Src1 : mpz_t; Src2 : MedCard); asmname '__gmpz_tdiv_r_2exp';
procedure mpz_fdiv_q_2exp (var Dest : mpz_t; protected var
Src1 : mpz_t; Src2 : MedCard); asmname '__gmpz_fdiv_q_2exp';
procedure mpz_fdiv_r_2exp (var Dest : mpz_t; protected var
Src1 : mpz_t; Src2 : MedCard); asmname '__gmpz_fdiv_r_2exp';
procedure mpz_powm (var Dest : mpz_t; protected var
Base, Exponent, Modulus : mpz_t); asmname '__gmpz_powm';
procedure mpz_powm_ui (var Dest : mpz_t; protected var
Base : mpz_t; Exponent : MedCard; protected var Modulus : mpz_t);
asmname '__gmpz_powm_ui';
procedure mpz_pow_ui (var Dest : mpz_t; protected var
Base : mpz_t; Exponent : MedCard); asmname '__gmpz_pow_ui';
procedure mpz_ui_pow_ui (var Dest : mpz_t; Base, Exponent :
MedCard); asmname '__gmpz_ui_pow_ui';
procedure mpz_sqrt (var Dest : mpz_t; protected var
Src : mpz_t); asmname '__gmpz_sqrt';
procedure mpz_sqrtrem (var Dest, DestR : mpz_t; protected
var Src : mpz_t); asmname '__gmpz_sqrtrem';
function mpz_perfect_square_p (protected var Src : mpz_t) :
Integer; asmname '__gmpz_perfect_square_p';
function mpz_probab_prime_p (protected var Src : mpz_t;
Repetitions : Integer) : Integer; asmname '__gmpz_probab_prime_p';
procedure mpz_gcd (var Dest : mpz_t; protected var
Src1, Src2 : mpz_t); asmname '__gmpz_gcd';
function mpz_gcd_ui (var Dest : mpz_t; protected var
Src1 : mpz_t; Src2 : MedCard) : MedCard; asmname '__gmpz_gcd_ui';
procedure mpz_gcdext (var Dest, DestA, DestB : mpz_t;
protected var SrcA, SrcB : mpz_t); asmname '__gmpz_gcdext';
function mpz_invert (var Dest : mpz_t; protected var Src,
Modulus : mpz_t) : Integer; asmname '__gmpz_invert';
function mpz_jacobi (protected var Src1, Src2 : mpz_t) :
Integer; asmname '__gmpz_jacobi';
function mpz_legendre (protected var Src1, Src2 : mpz_t) :
Integer; asmname '__gmpz_legendre';
function mpz_cmp (protected var Src1, Src2 : mpz_t) :
Integer; asmname '__gmpz_cmp';
function mpz_cmp_ui (protected var Src1 : mpz_t; Src2 :
MedCard) : Integer; asmname '__gmpz_cmp_ui';
function mpz_cmp_si (protected var Src1 : mpz_t; Src2 :
MedInt) : Integer; asmname '__gmpz_cmp_si';
function mpz_sgn (protected var Src : mpz_t) :
Integer;
procedure mpz_and (var Dest : mpz_t; protected var
Src1, Src2 : mpz_t); asmname '__gmpz_and';
procedure mpz_ior (var Dest : mpz_t; protected var
Src1, Src2 : mpz_t); asmname '__gmpz_ior';
procedure mpz_com (var Dest : mpz_t; protected var
Src : mpz_t); asmname '__gmpz_com';
function mpz_popcount (protected var Src : mpz_t) :
MedCard; asmname '__gmpz_popcount';
function mpz_hamdist (protected var Src1, Src2 : mpz_t) :
MedCard; asmname '__gmpz_hamdist';
function mpz_scan0 (protected var Src : mpz_t;
StartingBit : MedCard) : MedCard; asmname '__gmpz_scan0';
function mpz_scan1 (protected var Src : mpz_t;
StartingBit : MedCard) : MedCard; asmname '__gmpz_scan1';
procedure mpz_setbit (var Dest : mpz_t; BitIndex :
MedCard); asmname '__gmpz_setbit';
procedure mpz_clrbit (var Dest : mpz_t; BitIndex :
MedCard); asmname '__gmpz_clrbit';
procedure mpz_random (var Dest : mpz_t; MaxSize :
mp_size_t); asmname '__gmpz_random';
procedure mpz_random2 (var Dest : mpz_t; MaxSize :
mp_size_t); asmname '__gmpz_random2';
function mpz_sizeinbase (protected var Src : mpz_t; Base :
Integer) : SizeType; asmname '__gmpz_sizeinbase';
{**************** Rational (i.e. Q) routines. ****************}
procedure mpq_canonicalize (var Dest : mpq_t);
asmname '__gmpq_canonicalize';
procedure mpq_init (var Dest : mpq_t);
asmname '__gmpq_init';
procedure mpq_clear (var Dest : mpq_t);
asmname '__gmpq_clear';
procedure mpq_set (var Dest : mpq_t; protected var
Src : mpq_t); asmname '__gmpq_set';
procedure mpq_set_z (var Dest : mpq_t; protected var
Src : mpz_t); asmname '__gmpq_set_z';
procedure mpq_set_ui (var Dest : mpq_t; Nom, Den :
MedCard); asmname '__gmpq_set_ui';
procedure mpq_set_si (var Dest : mpq_t; Nom : MedInt;
Den : MedCard); asmname '__gmpq_set_si';
procedure mpq_add (var Dest : mpq_t; protected var
Src1, Src2 : mpq_t); asmname '__gmpq_add';
procedure mpq_sub (var Dest : mpq_t; protected var
Src1, Src2 : mpq_t); asmname '__gmpq_sub';
procedure mpq_mul (var Dest : mpq_t; protected var
Src1, Src2 : mpq_t); asmname '__gmpq_mul';
procedure mpq_div (var Dest : mpq_t; protected var
Src1, Src2 : mpq_t); asmname '__gmpq_div';
procedure mpq_neg (var Dest : mpq_t; protected var
Src : mpq_t); asmname '__gmpq_neg';
procedure mpq_inv (var Dest : mpq_t; protected var
Src : mpq_t); asmname '__gmpq_inv';
function mpq_cmp (protected var Src1, Src2 : mpq_t) :
Integer; asmname '__gmpq_cmp';
function mpq_cmp_ui (protected var Src1 : mpq_t; Nom2,
Den2 : MedCard) : Integer; asmname '__gmpq_cmp_ui';
function mpq_sgn (protected var Src : mpq_t) :
Integer;
function mpq_equal (protected var Src1, Src2 : mpq_t) :
Integer; asmname '__gmpq_equal';
function mpq_get_d (protected var Src : mpq_t) : Double;
asmname '__gmpq_get_d';
procedure mpq_set_num (var Dest : mpq_t; protected var
Src : mpz_t); asmname '__gmpq_set_num';
procedure mpq_set_den (var Dest : mpq_t; protected var
Src : mpz_t); asmname '__gmpq_set_den';
procedure mpq_get_num (var Dest : mpz_t; protected var
Src : mpq_t); asmname '__gmpq_get_num';
procedure mpq_get_den (var Dest : mpz_t; protected var
Src : mpq_t); asmname '__gmpq_get_den';
{**************** Float (i.e. R) routines. ****************}
procedure mpf_set_default_prec (Precision : MedCard);
asmname '__gmpf_set_default_prec';
procedure mpf_init (var Dest : mpf_t);
asmname '__gmpf_init';
procedure mpf_init2 (var Dest : mpf_t; Precision :
MedCard); asmname '__gmpf_init2';
procedure mpf_clear (var Dest : mpf_t);
asmname '__gmpf_clear';
procedure mpf_set_prec (var Dest : mpf_t; Precision :
MedCard); asmname '__gmpf_set_prec';
function mpf_get_prec (protected var Src : mpf_t) :
MedCard; asmname '__gmpf_get_prec';
procedure mpf_set_prec_raw (var Dest : mpf_t; Precision :
MedCard); asmname '__gmpf_set_prec_raw';
procedure mpf_set (var Dest : mpf_t; protected var
Src : mpf_t); asmname '__gmpf_set';
procedure mpf_set_ui (var Dest : mpf_t; Src : MedCard);
asmname '__gmpf_set_ui';
procedure mpf_set_si (var Dest : mpf_t; Src : MedInt);
asmname '__gmpf_set_si';
procedure mpf_set_d (var Dest : mpf_t; Src : Double);
asmname '__gmpf_set_d';
procedure mpf_set_z (var Dest : mpf_t; protected var
Src : mpz_t); asmname '__gmpf_set_z';
procedure mpf_set_q (var Dest : mpf_t; protected var
Src : mpq_t); asmname '__gmpf_set_q';
function mpf_set_str (var Dest : mpf_t; Src : CString;
Base : Integer) : Integer; asmname '__gmpf_set_str';
procedure mpf_init_set (var Dest : mpf_t; protected var
Src : mpf_t); asmname '__gmpf_init_set';
procedure mpf_init_set_ui (var Dest : mpf_t; Src : MedCard);
asmname '__gmpf_init_set_ui';
procedure mpf_init_set_si (var Dest : mpf_t; Src : MedInt);
asmname '__gmpf_init_set_si';
procedure mpf_init_set_d (var Dest : mpf_t; Src : Double);
asmname '__gmpf_init_set_d';
function mpf_init_set_str (var Dest : mpf_t; Src : CString;
Base : Integer) : Integer; asmname '__gmpf_init_set_str';
function mpf_get_d (protected var Src : mpf_t) : Double;
asmname '__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 : Integer;
NumberOfDigits : SizeType; protected
var Src : mpf_t) : CString; asmname '__gmpf_get_str';
procedure mpf_add (var Dest : mpf_t; protected var
Src1, Src2 : mpf_t); asmname '__gmpf_add';
procedure mpf_add_ui (var Dest : mpf_t; protected var
Src1 : mpf_t; Src2 : MedCard); asmname '__gmpf_add_ui';
procedure mpf_sub (var Dest : mpf_t; protected var
Src1, Src2 : mpf_t); asmname '__gmpf_sub';
procedure mpf_ui_sub (var Dest : mpf_t; Src1 : MedCard;
protected var Src2 : mpf_t); asmname '__gmpf_ui_sub';
procedure mpf_sub_ui (var Dest : mpf_t; protected var
Src1 : mpf_t; Src2 : MedCard); asmname '__gmpf_sub_ui';
procedure mpf_mul (var Dest : mpf_t; protected var
Src1, Src2 : mpf_t); asmname '__gmpf_mul';
procedure mpf_mul_ui (var Dest : mpf_t; protected var
Src1 : mpf_t; Src2 : MedCard); asmname '__gmpf_mul_ui';
procedure mpf_div (var Dest : mpf_t; protected var
Src1, Src2 : mpf_t); asmname '__gmpf_div';
procedure mpf_ui_div (var Dest : mpf_t; Src1 : MedCard;
protected var Src2 : mpf_t); asmname '__gmpf_ui_div';
procedure mpf_div_ui (var Dest : mpf_t; protected var
Src1 : mpf_t; Src2 : MedCard); asmname '__gmpf_div_ui';
procedure mpf_sqrt (var Dest : mpf_t; protected var
Src : mpf_t); asmname '__gmpf_sqrt';
procedure mpf_sqrt_ui (var Dest : mpf_t; Src : MedCard);
asmname '__gmpf_sqrt_ui';
procedure mpf_neg (var Dest : mpf_t; protected var
Src : mpf_t); asmname '__gmpf_neg';
procedure mpf_abs (var Dest : mpf_t; protected var
Src : mpf_t); asmname '__gmpf_abs';
procedure mpf_mul_2exp (var Dest : mpf_t; protected var
Src1 : mpf_t; Src2 : MedCard); asmname '__gmpf_mul_2exp';
procedure mpf_div_2exp (var Dest : mpf_t; protected var
Src1 : mpf_t; Src2 : MedCard); asmname '__gmpf_div_2exp';
function mpf_cmp (protected var Src1, Src2 : mpf_t) :
Integer; asmname '__gmpf_cmp';
function mpf_cmp_si (protected var Src1 : mpf_t; Src2 :
MedInt) : Integer;
function mpf_cmp_ui (protected var Src1 : mpf_t; Src2 :
MedCard) : Integer;
function mpf_eq (protected var Src1, Src2 : mpf_t;
NumberOfBits : MedCard) : Integer; asmname '__gmpf_eq';
procedure mpf_reldiff (var Dest : mpf_t; protected var
Src1, Src2 : mpf_t); asmname '__gmpf_reldiff';
function mpf_sgn (protected var Src : mpf_t) :
Integer;
procedure mpf_random2 (var Dest : mpf_t; MaxSize :
mp_size_t; MaxExp : mp_exp_t); asmname '__gmpf_random2';
{$if 0} (*@@ commented out because they use C file pointers *)
function mpz_inp_str (var Dest : mpz_t; Src : CFilePtr;
Base : Integer) : SizeType; asmname '__gmpz_inp_str';
function mpz_inp_raw (var Dest : mpz_t; Src : CFilePtr) :
SizeType ; asmname '__gmpz_inp_raw';
function mpz_out_str (Dest : CFilePtr; Base : Integer;
protected var Src : mpz_t) : SizeType; asmname '__gmpz_out_str';
function mpz_out_raw (Dest : CFilePtr; protected var Src :
mpz_t) : SizeType ; asmname '__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 : Integer;
NumberOfDigits : SizeType; protected var Src : mpf_t) : SizeType;
asmname '__gmpf_out_str';
function mpf_inp_str (var Dest : mpf_t; Src : CFilePtr;
Base : Integer) : SizeType; asmname '__gmpf_inp_str';
{$endif}
{ New declarations in GMP 3.x. @@ Mostly untested! }
{$ifdef HAVE_GMP3}
{ 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; ...); asmname '__gmp_randinit';
procedure gmp_randinit_lc (var State : gmp_randstate_t; A :
mpz_t; C : MedCard; M : mpz_t); asmname '__gmp_randinit_lc';
procedure gmp_randinit_lc_2exp (var State : gmp_randstate_t; A :
mpz_t; C : MedCard; M2Exp : MedCard);
asmname '__gmp_randinit_lc_2exp';
procedure gmp_randseed (var State : gmp_randstate_t; Seed :
mpz_t); asmname '__gmp_randseed';
procedure gmp_randseed_ui (var State : gmp_randstate_t; Seed :
MedCard); asmname '__gmp_randseed_ui';
procedure gmp_randclear (var State : gmp_randstate_t);
asmname '__gmp_randclear';
procedure mpz_addmul_ui (var Dest : mpz_t; protected var
Src1 : mpz_t; Src2 : MedCard); asmname '__gmpz_addmul_ui';
procedure mpz_bin_ui (var Dest : mpz_t; protected var
Src1 : mpz_t; Src2 : MedCard); asmname '__gmpz_bin_ui';
procedure mpz_bin_uiui (var Dest : mpz_t; Src1, Src2 :
MedCard); asmname '__gmpz_bin_uiui';
function mpz_cmpabs (protected var Src1, Src2 : mpz_t) :
Integer; asmname '__gmpz_cmpabs';
function mpz_cmpabs_ui (protected var Src1 : mpz_t; Src2 :
MedCard) : Integer; asmname '__gmpz_cmpabs_ui';
procedure mpz_dump (protected var Src : mpz_t);
asmname '__gmpz_dump';
procedure mpz_fib_ui (var Dest : mpz_t; Src : MedCard);
asmname '__gmpz_fib_ui';
function mpz_fits_sint_p (protected var Src : mpz_t) :
Integer; asmname '__gmpz_fits_sint_p';
function mpz_fits_slong_p (protected var Src : mpz_t) :
Integer; asmname '__gmpz_fits_slong_p';
function mpz_fits_sshort_p (protected var Src : mpz_t) :
Integer; asmname '__gmpz_fits_sshort_p';
function mpz_fits_uint_p (protected var Src : mpz_t) :
Integer; asmname '__gmpz_fits_uint_p';
function mpz_fits_ulong_p (protected var Src : mpz_t) :
Integer; asmname '__gmpz_fits_ulong_p';
function mpz_fits_ushort_p (protected var Src : mpz_t) :
Integer; asmname '__gmpz_fits_ushort_p';
procedure mpz_lcm (var Dest : mpz_t; protected var
Src1, Src2 : mpz_t); asmname '__gmpz_lcm';
procedure mpz_nextprime (var Dest : mpz_t; protected var
Src : mpz_t); asmname '__gmpz_nextprime';
function mpz_perfect_power_p (protected var Src : mpz_t) :
Integer; asmname '__gmpz_perfect_power_p';
function mpz_remove (var Dest : mpz_t; protected var
Src1, Src2 : mpz_t) : MedCard; asmname '__gmpz_remove';
function mpz_root (var Dest : mpz_t; protected var
Src : mpz_t; N : MedCard) : Integer; asmname '__gmpz_root';
procedure mpz_rrandomb (var ROP : mpz_t; var State :
gmp_randstate_t; N : MedCard); asmname '__gmpz_rrandomb';
procedure mpz_swap (var v1, v2 : mpz_t);
asmname '__gmpz_swap';
function mpz_tdiv_ui (protected var Src1 : mpz_t; Src2 :
MedCard) : MedCard; asmname '__gmpz_tdiv_ui';
function mpz_tstbit (protected var Src1 : mpz_t; Src2 :
MedCard) : Integer; asmname '__gmpz_tstbit';
procedure mpz_urandomb (ROP : mpz_t; var State :
gmp_randstate_t; N : MedCard); asmname '__gmpz_urandomb';
procedure mpz_urandomm (ROP : mpz_t; var State :
gmp_randstate_t; N : mpz_t); asmname '__gmpz_urandomm';
procedure mpz_xor (var Dest : mpz_t; protected var
Src1, Src2 : mpz_t); asmname '__gmpz_xor';
procedure mpq_set_d (var Dest : mpq_t; Src : Double);
asmname '__gmpq_set_d';
procedure mpf_ceil (var Dest : mpf_t; protected var
Src : mpf_t); asmname '__gmpf_ceil';
procedure mpf_floor (var Dest : mpf_t; protected var
Src : mpf_t); asmname '__gmpf_floor';
procedure mpf_pow_ui (var Dest : mpf_t; protected var
Src1 : mpf_t; Src2 : MedCard); asmname '__gmpf_pow_ui';
procedure mpf_trunc (var Dest : mpf_t; protected var
Src : mpf_t); asmname '__gmpf_trunc';
procedure mpf_urandomb (ROP : mpf_t; var State :
gmp_randstate_t; N : MedCard); asmname '__gmpf_urandomb';
const
GMPErrorNone = 0;
GMPErrorUnsupportedArgument = 1;
GMPErrorDivisionByZero = 2;
GMPErrorSqrtOfNegative = 4;
GMPErrorInvalidArgument = 8;
GMPErrorAllocate = 16;
var
gmp_errno : Integer; asmname '__gmp_errno'; external;
{$endif}
{ 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_arctan (var c : mpf_t; protected var x : mpf_t);
procedure mpf_pi (var c : mpf_t);
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-2001 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__ < 20000412}
{$error This unit requires GPC release 20000412 or newer.}
{$endif}
unit GPCUtil;
interface
uses GPC;
{ Replace all occurences of OldC with NewC in s and return the
result }
function ReplaceChar (const s : String; OldC, NewC : Char) :
TString;
{ Return the current working directory }
function ThisDirectory : TString;
asmname '_p_get_current_directory';
{ Does a directory exist? }
function IsDirectory (const aFileName : String) : Boolean;
asmname '_p_directory_exists';
{ Break a string into 2 parts, using Ch as a marker }
function BreakStr (const Src : String; var Dest1, Dest2 : String;
Ch : Char) : Boolean;
{ Convert a CString to an Integer }
function PChar2Int (s : CString) : Integer;
{ Convert a CString to a LongInt }
function PChar2Long (s : CString) : LongInt;
{ Convert a CString to a Double }
function PChar2Double (s : CString) : 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;
{ 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) : LongInt;
{ 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;
{ 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) :
Boolean;
{ Does file name s exist? }
function ExistFile (const aFileName : String) : Boolean;
asmname '_p_file_exists';
{ Return just the directory path of Path. Returns DirSelf +
DirSeparator if Path contains no directory. }
function JustPathName (const Path : String) : TString;
asmname '_p_dir_from_path';
{ Return just the file name part without extension of Path. Empty if
Path contains no file name. }
function JustFileName (const Path : String) : TString;
asmname '_p_name_from_path';
{ Return just the extension of Path. Empty if Path contains no
extension. }
function JustExtension (const Path : String) : TString;
asmname '_p_ext_from_path';
{ Change the extension of s to Ext (do not include the dot!) }
function ForceExtension (const s, Ext : String) : TString;
{ Return the full pathname of Path }
function FullPathName (const Path : String) : TString;
asmname '_p_fexpand';
{ Add a DirSeparator to the end of s if there is not already one }
function AddBackSlash (const s : String) : TString;
asmname '_p_forceadddirseparator';
{ Convert Integer to PChar; uses CStringNew 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) : TString;
{ Convert string to Integer }
function Str2Int (const s : String; var i : Integer) : Boolean;
{ Convert string to LongInt }
function Str2Long (const s : String; var i : LongInt) : Boolean;
{ Convert string to Double }
function Str2Real (const s : String; var i : Double) : Boolean;
{ Return a string stripped of leading spaces }
function TrimLead (const s : String) : TString;
asmname '_p_trimleft_str';
{ Return a string stripped of trailing spaces }
function TrimTrail (const s : String) : TString;
asmname '_p_trimright_str';
{ Return a string stripped of leading and trailing spaces }
function Trim (const s : String) : TString;
asmname '_p_trimboth_str';
{ Return a string right-padded to length Len with ch }
function PadCh (const s : String; ch : Char; Len : Integer) :
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) :
TString;
{ Return a string left-padded to length Len with blanks }
function LeftPad (const s : String; Len : Integer) : TString;
{ Convert a string to lowercase }
function StLoCase (const s : String) : TString;
asmname '_p_locase_str';
{ Convert a string to uppercase }
function StUpCase (const s : String) : TString;
asmname '_p_upcase_str';
{ 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 backdraw is
that
this memory cannot be used freely, but only with the following
moving
routines. }
type
PBigMem = ^TBigMem;
TBigMem (MaxNumber : Integer) = record
{ Public fields }
Number, BlockSize : SizeType;
Mappable : Boolean;
{ Private fields }
Pointers : array [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) : 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;
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. This is meant as a debugging help
for avoiding 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 prints a message to StdErr. 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-2001 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-}
unit HeapMon;
interface
uses GPC;
{ This unit has an empty interface. It is automatically activated
when used. }
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.
IMPORTANT NOTE: This unit is distributed under the GNU GPL, NOT
under the GNU LGPL under which most of the other GPC units are
distributed. This means that you must distribute any code that
uses this unit under the GPL as well, which means that you have to
make the source code available whenever you distribute a binary of
the code, and that you must allow recipients to modify the code
and redistribute it under the GPL.
Copyright (C) 1995, 1996, 2000-2001 Free Software Foundation, Inc.
Based on the C code written by Ulrich Drepper
<drepper@gnu.ai.mit.edu>, 1995 as part of the GNU C Library.
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.
}
{$gnu-pascal,I-}
{$if __GPC_RELEASE__ < 20000412}
{$error This unit requires GPC release 20000412 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 (8);
TMD5 = array [1 .. 16] of Card8;
{ Computes MD5 message digest for Length bytes in Buffer. }
procedure MD5Buffer (const Buffer; Length : SizeType; var MD5 :
TMD5); asmname '_p_md5_buffer';
{ Computes MD5 message digest for the contents of the file f. }
(*@@iocritical*)procedure MD5File (var f : File; var MD5 : TMD5);
asmname '_p_md5_file';
{ Initializes a MD5 value with zeros. }
procedure MD5Clear (var MD5 : TMD5); asmname '_p_md5_clear';
{ Compares two MD5 values for equality. }
function MD5Compare (const Value1, Value2 : TMD5) : Boolean;
asmname '_p_md5_compare';
{ Converts an MD5 value to a string. }
function MD5Str ((*@@fjf382 const*) MD5 : TMD5) = s : TString;
asmname '_p_md5_str';
{ Converts a string to an MD5 value. Returns True if successful. }
function MD5Val (const s : String; var MD5 : TMD5) : Boolean;
asmname '_p_md5_val';
{ Composes two MD5 values to a single one. }
function MD5Compose (const Value1, Value2 : TMD5) = Dest : TMD5;
asmname '_p_md5_compose';
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-2001 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-}
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;
The following listing contains the interface of the Pipe 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 and process signaling
Copyright (C) 1998-2001 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__ < 20000412}
{$error This unit requires GPC release 20000412 or newer.}
{$endif}
{ Keep this consistent with the one in pipec.c }
{$if defined (MSDOS) or defined (__MINGW32__)}
{$define NOFORK}
{$endif}
unit Pipe;
interface
uses GPC;
(*$local W-*)type PPStrings = ^TPStrings;TPStrings (Count: Cardinal)
= array [1 .. Count] of ^String; (*@@two unit bug with definition
in gpc.pas in programs using these two units*) (*$endlocal*)
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;
const
EFork = 600; { cannot fork `%s'' }
ESpawn = 601; { cannot spawn `%s'' }
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.
}
(*@@IO critical*) procedure Pipe (var ToInputFile, FromOutputFile,
FromStdErrFile : AnyFile; (*@@fjf265 const*) ProcessName : String;
protected var Parameters : TPStrings; ProcessEnvironment :
PCStrings; var Process : PPipeProcess; ChildProc : TProcedure);
{
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;
The following listing contains the interface of the Ports unit.
This unit provides access routines for the hardware ports on the x86, 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 x86, 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 x86 platform. This unit
is *not* portable. It works only on x86 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-2001 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-}
{$ifndef __i386__}
{$error The Ports unit is only for the x86 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. }
function IOPerm (From, Num : MedCard; On : Integer) : Integer;
asmname 'ioperm';
function IOPL (Level : Integer) : Integer; asmname 'iopl';
function SetEUID (EUID : Integer) : Integer; asmname 'seteuid';
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-2001 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__ < 20000412}
{$error This unit requires GPC release 20000412 or newer.}
{$endif}
unit Printer;
interface
{$ifdef __OS_DOS__}
{ Dos-like systems: writing to a printer device }
uses GPC;
var
{ The file name to write printer output into }
PrinterDeviceName : ^String = @'prn';
{$else}
{ Unix-like systems: printing via a printer program }
uses GPC, Pipe;
const
EPrinterRead = 610; { printer can only be opened for writing }
var
{ 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 : ^String = @'lpr';
{ Optional command line parameters for the printer program.
Ignored when nil. }
PrinterArguments : ^TPStrings = nil;
{ How to deal with the printer spooler after the printer pipe is
closed, cf. the Pipe unit. }
PrinterPipeSignal : Integer = 0;
PrinterPipeSeconds : Integer = 0;
PrinterPipeWait : Boolean = True;
{$endif}
{ 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);
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 ftp://agnes.dida.physik.uni-essen.de/gnu-pascal/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 ftp://agnes.dida.physik.uni-essen.de/gnu-pascal/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-2001 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__ < 20000412}
{$error This unit requires GPC release 20000412 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 : Integer; { Internal }
SubExpressions : Integer;
Error : PString
end;
{ Simple interface to regular expression mathing. 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) :
Integer; asmname '_p_regexposfrom';
{ 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 mathing 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);
asmname '_p_newregex';
{ 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);
asmname '_p_dispose_regex';
{ Matches a regular expression created with `NewRegEx' against a
string. }
function MatchRegEx (var RegEx : RegExType; const s : String;
NotBeginningOfLine, NotEndOfLine : Boolean) : Boolean;
asmname '_p_matchregex';
{ 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; asmname '_p_matchregexfrom';
{ 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 MatchPosition for 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);
asmname '_p_getmatch_regex';
{ 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;
asmname '_p_find_subexpressionreferences_regex';
{ 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) : TString;
asmname '_p_replace_subexpressionreferences_regex';
{ 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) : TString;
asmname '_p_CharSet2RegEx';
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, section Pascal declarations for GPC's 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-2001 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-}
unit Strings;
interface
uses GPC;
function StrLen (Src : CString) : SizeType;
asmname '_p_strlen';
function StrEnd (Src : CString) : CString; asmname '_p_strend';
function StrMove (Dest, Source : CString; Count : SizeType) :
CString; asmname '_p_strmove';
function StrCopy (Dest, Source : CString) : CString;
asmname '_p_strcpy';
function StrECopy (Dest, Source : CString) : CString;
asmname '_p_strecpy';
function StrLCopy (Dest, Source : CString; MaxLen : SizeType) :
CString; asmname '_p_strlcpy';
function StrPCopy (Dest : CString; const Source : String) :
CString; asmname '_p_cstringcopystring';
function StrCat (Dest, Source : CString) : CString;
asmname '_p_strcat';
function StrLCat (Dest, Source : CString; MaxLen : SizeType) :
CString; asmname '_p_strlcat';
function StrComp (s1, s2 : CString) : Integer;
asmname '_p_strcmp';
function StrIComp (s1, s2 : CString) : Integer;
asmname '_p_strcasecmp';
function StrLComp (s1, s2 : CString; MaxLen : SizeType) :
Integer; asmname '_p_strlcmp';
function StrLIComp (s1, s2 : CString; MaxLen : SizeType) :
Integer; asmname '_p_strlcasecmp';
function StrScan (Src : CString; Ch : Char) : CString;
asmname '_p_strscan';
function StrRScan (Src : CString; Ch : Char) : CString;
asmname '_p_strrscan';
function StrPos (aString, SubString : CString) : CString;
asmname '_p_strpos';
function StrRPos (aString, SubString : CString) : CString;
asmname '_p_strrpos';
function StrUpper (s : CString) : CString; asmname '_p_strupper';
function StrLower (s : CString) : CString; asmname '_p_strlower';
function StrPas (aString : CString) : TString;
asmname '_p_strpas';
function StrEmpty (s : CString) : Boolean; asmname '_p_strempty';
function StrNew (Src : CString) : CString; asmname '_p_strdup';
procedure StrDispose (s : CString); asmname '_p_dispose';
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-2001 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__ < 20000814}
{$error This unit requires GPC release 20000814 or newer.}
{$endif}
unit StringUtils;
interface
uses GPC;
{ 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) : 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;
{ 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 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,
RFC 1521, section 5.1) and being able to read them back losslessly
(with UnQuoteString). }
function QuoteString (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;
{ Decode a quoted-printable string (not enclosed in `"', unlike for
UnQuoteString). Returns True if successful and False if the string
has an invalid form. }
function UnQPString (var s : String) : Boolean;
{ 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;
{ 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) : TString;
{ 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;
{ 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;
{ 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;
{ Check that a certain string is contained in s (after possible
space characters). }
function StrReadConst (const s : String; var i : Integer; const
Expected : String) : Boolean;
{ A simpler to use version of StrReadConst that expects a `,'. }
function StrReadComma (const s : String; var i : Integer) :
Boolean;
{ Read an integer number from a string. }
function StrReadInt (const s : String; var i : Integer; var Dest :
Integer) : Boolean;
{ Read a real number from a string. }
function StrReadReal (const s : String; var i : Integer; var Dest :
Real) : Boolean;
{ 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;
{ 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; var IDs : array of PString) : Boolean;
{ 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) : 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 DisposeStrHashTable (HashTable : PStrHashTable);
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 compatible System unit for GPC
This unit is released as part of the GNU Pascal project. It
implements some rather exotic BP compatibility features. Even many
BP programs don't need them, but they're here for maximum
compatibility. Most of BP's System unit's features are built into
the compiler or the RTS.
The unit depends on the conditional defines `__BP_TYPE_SIZES__',
`__BP_RANDOM__' and `__BP_PARAMSTR_0__'.
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.
Copyright (C) 1998-2001 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__ < 20000412}
{$error This unit requires GPC release 20000412 or newer.}
{$endif}
unit System;
interface
uses GPC;
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 (32) = 0;
{$endif}
type
OrigInt = Integer;
OrigWord = Word;
{ needed in the Dos unit }
Int7 = Integer (7);
Word16 = Word (16);
Word32 = Word (32);
{ Delphi }
SmallInt = Integer (16);
DWord = Cardinal (32);
{ Short BP compatible type sizes if wanted }
{$ifdef __BP_TYPE_SIZES__}
ByteBool = Boolean (8);
WordBool = Boolean (16);
LongBool = Boolean (32);
Boolean = ByteBool; { important in packed records and arrays
}
ShortInt = Integer (8);
Byte = Cardinal (8);
Word = Cardinal (16);
LongInt = Integer (32);
Comp = Integer (64);
LongWord = Cardinal (32); { Delphi }
Integer = Integer (16);
{$endif}
(*@@ doesn't work well (dialec3.pas) -- when GPC gets short
strings, it will be unnecessary
{$ifdef __BORLAND_PASCAL__}
String = String [255];
{$endif} *)
const
MaxInt = High (Integer);
MaxLongInt = High (LongInt);
{ Return the lowest-order byte of x }
function Lo (x : LongestInt) : Byte;
{ Return the lowest-but-one-order byte of x }
function Hi (x : LongestInt) : Byte;
{ Swap the lowest- and lowest-but-one-order bytes, mask out the
higher ones }
function Swap (x : LongestInt) : Word;
{ 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 : Word = $1000;
Seg0040 : Word = $40;
SegA000 : Word = $a000;
SegB000 : Word = $b000;
SegB800 : Word = $b800;
Test8086 : Byte = 2;
Test8087 : Byte = 3; { floating-point arithmetic is emulated
transparently by the OS if not present
in hardware }
OvrCodeList : Word = 0;
OvrHeapSize : Word = 0;
OvrDebugPtr : Pointer = nil;
OvrHeapOrg : Word = 0;
OvrHeapPtr : Word = 0;
OvrHeapEnd : Word = 0;
OvrLoadList : Word = 0;
OvrDosHandle : Word = 0;
OvrEmsHandle : Word = $ffff;
HeapOrg : Pointer absolute HeapBegin;
HeapPtr : Pointer absolute HeapHigh;
HeapEnd : Pointer = Pointer (High (PtrCard));
FreeList : Pointer = nil;
FreeZero : Pointer = nil;
StackLimit : Word = 0;
HeapList : Word = 0;
HeapLimit : Word = 1024;
HeapBlock : Word = 8192;
HeapAllocFlags : Word = 2;
CmdShow : Integer = 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
BPReal = record
Format : array [1 .. 6] of Cardinal (8)
end;
function RealToBPReal (R : Real) : BPReal;
function BPRealToReal (const BR : BPReal) : Real;
{ Heap management stuff }
const
{ Possible return values 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 return value
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 : Word) : Integer = 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 : Word) : Integer;
{ 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;
function AllocMemCount : Integer;
function AllocMemSize : SizeType;
procedure Assert (Condition : Boolean);
procedure DefaultAssertErrorProc (const Message, FileName: String;
LineNumber: Integer; ErrorAddr: Pointer);
var
AssertErrorProc: ^procedure (const Message, FileName: String;
LineNumber: Integer; ErrorAddr: Pointer) =
@DefaultAssertErrorProc;
NoErrMsg: Boolean = False;
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 errors will not be trapped.
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-2001 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-}
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));
asmname '_p_trapexec';
{ Forget about saved errors from the innermost TrapExec instance. }
procedure TrapReset; asmname '_p_trapreset';
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-2001 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__ < 20000412}
{$error This unit requires GPC release 20000412 or newer.}
{$endif}
unit Turbo3;
interface
uses GPC, System, CRT;
var
Kbd : Text;
CBreak : Boolean absolute CheckBreak;
procedure AssignKbd (var F : (*AnyFile*)Text);
function (*@@fjf260*)MemAvail3 : Integer;
function (*@@fjf260*)MaxAvail3 : Integer;
function LongFileSize (var F : AnyFile) : Real;
function LongFilePos (var F : AnyFile) : Real;
procedure LongSeek (var F : AnyFile; aPosition : Real);
procedure (*@@fjf260*)LowVideo3;
procedure (*@@fjf260*)HighVideo3;
The following listing contains the interface of the WinDos unit.
This is a portable implementation of most routines from BP's `WinDos' unit. A few routines that are Dos -- or even x86 real mode -- specific, are only available if `__BP_UNPORTABLE_ROUTINES__' is defined, section BP Incompatibilities.
The same functionality and much more is available in the Run Time System, section Pascal declarations for GPC's Run Time System. The RTS routines usually have different names and/or easier and less limiting interfaces (e.g. `ReadDir' etc. vs. `FindFirst' etc.), and are often more efficient.
Therefore, using this unit is not recommended in newly written programs.
{
Mostly BP compatible portable WinDos unit
This unit supports most, but not all, of the routines and
declarations of BP's WinDos unit.
NOTES:
- The procedures GetIntVec and SetIntVec are not supported since
they make only sense for Dos real-mode programs (and GPC compiled
programs do not run in real-mode, even on x86 under Dos). The
procedures Intr and MsDos are only supported under DJGPP if
`__BP_UNPORTABLE_ROUTINES__' is defined (with the
`-D__BP_UNPORTABLE_ROUTINES__' option). A few other routines are
also only supported with this define, but on all platforms (but
they are crude hacks, that's why they are not supported without
this define).
- The internal structure of file variables (TFileRec and TTextRec)
is different in GPC. However, as far as TFDDs are concerned, there
are other ways to achieve the same in GPC, see the GPC unit.
Copyright (C) 1998-2001 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-}
unit WinDos;
interface
uses GPC, System, Dos;
const
{ File attribute constants }
faReadOnly = ReadOnly;
faHidden = Hidden; { set for dot files except `.' and `..' }
faSysFile = SysFile; { not supported }
faVolumeID = VolumeID; { not supported }
faDirectory = Directory;
faArchive = Archive; { means: not executable }
faAnyFile = AnyFile;
{ Maximum file name component string lengths }
fsPathName = 79;
fsDirectory = 67;
fsFileName = 8;
fsExtension = 4;
{ FileSplit return flags }
fcExtension = 1;
fcFileName = 2;
fcDirectory = 4;
fcWildcards = 8;
{ Flag bit masks -- only used by the unportable Dos routines }
FCarry = 1;
FParity = 4;
FAuxiliary = $10;
FZero = $40;
FSign = $80;
FOverflow = $800;
type
PTextBuf = ^TTextBuf;
TTextBuf = TextBuf;
{ Search record used by FindFirst and FindNext }
TSearchRec = {$ifdef __BP_TYPE_SIZES__} packed {$endif} record
Fill : SearchRecFill;
Attr : Byte8;
Time, Size : LongInt;
Name : {$ifdef __BP_TYPE_SIZES__}
packed array [0 .. 12] of Char
{$else}
TStringBuf
{$endif};
Reserved : SearchRec
end;
{ Date and time record used by PackTime and UnpackTime }
TDateTime = DateTime;
{ 8086 CPU registers -- only used by the unportable Dos routines }
TRegisters = Registers;
var
{ Error status variable }
DosError : Integer; external;
procedure GetDate (var Year, Month, Day, DayOfWeek : Word);
asmname '_p_getdate';
procedure GetTime (var Hour, Minute, Second, Sec100 : Word);
asmname '_p_gettime';
procedure (*@@fjf260*)WGetCBreak (var BreakOn : Boolean);
asmname '_p_getcbreak';
procedure (*@@fjf260*)WSetCBreak (BreakOn : Boolean);
asmname '_p_setcbreak';
procedure (*@@fjf260*)WGetVerify (var VerifyOn : Boolean);
asmname '_p_getverify';
procedure (*@@fjf260*)WSetVerify (VerifyOn : Boolean);
asmname '_p_setverify';
function DiskFree (Drive : Byte) : LongInt; asmname '_p_diskfree';
function DiskSize (Drive : Byte) : LongInt; asmname '_p_disksize';
procedure GetFAttr (var F (*@@anyfile : GPC_AnyFile*); var Attr :
TDosAttr); asmname '_p_getfattr';
procedure SetFAttr (var F (*@@anyfile : GPC_AnyFile*); Attr :
TDosAttr); asmname '_p_setfattr';
procedure GetFTime (var F (*@@anyfile : GPC_AnyFile*); var aTime :
LongInt); asmname '_p_getftime';
procedure SetFTime (var F (*@@anyfile : GPC_AnyFile*); aTime :
LongInt); asmname '_p_setftime';
{ 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 (*@@fjf260*)WFindFirst (Path : PChar; Attr : Word; var
SR : TSearchRec);
procedure (*@@fjf260*)WFindNext (var SR : TSearchRec);
procedure (*@@fjf260*)WFindClose (var SR : TSearchRec);
procedure UnpackTime (P : LongInt; var T : TDateTime);
asmname '_p_unpacktime';
procedure PackTime (const T : TDateTime; var P : LongInt);
asmname '_p_packtime';
function FileSearch (Dest, Name, List : PChar) : PChar;
function FileExpand (Dest, Name : PChar) : PChar;
function FileSplit (Path, Dir, Name, Ext : PChar) : Word;
function GetCurDir (Dir : PChar; Drive : Byte) : PChar;
procedure SetCurDir (Dir : PChar);
procedure CreateDir (Dir : PChar);
procedure RemoveDir (Dir : PChar);
function GetArgCount : Integer;
function GetArgStr (Dest : PChar; ArgIndex : Integer; MaxLen :
Word) : PChar;
function GetEnvVar (VarName : PChar) : PChar;
asmname '_p_cstringgetenv';
{$ifdef __BP_UNPORTABLE_ROUTINES__}
{$ifdef DJGPP}
procedure (*@@fjf260*)WIntr (IntNo : Byte; var Regs : Registers);
asmname '_p_intr';
procedure (*@@fjf260*)WMsDos (var Regs : Registers);
asmname '_p_msdos';
{$endif}
function (*@@fjf260*)WDosVersion : Word; asmname '_p_dosversion';
procedure (*@@fjf260*)WSetDate (Year, Month, Day : Word);
asmname '_p_setdate';
procedure (*@@fjf260*)WSetTime (Hour, Minute, Second, Sec100 :
Word); asmname '_p_settime';
{$endif}
Go to the first, previous, next, last section, table of contents.