[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top] [Contents] [Index] [ ? ]

13. The GNAT Pretty-Printer gnatpp

The gnatpp tool is an ASIS-based utility for source reformatting / pretty-printing. It takes an Ada source file as input and generates a reformatted version as output. You can specify various style directives via switches; e.g., identifier case conventions, rules of indentation, and comment layout.

To produce a reformatted file, gnatpp generates and uses the ASIS tree for the input source and thus requires the input to be syntactically and semantically legal. If this condition is not met, gnatpp will terminate with an error message; no output file will be generated.

If the compilation unit contained in the input source depends semantically upon units located outside the current directory, you have to provide the source search path when invoking gnatpp, if these units are contained in files with names that do not follow the GNAT file naming rules, you have to provide the configuration file describing the corresponding naming scheme; see the description of the gnatpp switches below. Another possibility is to use a project file and to call gnatpp through the gnat driver

The gnatpp command has the form

 
$ gnatpp [switches] filename

where

13.1 Switches for gnatpp  
13.2 Formatting Rules  


[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top] [Contents] [Index] [ ? ]

13.1 Switches for gnatpp

The following subsections describe the various switches accepted by gnatpp, organized by category.

You specify a switch by supplying a name and generally also a value. In many cases the values for a switch with a given name are incompatible with each other (for example the switch that controls the casing of a reserved word may have exactly one value: upper case, lower case, or mixed case) and thus exactly one such switch can be in effect for an invocation of gnatpp. If more than one is supplied, the last one is used. However, some values for the same switch are mutually compatible. You may supply several such switches to gnatpp, but then each must be specified in full, with both the name and the value. Abbreviated forms (the name appearing once, followed by each value) are not permitted. For example, to set the alignment of the assignment delimiter both in declarations and in assignment statements, you must write `-A2A3' (or `-A2 -A3'), but not `-A23'.

In most cases, it is obvious whether or not the values for a switch with a given name are compatible with each other. When the semantics might not be evident, the summaries below explicitly indicate the effect.

13.1.1 Alignment Control  
13.1.2 Casing Control  
13.1.3 Construct Layout Control  
13.1.4 General Text Layout Control  
13.1.5 Other Formatting Options  
13.1.6 Setting the Source Search Path  
13.1.7 Output File Control  
13.1.8 Other gnatpp Switches  


[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top] [Contents] [Index] [ ? ]

13.1.1 Alignment Control

Programs can be easier to read if certain constructs are vertically aligned. By default all alignments are set ON. Through the `-A0' switch you may reset the default to OFF, and then use one or more of the other `-An' switches to activate alignment for specific constructs.

`-A0'
Set all alignments to OFF

`-A1'
Align : in declarations

`-A2'
Align := in initializations in declarations

`-A3'
Align := in assignment statements

`-A4'
Align => in associations

`-A5'
Align at keywords in the component clauses in record representation clauses

The `-A' switches are mutually compatible; any combination is allowed.


[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top] [Contents] [Index] [ ? ]

13.1.2 Casing Control

gnatpp allows you to specify the casing for reserved words, pragma names, attribute designators and identifiers. For identifiers you may define a general rule for name casing but also override this rule via a set of dictionary files.

Three types of casing are supported: lower case, upper case, and mixed case. Lower and upper case are self-explanatory (but since some letters in Latin1 and other GNAT-supported character sets exist only in lower-case form, an upper case conversion will have no effect on them.) "Mixed case" means that the first letter, and also each letter immediately following an underscore, are converted to their uppercase forms; all the other letters are converted to their lowercase forms.

`-aL'
Attribute designators are lower case

`-aU'
Attribute designators are upper case

`-aM'
Attribute designators are mixed case (this is the default)

`-kL'
Keywords (technically, these are known in Ada as reserved words) are lower case (this is the default)

`-kU'
Keywords are upper case

`-nD'
Name casing for defining occurrences are as they appear in the source file (this is the default)

`-nU'
Names are in upper case

`-nL'
Names are in lower case

`-nM'
Names are in mixed case

`-pL'
Pragma names are lower case

`-pU'
Pragma names are upper case

`-pM'
Pragma names are mixed case (this is the default)

`-Dfile'
Use file as a dictionary file that defines the casing for a set of specified names, thereby overriding the effect on these names by any explicit or implicit -n switch. To supply more than one dictionary file, use several `-D' switches.

`gnatpp' implicitly uses a default dictionary file to define the casing for the Ada predefined names and the names declared in the GNAT libraries.

`-D-'
Do not use the default dictionary file; instead, use the casing defined by a `-n' switch and any explicit dictionary file(s)

