Irie Pascal for OS/2
(Beta 2B Release)
Now Available!



Stuart King releases Irie Pascal for OS/2 Warp Beta 2B and uploads the file (IPB2B0S2.ZIP, 196Kb) on Pete Norloff's BBS. The main purpose of Irie Pascal is to provide an excellent multi-platform tool for people who either want to learn Pascal or who want to write small to medium sized scripts and utility programs.

Jump Norloff's>@@@


Irie Pascal as a result the following are emphasized: 1) Simplicity and ease of use; 2) Good diagnostics (both compile time and run-time); 3) Generating correct code; 4) Very strong support for Standard Pascal; 5) Support for many extensions to Standard Pascal, particularly in the areas of file and string processing; 6) Support for multi-platform programming (i.e. you should be able to compile your programs once and run them on any supported platform); 7) Moderate price. The Software consists of two programs, the Compiler and the Interpreter. The Compiler is not a native code compiler (i.e. it does not generate
instructions for a real computer), instead it generates instructions (also called byte codes) for an imaginary computer (called the "Irie Virtual Machine"). These byte codes can not be directly executed by any existing computer, but instead must be executed by the Interpreter.


Installation

---------------------------
Minimum system requirements
---------------------------
- 1 MB hard disk space

-------------------------
Installation the Software
-------------------------
Irie Pascal for OS/2 is distributed as a zip file "ipb2bos2.zip".

----------------------------
Installing from the zip file
----------------------------
If you have the zip file the recommended installation procedure is
as follows:
A) Create a directory (I suggest "C:\IRIE") to store Irie Pascal.
B) Copy the zip file into this directory.
C) Use your unzip utility to extract the files.
D) Add the directory created in A) to the path
(i.e. edit your "config.sys").
E) Create a directory to store the sample pascal programs
(I suggest "C:\IRIE\SAMPLES").
F) Copy the zip file containing the samples "samples.zip" in to the
directory you just created.
G) Unzip the sample files.
H) Reboot your computer.

-------------------------------------------
Installing from the self-extracting archive
-------------------------------------------
Irie Pascal for OS/2 is not available as a self-extracting archive at
this time.

--------------------------------
2.3 Uninstalling the Software
--------------------------------
Irie Pascal does not make any behind the scenes modifications to your
system. Irie Pascal does not modify any system files, or install files
on you hard disk so uninstalling is very simple. Just delete the
directory, you created to store Irie Pascal, and remove it from the path.

Please make sure that you have the following files:

Documentation:
--------------
readme.txt -
install.txt - The Irie Pascal Installation Guide
user.txt - Irie Pascal Users Guide

Programs:
---------
ipc.exe - Irie Pascal Compiler for OS/2
ivm.exe - Irie Virtual Machine Interpreter for OS/2

Sample programs:
----------------
add.pas - A simple program that computes and displays the sum
of the command-line arguments passed to it.
append.pas - Appends two files together, writting the appended files
out to a third file.
args.pas - Displays the number of command-line arguments passed to it.
ascii.pas - This program displays the ASCII table.
bad.pas - This program is referred to in the Users Guide to
illustrate how the Compiler handles error messages.
batch.pas - A very primitive command processor.
calc.pas - A desktop calculator.
date.pas - Displays the system date and day.
dirpas.pas - A simple program which lists all the *.pas files in
the current directory.
hello.pas - The classic hello world program.
imake.pas - A simple makefile utility that processes a make language
that I designed to be more readable than the standard
make language. See the included 'imake' file for
the makefile I use to generate Irie Pascal. Note: this
make utility does not do dependency checking.
lowname.pas - Converts a file's name to lowercase
notstric.pas - A simple program that illustrates the dangers of
turning strict checking off.
primes.pas - A simple prime number generating program. I used this
program to help me get an idea of how much slower
Irie Pascal programs are than native code programs.
prime2.pas - Another simple prime number generating program. The
interesting thing about this program is that it uses
the built-in 'list' type.
rename.pas - Renames a file
strange.pas - A non-sensical program referred to in the Users Guide
to illustrate how program parameters are handled.
type.pas - A simple program which behaves like the 'type' command
(i.e. it echoes a file to the screen).
type2.pas - A simple program which behaves like the 'type' command
(i.e. it echoes a file to the screen).
vowels.pas - A simple vowel counting program which illustrates one
method of handling program arguments using Irie Pascal.

The sample programs are provided mostly to help you veryify that
Irie Pascal has been installed correctly. You may however find a few of
the sample programs like calc.pas and ascii.pas useful.

Users Guide

This is the Irie Pascal for OS/2 Users Guide.
In this guide "Software", "Compiler", and "Interpreter"
mean the following:
"Software" means "Irie Pascal for OS/2",
"Compiler" means "Irie Pascal Compiler for OS/2", and
"Interpreter" means "Irie Virtual Machine Interpreter for OS/2".

-----------------
Table Of Contents
-----------------
Preface
Purpose
1.0 Introduction
1.1 The Software
1.2 Disclaimer - Agreement
1.3 Compliance statement
1.4 Product support
1.5 Contacting the author
2.0 Installation
2.1 Minimum system requirements
2.2 Installing the Software
2.3 Uninstalling the Software
3.0 Compiling programs
3.1 Compiler messages
3.2 Compiler options
3.2.1 Compiler options list
3.3 Compiler directives
3.3.1 Compiler directives list
4.0 Executing programs
5.0 Extensions to Pascal as specified by ISO/IEC 7185
5.1 Relaxed declarations
5.2 Constant ranges
5.3 Otherwise
5.4 Relaxed parameter list congruity
5.5 Non-numeric statement labels
5.6 Underscores in identifiers
5.7 Binary integer constants
5.8 Hexadecimal integer constants
5.9 Input and Output automatically declared
5.10 Double-quoted literals
5.11 and_then operator
5.12 or_else operator
5.13 shl operator
5.14 shr operator
5.15 Extended constants
5.15.1 maxchar
5.16 Extended types
5.16.1 filename
5.16.2 list
5.16.3 string
5.17 Extended variables
5.17.1 exitcode
5.18 Extended functions
5.18.1 concat
5.18.2 copy
5.18.3 cosh
5.18.4 FilePos
5.18.5 FileSize
5.18.6 frac
5.18.7 GetEnv
5.18.8 hex
5.18.9 int
5.18.10 IOResult
5.18.11 length
5.18.12 log
5.18.13 locase
5.18.14 lowercase
5.18.15 paramcount
5.18.16 paramstr
5.18.17 pi
5.18.18 pos
5.18.19 random
5.18.20 reverse
5.18.21 sinh
5.18.22 swap
5.18.23 system
5.18.24 trim
5.18.25 upcase
5.18.26 uppercase
5.19 Extended procedures
5.19.1 append
5.19.2 assign
5.19.3 close
5.19.4 dec
5.19.5 delete
5.19.6 dispose
5.19.7 erase
5.19.8 exec
5.19.9 exit
5.19.10 flush
5.19.11 GetDate
5.19.12 GetTime
5.19.13 halt
5.19.14 inc
5.19.15 insert
5.19.16 new
5.19.17 randomize
5.19.18 RawRead
5.19.19 RawWrite
5.19.20 rename
5.19.21 seek
5.19.22 str
5.19.23 val
6.0 Miscellaneous features
6.1 Program parameters
6.2 Compatible types
6.3 Assignment compatibility
6.3.1 Assignment compatibility with array indexing
6.3.2 Assignment compatibility with value parameters
6.3.3 Assignment compatibility with 'read'
6.3.4 Assignment compatibility with assignment statements
6.3.5 Assignment compatibility with 'for'
6.3.6 Transfer procedures

Appendix A. Deviations from ISO/IEC 7185
A.1 end-of-line characters
A.2 Termination of all lines in text files
A.3 new(p, c1..CN)
A.4 dispose(q, k1..kM)
A.5 Carriage return

Appendix B. Implementation limits
B.1 Length of source lines
B.2 Number and nesting of statement sequences
B.3 Nesting of functions/procedures
B.4 Range of variant selectors type & Number of variants
B.5 Range of case-index's type & Number of case-list-elements
B.6 Size of integer constants
B.7 Size of real constants
B.8 Size of code and data
B.9 Number of set elements
B.10 Nesting of statements
B.11 Stack size

Appendix C. Implementation-defined features
C.1 String-elements
C.2 Provision of tokens and delimiting characters
C.3 Size and precision of real values
C.4 Character set
C.5 Ordinal values of characters
C.6 Characters prohibited from text files
C.7 When I/O is performed
C.8 Value of maxint
C.9 Accuracy of real operations and functions
C.10 Default value of TotalWidth for integer-type
C.11 Default value of TotalWidth for real-type
C.12 Default value of TotalWidth for Boolean-type
C.13 Number of digits written in exponents
C.14 Use of 'e' of 'E' as exponent character on output
C.15 Case of characters used on output of Boolean values
C.16 Effect of built-in procedure 'page'
C.17 Binding of file-type program-parameters
C.18 Effect of 'reset' and 'rewrite' on 'input' and 'output'

Appendix D. Implementation-dependent features
D.1 Effect of writing 'prohibited' characters
D.2 Order of evaluation of index-expressions
D.3 Order of evaluation of expressions of a member-designator
D.4 Order of evaluation of member-designators
D.5 Order of evaluation of operands of dyadic operators
D.6 Order of evaluation of actual-parameters for function calls
D.7 Order of evaluating components of assignment statements
D.8 Order of evaluation of actual-parameters for procedure calls
D.9 Effect of reading a text file to which 'page' has been applied
D.10 Binding of non-file program-parameters

Appendix E. Errors
E.1 Array index out of bounds
E.2 Accessing inactive variant
E.3 Dereferencing nil pointers
E.4 Dereferencing undefined pointers
E.5 Dangling pointers
E.6 Altering file-variables
E.7 Using out-of-range value parameters
E.8 Using out-of-range set value parameters
E.9 Output to file not open for writing
E.10 Output to undefined file
E.11 Writing to middle of file
E.12 Putting undefined buffer-variables
E.13 Resetting undefined files
E.14 Input from file not open for reading
E.15 Input from undefined file
E.16 Reading past end-of-file
E.17 Reading out of range values
E.18 Writing out of range values
E.19 new(p, c1..cN) constraints violated
E.20 Incompatible use of dispose(p)
E.21 Incompatible use of dispose(p, k1..kM)
E.22 dispose(p, k1..kM) constraint violations
E.23 disposing nil pointer
E.24 disposing undefined pointer
E.25 new(p, c1..cN) constraints violated
E.26 Invalid use of pack
E.27 Invalid use of pack
E.28 Invalid use of pack
E.29 Invalid use of unpack
E.30 Invalid use of unpack
E.31 Invalid use of unpack
E.32 Square root of negative number
E.33 ln(x) and x <= 0
E.34 Square root of negative number
E.35 Problems with trunc
E.36 Problems with round
E.37 Problems with chr
E.38 Problems with succ
E.39 Problems with pred
E.40 Using eof on undefined files
E.41 Using eoln on undefined files
E.42 Using eoln at end-of-file
E.43 Using undefined variables
E.44 Division by zero
E.45 Division by zero
E.46 Modulus of zero or negative
E.47 Integer overflow/underflow
E.48 Returning undefined value from function
E.49 Assigning out of range ordinal values
E.50 Assigning out of range set values
E.51 Non-matching case index
E.52 For loops initial value out of range
E.53 For loops final value out of range
E.54 Reading invalid integer values
E.55 Reading out of range integer values
E.56 Reading invalid numeric values
E.57 Reading when file is not open
E.58 Writing with TotalWidth or FracDigits less than one
E.59 Problems with program-parameters
E.60 Problems with conformant arrays

