DataMuseum.dk

Presents historical artifacts from the history of:

Rational R1000/400 Tapes

This is an automatic "excavation" of a thematic subset of
artifacts from Datamuseum.dk's BitArchive.

See our Wiki for more about Rational R1000/400 Tapes

Excavated with: AutoArchaeologist - Free & Open Source Software.


top - metrics - download
Index: C T

⟦37884855e⟧ TextFile

    Length: 49252 (0xc064)
    Types: TextFile
    Names: »CHAPTER_13«

Derivation

└─⟦180fe333a⟧ Bits:30000405 8mm tape, Rational 1000, SW CATALOG, 10_20_0
└─⟦180fe333a⟧ Bits:30000537 8mm tape, Rational 1000, SW Catalog 10_20_0
    └─⟦5cb1d1d7f⟧ »DATA« 
        └─⟦3b1ee7bd8⟧ 
            └─⟦this⟧ 

TextFile

     13. Representation Clauses and Implementation-Dependent Features



This      chapter     describes     representation     clauses,     certain
implementation-dependent features, and other  features  that  are  used  in
system programming.



13.1  Representation Clauses


Representation  clauses  specify  how  the  types of the language are to be
mapped onto the underlying machine.  They can  be  provided  to  give  more
efficient representation or to interface with features that are outside the
domain of the language (for example, peripheral hardware).

    representation_clause ::=
         type_representation_clause | address_clause

    type_representation_clause ::= length_clause
       | enumeration_representation_clause | record_representation_clause

A  type  representation clause applies either to a type or to a first named
subtype (that is, to a subtype declared by a  type  declaration,  the  base
type  being  therefore anonymous).  Such a representation clause applies to
all objects that have this type or this first named subtype.  At  most  one
enumeration  or  record  representation clause is allowed for a given type:
an enumeration representation clause is only  allowed  for  an  enumeration
type;   a  record  representation  clause, only for a record type.  (On the
other hand, more than one length clause can be provided for a  given  type;
moreover,  both a length clause and an enumeration or record representation
clause  can  be  provided.)   A  length  clause  is  the   only   form   of
representation  clause  allowed  for a type derived from a parent type that
has (user-defined) derivable subprograms.

An address clause applies either to an object;  to a  subprogram,  package,
or  task  unit;  or to an entry.  At most one address clause is allowed for
any of these entities.

A representation clause and the declaration of  the  entity  to  which  the
clause  applies  must  both  occur  immediately within the same declarative
part, package specification, or task specification;  the  declaration  must
occur  before  the clause.  In the absence of a representation clause for a
given  declaration,  a  default  representation  of  this  declaration   is
determined  by  the implementation.  Such a default determination occurs no
later than the end of the immediately enclosing declarative  part,  package
specification,  or  task  specification.   For  a  declaration  given  in a
declarative part, this default determination  occurs  before  any  enclosed


                                  13 - 1








body.

In  the  case  of  a  type,  certain occurrences of its name imply that the
representation of the type must already have been determined.  Consequently
these occurrences force the default determination  of  any  aspect  of  the
representation  not  already  determined  by  a  prior  type representation
clause.  This default determination is also forced by  similar  occurrences
of the name of a subtype of the type, or of the name of any type or subtype
that has subcomponents of the type.  A forcing occurrence is any occurrence
other than in a type or subtype declaration, a subprogram specification, an
entry  declaration,  a  deferred  constant  declaration,  a  pragma,  or  a
representation clause for the type itself.   In  any  case,  an  occurrence
within an expression is always forcing.












































                                  13 - 2








A  representation  clause  for  a  given  entity  must  not appear after an
occurrence of the name of the entity if this occurrence  forces  a  default
determination of representation for the entity.

Similar  restrictions  exist  for  address  clauses.   For  an  object, any
occurrence of  its  name  (after  the  object  declaration)  is  a  forcing
occurrence.  For a subprogram, package, task unit, or entry, any occurrence
of a representation attribute of such an entity is a forcing occurrence.

The  effect  of the elaboration of a representation clause is to define the
corresponding aspects of the representation.

The interpretation of some of the expressions that appear in representation
clauses is implementation-dependent, for  example,  expressions  specifying
addresses.   An  implementation  may limit its acceptance of representation
clauses to those that can be handled simply by the underlying hardware.  If
a representation clause is accepted by an implementation, the compiler must
guarantee that the net effect of the program is not changed by the presence
of the clause, except for address clauses and for parts of the program that
interrogate  representation  attributes.    If   a   program   contains   a
representation  clause  that  is not accepted, the program is illegal.  For
each  implementation,  the  allowed   representation   clauses,   and   the
conventions   used   for   implementation-dependent  expressions,  must  be
documented in Appendix F of the reference manual.

Whereas a representation clause is used to impose  certain  characteristics
of  the  mapping   of an entity onto the underlying machine, pragmas can be
used to provide an implementation with criteria for its selection of such a
mapping.  The pragma PACK specifies that storage minimization should be the
main criterion when selecting the representation of a record or array type.
Its form is as follows:

    pragma PACK(type_simple_name);

Packing means that gaps between the storage areas allocated to  consecutive
components  should  be minimized.  It need not, however, affect the mapping
of each component onto storage.  This mapping can itself be influenced by a
pragma (or controlled by a representation  clause)  for  the  component  or
component type.  The position of a PACK pragma, and the restrictions on the
named  type, are governed by the same rules as for a representation clause;
in particular, the pragma must appear before any use  of  a  representation
attribute of the packed entity.

