Contents
--------

1. What is gnatpp
2. GNATPP parameters
4. Formatting rules
3. Related information
4. Submitting bug reports


1. What is gnatpp
   --------------

GNATPP is the GNAT pretty-printer. It takes a compilable Ada source as input
and generates the reformatted version of the source as output. The user can
specify style directives such as rules of capitalization, rules of
indentation, comment layout, etc.

GNATPP has a command-line interface. By default the output is sent to the file
which name is obtained by appending the '.pp' suffix to the name of the
argument file (if the file with this name already exists, it is
unconditionally overridden). The GNATPP output can be directed to a specific
file or to Stdout. All diagnostic information is sent to Stderr.

GNATPP is an ASIS-based tool. It compiles the given source to create the
corresponding tree file. If the tree for the specified source already exists,
GNATPP tries to reuse it; it recreates the tree if the previous tree is
unusable, either because it was created by an older version of the compiler,
or because its own source is obsolete.  If GNATPP creates a tree file as a
part of its processing, then it deletes this tree file, as well as the
corresponding ALI file, after completion. If it has successfully reused an
existing tree file, it does not delete it. The ALI file is deleted by GNATPP
only if this file has been created as a part of this GNATPP run.

If the specified source file is not a legal Ada program, GNATPP cannot process
it. If the specified source depends on Ada units located in other directories,
the user has to provide the corresponding source search path, according to the
general GNAT rules, (s)he may use the '-I' GNATPP option to set this search
path explicitly.


2. GNATPP parameters
   -----------------

GNATPP has the following command-line interface:

    gnatpp [options] filename

GNATPP options (in alphabetic order):

 -A(0|1|2|3|4) - set alignment, all the alignments are set ON by default
   0 - set the default for all the alignments OFF
   1 - align colons in declarations
   2 - align assignments in declarations
   3 - align assignments in assignment statements
   4 - align arrow delimiters in associations
   Any combination of parameters can be set for -A option.

 -a(L|U|M) - set attribute casing
   L - lower case
   U - upper case
   M - mixed case (set as default) Mixed case means that the first letter and
       each letter following underscore is uppercase and all the other letters
       are lowercase

 -c(1|2|3|4) - comments layout
   1 - GNAT style comment line indentation (set as default)
   2 - standard comment line indentation
   3 - GNAT style comment beginning
   4 - reformat comment blocks
   All combinations are allowed for the -C option, except for C1 and C2
   which are mutually exclusive. For more details about comment
   formatting see the next section.

 -clnnn - indentation level for continuation lines, nnn from 1 .. 9. The
          default value is one less then the (normal) indentation level, unless
          the indentation is set to 1 (in that case the default value for
          continuation line indentation is also 1)

 -D<file> - set <file> as the dictionary file defining casing exceptions
 -D-      - do not use RM95-defined casing for predefined names, use casing
            defined by -n parameter and dictionary file(s) instead

 -e - do not insert missing end/exit labels. The end label is the name of
      a construct that may optionally appear at the end of the construct. This
      includes loop labels, and the names of packages and subprograms.
      Similarly, the exit label is the name of a loop that may appear at the
      end of the loop and that is also the argument of an exit statement within
      the loop. By default, GNATPP inserts these end/exit labels when they are
      absent in the original source. The -e option suppresses this insertion,
      so that the formatted source reflects the original.

 -gnatec<path> - the same as GNAT -gnatec option

 -innn - indentation level, nnn from 1 .. 9, the default value is 3

 -I<dir> - the same as gcc -I option
 -I-     - the same as gcc -I option

 -k(L|U) - set keyword casing
   L - lower case (set as default)
   U - upper case

 -l(1|2|3) - set construct layout
   1 - GNAT style layout (set as default)
   2 - compact layout
   3 - uncompact layout
   For more details, see the next section

 -Mnnn - set maximum line length, nnn from 32 ..256, the default value is 79

 -n(D|U|L|M) - set name casing (for both defining and usage occurrences)
   D - as declared (set as default)
   U - all in upper case
   L - all in lower case
   M - mixed

 -p(L|U|M) - set pragma casing
   L - lower case
   U - upper case
   M - mixed case (set as default)

 -r(D|M) - set references casing
   D - as declared (set as default)
   M - mixed

 -Tnnn - do not use an additional indentation level for case alternatives
         and variants if their number is nnn or more (the default value is
         10). If the parameter is zero, an additional indentation level is
         used for any number of case alternatives and variants.

 -v - verbose mode.

Output file control:
 -pipe - send the output into Stdout
 -o output_file - write the output into output_file. Give up if output_file
                  already exists
 -of output_file - write the output into output_file, overriding the existing
     file
 -r - replace the argument source with the pretty-printed source and copy the
      argument source into filename.npp. Give up if filename.npp already exists
 -rf - replace the argument source with the pretty-printed source and copy the
       argument source into filename.npp, overriding the existing file

 filename - the name of the Ada source file to be reformatted. The file
            should contain the compilable Ada source (with the given set of -I
            options). Its name does not have to follow GNAT file name rules

If an option allows the setting of more then one parameter, then each
parameter must be preceded by the option letter. That is, if you want to set
the alignment of the assignment delimiter both in declarations and in
assignments statements, you must write -A2A3 (or -A2 -A3), but not -A23.

3. Formatting rules
   ----------------

3.1 Formatting comments.

GNATPP leaves all comments exactly in the same locations as they have in the
original source (that is, in the formatted source each comment follows the
same lexical element as in the original source). Comments lines are indented
according to the corresponding code lines of the formatted sources. For
end-of-line comments (that is, comments which follow some lexemes belonging to
the Ada code), if in the formatted source the comment fits into one line,
GNATPP leaves the same number of spaces between the end of the last Ada lexeme
and the beginning of the comment as appear in the original source, except if
the comment has to be split to satisfy the line length limitation, or if there
are comment lines which are considered as a continuation of this end-of-line
comment. In the latter two cases, the start of the comment is moved right to
the nearest multiple of the indentation level.