Appendix F. I/O error codes

-------
Preface
-------
The Software supports Standard (i.e. ISO/IEC 7185) Pascal
(see the Compliance statement) below. This guide covers mainly how
to install and use the Software, and the extensions to Standard Pascal
supported by the Software. This guide is NOT a Standard Pascal reference,
so for example the functions and procedures defined by Standard Pascal are
not described in this guide, even though they are supported by the Software.

You will probably need, in addition to this guide, reference and/or
tutorial information about Standard Pascal. However when choosing a Pascal
book, to supplement this guide, avoid books with "TURBO" or "BORLAND"
in their titles since these books are likely to cover Borland's
implementation of Pascal and not Standard Pascal.

-------
Purpose
-------
The main purpose of Irie Pascal is to provide an excellent multi-platform
tool for people who either want to learn Pascal or who want to write small
to medium sized scripts and utility programs. As a result the following
are emphasized:
1) Simplicity and ease of use
2) Good diagnostics (both compile time and run-time)
3) Generating correct code
4) Very strong support for Standard Pascal
5) Support for many extensions to Standard Pascal, particularly in the
areas of file and string processing
6) Support for multi-platform programming (i.e. you should be able to
compile your programs once and run them on any supported platform)
7) Moderate price

----------------
1.0 Introduction
----------------

-------------------
1.1 The Software
-------------------
The Software consists of two programs, the Compiler and the Interpreter.
The Compiler is not a native code compiler (i.e. it does not generate
instructions for a real computer), instead it generates instructions
(also called byte codes) for an imaginary computer (called the
"Irie Virtual Machine"). These byte codes can not be directly executed
by any existing computer, but instead must be executed by the Interpreter.

The main advantage of generating byte codes instead of native code is that
the resulting programs are very portable. The programs generated by the
Compiler can be run (without being recompiled) on any computer platform
on which the Interpreter exists. Currently the Interpreter exists on four
computer platforms:
1) Win95/NT
2) OS/2.
3) MS-DOS
4) Linux
A ports to FreeBSD is planned for the very near future.

Another advantage to generating byte codes is that the resulting programs
tend to be much smaller than their native-code equivalents. I have found
that programs generated by the Compiler tend to be roughly 20 times smaller
than equivalent programs generated by native code compilers.

The main disadvantage of generating byte codes instead of native code is
speed or rather the lack of it. This is because the byte codes are not
directly executed, but are executed by the Interpreter. I have found that
programs generated by the Compiler tend to run roughly 50 times slower than
equivalent programs generated by native code compilers. There are many
kinds of programs where this speed is perfectly acceptable, but there
are other kinds where this speed is just too slow. I expect the Software
to be used mainly to generate utility programs, and programs for learning
purposes (if you are learning Pascal you don't need your test programs to
be the fastest possible, you probably need good diagnostics
(both compile-time and run-time) more.

This is a beta release of Irie Pascal (i.e. this release has been thoroughly
tested by me but has not been tested by anyone else). While I am confident
that Irie Pascal is stable enough to be a useful tool, I can not guarantee
that it is bug free. You should be also be aware that although I claim
Irie Pascal complies with ISO/IEC 7185 Level 0 (since it does according to
my tests) it has not been formally certified by an external body.

This beta release of Irie Pascal is available free of charge. Feel free to
share this release with your friends, but do not give it away altered or as
part of another system.

NOTE: The final version of Irie Pascal will be released as shareware.
There will be two versions. One version is called the evaluation version
which will be freely available at no charge. You are encouraged to share
this version with others (hence the name 'shareware'). The other version
is called the registered version which you will be able to obtain after
paying the registration fee. You will not authorized to share the
registered version (i.e. you should treat it like any other type of
commercial software). The amount of the registration fee will be specified
when the final version is released.

This is actually the evaluation version of Irie Pascal, but because
this is a beta release I am not accepting registration fees, and therefore
the registered version is not yet available. The only reason I mention this
is that programs compiled by the evaluation version expire after seven days,
while programs compiled with the registered version never expire. This is
intended to gently encourage you to pay the registration fee and obtain the
registered version. I say "gently encourage" because you can re-compile
expired programs as many times as you like to keep them running indefinitely.

-----------------------------
1.2 Disclaimer - Agreement
-----------------------------
Users of the Software must accept this disclaimer of warranty:
"The Software is supplied as is. The author disclaims all warranties,
expressed or implied, including, without limitation, the warranties of
merchantability and of fitness for any purpose. The author assumes no
liability for damages, direct or consequential, which may result from the
use of the Software."

---------------------------
1.3 Compliance statement
---------------------------
The following compliance statement is required by the International
Standard for the Pascal language ISO/IEC 7185.

"Irie Pascal for OS/2 complies with the requirements of level 0 of
ISO/IEC 7185, with the following exceptions: (see Appendix A)".

----------------------
1.4 Product support
----------------------
I am very interested in all your comments about the Software, but
most especially in your comments about the usefullness of the Software,
any problems you encounter installing or using the Software, and any
changes you would like to see in this guide or in the Software.

The latest information and updates of the Software are available at
the Irie Tools web site at http://www.irietools.com

You can also contact me directly with your technical support
questions (see "Contacting the author" below).

----------------------------
1.5 Contacting the author
----------------------------
For the quickest response contact me by e-mail at support@irietools.com

If you prefer you can contact me by regular mail (but this takes longer) at:
Stuart King
MB #247
221 S. State Road 7
Ft. Lauderdale, Fl 33317
U.S.A.

----------------
2.0 Installation
----------------

----------------------------------
2.1 Minimum system requirements
----------------------------------
- 1 MB hard disk space

--------------------------------
2.2 Installation the Software
--------------------------------
For information on installing Irie Pascal see "install.txt"

--------------------------------
2.3 Uninstalling the Software
--------------------------------
For information on uninstalling Irie Pascal see "install.txt"

----------------------
3.0 Compiling programs
----------------------
You compile programs using the Irie Pascal Compiler (referred to as
"the Compiler"). The Compiler should be run from a command-line prompt.

Once you are at a command-line prompt use the following syntax
Syntax: ipc [options] filename
or ipc ?
or ipc
where [options] modify the behaviour of the Compiler.
[filename] specifies the file to compile.
NOTE: [x] indicates that x is optional.

If you enter
"ipc"
then the Compiler displays a brief help screen showing the proper syntax.
If you enter
"ipc ?"
then the Compiler displays a more detailed help screen listing all the
options that you can use.
If you enter
"ipc [options] filename"
then the Compiler attempts to compile the file specified by 'filename'
taking into account the options specified if any.

If we ignore the compiler options for the time being then to
compile a program you enter "ipc filename".

For example to compile the sample "hello.pas" program
enter "ipc hello" or "ipc hello.pas" (assuming of course that
"hello.pas" is in the current directory).
The Compiler will generate a file called "hello.ivm" which contains an
Irie Virtual Machine Executable. You can run it by entering
"ivm hello" or "ivm hello.ivm".

------------------------
3.1 Compiler messages
------------------------
The compiler can display four different classes of messages
1) Fatal error messages
2) Error messages
3) Warning messages
4) Informatory messages

Fatal error messages are displayed when the compiler detects a problem
that is so serious it can not continue. After displaying a fatal error
message the compiler deletes the Irie Virtual Machine Executable if one
is being created and then stops immediately.

Error messages are displayed when the compiler detects a problem
that prevents it from generating a reliable executable. After displaying
an error message the compile deletes the Irie Virtual Machine Executable
and continues compiling in order to detect other problems.

Warning messages are generated when the compiler detects something
which may indicate a problem with your program. For example if you
declare a variable and never use it the compile displays a warning
message.

Informatory messages display information which may be interesting
but not really necessary. For example there are messages which show
the speed of compilation.

Here is an example of what I mean.
If you compile the following program which is one of the sample programs
"bad.pas"

program bad(output);
begin
writelm('Hello') (* writelm used instead of writeln *)
end.

then the Compiler produces the following output

Irie Pascal for OS/2 (Beta 2B) Copyright (c) 1998, Stuart King.
Error #76: "bad.pas" (line 3, col 4): Procedure identifier expected.
writelm('Hello') (* writelm used instead of writeln *)
^
Warning #44: "bad.pas" (line 1, col 13): Variable is never used.
program bad(output);
^
1 error(s) and 1 warning(s) were issued.
5 lines compiled in 0.110 seconds.
Compilation speed 45 lines/sec, 2700 lines/min.

The first line is the copyright notice.
The second line is an error message
The word "Error" indicates that this is an error or fatal error message.
The #76 is the message number.
Then comes the name of the file with the error.
Then comes the location where the error was detected
(line 3, column 4).
Finally the text of the message.
The third line shows the line where the error was detected.
The fourth line has a ^ pointing to the location in the third line where
the error was detected.
The fifth line is blank.
The sixth, seventh and eighth lines display a warning message with
essentially the same layout as the error message.
The final three lines are informatory messages.
NOTE: The speed of compilation will vary.

Tip: Sometimes a single problem can confuse the Compiler and make it
report problems later on that don't really exist. So pay special
attention to the problem reported by the first message and try to fix
this one first.

-----------------------
3.2 Compiler options
-----------------------
Compiler options are instructions to the Compiler to somehow modify it's
behaviour (usually they are instruction to enable or disable a particular
compiler feature). Compiler options are entered on the command-line when
you invoke the Compiler (see "Compiling programs" above).
NOTE: Compile options are case sensitive so for example 'i' and 'I' are
different options.

There are two kinds of compiler options
1) Flag options
2) Value options

Flag options are used to enable or disable a compiler feature.
To enable the feature use
-option or -option+
where
option is the particular compiler option.
To disable the feature use
-option-

For example the 'nc' option is used to enable/disable the processing of
nested comments. So -nc or -nc+ is used to enable the processing of nested
comments and -nc- is used to disable the processing of nested comments.

Value options are used to specify the value of some quantity.
To specify a value option use
-optionVALUE
where
option is the particular compiler option
and
VALUE is the value being specified.

For example the 'mw' option is used to specify the maximum number of
warnings that the Compiler should process.
So -mw2 is used to set the maximum number of warnings to 2.

More than one option can be specified so suppose you want to compile
the program "bad.pas" using brief messages and nested comments then
you can enter "ipc -b -nc bad.pas".

Options can be combined so you can also enter "ipc -bnc bad".

To turn off nested comment processing and brief message then
you can enter "ipc -nc- -b- bad" or "ipc -ncb- bad".

-------------------------------
3.2.1 Compiler options list
-------------------------------
Option: 'a'
Purpose: Specifies the maximum alignment used by the Compiler.
Syntax: -aN Set maximum alignment to N.
Default: Maximum alignment 4.
Notes:
N must be between 0 and 8 (N=0 is treated like N=1).

Some CPUs (including those in the 80x86 family) access data faster if it
is aligned on an address which is a multiple of the size of the data.
Suppose the CPU is accessing a real which is 8 bytes long then for
fastest access the real should be on an address which is a multiple
of 8 (for example 0, 8, 16, 24, 32, 40, 48, ...).

The Compiler stores variables in memory at the lowest available address
which is a multiple of either the variables size or the maximum alignment,
whichever is smaller.

For example suppose you compile the following program and the maximum
alignment is 4.

program x(output);
var
c : char;
i : integer;
b : boolean;
r : real;
begin
end.

The compiler needs to decide where to store the variables
'c', 'i', 'b' and 'r'.

The first variable 'c' gets stored at address 0, and since 'c' is
a char variable (which are 1 byte long) the available addresses are
from 1 upwards.

