------------------------------------------------------------------------------
--                                                                          --
--                            GNATPP COMPONENTS                             --
--                                                                          --
--                         G N A T P P . S T A T E                          --
--                                                                          --
--                                 S p e c                                  --
--                                                                          --
--                     Copyright (C) 2001-2014, AdaCore                     --
--                                                                          --
-- GNATPP is free software; you can redistribute it  and/or modify it under --
-- terms of the  GNU General Public License as published  by the Free Soft- --
-- ware  Foundation;  either version 2,  or (at your option) any later ver- --
-- sion.  GNATPP is  distributed in the  hope that it will  be  useful, but --
-- WITHOUT ANY WARRANTY; without even the implied warranty of  MERCHANTABI- --
-- LITY or  FITNESS  FOR A  PARTICULAR  PURPOSE. See the GNU General Public --
-- License  for more details. You  should  have  received a copy of the GNU --
-- General Public License  distributed with GNAT; see file COPYING. If not, --
-- write to the Free Software Foundation,  51 Franklin Street, Fifth Floor, --
-- Boston,                                                                  --
--                                                                          --
-- GNATPP is maintained by AdaCore (http://www.adacore.com)                 --
--                                                                          --
------------------------------------------------------------------------------

--  This package defines data which all together define the state of the
--  pretty-printer. Most of this data may be defined as the state of the
--  traversal, but we have only one traversal in GNATPP, and its state is
--  rather complicated, so we use global parameters to avoid passing
--  complicated structures as parameters of pre- and post-operations

with GNAT.OS_Lib;                     use GNAT.OS_Lib;
with Asis;                            use Asis;
with Asis.Text;                       use Asis.Text;
with Asis.Extensions.Flat_Kinds;      use Asis.Extensions.Flat_Kinds;

with GNATPP.Common;                   use GNATPP.Common;
with GNATPP.General_Traversal_Stacks; use GNATPP.General_Traversal_Stacks;

package GNATPP.State is

   Before_CU         : Boolean := False;
   In_Context_Clause : Boolean := False;
   In_Unit           : Boolean := False;
   Behind_Unit       : Boolean := False;
   --  These boolean flags show where we are in the original source

   Prev_Element_Kind : Flat_Element_Kinds := Not_An_Element;
   Prev_Element      : Asis.Element       := Nil_Element;
   --  Is used to keep the kind of the previous element when we are processing
   --  some lists (for example, when we are processing context clause, we
   --  need to know if there is a with clause just before the use clause to
   --  put this use clause on the same line).

   Last_KW : Keyword_Kinds := Not_A_KW;
   --  The last keyword sent into the output stream, each output routine should
   --  reset it. Is set to Not_A_KW if the latest outputted lexem was not a
   --  keyword. Outputting a comment or a line break does not change the value
   --  of this indicator

   Last_Dlm : Delimiter_Kinds := Not_A_Dlm;
   --  The last delimiter sent into the output stream, each output routine
   --  should reset it. Is set to Not_A_Dlm if the latest outputted lexem was
   --  not a keyword.  Outputting a comment or a line break does not change the
   --  value of this indicator

   Unary_Adding_Op_Just_Printed : Boolean := False;
   --  Flag indicating if the last outputted operator symbol was the unary plus
   --  or minus operator.

   Saved_Last_KW  : Keyword_Kinds := Not_A_KW;
   Saved_Last_Dlm : Delimiter_Kinds := Not_A_Dlm;
   --  Used to keep the values of the corresponding indicators when needed

   Is_First_Parameter_Spec       : Boolean := False;
   --  Flags used for list element pretty-printing

   Par_Specs_On_Separate_Lines : Boolean := False;

   The_Very_First_Line : Boolean := True;
   --  The boolean flag needed to detect the situation of the very first line
   --  to be sent into the output stream - in that case we do not need to call
   --  the new line procedure

   Current_Line       : Asis.Text.Line_Number;  --   ???
   --  The lines in the source corresponding to the currently visited Element.
   --  It is a line inside Element Span where the process of the
   --  pretty-printing is at the moment (Consider situations like this
   --
   --     procedure P is
   --        ...
   --     end -- some comment
   --        P --  some other comment
   --     --  one more comment line
   --     ;
   --
   --  Current_Line is updated each time when the given line is placed into
   --  Source Line Buffer.

   Current_Out_Line : Positive := 1;
   --  The number of the line in the output source

   Last_If_Path_Start : Natural := 0;
   --  The number of the output line where the last IF or ELSIF keyword has
   --  been printed

   Last_Loop_Start : Natural := 0;
   --  The number of the output line where the last WHILE or FOR keyword has
   --  been printed

   Last_Type_Start : Natural := 0;
   --  The number of the output line where the last TYPE keyword has been
   --  printed

   -------------------------------------------------------------------------
   Current_State : Traversal_Step_Record;
   --  The global variable for keeping the current state of the traversal,
   --  including the layout info

   Upper_Current_State : Traversal_Step_Record;
   --  Is used as a temporary storage for the global state if we need to make
   --  a change in the already computed layout

   procedure Initialize;
   --  (Re)initialize the global variables declared in this package, needed in
   --  case of multiple file processing

   -------------------------------------------------------------------------

   procedure Set_Prev_Element (The_Element : Asis.Element);
   --  Sets Prev_Element from its argument. The setting depends on argument.
   --  For now, the following settings are implemented:
   --
   --  with clause - a unit name if the clause contains only one unit name,
   --                Nil_Element otherwise
   --
   --  Nil_Element is set for all the cases that are not listed above.

   procedure Set_Current_State (The_Element : Asis.Element);
   --  Sets the Element and Span component of the current state. The layout
   --  info is set to the null value and is supposed to be computed later (if
   --  needed).

   procedure Get_Current_State;
   --  Gets Current_State from the traversal stack.

   Logical_Depth : Natural := 0;
   --  Nesting level counter. Note, that this is a logical nesting level - it
   --  grows up only when the part of the output line available for the
   --  pretty-printed text is enough for reasonable formatting. See below
   --  procedures Increase_Indentation and Decrease_Indentation for more
   --  details.
   --
   --  Note, that clients should never change this counter directly! Only
   --  procedures Increase_Indentation and Decrease_Indentation should be used.

   procedure Increase_Indentation;
   procedure Decrease_Indentation;
   procedure Set_Max_Nesting_Level;
   --  The first two procedures controls the indentation level for the output
   --  code. The general rule is - we can increase the indentation when the
   --  rest of the output line is enough for reasonable formatting. When we get
   --  to the indentation level which does not leave enough space in the output
   --  line, we generate the warning message and "freeze" the logical
   --  indentation level used for formatting. We also have the physical
   --  indentation counter which is changed according to the nesting level in
   --  the original source. When this counter goes down and reaches the level
   --  when the logical counter was frozen, the logical counter is de-frozen
   --  and starts to change again.
   --
   --  The level where the logical indentation counter is frozen depends on
   --  the settings for maximum line length and indentation level. It is
   --  computed by Set_Max_Nesting_Level procedure. At the moment we have the
   --  minimal number of positions that should be available in the output line
   --  as a hard-coded constant in GNATPP.Options. But we may think about
   --  adding the corresponding parameter to gnatpp.

   function Get_Current_SLOC return String;
   --  Forms the SLOC string from the name of the currently processed file,
   --  current line and current position

   ----------------------------------------
   --  File processing control variables --
   ----------------------------------------

   Arg_Source_Name : String_Access;  --  ???

   Res_File_Name   : String_Access;
   --  ???In Use_New_PP mode, this is used only for the -o and -of switches.

   Out_File_Exists : Boolean := False;

   File_Name_File_Name : String_Access;
   --  There is a "file name file"; this is its name. ASIS_Processing writes
   --  the output to a temp file, and Finalize moves the temp file to the
   --  actual output file. The file name file is used to pass the names of the
   --  temp and output files from ASIS_Processing to Finalize (both subunits of
   --  ASIS_UL.Source_Table.Processing).
   --
   --  ASIS_Processing is called once for each file, and it writes two lines to
   --  the file name file: the name of the temp file, and then the name of the
   --  output file. Finalize reads pairs of lines from the file name file, and
   --  moves temp --> output.
   --
   --  The reason for passing information via a file is that in
   --  Incremental_Mode, ASIS_Processing and Finalize are running in two
   --  different processes; the inner processes do ASIS_Processing, and needs
   --  to pass those file names back to the outer process. The builder is in
   --  between inner and outer, and doesn't know how to cooperate in this
   --  dance.
   --
   --  The reason for doing all the renames at the end (after all
   --  ASIS_Processing is done) is again Incremental_Mode, specifically
   --  Replace_Modes. We don't want to replace the original input with the
   --  output during ASIS_Processing, because that would change timestamps and
   --  confuse the builder.
   --
   --  In Incremental_Mode, the File_Name_File_Name is constructed in the outer
   --  invocation (in Initialize), and passed down to the inner invocations via
   --  the command-line switch --file-name-file=. --file-name-file is not
   --  documented for users; it is for internal use only. In other modes, it is
   --  constructed in Initialize.
   --
   --  We use the file name file even in non-Incremental_Mode, even though it's
   --  not really necessary, just for uniformity/simplicity.
   --
   --  In Replace_Modes, we optimize by not overwriting the output (i.e. the
   --  input) if it didn't change. This is especially important in
   --  Incremental_Mode, because of the way the builder works: it will invoke
   --  gnatpp (in Mimic_gcc mode) on something.adb, which will pretty-print
   --  something.ads. If something.ads didn't need pretty-printing, we don't
   --  want to change its timestamp, causing real (code-generating) builds to
   --  do unnecessary recompiles.

end GNATPP.State;
