-- Store error messages -- Copyright (C) 2018 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 . with Tables; package body Errorout.Memory is type Char_Index is new Uns32; package Messages is new Tables (Table_Component_Type => Character, Table_Index_Type => Char_Index, Table_Low_Bound => 1, Table_Initial => 128); type Error_Element is record Header : Error_Message; Str : Char_Index; end record; package Errors is new Tables (Table_Component_Type => Error_Element, Table_Index_Type => Error_Index, Table_Low_Bound => 1, Table_Initial => 32); Group : Group_Type; function Get_Nbr_Messages return Error_Index is begin return Errors.Last; end Get_Nbr_Messages; function Get_Error_Record (Idx : Error_Index) return Error_Message is begin return Errors.Table (Idx).Header; end Get_Error_Record; function Get_Error_Message (Idx : Error_Index) return String is First : constant Char_Index := Errors.Table (Idx).Str; Last : Char_Index; begin if Idx = Errors.Last then Last := Messages.Last; else Last := Errors.Table (Idx + 1).Str - 1; end if; return String (Messages.Table (First .. Last - 1)); end Get_Error_Message; function Get_Error_Message_Addr (Idx : Error_Index) return System.Address is First : constant Char_Index := Errors.Table (Idx).Str; begin return Messages.Table (First)'Address; end Get_Error_Message_Addr; procedure Clear_Errors is begin Errors.Init; Messages.Init; Nbr_Errors := 0; end Clear_Errors; procedure Memory_Error_Start (E : Error_Record) is Msg : constant Error_Message := (Id => E.Id, Group => Group, File => E.File, Line => E.Line, Offset => E.Offset, Length => E.Length); begin Errors.Append ((Msg, Messages.Last + 1)); if Group = Msg_Main then Group := Msg_Related; end if; end Memory_Error_Start; procedure Memory_Message (Str : String) is begin for I in Str'Range loop Messages.Append (Str (I)); end loop; end Memory_Message; procedure Memory_Message_End is begin Messages.Append (ASCII.NUL); end Memory_Message_End; procedure Memory_Message_Group (Start : Boolean) is begin if Start then pragma Assert (Group = Msg_Single); Group := Msg_Main; else pragma Assert (Group /= Msg_Single); case Errors.Table (Errors.Last).Header.Group is when Msg_Single | Msg_Last => -- Check consistency until messages are discarded. if Nbr_Errors <= Max_Nbr_Errors then raise Internal_Error; end if; when Msg_Main => Errors.Table (Errors.Last).Header.Group := Msg_Single; when Msg_Related => Errors.Table (Errors.Last).Header.Group := Msg_Last; end case; Group := Msg_Single; end if; end Memory_Message_Group; procedure Install_Handler is begin Set_Report_Handler ((Memory_Error_Start'Access, Memory_Message'Access, Memory_Message_End'Access, Memory_Message_Group'Access)); Group := Msg_Single; end Install_Handler; end Errorout.Memory;