The  pragma  PACK  is  the  only  language-defined  representation  pragma.
Additional representation pragmas may be  provided  by  an  implementation;
these  must  be  documented  in Appendix F.  (In contrast to representation
clauses, a pragma that is not accepted by the implementation  is  ignored.)

Note:

No representation clause is allowed for a generic formal type.

References:   address  clause  13.5,  allow  1.6,  body 3.9, component 3.3,
declaration 3.1, declarative part 3.9, default expression  3.2.1,  deferred
constant  declaration  7.4,  derivable  subprogram  3.4,  derived type 3.4,


                                  13 - 3








entity 3.1, entry 9.5, enumeration representation clause  13.3,  expression
4.4, generic formal type 12.1.2, illegal 1.6, length clause 13.2, must 1.6,
name  4.1,  object  3.2,  occur  immediately within 8.1, package 7, package
specification 7.1, parent  type  3.4,  pragma  2.8,  record  representation
clause  13.4,  representation  attribute  13.7.2  13.7.3, subcomponent 3.3,
subprogram 6, subtype 3.3, subtype declaration  3.3.2,  task  specification
9.1, task unit 9, type 3.3, type declaration 3.3.1


















































                                  13 - 4








13.2  Length Clauses


A length clause specifies an amount of storage associated with a type.

    length_clause ::= for attribute use simple_expression;

The  expression  must  be  of some numeric type and is evaluated during the
elaboration of the length clause (unless it is a static  expression).   The
prefix of the attribute must denote either a type or a first named subtype.
The  prefix  is  called  T  in  what  follows.   The only allowed attribute
designators in a length clause are  SIZE,  STORAGE_SIZE,  and  SMALL.   The
effect of the length clause depends on the attribute designator:


(a)  Size specification:  T'SIZE

     The  expression must be a static expression of some integer type.  The
     value of the expression specifies an upper bound  for  the  number  of
     bits  to be allocated to objects of the type or first named subtype T.
     The  size  specification  must  allow  for  enough  storage  space  to
     accommodate   every   allowable   value  of  these  objects.   A  size
     specification for a composite type may affect the  size  of  the  gaps
     between the storage areas allocated to consecutive components.  On the
     other  hand, it need not affect the size of the storage area allocated
     to each component.

     The size specification is only allowed if the constraints on T and  on
     its   subcomponents   (if   any)  are  static.   In  the  case  of  an
     unconstrained array type, the index subtypes must also be static.


(b)  Specification of collection size:  T'STORAGE_SIZE

     The prefix T must denote an access type.  The expression  must  be  of
     some  integer  type (but need not be static);  its value specifies the
     number of storage units to be reserved for the  collection,  that  is,
     the  storage  space needed to contain all objects designated by values
     of the access type and by values  of  other  types  derived  from  the
     access  type,  directly  or indirectly.  This form of length clause is
     not allowed for a type derived from an access type.


(c)  Specification of storage for a task activation:  T'STORAGE_SIZE

     The prefix T must denote a task type.  The expression must be of  some
     integer type (but need not be static);  its value specifies the number
     of  storage units to be reserved for an activation (not the code) of a
     task of the type.


(d)  Specification of small for a fixed point type:  T'SMALL

     The prefix T must denote the first named  subtype  of  a  fixed  point
     type.   The  expression must be a static expression of some real type;


                                  13 - 5








     its value must not be greater  than  the  delta  of  the  first  named
     subtype.   The  effect  of  the  length clause is to use this value of
     small for the representation of values of the fixed point  base  type.
     (The  length  clause  thereby  also  affects the amount of storage for
     objects that have this type.)

Notes:

A size specification is allowed for an access, task, or fixed  point  type,
whether or not another form of length clause is also given for the type.















































                                  13 - 6








What  is  considered to be part of the storage reserved for a collection or
for an activation of  a  task  is  implementation-dependent.   The  control
afforded  by  length  clauses  is  therefore relative to the implementation
conventions.  For example, the language does not define whether the storage
reserved for an activation of a task includes any storage  needed  for  the
collection  associated  with  an access type declared within the task body.
Neither does it define the method of  allocation  for  objects  denoted  by
values  of  an access type.  For example, the space allocated could be on a
stack;  alternatively,   a  general  dynamic  allocation  scheme  or  fixed
storage could be used.

The  objects  allocated  in a collection need not have the same size if the
designated type is an unconstrained array type  or  an  unconstrained  type
with  discriminants.   Note also that the allocator itself may require some
space for internal tables  and  links.   Hence  a  length  clause  for  the
collection  of an access type does not always give precise control over the
maximum number of allocated objects.

