home *** CD-ROM | disk | FTP | other *** search
/ Geek Gadgets 1 / ADE-1.bin / ade-dist / gnat-2.06-src.tgz / tar.out / fsf / gnat / ada / errout.adb < prev    next >
Text File  |  1996-09-28  |  64KB  |  2,030 lines

  1. ------------------------------------------------------------------------------
  2. --                                                                          --
  3. --                         GNAT COMPILER COMPONENTS                         --
  4. --                                                                          --
  5. --                               E R R O U T                                --
  6. --                                                                          --
  7. --                                 B o d y                                  --
  8. --                                                                          --
  9. --                            $Revision: 1.117 $                            --
  10. --                                                                          --
  11. --        Copyright (c) 1992,1993,1994,1995 NYU, All Rights Reserved        --
  12. --                                                                          --
  13. -- GNAT is free software;  you can  redistribute it  and/or modify it under --
  14. -- terms of the  GNU General Public License as published  by the Free Soft- --
  15. -- ware  Foundation;  either version 2,  or (at your option) any later ver- --
  16. -- sion.  GNAT is distributed in the hope that it will be useful, but WITH- --
  17. -- OUT ANY WARRANTY;  without even the  implied warranty of MERCHANTABILITY --
  18. -- or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License --
  19. -- for  more details.  You should have  received  a copy of the GNU General --
  20. -- Public License  distributed with GNAT;  see file COPYING.  If not, write --
  21. -- to the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. --
  22. --                                                                          --
  23. ------------------------------------------------------------------------------
  24.  
  25. with Atree;    use Atree;
  26. with Casing;   use Casing;
  27. with Csets;    use Csets;
  28. with Debug;    use Debug;
  29. with Einfo;    use Einfo;
  30. with Expander; use Expander;
  31. with Lib;      use Lib;
  32. with Namet;    use Namet;
  33. with Opt;      use Opt;
  34. with Output;   use Output;
  35. with Scans;    use Scans;
  36. with Sem_Util; use Sem_Util;
  37. with Sinput;   use Sinput;
  38. with Sinfo;    use Sinfo;
  39. with Snames;   use Snames;
  40. with Stand;    use Stand;
  41. with Uintp;    use Uintp;
  42. with Uname;    use Uname;
  43.  
  44. with System.Parameters;
  45.  
  46. package body Errout is
  47.  
  48.    Max_Msg_Length : constant := 80 + 2 * System.Parameters.Max_Line_Length;
  49.    --  Maximum length of error message. The addition of Max_Line_Length
  50.    --  ensures that two insertion tokens of maximum length can be accomodated.
  51.  
  52.    Msg_Buffer : String (1 .. Max_Msg_Length);
  53.    --  Buffer used to prepare error messages
  54.  
  55.    Msg_Len : Integer;
  56.    --  Number of characters currently stored in the message buffer
  57.  
  58.    Flag_Source : Source_File_Index;
  59.    --  Source file index for source file where error is being posted
  60.  
  61.    Is_Warning_Msg : Boolean;
  62.    --  Set by Set_Msg_Text to indicate if current message is warning message
  63.  
  64.    Is_Unconditional_Msg : Boolean;
  65.    --  Set by Set_Msg_Text to indicate if current message is unconditional
  66.  
  67.    Cur_Msg : Error_Msg_Id;
  68.    --  Id of most recently posted error message
  69.  
  70.    Current_Error_Source_File : Source_File_Index;
  71.    --  Id of current messages. Used to post file name when unit changes. This
  72.    --  is initialized to Main_Source at the start of a compilation, which means
  73.    --  that no file names will be output unless there are errors in units
  74.    --  other than the main unit.
  75.  
  76.    Manual_Quote_Mode : Boolean;
  77.    --  Set True in manual quotation mode
  78.  
  79.    List_Pragmas_Index : Int;
  80.    --  Index into List_Pragmas table
  81.  
  82.    List_Pragmas_Mode : Boolean;
  83.    --  Starts True, gets set False by pragma List (Off), True by List (On)
  84.  
  85.    Suppress_Message : Boolean;
  86.    --  A flag used to suppress certain obviously redundant messages (i.e.
  87.    --  those referring to a node whose type is Any_Type). This suppression
  88.    --  is effective only if All_Errors_Mode is off.
  89.  
  90.    Kill_Message : Boolean;
  91.    --  A flag used to kill weird messages (e.g. those containing uninterpreted
  92.    --  implicit type references) if we have already seen at least one message
  93.    --  already. The idea is that we hope the weird message is a junk cascaded
  94.    --  message that should be suppressed.
  95.  
  96.    Error_Msg_Loc_Output : Source_Ptr;
  97.    --  This is set by Error_Msg_Internal to indicate if a # insertion was
  98.    --  processed. If so, it is set to the output location, if not it is set
  99.    --  to No_Location. This is used in Error_Msg to handle the case where
  100.    --  the reference is to an instantiation.
  101.  
  102.    -----------------------------------
  103.    -- Error Message Data Structures --
  104.    -----------------------------------
  105.  
  106.    --  The error messages are stored as a linked list of error message objects
  107.    --  sorted into ascending order by the source location (Sloc). Each object
  108.    --  records the text of the message and its source location.
  109.  
  110.    --  The following record type and table are used to represent error
  111.    --  messages, with one entry in the table being allocated for each message.
  112.  
  113.    type Error_Msg_Object is record
  114.       Text   : Name_Id;              -- Text of error message
  115.       Next   : Error_Msg_Id;         -- Pointer to next message
  116.       Sfile  : Source_File_Index;    -- Source table index of source file
  117.       Sptr   : Source_Ptr;           -- Flag pointer
  118.       Line   : Logical_Line_Number;  -- Line number
  119.       Col    : Column_Number;        -- Column number
  120.       Warn   : Boolean;              -- True if warning message
  121.       Uncond : Boolean;              -- True if unconditional message
  122.    end record;
  123.  
  124.    package Errors is new Table (
  125.      Table_Component_Type => Error_Msg_Object,
  126.      Table_Index_Type     => Error_Msg_Id,
  127.      Table_Low_Bound      => 1,
  128.      Table_Initial        => 200,
  129.      Table_Increment      => 200,
  130.      Table_Name           => "Error");
  131.  
  132.    Error_Msgs : Error_Msg_Id;
  133.    --  The list of error messages
  134.  
  135.    -----------------------
  136.    -- Local Subprograms --
  137.    -----------------------
  138.  
  139.    procedure Debug_Output (N : Node_Id);
  140.    --  Called from Error_Msg_N and Error_Msg_NE to generate line of debug
  141.    --  output giving node number (of node N) if the debug X switch is set.
  142.  
  143.    procedure Error_Msg_Internal (Msg : String; Flag_Location : Source_Ptr);
  144.    --  This is like Error_Msg, except that Flag_Location is known not to be
  145.    --  within a generic instance. The outer level routine, Error_Msg takes
  146.    --  care of dealing with the generic instance cases. Error_Msg_Internal
  147.    --  also leaves Error_Msg_Loc_Output set to indicate if a # insertion
  148.    --  was processed. If so, it is set to the location output, if not it
  149.    --  is set to No_Location.
  150.  
  151.    function OK_Node (N : Node_Id) return Boolean;
  152.    --  Determines if a node is an OK node to place an error message on (return
  153.    --  True) or if the error message should be suppressed (return False). A
  154.    --  message is suppressed if the node already has an error posted on it,
  155.    --  or if it refers to an Etype that has an error posted on it, or if
  156.    --  it references an Entity that has an error posted on it.
  157.  
  158.    procedure Output_Error_Msgs (E : in out Error_Msg_Id);
  159.    --  Output source line, error flag, and text of stored error message and
  160.    --  all subsequent messages for the same line and unit. On return E is
  161.    --  set to be one higher than the last message output.
  162.  
  163.    procedure Output_Line_Number (L : Logical_Line_Number);
  164.    --  Output a line number as six digits (with leading zeroes suppressed),
  165.    --  followed by a period and a blank (note that this is 8 characters which
  166.    --  means that tabs in the source line will not get messed up).
  167.  
  168.    procedure Output_Msg_Text (E : Error_Msg_Id);
  169.    --  Outputs characters of text in the text of the error message E, excluding
  170.    --  any final exclamation point. Note that no end of line is output, the
  171.    --  caller is responsible for adding the end of line.
  172.  
  173.    procedure Output_Source_Line
  174.      (L     : Logical_Line_Number;
  175.       Sfile : Source_File_Index;
  176.       Errs  : Boolean);
  177.    --  Outputs text of source line L, in file S, together with preceding line
  178.    --  number, as described above for Output_Line_Number. The Errs parameter
  179.    --  indicates if there are errors attached to the line, which forces
  180.    --  listing on, even in the presence of pragma List (Off).
  181.  
  182.    procedure Set_Msg_Blank;
  183.    --  Sets a single blank in the message if the preceding character is a
  184.    --  non-blank character other than a left parenthesis.
  185.  
  186.    procedure Set_Msg_Blank_Conditional;
  187.    --  Sets a single blank in the message if the preceding character is a
  188.    --  non-blank character other than a left parenthesis or quote.
  189.  
  190.    procedure Set_Msg_Char (C : Character);
  191.    --  Add a single character to the current message. This routine does not
  192.    --  check for special insertion characters (they are just treated as text
  193.    --  characters if they occur).
  194.  
  195.    procedure Set_Msg_Insertion_Column;
  196.    --  Handle column number insertion (@ insertion character)
  197.  
  198.    procedure Set_Msg_Insertion_Name;
  199.    --  Handle name insertion (% insertion character)
  200.  
  201.    procedure Set_Msg_Insertion_Line_Number (Loc, Flag : Source_Ptr);
  202.    --  Handle line number insertion (# insertion character). Loc is the
  203.    --  location to be referenced, and Flag is the location at which the
  204.    --  flag is posted (used to determine whether to add "in file xxx")
  205.  
  206.    procedure Set_Msg_Insertion_Node;
  207.    --  Handle node (name from node) insertion (& insertion character)
  208.  
  209.    procedure Set_Msg_Insertion_Reserved_Name;
  210.    --  Handle insertion of reserved word name (* insertion character).
  211.  
  212.    procedure Set_Msg_Insertion_Reserved_Word
  213.      (Text : String;
  214.       J    : in out Integer);
  215.    --  Handle reserved word insertion (upper case letters). The Text argument
  216.    --  is the current error message input text, and J is an index which on
  217.    --  entry points to the first character of the reserved word, and on exit
  218.    --  points past the last character of the reserved word.
  219.  
  220.    procedure Set_Msg_Insertion_Type_Reference (Flag : Source_Ptr);
  221.    --  Handle type reference (right brace insertion character). Flag is the
  222.    --  location of the flag, which is provided for the internal call to
  223.    --  Set_Msg_Insertion_Line_Number,
  224.  
  225.    procedure Set_Msg_Insertion_Uint;
  226.    --  Handle Uint insertion (^ insertion character)
  227.  
  228.    procedure Set_Msg_Insertion_Unit_Name;
  229.    --  Handle unit name insertion ($ insertion character)
  230.  
  231.    procedure Set_Msg_Insertion_File_Name;
  232.    --  Handle file name insertion (left brace insertion character)
  233.  
  234.    procedure Set_Msg_Int (Line : Int);
  235.    --  Set the decimal representation of the argument in the error message
  236.    --  buffer with no leading zeroes output.
  237.  
  238.    procedure Set_Msg_Name_Buffer;
  239.    --  Output name from Name_Buffer, with surrounding quotes unless manual
  240.    --  quotation mode is in effect.
  241.  
  242.    procedure Set_Msg_Node (Node : Node_Id);
  243.    --  Add the sequence of characters for the name associated with the
  244.    --  given node to the current message.
  245.  
  246.    procedure Set_Msg_Quote;
  247.    --  Set quote if in normal quote mode, nothing if in manual quote mode
  248.  
  249.    procedure Set_Msg_Str (Text : String);
  250.    --  Add a sequence of characters to the current message. This routine does
  251.    --  not check for special insertion characters (they are just treated as
  252.    --  text characters if they occur).
  253.  
  254.    procedure Set_Msg_Text (Text : String; Flag : Source_Ptr);
  255.    --  Add a sequence of characters to the current message. The characters may
  256.    --  be one of the special insertion characters (see documentation in spec).
  257.    --  Flag is the location at which the error is to be posted, which is used
  258.    --  to determine whether or not the # insertion needs a file name. The
  259.    --  variables Msg_Buffer, Msg_Len, Is_Warning_Msg, and Is_Unconditional_Msg
  260.    --  are set on return.
  261.  
  262.    -----------------------
  263.    -- Change_Error_Text --
  264.    -----------------------
  265.  
  266.    procedure Change_Error_Text (Error_Id : Error_Msg_Id; New_Msg : String) is
  267.       Save_Next : Error_Msg_Id;
  268.       Err_Id    : Error_Msg_Id := Error_Id;
  269.  
  270.    begin
  271.       Set_Msg_Text (New_Msg, Errors.Table (Error_Id).Sptr);
  272.       Name_Len := Msg_Len;
  273.       Name_Buffer (1 .. Name_Len) := Msg_Buffer (1 .. Msg_Len);
  274.  
  275.       Errors.Table (Error_Id).Text  := Name_Find;
  276.  
  277.       --  If in immediate error message mode, output modified error message now
  278.       --  This is just a bit tricky, because we want to output just a single
  279.       --  message, and the messages we modified is already linked in. We solve
  280.       --  this by temporarily resetting its forward pointer to empty.
  281.  
  282.       if Immediate_Errors then
  283.          Save_Next := Errors.Table (Error_Id).Next;
  284.          Errors.Table (Error_Id).Next := No_Error_Msg;
  285.          Write_Eol;
  286.          Output_Source_Line
  287.            (Errors.Table (Error_Id).Line, Errors.Table (Error_Id).Sfile, True);
  288.          Output_Error_Msgs (Err_Id);
  289.          Errors.Table (Error_Id).Next := Save_Next;
  290.       end if;
  291.    end Change_Error_Text;
  292.  
  293.    ------------------
  294.    -- Debug_Output --
  295.    ------------------
  296.  
  297.    procedure Debug_Output (N : Node_Id) is
  298.    begin
  299.       if Debug_Flag_1 then
  300.          Write_Str ("*** following error message posted on node id = #");
  301.          Write_Int (Int (N));
  302.          Write_Str (" ***");
  303.          Write_Eol;
  304.       end if;
  305.    end Debug_Output;
  306.  
  307.    ---------------
  308.    -- Error_Msg --
  309.    ---------------
  310.  
  311.    --  Error_Msg is the same as Error_Msg_Internal for the cases where no
  312.    --  generic instantiations occur. There are two special cases in which
  313.    --  instantiations are relevant to error messages.
  314.  
  315.    --  First, if an error is posted within an instance, then this is a
  316.    --  generic contract violation, and we want the error message to point
  317.    --  to the original instantiation.
  318.  
  319.    --  Second, if the error message contains a reference to an instantiation,
  320.    --  then we want to point to the instantiation as well as the location in
  321.    --  the template being referenced.
  322.  
  323.    procedure Error_Msg (Msg : String; Flag_Location : Source_Ptr) is
  324.       X : Source_File_Index;
  325.  
  326.       Actual_Error_Loc : Source_Ptr;
  327.       --  Location of outer level instantiation in instantiation case, or
  328.       --  just a copy of Flag_Location in the normal case. This is the
  329.       --  location where all error messages will actually be posted.
  330.  
  331.       Save_Error_Msg_Sloc : Source_Ptr;
  332.       --  Save Error_Msg_Sloc in instantiation case
  333.  
  334.    begin
  335.       --  It is a fatal error to issue an error message when scanning from
  336.       --  the internal source buffer (see Sinput for further documentation)
  337.  
  338.       pragma Assert (Source /= Internal_Source_Ptr);
  339.  
  340.       --  Otherwise continue with error message processing
  341.  
  342.       X := Get_Source_File_Index (Flag_Location);
  343.  
  344.       --  If not an instance then just output the message at current location
  345.  
  346.       if Instantiation (X) = No_Location then
  347.          Actual_Error_Loc := Flag_Location;
  348.  
  349.       --  If we are trying to flag an error in an instantiation, we have
  350.       --  a generic contract violation. What we want to generate in this
  351.       --  case is:
  352.  
  353.       --     instantiation requirements not met, detected at ...
  354.       --     original error message
  355.  
  356.       --  All these messages are posted at the location of the top level
  357.       --  instantiation. If there are nested instantiations, then the
  358.       --  initial error message can be repeated. We first save the value
  359.       --  of Error_Msg_Sloc, in case it is used in the original error text.
  360.  
  361.       else
  362.          Save_Error_Msg_Sloc := Error_Msg_Sloc;
  363.  
  364.          --  Now use a recursive procedure to output the instantiation messages
  365.          --  The instantiation pointers point from the inside outwards, so the
  366.          --  first message to be output (for the outer instantiation) is for
  367.          --  the deepest one when we are following Instantiation links.
  368.  
  369.          declare
  370.             procedure Output_Inst_Error_Msg (Loc : Source_Ptr);
  371.             --  Output instantiation message, where Loc is the location of
  372.             --  the instantiation.
  373.  
  374.             procedure Output_Inst_Error_Msg (Loc : Source_Ptr) is
  375.                Xinst : Source_File_Index;
  376.  
  377.             begin
  378.                Xinst := Get_Source_File_Index (Loc);
  379.  
  380.                if Instantiation (Xinst) /= No_Location then
  381.                   Output_Inst_Error_Msg (Instantiation (Xinst));
  382.                else
  383.                   Actual_Error_Loc := Loc;
  384.                end if;
  385.  
  386.                Error_Msg_Sloc := Loc;
  387.                Error_Msg_Internal
  388.                  ("instantiation requirements not met, detected at #",
  389.                   Actual_Error_Loc);
  390.             end Output_Inst_Error_Msg;
  391.  
  392.          begin
  393.             Output_Inst_Error_Msg (Instantiation (X));
  394.          end;
  395.  
  396.          Error_Msg_Sloc := Save_Error_Msg_Sloc;
  397.       end if;
  398.  
  399.       Error_Msg_Internal (Msg, Actual_Error_Loc);
  400.  
  401.       --  Now we have output the message, together with instantiation
  402.       --  references if the message was placed within the instantiation.
  403.       --  Now we must deal with the case where the message contained a
  404.       --  reference to an instantiation. In this case we will append
  405.       --  messages of the form:
  406.  
  407.       --    instantiated at #
  408.  
  409.       --  showing the instantiation locations. In the case of nested
  410.       --  instantiations, more than one such message will be output.
  411.  
  412.       if Error_Msg_Loc_Output /= No_Location then
  413.          declare
  414.             Xind : Source_File_Index;
  415.  
  416.          begin
  417.             Error_Msg_Sloc := Error_Msg_Loc_Output;
  418.  
  419.             loop
  420.                Xind := Get_Source_File_Index (Error_Msg_Sloc);
  421.                Error_Msg_Sloc := Instantiation (Xind);
  422.                exit when Error_Msg_Sloc = No_Location;
  423.                Error_Msg_Internal ("instantiated at #", Actual_Error_Loc);
  424.             end loop;
  425.          end;
  426.       end if;
  427.    end Error_Msg;
  428.  
  429.    ------------------------
  430.    -- Error_Msg_Internal --
  431.    ------------------------
  432.  
  433.    procedure Error_Msg_Internal (Msg : String; Flag_Location : Source_Ptr) is
  434.       Next_Msg : Error_Msg_Id;
  435.       --  Pointer to next message at insertion point
  436.  
  437.       Prev_Msg : Error_Msg_Id;
  438.       --  Pointer to previous message at insertion point
  439.  
  440.       Temp_Msg : Error_Msg_Id;
  441.  
  442.    begin
  443.       Suppress_Message := False;
  444.       Kill_Message := False;
  445.       Error_Msg_Loc_Output := No_Location;
  446.       Set_Msg_Text (Msg, Flag_Location);
  447.  
  448.       --  Return without doing anything if message is suppressed
  449.  
  450.       if Suppress_Message
  451.         and not All_Errors_Mode
  452.         and not (Msg (Msg'Last) = '!')
  453.       then
  454.          return;
  455.       end if;
  456.  
  457.       --  Return without doing anything if message is killed and this
  458.       --  is not the first error message. The philosophy is that if we
  459.       --  get a weird error message and we already have had a message,
  460.       --  then we hope the weird message is a junk cascaded message
  461.  
  462.       if Kill_Message
  463.         and then not All_Errors_Mode
  464.         and then Errors_Detected /= 0
  465.       then
  466.          return;
  467.       end if;
  468.  
  469.       --  Immediate return if warning message and warnings are suppressed
  470.  
  471.       if Is_Warning_Msg and then Warning_Mode = Suppress then
  472.          Cur_Msg := No_Error_Msg;
  473.          return;
  474.       end if;
  475.  
  476.       --  Otherwise build error message object for new message
  477.  
  478.       Name_Buffer (1 .. Msg_Len) := Msg_Buffer (1 .. Msg_Len);
  479.       Name_Len := Msg_Len;
  480.  
  481.       Errors.Increment_Last;
  482.       Cur_Msg := Errors.Last;
  483.       Errors.Table (Cur_Msg).Text   := Name_Find;
  484.       Errors.Table (Cur_Msg).Next   := No_Error_Msg;
  485.       Errors.Table (Cur_Msg).Sptr   := Flag_Location;
  486.       Errors.Table (Cur_Msg).Sfile  := Get_Source_File_Index (Flag_Location);
  487.       Errors.Table (Cur_Msg).Line   := Get_Line_Number (Flag_Location);
  488.       Errors.Table (Cur_Msg).Col    := Get_Column_Number (Flag_Location);
  489.       Errors.Table (Cur_Msg).Warn   := Is_Warning_Msg;
  490.       Errors.Table (Cur_Msg).Uncond := Is_Unconditional_Msg;
  491.  
  492.       --  If immediate errors mode set, output error message now. Also output
  493.       --  now if the -d1 debug flag is set (so node number message comes out
  494.       --  just before actual error message)
  495.  
  496.       if Immediate_Errors or else Debug_Flag_1 then
  497.          Write_Eol;
  498.          Output_Source_Line (Errors.Table (Cur_Msg).Line,
  499.            Errors.Table (Cur_Msg).Sfile, True);
  500.          Temp_Msg := Cur_Msg;
  501.          Output_Error_Msgs (Temp_Msg);
  502.  
  503.       --  If not in immediate errors mode, then we insert the message in the
  504.       --  error chain for later output by Finalize_Error_Output. The messages
  505.       --  are sorted first by unit (main unit comes first), and within a unit
  506.       --  by source location (earlier flag location first in the chain).
  507.  
  508.       else
  509.          Prev_Msg := No_Error_Msg;
  510.          Next_Msg := Error_Msgs;
  511.  
  512.          while Next_Msg /= No_Error_Msg loop
  513.             exit when
  514.               Errors.Table (Cur_Msg).Sfile < Errors.Table (Next_Msg).Sfile;
  515.  
  516.             if Errors.Table (Cur_Msg).Sfile =
  517.                  Errors.Table (Next_Msg).Sfile
  518.             then
  519.                exit when Flag_Location < Errors.Table (Next_Msg).Sptr;
  520.             end if;
  521.  
  522.             Prev_Msg := Next_Msg;
  523.             Next_Msg := Errors.Table (Next_Msg).Next;
  524.          end loop;
  525.  
  526.          --  The possible insertion point for the new message is after Prev_Msg
  527.          --  and before Next_Msg. However, there are some cases in which we do
  528.          --  not insert the message on the grounds that it is redundant with
  529.          --  respect to the previous message. We only consider deleting the
  530.          --  message if it is for the same line and unit as the previous one.
  531.  
  532.          if Prev_Msg /= No_Error_Msg
  533.            and then Errors.Table (Prev_Msg).Line =
  534.                                              Errors.Table (Cur_Msg).Line
  535.            and then Errors.Table (Prev_Msg).Sfile =
  536.                                              Errors.Table (Cur_Msg).Sfile
  537.          then
  538.             --  Delete a complete duplicate message (i.e. same error text
  539.             --  at same position). Such duplicate messages are typically
  540.             --  lexical messages from tokens that are rescanned. Note that
  541.             --  such complete duplicates are deleted even if All_Errors
  542.             --  mode is set on, since they can't possibly give any useful
  543.             --  information under any circumstances.
  544.  
  545.             if Errors.Table (Prev_Msg).Col = Errors.Table (Cur_Msg).Col
  546.               and then
  547.                 Errors.Table (Prev_Msg).Text = Errors.Table (Cur_Msg).Text
  548.             then
  549.                return;
  550.             end if;
  551.  
  552.             --  Remaining case is where we are parsing and we are not in
  553.             --  all errors mode (in semantics, don't delete any messages)
  554.  
  555.             if not All_Errors_Mode and then Compiler_State = Parsing then
  556.  
  557.                --  Don't delete unconditional messages
  558.  
  559.                if not Errors.Table (Cur_Msg).Uncond then
  560.  
  561.                   --  Don't delete if prev msg is warning and new msg is
  562.                   --  an error. This is because we don't want a real error
  563.                   --  masked by a warning. In all other cases (that is parse
  564.                   --  errors for the same line that are not unconditional)
  565.                   --  we do delete the message. This helps to avoid
  566.                   --  junk extra messages from cascaded parsing errors
  567.  
  568.                   if not Errors.Table (Prev_Msg).Warn
  569.                     or else Errors.Table (Cur_Msg).Warn
  570.                   then
  571.                      --  All tests passed, delete the message by simply
  572.                      --  returning without any further processing.
  573.  
  574.                      return;
  575.                   end if;
  576.                end if;
  577.             end if;
  578.          end if;
  579.  
  580.          --  Come here if message is to be inserted in the error chain
  581.  
  582.          if Prev_Msg = No_Error_Msg then
  583.             Error_Msgs := Cur_Msg;
  584.          else
  585.             Errors.Table (Prev_Msg).Next := Cur_Msg;
  586.          end if;
  587.  
  588.          Errors.Table (Cur_Msg).Next := Next_Msg;
  589.       end if;
  590.  
  591.       --  Bump appropriate statistics count
  592.  
  593.       if Errors.Table (Cur_Msg).Warn
  594.         and then Warning_Mode /= Treat_As_Error
  595.       then
  596.          Warnings_Detected := Warnings_Detected + 1;
  597.  
  598.       else
  599.          if Error_Monitoring_On then
  600.             Monitored_Errors := Monitored_Errors + 1;
  601.             Warnings_Detected := Warnings_Detected + 1;
  602.             Errors.Table (Cur_Msg).Warn := True;
  603.  
  604.             if Monitored_Message /= No_Name then
  605.                if Monitored_Message = Errors.Table (Cur_Msg).Text then
  606.                   Monitored_Message := No_Name;
  607.                else
  608.                   Monitored_Message := Error_Name;
  609.                end if;
  610.             end if;
  611.  
  612.          else
  613.             Errors_Detected := Errors_Detected + 1;
  614.          end if;
  615.  
  616.          --  Turn off code generation if not done already
  617.  
  618.          if Operating_Mode = Generate_Code then
  619.             Operating_Mode := Check_Semantics;
  620.             Expander_Active := False;
  621.          end if;
  622.  
  623.          --  Set the fatal error flag in the unit table unless we are
  624.          --  in Try_Semantics mode. This stops the semantics from
  625.  
  626.          if not Try_Semantics then
  627.             Set_Fatal_Error (Get_Sloc_Unit_Number (Flag_Location));
  628.          end if;
  629.       end if;
  630.  
  631.       --  Terminate if max errors reached
  632.  
  633.       if Errors_Detected = Maximum_Errors then
  634.          raise Unrecoverable_Error;
  635.       end if;
  636.  
  637.    end Error_Msg_Internal;
  638.  
  639.    -----------------
  640.    -- Error_Msg_S --
  641.    -----------------
  642.  
  643.    procedure Error_Msg_S (Msg : String) is
  644.    begin
  645.       Error_Msg (Msg, Scan_Ptr);
  646.    end Error_Msg_S;
  647.  
  648.    ------------------
  649.    -- Error_Msg_AP --
  650.    ------------------
  651.  
  652.    procedure Error_Msg_AP (Msg : String) is
  653.       S1 : Source_Ptr;
  654.       C  : Character;
  655.  
  656.    begin
  657.       --  If we had saved the Scan_Ptr value after scanning the previous
  658.       --  token, then we would have exactly the right place for putting
  659.       --  the flag immediately at hand. However, that would add at least
  660.       --  two instructions to a Scan call *just* to service the possibility
  661.       --  of an Error_Msg_AP call. So instead we reconstruct that value.
  662.  
  663.       --  We have two possibilities, start with Prev_Token_Ptr and skip over
  664.       --  the current token, which is made harder by the possibility that this
  665.       --  token may be in error, or start with Token_Ptr and work backwards.
  666.       --  We used to take the second approach, but it's hard because of
  667.       --  comments, and harder still because things that look like comments
  668.       --  can appear inside strings. So now we take the first approach.
  669.  
  670.       --  Note: in the case where there is no previous token, Prev_Token_Ptr
  671.       --  is set to Source_First, which is a reasonable position for the
  672.       --  error flag in this situation.
  673.  
  674.       S1 := Prev_Token_Ptr;
  675.       C := Source (S1);
  676.  
  677.       --  If the previous token is a string literal, we need a special approach
  678.       --  since there may be white space inside the literal and we don't want
  679.       --  to stop on that white space.
  680.  
  681.       if Prev_Token = Tok_String_Literal then
  682.          loop
  683.             S1 := S1 + 1;
  684.  
  685.             if Source (S1) = C then
  686.                S1 := S1 + 1;
  687.                exit when Source (S1) /= C;
  688.             elsif Source (S1) in Line_Terminator then
  689.                exit;
  690.             end if;
  691.          end loop;
  692.  
  693.       --  Character literal also needs special handling
  694.  
  695.       elsif Prev_Token = Tok_Char_Literal then
  696.          S1 := S1 + 3;
  697.  
  698.       --  Otherwise we search forward for the end of the current token, marked
  699.       --  by a line terminator, white space, a comment symbol or if we bump
  700.       --  into the following token (i.e. the current token)
  701.  
  702.       else
  703.          while Source (S1) not in Line_Terminator
  704.            and then Source (S1) /= ' '
  705.            and then Source (S1) /= Ascii.HT
  706.            and then (Source (S1) /= '-' or else Source (S1 + 1) /= '-')
  707.            and then S1 /= Token_Ptr
  708.          loop
  709.             S1 := S1 + 1;
  710.          end loop;
  711.       end if;
  712.  
  713.       --  S1 is now set to the location for the flag
  714.  
  715.       Error_Msg (Msg, S1);
  716.  
  717.    end Error_Msg_AP;
  718.  
  719.    ------------------
  720.    -- Error_Msg_BC --
  721.    ------------------
  722.  
  723.    procedure Error_Msg_BC (Msg : String) is
  724.    begin
  725.       --  If we are at end of file, post the flag after the previous token
  726.  
  727.       if Token = Tok_EOF then
  728.          Error_Msg_AP (Msg);
  729.  
  730.       --  If we are at start of file, post the flag at the current token
  731.  
  732.       elsif Token_Ptr = Source_First (Current_Source_File) then
  733.          Error_Msg_SC (Msg);
  734.  
  735.       --  If the character before the current token is a space or a horizontal
  736.       --  tab, then we place the flag on this character (in the case of a tab
  737.       --  we would really like to place it in the "last" character of the tab
  738.       --  space, but that it too much trouble to worry about).
  739.  
  740.       elsif Source (Token_Ptr - 1) = ' '
  741.          or else Source (Token_Ptr - 1) = Ascii.HT
  742.       then
  743.          Error_Msg (Msg, Token_Ptr - 1);
  744.  
  745.       --  If there is no space or tab before the current token, then there is
  746.       --  no room to place the flag before the token, so we place it on the
  747.       --  token instead (this happens for example at the start of a line).
  748.  
  749.       else
  750.          Error_Msg (Msg, Token_Ptr);
  751.       end if;
  752.    end Error_Msg_BC;
  753.  
  754.    ------------------
  755.    -- Error_Msg_SC --
  756.    ------------------
  757.  
  758.    procedure Error_Msg_SC (Msg : String) is
  759.    begin
  760.       --  If we are at end of file, post the flag after the previous token
  761.  
  762.       if Token = Tok_EOF then
  763.          Error_Msg_AP (Msg);
  764.  
  765.       --  For all other cases the message is posted at the current token
  766.       --  pointer position
  767.  
  768.       else
  769.          Error_Msg (Msg, Token_Ptr);
  770.       end if;
  771.    end Error_Msg_SC;
  772.  
  773.    ------------------
  774.    -- Error_Msg_SP --
  775.    ------------------
  776.  
  777.    procedure Error_Msg_SP (Msg : String) is
  778.    begin
  779.       --  Note: in the case where there is no previous token, Prev_Token_Ptr
  780.       --  is set to Source_First, which is a reasonable position for the
  781.       --  error flag in this situation
  782.  
  783.       Error_Msg (Msg, Prev_Token_Ptr);
  784.    end Error_Msg_SP;
  785.  
  786.    -----------------
  787.    -- Error_Msg_N --
  788.    -----------------
  789.  
  790.    procedure Error_Msg_N (Msg : String; N : Node_Id) is
  791.    begin
  792.       if All_Errors_Mode
  793.         or else Msg (Msg'Last) = '!'
  794.         or else OK_Node (N)
  795.       then
  796.          Debug_Output (N);
  797.          Error_Msg_Node_1 := N;
  798.          Error_Msg (Msg, Sloc (N));
  799.       end if;
  800.  
  801.       if not Is_Warning_Msg then
  802.          Set_Error_Posted (N, True);
  803.       end if;
  804.    end Error_Msg_N;
  805.  
  806.    ------------------
  807.    -- Error_Msg_NE --
  808.    ------------------
  809.  
  810.    procedure Error_Msg_NE (Msg : String; N : Node_Id; E : Entity_Id) is
  811.    begin
  812.       if All_Errors_Mode
  813.         or else Msg (Msg'Last) = '!'
  814.         or else OK_Node (N)
  815.       then
  816.          Debug_Output (N);
  817.          Error_Msg_Node_1 := E;
  818.          Error_Msg (Msg, Sloc (N));
  819.       end if;
  820.  
  821.       if not Is_Warning_Msg then
  822.          Set_Error_Posted (N, True);
  823.       end if;
  824.    end Error_Msg_NE;
  825.  
  826.    --------------
  827.    -- Finalize --
  828.    --------------
  829.  
  830.    procedure Finalize is
  831.       E        : Error_Msg_Id;
  832.       Err_Flag : Boolean;
  833.       L        : Logical_Line_Number;
  834.  
  835.    begin
  836.       --  Brief Error mode
  837.  
  838.       if Brief_Output or (not Full_List and not Verbose_Mode) then
  839.          E := Error_Msgs;
  840.          Set_Standard_Error;
  841.  
  842.          while E /= No_Error_Msg loop
  843.             Write_Name (Reference_Name (Errors.Table (E).Sfile));
  844.             Write_Char (':');
  845.             Write_Int (Int (Errors.Table (E).Line));
  846.             Write_Char (':');
  847.  
  848.             if Errors.Table (E).Col < 10 then
  849.                Write_Char ('0');
  850.             end if;
  851.  
  852.             Write_Int (Int (Errors.Table (E).Col));
  853.             Write_Str (": ");
  854.             Output_Msg_Text (E);
  855.             Write_Eol;
  856.             E := Errors.Table (E).Next;
  857.          end loop;
  858.  
  859.          Set_Standard_Output;
  860.       end if;
  861.  
  862.       --  Full source listing case
  863.  
  864.       if Full_List then
  865.          List_Pragmas_Index := 1;
  866.          List_Pragmas_Mode := True;
  867.          E := Error_Msgs;
  868.          Write_Eol;
  869.  
  870.          --  First list initial main source file with its error messages
  871.  
  872.          for N in 1 .. Num_Source_Lines (Main_Source) loop
  873.             L := Physical_To_Logical (N, Main_Source);
  874.  
  875.             Err_Flag :=
  876.               E /= No_Error_Msg
  877.                 and then Errors.Table (E).Line = L
  878.                 and then Errors.Table (E).Sfile = Main_Source;
  879.  
  880.             Output_Source_Line (L, Main_Source, Err_Flag);
  881.  
  882.             if Err_Flag then
  883.                Output_Error_Msgs (E);
  884.  
  885.                if not Debug_Flag_2 then
  886.                   Write_Eol;
  887.                end if;
  888.             end if;
  889.  
  890.          end loop;
  891.  
  892.          --  Then output errors, if any, for subsidiary units
  893.  
  894.          while E /= No_Error_Msg
  895.            and then Errors.Table (E).Sfile /= Main_Source
  896.          loop
  897.             Write_Eol;
  898.             Output_Source_Line
  899.               (Errors.Table (E).Line, Errors.Table (E).Sfile, True);
  900.             Output_Error_Msgs (E);
  901.          end loop;
  902.       end if;
  903.  
  904.       --  Verbose mode (error lines only with error flags)
  905.  
  906.       if Verbose_Mode and not Full_List then
  907.          E := Error_Msgs;
  908.  
  909.          --  Loop through error lines
  910.  
  911.          while E /= No_Error_Msg loop
  912.             Write_Eol;
  913.             Output_Source_Line
  914.               (Errors.Table (E).Line, Errors.Table (E).Sfile, True);
  915.             Output_Error_Msgs (E);
  916.          end loop;
  917.       end if;
  918.  
  919.       --  Output error summary if verbose or full list mode
  920.  
  921.       if Verbose_Mode or else Full_List then
  922.  
  923.          --  Extra blank line if error messages or source listing were output
  924.  
  925.          if Errors_Detected + Warnings_Detected > 0 or else Full_List then
  926.             Write_Eol;
  927.          end if;
  928.  
  929.          --  Message giving total number of lines
  930.  
  931.          Write_Str (" ");
  932.          Write_Int (Num_Source_Lines (Main_Source));
  933.  
  934.          if Num_Source_Lines (Main_Source) = 1 then
  935.             Write_Str (" line: ");
  936.          else
  937.             Write_Str (" lines: ");
  938.          end if;
  939.  
  940.          --  Message giving number of errors detected. This normally goes to
  941.          --  Standard_Output. The exception is when brief mode is not set,
  942.          --  verbose mode (or full list mode) is set, and there are errors.
  943.          --  In this case we send the message to standard error to make sure
  944.          --  that *something* appears on standard error in an error situation.
  945.  
  946.          if Errors_Detected + Warnings_Detected /= 0
  947.            and then not Brief_Output
  948.            and then (Verbose_Mode or Full_List)
  949.          then
  950.             Set_Standard_Error;
  951.          end if;
  952.  
  953.          if Errors_Detected = 0 then
  954.             Write_Str ("No errors");
  955.  
  956.          elsif Errors_Detected = 1 then
  957.             Write_Str ("1 error");
  958.  
  959.          else
  960.             Write_Int (Errors_Detected);
  961.             Write_Str (" errors");
  962.          end if;
  963.  
  964.          if Warnings_Detected = 1 then
  965.             Write_Str (", 1 warning");
  966.  
  967.          elsif Warnings_Detected > 1 then
  968.             Write_Str (", ");
  969.             Write_Int (Warnings_Detected);
  970.             Write_Str (" warnings");
  971.          end if;
  972.  
  973.          Write_Eol;
  974.          Set_Standard_Output;
  975.       end if;
  976.  
  977.       if Maximum_Errors /= 0
  978.         and then Errors_Detected = Maximum_Errors
  979.       then
  980.          Set_Standard_Error;
  981.          Write_Str ("fatal error: maximum errors reached");
  982.          Write_Eol;
  983.          Set_Standard_Output;
  984.       end if;
  985.  
  986.    end Finalize;
  987.  
  988.    ----------------
  989.    -- Get_Msg_Id --
  990.    ----------------
  991.  
  992.    function Get_Msg_Id return Error_Msg_Id is
  993.    begin
  994.       return Cur_Msg;
  995.    end Get_Msg_Id;
  996.  
  997.    ----------------
  998.    -- Initialize --
  999.    ----------------
  1000.  
  1001.    procedure Initialize is
  1002.    begin
  1003.       Errors.Init;
  1004.       Error_Msgs := No_Error_Msg;
  1005.       Errors_Detected := 0;
  1006.       Warnings_Detected := 0;
  1007.       Error_Monitoring_On := False;
  1008.       Cur_Msg := No_Error_Msg;
  1009.       Current_Error_Source_File := Main_Source;
  1010.       List_Pragmas.Init;
  1011.    end Initialize;
  1012.  
  1013.    -------------
  1014.    -- OK_Node --
  1015.    -------------
  1016.  
  1017.    function OK_Node (N : Node_Id) return Boolean is
  1018.       K : constant Node_Kind := Nkind (N);
  1019.  
  1020.    begin
  1021.       if Error_Posted (N) then
  1022.          return False;
  1023.  
  1024.       elsif K in N_Has_Etype
  1025.         and then Present (Etype (N))
  1026.         and then Error_Posted (Etype (N))
  1027.       then
  1028.          return False;
  1029.  
  1030.       elsif (K in N_Op
  1031.               or else K = N_Attribute_Reference
  1032.               or else K = N_Character_Literal
  1033.               or else K = N_Expanded_Name
  1034.               or else K = N_Identifier
  1035.               or else K = N_Operator_Symbol)
  1036.         and then Present (Entity (N))
  1037.         and then Error_Posted (Entity (N))
  1038.       then
  1039.          return False;
  1040.       else
  1041.          return True;
  1042.       end if;
  1043.    end OK_Node;
  1044.  
  1045.    -----------------------
  1046.    -- Output_Error_Msgs --
  1047.    -----------------------
  1048.  
  1049.    procedure Output_Error_Msgs (E : in out Error_Msg_Id) is
  1050.       P : Source_Ptr;
  1051.       T : Error_Msg_Id;
  1052.       Flag_Num : Pos;
  1053.       Mult_Flags : Boolean := False;
  1054.  
  1055.    begin
  1056.       --  Figure out if we will place more than one error flag on this line
  1057.  
  1058.       T := E;
  1059.       while T /= No_Error_Msg
  1060.         and then Errors.Table (T).Line = Errors.Table (E).Line
  1061.         and then Errors.Table (T).Sfile = Errors.Table (E).Sfile
  1062.       loop
  1063.          if Errors.Table (T).Sptr > Errors.Table (E).Sptr then
  1064.             Mult_Flags := True;
  1065.          end if;
  1066.  
  1067.          T := Errors.Table (T).Next;
  1068.       end loop;
  1069.  
  1070.       --  Output the error flags. The circuit here makes sure that the tab
  1071.       --  characters in the original line are properly accounted for. The
  1072.       --  eight blanks at the start are to match the line number.
  1073.  
  1074.       if not Debug_Flag_2 then
  1075.          Write_Str ("        ");
  1076.          P := Line_Start (Errors.Table (E).Sptr);
  1077.          Flag_Num := 1;
  1078.  
  1079.          --  Loop through error messages for this line to place flags
  1080.  
  1081.          T := E;
  1082.          while T /= No_Error_Msg
  1083.            and then Errors.Table (T).Line = Errors.Table (E).Line
  1084.            and then Errors.Table (T).Sfile = Errors.Table (E).Sfile
  1085.          loop
  1086.  
  1087.             --  Loop to output blanks till current flag position
  1088.  
  1089.             while P < Errors.Table (T).Sptr loop
  1090.                if Source_Text (Errors.Table (T).Sfile) (P) = Ascii.HT then
  1091.                   Write_Char (Ascii.HT);
  1092.                else
  1093.                   Write_Char (' ');
  1094.                end if;
  1095.  
  1096.                P := P + 1;
  1097.             end loop;
  1098.  
  1099.             --  Output flag (unless already output, this happens if more
  1100.             --  than one error message occurs at the same flag position).
  1101.  
  1102.             if P = Errors.Table (T).Sptr then
  1103.                if (Flag_Num = 1 and then not Mult_Flags)
  1104.                  or else Flag_Num > 9
  1105.                then
  1106.                   Write_Char ('|');
  1107.                else
  1108.                   Write_Char (Character'Val (Character'Pos ('0') + Flag_Num));
  1109.                end if;
  1110.  
  1111.                P := P + 1;
  1112.             end if;
  1113.  
  1114.             T := Errors.Table (T).Next;
  1115.             Flag_Num := Flag_Num + 1;
  1116.          end loop;
  1117.  
  1118.          Write_Eol;
  1119.       end if;
  1120.  
  1121.       --  Now output the error messages
  1122.  
  1123.       T := E;
  1124.  
  1125.       while T /= No_Error_Msg
  1126.         and then Errors.Table (T).Line = Errors.Table (E).Line
  1127.         and then Errors.Table (T).Sfile = Errors.Table (E).Sfile
  1128.  
  1129.       loop
  1130.          Write_Str ("        >>> ");
  1131.          Output_Msg_Text (T);
  1132.  
  1133.          if Debug_Flag_2 then
  1134.             while Column < 74 loop
  1135.                Write_Char (' ');
  1136.             end loop;
  1137.  
  1138.             Write_Str (" <<<");
  1139.          end if;
  1140.  
  1141.          Write_Eol;
  1142.          T := Errors.Table (T).Next;
  1143.       end loop;
  1144.  
  1145.       E := T;
  1146.    end Output_Error_Msgs;
  1147.  
  1148.    ------------------------
  1149.    -- Output_Line_Number --
  1150.    ------------------------
  1151.  
  1152.    procedure Output_Line_Number (L : Logical_Line_Number) is
  1153.       D     : Int;       -- next digit
  1154.       C     : Character; -- next character
  1155.       Z     : Boolean;   -- flag for zero suppress
  1156.       N, M  : Int;       -- temporaries
  1157.  
  1158.    begin
  1159.       Z := False;
  1160.       N := Int (L);
  1161.  
  1162.       M := 100_000;
  1163.       while M /= 0 loop
  1164.          D := Int (N / M);
  1165.          N := N rem M;
  1166.          M := M / 10;
  1167.  
  1168.          if D = 0 then
  1169.             if Z then
  1170.                C := '0';
  1171.             else
  1172.                C := ' ';
  1173.             end if;
  1174.          else
  1175.             Z := True;
  1176.             C := Character'Val (D + 48);
  1177.          end if;
  1178.  
  1179.          Write_Char (C);
  1180.       end loop;
  1181.  
  1182.       Write_Str (". ");
  1183.    end Output_Line_Number;
  1184.  
  1185.    ---------------------
  1186.    -- Output_Msg_Text --
  1187.    ---------------------
  1188.  
  1189.    procedure Output_Msg_Text (E : Error_Msg_Id) is
  1190.    begin
  1191.       if Errors.Table (E).Warn then
  1192.          Write_Str ("warning: ");
  1193.  
  1194.       elsif System.Parameters.Tag_Errors then
  1195.          Write_Str ("error: ");
  1196.       end if;
  1197.  
  1198.       Write_Name (Errors.Table (E).Text);
  1199.    end Output_Msg_Text;
  1200.  
  1201.    ------------------------
  1202.    -- Output_Source_Line --
  1203.    ------------------------
  1204.  
  1205.    procedure Output_Source_Line
  1206.      (L     : Logical_Line_Number;
  1207.       Sfile : Source_File_Index;
  1208.       Errs  : Boolean)
  1209.    is
  1210.       S : Source_Ptr;
  1211.       C : Character;
  1212.  
  1213.       Line_Number_Output : Boolean := False;
  1214.       --  Set True once line number is output
  1215.  
  1216.    begin
  1217.       if Sfile /= Current_Error_Source_File then
  1218.          Write_Str ("==============Error messages for source file: ");
  1219.          Write_Name (Reference_Name (Sfile));
  1220.          Write_Eol;
  1221.          Current_Error_Source_File := Sfile;
  1222.       end if;
  1223.  
  1224.       if Errs or List_Pragmas_Mode then
  1225.          Output_Line_Number (L);
  1226.          Line_Number_Output := True;
  1227.       end if;
  1228.  
  1229.       S := Line_Start (L, Sfile);
  1230.  
  1231.       loop
  1232.          C := Source_Text (Sfile) (S);
  1233.          exit when C = Ascii.LF or else C = Ascii.CR or else C = EOF;
  1234.  
  1235.          --  Deal with matching entry in List_Pragmas table
  1236.  
  1237.          if Full_List
  1238.            and then List_Pragmas_Index <= List_Pragmas.Last
  1239.            and then S = List_Pragmas.Table (List_Pragmas_Index).Ploc
  1240.          then
  1241.  
  1242.             case List_Pragmas.Table (List_Pragmas_Index).Ptyp is
  1243.                when Page =>
  1244.                   Write_Char (C);
  1245.  
  1246.                   --  Ignore if on line with errors so that error flags
  1247.                   --  get properly listed with the error line .
  1248.  
  1249.  
  1250.                   if not Errs then
  1251.                      Write_Char (Ascii.FF);
  1252.                   end if;
  1253.  
  1254.                when List_On =>
  1255.                   List_Pragmas_Mode := True;
  1256.  
  1257.                   if not Line_Number_Output then
  1258.                      Output_Line_Number (L);
  1259.                      Line_Number_Output := True;
  1260.                   end if;
  1261.  
  1262.                   Write_Char (C);
  1263.  
  1264.                when List_Off =>
  1265.                   Write_Char (C);
  1266.                   List_Pragmas_Mode := False;
  1267.             end case;
  1268.  
  1269.             List_Pragmas_Index := List_Pragmas_Index + 1;
  1270.  
  1271.          --  Normal case (no matching entry in List_Pragmas table)
  1272.  
  1273.          else
  1274.             if Errs or List_Pragmas_Mode then
  1275.                Write_Char (C);
  1276.             end if;
  1277.          end if;
  1278.  
  1279.          S := S + 1;
  1280.       end loop;
  1281.  
  1282.       if Line_Number_Output then
  1283.          Write_Eol;
  1284.       end if;
  1285.    end Output_Source_Line;
  1286.  
  1287.    -------------------
  1288.    -- Set_Msg_Blank --
  1289.    -------------------
  1290.  
  1291.    procedure Set_Msg_Blank is
  1292.    begin
  1293.       if Msg_Len > 0
  1294.         and then Msg_Buffer (Msg_Len) /= ' '
  1295.         and then Msg_Buffer (Msg_Len) /= '('
  1296.       then
  1297.          Set_Msg_Char (' ');
  1298.       end if;
  1299.    end Set_Msg_Blank;
  1300.  
  1301.    -------------------------------
  1302.    -- Set_Msg_Blank_Conditional --
  1303.    -------------------------------
  1304.  
  1305.    procedure Set_Msg_Blank_Conditional is
  1306.    begin
  1307.       if Msg_Len > 0
  1308.         and then Msg_Buffer (Msg_Len) /= ' '
  1309.         and then Msg_Buffer (Msg_Len) /= '('
  1310.         and then Msg_Buffer (Msg_Len) /= '"'
  1311.       then
  1312.          Set_Msg_Char (' ');
  1313.       end if;
  1314.    end Set_Msg_Blank_Conditional;
  1315.  
  1316.    ------------------
  1317.    -- Set_Msg_Char --
  1318.    ------------------
  1319.  
  1320.    procedure Set_Msg_Char (C : Character) is
  1321.    begin
  1322.  
  1323.       --  The check for message buffer overflow is needed to deal with cases
  1324.       --  where insertions get too long (in particular a child unit name can
  1325.       --  be very long).
  1326.  
  1327.       if Msg_Len < Max_Msg_Length then
  1328.          Msg_Len := Msg_Len + 1;
  1329.          Msg_Buffer (Msg_Len) := C;
  1330.       end if;
  1331.    end Set_Msg_Char;
  1332.  
  1333.    ------------------------------
  1334.    -- Set_Msg_Insertion_Column --
  1335.    ------------------------------
  1336.  
  1337.    procedure Set_Msg_Insertion_Column is
  1338.    begin
  1339.       if RM_Column_Check then
  1340.          Set_Msg_Str (" in column ");
  1341.          Set_Msg_Int (Int (Error_Msg_Col) + 1);
  1342.       end if;
  1343.    end Set_Msg_Insertion_Column;
  1344.  
  1345.    ---------------------------------
  1346.    -- Set_Msg_Insertion_File_Name --
  1347.    ---------------------------------
  1348.  
  1349.    procedure Set_Msg_Insertion_File_Name is
  1350.    begin
  1351.       if Error_Msg_Name_1 = No_Name then
  1352.          null;
  1353.  
  1354.       elsif Error_Msg_Name_1 = Error_Name then
  1355.          Set_Msg_Blank;
  1356.          Set_Msg_Str ("<error>");
  1357.  
  1358.       else
  1359.          Set_Msg_Blank;
  1360.          Get_Decoded_Name_String (Error_Msg_Name_1);
  1361.          Set_Msg_Quote;
  1362.          Set_Msg_Name_Buffer;
  1363.          Set_Msg_Quote;
  1364.       end if;
  1365.  
  1366.       --  The following assignments ensure that the second and third percent
  1367.       --  insertion characters will correspond to the Error_Msg_Name_2 and
  1368.       --  Error_Msg_Name_3 as required.
  1369.  
  1370.       Error_Msg_Name_1 := Error_Msg_Name_2;
  1371.       Error_Msg_Name_2 := Error_Msg_Name_3;
  1372.  
  1373.    end Set_Msg_Insertion_File_Name;
  1374.  
  1375.    -----------------------------------
  1376.    -- Set_Msg_Insertion_Line_Number --
  1377.    -----------------------------------
  1378.  
  1379.    procedure Set_Msg_Insertion_Line_Number (Loc, Flag : Source_Ptr) is
  1380.       Sindex : Source_File_Index;
  1381.  
  1382.    begin
  1383.       Set_Msg_Blank;
  1384.  
  1385.       if Loc = No_Location then
  1386.          Set_Msg_Str ("at unknown location");
  1387.  
  1388.       elsif Loc <= Standard_Location then
  1389.          Set_Msg_Str ("in package Standard");
  1390.  
  1391.          if Loc = Standard_Ascii_Location then
  1392.             Set_Msg_Str (".Ascii");
  1393.          end if;
  1394.  
  1395.       else
  1396.          Sindex := Get_Source_File_Index (Flag);
  1397.  
  1398.          --  Add "at file-name:" if reference is to other than the source
  1399.          --  file in which the error message is placed.
  1400.  
  1401.          if Loc not in Source_First (Sindex) .. Source_Last (Sindex) then
  1402.             Set_Msg_Str ("at ");
  1403.             Get_Decoded_Name_String
  1404.               (File_Name (Get_Source_File_Index (Loc)));
  1405.             Set_Msg_Name_Buffer;
  1406.             Set_Msg_Char (':');
  1407.  
  1408.          --  If in current file, add text "at line "
  1409.  
  1410.          else
  1411.             Set_Msg_Str ("at line ");
  1412.          end if;
  1413.  
  1414.          --  Output line and column
  1415.  
  1416.          Set_Msg_Int (Int (Get_Line_Number (Loc)));
  1417.          Error_Msg_Loc_Output := No_Location;
  1418.       end if;
  1419.    end Set_Msg_Insertion_Line_Number;
  1420.  
  1421.    ----------------------------
  1422.    -- Set_Msg_Insertion_Name --
  1423.    ----------------------------
  1424.  
  1425.    procedure Set_Msg_Insertion_Name is
  1426.    begin
  1427.       if Error_Msg_Name_1 = No_Name then
  1428.          null;
  1429.  
  1430.       elsif Error_Msg_Name_1 = Error_Name then
  1431.          Set_Msg_Blank;
  1432.          Set_Msg_Str ("<error>");
  1433.  
  1434.       else
  1435.          Set_Msg_Blank_Conditional;
  1436.          Get_Decoded_Name_String (Error_Msg_Name_1);
  1437.  
  1438.          --  If operator name or character literal name, just print it as is
  1439.          --  Also print as is if it ends in a right paren (case of x'val(nnn))
  1440.  
  1441.          if Name_Buffer (1) = '"'
  1442.            or else Name_Buffer (1) = '''
  1443.            or else Name_Buffer (Name_Len) = ')'
  1444.          then
  1445.             Set_Msg_Name_Buffer;
  1446.  
  1447.          --  Else output with surrounding quotes in proper casing mode
  1448.  
  1449.          else
  1450.             Set_Casing (Identifier_Casing (Flag_Source), Mixed_Case);
  1451.             Set_Msg_Quote;
  1452.             Set_Msg_Name_Buffer;
  1453.             Set_Msg_Quote;
  1454.          end if;
  1455.       end if;
  1456.  
  1457.       --  The following assignments ensure that the second and third percent
  1458.       --  insertion characters will correspond to the Error_Msg_Name_2 and
  1459.       --  Error_Msg_Name_3 as required.
  1460.  
  1461.       Error_Msg_Name_1 := Error_Msg_Name_2;
  1462.       Error_Msg_Name_2 := Error_Msg_Name_3;
  1463.  
  1464.    end Set_Msg_Insertion_Name;
  1465.  
  1466.    ----------------------------
  1467.    -- Set_Msg_Insertion_Node --
  1468.    ----------------------------
  1469.  
  1470.    procedure Set_Msg_Insertion_Node is
  1471.    begin
  1472.       Suppress_Message :=
  1473.         Error_Msg_Node_1 = Error
  1474.           or else Error_Msg_Node_1 = Any_Type;
  1475.  
  1476.       if Error_Msg_Node_1 = Empty then
  1477.          Set_Msg_Blank_Conditional;
  1478.          Set_Msg_Str ("<empty>");
  1479.  
  1480.       elsif Error_Msg_Node_1 = Error then
  1481.          Set_Msg_Blank;
  1482.          Set_Msg_Str ("<error>");
  1483.  
  1484.       elsif Error_Msg_Node_1 = Standard_Void_Type then
  1485.          Set_Msg_Blank;
  1486.          Set_Msg_Str ("procedure name");
  1487.  
  1488.       else
  1489.          Set_Msg_Blank_Conditional;
  1490.  
  1491.          --  Skip quotes for operator case
  1492.  
  1493.          if Nkind (Error_Msg_Node_1) in N_Op then
  1494.             Set_Msg_Node (Error_Msg_Node_1);
  1495.  
  1496.          else
  1497.             Set_Msg_Quote;
  1498.             Set_Msg_Node (Error_Msg_Node_1);
  1499.             Set_Msg_Quote;
  1500.          end if;
  1501.       end if;
  1502.  
  1503.       --  The following assignment ensures that a second ampersand insertion
  1504.       --  character will correspond to the Error_Msg_Node_2 parameter.
  1505.  
  1506.       Error_Msg_Node_1 := Error_Msg_Node_2;
  1507.  
  1508.    end Set_Msg_Insertion_Node;
  1509.  
  1510.    -------------------------------------
  1511.    -- Set_Msg_Insertion_Reserved_Name --
  1512.    -------------------------------------
  1513.  
  1514.    procedure Set_Msg_Insertion_Reserved_Name is
  1515.    begin
  1516.       Set_Msg_Blank_Conditional;
  1517.       Get_Name_String (Error_Msg_Name_1);
  1518.       Set_Msg_Quote;
  1519.       Set_Casing (Keyword_Casing (Flag_Source), All_Lower_Case);
  1520.       Set_Msg_Name_Buffer;
  1521.       Set_Msg_Quote;
  1522.    end Set_Msg_Insertion_Reserved_Name;
  1523.  
  1524.    -------------------------------------
  1525.    -- Set_Msg_Insertion_Reserved_Word --
  1526.    -------------------------------------
  1527.  
  1528.    procedure Set_Msg_Insertion_Reserved_Word
  1529.      (Text : String;
  1530.       J    : in out Integer)
  1531.    is
  1532.    begin
  1533.       Set_Msg_Blank_Conditional;
  1534.       Name_Len := 0;
  1535.  
  1536.       while J <= Text'Last and then Text (J) in 'A' .. 'Z' loop
  1537.          Name_Len := Name_Len + 1;
  1538.          Name_Buffer (Name_Len) := Text (J);
  1539.          J := J + 1;
  1540.       end loop;
  1541.  
  1542.       Set_Casing (Keyword_Casing (Flag_Source), All_Lower_Case);
  1543.       Set_Msg_Quote;
  1544.       Set_Msg_Name_Buffer;
  1545.       Set_Msg_Quote;
  1546.    end Set_Msg_Insertion_Reserved_Word;
  1547.  
  1548.    --------------------------------------
  1549.    -- Set_Msg_Insertion_Type_Reference --
  1550.    --------------------------------------
  1551.  
  1552.    procedure Set_Msg_Insertion_Type_Reference (Flag : Source_Ptr) is
  1553.    begin
  1554.       Set_Msg_Blank;
  1555.  
  1556.       if Error_Msg_Node_1 = Standard_Void_Type then
  1557.          Set_Msg_Str ("procedure name instead of function");
  1558.          return;
  1559.  
  1560.       elsif Error_Msg_Node_1 = Standard_Exception_Type then
  1561.          Set_Msg_Str ("an exception");
  1562.          return;
  1563.  
  1564.       elsif     Error_Msg_Node_1 = Any_Access
  1565.         or else Error_Msg_Node_1 = Any_Boolean
  1566.         or else Error_Msg_Node_1 = Any_Character
  1567.         or else Error_Msg_Node_1 = Any_Composite
  1568.         or else Error_Msg_Node_1 = Any_Discrete
  1569.         or else Error_Msg_Node_1 = Any_Fixed
  1570.         or else Error_Msg_Node_1 = Any_Integer
  1571.         or else Error_Msg_Node_1 = Any_Numeric
  1572.         or else Error_Msg_Node_1 = Any_Real
  1573.         or else Error_Msg_Node_1 = Any_Scalar
  1574.         or else Error_Msg_Node_1 = Any_String
  1575.       then
  1576.          Get_Decoded_Name_String (Chars (Error_Msg_Node_1));
  1577.          Set_Msg_Name_Buffer;
  1578.          return;
  1579.  
  1580.       elsif Error_Msg_Node_1 = Universal_Real then
  1581.          Set_Msg_Str ("type universal real");
  1582.          return;
  1583.  
  1584.       elsif Error_Msg_Node_1 = Universal_Integer then
  1585.          Set_Msg_Str ("type universal integer");
  1586.          return;
  1587.  
  1588.       elsif Error_Msg_Node_1 = Universal_Fixed then
  1589.          Set_Msg_Str ("type universal fixed");
  1590.          return;
  1591.       end if;
  1592.  
  1593.       --  If we fall through, it is not a special case, so first output
  1594.       --  the name of the type, preceded by private for a private type
  1595.  
  1596.       if Is_Private_Type (Error_Msg_Node_1) then
  1597.          Set_Msg_Str ("private type ");
  1598.       else
  1599.          Set_Msg_Str ("type ");
  1600.       end if;
  1601.  
  1602.       if Sloc (Error_Msg_Node_1) <= Standard_Location then
  1603.          Set_Msg_Quote;
  1604.          Set_Msg_Str ("Standard.");
  1605.          Set_Msg_Node (Error_Msg_Node_1);
  1606.          Set_Msg_Quote;
  1607.       else
  1608.          Set_Msg_Quote;
  1609.          Set_Msg_Node (Error_Msg_Node_1);
  1610.          Set_Msg_Quote;
  1611.          Set_Msg_Str (" declared");
  1612.          Set_Msg_Insertion_Line_Number (Sloc (Error_Msg_Node_1), Flag);
  1613.       end if;
  1614.  
  1615.    end Set_Msg_Insertion_Type_Reference;
  1616.  
  1617.    ----------------------------
  1618.    -- Set_Msg_Insertion_Uint --
  1619.    ----------------------------
  1620.  
  1621.    procedure Set_Msg_Insertion_Uint is
  1622.    begin
  1623.       Set_Msg_Blank;
  1624.       UI_Image (Error_Msg_Uint_1);
  1625.  
  1626.       for J in 1 .. UI_Image_Length loop
  1627.          Set_Msg_Char (UI_Image_Buffer (J));
  1628.       end loop;
  1629.  
  1630.       --  The following assignment ensures that a second carret insertion
  1631.       --  character will correspond to the Error_Msg_Uint_2 parameter.
  1632.  
  1633.       Error_Msg_Uint_1 := Error_Msg_Uint_2;
  1634.    end Set_Msg_Insertion_Uint;
  1635.  
  1636.    ---------------------------------
  1637.    -- Set_Msg_Insertion_Unit_Name --
  1638.    ---------------------------------
  1639.  
  1640.    procedure Set_Msg_Insertion_Unit_Name is
  1641.    begin
  1642.       if Error_Msg_Unit_1 = No_Name then
  1643.          null;
  1644.  
  1645.       elsif Error_Msg_Unit_1 = Error_Name then
  1646.          Set_Msg_Blank;
  1647.          Set_Msg_Str ("<error>");
  1648.  
  1649.       else
  1650.          Get_Unit_Name_String (Error_Msg_Unit_1);
  1651.          Set_Msg_Blank;
  1652.          Set_Msg_Quote;
  1653.          Set_Msg_Name_Buffer;
  1654.          Set_Msg_Quote;
  1655.       end if;
  1656.  
  1657.       --  The following assignment ensures that a second percent insertion
  1658.       --  character will correspond to the Error_Msg_Unit_2 parameter.
  1659.  
  1660.       Error_Msg_Unit_1 := Error_Msg_Unit_2;
  1661.  
  1662.    end Set_Msg_Insertion_Unit_Name;
  1663.  
  1664.    -----------------
  1665.    -- Set_Msg_Int --
  1666.    -----------------
  1667.  
  1668.    procedure Set_Msg_Int (Line : Int) is
  1669.    begin
  1670.       if Line > 9 then
  1671.          Set_Msg_Int (Line / 10);
  1672.       end if;
  1673.  
  1674.       Set_Msg_Char (Character'Val (Character'Pos ('0') + (Line rem 10)));
  1675.    end Set_Msg_Int;
  1676.  
  1677.    -------------------------
  1678.    -- Set_Msg_Name_Buffer --
  1679.    -------------------------
  1680.  
  1681.    procedure Set_Msg_Name_Buffer is
  1682.    begin
  1683.       for J in 1 .. Name_Len loop
  1684.          Set_Msg_Char (Name_Buffer (J));
  1685.       end loop;
  1686.    end Set_Msg_Name_Buffer;
  1687.  
  1688.    ------------------
  1689.    -- Set_Msg_Node --
  1690.    ------------------
  1691.  
  1692.    procedure Set_Msg_Node (Node : Node_Id) is
  1693.       Ent         : Entity_Id;
  1694.       Old_Ent     : Entity_Id;
  1695.       Mchar       : Character;
  1696.       Derived     : Boolean := False;
  1697.       Class_Flag  : Boolean := False;
  1698.       Nam         : Name_Id;
  1699.  
  1700.       procedure Kill_Type;
  1701.       --  If message buffer ends with " type ", then remove the last five
  1702.       --  characters. This is used to avoid a duplication of "type" in the
  1703.       --  text of the message with "type" generated by the special tests
  1704.       --  below (e.g. we don't want "expected type type derived from ..")
  1705.  
  1706.       procedure Kill_Type is
  1707.       begin
  1708.          if Msg_Len > 4
  1709.            and then Msg_Buffer (Msg_Len - 4 .. Msg_Len) = "type "
  1710.            and then (Msg_Len = 5 or else Msg_Buffer (Msg_Len - 5) = ' ')
  1711.          then
  1712.             Msg_Len := Msg_Len - 5;
  1713.          end if;
  1714.       end Kill_Type;
  1715.  
  1716.    --  Start of processing for Set_Msg_Node
  1717.  
  1718.    begin
  1719.       if Nkind (Node) = N_Designator then
  1720.          Set_Msg_Node (Name (Node));
  1721.          Set_Msg_Char ('.');
  1722.          Set_Msg_Node (Identifier (Node));
  1723.          return;
  1724.  
  1725.       elsif Nkind (Node) = N_Defining_Program_Unit_Name then
  1726.          Set_Msg_Node (Name (Node));
  1727.          Set_Msg_Char ('.');
  1728.          Set_Msg_Node (Defining_Identifier (Node));
  1729.          return;
  1730.  
  1731.       elsif Nkind (Node) = N_Selected_Component then
  1732.          Set_Msg_Node (Prefix (Node));
  1733.          Set_Msg_Char ('.');
  1734.          Set_Msg_Node (Selector_Name (Node));
  1735.          return;
  1736.       end if;
  1737.  
  1738.       --  The only remaining possibilities are identifiers, defining
  1739.       --  identifiers and pragmas, i.e. nodes that have a Chars field.
  1740.       --  Why is this true ???
  1741.  
  1742.       --  Internal names generally represent something gone wrong. An exception
  1743.       --  is the case of internal type names, where we try to find a reasonable
  1744.       --  external representation for the external name
  1745.  
  1746.       if Is_Internal_Name (Chars (Node))
  1747.         and then
  1748.           ((Is_Entity_Name (Node) and then Is_Type (Entity (Node)))
  1749.               or else
  1750.            (Nkind (Node) = N_Defining_Identifier and then Is_Type (Node)))
  1751.       then
  1752.          if Nkind (Node) = N_Identifier then
  1753.             Ent := Entity (Node);
  1754.          else
  1755.             Ent := Node;
  1756.          end if;
  1757.  
  1758.          --  Undo placement of a quote, since we will put it back later
  1759.  
  1760.          Mchar := Msg_Buffer (Msg_Len);
  1761.  
  1762.          if Mchar = '"' then
  1763.             Msg_Len := Msg_Len - 1;
  1764.          end if;
  1765.  
  1766.          --  The loop here deals with recursive types, we are trying to
  1767.          --  find a related entity that is not an implicit type. Note
  1768.          --  that the check with Old_Ent stops us from getting "stuck".
  1769.          --  Also, we don't output the "type derived from" message more
  1770.          --  than once in the case where we climb up multiple levels.
  1771.  
  1772.          loop
  1773.             Old_Ent := Ent;
  1774.  
  1775.             --  Implicit access type, use directly designated type
  1776.  
  1777.             if Is_Access_Type (Ent) then
  1778.                Set_Msg_Str ("access to ");
  1779.                Ent := Directly_Designated_Type (Ent);
  1780.  
  1781.             --  Classwide type
  1782.  
  1783.             elsif Is_Class_Wide_Type (Ent) then
  1784.                Class_Flag := True;
  1785.                Ent := Root_Type (Ent);
  1786.  
  1787.             --  Use base type if this is a subtype
  1788.  
  1789.             elsif Ent /= Base_Type (Ent) then
  1790.                Kill_Type;
  1791.                Set_Msg_Str ("subtype of ");
  1792.                Ent := Base_Type (Ent);
  1793.  
  1794.             --  If this is a base type with a first named subtype, use the
  1795.             --  first named subtype instead. This is not quite accurate in
  1796.             --  all cases, but it makes too much noise to be accurate and
  1797.             --  add 'Base in all cases. Note that we only do this is the
  1798.             --  first named subtype is not itself an internal name. This
  1799.             --  avoids the obvious loop (subtype->basetype->subtype) which
  1800.             --  would otherwise occur!)
  1801.  
  1802.             elsif Present (Freeze_Node (Ent))
  1803.               and then Present (First_Subtype_Link (Freeze_Node (Ent)))
  1804.               and then
  1805.                 not Is_Internal_Name
  1806.                       (Chars (First_Subtype_Link (Freeze_Node (Ent))))
  1807.             then
  1808.                Ent := First_Subtype_Link (Freeze_Node (Ent));
  1809.  
  1810.             --  Otherwise use root type
  1811.  
  1812.             else
  1813.                if not Derived then
  1814.                   Kill_Type;
  1815.                   Set_Msg_Str ("type derived from ");
  1816.                   Derived := True;
  1817.                end if;
  1818.  
  1819.                Ent := Etype (Ent);
  1820.             end if;
  1821.  
  1822.             --  If we are stuck in a loop, get out and settle for the
  1823.             --  internal name after all.
  1824.  
  1825.             exit when Ent = Old_Ent;
  1826.  
  1827.             --  Get out if we finally found a non-internal name to use
  1828.  
  1829.             exit when not Is_Internal_Name (Chars (Ent));
  1830.          end loop;
  1831.  
  1832.          if Mchar = '"' then
  1833.             Set_Msg_Char ('"');
  1834.          end if;
  1835.  
  1836.          Nam := Chars (Ent);
  1837.  
  1838.       --  For any other internal names, we settle for using the name
  1839.  
  1840.       else
  1841.          Nam := Chars (Node);
  1842.       end if;
  1843.  
  1844.       --  If we still have an internal name, then set to kill the message
  1845.       --  if it is not the first message (we really try hard not to show
  1846.       --  the dirty laundry of the implementation to the compiler user!)
  1847.  
  1848.       if Is_Internal_Name (Nam) then
  1849.          Kill_Message := True;
  1850.       end if;
  1851.  
  1852.       --  At this stage, the name to output is in Nam
  1853.  
  1854.       Get_Decoded_Name_String (Nam);
  1855.  
  1856.       --  Now we have to set the proper case. If we have a source location
  1857.       --  then do a check to see if the name in the source is the same name
  1858.       --  as the name in the Names table, except for possible differences
  1859.       --  in case, which is the case when we can copy from the source.
  1860.  
  1861.       declare
  1862.          Src_Loc : constant Source_Ptr := Sloc (Error_Msg_Node_1);
  1863.          Sbuffer : Source_Buffer_Ptr;
  1864.          Ref_Ptr : Integer;
  1865.          Src_Ptr : Source_Ptr;
  1866.  
  1867.       begin
  1868.          Ref_Ptr := 1;
  1869.          Src_Ptr := Src_Loc;
  1870.  
  1871.          --  Determine if the reference we are dealing with corresponds
  1872.          --  to text at the point of the error reference. This will often
  1873.          --  be the case for simple identifier references, and is the case
  1874.          --  where we can copy the spelling from the source.
  1875.  
  1876.          if Src_Loc /= No_Location
  1877.            and then Src_Loc > Standard_Location
  1878.          then
  1879.             Sbuffer := Source_Text (Get_Source_File_Index (Src_Loc));
  1880.  
  1881.             while Ref_Ptr <= Name_Len loop
  1882.                exit when
  1883.                  Fold_Lower (Sbuffer (Src_Ptr)) /=
  1884.                  Fold_Lower (Name_Buffer (Ref_Ptr));
  1885.                Ref_Ptr := Ref_Ptr + 1;
  1886.                Src_Ptr := Src_Ptr + 1;
  1887.             end loop;
  1888.          end if;
  1889.  
  1890.          --  If we get through the loop without a mismatch, then output
  1891.          --  the name the way it is spelled in the source program
  1892.  
  1893.          if Ref_Ptr > Name_Len then
  1894.             Src_Ptr := Src_Loc;
  1895.  
  1896.             for J in 1 .. Name_Len loop
  1897.                Name_Buffer (J) := Sbuffer (Src_Ptr);
  1898.                Src_Ptr := Src_Ptr + 1;
  1899.             end loop;
  1900.  
  1901.          --  Otherwise set the casing using the default identifier casing
  1902.  
  1903.          else
  1904.             Set_Casing (Identifier_Casing (Flag_Source), Mixed_Case);
  1905.          end if;
  1906.       end;
  1907.  
  1908.       Set_Msg_Name_Buffer;
  1909.  
  1910.       --  Add 'Class if class wide type
  1911.  
  1912.       if Class_Flag then
  1913.          Set_Msg_Char (''');
  1914.          Get_Name_String (Name_Class);
  1915.          Set_Casing (Identifier_Casing (Flag_Source), Mixed_Case);
  1916.          Set_Msg_Name_Buffer;
  1917.       end if;
  1918.    end Set_Msg_Node;
  1919.  
  1920.    -------------------
  1921.    -- Set_Msg_Quote --
  1922.    -------------------
  1923.  
  1924.    procedure Set_Msg_Quote is
  1925.    begin
  1926.       if not Manual_Quote_Mode then
  1927.          Set_Msg_Char ('"');
  1928.       end if;
  1929.    end Set_Msg_Quote;
  1930.  
  1931.    -----------------
  1932.    -- Set_Msg_Str --
  1933.    -----------------
  1934.  
  1935.    procedure Set_Msg_Str (Text : String) is
  1936.    begin
  1937.       for J in Text'Range loop
  1938.          Set_Msg_Char (Text (J));
  1939.       end loop;
  1940.    end Set_Msg_Str;
  1941.  
  1942.    ------------------
  1943.    -- Set_Msg_Text --
  1944.    ------------------
  1945.  
  1946.    procedure Set_Msg_Text (Text : String; Flag : Source_Ptr) is
  1947.       C : Character;         -- Current character
  1948.       I : Natural;           -- Current index;
  1949.  
  1950.    begin
  1951.       Manual_Quote_Mode := False;
  1952.       Is_Warning_Msg := False;
  1953.       Is_Unconditional_Msg := False;
  1954.       Msg_Len := 0;
  1955.       Flag_Source := Get_Source_File_Index (Flag);
  1956.       I := Text'First;
  1957.  
  1958.       while I <= Text'Last loop
  1959.          C := Text (I);
  1960.          I := I + 1;
  1961.  
  1962.          --  Check for insertion character
  1963.  
  1964.          if C = '%' then
  1965.             Set_Msg_Insertion_Name;
  1966.  
  1967.          elsif C = '$' then
  1968.             Set_Msg_Insertion_Unit_Name;
  1969.  
  1970.          elsif C = '{' then
  1971.             Set_Msg_Insertion_File_Name;
  1972.  
  1973.          elsif C = '}' then
  1974.             Set_Msg_Insertion_Type_Reference (Flag);
  1975.  
  1976.          elsif C = '*' then
  1977.             Set_Msg_Insertion_Reserved_Name;
  1978.  
  1979.          elsif C = '&' then
  1980.             Set_Msg_Insertion_Node;
  1981.  
  1982.          elsif C = '#' then
  1983.             Set_Msg_Insertion_Line_Number (Error_Msg_Sloc, Flag);
  1984.  
  1985.          elsif C = '@' then
  1986.             Set_Msg_Insertion_Column;
  1987.  
  1988.          elsif C = '^' then
  1989.             Set_Msg_Insertion_Uint;
  1990.  
  1991.          elsif C = '`' then
  1992.             Manual_Quote_Mode := not Manual_Quote_Mode;
  1993.             Set_Msg_Char ('"');
  1994.  
  1995.          elsif C = '!' then
  1996.             Is_Unconditional_Msg := True;
  1997.  
  1998.          elsif C = '?' then
  1999.             Is_Warning_Msg := True;
  2000.  
  2001.          elsif C = ''' then
  2002.             Set_Msg_Char (Text (I));
  2003.             I := I + 1;
  2004.  
  2005.          --  Upper case letter (start of reserved word if 2 or more)
  2006.  
  2007.          elsif C in 'A' .. 'Z'
  2008.            and then I <= Text'Last
  2009.            and then Text (I) in 'A' .. 'Z'
  2010.          then
  2011.             I := I - 1;
  2012.             Set_Msg_Insertion_Reserved_Word (Text, I);
  2013.  
  2014.          --  Normal character with no special treatment
  2015.  
  2016.          else
  2017.             Set_Msg_Char (C);
  2018.          end if;
  2019.  
  2020.       end loop;
  2021.    end Set_Msg_Text;
  2022.  
  2023.    ---------------------
  2024.    -- Temporary_Msg_N --
  2025.    ---------------------
  2026.  
  2027.    procedure Temporary_Msg_N (Msg : String; N : Node_Id) renames Error_Msg_N;
  2028.  
  2029. end Errout;
  2030.