From edfccd332a56771311fefdbfcffcf269c8026aba Mon Sep 17 00:00:00 2001
From: Tristan Gingold <tgingold@free.fr>
Date: Sun, 2 Jun 2019 09:18:15 +0200
Subject: vhdl-formatters: add range for indent.

---
 src/ghdldrv/ghdlmain.adb     | 10 ++++++++
 src/ghdldrv/ghdlmain.ads     |  3 +++
 src/ghdldrv/ghdlprint.adb    | 31 ++++++++++++++++++++--
 src/vhdl/vhdl-formatters.adb | 61 ++++++++++++++++++++++++++++++++++++--------
 src/vhdl/vhdl-formatters.ads | 10 ++++++--
 5 files changed, 100 insertions(+), 15 deletions(-)

diff --git a/src/ghdldrv/ghdlmain.adb b/src/ghdldrv/ghdlmain.adb
index 932228b51..1b849c75c 100644
--- a/src/ghdldrv/ghdlmain.adb
+++ b/src/ghdldrv/ghdlmain.adb
@@ -263,6 +263,16 @@ package body Ghdlmain is
       Report_Msg (Msgid_Warning, Option, No_Source_Coord, Msg);
    end Warning;
 
+   function Index (Str : String; C : Character) return Natural is
+   begin
+      for I in Str'Range loop
+         if Str (I) = C then
+            return I;
+         end if;
+      end loop;
+      return 0;
+   end Index;
+
    procedure Main
    is
       use Ada.Command_Line;
diff --git a/src/ghdldrv/ghdlmain.ads b/src/ghdldrv/ghdlmain.ads
index f5ac4b05d..226dc9f94 100644
--- a/src/ghdldrv/ghdlmain.ads
+++ b/src/ghdldrv/ghdlmain.ads
@@ -69,6 +69,9 @@ package Ghdlmain is
    procedure Error (Msg : String);
    procedure Warning (Msg : String);
 
+   --  Return the index of C in STR, or 0 if not found.
+   function Index (Str : String; C : Character) return Natural;
+
    --  May be raise by perform_action if the arguments are bad.
    Option_Error : exception renames Errorout.Option_Error;
 
diff --git a/src/ghdldrv/ghdlprint.adb b/src/ghdldrv/ghdlprint.adb
index c06a907ba..b93cd147b 100644
--- a/src/ghdldrv/ghdlprint.adb
+++ b/src/ghdldrv/ghdlprint.adb
@@ -962,6 +962,8 @@ package body Ghdlprint is
       Flag_Sem : Boolean := True;
       Flag_Format : Boolean := False;
       Flag_Indent : Boolean := False;
+      First_Line : Positive := 1;
+      Last_Line : Positive := Positive'Last;
    end record;
    function Decode_Command (Cmd : Command_Reprint; Name : String)
                            return Boolean;
