-- This package provides a mechanism for writing commands which
-- perform error reporting and error handling in a manner consistent
-- with Environment commands.
--
with Profile;
generic

    Original_Response_Profile : Profile.Response_Profile;
    --
    -- Is the response profile to which the response profile should
    -- be reset when exiting.

    Current_Response_Profile : Profile.Response_Profile;
    --
    -- Is the response profile which should be used to evaluate log
    -- output destination, error reaction, etc.

    Operation_Name : in String;
    --
    -- Specifies the name of the operation to be used in the closing
    -- message (i.e. "[end of <Operation_Name>--error(s) detected]").

package Errors is

    Propagate : exception;
    Quit : exception;

    Nil_Message : constant String := "";

    procedure Report (This_Message : in String;
                      This_Type : in Profile.Msg_Kind := Profile.Error_Msg;
                      Fatal : in Boolean := True;
                      Nested : in Boolean := False;
                      Suppress_Closing_Message : in Boolean := False);
    --
    -- Does a "Log.Put_Line" of the specified message to the appropriate
    -- output. Message will be of the specified kind (if the message is
    -- equal to Nil_Message, nothing will be output, but the error reaction
    -- will still work as described below).
    --
    -- Once the message is written:
    --
    -- If the error reaction is "QUIT":
    --
    --    A closing message is written (unless "Suppress_Closing_Message" is
    --    True), and the response profile is reset to
    --    "Original_Response_Profile". Then:
    --
    --       If "Nested" is True, "Quit" is raised.
    --
    -- If the error reaction is "PROPAGATE":
    --
    --    A closing message is written (unless "Suppress_Closing_Message" is
    --    True), the response profile is reset to "Original_Response_Profile",
    --    and "Propagate" is raised.
    --
    -- If the error reaction is "PERSEVERE":
    --
    --    If "Fatal" is True:
    --
    --       A closing message is written (unless "Suppress_Closing_Message" is
    --       True), and the response profile is reset to
    --       "Original_Response_Profile". Then:
    --
    --           If "Nested" is True, "Quit" is raised.
    --
    -- If the error reaction is "RAISE_ERROR":
    --
    --    If "Fatal" is True:
    --
    --       A closing message is written (unless "Suppress_Closing_Message" is
    --       True), the response profile is reset to
    --       "Original_Response_Profile", and "Propagate" is raised.
    --
    -- For this procedure to work correctly, two conditions must be
    -- satisfied in the client:
    --
    -- 1) The client must provide the following exception handler alternatives
    --    at the outermost lexical level:
    --
    --        when Errors.Propagate =>
    --            raise;
    --        when Errors.Quit =>
    --            null;
    --
    -- 2) Every raise of "Propagate" and "Quit" by every call to "Report"
    --    must be able to get to the above exception handler alternatives.
    --
    -- *****
    --
    -- Here is a template of how this procedure should be used:
    --
    -- with Log;
    -- with Errors;
    -- with Profile;
    -- with Debug_Tools;
    -- with <others>;
    -- procedure Template (This_Parameter : in String := "<SPECIAL_NAME>";
    --                     That_Parameter : in String := ">> PLACEHOLDER <<";
    --                     Another_Parameter : in Boolean := True;
    --                     Response : in String := "<PROFILE>") is
    --
    --     Old_Response_Profile : Profile.Response_Profile := Profile.Get;
    --     New_Response_Profile : Profile.Response_Profile := Profile.Value (Response);
    --
    --     package Error is
    --        new Errors
    --               (Old_Response_Profile, New_Response_Profile, "Template");
    --
    --     <other declarations>;
    --
    -- begin
    --     Profile.Set (New_Response_Profile);
    --     Log.Put_Line ("[Template (This_Parameter => """ &
    --                   This_Parameter & """, That_Parameter => """ &
    --                   That_Parameter & """, Another_Parameter => " &
    --                   Boolean'Image (Another_Parameter) &
    --                   ", Response => """ & Response & """)]",
    --                   Profile.Auxiliary_Msg);
    --     loop
    --         begin
    --            Call_Some_Other_Procedure ("PROPAGATE," & Response);
    --            --
    --         exception
    --            when others =>
    --                Error.Report ("<message for call failure>",
    --                              -- IF CALL FAILURE IS NOT FATAL:
    --                              Fatal => False,
    --                              Nested => True);
    --         end;
    --     end loop;
    --     Log.Put_Line
    --            ("[end of Template operation --no error(s) detected]");
    --     Profile.Set (Old_Response_Profile);
    --     --
    -- exception
    --     when This_Exception =>
    --         Error.Report ("<message for this exception>");
    --     when That_Exception =>
    --         Error.Report ("<message for different exception>");
    --     when Error.Propagate =>
    --         raise;
    --     when Error.Quit =>
    --         null;
    --     when others =>
    --         Error.Report ("EXCEPTION: " & Debug_Tools.Get_Exception_Name,
    --                       Profile.Exception_Msg);
    -- end Template;
    --
    -- *****
    --
    -- NOTE: This procedure should NOT be used to report progress messages,
    -- warnings, and other non-errors.

end Errors;