The structure of a dictionary file, and details on the conventions used in the default dictionary file, are defined in 13.2.4 Name Casing.

The `-D-' and `-Dfile' switches are mutually compatible.


[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top] [Contents] [Index] [ ? ]

13.1.3 Construct Layout Control

This group of gnatpp switches controls the layout of comments and complex syntactic constructs. See 13.2.2 Formatting Comments for details on their effect.

`-c0'
All the comments remain unchanged

`-c1'
GNAT-style comment line indentation (this is the default).

`-c2'
Reference-manual comment line indentation.

`-c3'
GNAT-style comment beginning

`-c4'
Reformat comment blocks

`-l1'
GNAT-style layout (this is the default)

`-l2'
Compact layout

`-l3'
Uncompact layout

`-N'
All the VT characters are removed from the comment text. All the HT characters are expanded with the sequences of space characters to get to the next tab stops.

The `-c1' and `-c2' switches are incompatible. The `-c3' and `-c4' switches are compatible with each other and also with `-c1' and `-c2'. The `-c0' switch disables all the other comment formatting switches.

The `-l1', `-l2', and `-l3' switches are incompatible.


[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top] [Contents] [Index] [ ? ]

13.1.4 General Text Layout Control

These switches allow control over line length and indentation.

`-Mnnn'
Maximum line length, nnn from 32 ..256, the default value is 79

`-innn'
Indentation level, nnn from 1 .. 9, the default value is 3

`-clnnn'
Indentation level for continuation lines (relative to the line being continued), nnn from 1 .. 9. The default value is one less then the (normal) indentation level, unless the indentation is set to 1 (in which case the default value for continuation line indentation is also 1)


[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top] [Contents] [Index] [ ? ]

13.1.5 Other Formatting Options

These switches control the inclusion of missing end/exit labels, and the indentation level in case statements.

`-e'
Do not insert missing end/exit labels. An end label is the name of a construct that may optionally be repeated at the end of the construct's declaration; e.g., the names of packages, subprograms, and tasks. An exit label is the name of a loop that may appear as target of an exit statement within the loop. By default, gnatpp inserts these end/exit labels when they are absent from the original source. This option suppresses such insertion, so that the formatted source reflects the original.

`-ff'
Insert a Form Feed character after a pragma Page.

`-Tnnn'
Do not use an additional indentation level for case alternatives and variants if there are nnn or more (the default value is 10). If nnn is 0, an additional indentation level is used for case alternatives and variants regardless of their number.


[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top] [Contents] [Index] [ ? ]

13.1.6 Setting the Source Search Path

To define the search path for the input source file, gnatpp uses the same switches as the GNAT compiler, with the same effects.

`-Idir'
The same as the corresponding gcc switch

`-I-'
The same as the corresponding gcc switch

`-gnatec=path'
The same as the corresponding gcc switch

`--RTS=path'
The same as the corresponding gcc switch


[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top] [Contents] [Index] [ ? ]

13.1.7 Output File Control

By default the output is sent to the file whose name is obtained by appending the `.pp' suffix to the name of the input file (if the file with this name already exists, it is unconditionally overwritten). Thus if the input file is `my_ada_proc.adb' then gnatpp will produce `my_ada_proc.adb.pp' as output file. The output may be redirected by the following switches:

`-pipe'
Send the output to Standard_Output

`-o output_file'
Write the output into output_file. If output_file already exists, gnatpp terminates without reading or processing the input file.

`-of output_file'
Write the output into output_file, overwriting the existing file (if one is present).

`-r'
Replace the input source file with the reformatted output, and copy the original input source into the file whose name is obtained by appending the `.npp' suffix to the name of the input file. If a file with this name already exists, gnatpp terminates without reading or processing the input file.

`-rf'
Like `-r' except that if the file with the specified name already exists, it is overwritten.

`-rnb'
Replace the input source file with the reformatted output without creating any backup copy of the input source.

Options `-pipe', `-o' and `-of' are allowed only if the call to gnatpp contains only one file to reformat


[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top] [Contents] [Index] [ ? ]

13.1.8 Other gnatpp Switches

The additional gnatpp switches are defined in this subsection.

`-files filename'
Take the argument source files from the specified file. This file should be an ordinary textual file containing file names separated by spaces or line breaks. You can use this switch more then once in the same call to gnatpp. You also can combine this switch with explicit list of files.

`-v'
Verbose mode; gnatpp generates version information and then a trace of the actions it takes to produce or obtain the ASIS tree.

