aboutsummaryrefslogtreecommitdiffstats
path: root/src/files_map-editor.adb
diff options
context:
space:
mode:
authorTristan Gingold <tgingold@free.fr>2018-11-26 20:23:29 +0100
committerTristan Gingold <tgingold@free.fr>2018-11-26 20:29:32 +0100
commit0c9ea545925f0e027d25a6ba1c457ae34df9d100 (patch)
treef61d8cf13454471c24b60704ee7c366959dcb2d5 /src/files_map-editor.adb
parentbd681e64540831934ebc40dc8fcdfcbb0e559c6a (diff)
downloadghdl-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.adb172
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;