[ < ] | [ > ] | [ << ] | [ Up ] | [ >> ] | [Top] | [Contents] | [Index] | [ ? ] |
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] | [ ? ] |
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.
[ < ] | [ > ] | [ << ] | [ Up ] | [ >> ] | [Top] | [Contents] | [Index] | [ ? ] |
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.
:
in declarations
:=
in initializations in declarations
:=
in assignment statements
=>
in associations
at
keywords in the component clauses in record
representation clauses
The `-A' switches are mutually compatible; any combination is allowed.
[ < ] | [ > ] | [ << ] | [ Up ] | [ >> ] | [Top] | [Contents] | [Index] | [ ? ] |
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.
`gnatpp' implicitly uses a default dictionary file to define the casing for the Ada predefined names and the names declared in the GNAT libraries.
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] | [ ? ] |
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.
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] | [ ? ] |
These switches allow control over line length and indentation.
[ < ] | [ > ] | [ << ] | [ Up ] | [ >> ] | [Top] | [Contents] | [Index] | [ ? ] |
These switches control the inclusion of missing end/exit labels, and the indentation level in case statements.
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.
[ < ] | [ > ] | [ << ] | [ Up ] | [ >> ] | [Top] | [Contents] | [Index] | [ ? ] |
To define the search path for the input source file, gnatpp
uses the same switches as the GNAT compiler, with the same effects.
[ < ] | [ > ] | [ << ] | [ Up ] | [ >> ] | [Top] | [Contents] | [Index] | [ ? ] |
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:
Standard_Output
gnatpp
terminates without
reading or processing the input file.
gnatpp
terminates without
reading or processing the input file.
Options `-pipe', `-o' and `-of' are allowed only if the call to gnatpp contains only one file to reformat
[ < ] | [ > ] | [ << ] | [ Up ] | [ >> ] | [Top] | [Contents] | [Index] | [ ? ] |
gnatpp
Switches
The additional gnatpp
switches are defined in this subsection.
gnatpp
. You also can combine this switch with explicit list of
files.
gnatpp
generates version information and then
a trace of the actions it takes to produce or obtain the ASIS tree.
gnatpp
generates a warning whenever it can not provide
a required layout in the result source.
[ < ] | [ > ] | [ << ] | [ Up ] | [ >> ] | [Top] | [Contents] | [Index] | [ ? ] |
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] | [ ? ] |
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] | [ ? ] |
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:
gnatpp
inserts spaces if necessary after the starting two hyphens
to ensure that there are at least two spaces between these hyphens and the
first non-blank character of the comment.
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] | [ ? ] |
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] | [ ? ] |
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):
gnatpp
uses for this name
the casing defined by the dictionary; no subwords are checked for this word
gnatpp
checks if the dictionary contains the
corresponding string of the form *simple_identifier*
,
and if it does, the casing of this simple_identifier is used
for this subword
gnatpp
switches, each
dictionary adds new casing exceptions and overrides all the existing casing
exceptions set by the previous dictionaries
gnatpp
checks if the word or subword is in the dictionary,
this check is not case sensitive
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:
|
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] | [ ? ] |