aboutsummaryrefslogtreecommitdiffstats
path: root/src/file_comments.adb
diff options
context:
space:
mode:
Diffstat (limited to 'src/file_comments.adb')
-rw-r--r--src/file_comments.adb184
1 files changed, 184 insertions, 0 deletions
diff --git a/src/file_comments.adb b/src/file_comments.adb
new file mode 100644
index 000000000..183b17144
--- /dev/null
+++ b/src/file_comments.adb
@@ -0,0 +1,184 @@
+-- Comments table.
+-- Copyright (C) 2022 Tristan Gingold
+--
+-- This program is free software: you can redistribute it and/or modify
+-- it under the terms of the GNU General Public License as published by
+-- the Free Software Foundation, either version 2 of the License, or
+-- (at your option) any later version.
+--
+-- This program is distributed in the hope that it will be useful,
+-- but WITHOUT ANY WARRANTY; without even the implied warranty of
+-- MERCHANTABILITY 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
+-- along with this program. If not, see <gnu.org/licenses>.
+
+-- All the variables declared in this package are set by Parse_Option function
+-- and can by read as soon as the command line is parsed.
+--
+-- Since the names are not prefixed, this package is expected to be with'ed
+-- but not to be use'd.
+
+with Grt.Algos;
+
+package body File_Comments is
+ procedure Add_Comment (File : Source_File_Entry;
+ Start, Last : Source_Ptr)
+ is
+ pragma Assert (File > No_Source_File_Entry);
+ begin
+ -- Create entry for FILE if not already created.
+ if Comments_Table.Last < File then
+ while Comments_Table.Last < File loop
+ Comments_Table.Append
+ (File_Comment_Record'(Comments => <>,
+ Next => File_Comments_Tables.First));
+ end loop;
+ File_Comments_Tables.Init (Comments_Table.Table (File).Comments, 16);
+ end if;
+
+ -- Append a comment entry.
+ File_Comments_Tables.Append
+ (Comments_Table.Table (File).Comments,
+ Comment_Record'(Start => Start, Last => Last, N => 0));
+ end Add_Comment;
+
+ procedure Discard_Comments (File : Source_File_Entry) is
+ begin
+ if Comments_Table.Last < File then
+ -- No comments for FILE.
+ return;
+ end if;
+ raise Internal_Error;
+ end Discard_Comments;
+
+ procedure Gather_Comments (File : Source_File_Entry; N : Uns32)
+ is
+ use File_Comments_Tables;
+ begin
+ if Comments_Table.Last < File then
+ -- No comments for FILE.
+ return;
+ end if;
+ declare
+ Fc : File_Comment_Record renames Comments_Table.Table (File);
+ begin
+ while Fc.Next <= Last (Fc.Comments) loop
+ Fc.Comments.Table (Fc.Next).N := N;
+ Fc.Next := Fc.Next + 1;
+ end loop;
+ end;
+ end Gather_Comments;
+
+ procedure Rename_Comments (File : Source_File_Entry;
+ Prev : Uns32;
+ N : Uns32) is
+ begin
+ raise Internal_Error;
+ end Rename_Comments;
+
+ procedure Sort_Comments_By_Node_1 (Fc : File_Comment_Record)
+ is
+ function Lt (L, R : Positive) return Boolean
+ is
+ Lc : Comment_Record renames Fc.Comments.Table (Comment_Index (L));
+ Rc : Comment_Record renames Fc.Comments.Table (Comment_Index (R));
+ begin
+ if Lc.N < Rc.N then
+ return True;
+ elsif Lc.N = Rc.N then
+ return Lc.Start < Rc.Start;
+ end if;
+ return False;
+ end Lt;
+
+ procedure Swap (P1 : Positive; P2 : Positive)
+ is
+ L : Comment_Record renames Fc.Comments.Table (Comment_Index (P1));
+ R : Comment_Record renames Fc.Comments.Table (Comment_Index (P2));
+ T : Comment_Record;
+ begin
+ T := L;
+ L := R;
+ R := T;
+ end Swap;
+
+ procedure Sort is new Grt.Algos.Heap_Sort
+ (Lt => Lt, Swap => Swap);
+ begin
+ Sort (Natural (File_Comments_Tables.Last (Fc.Comments)));
+ end Sort_Comments_By_Node_1;
+
+ procedure Sort_Comments_By_Node (File : Source_File_Entry) is
+ begin
+ if File > Comments_Table.Last then
+ -- No comments gathered, nothing to do.
+ return;
+ end if;
+ Sort_Comments_By_Node_1 (Comments_Table.Table (File));
+ end Sort_Comments_By_Node;
+
+ function Find_First_Comment (File : Source_File_Entry; N : Uns32)
+ return Comment_Index is
+ begin
+ if Comments_Table.Last < File then
+ -- No comments for FILE.
+ return No_Comment_Index;
+ end if;
+ declare
+ Fc : File_Comment_Record renames Comments_Table.Table (File);
+ Nd : Uns32;
+ F, L, M : Comment_Index;
+ begin
+ F := File_Comments_Tables.First;
+ L := File_Comments_Tables.Last (Fc.Comments);
+ while F <= L loop
+ M := F + (L - F) / 2;
+ Nd := Fc.Comments.Table (M).N;
+ if Nd = N then
+ -- Found, but must return the first comment.
+ while M > No_Comment_Index + 1
+ and then Fc.Comments.Table (M - 1).N = N
+ loop
+ M := M - 1;
+ end loop;
+ return M;
+ elsif Nd < N then
+ F := M + 1;
+ else
+ pragma Assert (Nd > N);
+ L := M - 1;
+ end if;
+ end loop;
+ return No_Comment_Index;
+ end;
+ end Find_First_Comment;
+
+ procedure Get_Comment (File : Source_File_Entry;
+ Idx : Comment_Index;
+ Start, Last : out Source_Ptr)
+ is
+ pragma Assert (Comments_Table.Last >= File);
+ Fc : File_Comment_Record renames Comments_Table.Table (File);
+ begin
+ Start := Fc.Comments.Table (Idx).Start;
+ Last := Fc.Comments.Table (Idx).Last;
+ end Get_Comment;
+
+ function Get_Next_Comment (File : Source_File_Entry; Idx : Comment_Index)
+ return Comment_Index
+ is
+ use File_Comments_Tables;
+ pragma Assert (Comments_Table.Last >= File);
+ Fc : File_Comment_Record renames Comments_Table.Table (File);
+ begin
+ if Idx < Last (Fc.Comments)
+ and then Fc.Comments.Table (Idx + 1).N = Fc.Comments.Table (Idx).N
+ then
+ return Idx + 1;
+ else
+ return No_Comment_Index;
+ end if;
+ end Get_Next_Comment;
+end File_Comments;