The second variable 'i' is an integer variable (which are 4 bytes long).
The lowest available address which is a multiple of the variable size
is 4 and the lowest available address which is a multiple of the maximum
alignment is also 4. So the Compiler stores 'i' at address 4, and the
available address are from 8 upwards (since 'i' is 4 bytes long).

The third variable 'b' is a boolean variable (which are 4 bytes long).
The lowest available address which is a multiple of the variable size
is 8 and the lowest available address which is a multiple of the maximum
alignment is also 8. So the Compiler stores 'b' at address 8, and the
available address are from 12 upwards (since 'b' is 4 bytes long).

The fourth variable 'r' is a real variable (which are 8 bytes long).
The lowest available address which is a multiple of the variable size
is 16 but the lowest available address which is a multiple of the maximum
alignment is 12. So the Compiler stores 'r' at address 12 (since 12 is
less than 16).

In general if you set maximum alignment to 1 then you waste no memory
but you get fastest access only for chars. If you set the maximum alignment
to 4 you may waste memory when storing all variables except char, but
you get the fastest access to all variables except real. If you set the
maximum alignment to 8 you may waste memory when storing all variables
except char, but you get the fastest access to variables of all types.

If you are not sure about the setting of this option just leave the default.

------------------------------

Option: 'ao'
Purpose: Enables/disables assignment overflow checking.
Syntax: -ao[+|-]
Default: Enabled
Notes:
When assignment overflow checking is enabled the Compiler generates code
to check that variables are large enough to contain the values
assigned to them. The generated code will display a run-time diagnostic
message and stop your program if an assignment overflow error is detected.
Assignment overflow errors are only possible when assigning to string
variables or set variables using the array representation
(See "B.9 Number of set elements" for more information).

I strongly recommend you leave this option enabled.

------------------------------

Option: 'b'
Purpose: Enables/disables the use of the brief format for messages.
Syntax: -b[+|-]
Default: Disabled
Notes:
The verbose format for Fatal error and Error messages (which is used by
default) is
Error #nn: "name" (Line l, Col c): text
where
nn is a number identifying the message
name is the file where the problem as detected
l is the line where the problem was detected
c is the column where the problem was detected
text is the text of the message
The verbose format for warning messages are similiar except that "Warning"
is used instead of "Error".

The brief format for Fatal error and Error messages is
Enn: "name" l:text
where
nn is a number identifying the message
name is the file where the problem as detected
l is the line number of the line where the problem was detected
text is the text of the message
The brief format for warning messages are similiar except that "W" is
used instead of "E".

------------------------------


Option: 'C'
Purpose: Enables/disables case-sensitive compilation.
Syntax: -C[+|-]
Default: Disabled
Notes:
When case-sensitive compilation is disabled then the case of identifiers
is not considered significant. So for example 'x', and 'X' would be
considered to be the same identifier. When case-sensitive compilation
is enabled then the case of identifiers is considered to be significant.
So for example 'x', and 'X' are considered to be different identifiers.
Case-sensitive compilation is disabled by default since Standard Pascal is
not case-sensitive.

This option is disabled by default since Standard Pascal is not
case-sensitive. If you enable this option then remember to use all
lowercase for keywords and built-in identifiers
(i.e. constants, types, functions, procedures, and variables).

------------------------------

Option: 'eat'
Purpose: Enables/disables the and_then operator.
Syntax: -eat[+|-]
Default: Enabled
Notes:
See "Extensions to Pascal as specified by ISO/IEC 7185" for a description
of the and_then operator.

------------------------------

Option: 'eb'
Purpose: Enables/disables binary constants.
Syntax: -eb[+|-]
Default: Enabled
Notes:
See "Extensions to Pascal as specified by ISO/IEC 7185" for a description
of binary constants.

------------------------------

Option: 'ec'
Purpose: Enables/disables extended constants.
Syntax: -ec[+|-]
Default: Enabled
Notes:
See "Extensions to Pascal as specified by ISO/IEC 7185" for a description
of extended constants.

------------------------------
Option: 'ecr'
Purpose: Enables/disables constant ranges.
Syntax: -ecr[+|-]
Default: Enabled
Notes:
See "Extensions to Pascal as specified by ISO/IEC 7185" for a description
of constant ranges.

------------------------------

Option: 'edq'
Purpose: Enables/disables double quoted string and character literals.
Syntax: -edq[+|-]
Default: Enabled
Notes:
See "Extensions to Pascal as specified by ISO/IEC 7185" for a description
of double quoted literals.

------------------------------

Option: 'ef'
Purpose: Enables/disables extended functions.
Syntax: -ef[+|-]
Default: Enabled
Notes:
See "Extensions to Pascal as specified by ISO/IEC 7185" for a description
of the extended functions.

------------------------------

Option: 'efn'
Purpose: Enables/disables the built-in type 'filename'.
Syntax: -efn[+|-]
Default: Enabled
Notes:
See "Extensions to Pascal as specified by ISO/IEC 7185" for a description
of 'filename'.

------------------------------
Option: 'eh'
Purpose: Enables/disables hexadecimal constants.
Syntax: -eh[+|-]
Default: Enabled
Notes:
See "Extensions to Pascal as specified by ISO/IEC 7185" for a description
of hexadecimal constants.

------------------------------

Option: 'eio'
Purpose: Enables/disables automatic declaration of 'input' and 'output'.
Syntax: -eio[+|-]
Default: Enabled
Notes:
Standard Pascal specifies that whenever the required identifiers 'input'
and 'output' are referenced in a program
(either directly like write(output, 'Hello') or read(input, x)
or indirectly like write('Hello') or read(x))
then they must appear as program parameters.
However because some Pascal compilers do not enforce this requirement
many programmers don't bother.
If this option is enabled then the compiler automatically declares
'input' and 'output' as if they were specified as program parameters.

------------------------------

Option: 'el'
Purpose: Enables/disables the built-in type 'list'.
Syntax: -el[+|-]
Default: Enabled
Notes:
See "Extensions to Pascal as specified by ISO/IEC 7185" for a description
of the list type.

------------------------------

Option: 'emc'
Purpose: Enables/disables the built-in constant 'maxchar'.
Syntax: -emc[+|-]
Default: Enabled
Notes:
See "Extensions to Pascal as specified by ISO/IEC 7185" for a description
of 'maxchar'.

------------------------------
Option: 'enn'
Purpose: Enables/disables non-numeric statement labels.
Syntax: -enn[+|-]
Default: Enabled
Notes:
See "Extensions to Pascal as specified by ISO/IEC 7185" for a description
of non-numeric statement labels.

------------------------------

Option: 'eoe'
Purpose: Enables/disables the or_else operator.
Syntax: -eoe[+|-]
Default: Enabled
Notes:
See "Extensions to Pascal as specified by ISO/IEC 7185" for a description
of the or_else operator.

------------------------------

Option: 'eoth'
Purpose: Enables/disables 'otherwise' in case statements and variant records.
Syntax: -eoth[+|-]
Default: Enabled
Notes:
See "Extensions to Pascal as specified by ISO/IEC 7185" for a description
of the 'otherwise' keyword.

------------------------------

Option: 'ep'
Purpose: Enables/disables extended procedures.
Syntax: -ep[+|-]
Default: Enabled
Notes:
See "Extensions to Pascal as specified by ISO/IEC 7185" for a description
of the extended procedures.

------------------------------

Option: 'erd'
Purpose: Enables/disables relaxed declarations.
Syntax: -erd[+|-]
Default: Enabled
Notes:
See "Extensions to Pascal as specified by ISO/IEC 7185" for a description
of relaxed declarations.

------------------------------

Option: 'es'
Purpose: Enables/disables the built-in type 'string'.
Syntax: -es[+|-]
Default: Enabled
Notes:
See "Extensions to Pascal as specified by ISO/IEC 7185" for a description
of the string type.

------------------------------

Option: 'esh'
Purpose: Enables/disables the bit shift operators 'shr' and 'shl'.
Syntax: -esh[+|-]
Default: Enabled
Notes:
See "Extensions to Pascal as specified by ISO/IEC 7185" for a description
of the bit shift operators

------------------------------

Option: 'et'
Purpose: Enables/disables extended types.
Syntax: -et[+|-]
Default: Enabled
Notes:
See "Extensions to Pascal as specified by ISO/IEC 7185" for a description
of extended types

------------------------------
Option: 'eus'
Purpose: Enables/disables underscores in identifiers.
Syntax: -eus[+|-]
Default: Enabled
Notes:
See "Extensions to Pascal as specified by ISO/IEC 7185" for a description
of underscores in identifiers.

------------------------------

Option: 'ev'
Purpose: Enables/disables extended variables.
Syntax: -ev[+|-]
Default: Enabled
Notes:
See "Extensions to Pascal as specified by ISO/IEC 7185" for a description
of extended variables

------------------------------
Option: 'E'
Purpose: Enables/disables groups of extensions.
Syntax: -E[0|1|2]
Default: -E2
Notes:
Use -E0 to disable all extensions.
Use E1 to disable extensions which require a new keyword
and at the same time enable all other extensions.
Using E1 is the same as using
-eat- -eio+ -el- -eoe- -eoth- esh- eb+ -ed+ -eq+ -ef+ -ep+ -eh+ -es+
Use E2 to enable all extensions.

------------------------------

Option: 'i'
Purpose: Enables/disables I/O checking.
Syntax: -i[+|-]
Default: Enabled
Notes:
When I/O checking is enabled the Compiler generates code which checks each
I/O operation and issues a run-time diagnostic if an I/O error is detected.

------------------------------

Option: 'I'
Purpose: Enables/disables informatory messages.
Syntax: -I[nn][+|-]
Default: All informatory message enabled.
Notes:
Use -I or -I+ to enable all informatory messages.
Use -I- to disable all informatory messages.
Use -Inn or -Inn+ to enable the informatory message with message number nn.
Use -Inn- to disable the informatory message with message number nn.

------------------------------

Option: 'ln'
Purpose: Enables/disables line number information.
Syntax: -ln[+|-]
Default: Enabled
Notes:
When line number information is enabled, the Compiler stores the address
of the byte-codes generated for each line of source code, inside the
Irie Virtual Machine Executable. Enabling line number information
makes the executable bigger, but allows for more meaningful run-time
diagnostic messages since the line number of the source line that caused
the error is displayed in the message.

When line number information is not enabled, the executable is smaller
but run-time diagnostics messages display only the address of the code
that caused the error, which is unlikely to be very useful to you.

I recommend leaving this option enabled unless you really need to make the
executable as small as possible.

------------------------------

Option: 'mc'
Purpose: Enables/disables message context information
Syntax: -mc[+|-]
Default: Enabled
Notes:
When message context information is enabled the Compiler displays
context information for most error and warning messages. This context
information points to the specific place or item in the file that the
message is referring to.

------------------------------

Option: 'me'
Purpose: Specifies that the Compiler stop after N error messages.
Syntax: -meN
Default: N = 25
Notes:
Suppose you want the compiler to stop after 5 error messages then
use -me5

------------------------------

Option: 'ml'
Purpose: Enables/disables the the display of the message list.
Syntax: -ml[+|-]
Default: Disabled
Notes:
When the display of the message list is enabled the Compiler displays a
list of all of it's messages and then stops (it does not attempt to compile
anything). This option is useful to me when debugging the compiler so
that I can turn individual tracer messages on and off (I need to know
the message number).

------------------------------

Option: 'mw'
Purpose: Specifies that the Compiler stop after N warning messages.
Syntax: -mwN
Default: N = 100
Notes:
Suppose you want the compiler to stop after 5 warning messages then
use -mw5

