diff options
| author | Tristan Gingold <tgingold@free.fr> | 2018-11-26 20:23:29 +0100 | 
|---|---|---|
| committer | Tristan Gingold <tgingold@free.fr> | 2018-11-26 20:29:32 +0100 | 
| commit | 0c9ea545925f0e027d25a6ba1c457ae34df9d100 (patch) | |
| tree | f61d8cf13454471c24b60704ee7c366959dcb2d5 /src/files_map-editor.adb | |
| parent | bd681e64540831934ebc40dc8fcdfcbb0e559c6a (diff) | |
| download | ghdl-0c9ea545925f0e027d25a6ba1c457ae34df9d100.tar.gz ghdl-0c9ea545925f0e027d25a6ba1c457ae34df9d100.tar.bz2 ghdl-0c9ea545925f0e027d25a6ba1c457ae34df9d100.zip  | |
files_map-editor: WIP.
Diffstat (limited to 'src/files_map-editor.adb')
| -rw-r--r-- | src/files_map-editor.adb | 172 | 
1 files changed, 167 insertions, 5 deletions
diff --git a/src/files_map-editor.adb b/src/files_map-editor.adb index caf46c890..885bc1bc1 100644 --- a/src/files_map-editor.adb +++ b/src/files_map-editor.adb @@ -16,6 +16,8 @@  --  Software Foundation, 59 Temple Place - Suite 330, Boston, MA  --  02111-1307, USA. +with Ada.Text_IO; +  package body Files_Map.Editor is     --  Compute the number of character in FILE between [START_POS; END_POS)     function Get_Range_Length (File : Source_File_Entry; @@ -107,6 +109,52 @@ package body Files_Map.Editor is        F.Gap_Last := New_Start + Gap_Len - 1;     end Move_Gap; +   --  Count the length of newlines at position P in TEXT. +   --  Result can be: +   --    1 for (LF, CR) +   --    2 for (LF+CR or CR+LF), +   --    0 for non-newlines. +   function Is_Newline (Text : String; P : Positive) return Natural is +   begin +      if Text (P) = ASCII.CR then +         if P < Text'Last and then Text (P + 1) = ASCII.LF then +            return 2; +         else +            return 1; +         end if; +      elsif Text (P) = ASCII.LF then +         if P < Text'Last and then Text (P + 1) = ASCII.CR then +            return 2; +         else +            return 1; +         end if; +      else +         return 0; +      end if; +   end Is_Newline; + +   --  Count the number of newlines (LF, CR, LF+CR or CR+LF) in TEXT. +   function Count_Newlines (Text : String) return Natural +   is +      P : Positive; +      Res : Natural; +      R : Natural; +   begin +      P := Text'First; +      Res := 0; +      while P <= Text'Last loop +         R := Is_Newline (Text, P); +         if R > 0 then +            P := P + R; +            Res := Res + 1; +         else +            P := P + 1; +         end if; +      end loop; + +      return Res; +   end Count_Newlines; +     procedure Replace_Text (File : Source_File_Entry;                             Start_Line : Positive;                             Start_Off  : Natural; @@ -161,11 +209,46 @@ package body Files_Map.Editor is        end;        --  Renumber. -      if Start_Line /= End_Line then -         --  Not handled. -         --  FIXME: also handle newlines in TEXT. -         raise Internal_Error; -      end if; +      declare +         use Lines_Tables; +         Text_Lines : constant Natural := Count_Newlines (Text); +         Orig_Lines : constant Natural := End_Line - Start_Line; +         Diff : constant Integer := Text_Lines - Orig_Lines; +         Orig_Last : constant Natural := Last (F.Lines); +         P : Positive; +         Nl_Len : Natural; +         L : Natural; +      begin +         --  No change in newlines. +         if Text_Lines = 0 and then Orig_Lines = 0 then +            return; +         end if; + +         --  Make room for lines table. +         if Diff /= 0 then +            if Diff > 0 then +               Set_Last (F.Lines, Orig_Last + Diff); +            end if; +            F.Lines.Table (End_Line + Diff .. Orig_Last + Diff) := +              F.Lines.Table (End_Line .. Orig_Last); +            if Diff < 0 then +               Set_Last (F.Lines, Orig_Last + Diff); +            end if; +         end if; + +         --  Renumber. +         P := Text'First; +         L := Start_Line + 1; +         while P <= Text'Last loop +            Nl_Len := Is_Newline (Text, P); +            if Nl_Len = 0 then +               P := P + 1; +            else +               P := P + Nl_Len; +               F.Lines.Table (L) := Start_Pos + Source_Ptr (P - Text'First); +            end if; +         end loop; +      end;     end Replace_Text;     procedure Replace_Text_Ptr (File : Source_File_Entry; @@ -190,4 +273,83 @@ package body Files_Map.Editor is        F.Gap_Start := First;        F.Gap_Last := Last;     end Set_Gap; + +   procedure Check_Buffer_Content (File : Source_File_Entry; +                                   Str : Thin_String_Ptr; +                                   Str_Len : Natural) +   is +      use Ada.Text_IO; +      pragma Assert (File <= Source_Files.Last); +      F : Source_File_Record renames Source_Files.Table (File); +   begin +      --  Check length. +      declare +         Buf_Len : constant Source_Ptr := +           F.File_Length - (F.Gap_Last - F.Gap_Start); +      begin +         if Str_Len /= Natural (Buf_Len) then +            Put_Line (Standard_Error, +                      "length mismatch (text:" & Natural'Image (Str_Len) +                        & ", buffer:" & Source_Ptr'Image (Buf_Len)); +         end if; +      end; + +      --  Check content. +      declare +         T_Pos : Natural; +         S_Pos : Source_Ptr; +      begin +         T_Pos := Str'First; +         S_Pos := Source_Ptr_Org; +         while T_Pos <= Str_Len loop +            if F.Source (S_Pos) /= Str (T_Pos) then +               Put_Line (Standard_Error, +                         "difference at offset" & Natural'Image (T_Pos)); +               exit; +            end if; +            T_Pos := T_Pos + 1; +            S_Pos := S_Pos + 1; +            if S_Pos = F.Gap_Start then +               S_Pos := F.Gap_Last + 1; +            end if; +         end loop; +      end; + +      --  Check lines. +      declare +         L : Positive; +         P : Source_Ptr; +         Nl : Natural; +         subtype Buf_Subtype is String (1 .. Natural (F.File_Length)); +      begin +         L := 1; +         P := Source_Ptr_Org; +         loop +            if F.Lines.Table (L) /= P then +               Put_Line (Standard_Error, +                         "offset mismatch for line" & Natural'Image (L)); +            end if; +            L := L + 1; + +            loop +               Nl := Is_Newline +                 (Buf_Subtype (F.Source (Source_Ptr_Org +                                           .. F.File_Length - 1)), +                 Positive (1 + P)); +               if Nl = 0 then +                  P := P + 1; +               else +                  P := P + Source_Ptr (Nl); +                  exit; +               end if; +            end loop; + +            if P = F.Gap_Start then +               P := F.Gap_Last + 1; +            end if; +            exit when P = F.File_Length; +         end loop; +      end; +   end Check_Buffer_Content; +  end Files_Map.Editor;  | 
