In the previous section, we 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, and also 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, then the default is all
lower-case.
The optional Dot_Replacement
string is used to replace any periods
that occur in subunit or child unit names. If no Dot_Replacement
argument is used then separating dots appear unchanged in the resulting
file name.
Although the above syntax indicates that the
Casing
argument must appear
before the Dot_Replacement
argument, but it
is also permissible to write these arguments in the opposite order.
As indicated, it is possible to 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, there is no need to give
a separate Subunit_File_Name
rule, and in this case the
Body_File_name
rule is used for subunits as well.
The separate rule for subunits can also be used 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.
The file name translation works in the following steps:
Source_File_Name
pragma for the given unit,
then this is always used, and any general pattern rules are ignored.
Source_File_Name
pragma that applies to
the unit, then the resulting file name will be used if the file exists. If
more than one pattern matches, the latest one will be tried first, and the
first attempt resulting in a reference to a file that exists will be used.
Source_File_Name
pragma that applies to the unit
for which the corresponding file exists, then 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, and 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 actually implemented by providing the following default pragmas internally:
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 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);