@@ -991,7 +993,9 @@ package body Ghdlprint is
    procedure Decode_Option (Cmd : in out Command_Reprint;
                             Option : String;
                             Arg : String;
-                            Res : out Option_Res) is
+                            Res : out Option_Res)
+   is
+      pragma Assert (Option'First = 1);
    begin
       if Option = "--no-sem" then
          Cmd.Flag_Sem := False;
@@ -1004,6 +1008,28 @@ package body Ghdlprint is
          Cmd.Flag_Format := False;
          Cmd.Flag_Indent := True;
          Res := Option_Ok;
+      elsif Option'Length > 8 and then Option (1 .. 8) = "--range=" then
+         declare
+            F : constant Natural := 9;
+            L : constant Natural := Option'Last;
+            Colon : constant Natural := Index (Option (F .. L), ':');
+         begin
+            if Colon = 0 then
+               Cmd.First_Line := Positive'Value (Option (F .. L));
+               Cmd.Last_Line := Cmd.First_Line;
+            else
+               if Colon > 9 then
+                  Cmd.First_Line := Positive'Value (Option (F .. Colon - 1));
+               end if;
+               if Colon < Option'Last then
+                  Cmd.Last_Line := Positive'Value (Option (Colon + 1 .. L));
+               end if;
+            end if;
+            Res := Option_Ok;
+         exception
+            when Constraint_Error =>
+               Res := Option_Err;
+         end;
       else
          Decode_Option (Command_Lib (Cmd), Option, Arg, Res);
       end if;
@@ -1075,7 +1101,8 @@ package body Ghdlprint is
          if Cmd.Flag_Format then
             Vhdl.Formatters.Format (Design_File);
          elsif Cmd.Flag_Indent then
-            Vhdl.Formatters.Indent (Design_File);
+            Vhdl.Formatters.Indent (Design_File,
+                                    Cmd.First_Line, Cmd.Last_Line);
          end if;
       end loop;
    end Perform_Action;
diff --git a/src/vhdl/vhdl-formatters.adb b/src/vhdl/vhdl-formatters.adb
index 9749a3f07..49097dc4e 100644
--- a/src/vhdl/vhdl-formatters.adb
+++ b/src/vhdl/vhdl-formatters.adb
@@ -269,11 +269,18 @@ package body Vhdl.Formatters is
          Hfirst : Boolean;  --  First token in the hbox.
          Last_Tok : Source_Ptr;
          Col : Natural;
+         Line : Positive;
+         First_Line : Positive;
+         Last_Line : Positive;
+         Discard_Output : Boolean;
          Sfe : Source_File_Entry;
          Source : File_Buffer_Acc;
       end record;
 
-      procedure Init (Ctxt : out Indent_Ctxt; Sfe : Source_File_Entry);
+      procedure Init (Ctxt : out Indent_Ctxt;
+                      Sfe : Source_File_Entry;
+                      First_Line : Positive;
+                      Last_Line : Positive);
       procedure Start_Hbox (Ctxt : in out Indent_Ctxt);
       procedure Close_Hbox (Ctxt : in out Indent_Ctxt);
       procedure Start_Vbox (Ctxt : in out Indent_Ctxt);
@@ -288,13 +295,20 @@ package body Vhdl.Formatters is
    end Indent_Disp_Ctxt;
 
    package body Indent_Disp_Ctxt is
-      procedure Init (Ctxt : out Indent_Ctxt; Sfe : Source_File_Entry) is
+      procedure Init (Ctxt : out Indent_Ctxt;
+                      Sfe : Source_File_Entry;
+                      First_Line : Positive;
+                      Last_Line : Positive) is
       begin
          Ctxt := (Vnum => 0,
                   Hnum => 0,
                   Hfirst => False,
                   Last_Tok => Source_Ptr_Org,
                   Col => 0,
+                  Line => 1,
+                  First_Line => First_Line,
+                  Last_Line => Last_Line,
+                  Discard_Output => First_Line > 1,
                   Sfe => Sfe,
                   Source => Files_Map.Get_File_Source (Sfe));
 
@@ -321,6 +335,10 @@ package body Vhdl.Formatters is
          Bef_Tok : Source_Ptr;
          Indent : Natural;
       begin
+         if Ctxt.Discard_Output then
+            return;
+         end if;
+
          if Ctxt.Col = 0 then
             --  Reindent.
             Indent := Ctxt.Vnum;
@@ -359,6 +377,10 @@ package body Vhdl.Formatters is
          Aft_Tok : constant Source_Ptr := Get_Position;
          P : Source_Ptr;
       begin
+         if Ctxt.Discard_Output then
+            return;
+         end if;
+
          P := Get_Token_Position;
          while P < Aft_Tok loop
             Put (Indent_Ctxt'Class (Ctxt), Ctxt.Source (P));
@@ -374,8 +396,14 @@ package body Vhdl.Formatters is
                when Tok_Eof =>
                   raise Internal_Error;
                when Tok_Newline =>
-                  Put (Indent_Ctxt'Class (Ctxt), ASCII.LF);
+                  if not Ctxt.Discard_Output then
+                     Put (Indent_Ctxt'Class (Ctxt), ASCII.LF);
+                  end if;
                   Ctxt.Col := 0;
+                  Ctxt.Line := Ctxt.Line + 1;
+                  Ctxt.Discard_Output :=
+                    Ctxt.Line < Ctxt.First_Line
+                    or Ctxt.Line > Ctxt.Last_Line;
                when Tok_Line_Comment
                  | Tok_Block_Comment =>
                   Disp_Spaces (Ctxt);
@@ -449,7 +477,9 @@ package body Vhdl.Formatters is
 
       procedure Init (Ctxt : out Vstring_Ctxt;
                       Handle : Vstring_Acc;
-                      Sfe : Source_File_Entry);
+                      Sfe : Source_File_Entry;
+                      First_Line : Positive;
+                      Last_Line : Positive);
       procedure Put (Ctxt : in out Vstring_Ctxt; C : Character);
    private
       type Vstring_Ctxt is new Indent_Disp_Ctxt.Indent_Ctxt with record
@@ -460,9 +490,12 @@ package body Vhdl.Formatters is
    package body Indent_Vstrings_Ctxt is
       procedure Init (Ctxt : out Vstring_Ctxt;
                       Handle : Vstring_Acc;
-                      Sfe : Source_File_Entry) is
+                      Sfe : Source_File_Entry;
+                      First_Line : Positive;
+                      Last_Line : Positive) is
       begin
-         Indent_Disp_Ctxt.Init (Indent_Disp_Ctxt.Indent_Ctxt (Ctxt), Sfe);
+         Indent_Disp_Ctxt.Init (Indent_Disp_Ctxt.Indent_Ctxt (Ctxt), Sfe,
+                                First_Line, Last_Line);
          Ctxt.Hand := Handle;
       end Init;
 
@@ -499,25 +532,31 @@ package body Vhdl.Formatters is
       Deallocate (Handle1);
    end Free;
 
-   procedure Indent_String (F : Iir_Design_File; Handle : Vstring_Acc)
+   procedure Indent_String (F : Iir_Design_File;
+                            Handle : Vstring_Acc;
+                            First_Line : Positive := 1;
+                            Last_Line : Positive := Positive'Last)
    is
       use Indent_Vstrings_Ctxt;
       Sfe : constant Source_File_Entry := Get_Design_File_Source (F);
       Ctxt : Vstring_Ctxt;
    begin
-      Init (Ctxt, Handle, Sfe);
+      Init (Ctxt, Handle, Sfe, First_Line, Last_Line);
       Prints.Disp_Vhdl (Ctxt, F);
    end Indent_String;
 
-   procedure Indent (F : Iir_Design_File) is
+   procedure Indent (F : Iir_Design_File;
+                     First_Line : Positive := 1;
+                     Last_Line : Positive := Positive'Last) is
    begin
       if False then
+         --  Display character per character.  Slow but useful for debugging.
          declare
             use Indent_Disp_Ctxt;
             Sfe : constant Source_File_Entry := Get_Design_File_Source (F);
             Ctxt : Indent_Ctxt;
          begin
-            Init (Ctxt, Sfe);
+            Init (Ctxt, Sfe, First_Line, Last_Line);
             Prints.Disp_Vhdl (Ctxt, F);
          end;
       else
@@ -528,7 +567,7 @@ package body Vhdl.Formatters is
             Len : Natural;
          begin
             Handle := Allocate_Handle;
-            Indent_String (F, Handle);
+            Indent_String (F, Handle, First_Line, Last_Line);
             Res := Get_C_String (Handle);
             Len := Get_Length (Handle);
             Simple_IO.Put (Res (1 .. Len));
diff --git a/src/vhdl/vhdl-formatters.ads b/src/vhdl/vhdl-formatters.ads
index e072b1bd2..f07abb5bb 100644
--- a/src/vhdl/vhdl-formatters.ads
+++ b/src/vhdl/vhdl-formatters.ads
@@ -25,11 +25,17 @@ package Vhdl.Formatters is
    procedure Format (F : Iir_Design_File);
 
    --  Reindent the file.
-   procedure Indent (F : Iir_Design_File);
+   procedure Indent (F : Iir_Design_File;
+                     First_Line : Positive := 1;
+                     Last_Line : Positive := Positive'Last);
 
    type Vstring_Acc is access Grt.Vstrings.Vstring;
 
-   procedure Indent_String (F : Iir_Design_File; Handle : Vstring_Acc);
+   --  Reindent all lines of F between [First_Line; Last_Line] to HANDLE.
+   procedure Indent_String (F : Iir_Design_File;
+                            Handle : Vstring_Acc;
+                            First_Line : Positive := 1;
+                            Last_Line : Positive := Positive'Last);
 
    function Allocate_Handle return Vstring_Acc;
    function Get_Length (Handle : Vstring_Acc) return Natural;
-- 
cgit v1.2.3