The difference between -c1 (GNAT style comment line indentation) and -c2
(standard comment line indentation) is the following: for standard comment
indentation, any comment line is indented as if it were a declaration or
statement at the same place. For GNAT style comment indentation, comment lines
which are immediately followed by if or case statement alternative, record
variant or BEGIN keyword are indented as the keyword that follows them. For
example:

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

Standard 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;

Option -c3 (GNAT style comment beginning) means that for each comment which is
not considered as non-formattable separator (that is, the comment line
contains only dashes, or a comment line ends with two dashes), there must be
at least two spaces between starting "--" and the first non-blank character of
the comment.

For end-of-line comments, if in the original source the next line is a comment
line, and if the comment in this line starts from the same position as the
end-of-line comment, the comment line and all the following comment lines that
follow it and that start at the same position are made to start from the same
position as the end-of-line comment in the formatted source. That is, if in
the original source we have:

  begin
  A := B + C;            --  This assignment mean
                         --  something very important
               -- But I do not remember what...
  X := X + 1;

Then in the formatted source we get

  begin
     A := B + C;            --  This assignment mean
                            --  something very important
     -- But I do not remember what...
     X := X + 1;

Comments which exceeds the line length limitation are split. Unless option -c4
(reformat comment blocks) is set and the line belongs to a reformattable
block, splitting the line generates a GNATPP warning. The -c4 option specifies
that the comment lines which may be considered as containing some plain text
should be reformatted in typical word processor style (that is, moving words
between lines and putting as many words in a line as possible).

In the formatted source, comment lines do not ends with blank characters.

3.2 Construct layout

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

       GNAT style and                          Uncompact layout
       compact layout

       type q is record                        type q is
          a : integer;                            record
          b : integer;                               a : integer;
       end record;                                   b : integer;
                                                  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 in
GNAT style layout compound statements, return statements and bodies are always
separated by empty lines.

3.3 Name casing.

GNATPP always converts the usage occurrence of a (simple) name to the same
casing as the corresponding defining identifier has. As for defining
identifiers, GNATPP can either leave them as they are given in the argument
source (-nD option - "as declared"), or GNATPP may change the casing of
defining names according to the parameter of -n option: to convert it to
lower, upper or mixed case (the mixed case means that the first letter of the
name and the first letter immediately following the underline character are
uppercase and the rest is lowercase). If GNATPP changes the casing
occurrences, it also changes in the same way the casing of all the references
to these defining names.

If the defining occurrence of a name is not in the source (compilation unit)
currently processed by GNATPP, the casing of all the references to this name
is changed according to the GNATPP parameters (that is, it corresponds to the
casing of the defining name as if this defining name would also be formatted
by the GNATPP call with the same parameters).

For the names defined in the Ada Standard, GNATPP uses the same casing as it
is defined in RM95. -D- option abandons using RM95-defined casing for such
names, and the casing defined by -n option and exception dictionaries will be
used instead.

It is possible to define a set of exceptions to be used for name casing. These
exceptions can be specified in dictionary files. A dictionary file is an
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 it can
define exactly one case exception.

A case exception is defined by the string having the following syntax:

  case_Exception ::= identifier | [*]simple_identifier[*]

  simple_identifier ::= letter{letter_or_digit}

([]stands for optional parts, see RM95 for the definition of
identifier and letter_or_digit).

This string can be followed by white spaces and/or an Ada-style comment, any
number of white spaces is alloved before the string.

If a dictionary file is set as GNATPP parameter, 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 limited by '_' or by the end of the word and
which does not contain any '_' inside):

- if the whole name is in the dictionary, GNATPP use for this name the casing
  defined by the dictionary, no subwords are checked for this word;

- for the first subword (that is, for the subword limited by the leftmost
  '_'), the check is made 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;

- for the last subword (limited by the rightmost '_') the check is made 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;

- for every middle subword (surrounded by two'_') the check is made 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;

- if more then one dictionary file is set as GNATPP parameter, each
  dictionary adds new casing exceptions and overrides all the existing casing
  exceptions set by the previous dictionaries;

- when GNATPP checks if the word or subword is in the dictionary, this check
  is not case sensitive;

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*
   *NAME2

dict2
  *NAME3*

If GNATPP is called with the following options:

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

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;
      Nampe1_Var : Float
   begin
      name2_NAME3_name4 := name2_NAME3_name4 > NAME1;
   end Test;

3.4 Other GNATPP formatting rules.

The formatted source does not contain any format effectors except
platform-specific line breaks (except if these effectors are inside comments).
GNATPP does not have any option to control space characters. It put spaces
according to the RM95 coding style, additional spaces may be added for
alignment. In the formatted source, lines do not end with blank spaces.

For the empty lines contained in the original source, GNATPP keeps empty lines
only if they separate declarations or statements. Each sequence of empty lines
is replaced by exactly one empty line.

4. Related information
   -------------------

See GNAT User's Guide for more details about GNAT options.

See ASIS-for-GNAT User's Guide for more details concerning tree files.


5. Submitting bug reports
   ----------------------
All bug reports, as well as any comments concerning the GNATPP functionality
and options, are very welcomed. During the beta-testing period, they should be
sent to asis-report@gnat.com.

Usually, as a part of a problem report we need a complete set of sources to
reproduce the problem. In the case of GNATPP, it may be possible in some cases
to send only the code fragment that caused a failure or resulted in incorrect
formatting, together with the faulty formatted output.