------------------------------

Option: 'nc'
Purpose: Enables/disables nested comments.
Syntax: -nc[+|-]
Default: Disabled
Notes:
Nested comments are comments inside other comments.
For example
(* outer (* inner comment *) comment *)
When nested comments is disabled the example comment above will
terminate at the first *) so only
(* outer (* inner comment *)
will be treated as a comment.
When nested comments is enabled Compiler recognizes the end of comments
only when the number of close comment markers matches the number of open
comment markers. So the example comment above will terminate only after the
second *).

Both open comment markers (* and { are considered to be equivelent.
Both close comment markers *) and } are considered to be equivelent.
So attempting to trick the Compiler into accepting nested comments with
something like
(* outer { inner comment } comment *)
will not work.

Nested comments are disabled by default since in Standard Pascal comments
do not nest.

------------------------------
Option: 'p'
Purpose: Enables/disables mandatory parentheses mode.
Syntax: -p[+|-]
Default: Disabled
Notes:
The one thing I dislike about Pascal is that parentheses are not used
when calling or declaring functions or procedures with no parameters.
So for example in the following statement
a := b;
it is not clear whether 'b' is a function that takes no parameters or
whether 'b' is a variable.

When mandatory parentheses mode is enabled then parentheses are required
when declaring or calling all functions and procedures even those with
no parameters. Parentheses are also required after the program name even
if there are no program parameters.

So for example to declare a procedure that takes no parameters you would
use the following

procedure name();
...
begin
...
end;

And when calling it you would use

name();

The problem with using this option is that your programs are not strictly
speaking Pascal programs any longer and they probably could not be compiled
by another compiler without being modified.

------------------------------

Option: 'r'
Purpose: Enables/disables range checking.
Syntax: -r[+|-]
Default: Enabled
Notes:
When range checking is enabled the Compiler generates code to check
for range errors. The generated code will display a run-time diagnostic
message and stop your program if a range error is detected.
The possible causes of range errors are:
A) Attempts to assign or read in values which are not assignment
compatible with a particular type to a variable of that type.
e.g. given var bit : 0..1;
using bit := 2 is a range error.
B) Attempts to access element outside of array bounds.
e.g. given var x : array[-4..10] of integer;
using x[-5] is a range error
C) Attempts to use width or fraction specifiers in write/writeln
which are less than 1.
e.g.
writeln(1234.56677:x, y);
is a range error if x or y is less than 1.

------------------------------

Option: 's'
Purpose: Enables/disabled strict checking of var string parameters.
Syntax: -s[+|-]
Default: Enabled
Notes:
When strict checking is enabled it is an error to pass a string variable
by reference if the length of the variable's string type is not equal to
the length of the formal parameter's string type.

When strict checking is disabled you can pass a string variable by reference
even if the length of the string variable is not equal to the length of the
formal parameter.

For example if you compile the following program and strict checking is
enabled

program p(output);
type
string8 = string[8];
var
x : string16;

procedure print(var s : string8);
begin
writeln(s)
end;

begin
x := 'Hello';
print(x) (* Error only if strict checking is enabled *)
end.

then the Compiler will report an error with the call print(x) since the
length of x's string type is 16 and the length of the formal parameter's
sting type is 8 (i.e.. they are not equal). If strict checking is disabled
then no errors are reported.

------------------------------

Option: 'sc'
Purpose: Enables/disables short-circuit evaluation for 'and' and 'or'
Syntax: -sc[+|-]
Default: Enabled
Notes:
The Boolean operators 'and' and 'or' are both binary operators which
take two Boolean operands one on the left and one on the right.
Like
left 'and' right and left 'or' right
where left and right are Boolean expressions.

Remember that the result of the 'and' operator is true only if both the
left operand and the right operand are true. Short-circuit evaluation
takes advantage of the fact that if the left operand of 'and' is
evaluated and found to be false then there is no need to evaluate the
right operand since the final result must be false.

Similiarly the result of the 'or' operator is false only if both the
left operand and the right operand are false. Short-circuit evaluation
takes advantage of the fact that if the left operand of 'or' is evaluated
and found to be true then there is no need to evaluate the right operand
since the final result must be true.

You might want to disable short-circuit evaluation if you need the
"side-effects" of evaluating the right operand. For example suppose the
right operand is a call to a function which modifies some global variables
(a "side-effect") in addition to returning a Boolean value. Then
short-circuit evaluation might cause the function not to be called and
therefore the global variables will not get modified. If you want to make
sure that the right operand is always evaluated then disable short-circuit
evaluation.

On the other hand short-circuit evaluation is sometimes useful. For example
suppose you have a pointer to an integer and you want to perform some
calculations if the integer is greater than 100, but you don't know whether
the pointer is equal to Nil, then with short-circuit evaluation you can
write:

if (p <> Nil) and (p^ > 100) then ... perform calculations ...

If p is Nil then (p <> Nil) is false and the right operand (p^ > 100) is
not evaluated which is good since evaluating the (p^ > 100) will cause
an run-time error when p (which is equal to Nil) is dereferenced.
Without short-circuit evaluation you would have to write something like:

if p <> Nil then
if p^ > 100 then ... perform calculations ...

One solution is to disable short-circuit evaluation for 'and' and 'or' using
this compiler option and use 'and_then' instead of 'and' and 'or_else'
instead of 'or' when you want short-circuit evaluation.

See "Extensions to Pascal as specified by ISO/IEC 7185" for a
description of the 'and_then' and 'or_else' operators.

------------------------------

Option: 'so'
Purpose: Enables/disables detailed stack overflow checking
Syntax: -so[+|-]
Default: Disabled
Notes:
The Interpreter automatically checks for stack overflow at the beginning
and end of each procedure/function call and when large values are placed
on the stack. These checks should suffice for most purposes, however you
can enable this option if you want the compiler to generates code which
forces the Interpreter to check for stack overflow before every statement
is executed.

------------------------------

Option: 'S'
Purpose: Specifies the number of kilobytes to allocate for your program's
stack.
Syntax: -Snn
Default: nn = 64
Notes:
The default stack size (64K) should be more than enough for the vast
majority of programs. However if your program is heavily recursive or has
functions that need a large amount of space for local variables or
parameters then you can increase this value up to a maximum of 1024K (1MB).
On the other hand you can alse use this options to reduce the size of your
program's stack.

------------------------------

Option: 't'
Purpose: Enables/disables monitoring of stack temporaries.
Syntax: -t[+|-]
Default: Disabled
Notes:
This option is useful to me when debugging the Compiler to check that
the generated code is using the stack correctly.

If you suspect that the Compiler is generating faulty code then one way
to check is to compile your program with this option enabled and run it as
usual. If you get one of the following run-time diagnostic messages
Error: Stack log overflow
Error: Stack log is empty
Error: Value of BP does not agree with stack log entry
Error: Value of SP does not agree with stack log entry
then you have probably found a bug in the Compiler.

------------------------------

Option: 'u'
Purpose: Enables/disables checking for undefined values.
Syntax: -u[+|-]
Default: Enabled
Notes:
When this option is enabled the Compiler generates code which checks
each time your program gets a value from a variable to make sure that
the value is not undefined. If your program does get an undefined value
from a variable then the code generated by the Compiler will issue a
diagnostic message and terminate your program.
So for example if you compile and run the following program
program bad(output);
var
r : real;
begin
writeln(r) (* The value of 'r' is undefined *)
end.
The program will terminate with a diagnostic message because of the
attempt to print the value of 'r' which is undefined.

Unfortunately not all variable accesses can be checked, checks are only
made for accesses to variables of the following types:
enumerated types (including boolean)
subranges of enumerated types
subranges of integer that do not include -1
file
list
pointer
real
set (array representation) (See "B.9 Number of set elements"
for more information).

Accesses to variables of types 'char', 'integer', 'record' and 'set'
(Bit set representation) are not checked.

Checking for undefined values is performed as follows:
A) All memory is initialized by setting all bits to 1.
B) When accessing a variable a check is performed to see if all bits
are set and if they are this variable is undefined.

This doesn't work for 'char', 'integer' or 'set' (bit set representation)
variables since a value with all bits set is valid for these variables.
Record are not checked because they may contain fields which can not be
checked.

------------------------------

Option: 'v'
Purpose: Enables/disables variant checking.
Syntax: -v[+|-]
Default: Enabled
Notes:
When variant checking is enabled the Compiler generates code to check each
reference to a variant to make sure the variant is active.

------------------------------

Option: 'W'
Purpose: Enables/disables warning messages.
Syntax: -W[nn][+|-]
Default: All warning messages enabled.
Notes:
Use -W or -W+ to enable all warning messages.
Use -W- to disable all warning messages.
Use -Wnn or -Wnn+ to enable warning message number nn.
Use -Wnn- to disable warning message number nn.

------------------------------

--------------------------
3.3 Compiler directives
--------------------------
Compiler directives are special comments that can be placed in a program
to enable or disable certain compiler features.
The Compiler will treat
any comment that begins with a '$' as a compiler directive.

To enable the feature use
{$D+} or (*$D+*)
where
D specifies the particular compiler directive.
To disable the feature use
{$D-} or (*$D-*)

For example the '$I' directive is used to enable/disable I/O checking.
So use {$I+} or (*$I+*) to enable I/O checking and
use {$I-} or (*$I-*) to disable I/O checking.

----------------------------------
3.3.1 Compiler directives list
----------------------------------
Directive: '$B'
Purpose: Enables/disables short-circuit evaluation of 'and' and 'or'.
Syntax: {$B+} or (*$B+*) or {$B-} or (*$B-*)
Notes:
see option 'sc' in the Compiler options list for more information on
short-circuit evaluation.

------------------------------

Directive: '$I'
Purpose: Enables/disables I/O checking.
Syntax: {$I+} or (*$I+*) or {$I-} or (*$I-*)
Notes:
When I/O checking is enabled the Compiler generates code to check each
I/O operation. The generated code will display a run-time diagnostic message
and stop your program if an I/O error is detected.

------------------------------

Directive: '$P'
Purpose: Enables/disables mandatory parentheses mode.
Syntax: {$P+} or (*$P+*) or {$P-} or (*$P-*)
Notes:
see the 'p' option in the Compiler options list for more information.

------------------------------

Directive: '$R'
Purpose: Enables/disables range checking.
Syntax: {$R+} or (*$R+*) or {$R-} or (*$R-*)
Notes:
see the 'r' option in the Compiler options list for more information.

------------------------------

Directive: '$S'
Purpose: Enables/disabled strict checking of var string parameters.
Syntax: {$S+} or (*$S+*) or {$S-} or (*$S-*)
Notes:
see the 's' option in the Compiler options list for more information.

------------------------------

Directive: '$U'
Purpose: Enables/disables checking for undefined values.
Syntax: {$U+} or (*$U+*) or {$U-} or (*$U-*)
Notes:
see the 'u' option in the Compiler options list for more information.

------------------------------

Directive: '$V'
Purpose: Enables/disables variant checking.
Syntax: {$V+} or (*$V+*) or {$V-} or (*$V-*)
Notes:
see the 'v' option in the Compiler options list for more information.

------------------------------

Directive: '$W'
Purpose: Enables/disables warning messages.
Syntax: {$W[nn]+} or (*$W[nn]+*) or {$W[nn]-} or (*$W[nn]-*)
Notes:
Use $W+ to enable all warning messages.
Use $W- to disable all warning messages.
Use $WnnWnn+ to enable warning message number nn.
Use $Wnn- to disable warning message number nn.

------------------------------

