Ada '83 Quality and Style:
Guidelines for Professional Programmers
CHAPTER 7: Portability
This section introduces some generally applicable principles of writing
portable Ada programs. It includes guidelines about the assumptions you should
make with respect to a number of Ada features and their implementations and
guidelines about the use of other Ada features to ensure maximum portability.
guideline
- Make considered assumptions about the support provided for the
following on potential target platforms:
- Number of bits available for type
Integer
(range constraints).
- Number of decimal digits of precision available for floating point
types.
- Number of bits available for fixed-point types (delta and range
constraints).
- Number of characters per line of source text.
- Number of bits for
Universal_Integer
expressions.
- Number of seconds for the range of
Duration
.
- Number of milliseconds for
Duration'Small
.
instantiation
These are minimum values (or minimum precision in the case of
Duration'Small
)
that a project or application might assume that an implementation provides.
There is no guarantee that a given implementation provides more than the
minimum, so these would be treated by the project or application as maximum
values also.
- 16 bits available for type
Integer (-2**15 .. 2**15 - 1)
.
- 6 decimal digits of precision available for floating point types.
- 32 bits available for fixed-point types.
- 72 characters per line of source text.
- 16 bits for
Universal_Integer
expressions.
-86_400 .. 86_400
seconds (1 day) for the range of
Duration
(as
specified in 9.6 (4) of Department of Defense 1983))
- 20 milliseconds for
Duration'Small
(as specified in 9.6 (4) of
Department of Defense 1983)).
rationale
Some assumptions must be made with respect to certain implementation dependent
values. The exact values assumed should cover the majority of the target
equipment of interest. Choosing the lowest common denominator for values
improves portability.
note
Of the microcomputers currently available for incorporation within embedded
systems, 16-bit and 32-bit processors are prevalent. Although 4-bit and 8-bit
machines are still available, their limited memory addressing capabilities
make them unsuited to support Ada programs of any size. Using current
representation schemes, 6 decimal digits of floating point accuracy implies a
representation mantissa at least 21 bits wide, leaving 11 bits for exponent
and sign within a 32-bit representation. This correlates with the data widths
of floating point hardware currently available for the embedded systems
market. A 32-bit minimum on fixed-point numbers correlates with the accuracy
and storage requirements of floating point numbers.
The 72-column limit on source lines in the example is an unfortunate hold-over
from the days of Hollerith punch cards with sequence numbers. There may still
be machinery and software used in manipulating source code that are bound to
assumptions about this maximum line length. The 16-bit example for
Universal_Integer
expressions matches that for Integer
storage.
The values for the range and accuracy of values of the predefined type
Duration
are the limits expressed in the
Ada Language Reference Manual
(Department of Defense 1983, Section 9.6). You should not expect an implementation
to provide a wider range or a finer granularity.
Language Ref Manual references:
3.5.4 Integer Types,
3.5.6 Real Types,
3.5.9 Fixed Point Types,
9.6 Delay Statements, Duration, and Time,
C Predefined Language Environment,
F Implementation-Dependent Characteristics
guideline
- Don't implicitly use an implementation limit.
rationale
The Ada model may not match exactly with the underlying hardware, so some
compromises may have been made in the implementation. Check to see if they
could affect your program. Particular implementations may do "better" than the
Ada model requires while some others may be just minimally acceptable.
Arithmetic is generally implemented with a precision higher than the storage
capacity (this is implied by the Ada type model for floating point). Different
implementations may behave differently on the same underlying hardware.
Language Ref Manual references:
3.5.4 Integer Types,
3.5.6 Real Types,
F Implementation-Dependent Characteristics
guideline
- Use highlighting comments for each package, subprogram and task where
any nonportable features are present.
- For each nonportable feature employed, describe the expectations for
that feature.
example
------------------------------------------------------------------------
package Memory_Mapped_IO is
-- WARNING - This package is implementation specific.
-- It uses absolute memory addresses to interface with the I/O
-- system. It assumes a particular printer's line length.
-- Change memory mapping and printer details when porting.
Printer_Line_Length : constant := 132;
type Data is array (1 .. Printer_Line_Length) of Character;
procedure Write_Line (Line : in Data);
end Memory_Mapped_IO;
------------------------------------------------------------------------
with System;
package body Memory_Mapped_IO is
---------------------------------------------------------------------
procedure Write_Line (Line : in Data) is
Buffer : Data;
for Buffer use at System.Physical_Address(16#200#);
begin -- Write_Line
-- perform output operation through specific memory locations.
...
end Write_Line;
---------------------------------------------------------------------
end Memory_Mapped_IO;
------------------------------------------------------------------------ |
rationale
Explicitly commenting each breach of portability will raise its visibility and
aid in the porting process. A description of the non-portable feature's
expectations covers the common case where vendor documentation of the original
implementation is not available to the person performing the porting process.
Language Ref Manual references:
2.7 Comments,
6.1 Subprogram Declarations,
7.2 Package Specifications and Declarations,
9.1 Abort Statements,
F Implementation-Dependent Characteristics
guideline
- Use only a parameterless procedure as the main program.
rationale
The Ada Language Reference Manual
(Department of Defense 1983) places very few
requirements on the main subprogram. Assume the simplest case will increase
portability. That is, assume you may only use a parameterless procedure as a
main program.
Some operating systems are capable of acquiring and interpreting returned
integer values near zero from a function, but many others cannot. Further,
many real-time, embedded systems will not be designed to terminate, so a
function or a procedure having parameters with modes
out
or in out
will be
inappropriate to such applications.
This leaves procedures with in parameters. Although some operating systems can
pass parameters in to a program as it starts, others cannot. Also, an
implementation may not be able to perform type checking on such parameters
even if the surrounding environment is capable of providing them.
note
Real-time, embedded applications may not have an "operator" initiating the
program to supply the parameters, in which case it would be more appropriate
for the program to have been compiled with a package containing the
appropriate constant values or for the program to read the necessary values
from switch settings or a downloaded auxiliary file. In any case, the
variation in surrounding initiating environments is far too great to depend
upon the kind of last-minute (program) parameterization implied by
(subprogram) parameters to the main subprogram.
Language Ref Manual references:
6.1 Subprogram Declarations,
10.1 Compilation Units - Library Units
guideline
- Create packages specifically designed to isolate hardware and
implementation dependencies and designed so that their specification will not
change when porting.
- Clearly indicate the objectives if machine or solution efficiency is
the reason for hardware or implementation dependent code.
- For the packages that hide implementation dependencies, maintain
different package bodies for different target environments.
- Isolate interrupt receiving tasks into implementation dependent
packages.
example
See Guideline 7.1.3.
rationale
Encapsulating hardware and implementation dependencies in a package allows the
remainder of the code to ignore them and thus to be fully portable. It also
localizes the dependencies, making it clear exactly which parts of the code
may need to change when porting the program.
Some implementation-dependent features may be used to achieve particular
performance or efficiency objectives. Commenting these objectives ensures that
the programmer can find an appropriate way to achieve them when porting to a
different implementation, or explicitly recognize that they cannot be achieved.
Interrupt entries are implementation-dependent features that may not be
supported (e.g., VAX Ada uses pragmas to assign system traps to "normal"
rendezvous). However, interrupt entries cannot be avoided in most embedded
real-time systems and it is reasonable to assume that they are supported by an
Ada implementation. The value for an interrupt is implementation-defined.
Isolate it.
note
Ada can be used to write machine-dependent programs that take advantage of an
implementation in a manner consistent with the Ada model, but which make
particular choices where Ada allows implementation freedom. These machine
dependencies should be treated in the same way as any other implementation
dependent features of the code.
Language Ref Manual references:
2.7 Comments,
7.1 Package Structure,
7.2 Package Specifications and Declarations,
13.8 Machine Code Insertions,
13.9 Interface to Other Languages,
F Implementation-Dependent Characteristics
guideline
- Avoid the use of vendor supplied packages.
- Avoid the use of features added to the predefined packages that are
not specified in the language definition.
rationale
Vendor-added features are not likely to be provided by other implementations.
Even if a majority of vendors eventually provide similar additional features,
they are unlikely to have identical formulations. Indeed, different vendors
may use the same formulation for (semantically) entirely different features.
exceptions
There are many types of applications that require the use of these features.
Examples include: multilingual systems that standardize on a vendor's file
system, applications that are closely integrated with vendor products (i.e.,
user interfaces), and embedded systems for performance reasons. Isolate the
use of these features into packages.
Language Ref Manual references:
C Predefined Language Environment,
F Implementation-Dependent Characteristics
Back to document index