|
|
DataMuseum.dkPresents historical artifacts from the history of: CP/M |
This is an automatic "excavation" of a thematic subset of
See our Wiki for more about CP/M Excavated with: AutoArchaeologist - Free & Open Source Software. |
top - metrics - download
Length: 147584 (0x24080)
Types: TextFile
Names: »D169«
└─⟦4b76feb82⟧ Bits:30008865 Diskette med tekster der formodes at være 31-D-163…174
└─⟦this⟧ »D169«
\f
i
T_A_B_L_E_ _O_F_ _C_O_N_T_E_N_T_S_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _P_A_G_E_ _
1. INTRODUCTION .......................................... 1
2. BASIC DEFINITIONS ..................................... 3
2.1 Vocabulary ....................................... 3
2.2 Syntax Diagrams .................................. 3
2.2.1 Comments .................................. 4
2.2.2 Identifiers ............................... 5
2.2.3 Numbers ................................... 5
2.2.4 Separators ................................ 6
2.2.5 Strings of Characters ..................... 6
2.3 Fundamental Concepts ............................. 7
3. THE PASCAL80 LANGUAGE ................................. 10
3.1 The Process Structure ............................ 10
3.2 The Process Heading .............................. 12
3.3 The Declaration Part ............................. 13
3.3.1 Label Declaration Part .................... 14
3.3.2 Constants Definition Part ................. 15
3.3.3 Variable Declaration Part ................. 17
3.3.4 Type Definition Part ...................... 18
3.3.4.1 Types ............................ 18
3.3.4.2 Type Compatibility ............... 31
3.3.5 Routine Declaration Part .................. 34
3.3.5.1 Scope Rules ...................... 37
3.3.5.2 Routine Blocks ................... 38
3.3.5.3 Functions ........................ 38
3.3.6 Export Part ............................... 39
3.4 The Statement Part ............................... 40
3.4.1 Statements ................................ 40
3.4.2 Assignment Statement ...................... 41
3.4.3 Exchange Statement ........................ 44
3.4.4 Repetitive Statements ..................... 44
3.4.5 Conditional Statements .................... 46
2.4.6 Procedure Call ............................ 48
3.4.7 With Statement ............................ 50
3.4.8 Lock Statement ............................ 50
3.4.9 Channel Statement ......................... 51 \f
ii
T_A_B_L_E_ _O_F_ _C_O_N_T_E_N_T_S_ _(_c_o_n_t_i_n_u_e_d_)_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _P_A_G_E_ _
3.4.10 Goto Statement ........................... 52
3.4.11 Standard Routines abs, succ, pred, chr,
ord ...................................... 52
4. PROCESS COMMUNICATION ................................. 54
4.1 General Process Communication .................... 54
4.2 The Predefined Communication Routines ............ 68
5. PROCESS CONTROL ....................................... 75
5.1 The Predefined Routines for Process Control ...... 75
6. UTILITY PROGRAMS ...................................... 78
6.1 Indent ........................................... 78
6.2 Cross Reference Program .......................... 79
A_P_P_E_N_D_I_X_:
A. REFERENCES ............................................ 81
\f
F_ 1_._ _ _ _ _ _ _ _ _I_N_T_R_O_D_U_C_T_I_O_N_ 1.
This first edition of the PASCAL80 User>s Guide is mainly based
on extracts from earlier PASCAL80 papers such as the Report 1,
and some preliminary introductions, and information published in
Danish under the common little "PASCAL80 NYT".
This manual is directed to those who have previously acquired
some familiarity with computer programming, and now wish to get
acquainted with the programming language PASCAL80. The style of
the manual is that of a tutorial, i.e. a demonstration of the
language features by means of examples.
For a concise ultimate of the language definition the PASCAL80
REPORT 1 may be used and the actual implementations are des-
cribed in xx-PASCAL80-REFERENCE manuals, by now xx is RC3502 and
RC850.
Since PASCAL80 is based directly on Wirth>s Standard Pascal 2
familiarity with that language means that the parts concerning
sequential programs, i.e. most of the declarations and control
statements, may be well known. PASCAL80 can be characterized as
Standard Pascal without files but extended with communication
primitives to be used to connect concurrent process incarnations.
For programmers acquainted with ALGOL, or FORTRAN it may prove
helpful to glance at PASCAL80 in terms of these other languages.
For this purpose we list the following characteristics of
PASCAL80.
1. Declaration of variables is mandatory.
2. Certain key words (e.g. PROCESS, BEGIN) are "reserved" and
cannot be used as identifiers. In this manual they are writ-
ten with capital letters.
3. The semicolon (;) is considered as a statement separator, not
a statement terminator.
4. The standard data types are those of whole numbers, the logi-
cal values, the characters, semaphores, shadows, references,
and pools. The basic data structuring facilities include the
array, the record (corresponding to COBOL>s "structure"),\f
the pool, and the set. These structures can be combined and
nested.
5. The facilities of the ALGOL switch and the computed go to of
FORTRAN are represented by the case statement.
6. The for statement corresponding to the DO loop of FORTRAN,
may only have steps of 1 (TO) or -1 (DOWNTO) and is executed
only as long as the value of the control variable lies within
the limits. Consequently, the controlled statement may not be
executed at all.
7. There are no conditional expressions and no multiple assign-
ments.
8. Procedures and functions may be called recursively.
9. There is no "own" attribute for variables (as in ALGOL).
Parameters are called either by value or by reference;
there is no call by name.
10. The "block structure" differs from that of ALGOL insofar as
there are no anonymous blocks, i.e. each block is given a
name, and thereby is made into a routine.
11. PASCAL80 is equipped with semaphores as a synchronizing tool
and message buffers as a communication tool.
12. Concurrent process incarnations are synchronized by means of
signal-wait primitives.
\f
F_ 2_._ _ _ _ _ _ _ _ _B_A_S_I_C_ _D_E_F_I_N_I_T_I_O_N_S_ 2.
2_._1_ _ _ _ _ _ _ _V_o_c_a_b_u_l_a_r_y_ 2.1
The basic vocabulary consists of language symbols and user
defined symbols. The language symbols are reserved words (key
words) and punctuation marks:
AND ELSE LABEL PROCESS
ARRAY END LOCK RECORD
AS EXPORT MOD REPEAT
BEGIN EXTERNAL NOT SET
BEGINBODY FOR OF THEN
CASE FORWARD OR TO
CHANNEL FUNCTION OTHERWISE TYPE
CONST GOTO PACKED UNTIL
DIV IF POOL VAR
DO IN PREFIX WHILE
DOWNTO INCLUDE PROCEDURE WITH
+ - * / " > < '
<' <= '= ( ) (. .)
= := :=: . , : ; ..
*** (* *) ! ? <* *' #
The user may not use the reserved words in a context other than
that explicit stated in the definition of PASCAL80; in particu-
lar, these words may not be used as identifiers.
2_._2_ _ _ _ _ _ _ _S_y_n_t_a_x_ _D_i_a_g_r_a_m_s_ 2.2
The syntax of PASCAL80 is defined graphically by syntax diagrams.
A syntax diagram consists of arrows, language symbols, and names
of syntax diagrams. A PASCAL80 program is syntactically correct
if it can be obtained by traversing the syntax diagrams. A trav-
ersal must follow the arrows. The name of a syntax diagram indi-
cates a traversal of the corresponding diagram. The result of a
traversal is the sequence of language symbols encountered in the
traversal. \f
The following is an example of a syntax diagram.
while statement:
'WHILE 'expression 'DO 'statement '
The syntax diagram defines the name (while statement) and syntax
of language construct. The name is used when the construct is
referred to elsewhere in the text or in other syntax diagrams.
Language symbols are either names in capital letters (e.g. WHILE)
or punctuation marks (e.g. :=).
Constructs defined by other syntax diagrams are given by their
names in small letters (e.g. expression). To be able to distin-
quish between several occurrences of a construct, its name my be
subscripted.
2_._2_._1_ _ _ _ _ _C_o_m_m_e_n_t_s_ 2.2.1
Comment:
' '(* ' ' '*) ' '
< character<
< non-printing symbol<
'<* ' ' '*' '
< character<
< non-printing symbol<
Comments may be inserted between any two identifiers, numbers or
special symbols. A comment does not affect the execution of the
program.
\f
2_._2_._2_ _ _ _ _ _I_d_e_n_t_i_f_i_e_r_s_ 2.2.2
Names denoting labels, constants, types, variables, processes,
and routines are called identifiers. They must begin with a
letter or an underscore which may be followed by any combination
and number of letters, digits, and underscores. Contrary to
Standard PASCAL all the characters of an identifier are recog-
nized as significant. Small and big letters are handled as being
the same in identifiers.
identifier:
'letter ' ' ' '
' _ ' < letter<
< digit<
< _<
letter is A,B,...,Å,a,b,c,...,å
digit is 0,1,2,...,9
Examples of legal identifiers:
step use _count Local _Message
_ _ _ _ _very _ _ _special _ _ _defined _ _ _identifier
Note: "Local _Message" is identical to "local message",
"LOCAL _MESSAGE", and any other combination of small and big
letters.
2_._2_._3_ _ _ _ _ _N_u_m_b_e_r_s_2.2.3
At label can be either an identifier or a numeric value in
PASCAL80, this is in contrast to Standard Pascal where label is
demanded to be an unsigned integer.
\f
numeric value:
' 'digit ' ' '
<
'#b ' 'binary digit ' '
'#o ' 'octal digit ' '
'#h ' 'hexa digit ' '
binary digits are 0..1
octal digits are 0..7
hexa digits are 0..9 and a..f
Example of legal numbers:
7913 0033 #b101 #hff00 #o7654
2_._2_._4_ _ _ _ _ _S_e_p_a_r_a_t_o_r_s_ 2.2.4
Blanks, nl>s, ff>s and comments are considered as separators.
Separators can appear between any two consecutive language
symbols.
No separator may occur within an identifier, number, numeric
value, or language symbol. At least one separator must appear
between any pair of consecutive identifiers, character strings,
numbers, numeric values, or language symbols.
2_._2_._5_ _ _ _ _ _S_t_r_i_n_g_s_ _o_f_ _C_h_a_r_a_c_t_e_r_s_ 2.2.5
A character string is a sequence of characters enclosed by quote
marks, both single and double guote marks are legal but the end
mark must match the start mark.
\f
Character string:
' '" '-'string character ' '" ' '
<
'> ' 'string character ' '> '
<
String characters are the printable subset of the alphabet,
excluding newline (nl) and form feed (ff), i.e. > >, >!>, ...,> >
Examples of legal strings:
"abcd", " > > is a strange character", >">
Note: If a string surrounded by single quote marks is to contain
a quote mark or a string surrounded by double quote marks is to
contain the surrounding quote mark, then this quote mark is to be
written twice, for example """" is equivalent to >">, and >>>> is
equivalent to ">".
2_._3_ _ _ _ _ _ _ _F_u_n_d_a_m_e_n_t_a_l_ _C_o_n_c_e_p_t_s_ 2.3
This section gives a brief explanation of a few concepts and the
context in which they are used. The complete description of all
PASCAL80 concepts is given in the following sections.
A p_r_o_g_r_a_m_ consists of a number of processes. Each p_r_o_c_e_s_s_ is a
description of some actions and a description of a data struc-
ture. An i_n_c_a_r_n_a_t_i_o_n_ of a process is the execution of the actions
on a private data structure. Many incarnations can be executed
concurrently.
Actions are described by s_t_a_t_e_m_e_n_t_s_. The actions of one incarna-
tion are executed one at a time in the order defined by the
statements. The actions manipulate the data structure, which is
described by a number of v_a_r_i_a_b_l_e_s_. A v_a_r_i_a_b_l_e_ has a name and a
type. The t_y_p_e_ describes the set of values the variable can hold
when the program is executed. There is a number of p_r_e_d_e_f_i_n_e_d_
t_y_p_e_s_ (integer, char, boolean, reference, semaphore, and shadow).
\f
New types are defined either by listing their values or by com-
bining several types into a s_t_r_u_c_t_u_r_e_d_ _t_y_p_e_.
A number of statements and declarations can be combined into a
r_o_u_t_i_n_e_ _d_e_c_l_a_r_a_t_i_o_n_. Activation of a routine is described by
r_o_u_t_i_n_e_ _c_a_l_l_s_ (statement).
Process incarnations communicate by exchanging m_e_s_s_a_g_e_s_. A mes-
sage can be accessed by one incarnation at a time.
place data M await access
in M A to M B
T_i_m_e_ _T_: A has exclusive access to the message M.
M read data
A in M B
T_i_m_e_ _T_ _+_ _1_: B has exclusive access to M.
Variables of the two predefined types reference and semaphore are
used for accessing and exchanging access to messages.
The value of a reference variable is either a reference to a mes-
sage or nil (representing "no reference"). A message can be
accessed through at most one reference variable at a time. Since
process incarnations access messages through reference variables
only, mutually exclusive access to messages is secured.
Incarnations exchange access to messages by means of q_u_e_u_e_ _s_e_m_a_p_-
h_o_r_e_s_. An incarnation places a message in a semaphore from which
another incarnation can get access to it. Variables of type se-
maphore can be declared in any process. A semaphore variable may
be accessible by many incarnations simultaneously.
\f
Processes can be nested and a process which is declared within
another process is a sub-process (of the surrounding process).
An arbitrary number of incarnations of sub-processes (children)
can be created, they are all controlled by the parent.
Incarnations are created and removed dynamically.
A process can have f_o_r_m_a_l_ _p_a_r_a_m_e_t_e_r_s_. When an incarnation of the
process is created a number of a_c_t_u_a_l_ _p_a_r_a_m_e_t_e_r_s_ is given. Incar-
nations communicate through common semaphore variables only. In
this way a process determines the communication paths of sub-pro-
cesses. Note, however, that the controlling process incarnation
need not participate in the comminication.
\f
F_3_._ _ _ _ _ _ _ _ _T_H_E_ _P_A_S_C_A_L_8_0_ _L_A_N_G_U_A_G_E_ 3.
This chapter consists of descriptions of the different compo-
nents of a PASCAL80 process. First an example which shows the
structure of a complete process definition, and after the example
is given a more precise description of the syntactical defini-
tion, of the different parts of the process definition.
3_._1_ _ _ _ _ _ _ _T_h_e_ _P_r_o_c_e_s_s_ _S_t_r_u_c_t_u_r_e_ 3.1
A PASCAL80 process consists of d_e_c_l_a_r_a_t_i_o_n_s_ of constants, types,
variables, routines, labels, and some s_t_a_t_e_m_e_n_t_s_ that operate on
the declared objects.
This is an outline of a PASCAL80 process:
PROCESS catalog;
CONST
idlength = 10;
catalogsize = 256;
TYPE
identifier = ARRAY (1 .. idlength) OF char;
M_m_m_ .
.
P_p_p_ .
VAR
name: identifier;
found: boolean;
index: integer;
FUNCTION hash (id: identifier): integer;
VAR
key, next: integer;
ch: char; \f
BEGIN (* body of function hash *)
key:= 1;
next:= 0;
REPEAT
next:= next + 1;
ch:= id (next);
IF ch <' sp
THEN key:= key * ord (ch) MOD catalogsize + 1;
UNTIL (ch = sp) OR (next '= idlength);
hash:= key;
END; (* of hash *)
M_m_m_ .
.
P_p_p_ .
BEGIN (* main program *)
M_m_m_ .
.
P_p_p_ .
index:= hash (name);
REPEAT
M_m_m_ .
.
P_p_p_ .
found:= ---
M_m_m_ .
.
P_p_p_ .
UNTIL found;
M_m_m_ .
.
P_p_p_ .
END.
The process contains a declaration of
- two contants: idlength with the value 10 and catalogsize with
the value 256
- a type: identifier which is an array of characters
\f
- three variables: name which can hold a value of type identi-
fier, found which can hold a value of type boolean, and index
which can hold an integer.
- a function hash which maps an identifier to an integer.
The function has a formal parameter id and three local variables
key, next, and ch. The assignment statement: index:= hash (name)
contains a call of the function; the result of the function is
assigned to the variable index.
All declared objects have names: catalog, idlength, catalogsize,
identifier, name, found, index, hash, id, key, next, and ch.
These names are defined by declarations before they are used in
statements.
3_._2_ _ _ _ _ _ _ _T_h_e_ _P_r_o_c_e_s_s_ _H_e_a_d_i_n_g_ 3.2
The process heading consists of an identification of the process
to be declared and a parameter description. The process in the
example of section 3.1 has no parameter, the identification is
"catalog".
process heading:
'PROCESS 'process name 'formal parameter '
(formal parameters are described in subsection 3.3.5).
Declarations common to more processes may be defined in a
context, and it may be specified in the call of the compiler
which context(s) to include. The syntax is:
context:
'context name '; 'context declarations '. '
\f
context declarations:
' ' '
<
;
'constant declaration '
'type declaration '
'external routine declaration '
external routine declaration:
' 'procedure heading ' '; external '
'function heading
3_._3_ _ _ _ _ _ _ _T_h_e_ _D_e_c_l_a_r_a_t_i_o_n_ _P_a_r_t_ 3.3
The declarations of a program serves as a description of the data
which are manipulated by the actions performed by the program.
declarations:
' ' ' '
< <
'contstant declaration ' ';
'type declaration '
'variable declaration '
'label declaration '
'routine declaration '
'prefixed process declaration '
'export export part '
The order of declarations is only restricted of the demand for
definition before use.
\f
3_._3_._1_ _ _ _ _ _L_a_b_e_l_ _D_e_c_l_a_r_a_t_i_o_n_ _P_a_r_t_ 3.3.1
A l_a_b_e_l_ is an identification of a statement, it can be either a
number or an identifier. Every label must be declared.
label declaration:
'LABEL ' label ' '
,<
label:
' 'number ' '
'identifier
Example:
LABEL 7913, even _action;
A label is denoted by the identifier or the integer value of the
number. (GOTO statement 3.4.10)
A l_a_b_e_l_ _i_s_ _d_e_f_i_n_e_d_ by a labelled statement.
labelled statement:
'label ': 'statement '
Labels must be defined and used in the scope (not block) where
they are declared. A label may only be defined once in a scope.
Scope is defined in subsection 3.3.5.
example:
error _action: exception (error _code);
\f
3_._3_._2_ _ _ _ _ _C_o_n_s_t_a_n_t_s_ _D_e_f_i_n_i_t_i_o_n_ _P_a_r_t_ 3.3.2
If a value is used serveral times in a program, it is useful to
declare a constant with this value. In the program the constant
is used to denote the value.
constant declaration:
CONST ' 'constant name '= 'constant expression ' '
;<
The constant expression is an expression the value of which may
be computed at compile time, i.e. each operand must be a constant
or a symbolic value. A very convenient feature of PASCAL80 is the
so-called structured value which may be used for defining
constants and for initialization of structured variables.
structured value:
' 'character string ' '
'set '
'type name '( 'value list ') '
value list:
' ' 'unit ' ' '
'repetition '*** 'unit
,<
Units of a value list are given one at a time (separated by ,) or
by repeating a unit. The value of repetition specifies how many
times the unit is repeated.
\f
A structured value is built as follows:
- type name denotes a record type:
There must be a unit for each field and the first field gets
the value of the first unit, the second field the value of the
second unit etc. The repetition cannot be used.
- type name denotes an array type:
There must be a unit for each element and the first element
gets the value of the first unit, the second element the value
of the second unit etc.
repetition:
'constant expression '
unit:
' 'constant expression ' '
'?
The unit "?" specifies n_o_ _v_a_l_u_e_, i.e. the component is skipped,
its type is compatible with any type. This element is necessary
to specify values of components which have no symbolic represen-
tation, e.g. values of shielded types. The no value element can
only be used in value lists.
Example:
CONST
catalogsize = 256;
test = true;
nul = 0;
If these values are changed, only the constant declaration needs
to be changed.
\f
3_._3_._3_ _ _ _ _ _V_a_r_i_a_b_l_e_ _D_e_c_l_a_r_a_t_i_o_n_ _P_a_r_t_ 3.3.3
A declaration of a variable must specify the name and type of the
variable.
variable declaration:
'VAR ' 'variable name list ': 'type ' 'initialization ' ' '
'
;<
variable declaration
' 'variable name ' '
,<
initialization:
':= 'constant expression '
The type of the expression must be compatible with the type of
the variable.
The value specified by the constant expression becomes the ini-
tial value of all variables in the variable name list.
Example:
VAR
found: boolean:= false;
index: 1 .. catalogsize;
name: identifier:= identifier (idlength***sp);
\f
The type defines which values a variable can hold. The variable
found can hold the boolean values false and true, the initial
value is false. The variable index can hold an integer in the
range 1 to 256 (catalogsize = 256) the value of index is unde-
fined until first assignment. The value of a variable is changed
by an assignment:
found:= true;
index:= index MOD catalogsize + 1;
3_._3_._4_ _ _ _ _ _T_y_p_e_ _D_e_f_i_n_i_t_i_o_n_ _P_a_r_t_ 3.3.4
All data which is manipulated by a PASCAL80 program has a type.
All operands (variables, constants, values etc.) have a fixed
type and for each operator and statement there are strict rules
defining which types of operands it accepts.
3_._3_._4_._1_ _ _ _T_y_p_e_s_ 3.3.4.1
A_ _t_y_p_e_ _i_s_ _a_ _s_e_t_ _o_f_ _v_a_l_u_e_s_ _a_n_d_ _a_ _m_e_t_h_o_d_ _o_f_ _a_c_c_e_s_s_i_n_g_ _t_h_e_s_e_ _v_a_l_u_e_s_.
There is a number of predefined types: integer, char, boolean,
semaphore, reference, and shadow. New types are named and defined
by type declarations.
type declaration:
'TYPE ' 'type name '=type ' '
;<
\f
type:
' 'enumeration type ' '
'shielded type '
'pointer type '
'structured type '
'named type '
'frozen type
Type declarations may not be recursive, except in a type declara-
tion:
TYPE name = t;
where t may contain the pointer type name as an element or
field type;
E_n_u_m_e_r_a_t_i_o_n_ _T_y_p_e_s_
An e_n_u_m_e_r_a_t_i_o_n_ _t_y_p_e_ consists of a finite, totally ordered set of
values. Furthermore, there is a mapping from the set of values to
the integers.
enumeration type:
' 'char ' '
'boolean '
'integer '
'scalar type '
'subrange type '
The three predefined types char, boolean, and integer are
described below.
S_c_a_l_a_r_ _T_y_p_e_s_
A s_c_a_l_a_r_ _t_y_p_e_ is a sequence of values (scalar constants). A
scalar type is declared by listing its values in increasing
order.
scalar type:
'( ' 'scalar constant ' ') '
,<
\f
scalar constant:
'identifier '
A s_c_a_l_a_r_ _c_o_n_s_t_a_n_t_ is an identifier appearing in the declaration
of a scalar type T. The type of the scalar constant is T. Con-
M_M_m_ sider the following scalar type (e , e , ... e , e , ... e ),
P_P_p_ 0 1 n n+1 N
M_M_m_ then e is the p_r_e_d_e_c_e_s_s_o_r_ of e and e is the s_u_c_c_e_s_s_o_r_ of e
P_P_p_ n-1 n n+1 n
M_M_m_ the o_r_d_i_n_a_l_ _v_a_l_u_e_ of e is n. The predecessor of e and the
P_P_p_ n 0
M_M_m_ successor of e are undefined.
P_P_p_ N
Example:
TYPE
device = (drum, tape, disk);
The type device has the values drum, tape, and disk.
T_h_e_ _T_y_p_e_ _C_h_a_r_
The type c_h_a_r_ is a predefined enumeration type. Its values are
the (Danish) ISO characters.
_ _ _ _ _ _0_ _ _ _ _1_ _ _ _ _2_ _ _ _ _3_ _ _ _ _4_ _ _ _ _5_ _ _ _ _6_ _ _ _ _7_ _ _ _ _8_ _ _ _ _9_ _ _ _ _ _
0 nul soh stx etx eot enq ack bel bs ht
10 nl vt ff cr so si dle dc1 dc2 dc3
20 dc4 nak syn etb can em sub esc fs gs
30 rs us sp ! " % & >
40 ( ) * + , - . / 0 1
50 2 3 4 5 6 7 8 9 : ;
60 < = ' ? @ A B C D E
70 F G H I J K L M N O
80 P Q R S T U V W X Y
90 Z Æ Ø Å _ a b c
100 d e f g h i j k l m
110 n o p q r s t u v w
120 x y z æ ø å del
\f
The characters are numbered and the ordinal number of a character
is the sum of its row and column number in the above table. The
ordinal values define the ordering of the characters.
> > (sp), >!> >">, ... > > are printing characters.
T_h_e_ _T_y_p_e_ _B_o_o_l_e_a_n_
The type b_o_o_l_e_a_n_ is a predefined scalar type, defined as:
TYPE boolean = (false, true);
S_u_b_r_a_n_g_e_ _T_y_p_e_s_
A type can also be declared as a_ _s_u_b_r_a_n_g_e_ of an already defined
type.
A subrange type is a sub-sequence of an enumeration type.
subrange type:
'min bound '.. 'max bound '
min bound, max bound:
'expression '
The min and max bounds must be of the same enumeration type.
example:
TYPE
index = 1 .. catalogsize;
small _letters = "a" .. "å";
byte = 0 .. 255;
These declarations restrict the set of values of the type to the
specified range.
\f
S_t_r_u_c_t_u_r_e_d_ _T_y_p_e_s_
A structured type is a composition of other types. There are
three kinds of structured types: array, record, and set.
structured type:
' ' ' 'array type ' '
'PACKED 'record type '
'set type '
A structured type has a number of c_o_m_p_o_n_e_n_t_ _t_y_p_e_s_.
A_r_r_a_y_ _T_y_p_e_s_
An a_r_r_a_y_ consists of a number of elements of the same type. The
number of elements is specified by an index type.
array type:
'ARRAY '( ' 'index type ' ') 'OF 'element type '
,<
index type, element type:
'type '
The index type must be an enumeration type or the name of an
enumeration type.
Example:
TYPE
identifier = ARRAY (1 .. idlength) OF char;
count = ARRAY (letters) OF integer;
VAR
id: identifier;
\f
The elements of the array "id" have indices from 1 to 10 (idlength).
The value of an element can be changed:
id (5):= "x";
An array value (whole array) can also be constructed and
manipulated:
CONST
blank = " ";
.
.
.
IF id <' blank
THEN ...
Then array type
M_M_m_ ARRAY (t ,t ) OF t
P_P_p_ 1 2 3
is a shorthand for the type
M_M_m_ ARRAY (t ) OF ARRAY (t ) OF t .
P_P_p_ 1 2 3
This is a m_u_l_t_i_-_d_i_m_e_n_s_i_o_n_a_l_ array. The number of index types is
the d_i_m_e_n_s_i_o_n_ of the array.
The name of an array variable denotes the whole array. An element
is accessed by the array variable followed by an index enclosed
in parentheses. An index consists of a number of index expres-
sions. The number of index expressions must be less than or equal
to the dimension of the array.
If the element type itself is structured, the c_o_m_p_o_n_e_n_t_ _t_y_p_e_s_ _o_f_
t_h_e_ _a_r_r_a_y_ _t_y_p_e_ are the component types of the element type.
\f
array variable:
'variable ' ' '
'indec selector
index selector:
'( ' 'index expression ' ') '
,<
index expression:
'expression '
The type of each index expression must be compatible with the
corresponding index type.
R_e_c_o_r_d_ _T_y_p_e_s_
A r_e_c_o_r_d_ consists of a number of fields. Each f_i_e_l_d_ has a name
and a type.
record type:
'RECORD 'field list 'END '
field list:
' 'field name list ': 'field type ' ' '; ' '
;< '
field name list:
' 'field name ' '
,<
\f
Example:
TYPE
catalogentry = RECORD
id: identifier;
hashkey: integer;
medium: device;
addr: range;
END;
VAR
element: catalogentry;
The record of type catalogentry has four fields: id, hashkey,
medium, and addr. These fields are of the type identifier,
integer, device, and range respectively. The value of a field can
be changed or read:
element.medium:= drum;
IF element.id (1) <_ "a" THEN ...
Values of record type are structured values (see subsection
3.4.1):
element:= catalogentry (blank, 0, drum, 16712);
S_e_t_ _T_y_p_e_s_
The values of a s_e_t_ _t_y_p_e_ are the subset of some enumeration type.
set type:
'SET 'OF 'element type '
element type:
'type '
The element type must be an enumeration type or the name of an
enumeration type.
\f
A s_e_t_ _e_l_e_m_e_n_t_ is a value of the element type. The component type
of a set is the element type.
Values of set type are written as a list of set elements.
set:
'(. ' ' 'element list ' ' '.) '
,<
'
element list:
' 'element ' '
M_M_m_ 'element '.. 'element
P_P_p_ 1 2
element:
'expression '
All elements in a set must be of the same type and these must all
be compatible with the element type. The empty set is denoted
(..). The type of (..) is compatible with any set type.
A variable of type set can be given a value:
digits:= (. "0" .. "9".);
The operators on set operands are + (union), * (intersection),
- (difference), and IN (membership).
\f
Example:
TYPE
characters = SET OF char;
VAR
digits, letters: characters;
FUNCTION nextid: identifier;
VAR
i: 1 .. idlength;
ch: char;
BEGIN (* body of nextid *)
i:= 1;
nextid:= blank;
ch:= getchar;
IF ch IN letters THEN
WHILE (ch IN (letters + digits)) AND (i <= idlength) DO
BEGIN
nextid (i):= ch;
i:= i + 1;
ch:= getchar;
END;
END; (* of nextid *)
(Note, getchar is not a PASCAL80 primitive).
As the above examples show, a type (predefined or programmer
defined) can be used for constructing values of the type,
defining constants, and declaring variables.
P_o_i_n_t_e_r_ _T_y_p_e_s_
The values of pointer type are pointers to variables or nil (no
pointer).
pointer type:
' 'type '
\f
The value nil belongs to every pointer type; it does not point to
any variable.
Assignments can be made to variables of pointer types.
The variable pointed to by a pointer (value) is denoted by a
variable of pointer type followed by an arrow ( ).
For the use of pointer variables and pointer types see the
example in section 4.2 (under "ref").
F_r_o_z_e_n_ _T_y_p_e_s_
In PASCAL80 the programmer has the possibility of declaring vari-
ables and parameters as "read only" i.e. the variable/parameters
cannot be changed inside the process/routine with the read-only
declaration.
frozen type:
'! 'base type '
base type:
'type '
A variable of a frozen type must not be used as the lefthand side
of an assignment, in an exchange statement, or as a variable
parameter, unless the formal parameter is of the same frozen
type!
A frozen type is compatible with its base type. The component
types of a frozen type are the component types of the base type.
S_h_i_e_l_d_e_d_ _T_y_p_e_s_
Variables of s_h_i_e_l_d_e_d_ _t_y_p_e_s_ enable a process incarnation to
communicate with and control other incarnations.
\f
shielded type:
' 'reference ' '
'semaphore '
'shadow '
'pool type '
The values of shielded types cannot be accessed directly. They
are protected against malicious or accidental misuse. Therefore,
the assignment statement cannot be applied to variables of
shielded types. The exhange statement is provided instead (see
subsection 3.4.3).
T_h_e_ _T_y_p_e_ _R_e_f_e_r_e_n_c_e_
The values of type r_e_f_e_r_e_n_c_e_ are references to messages or nil
(no reference). A message is always accessible through exactly
one reference variable.
The syntax used to denote the accessible fields of a message
header is derived from considering the type reference as a
predefined pointer type (see section 5.3):
TYPE reference = message;
The type of the message header is:
TYPE
message = RECORD (*message header*)
size, messagekind: !integer;
u1, u2, u3, u4: 0..255;
(*owner, answer: semaphore;
data: message data;
other implementation dependent fields*)
END;
\f
The interpretation of s_i_z_e_ and m_e_s_s_a_g_e_k_i_n_d_ is i_m_p_l_e_m_e_n_t_a_t_i_o_n_
d_e_p_e_n_d_e_n_t_. The owner, answer, and data fields cannot be used
directly.
M_e_s_s_a_g_e_s_
Process incarnations communicate by exchanging access to messages
which hold data. When a process has access to a message it can
place data in or read data from the message. A message can be
accessed by one incarnation at a time (see section 2.3)
A message consists of a m_e_s_s_a_g_e_ _h_e_a_d_e_r_ and m_e_s_s_a_g_e_ _d_a_t_a_ (possibly
empty). A h_e_a_d_e_r_ _m_e_s_s_a_g_e_ is a message with no message data.
T_h_e_ _T_y_p_e_ _S_e_m_a_p_h_o_r_e_
A q_u_e_u_e_ _s_e_m_a_p_h_o_r_e_ consists of a sequence (fifo) of messages and a
set of waiting process incarnations. One of these is always
empty. The values of type semaphore are queue semaphores.
The semaphore is o_p_e_n_ when the set of waiting incarnations is
empty and the sequence of messages in non-empty. When the
sequence is empty and the set of waiting incarnations is none-
empty, the semaphore is l_o_c_k_e_d_. If both are empty, the semaphore
is p_a_s_s_i_v_e_.
These concepts are described in details in the sections concern-
ing process communication (chapter 4).
Variables of type semaphore (or variables with semaphore compo-
nents) are restricted only to be declared in the declarations of
a process and not in the declarations of a routine.
T_h_e_ _T_y_p_e_ _S_h_a_d_o_w_
The values of type s_h_a_d_o_w_ are references to process incarnations
or nil (no reference). Initially, a shadow variable is nil.
\f
A shadow variable is given a value by creating a new incarnation.
The incarnation is controlled through the shadow variable.
The predefined routines for controlling incarnations are des-
cribed in the sections concerning process control (chapter 5).
P_o_o_l_ _T_y_p_e_s_
A p_o_o_l_ consists of a number of messages.
pool type:
'POOL 'cardinality ' 'OF 'type ' '
'
cardinality:
'expression '
Initially a pool consists of a number of messages. The number is
the value of cardinality (expression) which must be a positive
integer. Each of the messages can hold a value from type. If no
type is specified, the messages have headers only.
With each variable of type pool an anonymous semaphore is asso-
ciated. This is the owner semaphore of all messages in the pool.
A message is allocated from the pool by the predefined procedure
alloc (see chapter 4).
3_._3_._4_._2_ _ _ _T_y_p_e_ _C_o_m_p_a_t_i_b_i_l_i_t_y_ 3.3.4.2
In PASCAL80 any operand has a fixed type which can be determined
statically. The type of constants, variables, and formal parame-
ters is specified in their declaration. \f
CONST
length = 16;
TYPE
word = ARRAY (0 .. length - 1) OF boolean;
CONST
nul = word (length *** false);
VAR
status: word;
The constant length is of type integer. The construct
"word (length *** false)" is a value of type word where all
elements are false. The constant nul and the variable status are
both of type word.
The type of an expression is determined by the types of its
operands and the way they are combined by operators. The addition
of two integers, i.e. length + 1, gives a result of type integer,
comparison of two integers, i.e. j <= length, gives a result of
type boolean, conjunction of two booleans gives a boolean result,
i.e. found AND (j <= length) etc. The operator AND can only be
applied to boolean operands, the operator / can only be applied
to integer operands etc. Similar restrictions are put on the
operands used in all other constructs. In a while statement, for
example, an expression of type boolean must be given:
WHILE found AND (j <= length) DO ...
A value of some type T can be assigned to a variable of the same
type.
status:= nul;
T_h_e_ _t_y_p_e_s_ _o_f_ _t_w_o_ _o_p_e_r_a_n_d_s_ _a_r_e_ _t_h_e_ _s_a_m_e_ _o_n_l_y_ _i_f_ _t_h_e_i_r_ _t_y_p_e_ _n_a_m_e_s_
(_i_d_e_n_t_i_f_i_e_r_s_)_ _a_r_e_ _t_h_e_ _s_a_m_e_,_ _o_r_ _t_h_e_ _t_w_o_ _o_p_e_r_a_n_d_s_ _a_r_e_ _d_e_c_l_a_r_e_d_ _i_n_
t_h_e_ _s_a_m_e_ _l_i_s_t_.
\f
VAR
status: word;
mask : word;
result: ARRAY (0 .. length - 1) OF boolean;
trap : ARRAY (0 .. length - 1) OF boolean;
rec1, rec2: record ... end;
The types of status and mask are the same, but none of them are
the same as the type of result. Consequently:
status:= mask;
is a valid assignment, but
status:= result;
is not a valid assignment. Furthermore, the type of trap is
neither the same as the type of result nor the same as the type
of status and mask. And the operands rec1 and rec2 are of the
same type.
M_M_m_ The type t is c_o_m_p_a_t_i_b_l_e_ with the type t if:
P_P_p_ 1 2
M_M_m_ - t and t are the same named type
P_P_p_ 1 2
M_M_m_ - t is a subrange or t or t is a subrange of t
P_P_p_ 1 2 2 1
M_M_m_ - t is SET OF b and t is SET OF b and
P_P_p_ 1 1 2 2
M_M_m_ b is compatible with b
P_P_p_ 1 2
M_M_m_ - t is ! t
P_P_p_ 1 2
M_M_m_ - t is t and t is t where t is a type name
P_P_p_ 1 2
M_M_m_ - t and t are of pool type
P_P_p_ 1 2
Note, that the relation compatible is not symmetric. If the type
M_M_m_ t is compatible with the type t , a value of type t can be
P_P_p_ 1 2 1
M_M_m_ assigned to a variable of type t .
P_P_p_ 2 \f
3_._3_._5_ _ _ _ _ _R_o_u_t_i_n_e_ _D_e_c_l_a_r_a_t_i_o_n_ _P_a_r_t_ 3.3.5
A number of statements and declarations can be combined into a
routine. When the routine is called, the data structure defined
by the declarations is allocated and the statements are executed.
A routine is either a procedure or a function.
routine declaration:
' 'procedure heading ' '; 'block '
'function heading
procedure heading:
'PROCEDURE 'procedure name 'formal parameters '
function heading:
'FUNCTION 'function name 'formal parameters ':type '
The type of a function cannot be a shielded type.
F_o_r_m_a_l_ _P_a_r_a_m_e_t_e_r_s_
The f_o_r_m_a_l_ _p_a_r_a_m_e_t_e_r_s_ specify the interface between a block and
the surrounding. For each formal parameter is given its kind,
formal name, and type.
formal parameters:
' ' '
'( ' 'parameter description ' ')
;<
parameter description:
' ' 'formal name list ': 'type ' '
'VAR
\f
formal name list:
' 'formal name ' '
,<
If VAR is specified the parameter is of kind variable: a v_a_r_
p_a_r_a_m_e_t_e_r_; otherwise the parameter is of kind value: a v_a_l_u_e_
p_a_r_a_m_e_t_e_r_.
A formal parameter is used as a declared variable of the speci-
fied name and type.
Parameters with components of shielded type must be of kind vari-
able.
Example:
TYPE
parity = (even, odd);
frame = 0 .. 31;
FUNCTION frame _parity (arg: frame): parity;
CONST
table = (. 0,3,5,6,9,10,12,15,
17,18,20,23,24,27,29,30 .);
(* The set table contains all values of type
frame with even parity *)
BEGIN
IF arg IN table
THEN frame _parity:= even
ELSE frame _parity:= odd;
END;
A routine can have local declarations as in this case the con-
stant table. A function returns a result, this result is the
value assigned to the funcion name, e.g. frame _parity:= even. The
function has a parameter with the name arg and the type frame.
The type of the result is parity.
\f
Routine declarations can be nested:
TYPE
parity = (even, odd);
byte = 0 .. 255;
FUNCTION byte _parity (arg: byte) : parity;
TYPE
frame = 0 .. 31;
FUNCTION frame _parity (arg: frame) : parity;
CONST
table = (. 0,3,5,6,9,10,12,15,
17,18,20,23,24,27,30 .);
BEGIN (* frame parity *)
IF arg IN table
THEN frame _parity:= even
ELSE frame _parity:= odd;
END;
BEGIN (* byte parity *)
IF frame _parity (arg MOD 32) = frame _parity (arg DIV 32)
THEN byte _parity:= even
ELSE byte _parity:= odd;
END;
The declaration of a name in a routine is only valid inside the
routine. Outside the routine it is invisible. The constant table
can therefore only be applied in the function frame _parity where
it is declared. But it cannot be applied in the function
byte _parity. Similarly, the type frame is not known outside
byte _parity. It can, however, be applied in inner routines such
as the function frame _parity. The exact rules about valid con-
texts for a variable are called the scope rules (see the next
subsection).
\f
The scope rules require that a process or routine is declared
before it is used. A declaration where the block is a forward
block is an announcement of a routine or process declaration
which is given textually later, this is a f_o_r_w_a_r_d_ _d_e_c_l_a_r_a_t_i_o_n_.
The heading of the declaration must be the same as the heading
given in the forward declaration. That is the name, type, and
order of the formal parameters must be the same.
3_._3_._5_._1_ _ _ _S_c_o_p_e_ _R_u_l_e_s_ 3.3.5.1
A scope is one of the following:
- a field list excluding inner scopes,
- a process or routine heading excluding inner scopes,
- a block excluding inner scopes,
- a prefix excluding inner scopes,
- a local declaration (in a lock statement) excluding inner scopes.
A name can be declared once in each scope only. All names must be
declared before they are used. If a name is declared both in a
scope and in an inner scope, it is always the inner declaration
which is effective in the inner scope.
Generally the declaration of a name is effective in the rest of
the block where it is declared. Further details for each kind of
name is given below.
c_o_n_s_t_a_n_t_ _n_a_m_e_, t_y_p_e_ _n_a_m_e_, v_a_r_i_a_b_l_e_ _n_a_m_e_, and r_o_u_t_i_n_e_ _n_a_m_e_: The
declaration of these names is effective in the rest of the block
excluding inner process blocks.
f_i_e_l_d_ _n_a_m_e_: The declaration of a field name is effective in the
rest of the block excluding inner process blocks. But the field
name can be used in record variables and with-statements only.
\f
s_c_a_l_a_r_ _c_o_n_s_t_a_n_t_: The declaration of a scalar constant name is
effective in the rest of the block excluding inner process
blocks. But used in a type definition of a fieldname the constant
name can be used in with-statements only.
l_a_b_e_l_: The declaration of a label is effective in the scope where
it is declared.
r_o_u_t_i_n_e_ _p_a_r_a_m_e_t_e_r_ _n_a_m_e_ (implicit and explicit): The declaration
of a routine parameter name is effective in the routine block.
Note that the declaration is not effective in the routine
heading.
p_r_o_c_e_s_s_ _n_a_m_e_: The declaration of a process name is effective in
the rest of the block where it is declared excluding inner pro-
cess blocks.
3_._3_._5_._2_ _ _ _R_o_u_t_i_n_e_ _B_l_o_c_k_s_ 3.3.5.2
Within the block of a routine a recursive call of the routine can
be made.
Processes, exception routines, and variables with semaphore or
pool components cannot be declared in a routine block.
3_._3_._5_._3_ _ _ _F_u_n_c_t_i_o_n_s_ 3.3.5.3
A function name may appear as a variable on the left head side of
an assignment. The type in the function heading is the f_u_n_c_t_i_o_n_
t_y_p_e_, it specifies the range of the function. The value of a
function is the dynamically last value assigned to the function
variable.
\f
function variable:
'function name '
3_._3_._6_ _ _ _ _ _E_x_p_o_r_t_ _P_a_r_t_ 3.3.6
Export part is an implementation dependent feature which may open
for special linkage editor facilities (see chapter 4).
export part:
'EXPORT ' 'export name '= 'exp.kind 'simple variable' '
;<
exp.kind:
' 'VALUE ' '
'DISP '
'SIZE ' N_o_t_e_:
'ADDRESS ' The five words for exp.kind
'OFFSET ' are not reserved words!
VALUE is for constants only
DISP is for fields only and means displacement relative to
record start
SIZE is for constants, entire variables, and fields. SIZE
means size (in bytes) of the type which is associated
to the "simple variable"
ADDRESS indicates absolute address
OFFSET indicates relative offset in current stack frame
\f
simple variable:
'simple var name ' ' '
field name< .<
simple var name can be either a constant name or a variable name.
3_._4_ _ _ _ _ _ _ _T_h_e_ _S_t_a_t_e_m_e_n_t_ _P_a_r_t_ 3.4
This section contains subsections describing the syntax and the
use of the different statements which are included in the
language. Most of the statements are also found in Standard
PASCAL and may be well known language elements.
3_._4_._1_ _ _ _ _ _S_t_a_t_e_m_e_n_t_s_ 3.4.1
The statements of a process describe the actions which are exe-
cuted by a process incarnation. These statements are collected in
a compound statement.
compound statement:
'BEGIN ' 'statement ' 'END '
;<
The statements are executed one at a time in the specified order.
Below, all statement forms are given together with references to
their precise description:
\f
statement: section
' ' '
'compound statement ' 3.4.1
'procedure call ' 3.4.6
'assignment statement ' 3.4.2
'exchange statement ' 3.4.3
'case statement ' 3.4.5
'for statement ' 3.4.4
'if statement ' 3.4.5
'repeat statement ' 3.4.4
'while statement ' 3.4.4
'with statement ' 3.4.7
'goto statement ' 3.4.10
'labelled statement ' 3.4.10
'lock statement ' 3.4.8
'channel statement ' 3.4.9
3_._4_._2_ _ _ _ _ _A_s_s_i_g_n_m_e_n_t_ _S_t_a_t_e_m_e_n_t_ 3.4.2
assignment statement:
'variable ':= 'expression '
The type of the variable must be compatible with the type of the
expression.
Assignments can be made to a variable of:
- a simple type,
- a pointer type,
- a structured type where all components are of a
simple type or a pointer type.
The assignment statement replaces the current value of the vari-
able by the value of the expression.
\f
E_x_p_r_e_s_s_i_o_n_s_ describe how values are computed. Expressions are
evaluated from left to right using the following precedence
rules:
NOT has the highest precedence followed by
*, /, DIV, MOD, AND followed by
+ , - , OR followed by
=, <', <, <=, ', '=, IN
expression:
'simple expression ' ' '
'=---'--'simple expression
' <' '
' < '
' <= '
' ' '
' '= '
' IN '
simple expression
' ' ' 'term ' '
' + ' < + <
' - ' < - <
< OR <
term:
' 'factor ' '
< *<
< /<
< DIV<
< MOD<
< AND<
\f
N_o_t_e_: All factors in an expression are evaluated.
Factor:
' 'operand ' ' '
'( 'expression ) '
'NOT 'factor '
operand:
' 'variable ' '
'value
V_a_r_i_a_b_l_e_s_
The term variable includes declared variables, formal parameters,
and function variables. All variables are denoted by their name
and possibly a selector.
variable:
' 'variable name ' '
'function variable '
'formal name '
'array variable '
'record variable '
'pointed variable '
array
record variables are described in subsection 3.3.4
pointed
function variables are described in subsection 3.3.5.3
\f
Variables of shielded and pointer types are implicitly given the
following initial values:
semaphore: passive
shadow: nil
reference: nil
pool: a number of messages, determined by the cardinality
expression; the contents of these messages are unde-
fined
pointer: nil
3_._4_._3_ _ _ _ _ _E_x_c_h_a_n_g_e_ _S_t_a_t_e_m_e_n_t_ 3.4.3
exchange statement:
'variable ':=: 'variable '
The two variables must either both be of type reference or both
be of type shadow.
The exchange statement exchanges the values of the two variables.
3_._4_._4_ _ _ _ _ _R_e_p_e_t_i_t_i_v_e_ _S_t_a_t_e_m_e_n_t_s_ 3.4.4
R_e_p_e_a_t_ _S_t_a_t_e_m_e_n_t_
repeat statement:
'REPEAT ' 'statement ' 'UNTIL 'expression '
;<
The result of the expression must be of type boolean.
The statement sequence is executed one or more times. Every time
the sequence has been executed, the expression is evaluated, when
the result is true the repeat statement is completed.
\f
W_h_i_l_e_ _S_t_a_t_e_m_e_n_t_
while statement:
'WHILE 'expression 'DO 'statement '
The result of the expression must be of type boolean.
The statement is executed a number of times (possibly zero). The
expression is evaluated before each execution, when the result is
false, the while statement is completed.
F_o_r_ _S_t_a_t_e_m_e_n_t_
for statement:
'FOR 'variable ':= 'for list 'DO 'statement '
for list:
'TO '
M_M_m_ 'expression ' 'expression '
P_P_p_ 1 2
U_U_u_ --'DOWNTO-'
The two expressions must be of the same enumeration type and the
type of the variable must be compatible with this.
The selection of the variable cannot be changed in the statement.
Hence, if the variable has array indices or pointers, changes to
these (in the statement) will not affect the selection.
The statement is executed with consecutive values of the variable
The ordinal value of the variable can either be incremented (in
M_M_m_ steps of 1 (succ)) from expression TO expression , or descrem-
P_P_p_ 1 2
M_M_m_ ted (in steps 1 (pred)) from expression DOWNTO expression . The
P_P_p_ 1 2
two expressions are evaluated once, before the repetition. If the
M_M_m_ value of expression is greater than the value of expression and
P_P_p_ 1 2
TO is specified, the statement is not executed.
\f
M_M_m_ Similarly, if the value of expression is less than the value of
P_P_p_ 1
M_M_m_ expression and DOWNTO is specified, the statement is not execu-
P_P_p_ 2
ted.
The value of the variable is dependent of the expressions after
the for statement.
3_._4_._5_ _ _ _ _ _C_o_n_d_i_t_i_o_n_a_l_ _S_t_a_t_e_m_e_n_t_s_ 3.4.5
C_a_s_e_ _ _S_t_a_t_e_m_e_n_t_
case statement:
'CASE 'switch OF ' 'case list element 'end part '
;<
end part:
' ' 'END '
'OTHERWISE ' 'statement '
;<
case list element:
' ' ' 'constant expression ' ' ': statement ' '
'constant expression '.. 'constant expression
,<
'
switch:
'expression '
\f
The values of the constant expressions in case list elements are
called c_a_s_e_ _l_a_b_e_l_s_. All case labels and the switch must be of the
same enumeration type and all case labels must be distinct. The
switch is evaluated and the statement labelled by the value of
the switch is executed. If no such label is present, the state-
ment following OTHERWISE is executed; if OTHERWISE is not speci-
fied, an exception occurs.
I_f_ _S_t_a_t_e_m_e_n_t_
if statement:
M_M_m_ 'IF 'expression 'THEN 'statement ' 'ELSE 'statement ' '
P_P_p_ 1 2
U_U_u_ '
The result of the expression must be of type boolean.
M_M_m_ Statement is executed if the value of the expression is true. If
P_P_p_ 1
M_M_m_ it is false, statement (if specified) is executed.
P_P_p_ 2
The statement:
M_M_m_ IF e THEN IF e THEN s ELSE s
P_P_p_ 1 2 1 2
is equivalent to:
M_M_m_ IF e
P_P_p_ 1
THEN BEGIN
M_M_m_ IF e
P_P_p_ 2
M_M_m_ THEN s
P_P_p_ 1
M_M_m_ ELSE s
P_P_p_ 2
U_U_u_ END
\f
3_._4_._6_ _ _ _ _ _P_r_o_c_e_d_u_r_e_ _C_a_l_l_ 3.4.6
routine call:
'routine name 'actual parameters '
A r_o_u_t_i_n_e_ _c_a_l_l_ binds actual parameters to formal parameters,
allocates local variables, and executes the compound statement of
the block. When the compound statement is completed, local vari-
ables are deallocated and execution is resumed immediately after
the routine call. All local reference and shadow variables must
be nil when the compound statement is completed, otherwise an
exception occurs.
The variables of a routine are associated with a specific call;
they exist from the routine call until the compound statement (of
the block) is completed. When a routine is called recursively,
several versions of the variables exist simultaneously, one for
each uncompleted call.
The difference between a procedure and a function is that a pro-
cedure call is a statement and a function call a factor (function
variable) in an expression.
A f_u_n_c_t_i_o_n_ _c_a_l_l_ is an operand in an expression.
function call:
'function name 'actual parameters '
A_c_t_u_a_l_ _P_a_r_a_m_e_t_e_r_s_
When a process incarnation is created or a routine is called
a_c_t_u_a_l_ _p_a_r_a_m_e_t_e_r_s_ are bound to formal parameters.
actual parameters:
' ' '
'( ' 'actual parameter ' ')
,< \f
actual parameter:
'expression '
There must be an actual parameter for each explicit formal para-
meter.
The binding of an actual parameter to a formal parameter depends
on the parameter kind:
value: The type of the actual parameter must be compatible
with the type of the formal parameter. The value of the
actual parameter is evaluated and this value becomes
the initial value of the formal parameter. Assignments
to the formal parameter within the block does not
affect the actual parameter (call by value).
variable: The type of the actual and formal parameter must be the
same. The actual parameter must be a variable, the
value of this variable becomes the initial value of the
formal parameter. Changes to the value of the formal
parameter within the block affects the actual parameter
directly.
The actual parameter selects a variable, this selection
cannot be changed in the block. Hence, if the variable
has array indices or pointers, changes to these do not
affect the selection (c_a_l_l_ _b_y_ _r_e_f_e_r_e_n_c_e_).
An element or a field of a packed variable cannot be an
actual var parameter. The w_h_o_l_e_ packed variable can,
however, be an actual var parameter.
\f
3_._4_._7_ _ _ _ _ _W_i_t_h_ _S_t_a_t_e_m_e_n_t_ 3.4.7
with statement:
'WITH ' 'record variable ' 'DO 'statement '
,<
Within the statement fields can be accessed by giving their field
names only.
The with statement
WITH v1, v2, ..., vn DO s;
is a shorthand for the nested with statement shown below.
WITH v1 DO
WITH v2 DO
.
.
.
WITH vn DO s;
The record variable selects a record, this selection cannot be
changed in the statement. Hence, if the record variable has array
indices or pointers, changes to these (in the statement) will not
affect the selection.
3_._4_._8_ _ _ _ _ _L_o_c_k_ _S_t_a_t_e_m_e_n_t_ 3.4.8
lock statement:
'LOCK 'reference variable 'AS 'local declaration 'DO 'statement '
local declaration:
'local name ': 'type '
\f
reference variable:
'variable '
local name:
'identifier '
The component types of the type must be simple. The reference
variable must refer to a message (must not be nil), otherwise an
exception occurs. If the message is too small to represent the
specified type an exception occurs.
In the statement local name is a declared variable with the
specified type. In the statement the reference variable must not
be used as part of an exchange statement or as a parameter to
signal, return, release, pop, or push.
The data part of a message is manipulated as a declared variable
with the local name. It is always the top in the message stack
which is manipulated.
3_._4_._9_ _ _ _ _ _C_h_a_n_n_e_l_ _S_t_a_t_e_m_e_n_t_ 3.4.9
channel statement:
'CHANNEL 'reference variable 'DO 'statement '
The reference variable must refer to a message (must not be nil).
Any implementation may place restrictions on this message. If the
message is not of this restricted form an exception occurs.
In the statement the reference variable must not be used as part
of an exchange statement or as a parameter to, signal, return,
release, pop, or push.
\f
The channel statement controls the handling of peripherals in an
implementation dependent way.
3_._4_._1_0_ _ _ _ _G_o_t_o_ _S_t_a_t_e_m_e_n_t_ 3.4.10
goto statement:
'GOTO 'label '
The goto statement, the declaration of the label, and the
definition of the label must be in the same scope.
Execution continues at the statement labelled by the label
(labelled statement).
Jumps out of a channel or lock statement and jumps out of a
routine are not allowed.
labelled statement:
'label ': 'statement '
3_._4_._1_1_ _ _ _ _S_t_a_n_d_a_r_d_ _R_o_u_t_i_n_e_s_ _a_b_s_,_ _s_u_c_c_,_ _p_r_e_d_,_ _c_h_r_,_ _o_r_d_ 3.4.11
The absolute value of an integer variable is given as the result
of:
FUNCTION abs (int: integer) : integer;
The successor and predecessor of a variable of scalar type is
given as the result of:
FUNCTION succ (s: s _type): s _type
FUNCTION pred (s: s _type): s _type
s _type may be any scalar type.
succ taken on the last element and pred taken on the first ele-
ment of a scalar type results in an exception.
\f
The character with the ordinal value n is the result of a call
chr(n) where chr is defined as:
FUNCTION chr (n: 0 .. 127): char;
The ordinal value of a scalar element is retrieved by the func-
tion ord:
FUNCTION ord (s: s _type): integer;
where s _type may be any scalar type.
\f
F_ 4_._ _ _ _ _ _ _ _ _P_R_O_C_E_S_S_ _C_O_M_M_U_N_I_C_A_T_I_O_N_ 4.
This chapter contains a general description of communication
between incarnations, i.e. a description of the language concepts
and the tables available for the programmer. After that is a more
detailed description of the predefined routines intended for syn-
chronization of the communication between process incarnations.
4.1
4_._1_ _ _ _ _ _ _ _G_e_n_e_r_a_l_ _P_r_o_c_e_s_s_ _C_o_m_m_u_n_i_c_a_t_i_o_n_
A process consists of a number of statements and declarations. An
incarnation of a process is the execution of the actions on a
private data structure. Many incarnations can be executed concur-
rently.
Process incarnations communicate by exchanging m_e_s_s_a_g_e_s_. A mes-
sage can be accessed by at most one incarnation at a time.
M_m_m_ place data await access
M
P_p_p_ in M to M
A B
T_i_m_e_ _T_: A has exclusive access to the message M.
read data
M
in M
A B
T_i_m_e_ _T_ _+_ _1_: B has exclusive access to M.
The two predefined types reference and semaphore are used for re-
ferencing and exchanging access to messages.
\f
The value of a reference variable is either a reference to a
message or nil (representing "no reference"). At most one
variable references a message. Since process incarnations access
messages through reference variables only, mutually exclusive
access to messages is secured.
Q_u_e_u_e_ _s_e_m_a_p_h_o_r_e_s_ are used for exchanging access to messages.
A queue semaphore consists of a sequence (fifo) of messages and a
set of waiting process incarnations. One of these is always
empty.
A queue semaphore s can be in one of three states:
o_p_e_n_
1
2 The sequence of messages is n_o_t_ _e_m_p_t_y_.
M_m_m_ s . The set of incarnations is e_m_p_t_y_.
.
P_p_p_ .
N
sequence of
messages
l_o_c_k_e_d_
The sequence of messages is e_m_p_t_y_.
The set of incarnations is n_o_t_ _e_m_p_t_y_.
s
waiting
incarnations
p_a_s_s_i_v_e_
s The sequence of messages is e_m_p_t_y_.
The set of incarnations is e_m_p_t_y_.
\f
Any process may contain declarations of variables of type sema-
phore, and it may receive semaphore variables as parameters when
it is created. All declared semephore variables are initially in
the passive state. In constrast to variables of any other type a
semaphore variable can be accessible by many process incarnations
simultaneously.
example:
PROCESS converter (input, output: semaphore);
VAR
myown: ARRAY (1 .. 2) OF semaphore;
The process converter has access to four semaphores: input,
output, myown(1), and myown(2).
The predefined routines signal and wait are used for exchanging
access to messages.
PROCEDURE signal (VAR r: reference; VAR s: semaphore);
The reference r must reference a message. If the semaphore s is
open or passive, the message referenced by r is entered in the
sequence of messages belonging to s.
o_p_e_n_ _o_r_ _p_a_s_s_i_v_e_
incarnation executing signal
1
r s 2
M_m_m_ .
message .
P_p_p_ .
N
sequence of
messages
p_r_i_o_r_ _t_o_ _s_i_g_n_a_l_ _(_r_,_ _s_)_
\f
incarnation executing signal
s 1
r 2
M_m_m_ nil .
.
P_p_p_ .
N
N + 1
sequence of
messages
a_f_t_e_r_ _s_i_g_n_a_l_ _(_r_,_ _s_)_
If s is locked one incarnation is removed from the set of waiting
incarnations and reactivated. That is, it will be allowed to com-
plete the call of wait which caused it to wait.
l_o_c_k_e_d_
incarnation executing signal
incarnation executing wait
s
r
message
waiting incarnations
p_r_i_o_r_ _t_o_ _s_i_g_n_a_l_ _(_r_,_ _s_)_
incarnation executing signal
incarnation executing wait
r
nil message
s
waiting incarnations
a_f_t_e_r_ _s_i_g_n_a_l_ _(_r_,_ _s_)_
\f
PROCEDURE wait (VAR r: reference; VAR s: semaphore);
The reference r must be nil. If the semaphore is open the first
message in the sequence is removed and r becomes a reference to
this message.
o_p_e_n_
1 incarnation executing wait
2 message r
M_m_m_ s . nil
.
P_p_p_ .
N
sequence of messages
p_r_i_o_r_ _t_o_ _w_a_i_t_ _(_r_,_ _s_)_
2
M_m_m_ s . message incarnation executing wait
. r
P_p_p_ .
N
sequence of messages
a_f_t_e_r_ _w_a_i_t_ _(_r_,_ _s_)_
If the state is locked or passive the incarnation is temporarily
stopped and entered in the set of waiting incarnations.
l_o_c_k_e_d_ _o_r_ _p_a_s_s_i_v_e_
incarnation executing wait
r
s nil
waiting incarnations
p_r_i_o_r_ _t_o_ _w_a_i_t_ _(_r_,_ _s_)_
\f
incarnation executing wait
r
s nil
waiting
incarnations
Incarnation has been stopped during wait (r, s)
It is implementation dependent which one of several waiting in-
carnations is selected for activation during execution of signal.
However, the selection algorithm must be fair: no incarnation may
remain waiting indefinitely on a semaphore, provided some other
incarnations continue to signal messages to that semaphore.
Execution of wait and of signal is performed indivisibly: e.g.
from the moment an incarnation starts execution of a signal on a
given semaphore and until the execution is completed, any other
incarnation trying to operate on that semaphore variable is
delayed.
A process may only inspect or alter the contents of a message in
a so-called lock statement. Let r be a reference variable which
references a message:
LOCK r AS b: t DO s;
In the statement s the message referenced by r is manipulated as
if it were a variable with the name b of type t.
In the following example there are two processes, one which pro-
duces data (e.g. input data) and one which consumes data (e.g.
uses the input data in a computation).
\f
PROCESS producer (full, PROCESS consumer (full,
void: semaphore); void: semaphore);
TYPE TYPE
buffertype = ...; buffertype = ...;
VAR VAR
r: reference; r: reference;
BEGIN BEGIN
REPEAT REPEAT
wait (r, void); wait (r, full);
LOCK r AS b: buffertype DO LOCK r AS b: buffertype DO
BEGIN BEGIN
(*...produce data...*) (*...consume data...*)
END; END;
signal (r, full); signal (r, void);
UNTIL...; UNTIL...;
END; END;
The allocation of messages is specified by declaring a variable
of pool type.
VAR
m: POOL cardinality OF type;
Initially, the variable m contains cardinality messages. These
messages can hold a value from type. The predefined procedure
alloc removes a message from a pool variable:
alloc (r, m, s);
The reference r must be nil. If the pool of messages is not emp-
ty, one of the messages is removed and r references this message.
If the pool is empty the process incarnation waits until a mes-
sage is released (by another incarnation calling the predefined
procedure release).
\f
Each message contains information about its origin. The third
parameter to alloc must be a semaphore and it becomes the a_n_s_w_e_r_
s_e_m_a_p_h_o_r_e_ of the message. This is the equivalent of a return
address on an envelope of a letter. The answer semaphore is used
in the predefined procedure return:
PROCEDURE return (VAR r: reference);
A call of return is equivalent to a call of signal:
signal (r, "answer semaphore")
But the answer semaphore is only implicitly available through
return.
The following is a revised version of the producer comsumer
example given above.
PROCESS proceducer (stream: PROCESS comsumer (stream:
semaphore); semaphore);
TYPE TYPE
buffertype = ...; buffertype = ...;
VAR VAR
r: reference; r: reference;
m: POOL 1 OF buffertype;
a: semaphore;
BEGIN BEGIN
alloc (r, m, a); REPEAT
REPEAT wait (r, stream);
LOCK r AS b: buffertype DO LOCK r AS b: buffertype DO
BEGIN BEGIN
(*...produce buffer...*) (*...comsume buffer...*)
END; END;
signal (r, stream); return (r);
wait (r, a); UNTIL...;
UNTIL...; END;
END;
\f
The following communication flow is possible by means of
SIGNAL/RETURN:
A reference variable may point to none or a stack of messages.
This is a generalization of the concept of reference variables as
described earlier. In general terms a reference variable points
to a stack of messages.
When the value of the reference variable is nil, the stack is
empty.
A well-defined reference variable points to a stack of reference
variables. The message header of the stack elements contains a
field, which chains the messages together. This field is called
the s_t_a_c_k_ _c_h_a_i_n_. This pointer is nil in the last element of the
chain.
Two procedures:
PUSH(<reference variable',<reference variable')
POP (<reference variable',<reference variable')
are used to manipulate reference variables when interpreted as
stack reference variables.
\f
example:
VAR element: REFERENCE;
stack: REFERENCE;
M_m_m_ .
.
P_p_p_ .
PUSH (element, stack);
M_m_m_ .
.
P_p_p_ .
POP (element, stack);
P_U_S_H_ _(_r_e_f_1_,_ _r_e_f_2_)_
B_e_f_o_r_e_ _c_a_l_l_
ref1 - well-defined reference to element.
The stack chain field in the element m_u_s_t_ be NIL.
ref2 - well-defined stackop element or
nil if stack is empty:
A_f_t_e_r_ _c_a_l_l_
ref1 - nil
ref2 - ref2:= old ref1
If the old ref1 has no associated message data, the message data
associated the old ref2, if any, are assigned the old ref1,
together with the pushing.
If the old ref1 has associated message data the old ref1 is just
pushed.
\f
E_x_a_m_p_l_e_
1) Before call After call
ref1 ref2 ref1 ref2
2)
ref1 ref2 ref1 ref2
P_O_P_ _(_r_e_f_1_,_ _r_e_f_2_)_
B_e_f_o_r_e_ _c_a_l_l_
ref1 - nil
ref2 - well-defined stacktop element
\f
A_f_t_e_r_ _c_a_l_l_
ref1 - ref1:= old ref2
ref2 - new stacktopelement.
Note: ref2:= nil if the stack
became empty during call.
If the old stackop element has associated message data, and the
new stackop element points to the same message data, the message
data pointer in the popped element is set to nil.
This is not done if the new stackop element points either to
another message data or points to nil.
\f
E_x_a_m_p_l_e_s_
1) Before call After call
ref1 ref2 ref1 ref2
2)
ref1 ref2 ref1 ref2
3)
ref1 ref2 ref1 ref2
\f
The PUSH and POP procedures are especially suited to the
following situations:
- to associate a new messageheader to received message data by
the PUSH procedure in order to avoid copying of data, and to
signal the message on to the next incarnation in the flow. The
general answer mechanism will be to reestablish the original
message header by a call of POP and return the message to the
sender by calling RETURN.
SIGNAL SIGNAL SIGNAL SIGNAL
M_M_m_ P P P P
P_P_p_ 1 2 n-1 n
RETURN RETURN RETURN RETURN
- to pile together a number of messages and pass the whole batch
to an incarnation by one call of SIGNAL.
S_e_m_a_p_h_o_r_e_ _P_o_i_n_t_e_r_s_
A semaphore pointer variable is a variable of type:
semaphore
A semaphore pointer variable is a variable, whose value refer-
ences a semaphore variable.
If the value is not a reference to a semaphore variable, the
value is nil.
The only legal operations on semaphore pointer variables are:
nil, and := (assignment)
If p is a semaphore pointer variable, p denotes the semaphore
pointed to by p.
\f
4_._2_ _ _ _ _ _ _ _T_h_e_ _P_r_e_d_e_f_i_n_e_d_ _C_o_m_m_u_n_i_c_a_t_i_o_n_ _R_o_u_t_i_n_e_s_ 4.2
s_i_g_n_a_l_,_ _w_a_i_t_,_ _r_e_t_u_r_n_,_ _a_n_d_ _r_e_l_e_a_s_e_.
There are four predefined communication routines, signal, return,
wait, and release.
PROCEDURE signal (VAR r: reference; VAR s: semaphore);
The reference parameter must refer to a message (must not be
nil), otherwise an exception occurs. The reference variable is
nil after a call of signal.
If the semaphore is passive or open, the message referred to by r
becomes the last element of the semaphore>s sequence of messages.
If the semaphore is locked, one of the incarnations waiting on
the semaphore completes its wait call.
When several process incarnations are waiting, it is implementa-
tion dependent which one is resumed by a signal call. No process
must, however, be waiting indefinitely if other incarnations con-
tinue to signal messages to the semaphore.
PROCEDURE return (VAR r: reference);
The parameter must refer to a message (must not be nil), other-
wise an exception occurs.
The call:
return (r);
has the same effect as the call:
signal (r, r .answer );
The latter is, however, not a valid call because the answer
semaphore is not explicitly available.
\f
PROCEDURE release (VAR r: reference);
The parameter must refer to a message (must not be nil), other-
wise an exception occurs.
The call:
release (r);
has the same effect as the call:
signal (r, r .owner );
The latter is, however, not a valid call because the owner sama-
phore is not explicitly avaiable.
PROCEDURE wait (VAR r: reference; VAR s: semaphore);
The reference parameter must be nil, otherwise an exception
occurs. After a call of wait it refers to a message.
If the semaphore is open, the first message is removed from the
semaphore>s sequence of messages. If the semaphore is passive or
locked, the incarnation waits and enters the set of incarnations
waiting on the semaphore. It can be resumed by another
incarnation calling signal or return.
O_p_e_n_,_ _L_o_c_k_e_d_,_ _P_a_s_s_i_v_e_,_ _a_n_d_ _S_e_n_s_e_s_e_m_
There are three predefined boolean functions to detect the state
of a semaphore variable:
FUNCTION open (s: semaphore): boolean
FUNCTION locked (s: semaphore): boolean
FUNCTION passive (s: semaphore): boolean
\f
The three states may be depicted as:
o_p_e_n_
1
2 The sequence of messages is n_o_t_ _e_m_p_t_y_.
M_m_m_ . The set of incarnations is e_m_p_t_y_.
.
P_p_p_ .
N
sequence of
messages
l_o_c_k_e_d_
The sequence of messages is e_m_p_t_y_.
The set of incarnations is n_o_t_ _e_m_p_t_y_.
s
waiting
incarnations
p_a_s_s_i_v_e_
s The sequence of messages is e_m_p_t_y_.
The set of incarnations is e_m_p_t_y_.
S_e_n_s_e_s_e_m_
PROCEDURE sensesem (VAR r: reference;
VAR s: semaphore);
The body of sensesem is equivalent to:
IF open (s) THEN wait (r, s);
i.e. take a message from s if there is any, otherwise r remains
nil. \f
R_e_f_
Semaphore pointers may be assigned to denote a semaphore by means
of the predefined routine ref:
FUNCTION ref (s: semaphore): semaphore;
Semaphore pointers are initially set to nil by the system, this
may be used to define a nilpointer which may be useful if
semaphore pointers are used.
example:
var nil _pointer:! semaphore; (* nil _pointer cannot be
changed since it is frozen*)
sem _arr: array (low .. high) of semaphore;
.
.
sem _arr (index):= ref (sem);
.
.
sem _arr (index):= nil _pointer;
P_u_s_h_,_ _p_o_p_,_ _a_n_d_ _e_m_p_t_y_
A message may consist of a stack of headers and data areas. The
stack of message headers is the m_e_s_s_a_g_e_ _h_e_a_d_e_r_ _s_t_a_c_k_, and the
stack of the data areas, the m_e_s_s_a_g_e_ _d_a_t_a_ _s_t_a_c_k_.
\f
message:
M_M_m_ header header ... header message header stack
P_P_p_ 1 2 n
M_M_m_ data ... data message data stack
P_P_p_ 1 m
A header may or may not point to a data area (m <_ n). The t_o_p_
M_M_m_ h_e_a_d_e_r_ of the message is header . The t_o_p_ _d_a_t_a_ of a message is
P_P_p_ 1
M_M_m_ data .
P_P_p_ 1
The message is organized as a stack which is manipulated by the
two predefined procedures push and pop.
PROCEDURE push (VAR r1, r2: reference);
The parameter r1 must refer to a message (must not be nil), and
this message must have exactly one header, otherwise an exception
occurs. The message accessible through r2 (possibly nil) is
called the stack.
The header referred to by r1 becomes the new top header of the
stack. After the call, r2 refers to the new stack.
If the new top message is a header message, the top data of r2
remains the same. After the call r1 is nil.
PROCEDRUE pop (VAR r1, r2: reference);
Reference variable r1 must be nil and r2 must refer to a message
(must not be nil), otherwise an exception occurs.
The top header is removed from the message (accessed through r2)
and after the call r2 refers to the remaining part, while r1
refers to the removed message.
\f
It may be detected if a reference variable refers to a message
with one header only by means of the predefined boolean function:
FUNCTION empty (r: reference): boolean
The body of empty may be:
pop (local ref, r),
empty:= nil (r)
where nil is another standard function:
N_i_l_
FUNCTION nil (p: pointer _type): boolean
pointer _type may be any pointed type, for example reference which
is defined like
TYPE reference = message;
A_l_l_o_c_ _a_n_d_ _O_p_e_n_p_o_o_l_
With each variable of type pool an anonymous semaphore is asso-
ciated. This is the owner semaphore of all messages in the pool.
A message is allocated from the pool by the predefined procedure
alloc.
PROCEDURE alloc (VAR r: reference, VAR p: pool 1; VAR s: semaphore);
The pool variable can be of any pool type.
The reference variable must be nil, otherwise an exception
occurs. After the call it refers to a message. If the pool of
message is not empty, one of the messages is removed. If the pool
is empty the incarnation waits until a message is released to the
pool by another process incarnation calling release. The answer
semaphore of the removed message becomes s.
Variables of type pool (or variables with pool components) can
only be declared in the declaration of a process and not in the
declarations of a routine. \f
It may be detected if a pool is open (i.e. not empty) by means of
FUNCTION openpool (VAR p: pool 1): boolean;
the function result becomes true if the pool is not empty (cf.
function open for semaphore).
\f
F_ 5_._ _ _ _ _ _ _ _ _P_R_O_C_E_S_S_ _C_O_N_T_R_O_L_ 5.
Processes can be nested and a process declared within another
process is a s_u_b_-_p_r_o_c_e_s_s_ (of the surrounding process).
An arbitrary number of incarnations of sub-processes (children)
can be created, they are all controlled by the parent. Incar-
nations are created and removed dynamically.
A process can have f_o_r_m_a_l_ _p_a_r_a_m_e_t_e_r_s_. When an incarnation of the
process is created a number of a_c_t_u_a_l_ _p_a_r_a_m_e_t_e_r_s_ is given. Incar-
nations communicate through common semaphore variables only. In
this way a parent determines the communication paths of children.
Note, however, that the controlling process incarnation need not
participate in the communication.
Variables of the predefined type shadow are used to discern dif-
ferent incarnations of sub-processes. A shadow variable is the
controlling process> link to an incarnation of a child. There is
a number of predefined routines for exercising this control
(start, stop, etc.).
5_._1_ _ _ _ _ _ _ _T_h_e_ _P_r_e_d_e_f_i_n_e_d_ _R_o_u_t_i_n_e_s_ _f_o_r_ _P_r_o_c_e_s_s_ _C_o_n_t_r_o_l_ 5.1
L_i_n_k_
FUNCTION link (external _name: alfa;
process name): integer;
There must not be a process linked to process name, process name
must be the name of a process. The process identified by the
external _name is linked to process name. The external identifica-
tion of processes is implementation dependent.
Result 0 means success, other values are implementation dependent
error codes. \f
FUNCTION create (incarnation _name: alfa;
process name (actual parameters);
VAR sh: shadow; storage: integer): integer;
The shadow variable must be nil and process name must be linked
to a process. Result 0 means success, other values are implemen-
tation dependent error codes.
A new i_n_c_a_r_n_a_t_i_o_n_ of the process linked to process name is crea-
ted. The storage parameter specifies the amount of storage for
holding the runtime stack. The store is initialized with the
actual parameters and various administrative informations but the
incarnation is stopped. The created incarnation is a c_h_i_l_d_ of the
creating incarnation, the p_a_r_e_n_t_. After the call the shadow
variable refers to the child.
R_e_m_o_v_e_
PROCEDURE remove (VAR sh: shadow);
The shadow variable must refer to a process incarnation (child),
otherwise an exception occurs.
Remove terminates execution of the child and deallocates all its
resources. Execution of that incarnation cannot be resumed.
Remove also removes all incarnations controlled by the child,
their children ect.
After the call the shadow variable is nil.
S_t_a_r_t_,_ _S_t_o_p_,_ _a_n_d_ _B_r_e_a_k_
The following predefined procedures are used for controlling
children between calls of create and remove.
PROCEDURE start (VAR sh: shadow; priority: integer);
\f
Start initiates or resumes execution of a child which is stopped.
The meaning of priority is implementation dependent.
PRODURE stop (VAR sh: shadow);
The shadow variable must refer to a process incarnation (child).
The child is stopped.
PROCEDURE break (VAR sh: shadow; exception _code: integer);
The shadow variable must refer to a process incarnation (child).
The call forces an exception upon the child. The meaning of the
exception _code is implementation dependent.
U_n_l_i_n_k_
FUNCTION unlink (process name): integer;
At process must be linked to process name and no incarnations of
the process may exist. After the call the link is deleted.
Result 0 means success, other values are implementation dependent
error codes.
\f
F_6_._ _ _ _ _ _ _ _ _U_T_I_L_I_T_Y_ _P_R_O_G_R_A_M_S_ 6.
6_._1_ _ _ _ _ _ _ _I_n_d_e_n_t_ 6.1
T_e_x_t_ _f_o_r_m_a_t_t_i_n_g_ _p_r_o_g_r_a_m_
The program performs indention of source programs depending on
the options specified in the call and on the keyswords (reserved
words) of PASCAL/PASCAL80.
c_a_l_l_:
M_m_m_ 1
<outputfile'= indent <input file' <option'
P_p_p_ 0 0
<option'::= lines line numbers are added
mark the blockstructure is made clear by means
of ! between matching begin-end>s
list the same as: lines mark
noind the output will be left justified
myind the output indention is the same as the
input indention
lc lists keywords in capital letters and
identifiers in small (lower case) letters
uc both key words and indentifiers are listed
in upper case letters
help produces a list of legal options
Storage requirements:
The core store required for indent is 16000 hW (size 16000).
E_r_r_o_r_ _m_e_s_s_a_g_e_s_:
??? illegal input-filename
input file must be specified
\f
call: "indent help", for help
an error is detected in the program call, a new call
"indent help" will produce a list of the valid options.
** warning, end(s) missing
an error in the begin-end structure has been detected.
** premature end of file
comment or string not terminated.
6_._2_ _ _ _ _ _ _ _C_r_o_s_s_ _R_e_f_e_r_e_n_c_e_ _P_r_o_g_r_a_m_ 6.2
Produces a cross reference listing of the identifiers and numbers
and a use count of the PASCAL/PASCAL80 key words used in the input
text.
The cross reference list is made with no regard to the block
structure of the program. The list is sorted according to the
ISO-alphabet, i.e. numbers before letters, but with no difference
between upper and lower case letters.
The occurrence list for an identifier consists of a sequence of
PASCAL/PASCAL80 line numbers. The occurrence kind is specified by
means of the character following the line number:
* meaning the identifier or number is found in a declaration part.
= meaning the identifier is assigned to in the line specified.
: meaning the identifier or number occurred as a label.
blank all other uses
<<<<<<<<<<<<<<in the list is a warning denoting that the name
consists of more than 12 characters, which is the number
of significant characters for PASCAL-identifiers.
\f
C_a_l_l_:
M_m_m_ 1
<output file' = cross <input file' <option'
P_p_p_ 0
<option'::= bossline. <yes or no'
<yes or no'::= yes bossline>s are added to the listing.
(default).
no only PASCAL/PASCAL80 line numbers are
generated.
S_t_o_r_a_g_e_ _r_e_q_u_i_r_e_m_e_n_t_s_:
The core store required for cross is at least 40000 hW (size
40000), but the requirement depends on the size of the input
text.
E_r_r_o_r_m_e_s_s_:
??? illegal output-filename
left hand side of the call must be a name.
??? illegal input-filename
input file must be specified
??? yes or no expected
option >bossline> must be >bossline.yes> or >bossline.no>
??? error in bracket structure, detected at line: xx
missing ")" (>s)
??? error in blockstructure, detected at line: xx
unmatched end
***** warning: hash table overflow at line: xx
the name table ran full at line xx, the cross referencing
continues for the names met until line xx, new names in
the following lines are ignored.
\f
F_ A_._ _ _ _ _ _ _ _ _R_E_F_E_R_E_N_C_E_S_A.
1 Staunstrup, J.:
PASCAL80 Report
RCSL No 52-AA964
A/S Regnecentralen af 1979
2 Jensen, K. and Wirth, N.:
PASCAL User Manual and Report
Springer - Verlag
Berlin 1974
\f
\f
i
T_A_B_L_E_ _O_F_ _C_O_N_T_E_N_T_S_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _P_A_G_E_ _
1. INTRODUCTION .......................................... 1
2. FUNCTIONS SUPPORTED BY THE DRIVER ..................... 3
3. DRIVER INTERFACE ...................................... 4
3.1 Read Character ROM ............................... 4
3.2 Read Character RAM ............................... 4
3.3 Write Character RAM .............................. 4
3.4 Write Shadow RAM ................................. 5
3.5 Write Attribute RAM .............................. 5
4. DRIVER DECLARATION .................................... 6
5. BASIC DISPLAY ROUTINES ................................ 7
A_P_P_E_N_D_I_X_:
A. REFERENCES ............................................ 11
\f
ii
\f
1_._ _ _ _ _ _ _ _ _I_N_T_R_O_D_U_C_T_I_O_N_ 1.
The RC850 display driver is used to control the screen display
function of an RC850 terminal. The driver runs on the PI-1
Machine 1 implemented on a Z80-microprocessor as part of the
RC850.
The functions provided by the driver may be characterized as
rudimentary. Most of the functions are transparent transfer
functions between CPU-memory and the various memories of the
display module. The display module is described in detail in
chapter 2 of 2. Its components are summarized below:
R_e_f_r_e_s_h_ _R_A_M_
The memory holds the picture shown on the display, 2000 char-
acters. 16 bits per. display position: 9 bits character value and
7 bits attributes.
C_h_a_r_a_c_t_e_r_ _R_O_M_
The memory holds up to 128 standard character patterns, addressed
by character values 0-127.
C_h_a_r_a_c_t_e_r_ _R_A_M_
This memory can hold up to 256 extra character patterns,
addressed by character values 256-511.
S_h_a_d_o_w_ _R_A_M_
This memory can hold 4 shadow patterns which can be shown
together with the addressed character. It is addressed by 2
attribute bits.
A_t_t_r_i_b_u_t_e_ _R_A_M_
This memory can perform a conversion of 5 of the attribute bits
to a number of different light effects on the display.
C_R_T_ _c_o_n_t_r_o_l_l_e_r_
Contains the physical display parameters. These parameters are
initialized by the driver, and can only be changed in the driver
code. \f
Under normal use only the refresh RAM is updated dynamically. In
fact when the driver is not performing a specifically requested
transfer function it will continously transfer the contents of a
buffer in CPU RAM, the r_e_f_r_e_s_h_ _R_A_M_ _o_r_i_g_i_n_a_l_ to the display
refresh RAM by means of DMA.
With this strategy process incarnations on the PI-1 machine may
update the display picture simply be writing into the refresh RAM
original.
Normally, an RC850 application will issue very few request to the
display driver, because only those functions which require syn-
chronization by means of interrupts have been implemented as
parts of the actual driver. A number of more commonly used func-
tions are provided by the basic display routines described in
chapter 5. The implementation of these functions in the form of
routines eliminates a significant amount of costly process inter-
communication.
\f
2_._ _ _ _ _ _ _ _ _F_U_N_C_T_I_O_N_S_ _S_U_P_P_O_R_T_E_D_ _B_Y_ _T_H_E_ _D_R_I_V_E_R_ 2.
The CTR controller will be initialized to physical characteris-
tics as described in 2.
The contents of all RAM memories will be undefined, and the dis-
play will be blocked. Proper initialization from the application
should include writing of all RAM memories and unblocking the
display.
The following data transfer functions are executed by the driver
on request:
- read character ROM to CPU RAM,
- read/write character RAM,
- write shadow RAM,
- write attribute RAM.
Note that all display memories are accessed in blocks of bytes
from byte 0 onwards.
The following basic functions on the display module are not
performed by the driver, but by a collection of basic display
routines described in chapter 5:
- set/read cursor position,
- block/unblock the display,
- set cursor mode.
\f
3_._ _ _ _ _ _ _ _ _D_R_I_V_E_R_ _I_N_T_E_R_F_A_C_E_ 3.
The following description is based on the driver interface
conventions 3. Each request supported by the driver is
described in one section.
3_._1_ _ _ _ _ _ _ _R_e_a_d_ _C_h_a_r_a_c_t_e_r_ _R_O_M_ 3.1
Transfers contents of the character ROM to the data buffer.
function code 5 (read + 1 * 4)
Possible results:
0 processed succesfully
4 illegal function.
3_._2_ _ _ _ _ _ _ _R_e_a_d_ _C_h_a_r_a_c_t_e_r_ _R_A_M_ 3.2
Transfers contents of the character RAM to the data buffer.
function code 9 (read + 2 * 4)
Possible results:
0 processed succesfully
4 illegal function.
3_._3_ _ _ _ _ _ _ _W_r_i_t_e_ _C_h_a_r_a_c_t_e_r_ _R_A_M_ 3.3
Transfers contents of the data buffer to the character RAM.
function code 10 (write + 2 * 4)
Possible results:
0 processed successfully
4 illegal function.
\f
3_._4_ _ _ _ _ _ _ _W_r_i_t_e_ _S_h_a_d_o_w_ _R_A_M_ 3.4
Transfers contents of data buffer to shadow RAM.
function code 14 (write + 3 * 4)
Possible results:
0 processed succesfully
4 illegal function.
3_._5_ _ _ _ _ _ _ _W_r_i_t_e_ _A_t_t_r_i_b_u_t_e_ _R_A_M_ 3.5
Transfers contents of data buffer to attribute RAM.
function code 18 (write + 4 * 4)
Possible results:
0 processed succesfully
4 illegal function.
\f
4_._ _ _ _ _ _ _ _ _D_R_I_V_E_R_ _D_E_C_L_A_R_A_T_I_O_N_ 4.
The display driver is always placed in an RC850 bootstrap image
along with the PI-1 basic software. The parent of the display
driver is the Eve process (see 1). The PASCAL80 process heading
of the display driver is as follows:
PROCESS Display _driver (VAR display _sem: semaphore;
int _vector: channel _number);
where display _sem is the driver>s request semaphore, and
int _vector is the interrupt vector programmed in channel 2 of the
CTC (used for interrupt on termination of DMA transfer).
The basic system variables used for performing display functions
which are defined in the next chapter are also declared in the
Eve process.
\f
5_._ _ _ _ _ _ _ _ _B_A_S_I_C_ _D_I_S_P_L_A_Y_ _R_O_U_T_I_N_E_S_
The routines described in the following are included in the boot-
strap image of any RC850 terminal along with the display driver and
included in the RC850 context used when compiling PASCAL80 program
for an RC850 terminal. The routines access three basic system
variables:
- the refresh RAM orginal, cf. chapter 1,
- the current cursor position (row, column),
- the current attribute byte (this is stored together with each
character written).
PROCEDURE WriteDisplay (a: integer; b: byte);
The byte is written in the refresh RAM original at address a.
FUNCTION ReadDisplay (a: integer): byte;
The function returns the value stored at address a in the refresh
RAM original.
PROCEDURE SetCursorPosition (r,c: byte);
The cursor is placed at location (r,c) on the display, and the
current cursor position variable is updated to this value. The
caller is responsible for ensuring that 0 <_ r <_ 24 and 0 <_ c <_ 79.
PROCEDURE ReadCursorPosition (VAR r,c: byte);
The value of the current cursor position variable is copied into r
and c.
PROCEDURE BlockDisplay;
Display of the contents of the refresh RAM on the screen is
inhibited, i.e. the screen goes black.
PROCEDURE UnblockDisplay;
Display of the contents of the refresh RAM is enabled.
PROCEDURE SetCursorMode (mode: cursor _mode);
The type cursor _mode is defined as
\f
cursor _mode = PACKED RECORD
dummy1: bit;
blink: boolean;
blinkrate: bit;
dummy2: bit;
startc: 0..13;
dummy3: 0..15;
endc: 0..13
END;
A call of SetCursorMode will set the blink rate, size, and
position of the cursor as specified by the fields of mode.
blink: If TRUE, the cursor will blink.
blinkrate: If 0 the blink rate is 1/32 of the field rate
(50 Hz), otherwise 1/16.
startc and endc: First and last scanline of the cursor block.
PROCEDURE WriteChar (b: char);
The character is written on the display at the current cursor
position which is then updated. Updating the cursor position
(r,c) yields (r,c+1), except if c = 79 in which case a newline is
output (see WriteNL). The cursor is set at the updated position.
The attribute byte of the character is set to current attribute.
PROCEDURE WriteNL;
The cursor and current cursor position are both moved to the begin-
ning of the next line. If the cursor was already in the last line
(24) before the call, the screen image is rolled one line before
the new line function is performed. Spaces are written in all char-
acter positions of the new bottom line, with zero attribyte bytes.
PROCEDURE SetAttribute (att: byte);
The current attribute byte is set to the value of att. Subsequent
characters written using WriteChar will have this byte as attri-
bute byte.
\f
PROCEDURE ClearScreen;
The procedure will clear the screen (setting all positions to
blank with zero attribute), set current cursor position to (0,0)
and set current attribute to 0.
\f
\f
A_._ _ _ _ _ _ _ _ _R_E_F_E_R_E_N_C_E_S_ A.
1 RCSL No 31-D615:
The P1-1 Machine, Reference Manual.
2 RCSL No 31-D594:
RC850 Controllers, Reference Manual.
3 RCSL No 31-D617:
PASCAL80 Driver Conventions.
\f
«eof»