--------------------
4.0 Running programs
--------------------
You run programs using the Irie Pascal Interpreter (referred to as
"the Interpreter"). The Interpreter should be run from a command-line
prompt.

To go to a command-line prompt you do one of the following:
If you are running Windows NT 3.51 then double click on the
MS-DOS prompt icon in the main program group.
If you are running Windows 95 or Windows NT 4.0 then
a) Click on start
b) Select "programs"
c) Select "Command prompt"

Once you are at a command-line prompt use the following syntax
Syntax: ivm [filename] [arguments]
where
filename specifies the Irie Virtual Machine Executable to run.
and
[arguments] are program arguments passed to the executable.
NOTE: [x] indicates that x is optional.

For example if you compile the sample "hello.pas" program, the Compiler
will generate a file called "hello.ivm" which contains an
Irie Virtual Machine Executable. You can run it by entering
"ivm hello" or "ivm hello.ivm".

-----------------------------------------------------
5.0 Extensions to Pascal as specified by ISO/IEC 7185
-----------------------------------------------------
Irie Pascal supports a number of extensions to Standard Pascal.
Some of these extensions were added for compatibility with Turbo Pascal and
Extended Pascal, while others were added because I thought they might be
useful.

Most extensions can be enabled/disabled using compiler options.

---------------------------
5.1 Relaxed declarations
---------------------------
Standard Pascal requires that all declarations/definitions of the same
kind must be made together in a single group and that the groups must
appear in a specific order. The order required by Standard Pascal is:
Label declaration group
Constant definition group
Type definition group
Variable declaration group
Function/Procedure declaration group

When "relaxed declarations" is enabled there can be more than one of each
kind of group and groups can appear in any order except that the
Function/Procedure group must be last.

So if "relaxed declarations" is enabled then the following program is legal,

program summing(output);
const
first = 1;
last = 100;
type
num = first..last;
var
i : num;
type
atype = array[first..last] of integer;
var
a : atype;
sum : integer;
begin
sum := 0;
for i := first to last do
begin
sum := sum + i;
a[i] := sum
end;
for i := last downto first do
writeln(i, a[i]);
end.

even though it has two type definition groups
"type num = first..last;"
and
"type atype = array[first..last] of integer;"
and two variable declaration groups
"var i : num;"
and
"var a : atype; sum : integer;"

In Standard Pascal or with "relaxed declarations" disabled you would have to
combine these groups so you would have the following

program summing(output);
const
first = 1;
last = 100;
type
num = first..last;
atype = array[first..last] of integer;
var
i : num;
a : atype;
sum : integer;
begin
sum := 0;
for i := first to last do
begin
sum := sum + i;
a[i] := sum
end;
for i := last downto first do
writeln(i, a[i]);
end.

"Relaxed declarations" can be enabled/disabled using the 'erd' compiler
option.

----------------------
5.2 Constant ranges
----------------------
You can use constant ranges to specify a number of consecutive case
constants.
To use a constant range you specify the first constant, and the last
constant, separated by '..' as follows:
first..last

You could use the constant range
1..5
to specify the following constants
1, 2, 3, 4, 5

For example suppose 'c' is a char variable and you want to use a
case statement to write the word 'Letter' if 'c' contains a letter, and the
word 'Digit' if 'c' contains a digit, then you could specify each constant
individually as follows:

case c of
'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm',
'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z',
'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M',
'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z'
: write('Letter');
'0', '1', '2', '3', '4', '5', '6', '7', '8', '9'
: write('Digit');
end;

Or you could use constant ranges like the following:

case c of
'a'..'z', 'A'..'Z'
: write('Letter');
'0'..'9'
: write('Digit');
end;

Constant ranges can be used in case statements, like the example above,
and in variant records.

Support for constant ranges can be enabled/disabled using the 'ecr'
compiler option.

----------------
5.3 Otherwise
----------------
You can use the keyword 'otherwise' in case statements and variant records
to specify "all values that haven't been specified yet".

For example in the following variant record

type
character = record
case c : char of
'a'..'z', 'A'..'Z'
: (vowel : Boolean);
'0'..'9'
: (value : integer);
otherwise
: ();
end;

when 'otherwise' is used, the following values have already been specified
'a'..'z', 'A'..'Z', and '0'..'9'
so otherwise specifies all character values except
'a'..'z', 'A'..'Z', and '0'..'9'

Support for otherwise can be enabled/disabled using the 'eoth'
compiler option.

---------------------------------------
5.4 Relaxed parameter list congruity
---------------------------------------
Standard Pascal says the following parameter lists
(VAR a, b : integer)
and
(VAR c : integer; VAR d : integer)
are not congruous even though the individual parameters are congruous
because Standard Pascal compares formal parameter sections.
So in the example above the parameter lists are not congruous for two
reasons:
1) The first parameter list has one formal parameter section
'VAR a, b : integer'
while the second parameter list has two formal parameter section
'VAR c : integer' and 'VAR d : integer'
2) The individual parameter sections are not congruous
(i.e.. 'VAR a, b : integer' is not congruous with 'VAR c : integer')

Irie Pascal checks for parameter list congruity by comparing the
individual parameters without regard to the formal-parameter-sections.
So the example above would be considered congruous since
'a' and 'c' are both integer variable parameters
and
'b' and 'd' are both integer variable parameters

Parameter list congruity becomes important when passing functions/procedures
since the parameter list of the actual function/procedure parameter must be
congrous with the parameter list of the corresponding formal
function/procedure parameter.

Relaxed parameter list congruity can not be disabled.

-----------------------------------
5.5 Non-numeric statement labels
-----------------------------------
Irie Pascal supports non-numeric statement labels.

For example in the following program 'loop' is used as a statement label.

program name(output);
label loop;
var
i : integer;
begin
i := 1;
loop:
writeln(i);
i := i + 1;
if i <= 20 then goto loop;
end.

Support for non-numeric statement labels can be enabled/disabled using the
'enn' compiler option.

---------------------------------
5.6 Underscores in identifiers
---------------------------------
Irie Pascal supports identifiers which contain and/or start with
underscores ('_').

Support for underscores in identifiers can be enabled/disabled using the
'eus' compiler option.

-------------------------------
5.7 Binary integer constants
-------------------------------
Binary integer constants begin with '%', and are followed by one or
more binary digits.

The following are examples of valid binary constants
%0 %1 %01110101010101010111101

The following are not valid binary constants
%2 % %151 %g

Support for binary integer constants can be enabled/disabled using the
'eb' compiler option.

------------------------------------
5.8 Hexadecimal integer constants
------------------------------------
Hexadecimal integer constants begin with '$', and are followed by one or
more hexadecimal digits.

The following are examples of valid hexadecimal integer constants
$9 $A123 $ffff

The following is not a valid hexadecimal integer constant
$abgd
since 'g' is not a hexadecimal integer constants.

Support for hexadecimal integer constants can be enabled/disabled using the
'eh' compiler option.

-----------------------------------------------
5.9 Input and Output automatically declared.
-----------------------------------------------
Standard (ISO/IEC 7185) Pascal specifies that whenever the required
identifiers 'Input' and 'Output' are referenced in a program that they
must by declared (i.e. appear as program parameters). However because
some Pascal compilers do not enforce this requirement many Pascal programs
do not meet this specification. In order to allow Irie Pascal to compile
these programs without requiring the user to insert Input and Output
in the program parameter list, I decided that by default Irie Pascal
should automatically declare Input and Output.

Support for automatic declaration of Input and Output can be
enabled/disabled using the 'eio' compiler option.

-----------------------------
5.10 Double-quoted literals
-----------------------------
You can use double quotation marks to form character and string literals.

For example you could use
"Hello world"
instead of
'Hello world'

Double-quoted literals can be useful if you want to create literals with
single quotes in them since you don't have to use two single quotes to
represent one single quote.

For example you could use
"Don't go away"
which is equivalent to
'Don''t do away'

Support for double-quoted literals can be enabled/disabled using the
'edq' compiler option.

------------------------
5.11 and_then operator
------------------------
The 'and_then' operator is similiar to the 'and' operator except that
short-circuit evaluation is always used for 'and_then' regardless of
the setting of the 'sc' compiler option.

See the 'sc' compiler option for more information on short-circuit
evaluation.

Support for the 'and_then' operator can be enabled/disabled using the 'eat'
compiler option.

-----------------------
5.12 or_else operator
-----------------------
The 'or_else' operator is similiar to the 'or' operator except that
short-circuit evaluation is always used for 'or_else' regardless of
the setting of the 'sc' compiler option.

See the 'sc' compiler option for more information on short-circuit
evaluation.

Support for the 'or_else' operator can be enabled/disabled using the 'eoe'
compiler option.

-------------------
5.13 shl operator
-------------------
The 'shl' operator performs a left bit-shift, and returns the result of
this bit-shift. The left operand is the integer to be shifted, and the
right operand, which is also an integer, specifies the number of bits
to shift.

For example
4 shl 2
is equal to 16, since 4 shifted left by 2 bits is 16.

Support for the 'shl' and the 'shr' operators can be enabled/disabled using
the 'esh' compiler option.

-------------------
5.14 shr operator
-------------------
The 'shr' operator performs a right bit-shift, and returns the result of
this bit-shift. The left operand is the integer to be shifted, and the
right operand, which is also an integer, specifies the number of bits
to shift.

For example
4 shr 2
is equal to 1, since 4 shifted right by 2 bits is 1.

Support for the 'shl' and the 'shr' operators can be enabled/disabled using
the 'esh' compiler option.

-------------------------
5.15 Extended constants
-------------------------
Irie Pascal defines one of extended constant
(i.e. a built-in constant that is not a part of Standard Pascal).

-----------------
5.15.1 maxchar
-----------------
Irie Pascal defines 'maxchar' which is a built-in character constant,
whoose value is the maximum character value allowed.

Syntax: maxchar

'maxchar' can be enabled/disabled using the 'emc' compiler option.

---------------------
5.16 Extended types
---------------------
Irie Pascal defines a number of extended types
(i.e. built-in types that are not a part of Standard Pascal).

------------------
5.16.1 filename
------------------
Irie Pascal defines a type identifier called 'filename' which is the
string type most suitable for variables used to store filenames.

Syntax: filename

For example to declare a variable to store filenames use
var
name : filename;

NOTE: You can also use string types such as
var
name : packed array[1..N] of char;
or
name : string;

But I recommend you use 'filename' since this type is will always be
the most suitable type for storing filenames.

'filename' can be enabled/disabled using the 'efn' compiler option.

--------------
5.16.2 list
--------------
Irie Pascal defines a new keyword 'list' in order to provide support
for lists. To create a list type use the syntax below.

Syntax: [packed] list of Type
where
'Type' is the type of the components in the list.

If you use 'packed' then the list is likely to be more efficient in
terms of memory but less efficient in terms of speed.

You must use 'new' to initialize a list variable before you use it.
The syntax is:
new(list-variable)

You can use 'dispose' to release the memory used by a list variable
after you have finished with it. The syntax is:
dispose(list-variable)

You can use 'insert' to add components to a list variable.
The syntax is:
insert(component, list-variable [, p])
where
'component' is an expression which is assignment compatible with the
type of the list components.
'list-variable' is the list variable to which the component is to be
added.
'p' is an integer expression specifying the position in the list
at which to add the component. The valid values of 'p' are 1..N+1
where N is the number of components in the list variable.
If 'p' is not specified then the position used for the insertion
is N+1 (i.e. 'component' is appended at the end of the list).