`-w'
Warning mode; gnatpp generates a warning whenever it can not provide a required layout in the result source.


[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top] [Contents] [Index] [ ? ]

13.2 Formatting Rules

The following subsections show how gnatpp treats "white space", comments, program layout, and name casing. They provide the detailed descriptions of the switches shown above.

13.2.1 White Space and Empty Lines  
13.2.2 Formatting Comments  
13.2.3 Construct Layout  
13.2.4 Name Casing  


[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top] [Contents] [Index] [ ? ]

13.2.1 White Space and Empty Lines

gnatpp does not have an option to control space characters. It will add or remove spaces according to the style illustrated by the examples in the Ada Reference Manual.

The only format effectors (see Ada Reference Manual, paragraph 2.1(13)) that will appear in the output file are platform-specific line breaks, and also format effectors within (but not at the end of) comments. In particular, each horizontal tab character that is not inside a comment will be treated as a space and thus will appear in the output file as zero or more spaces depending on the reformatting of the line in which it appears. The only exception is a Form Feed character, which is inserted after a pragma Page when `-ff' is set.

The output file will contain no lines with trailing "white space" (spaces, format effectors).

Empty lines in the original source are preserved only if they separate declarations or statements. In such contexts, a sequence of two or more empty lines is replaced by exactly one empty line. Note that a blank line will be removed if it separates two "comment blocks" (a comment block is a sequence of whole-line comments). In order to preserve a visual separation between comment blocks, use an "empty comment" (a line comprising only hyphens) rather than an empty line. Likewise, if for some reason you wish to have a sequence of empty lines, use a sequence of empty comments instead.


[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top] [Contents] [Index] [ ? ]

13.2.2 Formatting Comments

Comments in Ada code are of two kinds:

The indentation of a whole-line comment is that of either the preceding or following line in the formatted source, depending on switch settings as will be described below.

For an end-of-line comment, gnatpp leaves the same number of spaces between the end of the preceding Ada lexical element and the beginning of the comment as appear in the original source, unless either the comment has to be split to satisfy the line length limitation, or else the next line contains a whole line comment that is considered a continuation of this end-of-line comment (because it starts at the same position). In the latter two cases, the start of the end-of-line comment is moved right to the nearest multiple of the indentation level. This may result in a "line overflow" (the right-shifted comment extending beyond the maximum line length), in which case the comment is split as described below.

There is a difference between `-c1' (GNAT-style comment line indentation) and `-c2' (reference-manual comment line indentation). With reference-manual style, a whole-line comment is indented as if it were a declaration or statement at the same place (i.e., according to the indentation of the preceding line(s)). With GNAT style, a whole-line comment that is immediately followed by an if or case statement alternative, a record variant, or the reserved word begin, is indented based on the construct that follows it.

For example:
 
if A then
    null;
       -- some comment
else
   null;
end if;

Reference-manual indentation produces:

 
if A then
   null;
   --  some comment
else
   null;
end if;

while GNAT-style indentation produces:

 
if A then
   null;
--  some comment
else
   null;
end if;

The `-c3' switch (GNAT style comment beginning) has the following effect:

For an end-of-line comment, if in the original source the next line is a whole-line comment that starts at the same position as the end-of-line comment, then the whole-line comment (and all whole-line comments that follow it and that start at the same position) will start at this position in the output file.

That is, if in the original source we have:

 
begin
A := B + C;            --  B must be in the range Low1..High1
                       --  C must be in the range Low2..High2
             --B+C will be in the range Low1+Low2..High1+High2
X := X + 1;

Then in the formatted source we get

 
begin
   A := B + C;            --  B must be in the range Low1..High1
                          --  C must be in the range Low2..High2
   --  B+C will be in the range Low1+Low2..High1+High2
   X := X + 1;

A comment that exceeds the line length limit will be split. Unless switch `-c4' (reformat comment blocks) is set and the line belongs to a reformattable block, splitting the line generates a gnatpp warning. The `-c4' switch specifies that whole-line comments may be reformatted in typical word processor style (that is, moving words between lines and putting as many words in a line as possible).


[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top] [Contents] [Index] [ ? ]

13.2.3 Construct Layout

In several cases the suggested layout in the Ada Reference Manual includes an extra level of indentation that many programmers prefer to avoid. The affected cases include:

In compact mode (when GNAT style layout or compact layout is set), the pretty printer uses one level of indentation instead of two. This is achived in the record definition and record representation clause cases by putting the record keyword on the same line as the start of the declaration or representation clause, and in the block and loop case by putting the block or loop header on the same line as the statement identifier.

The difference between GNAT style `-l1' and compact `-l2' layout on the one hand, and uncompact layout `-l3' on the other hand, can be illustrated by the following examples:

 
GNAT style, compact layout              Uncompact layout