Examples:

    --  assumed declarations:

    type MEDIUM is range 0 .. 65000;
    type SHORT  is delta 0.01 range -100.0 .. 100.0;
    type DEGREE is delta 0.1  range -360.0 .. 360.0;

    BYTE : constant := 8;
    PAGE : constant := 2000;

    --  length clauses:

    for COLOR'SIZE  use 1*BYTE;  --  see 3.5.1
    for MEDIUM'SIZE use 2*BYTE;
    for SHORT'SIZE  use 15;

    for CAR_NAME'STORAGE_SIZE use  --  approximately 2000 cars
                2000*((CAR'SIZE/SYSTEM.STORAGE_UNIT) + 1);

    for KEYBOARD_DRIVER'STORAGE_SIZE use 1*PAGE;

    for DEGREE'SMALL use 360.0/2**(SYSTEM.STORAGE_UNIT - 1);

Notes on the examples:

In the length clause for SHORT, fifteen  bits  is  the  minimum  necessary,
since   the   type   definition   requires   SHORT'SMALL  =  2.0**(-7)  and
SHORT'MANTISSA = 14.  The length clause for DEGREE forces the model numbers
to exactly span the range of the type.

References:  access type 3.8, allocator 4.8, allow  1.6,  array  type  3.6,
attribute  4.1.4, collection 3.8, composite type 3.3, constraint 3.3, delta
of a fixed point type 3.5.9, derived type 3.4, designate  3.8,  elaboration
3.9,  entity 3.1, evaluation 4.5, expression 4.4, first named subtype 13.1,
fixed point type 3.5.9, index subtype 3.6, integer type  3.5.4,  must  1.6,
numeric  type 3.5, object 3.2, real type 3.5.6, record type 3.7, small of a


                                  13 - 7








fixed point type 3.5.10, static  constraint  4.9,  static  expression  4.9,
static  subtype  4.9,  storage  unit 13.7, subcomponent 3.3, system package
13.7, task 9, task activation 9.3, task specification 9.1, task  type  9.2,
type 3.3, unconstrained array type 3.6





















































                                  13 - 8








13.3  Enumeration Representation Clauses


An  enumeration  representation clause specifies the internal codes for the
literals of the enumeration type that is named in the clause.

    enumeration_representation_clause ::= for type_simple_name use aggregate;

The aggregate used to specify this mapping is written as a  one-dimensional
aggregate,  for  which  the  index  subtype is the enumeration type and the
component type is universal_integer.

All literals of the enumeration type must be provided with distinct integer
codes, and all choices and component values given in the aggregate must  be
static.   The integer codes specified for the enumeration type must satisfy
the predefined ordering relation of the type.

Example:

    type MIX_CODE is (ADD, SUB, MUL, LDA, STA, STZ);

    for MIX_CODE use
       (ADD => 1, SUB => 2, MUL => 3, LDA => 8, STA => 24, STZ => 33);


Notes:

The attributes SUCC, PRED, and POS are defined even for  enumeration  types
with  a  noncontiguous representation;  their definition corresponds to the
(logical)  type  declaration  and  is  not  affected  by  the   enumeration
representation  clause.   In  the example, because of the need to avoid the
omitted  values,  these  functions  are  likely  to  be  less   efficiently
implemented  than  they could be in the absence of a representation clause.
Similar considerations apply when such types are used for indexing.


References:   aggregate  4.3,  array  aggregate  4.3.2,  array  type   3.6,
attribute  of  an  enumeration  type  3.5.5,  choice  3.7.3, component 3.3,
enumeration literal 3.5.1, enumeration type 3.5.1, function 6.5, index 3.6,
index subtype 3.6, literal 4.2, ordering relation of  an  enumeration  type
3.5.1,  representation clause 13.1, simple name 4.1, static expression 4.9,
type 3.3, type declaration 3.3.1, universal_integer type 3.5.4



13.4  Record Representation Clauses


A record representation clause  specifies  the  storage  representation  of
records,  that  is,  the  order,  position,  and  size of record components
(including discriminants, if any).

    record_representation_clause ::=
       for type_simple_name use
          record [alignment_clause]


                                  13 - 9








             {component_clause}
          end record;

    alignment_clause ::= at mod static_simple_expression;

    component_clause ::=
       component_name at static_simple_expression range static_range;


















































                                  13 - 10








The simple expression given after the reserved words at mod in an alignment
clause, or after the reserved word at in a  component  clause,  must  be  a
static  expression  of  some integer type.  If the bounds of the range of a
component clause are defined by simple expressions, then each bound of  the
range  must be defined by a static expression of some integer type, but the
two bounds need not have the same integer type.

An alignment clause forces each record of the given type to be allocated at
a starting address that is a multiple of the value of the given  expression
(that   is,   the   address  modulo  the  expression  must  be  zero).   An
implementation may place restrictions on the allowable alignments.

A component clause specifies the storage place of a component, relative  to
the start of the record.  The integer defined by the static expression of a
component  clause  is  a  relative address expressed in storage units.  The
range defines the bit positions of  the  storage  place,  relative  to  the
storage  unit.   The  first storage unit of a record is numbered zero.  The
first bit of a storage unit is numbered zero.  The ordering of  bits  in  a
storage unit is machine-dependent and may extend to adjacent storage units.
(For a specific machine, the size in bits of a storage unit is given by the
configuration-dependent   named  number  SYSTEM.STORAGE_UNIT.)   Whether  a
component is allowed to overlap a storage boundary,  and  if  so,  how,  is
implementation-defined.

At  most  one  component clause is allowed for each component of the record
type, including for each discriminant (component clauses may be  given  for
some, all, or none of the components).  If no component clause is given for
a component, then the choice of the storage place for the component is left
to  the  compiler.   If component clauses are given for all components, the
record representation clause completely specifies the representation of the
record type and must be obeyed exactly by the compiler.

Storage places within a record variant must not overlap, but overlap of the
storage for distinct variants is allowed.  Each component clause must allow
for enough storage space  to  accommodate  every  allowable  value  of  the
component.   A  component  clause  is  only  allowed for a component if any
constraint on this component or on any of its subcomponents is static.

An implementation may generate names that  denote  implementation-dependent
components  (for  example, one containing the offset of another component).
Such implementation-dependent names can be used  in  record  representation
clauses  (these names need not be simple names;  for example, they could be
implementation-dependent attributes).


Example:

    WORD : constant := 4;  --  storage unit is byte, 4 bytes per word

    type STATE      is (A, M, W, P);
    type MODE       is (FIX, DEC, EXP, SIGNIF);

    type BYTE_MASK  is array (0 .. 7) of BOOLEAN;
    type STATE_MASK is array (STATE)  of BOOLEAN;
    type MODE_MASK  is array (MODE)   of BOOLEAN;


                                  13 - 11








    type PROGRAM_STATUS_WORD is
       record
          SYSTEM_MASK     : BYTE_MASK;
          PROTECTION_KEY  : INTEGER range 0 .. 3;
          MACHINE_STATE   : STATE_MASK;
          INTERRUPT_CAUSE : INTERRUPTION_CODE;
          ILC             : INTEGER range 0 .. 3;
          CC              : INTEGER range 0 .. 3;
          PROGRAM_MASK    : MODE_MASK;
          INST_ADDRESS    : ADDRESS;
       end record;














































                                  13 - 12








    for PROGRAM_STATUS_WORD use
       record at mod 8;
          SYSTEM_MASK     at 0*WORD range 0  .. 7;
          PROTECTION_KEY  at 0*WORD range 10 .. 11;  --  bits 8, 9 unused
          MACHINE_STATE   at 0*WORD range 12 .. 15;
          INTERRUPT_CAUSE at 0*WORD range 16 .. 31;
          ILC             at 1*WORD range 0  .. 1;   --  second word
          CC              at 1*WORD range 2  .. 3;
          PROGRAM_MASK    at 1*WORD range 4  .. 7;
          INST_ADDRESS    at 1*WORD range 8  .. 31;
       end record;

    for PROGRAM_STATUS_WORD'SIZE use 8*SYSTEM.STORAGE_UNIT;

Note on the example:

The record representation clause defines the  record  layout.   The  length
clause guarantees that exactly eight storage units are used.

References:   allow  1.6,  attribute 4.1.4, constant 3.2.1, constraint 3.3,
discriminant 3.7.1, integer type 3.5.4, must 1.6, named number  3.2,  range
3.5,  record  component 3.7, record type 3.7, simple expression 4.4, simple
name 4.1, static constraint 4.9, static expression 4.9, storage unit  13.7,
subcomponent 3.3, system package 13.7, variant 3.7.3




13.5  Address Clauses


An address clause specifies a required address in storage for an entity.

    address_clause ::= for simple_name use at simple_expression;

The expression given after the reserved word at must be of the type ADDRESS
defined  in the package SYSTEM (see 13.7);  this package must be named by a
with clause that applies to the  compilation  unit  in  which  the  address
clause  occurs.   The conventions that define the interpretation of a value
of the type ADDRESS as an address, as an interrupt level,  or  whatever  it
may  be,  are  implementation-dependent.   The allowed nature of the simple
name and the meaning of the corresponding address are as follows:

(a)  Name of an object:  the  address  is  that  required  for  the  object
     (variable or constant).

(b)  Name of a subprogram, package, or task  unit:   the  address  is  that
     required  for the machine code associated with the body of the program
     unit.

(c)  Name of a single entry:  the address specifies a hardware interrupt to
     which the single entry is to be linked.

If the simple name is  that  of  a  single  task,  the  address  clause  is
understood  to  refer  to the task unit and not to the task object.  In all


                                  13 - 13








cases, the address clause is only legal if  exactly  one  declaration  with
this  identifier  occurs  earlier,  immediately within the same declarative
part, package specification, or task specification.  A name declared  by  a
renaming declaration is not allowed as the simple name.

Address  clauses  should  not  be  used  to  achieve overlays of objects or
overlays of program units.  Nor should a given interrupt be linked to  more
than  one entry.  Any program using address clauses to achieve such effects
is erroneous.
















































                                  13 - 14








Example:


    for CONTROL use at 16#0020#;  --  assuming that SYSTEM.ADDRESS is an integer type

Notes:

The above rules imply that if two subprograms overload each other  and  are
visible at a given point, an address clause for any of them is not legal at
this  point.   Similarly  if  a  task  specification  declares entries that
overload each other, they cannot be interrupt entries.  The syntax does not
allow an address clause for a library unit.  An implementation may  provide
pragmas for the specification of program overlays.


References:   address  predefined type 13.7, apply 10.1.1, compilation unit
10.1, constant 3.2.1, entity 3.1, entry 9.5, erroneous 1.6, expression 4.4,
library unit 10.1, name 4.1, object 3.2, package  7,  pragma  2.8,  program
unit  6,  reserved  word  2.9,  simple  expression  4.4,  simple  name 4.1,
subprogram 6, subprogram body 6.3, system package 13.7, task body 9.1, task
object 9.2, task unit 9, type 3.3, variable 3.2.1, with clause 10.1.1




13.5.1  Interrupts


An address clause given for an entry associates the entry with some  device
that  may cause an interrupt;  such an entry is referred to in this section
as an  interrupt  entry.   If  control  information  is  supplied  upon  an
interrupt,  it  is  passed  to an associated interrupt entry as one or more
parameters of mode in;  only parameters of this mode are allowed.

An interrupt acts as an entry call issued by a hardware task whose priority
is higher than the priority of the main program, and also higher  than  the
priority of any user-defined task (that is, any task whose type is declared
by  a  task  unit in the program).  The entry call may be an ordinary entry
call, a timed entry call, or a conditional entry  call,  depending  on  the
kind of interrupt and on the implementation.

If  a  select statement contains both a terminate alternative and an accept
alternative for an interrupt  entry,  then  an  implementation  may  impose
further  requirements  for  the  selection  of the terminate alternative in
addition to those given in section 9.4.

Example:

    task INTERRUPT_HANDLER is
       entry DONE;
       for DONE use at 16#40#;  --  assuming that SYSTEM.ADDRESS is an integer type
    end INTERRUPT_HANDLER;

Notes:



                                  13 - 15








Interrupt entry calls need only have the semantics described  above;   they
may  be implemented by having the hardware directly execute the appropriate
accept statements.

Queued interrupts correspond to ordinary entry calls.  Interrupts that  are
lost  if  not  immediately processed correspond to conditional entry calls.
It is a consequence of the priority rules that an accept statement executed
in response to an interrupt takes precedence  over  ordinary,  user-defined
tasks, and can be executed without first invoking a scheduling action.
















































                                  13 - 16








One  of the possible effects of an address clause for an interrupt entry is
to specify the priority of the interrupt (directly or indirectly).   Direct
calls to an interrupt entry are allowed.

References:   accept  alternative  9.7.1,  accept  statement  9.5,  address
predefined type 13.7, allow 1.6, conditional entry call 9.7.2,  entry  9.5,
entry call 9.5, mode 6.1, parameter of a subprogram 6.2, priority of a task
9.8,  select  alternative 9.7.1, select statement 9.7, system package 13.7,
task 9, terminate alternative 9.7.1, timed entry call 9.7.3




13.6  Change of Representation


At most one representation clause is allowed for a given type and  a  given
aspect  of  its representation.  Hence, if an alternative representation is
needed, it is necessary to declare a second type, derived from  the  first,
and to specify a different representation for the second type.

Example:

    --  PACKED_DESCRIPTOR and DESCRIPTOR are two different types
    --  with identical characteristics, apart from their representation

    type DESCRIPTOR is
       record
          --  components of a descriptor
       end record;

    type PACKED_DESCRIPTOR is new DESCRIPTOR;

    for PACKED_DESCRIPTOR use
       record
          --  component clauses for some or for all components
       end record;

Change  of  representation  can  now  be  accomplished  by  assignment with
explicit type conversions:

    D : DESCRIPTOR;
    P : PACKED_DESCRIPTOR;

    P := PACKED_DESCRIPTOR(D);  --  pack D
    D := DESCRIPTOR(P);         --  unpack P


References:  assignment 5.2, derived type 3.4, type  3.3,  type  conversion
4.6, type declaration 3.1, representation clause 13.1



13.7  The Package System



                                  13 - 17








For each implementation there is a predefined library package called SYSTEM
which   includes   the   definitions   of  certain  configuration-dependent
characteristics.    The   specification   of   the   package   SYSTEM    is
implementation-dependent and must be given in Appendix F.  The visible part
of this package must contain at least the following declarations.




















































                                  13 - 18








    package SYSTEM is
       type ADDRESS is implementation_defined;
       type NAME    is implementation_defined_enumeration_type;

       SYSTEM_NAME  : constant NAME := implementation_defined;

       STORAGE_UNIT : constant := implementation_defined;
       MEMORY_SIZE  : constant := implementation_defined;

       --  System-Dependent Named Numbers:

       MIN_INT      : constant := implementation_defined;
       MAX_INT      : constant := implementation_defined;
       MAX_DIGITS   : constant := implementation_defined;
       MAX_MANTISSA : constant := implementation_defined;
       FINE_DELTA   : constant := implementation_defined;
       TICK         : constant := implementation_defined;

       --  Other System-Dependent Declarations

       subtype PRIORITY is INTEGER range implementation_defined;

       ...
    end SYSTEM;

The  type ADDRESS is the type of the addresses provided in address clauses;
it is also the type of the  result  delivered  by  the  attribute  ADDRESS.
Values  of  the  enumeration type NAME are the names of alternative machine
configurations handled by the implementation;  one of these is the constant
SYSTEM_NAME.  The named number STORAGE_UNIT  is  the  number  of  bits  per
storage  unit;   the  named  number  MEMORY_SIZE is the number of available
storage units in the configuration;  these named numbers are  of  the  type
universal_integer.

An  alternative  form  of  the package SYSTEM, with given values for any of
SYSTEM_NAME, STORAGE_UNIT, and MEMORY_SIZE, can be obtained by means of the
corresponding pragmas.  These pragmas are only allowed at the  start  of  a
compilation, before the first compilation unit (if any) of the compilation.

    pragma SYSTEM_NAME(enumeration_literal);

The  effect  of the above pragma is to use the enumeration literal with the
specified identifier for the definition of the constant SYSTEM_NAME.   This
pragma  is  only  allowed if the specified identifier corresponds to one of
the literals of the type NAME.

    pragma STORAGE_UNIT(numeric_literal);

The effect of the above pragma is to use the value of the specified numeric
literal for the definition of the named number STORAGE_UNIT.

    pragma MEMORY_SIZE(numeric_literal);

The effect of the above pragma is to use the value of the specified numeric
literal for the definition of the named number MEMORY_SIZE.


                                  13 - 19








The compilation of any of these pragmas causes an implicit recompilation of
the package SYSTEM.  Consequently any compilation unit that names SYSTEM in
its context clause becomes obsolete after this implicit recompilation.   An
implementation  may impose further limitations on the use of these pragmas.
For example, an implementation may allow them only  at  the  start  of  the
first compilation, when creating a new program library.

Note:

It is a consequence of the visibility rules that a declaration given in the
package  SYSTEM is not visible in a compilation unit unless this package is
mentioned by a with clause that applies (directly  or  indirectly)  to  the
compilation unit.



References:    address   clause   13.5,   apply  10.1.1,  attribute  4.1.4,
compilation  unit  10.1,  declaration  3.1,  enumeration   literal   3.5.1,
enumeration  type 3.5.1, identifier 2.3, library unit 10.1, must 1.6, named
number 3.2, number declaration  3.2.2,  numeric  literal  2.4,  package  7,
package  specification  7.1,  pragma  2.8,  program library 10.1, type 3.3,
visibility 8.3, visible part 7.2, with clause 10.1.1




13.7.1  System-Dependent Named Numbers


Within the package SYSTEM, the following named numbers are  declared.   The
numbers FINE_DELTA and TICK are of the type universal_real;  the others are
of the type universal_integer.

MIN_INT       The smallest (most negative) value of all predefined  integer
              types.

MAX_INT       The largest (most positive) value of all  predefined  integer
              types.

MAX_DIGITS    The largest value  allowed  for  the  number  of  significant
              decimal digits in a floating point constraint.

MAX_MANTISSA  The largest possible number of binary digits in the  mantissa
              of model numbers of a fixed point subtype.

FINE_DELTA    The smallest delta allowed in a fixed point  constraint  that
              has the range constraint -1.0 .. 1.0.

TICK          The basic clock period, in seconds.



References:   allow  1.6,  delta  of  a fixed point constraint 3.5.9, fixed
point constraint 3.5.9,  floating  point  constraint  3.5.7,  integer  type
3.5.4,  model  number  3.5.6, named number 3.2, package 7, range constraint


                                  13 - 20








3.5,  system  package  13.7,  type  3.3,  universal_integer   type   3.5.4,
universal_real type 3.5.6























































                                  13 - 21








13.7.2  Representation Attributes


The  values  of  certain  implementation-dependent  characteristics  can be
obtained by interrogating  appropriate  representation  attributes.   These
attributes are described below.

For any object, program unit, label, or entry X:

X'ADDRESS       Yields the address  of  the  first  of  the  storage  units
                allocated  to  X.   For a subprogram, package, task unit or
                label, this value refers to  the  machine  code  associated
                with the corresponding body or statement.  For an entry for
                which an address clause has been given, the value refers to
                the  corresponding  hardware  interrupt.  The value of this
                attribute is of the type ADDRESS  defined  in  the  package
                SYSTEM.

For any type or subtype X, or for any object X:

X'SIZE          Applied to an object, yields the number of  bits  allocated
                to  hold  the object.  Applied to a type or subtype, yields
                the  minimum  number  of  bits  that  is  needed   by   the
                implementation  to hold any possible object of this type or
                subtype.  The value  of  this  attribute  is  of  the  type
                universal_integer.

For the above two representation attributes, if the prefix is the name of a
function,  the  attribute  is understood to be an attribute of the function
(not of the result of calling the function).  Similarly, if the type of the
prefix is an access type, the attribute is understood to be an attribute of
the prefix (not of the designated object:  attributes of the latter can  be
written with a prefix ending with the reserved word all).

For any component C of a record object R:

R.C'POSITION    Yields the offset, from the start of the first storage unit
                occupied  by  the record, of the first of the storage units
                occupied by C.  This offset is measured in  storage  units.
                The    value   of   this   attribute   is   of   the   type
                universal_integer.

R.C'FIRST_BIT   Yields the offset, from the  start  of  the  first  of  the
                storage  units  occupied by C, of the first bit occupied by
                C.  This offset is measured in bits.   The  value  of  this
                attribute is of the type universal_integer.

R.C'LAST_BIT    Yields the offset, from the  start  of  the  first  of  the
                storage units occupied by C, of the last bit occupied by C.
                This  offset  is  measured  in  bits.   The  value  of this
                attribute is of the type universal_integer.

For any access type or subtype T:




                                  13 - 22








T'STORAGE_SIZE  Yields the total number of storage units reserved  for  the
                collection  associated  with the base type of T.  The value
                of this attribute is of the type universal_integer.

For any task type or task object T:

T'STORAGE_SIZE  Yields the  number  of  storage  units  reserved  for  each
                activation of a task of the type T or for the activation of
                the  task  object T.  The value of this attribute is of the
                type universal_integer.















































                                  13 - 23








Notes:

For a task object X, the attribute X'SIZE gives the number of bits used  to
hold the object X, whereas X'STORAGE_SIZE gives the number of storage units
allocated  for  the  activation  of the task designated by X.  For a formal
parameter X, if parameter passing is achieved by copy, then  the  attribute
X'ADDRESS yields the address of the local copy;  if parameter passing is by
reference, then the address is that of the actual parameter.

References:   access  subtype  3.8, access type 3.8, activation 9.3, actual
parameter 6.2, address clause 13.5, address predefined type 13.7, attribute
4.1.4, base type 3.3, collection 3.8,  component  3.3,  entry  9.5,  formal
parameter  6.1  6.2,  label  5.1,  object 3.2, package 7, package body 7.1,
parameter passing 6.2, program unit 6,  record  object  3.7,  statement  5,
storage  unit  13.7, subprogram 6, subprogram body 6.3, subtype 3.3, system
predefined package 13.7, task 9, task body 9.1, task object 9.2, task  type
9.2, task unit 9, type 3.3, universal_integer type 3.5.4




13.7.3  Representation Attributes of Real Types


For   every  real  type  or  subtype  T,  the  following  machine-dependent
attributes are defined,  which  are  not  related  to  the  model  numbers.
Programs  using  these  attributes  may  thereby exploit properties that go
beyond the minimal properties associated with the numeric type (see section
4.5.7  for  the  rules  defining  the  accuracy  of  operations  with  real
operands).    Precautions   must   therefore  be  taken  when  using  these
machine-dependent attributes if portability is to be ensured.

For both floating point and fixed point types:

T'MACHINE_ROUNDS       Yields the value TRUE if every predefined arithmetic
                       operation on values of the base  type  of  T  either
                       returns   an  exact  result  or  performs  rounding;
                       yields the value FALSE otherwise.  The value of this
                       attribute is of the predefined type BOOLEAN.

T'MACHINE_OVERFLOWS    Yields the value TRUE if every predefined  operation
                       on  values  of  the base type of T either provides a
                       correct   result,   or    raises    the    exception
                       NUMERIC_ERROR  in  overflow  situations (see 4.5.7);
                       yields the value FALSE otherwise.  The value of this
                       attribute is of the predefined type BOOLEAN.

For floating point types, the following attributes provide  characteristics
of  the  underlying  machine representation, in terms of the canonical form
defined in section 3.5.7:

T'MACHINE_RADIX        Yields the value of the radix used  by  the  machine
                       representation  of the base type of T.  The value of
                       this attribute is of the type universal_integer.



                                  13 - 24








T'MACHINE_MANTISSA     Yields the number of digits in the mantissa for  the
                       machine  representation  of  the base type of T (the
                       digits  are  extended  digits  in  the  range  0  to
                       T'MACHINE_RADIX -1).  The value of this attribute is
                       of the type universal_integer.

T'MACHINE_EMAX         Yields the largest value of exponent for the machine
                       representation  of the base type of T.  The value of
                       this attribute is of the type universal_integer.

T'MACHINE_EMIN         Yields  the  smallest  (most  negative)   value   of
                       exponent  for the machine representation of the base
                       type of T.  The value of this attribute  is  of  the
                       type universal_integer.











































                                  13 - 25








Note:

For  many  machines  the  largest machine representable number of type F is
almost

    (F'MACHINE_RADIX)**(F'MACHINE_EMAX),

and the smallest positive representable number is

    F'MACHINE_RADIX ** (F'MACHINE_EMIN - 1)


References:  arithmetic operator  4.5,  attribute  4.1.4,  base  type  3.3,
boolean  predefined type 3.5.3, false boolean value 3.5.3, fixed point type
3.5.9, floating point type 3.5.7, model number  3.5.6,  numeric  type  3.5,
numeric_error exception 11.1, predefined operation 3.3.3, radix 3.5.7, real
type   3.5.6,   subtype   3.3,   true   boolean   value  3.5.3,  type  3.3,
universal_integer type 3.5.4




13.8  Machine Code Insertions


A machine code insertion can be achieved by a call  to  a  procedure  whose
sequence of statements contains code statements.

    code_statement ::= type_mark'record_aggregate;

A  code  statement  is  only  allowed  in  the  sequence of statements of a
procedure body.  If a procedure body contains code statements, then  within
this  procedure body the only allowed form of statement is a code statement
(labeled or not), the only allowed declarative items are use  clauses,  and
no  exception  handler  is  allowed  (comments  and  pragmas are allowed as
usual).

Each machine instruction appears as a record aggregate  of  a  record  type
that defines the corresponding instruction.  The base type of the type mark
of  a code statement must be declared within the predefined library package
called MACHINE_CODE;  this package must be named  by  a  with  clause  that
applies  to  the  compilation  unit in which the code statement occurs.  An
implementation is not required to provide such a package.

An implementation is allowed to impose further restrictions on  the  record
aggregates  allowed  in  code statements.  For example, it may require that
expressions contained in such aggregates be static expressions.

An implementation may provide machine-dependent pragmas specifying register
conventions and calling conventions.  Such pragmas must  be  documented  in
Appendix F.

Example:




                                  13 - 26








    M : MASK;
    procedure SET_MASK; pragma INLINE(SET_MASK);

    procedure SET_MASK is
       use MACHINE_CODE;
    begin
       SI_FORMAT'(CODE => SSM, B => M'BASE_REG, D => M'DISP);
       --  M'BASE_REG and M'DISP are implementation-specific predefined attributes
    end;
















































                                  13 - 27








References:   allow  1.6, apply 10.1.1, comment 2.7, compilation unit 10.1,
declarative item 3.9, exception handler 11.2, inline pragma 6.3.2,  labeled
statement  5.1,  library unit 10.1, package 7, pragma 2.8, procedure 6 6.1,
procedure body 6.3, record aggregate 4.3.1, record type  3.7,  sequence  of
statements  5.1,  statement  5, static expression 4.9, use clause 8.4, with
clause 10.1.1




13.9  Interface to Other Languages


A subprogram written in another language can be called from an Ada  program
provided  that  all  communication  is achieved via parameters and function
results.  A pragma of the form

    pragma INTERFACE (language_name, subprogram_name);

must be given for each such subprogram; a subprogram  name  is  allowed  to
stand  for  several  overloaded subprograms.  This pragma is allowed at the
place of a declarative item, and must apply in this case  to  a  subprogram
declared  by  an  earlier  declarative item of the same declarative part or
package specification.  The pragma is also allowed for a library unit;   in
this  case  the  pragma  must appear  after the subprogram declaration, and
before any subsequent compilation unit.  The  pragma  specifies  the  other
language  (and  thereby  the  calling conventions) and informs the compiler
that an object module will be supplied for the corresponding subprogram.  A
body is not allowed for such a subprogram (not even in the form of  a  body
stub)  since  the  instructions  of  the  subprogram are written in another
language.

This  capability  need  not  be  provided  by  all  implementations.     An
implementation  may place restrictions on the allowable forms and places of
parameters and calls.


Example:

    package FORT_LIB is
       function SQRT(X : FLOAT) return FLOAT;
       function EXP (X : FLOAT) return FLOAT;
    private
       pragma INTERFACE(FORTRAN, SQRT);
       pragma INTERFACE(FORTRAN, EXP);
    end FORT_LIB;

Notes:

The conventions used by other language processors that  call  Ada  programs
are  not  part  of  the  Ada language definition.  Such conventions must be
defined by these other language processors.

The pragma INTERFACE is not defined for generic subprograms.



                                  13 - 28









References:  allow 1.6, body stub 10.2, compilation unit 10.1,  declaration
3.1,  declarative  item  3.9,  declarative  part  3.9, function result 6.5,
library unit 10.1, must 1.6, name 4.1, overloaded subprogram  6.6,  package
specification 7.1, parameter of a subprogram 6.2, pragma 2.8, subprogram 6,
subprogram body 6.3, subprogram call 6.4, subprogram declaration 6.1



















































                                  13 - 29








13.10  Unchecked Programming


The  predefined  generic  library  subprograms  UNCHECKED_DEALLOCATION  and
UNCHECKED_CONVERSION are used for unchecked storage  deallocation  and  for
unchecked type conversions.

    generic
       type OBJECT is limited private;
       type NAME   is access OBJECT;
    procedure UNCHECKED_DEALLOCATION(X : in out NAME);

    generic
       type SOURCE is limited private;
       type TARGET is limited private;
    function UNCHECKED_CONVERSION(S : SOURCE) return TARGET;


References:  generic subprogram 12.1, library unit 10.1, type 3.3



13.10.1  Unchecked Storage Deallocation


Unchecked  storage  deallocation  of  an object designated by a value of an
access type is achieved by a call  of  a  procedure  that  is  obtained  by
instantiation   of   the  generic  procedure  UNCHECKED_DEALLOCATION.   For
example:

    procedure FREE is new UNCHECKED_DEALLOCATION(object_type_name, access_type_name);


Such a FREE procedure has the following effect:

(a)  after executing FREE(X), the value of X is null;

(b)  FREE(X), when X is already equal to null, has no effect;

(c)  FREE(X), when X is not equal to null, is an indication that the object
     designated by X is  no  longer  required,  and  that  the  storage  it
     occupies is to be reclaimed.

If  X and Y designate the same object, then accessing this object through Y
is erroneous if this access is performed  (or  attempted)  after  the  call
FREE(X);  the effect of each such access is not defined by the language.

Notes:

It  is  a  consequence  of  the visibility rules that the generic procedure
UNCHECKED_DEALLOCATION is not visible in a  compilation  unit  unless  this
generic  procedure  is  mentioned  by  a  with  clause  that applies to the
compilation unit.




                                  13 - 30








If X designates a task object, the call FREE(X) has no effect on  the  task
designated  by  the  value  of  this  task  object.  The same holds for any
subcomponent of the object designated by X, if this subcomponent is a  task
object.

References:    access  type  3.8,  apply  10.1.1,  compilation  unit  10.1,
designate 3.8 9.1,  erroneous  1.6,  generic  instantiation  12.3,  generic
procedure  12.1, generic unit 12, library unit 10.1, null access value 3.8,
object 3.2, procedure 6, procedure call 6.4, subcomponent 3.3, task 9, task
object 9.2, visibility 8.3, with clause 10.1.1















































                                  13 - 31








13.10.2  Unchecked Type Conversions


An unchecked type conversion can be achieved by a call of a  function  that
is  obtained by instantiation of the generic function UNCHECKED_CONVERSION.

The effect of an unchecked conversion  is  to  return  the  (uninterpreted)
parameter  value  as  a  value of the target type, that is, the bit pattern
defining the source value is returned unchanged as the bit pattern defining
a value of the target type.  An implementation may  place  restrictions  on
unchecked   conversions,   for   example,  restrictions  depending  on  the
respective  sizes  of  objects  of  the  source  and  target  type.    Such
restrictions must be documented in appendix F.

Whenever   unchecked   conversions   are   used,  it  is  the  programmer's
responsibility to ensure that these  conversions  maintain  the  properties
that  are  guaranteed  by  the  language  for  objects  of the target type.
Programs that violate these properties by means  of  unchecked  conversions
are erroneous.


Note:

It  is  a  consequence  of  the  visibility rules that the generic function
UNCHECKED_CONVERSION is not visible  in  a  compilation  unit  unless  this
generic  function  is  mentioned  by  a  with  clause  that  applies to the
compilation unit.


References:  apply 10.1.1, compilation unit 10.1,  erroneous  1.6,  generic
function 12.1, instantiation 12.3, parameter of a subprogram 6.2, type 3.3,
with clause 10.1.1

























                                  13 - 32