If 'p' is between 1 and N then the component already at position 'p' is
not overwritten, instead the components at positions 'p' thru N are moved
down one position to make room for the new component.
If 'p' is equal to N+1 then 'component' is appended at the end of the list.
If 'p' > N+1 or 'p' < 1 then a run-time diagnostic message is displayed
and your program is stopped.


You can use 'delete' to remove components from a list variable.
The syntax is:
delete(lv, p [, count])
where
'lv' is the list variable from which the components are to be removed.
'p' is an integer expression specifying the position in the
list variable 'lv', from which to remove the components. The valid
values of 'p' are 1..N where N is the number of components in the
list variable 'lv'.
'count' is an integer expression specifying the number of components to
remove. If 'count' is not specified, or count is greater than the number
of components in the list from position 'p' to the end, then all the
components from position 'p' to the end are removed.

You can use the 'length' function to determine the number of components in a
list variable. The syntax is
length(list-variable)

Length is a function that takes as its only argument a list variable and
returns an integer value equal to the number of components in the list
variable.

You can access the components of a list variable just like an array
variable. The syntax is
lv '[' p ']'
where
'lv' is the list variable being accessed
'p' is the position of the component being accessed
For example if 'i' is an integer and 'lv' is a list variable the
statement below will write each component of 'lv'.
for i := 1 to length(lv) do
writeln(lv[i])

List types can be enabled/disabled using the 'el' compiler option.

----------------
5.16.3 string
----------------
Standard Pascal considers packed arrays of char with a lower bound of 1 to
be strings. However these are fixed length strings (i.e.. the only text that
can be assigned to these strings is text of exactly the same length as the
length of the array).

Irie Pascal supports variable length strings using a new type 'string'.
To create variable length string types use the syntax below.

Syntax: string
or string[max]
or string(max)
where
max is an integer constant, between 1 and 255, which specifies the maximum
length of the string.
If max is not specified the maximum length used is 255.

For example to create a variable length string type called 'name' with
a maximum length of 80 use
name = string[80];
or
name = string(80);
To create a variable length string type called 'address' with a maximum length
of 255 use
address = string;
or
address = string[255];
or
address = string(255);

The advantage of variable length strings is that any string can be assigned
to them, whether fixed or variable length, as long as the length of the
string being assigned does not exceed the string's maximum length.
Even characters can be assigned to variable length strings.

You can use the '+' operator to perform string concatenation.
For example here is a hello world program using string concatenation.

program good(output);
begin
writeln('hello' + ' ' + 'world' + '!')
end.

See "Extended functions" and "Extended procedures" for information the
functions and procedures that can be used with the 'string' type.

The string type can be enabled/disabled using the 'es' compiler option.

-------------------------
5.17 Extended variables
-------------------------
Irie Pascal defines one extended variable
(i.e. a built-in variable that is not a part of Standard Pascal).

------------------
5.17.1 exitcode
------------------
Irie Pascal defines 'exitcode' which is a built-in integer variable,
whoose value is returned to the calling program when your program exits.

Syntax: exitcode

For example suppose you want to return a value of 1 from your program
(perhaps to indicate that your program detected an error) then you can
use the following code

exitcode := 1;
halt;

NOTE: You can treat 'exitcode' like any other integer variable
(i.e. you can assign to it, use it in an expression, pass it as an
argument to a function, etc).

'exitcode' can be enabled/disabled using the 'ev' compiler option.

-------------------------
5.18 Extended functions
-------------------------
Irie Pascal defines a number of extended functions
(i.e. built-in functions that are not a part of Standard Pascal).

Extended functions can be enabled/disabled using the 'ef' compiler option.

----------------
5.18.1 concat
----------------
Syntax: concat(s1, ..., sN)
where N is the number of string/character parameters.
Purpose: Creates a string by concatenating its parameters.
Returns: The concatenated string.
Notes:
For example you could do something like
message := concat('Hello', ' ', 'world', '!');
to make message equal to 'Hello world!'

---------------
5.18.2 copy
---------------
Syntax: copy(strg, start [, N])
where 'strg' is a string/char value
and 'start' is an integer value
and 'N' is an integer value.
Purpose: Creates a string by copying 'N' characters in 'strg' starting from
position 'start'. If 'N' is omitted, or is greater than the number
of characters in 'strg' from 'start' to the end, then all the
characters in 'strg' starting from 'start' to the end are copied.
Returns: The created string.
Notes:
For example
copy('Testing...', 5, 2) is equal to 'in'
and
copy('Testing...', 7) is equal to 'g...'
and
copy('Testing...', 1, 1000) is equal to 'Testing...'

---------------
5.18.3 cosh
---------------
Syntax: cosh(x)
where 'x' is an integer or real value.
Purpose: Returns the hyperbolic cosine of 'x'
Notes:
This function always returns a real value even if 'x' is an integer.

-----------------
5.18.4 FilePos
-----------------
Syntax: FilePos(f)
where 'f' is a file variable.
Purpose: Returns the value of the file position indicator of 'f'.
Notes:
This function returns an integer value.
The file variable 'f' must be open.
For a text file variable the value of the file position indicator may
not be equal to the number of characters read/written so far.
For a binary file the value of the file position indicator is equal to
the number of characters read/written so far.

------------------
5.18.5 FileSize
------------------
Syntax: FileSize(f)
where 'f' is a file variable.
Purpose: Returns the size of the 'f'.
Notes:
This function returns an integer value.
The file variable 'f' must be open.
This function is currently implemented by saving the current file position
indicator, then seeking to the end of the file, then calling 'filepos' and
saving the result of this call, and finally seeking back to the saved
file position. One problem with this implementation is that it may not
be accurate for text files. However this implementation was chosen because
it is portable.

--------------
5.18.6 frac
--------------
Syntax: frac(x)
where 'x' is a real value.
Purpose: Returns the fractional part of 'x'.
Notes:
For example frac(7.234) is equal to .234 .
This function returns a real value.

----------------
5.18.7 GetEnv
----------------
Syntax: GetEnv(s)
where 's' is a string/char value.
Purpose: Searches the program's environment list for a string that matches
's'.
Notes:
If a string matching 's' can not be found in the environment list then an
empty string is returned.

-------------
5.18.8 hex
-------------
Syntax: hex(i)
where 'i' is an integer value.
Purpose: Returns a string equal to the hexadecimal representation of 'i'.
Notes:
For example hex(16) is equal to '10'.

-------------
5.18.9 int
-------------
Syntax: int(x)
where 'x' is a real value.
Purpose: Returns the integer part of 'x'.
Notes:
For example int(7.234) is equal to 7 .
This function returns a real value.

-------------------
5.18.10 IOResult
-------------------
Syntax: IOResult
Purpose: Returns the error code of the last input/output operation.
Notes:
By default (when I/O checking is enabled) your program automatically
checks for errors after each I/O operation and terminates with an error
message if any errors are detected. If you do not want this default
behaviour you can disable I/O checking (either globally using the 'i'
compiler option or locally using the 'i' compiler directive) and call
this function to determine if any I/O errors occurred.
The error codes returned by this function are given in Appendix F
(0 means no error occurred).
This function resets the error code to zero after it is called, so if you
call this function twice after an I/O operation then the second call
will always return 0. If you need to refer to the error code more than once
you can save the error code into a variable.
For example:
errcode := IOResult;
if errcode <> 0 then
case errcode of
1: writeln('Error erasing file');
2: writeln('Error renaming file');
3: writeln('File is undefined')
end

See also the 'i' compiler option and the '$I' compiler directive.

-----------------
5.18.11 length
-----------------
Syntax: length(l) | length(s)
where 'l' is a list variable
and 's' is a string/char variable
Purpose: Returns the length of the list 'l' or the string 's'.
Notes:

--------------
5.18.12 log
--------------
Syntax: log(x)
where 'x' is an integer or real value.
Purpose: Returns the base-ten logarithm of 'x'.
Notes:

-----------------
5.18.13 locase
-----------------
Syntax: locase(c)
where 'c' is a character value.
Purpose: Returns the lowercase letter corresponding to 'c'.
If there is no lowercase letter corresponding to 'c' then
'c' is returned.
Notes:

--------------------
5.18.14 lowercase
--------------------
Syntax: lowercase(s)
where 's' is a string value.
Purpose: Returns a string equal to 's' with all of it's uppercase letters
converted to lowercase letters.
Notes:

---------------------
5.18.15 paramcount
---------------------
Syntax: paramcount
Purpose: Returns the number of arguments passed to the program.
Notes:
For example the following is the sample program 'args.pas'.

program args(output);
begin
writeln('Number of program arguments =', paramcount)
end.

If you compile it and run it as follows
ipc args
ivm args this is a test
then the output would be
Number of program arguments = 4

-------------------
5.18.16 paramstr
-------------------
Syntax: paramstr(i)
where 'i' is an integer value.
Purpose: Returns the ith program argument as a string.
Notes:
If there is no ith program argument an empty string is returned.

-------------
5.18.17 pi
-------------
Syntax: pi
Purpose: Returns the approximate value of the mathematical constant 'pi'
Notes:

--------------
5.18.18 pos
--------------
Syntax: pos(needle, haystack [, start])
where 'needle' is a string/char value
and 'haystack' is a string/char value
and 'start' in an integer value
Purpose: Search for 'needle' in 'haystack' starting at position 'start'
and returns 0 if 'needle' is not found or returns the position
of 'needle' in 'haystack'. If 'start' is omitted then the search
begins at position 1. If 'start' is greater than the length of
'haystack' then 0 is returned.
Notes:
pos('o', 'Hello world') is equal to 5
pos('o', 'Hello world', 1) is equal to 5
pos('o', 'Hello world', 6) is equal to 8
pos('o', 'Hello world', 256) is equal to 0

-----------------
5.18.19 random
-----------------
Syntax: random [ (i) ]
where 'i' is an integer value.
Purpose: Returns a psuedo-random number.
Notes:
If 'i' is not specified then random returns a psuedo-random real value
between 0 and 1.
If 'i' is specified then random returns a psuedo-random integer value
between 1 and 'i'-1.
See also the randomize procedure.

------------------
5.18.20 reverse
------------------
Syntax: reverse(s)
where 's' is a string/char value.
Purpose: Returns a string created by reversing the characters in 's'.
Notes:
For example
reverse('Hello') is equal to 'olleH'

---------------
5.18.21 sinh
---------------
Syntax: sin(x)
where 'x' is an integer or real value.
Purpose: Returns the hyperbolic sine of 'x'
Notes:
This function always returns a real value even if 'x' is an integer.

---------------
5.18.22 swap
---------------
Syntax: swap(i)
where 'i' is an integer value.
Purpose: Returns an integer value calculated by reversing the byte ordering
in 'i'.
Notes:
For example assuming 32 bit little endian integers then 256 is stored in
four bytes as follows:

0 0 1 0

So swap(256) results in the following integer:

0 1 0 0

which is equal to 65536

-----------------
5.18.23 system
-----------------
Syntax: system(s)
where 's' is a string value.
Purpose: Passes 's' to the command processor, which will attempt to process
's' as a command.
Notes:
If there is an error then 'system' returns a non-zero value indicating
the kind of error.
If there is no error then 'system' returns zero.

See also the 'exec' procedure.

For example the sample program 'batch.pas' below is a very primitive
batch processor. It sends each line in the input file to the command
processor to be executed.

program batch(f, output);
var
f : text;
s : string;
err : integer;
begin
reset(f); (* open input file or standard input file *)
while not eof(f) do
begin
readln(f, s);
writeln('Executing ', s);
err := system(s); (* Pass 's' to the command processor *)
writeln('Error code is ', err)
end
end.

---------------
5.18.24 trim
---------------
Syntax: trim(s)
where 's' is a string value.
Purpose: Returns a string equal to 's' with no leading or trailing spaces.
Notes:
For example
trim(' hello ') is equal to 'hello'

