Alternative File Naming Schemes (GNAT User’s Guide for Native Platforms)

#### 3.3.3 Alternative File Naming Schemes ¶

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:

- If there is a specific `Source_File_Name` pragma for the given unit, this is always used and any general pattern rules are ignored.
- If there is a pattern type `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.
- If no pattern type `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);