The previous section described the use of the Source_File_Name
pragma to allow arbitrary names to be assigned to individual source files.
However, this approach requires one pragma for each file and, especially in
large systems, can result in very long gnat.adc
files, which can create
a maintenance problem.
GNAT also provides a facility for specifying systematic file naming schemes
other than the standard default naming scheme previously described. An
alternative scheme for naming is specified by the use of
Source_File_Name
pragmas having the following format:
pragma Source_File_Name ( Spec_File_Name => FILE_NAME_PATTERN [ , Casing => CASING_SPEC] [ , Dot_Replacement => STRING_LITERAL ] ); pragma Source_File_Name ( Body_File_Name => FILE_NAME_PATTERN [ , Casing => CASING_SPEC ] [ , Dot_Replacement => STRING_LITERAL ] ) ; pragma Source_File_Name ( Subunit_File_Name => FILE_NAME_PATTERN [ , Casing => CASING_SPEC ] [ , Dot_Replacement => STRING_LITERAL ] ) ; FILE_NAME_PATTERN ::= STRING_LITERAL CASING_SPEC ::= Lowercase | Uppercase | Mixedcase
The FILE_NAME_PATTERN
string shows how the file name is constructed.
It contains a single asterisk character, and the unit name is substituted
systematically for this asterisk. The optional parameter
Casing
indicates
whether the unit name is to be all upper-case letters, all lower-case letters,
or mixed-case. If no
Casing
parameter is used, the default is all
lower-case.
You use the optional Dot_Replacement
string to replace any periods
that occur in subunit or child unit names. If you don’t specify a
Dot_Replacement
argument, separating dots appear unchanged in the
resulting file name. The above syntax indicates that the Casing
argument must appear before the Dot_Replacement
argument, but you
can write these arguments in any order.
As indicated, you can specify different naming schemes for
bodies, specs, and subunits. Quite often, the rule for subunits is the
same as the rule for bodies, in which case, you need not provide
a separate Subunit_File_Name
rule; in this case the
Body_File_name
rule is used for subunits as well.
You can also use the separate rule for subunits to implement the rather unusual case of a compilation environment (e.g., a single directory) which contains a subunit and a child unit with the same unit name. Although both units cannot appear in the same partition, the Ada Reference Manual allows (but does not require) the possibility of the two units coexisting in the same environment.
File name translation consists of the following steps:
Source_File_Name
pragma for the given unit,
this is always used and any general pattern rules are ignored.
Source_File_Name
pragma that applies to
the unit, the resulting file name is used if the file exists. If
more than one pattern matches, the latest one is tried first and the
first attempt that results in a reference to a file that exists is used.
Source_File_Name
pragma that applies to the unit
for which the corresponding file exists, the standard GNAT default
naming rules are used.
As an example of the use of this mechanism, consider a commonly used scheme
in which file names are all lower case, with separating periods copied
unchanged to the resulting file name, specs end with .1.ada
, and
bodies end with .2.ada
. GNAT will follow this scheme if the following
two pragmas appear:
pragma Source_File_Name (Spec_File_Name => ".1.ada"); pragma Source_File_Name (Body_File_Name => ".2.ada");
The default GNAT scheme is equivalent to providing the following default pragmas:
pragma Source_File_Name (Spec_File_Name => ".ads", Dot_Replacement => "-"); pragma Source_File_Name (Body_File_Name => ".adb", Dot_Replacement => "-");
Our final example implements a scheme typically used with one of the
legacy Ada 83 compilers, where the separator character for subunits was ‘__’
(two underscores), specs were identified by adding _.ADA
, bodies
by adding .ADA
, and subunits by
adding .SEP
. All file names were
upper case. Child units were not present, of course, since this was an
Ada 83 compiler, but it seems reasonable to extend this scheme to use
the same double underscore separator for child units.
pragma Source_File_Name (Spec_File_Name => "_.ADA", Dot_Replacement => "__", Casing = Uppercase); pragma Source_File_Name (Body_File_Name => ".ADA", Dot_Replacement => "__", Casing = Uppercase); pragma Source_File_Name (Subunit_File_Name => ".SEP", Dot_Replacement => "__", Casing = Uppercase);