-----------------
5.18.25 upcase
-----------------
Syntax: upcase(c)
where 'c' is a character value.
Purpose: Returns the uppercase letter corresponding to 'c'.
If there is no uppercase letter corresponding to 'c' then
'c' is returned.
Notes:

--------------------
5.18.26 uppercase
--------------------
Syntax: uppercase(s)
where 's' is a string value.
Purpose: Returns a string equal to 's' with all of it's lowercase letters
converted to uppercase letters.
Notes:


--------------------------
5.19 Extended procedures
--------------------------
Irie Pascal defines a number of extended procedures
(i.e. built-in procedures that are not a part of Standard Pascal).

Extended procedures can be enabled/disabled using the 'ep' compiler option.

----------------
5.19.1 append
----------------
Syntax: append(f)
where 'f' is a file variable.
Purpose: Opens the file variable 'f' for writing at the end of file.
Notes:
All writes will occur at the end of the file regardless of calls to 'seek'.

----------------
5.19.2 assign
----------------
Syntax: assign(f, name)
where 'f' is a file variable.
and 'name' is a string value
Purpose: Associates 'name' with the file variable 'f'.
Notes:
The file variable 'f' must be closed.

For example to open a file named 'README.TXT' for reading use
assign(f, 'README.TXT');
reset(f);
where 'f' is a file variable.

You can't use this function to rename a file, use the 'rename' procedure
if you want to do that.

---------------
5.19.3 close
---------------
Syntax: close(f)
where 'f' is a file variable.
Purpose: Flushes and then closes the file variable 'f'.
Notes:

-------------
5.19.4 dec
-------------
Syntax: dec(o [, amount])
where 'o' is an ordinal variable
and amount is an integer value.
Purpose: Decrements 'o' by 'amount' or by one if 'amount' is omitted.
Notes:
Using this function is slightly more efficient than using
o := o - amount;

----------------
5.19.5 delete
----------------
Syntax: delete(s, start [, count]) | delete(l, start [, count])
where 's' is a string variable
and 'l' is a list variable
and 'start' is an integer value
and 'count' is an integer value
Purpose: Deletes 'count' components from a list or string.
'start' specifies the position at which to perform the deletion.
'count' specifies the number of components to delete.
If 'count' is omitted all the components from 'start' to the
end are deleted.
Notes:

-----------------
5.19.6 dispose
-----------------
Syntax: dispose(l)
where 'l' is a list variable.
Purpose: Releases the memory allocated for 'l' and makes 'l' undefined.
Notes:
The use of 'dispose' with pointer variables is part of Standard Pascal
and while supported by Irie Pascal is not covered in this guide.