type q is record                        type q is
   a : integer;                            record
   b : integer;                               a : integer;
end record;                                   b : integer;
                                           end record;

for q use record                        for q use
   a at 0 range  0 .. 31;                  record
   b at 4 range  0 .. 31;                     a at 0 range  0 .. 31;
end record;                                   b at 4 range  0 .. 31;
                                           end record;

Block : declare                         Block :
   A : Integer := 3;                       declare
begin                                         A : Integer := 3;
   Proc (A, A);                            begin
end Block;                                    Proc (A, A);
                                           end Block;

Clear : for J in 1 .. 10 loop           Clear :
   A (J) := 0;                             for J in 1 .. 10 loop
end loop Clear;                               A (J) := 0;
                                           end loop Clear;

A further difference between GNAT style layout and compact layout is that GNAT style layout inserts empty lines as separation for compound statements, return statements and bodies.


[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top] [Contents] [Index] [ ? ]

13.2.4 Name Casing

gnatpp always converts the usage occurrence of a (simple) name to the same casing as the corresponding defining identifier.

You control the casing for defining occurrences via the `-n' switch. With `-nD' ("as declared", which is the default), defining occurrences appear exactly as in the source file where they are declared. The other values for this switch --- `-nU', `-nL', `-nM' --- result in upper, lower, or mixed case, respectively. If gnatpp changes the casing of a defining occurrence, it analogously changes the casing of all the usage occurrences of this name.

If the defining occurrence of a name is not in the source compilation unit currently being processed by gnatpp, the casing of each reference to this name is changed according to the value of the `-n' switch (subject to the dictionary file mechanism described below). Thus gnatpp acts as though the `-n' switch had affected the casing for the defining occurrence of the name.

Some names may need to be spelled with casing conventions that are not covered by the upper-, lower-, and mixed-case transformations. You can arrange correct casing by placing such names in a dictionary file, and then supplying a `-D' switch. The casing of names from dictionary files overrides any `-n' switch.

To handle the casing of Ada predefined names and the names from GNAT libraries, gnatpp assumes a default dictionary file. The name of each predefined entity is spelled with the same casing as is used for the entity in the Ada Reference Manual. The name of each entity in the GNAT libraries is spelled with the same casing as is used in the declaration of that entity.

The `-D-' switch suppresses the use of the default dictionary file. Instead, the casing for predefined and GNAT-defined names will be established by the `-n' switch or explicit dictionary files. For example, by default the names Ada.Text_IO and GNAT.OS_Lib will appear as just shown, even in the presence of a `-nU' switch. To ensure that even such names are rendered in uppercase, additionally supply the `-D-' switch (or else, less conveniently, place these names in upper case in a dictionary file).

A dictionary file is a plain text file; each line in this file can be either a blank line (containing only space characters and ASCII.HT characters), an Ada comment line, or the specification of exactly one casing schema.

A casing schema is a string that has the following syntax:

 
  casing_schema ::= identifier | *simple_identifier*

  simple_identifier ::= letter{letter_or_digit}

(See Ada Reference Manual, Section 2.3) for the definition of the identifier lexical element and the letter_or_digit category.)

The casing schema string can be followed by white space and/or an Ada-style comment; any amount of white space is allowed before the string.

If a dictionary file is passed as the value of a `-Dfile' switch then for every simple name and every identifier, gnatpp checks if the dictionary defines the casing for the name or for some of its parts (the term "subword" is used below to denote the part of a name which is delimited by "_" or by the beginning or end of the word and which does not contain any "_" inside):

For example, suppose we have the following source to reformat:

 
procedure test is
   name1 : integer := 1;
   name4_name3_name2 : integer := 2;
   name2_name3_name4 : Boolean;
   name1_var : Float;
begin
   name2_name3_name4 := name4_name3_name2 > name1;
end;

And suppose we have two dictionaries:

 
dict1:
   NAME1
   *NaMe3*
   *Name1*

dict2:
  *NAME3*

If gnatpp is called with the following switches:

 
gnatpp -nM -D dict1 -D dict2 test.adb

then we will get the following name casing in the gnatpp output:

 
procedure Test is
   NAME1             : Integer := 1;
   Name4_NAME3_Name2 : Integer := 2;
   Name2_NAME3_Name4 : Boolean;
   Name1_Var         : Float;
begin
   Name2_NAME3_Name4 := Name4_NAME3_Name2 > NAME1;
end Test;


[ << ] [ >> ]           [Top] [Contents] [Index] [ ? ]

This document was generated by Mail Server on June, 15 2005 using texi2html