---------------
5.19.7 erase
---------------
Syntax: erase(f)
where 'f' is a file variable.
Purpose: Erases the file associated with 'f'.
Notes:
'f' must be closed and must have a name associated with it (either using
the 'assign' procedure or by being one of the program arguments.

--------------
5.19.8 exec
--------------
Syntax: exec(p, a)
where 'p' and 'a' are string values.
Purpose: Executes the program specified by 'p' and passes 'a' as it's program
argument(s). The return code from 'p' is stored in the built-in
integer variable 'ExitCode'.
Notes:
For example here is the sample program 'dirpas.pas'.
program dirpas(output);
begin
exec('dir', '*.pas');
if exitcode <> 0 then
writeln('Error listing directory', exitcode)
end.

--------------
5.19.9 exit
--------------
Syntax: exit [ (x) ]
where 'x' is a value.
Purpose: Terminates the function/procedure/program in which it is used,
and returns 'x' if 'x' is specified.
If used in a function then 'exit' terminates the function.
If used in a function named 'f' then 'exit(x)' is equivalent to
f := x;
exit
If used in a procedure then 'exit' terminates the procedure.
If used in a procedure then 'exit(x)' is an error since you can
not return a value from a procedure.
If used not in a function or procedure but in the main program
then 'exit' terminates the program.
If used not in a function or procedure but in the main program
then 'exit(x)' is equivalent to:
ExitCode := x;
exit
(i.e. the program is terminated with 'x' as the exit code).
Notes:
See also 'halt'

----------------
5.19.10 flush
----------------
Syntax: flush(f)
where 'f' is a file variable.
Purpose: Flushes the file associated with 'f' (i.e.. all data waiting to
be written to the file is written).
Notes:
The file associated with 'f' must be open.

------------------
5.19.11 GetDate
------------------
Syntax: GetDate(year, month, day, day_of_week)
where 'year', 'month', 'day', 'day_of_week' are integer variables.
Purpose: Retrieves the current system date into the four integer variables.
'month' = 1 to 12
day = 1 to 31
day_of_week = 0 to 6 counting from Sunday
Notes:
Suppose the current system date is Saturday September 6, 1997 then after
GetDate(year, month, day, day_of_week)
year = 1997
month = 9
day = 6
day_of_week = 6

------------------
5.19.12 GetTime
------------------
Syntax: GetTime(hour, minute, second)
where 'hour' is an integer variable
and 'minute' is an integer variable
and 'second' is an integer variable.
Purpose: Retrieves the current system time into the three integer variables.
'hour' = 0 thru 23
'minute' = 0 thru 59
'second' = 0 thru 61
Notes:

---------------
5.19.13 halt
---------------
Syntax: halt [ (i) ]
where 'i' is an integer value.
Purpose: Terminates the program and if 'i' is specified returns 'i' as
the program's exit code.
Notes:

--------------
5.19.14 inc
--------------
Syntax: inc(o [, amount])
where 'o' is an ordinal variable
and amount is an integer value.
Purpose: Increments 'o' by 'amount' or by one if 'amount' is omitted.
Notes:
Using this function is slightly more efficient than using
o := o + amount;

-----------------
5.19.15 insert
-----------------
Syntax: insert(x, s, position) or insert(v, l, position)
where 'x' is a string or char value
and 's' is a string variable
and 'position' is an integer value
and 'v' is a value
and 'l' is a list variable.
Purpose: Inserts 'x' into 's' at 'position' or
inserts 'v' into 'l' at 'position'.
Notes:
'v' must be assignment compatible with the component type of the list 'l'.

--------------
5.19.16 new
--------------
Syntax: new(l)
where 'l' is a list variable.
Purpose: Initializes the list 'l'.
Notes:
The use of 'new' with pointer variables is part of Standard Pascal
and while supported by Irie Pascal is not covered in this guide.

--------------------
5.19.17 randomize
--------------------
Syntax: randomize[ (i) ]
where 'i' is an integer value.
Purpose: Seeds the random number generator with 'i'. If 'i' is omitted
the random number generator is seeded with a value derived from
the current system time and date.
Note:
Specifying 'i' is useful if you want a repeatable sequence of random
numbers.

------------------
5.19.18 RawRead
------------------
Syntax: RawRead(f, buffer, count, actual)
where 'f' is a file variable
and 'buffer' is a packed array of char variable
and 'count' is an integer value
and 'actual' is an integer variable.
Purpose: Reads up to 'count' characters from the file associated with
'f' into 'buffer' and returns the actual number of characters
read in 'actual'.
Notes:
After calling RawRead 'actual' may be less than 'count' if there was
an I/O error (you can check for this by disabling I/O checking and using
the IOResult function) or if end of file was reached.

-------------------
5.19.19 RawWrite
-------------------
Syntax: RawWrite(f, buffer, count, actual)
where 'f' is a file variable
and 'buffer' is a packed array of char variable
and 'count' is an integer value
and 'actual' is an integer variable.
Purpose: Writes up to 'count' characters from 'buffer' to the file
associated with 'f' into 'buffer' and returns the actual number of
characters written in 'actual'.
Notes:
After calling RawWrite 'actual' may be less than 'count' if there was
an I/O error (you can check for this by disabling I/O checking and using
the IOResult function).

-----------------
5.19.20 rename
-----------------
Syntax: rename(f, name)
where 'f' is a file variable
and 'name' is a string/char expression.
Purpose: Renames the file associated with 'f' to 'name'
Notes:
The file associated with 'f' must be closed.

---------------
5.19.21 seek
---------------
Syntax: seek(f, offset)
where 'f' is a file variable
and 'offset' is an integer value.
Purpose: Sets the position indicator for the file associated with 'f'.
Notes:
The file associated with 'f' must be open.

--------------
5.19.22 str
--------------
Syntax:
str(i [:width], s)
or
str(r [:width[:frac]], s)

where 'i', 'width', and 'frac' are integer expresions
and 'r' is a real expression
and 's' is a string variable
Purpose: Converts 'i' or 'r' into a string value and assigns this value to s.
'width' specifies the minimum width of the string value.
If 'width' is ommited then eight is assumed for integer conversion
and nine is assumed for real conversions.
The string value is padded on the left if necessary.
'frac' specifies the number of digits after the decimal point.
if 'frac' is ommited then the real exression is converted into a
string in exponential form.
if 'frac' is present then the real expression is converted into
a string in fixed form.
For example
str(1034:6, s) will store ' 1034' in 's'
str(3.1:8, s) will store '3.1E+001' in 's'
str(-3.14:6:2, s) will store ' -3.14' in 's'

------------------------------

--------------
5.19.23 val
--------------
Syntax: val(s, v, offset)
where 's' is a string/char value
and 'v' is a numeric (i.e.. integer, real or a subrange) variable
and 'offset' is an integer variable.
Purpose: Converts 's' into a numeric value of the same type as 'v'
and returns in 'offset' the position in 's' of the first
character which could not be converted.
If all of 's' could be converted then val sets 'offset' to zero.
Notes:
For example given integer variables 'i' and 'x' the following statement
val('123EB', i, x)
will store 123 in 'i' and 4 in 'x'.

------------------------------

--------------------------
6.0 Miscellaneous features
--------------------------

-------------------------
6.1 Program parameters
-------------------------
Program parameters are are identifiers which appear after the program name
(placed between parentheses). In addition to appearing after the program
name, most program parameters must also appear in a global variable
declaration. Two special program parameters 'input' and 'output' are
the exceptions to this rule. The appearance of the two special program
parameters, after the program name, automatically declares them as two
special file variables which reference the standard-input and
standard-output streams.

You can use program parameters to access command-line arguments passed to
your program (see also extended procedures 'paramcount' and 'paramstr'). For
example suppose you want to write a program to append two files together,
writing the appended files to a third file, then you might write a program
similiar to the sample program below.

(**********************************************************************
** This program appends two files together, writing the appended files
** out to a third file.
*)
program append(in1, in2, out, output);
type
char_file = file of char;
var
in1 : char_file; (* first input file *)
in2 : char_file; (* second input file *)
out : char_file; (* output file *)

(***************************************************************
** PURPOSE: Writes copies the contents of one file into another.
** ARGUMENTS:
** 'f' - the input file
** 'g' - the output file
** NOTES: It is up to the caller to open and close the files.
*)
procedure WriteFile(var f, g: char_file);
var
c : char;
begin
while not eof(f) do
begin
read(f, c);
write(g, c)
end
end;

(**********************************************
** PURPOSE: Writes a help screen and then halts
*)
procedure syntax;
begin
writeln('Appends two files together and writes the output to a third file');
writeln('Syntax');
writeln(' ivm append in1 in2 out');
writeln('where "in1" is the first input file');
writeln('and "in2" is the second input file');
writeln('and "out" is the output file');
halt
end;

begin
if paramcount <> 3 then
syntax;
rewrite(out);
reset(in1);
WriteFile(in1, out);
close(in1);
reset(in2);
WriteFile(in2, out);
close(in2)
close(out);
end.

The first thing to notice about this program is the line below:

program append(in1, in2, out, output);

Here four program parameters are being used 'in1', 'in2', 'out', and 'output'.
The first program parameter 'in1' accesses the first command-line argument
The second program parameter 'in2' accesses the second command-line argument.
The third program parameter 'out' accesses the third command-line argument.
The fourth program parameter 'output' declares the special file variable
which references the standard-output stream, and has nothing to do with
command-line arguments. 'output' does not have to be the last program
parameter, it can be used in the first, or second or any position. Since
'output' does not access any command-line arguments it can appear in any
position (not just the fourth and last position) without disturbing the
command-line arguments accessed by the other program parameters. In other
words all of the following are equivalent

program append(output, in1, in2, out);
or
program append(in1, output, in2, out);
or
program append(in1, in2, output, out);
or
program append(in1, in2, out, output);

And in each of the four cases 'in1' accesses the first command-line argument
and 'in2' accesses the second command-line argument
and 'out' accesses the third command-line argument.

The second thing to notice about the program are the following lines.

var
in1 : char_file; (* first input file *)
in2 : char_file; (* second input file *)
out : char_file; (* output file *)

Here the program parameters (except for 'output') appear in global variable
declarations as required. They are declared to be variables of type
'char_file' which has been declared to be 'file of char'. Now since they are
declared to be file variables it means that the command-line arguments
accessed specify the names of the external files associated with the file
variables. What this means is that if the file variables are opened (using
'reset', 'rewrite', or 'append') then the external file which is opened is
the one specified by the command-line argument accessed.
For example if the program is run with the line

ivm append x.txt y.txt a:\z.txt

then when 'in1' is opened the file 'x.txt' is opened
and when 'in2' is opened the file 'y.txt' is opened
and when 'out' is opened the file 'a:\z.txt' is opened.

The final thing to notice about the program are the following lines.

if paramcount <> 3 then
syntax;

These lines cause the procedure 'syntax' to be called if the number of
command-line arguments is not 3. These lines are intended to prevent
problems if the user does not enter 3 command-line arguments.

Suppose for example the this program was run with no command-line arguments.
The first program argument 'in1' will access the first command-line argument
which does not exist so the empty string will specify the external file
associated with this file variable. Similarly the empty string will specify
the external files associated with the file variables 'in2' and 'out'.

You might ask what happens if you open a file variable associated with an
external file specified by an empty string? Well if you open such a
file variable for reading (with 'reset') then the external file opened
is the standard input stream. If you open such a file for writing
(with 'rewrite') then the external file opened is the standard output
stream.

I didn't want this effect when I wrote the sample program above so I
inserted the lines

if paramcount <> 3 then
syntax;

to avoid this.

So far I have described how file-type program parameters are handled.
You can also use string-type program parameters. They also access the
command-line arguments, but in a different way. The command-line
argument accessed is simply assigned to the string-type program parameter.

If you use program parameters other than file-type or string-type then
the command-line argument is ignored. The compiler will issue a warning,
that the command-line argument has an invalid type, but otherwise do
nothing.

For example look at this rather strange program.

program strange(f, s1, dummy, s2);
var
f : text;
s1, s2 : string;
dummy : real;
begin
rewrite(f);
writeln(f, s1);
writeln(f, s2)
end.

If you compile it you will get some warnings but ignore them.
If you run the program with

ivm strange out.txt first skip second

then the first program parameter 'f' will access 'out.txt', and since
'f' is a file-type program argument when 'rewrite' is used on 'f' the
file 'out.txt' will be created.
The second program parameter 's1' will access 'first', and since this
is a string-type program argument then 'first' will be assigned to 's1'.
The third program parameter 'dummy' is not a file-type or string-type
program parameter so the third command-line argument 'skip' will be
ignored.
The fourth program parameter 's2' will access 'second', and since this
is a string-type program argument then 'second' will be assigned to 's2'.

So the effect of the following three lines

rewrite(f);
writeln(f, s1);
writeln(f, s2)

is that a text file 'out.txt' is created and two lines are written to it.
The first line will be 'first' and the second will be 'second'.

-----------------------
6.2 Compatible types
-----------------------
Irie Pascal implements the type compatibility rules defined by Standard
Pascal (ISO/IEC 7185), and adds one more to support the new string type.
The first four rules below are taken from ISO/IEC 7185 and the last one
is the one added to support the new string type. In this section the term
'standard-string-type' refers to the string type defined by Standard Pascal
(i.e.. packed arrays of char with lower bounds of one). The term
'string-type' refers to the new string type implemented by Irie Pascal.

Types T1 and T2 shall be designated compatible if any of the following
statements is true:

1. T1 and T2 are the same type.

2. T1 is a subrange of T2, or T2 is a subrange of T1, or both T1 and T2 are
subranges of the same host type.

3. T1 and T2 are set-types of compatible base-types, and either both T1 and
T2 are designated packed or neither T1 nor T2 is designated packed.

4. T1 and T2 are standard-string-types with the same number of components.

5. Either T1 is a string-type and T2 is a string-type,
or T1 is a string-type and T2 is a standard-string-type, and the number
of components in T2 is less than or equal to the maximum length of T1,
or T1 is a string-type and T2 is the char-type
or T2 is a string-type and T1 is a standard-string-type, and the number
of components in T1 is less than or equal to the maximum length of T2,
or T2 is a string-type and T1 is the char-type.

-------------------------------
6.3 Assignment compatibility
-------------------------------
Irie Pascal implements the assignment compatibility rules defined by
Standard Pascal (ISO/IEC 7185), and adds one more to support the new
string type. The first five rules below are taken from ISO/IEC 7185 and
the last one is the one added to support the new string type. In this
section the term 'standard-string-type' refers to the string type defined
by Standard Pascal (i.e.. packed arrays of char with lower bounds of one).
The term 'string-type' refers to the new string type implemented by
Irie Pascal.

A value 'V' of type T2 is assignment compatible with a type T1 if any of
the following is true:

1. T1 and T2 are the same type, and that type is not a file type or a type
which contains a file type.

2. T1 is the real-type and T2 is the integer-type.

3. T1 and T2 are compatible ordinal-types, and V is in the closed interval
specified by T1.

4. T1 and T2 are compatible set-types, and all the members of V are in the
closed interval specified by the base-type of T1.

5. T1 and T2 are standard-string-types with the same length.

6. T1 is a string-type and either
T2 is a string-type
or T2 is a standard-string-type, and the length of
or T2 is a char-type.
In addition the length of V must not be greater then the maximum
length of T1.

-------------------------------------------------------
6.3.1 Assignment compatibility with array indexing
-------------------------------------------------------
The value of an index-expression shall be assignment compatible with the
index-type of the array variable.

For example given:

var x : array[1..10] of integer;

and

x[i] := 20;

then 'i' (the value of the index-expression) shall be assignment compatible
with '1..10' (the index-type of the array variable).

---------------------------------------------------------
6.3.2 Assignment compatibility with value parameters
---------------------------------------------------------
When passing a parameter by value the actual-parameter shall be
assignment compatible with the type of the formal-parameter.

For example given:

function IsDigit(c : char) : Boolean;
begin
if c in ['0'..'9'] then
IsDigit := true
else
IsDigit := false
end;

and

while not IsDigit(key) do
read(key)

then 'key' (the actual-parameter in IsDigit(key) shall be
assignment compatible with 'char' (the type of the formal-parameter).

-----------------------------------------------
6.3.3 Assignment compatibility with 'read'
-----------------------------------------------
When using the built-in procedure 'read' to store an input value into
a variable the input value shall be assignment compatible with the type of
the variable to which it is stored.

For example given:

var s : string[40];

and

read(s);

then the value read in by 'read(s)' must be assignment compatible with
'string[40]'.

--------------------------------------------------------------
6.3.4 Assignment compatibility with assignment statements
--------------------------------------------------------------
The value of the expression on the right-hand side of an assignment statement
shall be assignment compatible with the type of the left-hand side (i.e..
either the variable or the function-identifier on the left-hand side).

For example given:

var age : 0..100;

and

age := v;

then 'v' (the right-hand side of the assignment statement) shall be
assignment compatible the '0..100' (the type of the left-hand side of the
assignment statement).

----------------------------------------------
6.3.5 Assignment compatibility with 'for'
----------------------------------------------
The initial value and the final value in a for-statement shall be
assignment compatible with the type of the control variable if the
statement of the for-statement is executed.

For example given:

for i := low to high do writeln(i);

then 'low' (the initial value) and 'high' (the final value) shall be
assignment compatible with the type of 'i' (the control variable) if
'writeln(i)' is executed. NOTE: 'writeln(i)' will get executed unless
'low' is greater than 'high'.

------------------------------
6.3.6 Transfer procedures
------------------------------
In the statement pack(a,i,z) and unpack(z,a,i) the value of 'i' shall be
assignment compatible with the index-type of a.

For example given:

var a : array[1..100] of real;
z : packed array[1..100] of real;
i : integer;

and

pack(a,i,z) or unpack(z,a,i)

then 'i' shall be assignment compatible with '1..100'
(the index-type of 'a').

----------------------------------------
Appendix A. Deviations from ISO/IEC 7185
----------------------------------------

----------------------------------
A.1 end-of-line characters
----------------------------------
ISO/IEC 7185 requires that end-of-line characters read from text files
be converted to spaces. For example given

read(f, c)
where 'f' is a file at end-of-line
and 'c' is a character variable

then according to ISO/IEC 7185, after the read above 'c' should contain
a space character rather than an end-of-line character.
Irie Pascal does not convert end-of-line characters read from text file,
so in the example above 'c' will contain an end-of-line character
(i.e.. a linefeed character, chr(10)).

-------------------------------------------------
A.2 Termination of all lines in text files
-------------------------------------------------
ISO/IEC 7185 requires that all lines in text files (except possibly the line
that is currently being written) should be terminated by an end-of-line.
Irie Pascal does not automatically terminate the last line in a text file.

--------------------------
A.3 new(p, c1..cN)
--------------------------
ISO/IEC 7185 requires support for a form of the required procedure 'new'
as follows:

new(p, c1..cN)
where 'p' is a pointer to a variant record and 'c1' thru 'cN' are
case constants which correspond to the variants in p^.

Irie Pascal does not currently support this form of 'new'.

------------------------------
A.4 dispose(q, k1..kM)
------------------------------
ISO/IEC 7185 requires support for a form of the required procedure 'dispose'
as follows:

dispose(q, k1..kM)
where 'q' is a pointer to a variant record and 'k1' thru 'kM' are
case constants which correspond to the variants in q^.

Irie Pascal does not currently support this form of 'dispose'.

---------------------------
A.5 Carriage return
---------------------------
ISO/IEC requires that all characters written to a file should appear when
the file is read (the exception to this is that implementations are allowed
to designate a set of characters 'prohibited from text files' and treat these
characters specially).

Irie Pascal does not currently comply fully with this requirement, since
currently carriage return characters do not appear when individual
characters are read from text files (i.e. carriage return/line feed pairs
are converted into a single line feed).

---------------------------------
Appendix B. Implementation limits
---------------------------------
Irie Pascal imposes various limits on the size and complexity of programs
that it will process. These limits have been set fairly high so as not to
inconvenience the user.

----------------------------------
B.1 Length of source lines
----------------------------------
The maximum length of a source line is 400 characters.

If you exceed this limit the compiler will issue an error message.

-----------------------------------------------------
B.2 Number and nesting of statement sequences
-----------------------------------------------------
Statement sequences are the statements that occur between 'begin' and 'end'