New Language: Ada
authorkenner <kenner@138bc75d-0d04-0410-961f-82ee72b054a4>
Tue, 2 Oct 2001 14:23:52 +0000 (14:23 +0000)
committerkenner <kenner@138bc75d-0d04-0410-961f-82ee72b054a4>
Tue, 2 Oct 2001 14:23:52 +0000 (14:23 +0000)
git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@45956 138bc75d-0d04-0410-961f-82ee72b054a4

57 files changed:
gcc/ada/par-ch10.adb [new file with mode: 0644]
gcc/ada/par-ch11.adb [new file with mode: 0644]
gcc/ada/par-ch12.adb [new file with mode: 0644]
gcc/ada/par-ch13.adb [new file with mode: 0644]
gcc/ada/par-ch2.adb [new file with mode: 0644]
gcc/ada/par-ch3.adb [new file with mode: 0644]
gcc/ada/par-ch4.adb [new file with mode: 0644]
gcc/ada/par-ch5.adb [new file with mode: 0644]
gcc/ada/par-ch6.adb [new file with mode: 0644]
gcc/ada/par-ch7.adb [new file with mode: 0644]
gcc/ada/par-ch8.adb [new file with mode: 0644]
gcc/ada/par-ch9.adb [new file with mode: 0644]
gcc/ada/par-endh.adb [new file with mode: 0644]
gcc/ada/par-labl.adb [new file with mode: 0644]
gcc/ada/par-load.adb [new file with mode: 0644]
gcc/ada/par-prag.adb [new file with mode: 0644]
gcc/ada/par-sync.adb [new file with mode: 0644]
gcc/ada/par-tchk.adb [new file with mode: 0644]
gcc/ada/par-util.adb [new file with mode: 0644]
gcc/ada/par.adb [new file with mode: 0644]
gcc/ada/par.ads [new file with mode: 0644]
gcc/ada/prj-attr.adb [new file with mode: 0644]
gcc/ada/prj-attr.ads [new file with mode: 0644]
gcc/ada/prj-com.adb [new file with mode: 0644]
gcc/ada/prj-com.ads [new file with mode: 0644]
gcc/ada/prj-dect.adb [new file with mode: 0644]
gcc/ada/prj-dect.ads [new file with mode: 0644]
gcc/ada/prj-env.adb [new file with mode: 0644]
gcc/ada/prj-env.ads [new file with mode: 0644]
gcc/ada/prj-ext.adb [new file with mode: 0644]
gcc/ada/prj-ext.ads [new file with mode: 0644]
gcc/ada/prj-nmsc.adb [new file with mode: 0644]
gcc/ada/prj-nmsc.ads [new file with mode: 0644]
gcc/ada/prj-pars.adb [new file with mode: 0644]
gcc/ada/prj-pars.ads [new file with mode: 0644]
gcc/ada/prj-part.adb [new file with mode: 0644]
gcc/ada/prj-part.ads [new file with mode: 0644]
gcc/ada/prj-proc.adb [new file with mode: 0644]
gcc/ada/prj-proc.ads [new file with mode: 0644]
gcc/ada/prj-strt.adb [new file with mode: 0644]
gcc/ada/prj-strt.ads [new file with mode: 0644]
gcc/ada/prj-tree.adb [new file with mode: 0644]
gcc/ada/prj-tree.ads [new file with mode: 0644]
gcc/ada/prj-util.adb [new file with mode: 0644]
gcc/ada/prj-util.ads [new file with mode: 0644]
gcc/ada/prj.adb [new file with mode: 0644]
gcc/ada/prj.ads [new file with mode: 0644]
gcc/ada/raise.c [new file with mode: 0644]
gcc/ada/raise.h [new file with mode: 0644]
gcc/ada/repinfo.adb [new file with mode: 0644]
gcc/ada/repinfo.ads [new file with mode: 0644]
gcc/ada/repinfo.h [new file with mode: 0644]
gcc/ada/restrict.adb [new file with mode: 0644]
gcc/ada/restrict.ads [new file with mode: 0644]
gcc/ada/rident.ads [new file with mode: 0644]
gcc/ada/rtsfind.adb [new file with mode: 0644]
gcc/ada/rtsfind.ads [new file with mode: 0644]

diff --git a/gcc/ada/par-ch10.adb b/gcc/ada/par-ch10.adb
new file mode 100644 (file)
index 0000000..a4fa121
--- /dev/null
@@ -0,0 +1,1080 @@
+------------------------------------------------------------------------------
+--                                                                          --
+--                         GNAT COMPILER COMPONENTS                         --
+--                                                                          --
+--                             P A R . C H 1 0                              --
+--                                                                          --
+--                                 B o d y                                  --
+--                                                                          --
+--                            $Revision: 1.115 $
+--                                                                          --
+--          Copyright (C) 1992-2001 Free Software Foundation, Inc.          --
+--                                                                          --
+-- GNAT is free software;  you can  redistribute it  and/or modify it under --
+-- terms of the  GNU General Public License as published  by the Free Soft- --
+-- ware  Foundation;  either version 2,  or (at your option) any later ver- --
+-- sion.  GNAT is distributed in the hope that it will be useful, but WITH- --
+-- OUT 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  distributed with GNAT;  see file COPYING.  If not, write --
+-- to  the Free Software Foundation,  59 Temple Place - Suite 330,  Boston, --
+-- MA 02111-1307, USA.                                                      --
+--                                                                          --
+-- GNAT was originally developed  by the GNAT team at  New York University. --
+-- It is now maintained by Ada Core Technologies Inc (http://www.gnat.com). --
+--                                                                          --
+------------------------------------------------------------------------------
+
+pragma Style_Checks (All_Checks);
+--  Turn off subprogram body ordering check. Subprograms are in order
+--  by RM section rather than alphabetical
+
+with Fname;    use Fname;
+with Fname.UF; use Fname.UF;
+with Hostparm; use Hostparm;
+with Uname;    use Uname;
+
+separate (Par)
+package body Ch10 is
+
+   --  Local functions, used only in this chapter
+
+   function P_Context_Clause    return List_Id;
+   function P_Subunit           return Node_Id;
+
+   function Set_Location return Source_Ptr;
+   --  The current compilation unit starts with Token at Token_Ptr. This
+   --  function determines the corresponding source location for the start
+   --  of the unit, including any preceding comment lines.
+
+   procedure Unit_Display
+     (Cunit      : Node_Id;
+      Loc        : Source_Ptr;
+      SR_Present : Boolean);
+   --  This procedure is used to generate a line of output for the a unit in
+   --  the source program. Cunit is the node for the compilation unit, and
+   --  Loc is the source location for the start of the unit in the source
+   --  file (which is not necessarily the Sloc of the Cunit node). This
+   --  output is written to the standard output file for use by gnatchop.
+
+   procedure Unit_Location (Sind : Source_File_Index; Loc : Source_Ptr);
+   --  This routine has the same calling sequence as Unit_Display, but
+   --  it outputs only the line number and offset of the location, Loc,
+   --  using Cunit to obtain the proper source file index.
+
+   -------------------------
+   -- 10.1.1  Compilation --
+   -------------------------
+
+   --  COMPILATION ::= {COMPILATION_UNIT}
+
+   --  There is no specific parsing routine for a compilation, since we only
+   --  permit a single compilation in a source file, so there is no explicit
+   --  occurrence of compilations as such (our representation of a compilation
+   --  is a series of separate source files).
+
+   ------------------------------
+   -- 10.1.1  Compilation unit --
+   ------------------------------
+
+   --  COMPILATION_UNIT ::=
+   --    CONTEXT_CLAUSE LIBRARY_ITEM
+   --  | CONTEXT_CLAUSE SUBUNIT
+
+   --  LIBRARY_ITEM ::=
+   --    private LIBRARY_UNIT_DECLARATION
+   --  | LIBRARY_UNIT_BODY
+   --  | [private] LIBRARY_UNIT_RENAMING_DECLARATION
+
+   --  LIBRARY_UNIT_DECLARATION ::=
+   --    SUBPROGRAM_DECLARATION | PACKAGE_DECLARATION
+   --  | GENERIC_DECLARATION    | GENERIC_INSTANTIATION
+
+   --  LIBRARY_UNIT_RENAMING_DECLARATION ::=
+   --    PACKAGE_RENAMING_DECLARATION
+   --  | GENERIC_RENAMING_DECLARATION
+   --  | SUBPROGRAM_RENAMING_DECLARATION
+
+   --  LIBRARY_UNIT_BODY ::= SUBPROGRAM_BODY | PACKAGE_BODY
+
+   --  Error recovery: cannot raise Error_Resync. If an error occurs, tokens
+   --  are skipped up to the next possible beginning of a compilation unit.
+
+   --  Note: if only configuration pragmas are found, Empty is returned
+
+   --  Note: in syntax-only mode, it is possible for P_Compilation_Unit
+   --  to return strange things that are not really compilation units.
+   --  This is done to help out gnatchop when it is faced with nonsense.
+
+   function P_Compilation_Unit return Node_Id is
+      Scan_State         : Saved_Scan_State;
+      Body_Node          : Node_Id;
+      Specification_Node : Node_Id;
+      Unit_Node          : Node_Id;
+      Comp_Unit_Node     : Node_Id;
+      Name_Node          : Node_Id;
+      Item               : Node_Id;
+      Private_Sloc       : Source_Ptr := No_Location;
+      Config_Pragmas     : List_Id;
+      P                  : Node_Id;
+      SR_Present         : Boolean;
+
+      Cunit_Error_Flag   : Boolean := False;
+      --  This flag is set True if we have to scan for a compilation unit
+      --  token. It is used to ensure clean termination in such cases by
+      --  not insisting on being at the end of file, and, in the sytax only
+      --  case by not scanning for additional compilation units.
+
+      Cunit_Location : Source_Ptr;
+      --  Location of unit for unit identification output (List_Unit option)
+
+   begin
+      Num_Library_Units := Num_Library_Units + 1;
+
+      --  Set location of the compilation unit if unit list option set
+      --  and we are in syntax check only mode
+
+      if List_Units and then Operating_Mode = Check_Syntax then
+         Cunit_Location := Set_Location;
+      else
+         Cunit_Location := No_Location;
+      end if;
+
+      --  Deal with initial pragmas
+
+      Config_Pragmas := No_List;
+
+      --  If we have an initial Source_Reference pragma, then remember
+      --  the fact to generate an NR parameter in the output line.
+
+      SR_Present := False;
+
+      if Token = Tok_Pragma then
+         Save_Scan_State (Scan_State);
+         Item := P_Pragma;
+
+         if Item = Error
+           or else Chars (Item) /= Name_Source_Reference
+         then
+            Restore_Scan_State (Scan_State);
+
+         else
+            SR_Present := True;
+
+            --  If first unit, record the file name for gnatchop use
+
+            if Operating_Mode = Check_Syntax
+              and then List_Units
+              and then Num_Library_Units = 1
+            then
+               Write_Str ("Source_Reference pragma for file """);
+               Write_Name (Full_Ref_Name (Current_Source_File));
+               Write_Char ('"');
+               Write_Eol;
+            end if;
+
+            Config_Pragmas := New_List (Item);
+         end if;
+      end if;
+
+      --  Scan out any configuration pragmas
+
+      while Token = Tok_Pragma loop
+         Save_Scan_State (Scan_State);
+         Item := P_Pragma;
+
+         if Item = Error
+           or else Chars (Item) > Last_Configuration_Pragma_Name
+         then
+            Restore_Scan_State (Scan_State);
+            exit;
+         end if;
+
+         if Config_Pragmas = No_List then
+            Config_Pragmas := Empty_List;
+
+            if Operating_Mode = Check_Syntax and then List_Units then
+               Write_Str ("Configuration pragmas at");
+               Unit_Location (Current_Source_File, Cunit_Location);
+               Write_Eol;
+            end if;
+         end if;
+
+         Append (Item, Config_Pragmas);
+         Cunit_Location := Set_Location;
+      end loop;
+
+      --  Establish compilation unit node and scan context items
+
+      Comp_Unit_Node := New_Node (N_Compilation_Unit, No_Location);
+      Set_Cunit (Current_Source_Unit, Comp_Unit_Node);
+      Set_Context_Items (Comp_Unit_Node, P_Context_Clause);
+      Set_Aux_Decls_Node
+        (Comp_Unit_Node, New_Node (N_Compilation_Unit_Aux, No_Location));
+
+      if Present (Config_Pragmas) then
+
+         --  Check for case of only configuration pragmas present
+
+         if Token = Tok_EOF
+           and then Is_Empty_List (Context_Items (Comp_Unit_Node))
+         then
+            if Operating_Mode = Check_Syntax then
+               return Empty;
+
+            else
+               Item := First (Config_Pragmas);
+               Error_Msg_N
+                 ("cannot compile configuration pragmas with gcc", Item);
+               Error_Msg_N
+                 ("use gnatchop -c to process configuration pragmas!", Item);
+               raise Unrecoverable_Error;
+            end if;
+
+         --  Otherwise configuration pragmas are simply prepended to the
+         --  context of the current unit.
+
+         else
+            Append_List (Context_Items (Comp_Unit_Node), Config_Pragmas);
+            Set_Context_Items (Comp_Unit_Node, Config_Pragmas);
+         end if;
+      end if;
+
+      --  Check for PRIVATE. Note that for the moment we allow this in
+      --  Ada_83 mode, since we do not yet know if we are compiling a
+      --  predefined unit, and if we are then it would be allowed anyway.
+
+      if Token = Tok_Private then
+         Private_Sloc := Token_Ptr;
+         Set_Keyword_Casing (Current_Source_File, Determine_Token_Casing);
+         if Style_Check then Style.Check_Indentation; end if;
+
+         Save_Scan_State (Scan_State); -- at PRIVATE
+         Scan; -- past PRIVATE
+
+         if Token = Tok_Separate then
+            Error_Msg_SP ("cannot have private subunits!");
+
+         elsif Token = Tok_Package then
+            Scan; -- past PACKAGE
+
+            if Token = Tok_Body then
+               Restore_Scan_State (Scan_State); -- to PRIVATE
+               Error_Msg_SC ("cannot have private package body!");
+               Scan; -- ignore PRIVATE
+
+            else
+               Restore_Scan_State (Scan_State); -- to PRIVATE
+               Scan; -- past PRIVATE
+               Set_Private_Present (Comp_Unit_Node, True);
+            end if;
+
+         elsif Token = Tok_Procedure
+           or else Token = Tok_Function
+           or else Token = Tok_Generic
+         then
+            Set_Private_Present (Comp_Unit_Node, True);
+         end if;
+      end if;
+
+      --  Loop to find our way to a compilation unit token
+
+      loop
+         exit when Token in Token_Class_Cunit and then Token /= Tok_With;
+
+         exit when Bad_Spelling_Of (Tok_Package)
+           or else Bad_Spelling_Of (Tok_Function)
+           or else Bad_Spelling_Of (Tok_Generic)
+           or else Bad_Spelling_Of (Tok_Separate)
+           or else Bad_Spelling_Of (Tok_Procedure);
+
+         --  Allow task and protected for nice error recovery purposes
+
+         exit when Token = Tok_Task
+           or else Token = Tok_Protected;
+
+         if Token = Tok_With then
+            Error_Msg_SC ("misplaced WITH");
+            Append_List (P_Context_Clause, Context_Items (Comp_Unit_Node));
+
+         elsif Bad_Spelling_Of (Tok_With) then
+            Append_List (P_Context_Clause, Context_Items (Comp_Unit_Node));
+
+         else
+            Error_Msg_SC ("compilation unit expected");
+            Cunit_Error_Flag := True;
+            Resync_Cunit;
+
+            --  If we are at an end of file, then just quit, the above error
+            --  message was complaint enough.
+
+            if Token = Tok_EOF then
+               return Error;
+            end if;
+         end if;
+      end loop;
+
+      --  We have a compilation unit token, so that's a reasonable choice for
+      --  determining the standard casing convention used for keywords in case
+      --  it hasn't already been done on seeing a WITH or PRIVATE.
+
+      Set_Keyword_Casing (Current_Source_File, Determine_Token_Casing);
+      if Style_Check then Style.Check_Indentation; end if;
+
+      --  Remaining processing depends on particular type of compilation unit
+
+      if Token = Tok_Package then
+
+         --  A common error is to omit the body keyword after package. We can
+         --  often diagnose this early on (before getting loads of errors from
+         --  contained subprogram bodies), by knowing that that the file we
+         --  are compiling has a name that requires a body to be found.
+
+         --  However, we do not do this check if we are operating in syntax
+         --  checking only mode, because in that case there may be multiple
+         --  units in the same file, and the file name is not a reliable guide.
+
+         Save_Scan_State (Scan_State);
+         Scan; -- past Package keyword
+
+         if Token /= Tok_Body
+           and then Operating_Mode /= Check_Syntax
+           and then
+             Get_Expected_Unit_Type
+               (File_Name (Current_Source_File)) = Expect_Body
+         then
+            Error_Msg_BC ("keyword BODY expected here [see file name]");
+            Restore_Scan_State (Scan_State);
+            Set_Unit (Comp_Unit_Node, P_Package (Pf_Pbod));
+         else
+            Restore_Scan_State (Scan_State);
+            Set_Unit (Comp_Unit_Node, P_Package (Pf_Decl_Gins_Pbod_Rnam));
+         end if;
+
+      elsif Token = Tok_Generic then
+         Set_Unit (Comp_Unit_Node, P_Generic);
+
+      elsif Token = Tok_Separate then
+         Set_Unit (Comp_Unit_Node, P_Subunit);
+
+      elsif Token = Tok_Procedure
+        or else Token = Tok_Function
+      then
+         Set_Unit (Comp_Unit_Node, P_Subprogram (Pf_Decl_Gins_Pbod_Rnam));
+
+         --  A little bit of an error recovery check here. If we just scanned
+         --  a subprogram declaration (as indicated by an SIS entry being
+         --  active), then if the following token is BEGIN or an identifier,
+         --  or a token which can reasonably start a declaration but cannot
+         --  start a compilation unit, then we assume that the semicolon in
+         --  the declaration should have been IS.
+
+         if SIS_Entry_Active then
+
+            if Token = Tok_Begin
+               or else Token = Tok_Identifier
+               or else Token in Token_Class_Deckn
+            then
+               Push_Scope_Stack;
+               Scope.Table (Scope.Last).Etyp := E_Name;
+               Scope.Table (Scope.Last).Sloc := SIS_Sloc;
+               Scope.Table (Scope.Last).Ecol := SIS_Ecol;
+               Scope.Table (Scope.Last).Lreq := False;
+               SIS_Entry_Active := False;
+
+               --  If we had a missing semicolon in the declaration, then
+               --  change the message to from <missing ";"> to <missing "is">
+
+               if SIS_Missing_Semicolon_Message /= No_Error_Msg then
+                  Change_Error_Text     -- Replace: "missing "";"" "
+                    (SIS_Missing_Semicolon_Message, "missing IS");
+
+               --  Otherwise we saved the semicolon position, so complain
+
+               else
+                  Error_Msg (""";"" should be IS", SIS_Semicolon_Sloc);
+               end if;
+
+               Body_Node := Unit (Comp_Unit_Node);
+               Specification_Node := Specification (Body_Node);
+               Change_Node (Body_Node, N_Subprogram_Body);
+               Set_Specification (Body_Node, Specification_Node);
+               Parse_Decls_Begin_End (Body_Node);
+               Set_Unit (Comp_Unit_Node, Body_Node);
+            end if;
+
+         --  If we scanned a subprogram body, make sure we did not have private
+
+         elsif Private_Sloc /= No_Location
+           and then Nkind (Unit (Comp_Unit_Node)) /= N_Function_Instantiation
+           and then Nkind (Unit (Comp_Unit_Node)) /= N_Procedure_Instantiation
+         then
+            Error_Msg ("cannot have private subprogram body", Private_Sloc);
+
+         --  P_Subprogram can yield an abstract subprogram, but this cannot
+         --  be a compilation unit. Treat as a subprogram declaration.
+
+         elsif
+           Nkind (Unit (Comp_Unit_Node)) = N_Abstract_Subprogram_Declaration
+         then
+            Error_Msg_N
+              ("compilation unit cannot be abstract subprogram",
+                 Unit (Comp_Unit_Node));
+
+            Unit_Node :=
+              New_Node (N_Subprogram_Declaration, Sloc (Comp_Unit_Node));
+            Set_Specification (Unit_Node,
+              Specification (Unit (Comp_Unit_Node)));
+            Set_Unit (Comp_Unit_Node, Unit_Node);
+         end if;
+
+      --  Otherwise we have TASK. This is not really an acceptable token,
+      --  but we accept it to improve error recovery.
+
+      elsif Token = Tok_Task then
+         Scan; -- Past TASK
+
+         if Token = Tok_Type then
+            Error_Msg_SP
+              ("task type cannot be used as compilation unit");
+         else
+            Error_Msg_SP
+              ("task declaration cannot be used as compilation unit");
+         end if;
+
+         --  If in check syntax mode, accept the task anyway. This is done
+         --  particularly to improve the behavior of GNATCHOP in this case.
+
+         if Operating_Mode = Check_Syntax then
+            Set_Unit (Comp_Unit_Node, P_Task);
+
+         --  If not in syntax only mode, treat this as horrible error
+
+         else
+            Cunit_Error_Flag := True;
+            return Error;
+         end if;
+
+      else pragma Assert (Token = Tok_Protected);
+         Scan; -- Past PROTECTED
+
+         if Token = Tok_Type then
+            Error_Msg_SP
+              ("protected type cannot be used as compilation unit");
+         else
+            Error_Msg_SP
+              ("protected declaration cannot be used as compilation unit");
+         end if;
+
+         --  If in check syntax mode, accept protected anyway. This is done
+         --  particularly to improve the behavior of GNATCHOP in this case.
+
+         if Operating_Mode = Check_Syntax then
+            Set_Unit (Comp_Unit_Node, P_Protected);
+
+         --  If not in syntax only mode, treat this as horrible error
+
+         else
+            Cunit_Error_Flag := True;
+            return Error;
+         end if;
+      end if;
+
+      --  Here is where locate the compilation unit entity. This is a little
+      --  tricky, since it is buried in various places.
+
+      Unit_Node := Unit (Comp_Unit_Node);
+
+      --  Another error from which it is hard to recover
+
+      if Nkind (Unit_Node) = N_Subprogram_Body_Stub
+        or else Nkind (Unit_Node) = N_Package_Body_Stub
+      then
+         Cunit_Error_Flag := True;
+         return Error;
+      end if;
+
+      --  Only try this if we got an OK unit!
+
+      if Unit_Node /= Error then
+         if Nkind (Unit_Node) = N_Subunit then
+            Unit_Node := Proper_Body (Unit_Node);
+         end if;
+
+         if Nkind (Unit_Node) in N_Generic_Declaration then
+            Unit_Node := Specification (Unit_Node);
+         end if;
+
+         if Nkind (Unit_Node) = N_Package_Declaration
+           or else Nkind (Unit_Node) = N_Subprogram_Declaration
+           or else Nkind (Unit_Node) = N_Subprogram_Body
+           or else Nkind (Unit_Node) = N_Subprogram_Renaming_Declaration
+         then
+            Unit_Node := Specification (Unit_Node);
+
+         elsif Nkind (Unit_Node) = N_Subprogram_Renaming_Declaration then
+            if Ada_83 then
+               Error_Msg_N
+                 ("(Ada 83) library unit renaming not allowed", Unit_Node);
+            end if;
+         end if;
+
+         if Nkind (Unit_Node) = N_Task_Body
+           or else Nkind (Unit_Node) = N_Protected_Body
+           or else Nkind (Unit_Node) = N_Task_Type_Declaration
+           or else Nkind (Unit_Node) = N_Protected_Type_Declaration
+           or else Nkind (Unit_Node) = N_Single_Task_Declaration
+           or else Nkind (Unit_Node) = N_Single_Protected_Declaration
+         then
+            Name_Node := Defining_Identifier (Unit_Node);
+         else
+            Name_Node := Defining_Unit_Name (Unit_Node);
+         end if;
+
+         Set_Sloc (Comp_Unit_Node, Sloc (Name_Node));
+         Set_Sloc (Aux_Decls_Node (Comp_Unit_Node), Sloc (Name_Node));
+
+         --  Set Entity field in file table. Easier now that we have name!
+         --  Note that this is also skipped if we had a bad unit
+
+         if Nkind (Name_Node) = N_Defining_Program_Unit_Name then
+            Set_Cunit_Entity
+              (Current_Source_Unit, Defining_Identifier (Name_Node));
+         else
+            Set_Cunit_Entity (Current_Source_Unit, Name_Node);
+         end if;
+
+         Set_Unit_Name
+           (Current_Source_Unit, Get_Unit_Name (Unit (Comp_Unit_Node)));
+
+      --  If we had a bad unit, make sure the fatal flag is set in the file
+      --  table entry, since this is surely a fatal error and also set our
+      --  flag to inhibit the requirement that we be at end of file.
+
+      else
+         Cunit_Error_Flag := True;
+         Set_Fatal_Error (Current_Source_Unit);
+      end if;
+
+      --  Clear away any missing semicolon indication, we are done with that
+      --  unit, so what's done is done, and we don't want anything hanging
+      --  around from the attempt to parse it!
+
+      SIS_Entry_Active := False;
+
+      --  Scan out pragmas after unit
+
+      while Token = Tok_Pragma loop
+         Save_Scan_State (Scan_State);
+
+         --  If we are in syntax scan mode allowing multiple units, then
+         --  start the next unit if we encounter a configuration pragma,
+         --  or a source reference pragma. We take care not to actually
+         --  scan the pragma in this case since we don't want it to take
+         --  effect for the current unit.
+
+         if Operating_Mode = Check_Syntax then
+            Scan;  -- past Pragma
+
+            if Token = Tok_Identifier
+              and then
+                (Token_Name in
+                         First_Pragma_Name .. Last_Configuration_Pragma_Name
+                   or else Token_Name = Name_Source_Reference)
+            then
+               Restore_Scan_State (Scan_State); -- to Pragma
+               exit;
+            end if;
+         end if;
+
+         --  Otherwise eat the pragma, it definitely belongs with the
+         --  current unit, and not with the following unit.
+
+         Restore_Scan_State (Scan_State); -- to Pragma
+         P := P_Pragma;
+
+         if No (Pragmas_After (Aux_Decls_Node (Comp_Unit_Node))) then
+            Set_Pragmas_After
+              (Aux_Decls_Node (Comp_Unit_Node), New_List);
+         end if;
+
+         Append (P, Pragmas_After (Aux_Decls_Node (Comp_Unit_Node)));
+      end loop;
+
+      --  Cancel effect of any outstanding pragma Warnings (Off)
+
+      Set_Warnings_Mode_On (Scan_Ptr);
+
+      --  Ada 83 error checks
+
+      if Ada_83 then
+
+         --  Check we did not with any child units
+
+         Item := First (Context_Items (Comp_Unit_Node));
+
+         while Present (Item) loop
+            if Nkind (Item) = N_With_Clause
+              and then Nkind (Name (Item)) /= N_Identifier
+            then
+               Error_Msg_N ("(Ada 83) child units not allowed", Item);
+            end if;
+
+            Next (Item);
+         end loop;
+
+         --  Check that we did not have a PRIVATE keyword present
+
+         if Private_Present (Comp_Unit_Node) then
+            Error_Msg
+              ("(Ada 83) private units not allowed", Private_Sloc);
+         end if;
+      end if;
+
+      --  If no serious error, then output possible unit information line
+      --  for gnatchop if we are in syntax only, list units mode.
+
+      if not Cunit_Error_Flag
+        and then List_Units
+        and then Operating_Mode = Check_Syntax
+      then
+         Unit_Display (Comp_Unit_Node, Cunit_Location, SR_Present);
+      end if;
+
+      --  And now we should be at the end of file
+
+      if Token /= Tok_EOF then
+
+         --  If we already had to scan for a compilation unit, then don't
+         --  give any further error message, since it just sems to make
+         --  things worse, and we already gave a serious error message.
+
+         if Cunit_Error_Flag then
+            null;
+
+         --  If we are in check syntax mode, then we allow multiple units
+         --  so we just return with Token not set to Tok_EOF and no message.
+
+         elsif Operating_Mode = Check_Syntax then
+            return Comp_Unit_Node;
+
+         --  Otherwise we have an error. We suppress the error message
+         --  if we already had a fatal error, since this stops junk
+         --  cascaded messages in some situations.
+
+         else
+            if not Fatal_Error (Current_Source_Unit) then
+
+               if Token in Token_Class_Cunit then
+                  Error_Msg_SC
+                    ("end of file expected, " &
+                     "file can have only one compilation unit");
+
+               else
+                  Error_Msg_SC ("end of file expected");
+               end if;
+            end if;
+         end if;
+
+         --  Skip tokens to end of file, so that the -gnatl listing
+         --  will be complete in this situation, but no error checking
+         --  other than that provided at the token level.
+
+         while Token /= Tok_EOF loop
+            Scan;
+         end loop;
+
+         return Error;
+
+      --  Normal return (we were at the end of file as expected)
+
+      else
+         return Comp_Unit_Node;
+      end if;
+
+   exception
+
+      --  An error resync is a serious bomb, so indicate result unit no good
+
+      when Error_Resync =>
+         Set_Fatal_Error (Current_Source_Unit);
+         return Error;
+
+   end P_Compilation_Unit;
+
+   --------------------------
+   -- 10.1.1  Library Item --
+   --------------------------
+
+   --  Parsed by P_Compilation_Unit (10.1.1)
+
+   --------------------------------------
+   -- 10.1.1  Library Unit Declaration --
+   --------------------------------------
+
+   --  Parsed by P_Compilation_Unit (10.1.1)
+
+   ------------------------------------------------
+   -- 10.1.1  Library Unit Renaming Declaration  --
+   ------------------------------------------------
+
+   --  Parsed by P_Compilation_Unit (10.1.1)
+
+   -------------------------------
+   -- 10.1.1  Library Unit Body --
+   -------------------------------
+
+   --  Parsed by P_Compilation_Unit (10.1.1)
+
+   ------------------------------
+   -- 10.1.1  Parent Unit Name --
+   ------------------------------
+
+   --  Parsed (as a name) by its parent construct
+
+   ----------------------------
+   -- 10.1.2  Context Clause --
+   ----------------------------
+
+   --  CONTEXT_CLAUSE ::= {CONTEXT_ITEM}
+
+   --  CONTEXT_ITEM ::= WITH_CLAUSE | USE_CLAUSE | WITH_TYPE_CLAUSE
+
+   --  WITH_CLAUSE ::=
+   --    with library_unit_NAME {,library_unit_NAME};
+
+   --  WITH_TYPE_CLAUSE ::=
+   --    with type type_NAME is access; | with type type_NAME is tagged;
+
+   --  Error recovery: Cannot raise Error_Resync
+
+   function P_Context_Clause return List_Id is
+      Item_List  : List_Id;
+      With_Node  : Node_Id;
+      First_Flag : Boolean;
+
+   begin
+      Item_List := New_List;
+
+      --  Get keyword casing from WITH keyword in case not set yet
+
+      if Token = Tok_With then
+         Set_Keyword_Casing (Current_Source_File, Determine_Token_Casing);
+      end if;
+
+      --  Loop through context items
+
+      loop
+         if Style_Check then Style.Check_Indentation; end if;
+
+         --  Gather any pragmas appearing in the context clause
+
+         P_Pragmas_Opt (Item_List);
+
+         --  Processing for WITH clause
+
+         if Token = Tok_With then
+            Scan; -- past WITH
+
+            if Token = Tok_Type then
+
+               --  WITH TYPE is an extension
+
+               if not Extensions_Allowed then
+                  Error_Msg_SP ("`WITH TYPE` is a non-standard extension");
+
+                  if OpenVMS then
+                     Error_Msg_SP
+                       ("\unit must be compiled with " &
+                        "'/'E'X'T'E'N'S'I'O'N'S'_'A'L'L'O'W'E'D qualifier");
+                  else
+                     Error_Msg_SP
+                       ("\unit must be compiled with -gnatX switch");
+                  end if;
+               end if;
+
+               Scan;  -- past TYPE
+               With_Node := New_Node (N_With_Type_Clause, Token_Ptr);
+               Append (With_Node, Item_List);
+               Set_Name (With_Node, P_Qualified_Simple_Name);
+
+               T_Is;
+
+               if Token = Tok_Tagged then
+                  Set_Tagged_Present (With_Node);
+                  Scan;
+
+               elsif Token = Tok_Access then
+                  Scan;
+
+               else
+                  Error_Msg_SC ("expect tagged or access qualifier");
+               end if;
+
+               TF_Semicolon;
+
+            else
+               First_Flag := True;
+
+               --  Loop through names in one with clause, generating a separate
+               --  N_With_Clause node for each nam encountered.
+
+               loop
+                  With_Node := New_Node (N_With_Clause, Token_Ptr);
+                  Append (With_Node, Item_List);
+
+                  --  Note that we allow with'ing of child units, even in
+                  --  Ada 83 mode, since presumably if this is not desired,
+                  --  then the compilation of the child unit itself is the
+                  --  place where such an "error" should be caught.
+
+                  Set_Name (With_Node, P_Qualified_Simple_Name);
+                  Set_First_Name (With_Node, First_Flag);
+                  First_Flag := False;
+                  exit when Token /= Tok_Comma;
+                  Scan; -- past comma
+               end loop;
+
+               Set_Last_Name (With_Node, True);
+               TF_Semicolon;
+            end if;
+
+         --  Processing for USE clause
+
+         elsif Token = Tok_Use then
+            Append (P_Use_Clause, Item_List);
+
+         --  Anything else is end of context clause
+
+         else
+            exit;
+         end if;
+      end loop;
+
+      return Item_List;
+   end P_Context_Clause;
+
+   --------------------------
+   -- 10.1.2  Context Item --
+   --------------------------
+
+   --  Parsed by P_Context_Clause (10.1.2)
+
+   -------------------------
+   -- 10.1.2  With Clause --
+   -------------------------
+
+   --  Parsed by P_Context_Clause (10.1.2)
+
+   -----------------------
+   -- 10.1.3  Body Stub --
+   -----------------------
+
+   --  Subprogram stub parsed by P_Subprogram (6.1)
+   --  Package stub parsed by P_Package (7.1)
+   --  Task stub parsed by P_Task (9.1)
+   --  Protected stub parsed by P_Protected (9.4)
+
+   ----------------------------------
+   -- 10.1.3  Subprogram Body Stub --
+   ----------------------------------
+
+   --  Parsed by P_Subprogram (6.1)
+
+   -------------------------------
+   -- 10.1.3  Package Body Stub --
+   -------------------------------
+
+   --  Parsed by P_Package (7.1)
+
+   ----------------------------
+   -- 10.1.3  Task Body Stub --
+   ----------------------------
+
+   --  Parsed by P_Task (9.1)
+
+   ---------------------------------
+   -- 10.1.3  Protected Body Stub --
+   ---------------------------------
+
+   --  Parsed by P_Protected (9.4)
+
+   ---------------------
+   -- 10.1.3  Subunit --
+   ---------------------
+
+   --  SUBUNIT ::= separate (PARENT_UNIT_NAME) PROPER_BODY
+
+   --  PARENT_UNIT_NAME ::= NAME
+
+   --  The caller has checked that the initial token is SEPARATE
+
+   --  Error recovery: cannot raise Error_Resync
+
+   function P_Subunit return Node_Id is
+      Subunit_Node : Node_Id;
+      Body_Node    : Node_Id;
+
+   begin
+      Subunit_Node := New_Node (N_Subunit, Token_Ptr);
+      Body_Node := Error; -- in case no good body found
+      Scan; -- past SEPARATE;
+
+      T_Left_Paren;
+      Set_Name (Subunit_Node, P_Qualified_Simple_Name);
+      T_Right_Paren;
+
+      if Token = Tok_Semicolon then
+         Error_Msg_SC ("unexpected semicolon ignored");
+         Scan;
+      end if;
+
+      if Token = Tok_Function or else Token = Tok_Procedure then
+         Body_Node := P_Subprogram (Pf_Pbod);
+
+      elsif Token = Tok_Package then
+         Body_Node := P_Package (Pf_Pbod);
+
+      elsif Token = Tok_Protected then
+         Scan; -- past PROTECTED
+
+         if Token = Tok_Body then
+            Body_Node := P_Protected;
+         else
+            Error_Msg_AP ("BODY expected");
+            return Error;
+         end if;
+
+      elsif Token = Tok_Task then
+         Scan; -- past TASK
+
+         if Token = Tok_Body then
+            Body_Node := P_Task;
+         else
+            Error_Msg_AP ("BODY expected");
+            return Error;
+         end if;
+
+      else
+         Error_Msg_SC ("proper body expected");
+         return Error;
+      end if;
+
+      Set_Proper_Body  (Subunit_Node, Body_Node);
+      return Subunit_Node;
+
+   end P_Subunit;
+
+   ------------------
+   -- Set_Location --
+   ------------------
+
+   function Set_Location return Source_Ptr is
+      Physical   : Boolean;
+      Loc        : Source_Ptr;
+      Scan_State : Saved_Scan_State;
+
+   begin
+      --  A special check. If the first token is pragma, and this is a
+      --  Source_Reference pragma, then do NOT eat previous comments, since
+      --  the Source_Reference pragma is required to be the first line in
+      --  the source file.
+
+      if Token = Tok_Pragma then
+         Save_Scan_State (Scan_State);
+         Scan; --  past Pragma
+
+         if Token = Tok_Identifier
+           and then Token_Name = Name_Source_Reference
+         then
+            Restore_Scan_State (Scan_State);
+            return Token_Ptr;
+         end if;
+
+         Restore_Scan_State (Scan_State);
+      end if;
+
+      --  Otherwise acquire previous comments and blank lines
+
+      if Prev_Token = No_Token then
+         return Source_First (Current_Source_File);
+
+      else
+         Loc := Prev_Token_Ptr;
+         loop
+            exit when Loc = Token_Ptr;
+
+            if Source (Loc) in Line_Terminator then
+               Skip_Line_Terminators (Loc, Physical);
+               exit when Physical;
+            end if;
+
+            Loc := Loc + 1;
+         end loop;
+
+         return Loc;
+      end if;
+   end Set_Location;
+
+   ------------------
+   -- Unit_Display --
+   ------------------
+
+   --  The format of the generated line, as expected by GNATCHOP is
+
+   --    Unit {unit} line {line}, file offset {offs} [, SR], file name {file}
+
+   --  where
+
+   --     {unit}     unit name with terminating (spec) or (body)
+   --     {line}     starting line number
+   --     {offs}     offset to start of text in file
+   --     {file}     source file name
+
+   --  The SR parameter is present only if a source reference pragma was
+   --  scanned for this unit. The significance is that gnatchop should not
+   --  attempt to add another one.
+
+   procedure Unit_Display
+     (Cunit      : Node_Id;
+      Loc        : Source_Ptr;
+      SR_Present : Boolean)
+   is
+      Unum : constant Unit_Number_Type    := Get_Cunit_Unit_Number (Cunit);
+      Sind : constant Source_File_Index   := Source_Index (Unum);
+      Unam : constant Unit_Name_Type      := Unit_Name (Unum);
+
+   begin
+      if List_Units then
+         Write_Str ("Unit ");
+         Write_Unit_Name (Unit_Name (Unum));
+         Unit_Location (Sind, Loc);
+
+         if SR_Present then
+            Write_Str (", SR");
+         end if;
+
+         Write_Str (", file name ");
+         Write_Name (Get_File_Name (Unam, Nkind (Unit (Cunit)) = N_Subunit));
+         Write_Eol;
+      end if;
+   end Unit_Display;
+
+   -------------------
+   -- Unit_Location --
+   -------------------
+
+   procedure Unit_Location (Sind : Source_File_Index; Loc : Source_Ptr) is
+      Line : constant Logical_Line_Number := Get_Logical_Line_Number (Loc);
+      --  Should the above be the physical line number ???
+
+   begin
+      Write_Str (" line ");
+      Write_Int (Int (Line));
+
+      Write_Str (", file offset ");
+      Write_Int (Int (Loc) - Int (Source_First (Sind)));
+   end Unit_Location;
+
+end Ch10;
diff --git a/gcc/ada/par-ch11.adb b/gcc/ada/par-ch11.adb
new file mode 100644 (file)
index 0000000..8b59c54
--- /dev/null
@@ -0,0 +1,246 @@
+------------------------------------------------------------------------------
+--                                                                          --
+--                         GNAT COMPILER COMPONENTS                         --
+--                                                                          --
+--                             P A R . C H 1 1                              --
+--                                                                          --
+--                                 B o d y                                  --
+--                                                                          --
+--                            $Revision: 1.22 $
+--                                                                          --
+--          Copyright (C) 1992-2001 Free Software Foundation, Inc.          --
+--                                                                          --
+-- GNAT is free software;  you can  redistribute it  and/or modify it under --
+-- terms of the  GNU General Public License as published  by the Free Soft- --
+-- ware  Foundation;  either version 2,  or (at your option) any later ver- --
+-- sion.  GNAT is distributed in the hope that it will be useful, but WITH- --
+-- OUT 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  distributed with GNAT;  see file COPYING.  If not, write --
+-- to  the Free Software Foundation,  59 Temple Place - Suite 330,  Boston, --
+-- MA 02111-1307, USA.                                                      --
+--                                                                          --
+-- GNAT was originally developed  by the GNAT team at  New York University. --
+-- It is now maintained by Ada Core Technologies Inc (http://www.gnat.com). --
+--                                                                          --
+------------------------------------------------------------------------------
+
+pragma Style_Checks (All_Checks);
+--  Turn off subprogram body ordering check. Subprograms are in order
+--  by RM section rather than alphabetical
+
+with Sinfo.CN; use Sinfo.CN;
+
+separate (Par)
+package body Ch11 is
+
+   --  Local functions, used only in this chapter
+
+   function P_Exception_Handler  return Node_Id;
+   function P_Exception_Choice   return Node_Id;
+
+   ---------------------------------
+   -- 11.1  Exception Declaration --
+   ---------------------------------
+
+   --  Parsed by P_Identifier_Declaration (3.3.1)
+
+   ------------------------------------------
+   -- 11.2  Handled Sequence Of Statements --
+   ------------------------------------------
+
+   --  HANDLED_SEQUENCE_OF_STATEMENTS ::=
+   --      SEQUENCE_OF_STATEMENTS
+   --    [exception
+   --      EXCEPTION_HANDLER
+   --      {EXCEPTION_HANDLER}]
+
+   --  Error_Recovery : Cannot raise Error_Resync
+
+   function P_Handled_Sequence_Of_Statements return Node_Id is
+      Handled_Stmt_Seq_Node : Node_Id;
+
+   begin
+      Handled_Stmt_Seq_Node :=
+        New_Node (N_Handled_Sequence_Of_Statements, Token_Ptr);
+      Set_Statements
+        (Handled_Stmt_Seq_Node, P_Sequence_Of_Statements (SS_Extm_Sreq));
+
+      if Token = Tok_Exception then
+         Scan; -- past EXCEPTION
+         Set_Exception_Handlers
+           (Handled_Stmt_Seq_Node, Parse_Exception_Handlers);
+      end if;
+
+      return Handled_Stmt_Seq_Node;
+   end P_Handled_Sequence_Of_Statements;
+
+   -----------------------------
+   -- 11.2  Exception Handler --
+   -----------------------------
+
+   --  EXCEPTION_HANDLER ::=
+   --    when [CHOICE_PARAMETER_SPECIFICATION :]
+   --      EXCEPTION_CHOICE {| EXCEPTION_CHOICE} =>
+   --        SEQUENCE_OF_STATEMENTS
+
+   --  CHOICE_PARAMETER_SPECIFICATION ::= DEFINING_IDENTIFIER
+
+   --  Error recovery: cannot raise Error_Resync
+
+   function P_Exception_Handler return Node_Id is
+      Scan_State        : Saved_Scan_State;
+      Handler_Node      : Node_Id;
+      Choice_Param_Node : Node_Id;
+
+   begin
+      Handler_Node := New_Node (N_Exception_Handler, Token_Ptr);
+      T_When;
+
+      --  Test for possible choice parameter present
+
+      if Token = Tok_Identifier then
+         Choice_Param_Node := Token_Node;
+         Save_Scan_State (Scan_State); -- at identifier
+         Scan; -- past identifier
+
+         if Token = Tok_Colon then
+            if Ada_83 then
+               Error_Msg_SP ("(Ada 83) choice parameter not allowed!");
+            end if;
+
+            Scan; -- past :
+            Change_Identifier_To_Defining_Identifier (Choice_Param_Node);
+            Set_Choice_Parameter (Handler_Node, Choice_Param_Node);
+
+         elsif Token = Tok_Others then
+            Error_Msg_AP ("missing "":""");
+            Change_Identifier_To_Defining_Identifier (Choice_Param_Node);
+            Set_Choice_Parameter (Handler_Node, Choice_Param_Node);
+
+         else
+            Restore_Scan_State (Scan_State); -- to identifier
+         end if;
+      end if;
+
+      --  Loop through exception choices
+
+      Set_Exception_Choices (Handler_Node, New_List);
+
+      loop
+         Append (P_Exception_Choice, Exception_Choices (Handler_Node));
+         exit when Token /= Tok_Vertical_Bar;
+         Scan; -- past vertical bar
+      end loop;
+
+      TF_Arrow;
+      Set_Statements (Handler_Node, P_Sequence_Of_Statements (SS_Sreq_Whtm));
+      return Handler_Node;
+   end P_Exception_Handler;
+
+   ------------------------------------------
+   -- 11.2  Choice Parameter Specification --
+   ------------------------------------------
+
+   --  Parsed by P_Exception_Handler (11.2)
+
+   ----------------------------
+   -- 11.2  Exception Choice --
+   ----------------------------
+
+   --  EXCEPTION_CHOICE ::= exception_NAME | others
+
+   --  Error recovery: cannot raise Error_Resync. If an error occurs, then the
+   --  scan pointer is advanced to the next arrow or vertical bar or semicolon.
+
+   function P_Exception_Choice return Node_Id is
+   begin
+
+      if Token = Tok_Others then
+         Scan; -- past OTHERS
+         return New_Node (N_Others_Choice, Prev_Token_Ptr);
+
+      else
+         return P_Name; -- exception name
+      end if;
+
+   exception
+      when Error_Resync =>
+         Resync_Choice;
+         return Error;
+   end P_Exception_Choice;
+
+   ---------------------------
+   -- 11.3  Raise Statement --
+   ---------------------------
+
+   --  RAISE_STATEMENT ::= raise [exception_NAME];
+
+   --  The caller has verified that the initial token is RAISE
+
+   --  Error recovery: can raise Error_Resync
+
+   function P_Raise_Statement return Node_Id is
+      Raise_Node : Node_Id;
+
+   begin
+      Raise_Node := New_Node (N_Raise_Statement, Token_Ptr);
+      Scan; -- past RAISE
+
+      if Token /= Tok_Semicolon then
+         Set_Name (Raise_Node, P_Name);
+      end if;
+
+      TF_Semicolon;
+      return Raise_Node;
+   end P_Raise_Statement;
+
+   ------------------------------
+   -- Parse_Exception_Handlers --
+   ------------------------------
+
+   --  This routine scans out a list of exception handlers appearing in a
+   --  construct as:
+
+   --    exception
+   --      EXCEPTION_HANDLER {EXCEPTION_HANDLER}
+
+   --  The caller has scanned out the EXCEPTION keyword
+
+   --  Control returns after scanning the last exception handler, presumably
+   --  at the keyword END, but this is not checked in this routine.
+
+   --  Error recovery: cannot raise Error_Resync
+
+   function Parse_Exception_Handlers return List_Id is
+      Handler       : Node_Id;
+      Handlers_List : List_Id;
+      Pragmas_List  : List_Id;
+
+   begin
+      Handlers_List := New_List;
+      P_Pragmas_Opt (Handlers_List);
+
+      if Token = Tok_End then
+         Error_Msg_SC ("must have at least one exception handler!");
+
+      else
+         loop
+            Handler := P_Exception_Handler;
+            Pragmas_List := No_List;
+            Append (Handler, Handlers_List);
+
+            --  Note: no need to check for pragmas here. Although the
+            --  syntax officially allows them in this position, they
+            --  will have been swallowed up as part of the statement
+            --  sequence of the handler we just scanned out.
+
+            exit when Token /= Tok_When;
+         end loop;
+      end if;
+
+      return Handlers_List;
+   end Parse_Exception_Handlers;
+
+end Ch11;
diff --git a/gcc/ada/par-ch12.adb b/gcc/ada/par-ch12.adb
new file mode 100644 (file)
index 0000000..139243e
--- /dev/null
@@ -0,0 +1,882 @@
+------------------------------------------------------------------------------
+--                                                                          --
+--                         GNAT COMPILER COMPONENTS                         --
+--                                                                          --
+--                             P A R . C H 1 2                              --
+--                                                                          --
+--                                 B o d y                                  --
+--                                                                          --
+--                            $Revision: 1.46 $
+--                                                                          --
+--          Copyright (C) 1992-2001 Free Software Foundation, Inc.          --
+--                                                                          --
+-- GNAT is free software;  you can  redistribute it  and/or modify it under --
+-- terms of the  GNU General Public License as published  by the Free Soft- --
+-- ware  Foundation;  either version 2,  or (at your option) any later ver- --
+-- sion.  GNAT is distributed in the hope that it will be useful, but WITH- --
+-- OUT 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  distributed with GNAT;  see file COPYING.  If not, write --
+-- to  the Free Software Foundation,  59 Temple Place - Suite 330,  Boston, --
+-- MA 02111-1307, USA.                                                      --
+--                                                                          --
+-- GNAT was originally developed  by the GNAT team at  New York University. --
+-- It is now maintained by Ada Core Technologies Inc (http://www.gnat.com). --
+--                                                                          --
+------------------------------------------------------------------------------
+
+pragma Style_Checks (All_Checks);
+--  Turn off subprogram body ordering check. Subprograms are in order
+--  by RM section rather than alphabetical
+
+separate (Par)
+package body Ch12 is
+
+   --  Local functions, used only in this chapter
+
+   function P_Formal_Derived_Type_Definition           return Node_Id;
+   function P_Formal_Discrete_Type_Definition          return Node_Id;
+   function P_Formal_Fixed_Point_Definition            return Node_Id;
+   function P_Formal_Floating_Point_Definition         return Node_Id;
+   function P_Formal_Modular_Type_Definition           return Node_Id;
+   function P_Formal_Package_Declaration               return Node_Id;
+   function P_Formal_Private_Type_Definition           return Node_Id;
+   function P_Formal_Signed_Integer_Type_Definition    return Node_Id;
+   function P_Formal_Subprogram_Declaration            return Node_Id;
+   function P_Formal_Type_Declaration                  return Node_Id;
+   function P_Formal_Type_Definition                   return Node_Id;
+   function P_Generic_Association                      return Node_Id;
+
+   procedure P_Formal_Object_Declarations (Decls : List_Id);
+   --  Scans one or more formal object declarations and appends them to
+   --  Decls. Scans more than one declaration only in the case where the
+   --  source has a declaration with multiple defining identifiers.
+
+   --------------------------------
+   -- 12.1  Generic (also 8.5.5) --
+   --------------------------------
+
+   --  This routine parses either one of the forms of a generic declaration
+   --  or a generic renaming declaration.
+
+   --  GENERIC_DECLARATION ::=
+   --    GENERIC_SUBPROGRAM_DECLARATION | GENERIC_PACKAGE_DECLARATION
+
+   --  GENERIC_SUBPROGRAM_DECLARATION ::=
+   --    GENERIC_FORMAL_PART SUBPROGRAM_SPECIFICATION;
+
+   --  GENERIC_PACKAGE_DECLARATION ::=
+   --    GENERIC_FORMAL_PART PACKAGE_SPECIFICATION;
+
+   --  GENERIC_FORMAL_PART ::=
+   --    generic {GENERIC_FORMAL_PARAMETER_DECLARATION | USE_CLAUSE}
+
+   --  GENERIC_RENAMING_DECLARATION ::=
+   --    generic package DEFINING_PROGRAM_UNIT_NAME
+   --      renames generic_package_NAME
+   --  | generic procedure DEFINING_PROGRAM_UNIT_NAME
+   --      renames generic_procedure_NAME
+   --  | generic function DEFINING_PROGRAM_UNIT_NAME
+   --      renames generic_function_NAME
+
+   --  GENERIC_FORMAL_PARAMETER_DECLARATION ::=
+   --    FORMAL_OBJECT_DECLARATION
+   --  | FORMAL_TYPE_DECLARATION
+   --  | FORMAL_SUBPROGRAM_DECLARATION
+   --  | FORMAL_PACKAGE_DECLARATION
+
+   --  The caller has checked that the initial token is GENERIC
+
+   --  Error recovery: can raise Error_Resync
+
+   function P_Generic return Node_Id is
+      Gen_Sloc   : constant Source_Ptr := Token_Ptr;
+      Gen_Decl   : Node_Id;
+      Decl_Node  : Node_Id;
+      Decls      : List_Id;
+      Def_Unit   : Node_Id;
+      Ren_Token  : Token_Type;
+      Scan_State : Saved_Scan_State;
+
+   begin
+      Scan; -- past GENERIC
+
+      if Token = Tok_Private then
+         Error_Msg_SC ("PRIVATE goes before GENERIC, not after");
+         Scan; -- past junk PRIVATE token
+      end if;
+
+      Save_Scan_State (Scan_State); -- at token past GENERIC
+
+      --  Check for generic renaming declaration case
+
+      if Token = Tok_Package
+        or else Token = Tok_Function
+        or else Token = Tok_Procedure
+      then
+         Ren_Token := Token;
+         Scan; -- scan past PACKAGE, FUNCTION or PROCEDURE
+
+         if Token = Tok_Identifier then
+            Def_Unit := P_Defining_Program_Unit_Name;
+
+            Check_Misspelling_Of (Tok_Renames);
+
+            if Token = Tok_Renames then
+               if Ren_Token = Tok_Package then
+                  Decl_Node := New_Node
+                    (N_Generic_Package_Renaming_Declaration, Gen_Sloc);
+
+               elsif Ren_Token = Tok_Procedure then
+                  Decl_Node := New_Node
+                    (N_Generic_Procedure_Renaming_Declaration, Gen_Sloc);
+
+               else -- Ren_Token = Tok_Function then
+                  Decl_Node := New_Node
+                    (N_Generic_Function_Renaming_Declaration, Gen_Sloc);
+               end if;
+
+               Scan; -- past RENAMES
+               Set_Defining_Unit_Name (Decl_Node, Def_Unit);
+               Set_Name (Decl_Node, P_Name);
+               TF_Semicolon;
+               return Decl_Node;
+            end if;
+         end if;
+      end if;
+
+      --  Fall through if this is *not* a generic renaming declaration
+
+      Restore_Scan_State (Scan_State);
+      Decls := New_List;
+
+      --  Loop through generic parameter declarations and use clauses
+
+      Decl_Loop : loop
+         P_Pragmas_Opt (Decls);
+         Ignore (Tok_Private);
+
+         if Token = Tok_Use then
+            Append (P_Use_Clause, Decls);
+         else
+            --  Parse a generic parameter declaration
+
+            if Token = Tok_Identifier then
+               P_Formal_Object_Declarations (Decls);
+
+            elsif Token = Tok_Type then
+               Append (P_Formal_Type_Declaration, Decls);
+
+            elsif Token = Tok_With then
+               Scan; -- past WITH
+
+               if Token = Tok_Package then
+                  Append (P_Formal_Package_Declaration, Decls);
+
+               elsif Token = Tok_Procedure or Token = Tok_Function then
+                  Append (P_Formal_Subprogram_Declaration, Decls);
+
+               else
+                  Error_Msg_BC
+                    ("FUNCTION, PROCEDURE or PACKAGE expected here");
+                  Resync_Past_Semicolon;
+               end if;
+
+            elsif Token = Tok_Subtype then
+               Error_Msg_SC ("subtype declaration not allowed " &
+                                "as generic parameter declaration!");
+               Resync_Past_Semicolon;
+
+            else
+               exit Decl_Loop;
+            end if;
+         end if;
+
+      end loop Decl_Loop;
+
+      --  Generic formal part is scanned, scan out subprogram or package spec
+
+      if Token = Tok_Package then
+         Gen_Decl := New_Node (N_Generic_Package_Declaration, Gen_Sloc);
+         Set_Specification (Gen_Decl, P_Package (Pf_Spcn));
+      else
+         Gen_Decl := New_Node (N_Generic_Subprogram_Declaration, Gen_Sloc);
+         Set_Specification (Gen_Decl, P_Subprogram_Specification);
+         TF_Semicolon;
+      end if;
+
+      Set_Generic_Formal_Declarations (Gen_Decl, Decls);
+      return Gen_Decl;
+   end P_Generic;
+
+   -------------------------------
+   -- 12.1  Generic Declaration --
+   -------------------------------
+
+   --  Parsed by P_Generic (12.1)
+
+   ------------------------------------------
+   -- 12.1  Generic Subprogram Declaration --
+   ------------------------------------------
+
+   --  Parsed by P_Generic (12.1)
+
+   ---------------------------------------
+   -- 12.1  Generic Package Declaration --
+   ---------------------------------------
+
+   --  Parsed by P_Generic (12.1)
+
+   -------------------------------
+   -- 12.1  Generic Formal Part --
+   -------------------------------
+
+   --  Parsed by P_Generic (12.1)
+
+   -------------------------------------------------
+   -- 12.1   Generic Formal Parameter Declaration --
+   -------------------------------------------------
+
+   --  Parsed by P_Generic (12.1)
+
+   ---------------------------------
+   -- 12.3  Generic Instantiation --
+   ---------------------------------
+
+   --  Generic package instantiation parsed by P_Package (7.1)
+   --  Generic procedure instantiation parsed by P_Subprogram (6.1)
+   --  Generic function instantiation parsed by P_Subprogram (6.1)
+
+   -------------------------------
+   -- 12.3  Generic Actual Part --
+   -------------------------------
+
+   --  GENERIC_ACTUAL_PART ::=
+   --    (GENERIC_ASSOCIATION {, GENERIC_ASSOCIATION})
+
+   --  Returns a list of generic associations, or Empty if none are present
+
+   --  Error recovery: cannot raise Error_Resync
+
+   function P_Generic_Actual_Part_Opt return List_Id is
+      Association_List : List_Id;
+
+   begin
+      --  Figure out if a generic actual part operation is present. Clearly
+      --  there is no generic actual part if the current token is semicolon
+
+      if Token = Tok_Semicolon then
+         return No_List;
+
+      --  If we don't have a left paren, then we have an error, and the job
+      --  is to figure out whether a left paren or semicolon was intended.
+      --  We assume a missing left paren (and hence a generic actual part
+      --  present) if the current token is not on a new line, or if it is
+      --  indented from the subprogram token. Otherwise assume missing
+      --  semicolon (which will be diagnosed by caller) and no generic part
+
+      elsif Token /= Tok_Left_Paren
+        and then Token_Is_At_Start_Of_Line
+        and then Start_Column <= Scope.Table (Scope.Last).Ecol
+      then
+         return No_List;
+
+      --  Otherwise we have a generic actual part (either a left paren is
+      --  present, or we have decided that there must be a missing left paren)
+
+      else
+         Association_List := New_List;
+         T_Left_Paren;
+
+         loop
+            Append (P_Generic_Association, Association_List);
+            exit when not Comma_Present;
+         end loop;
+
+         T_Right_Paren;
+         return Association_List;
+      end if;
+
+   end P_Generic_Actual_Part_Opt;
+
+   -------------------------------
+   -- 12.3  Generic Association --
+   -------------------------------
+
+   --  GENERIC_ASSOCIATION ::=
+   --    [generic_formal_parameter_SELECTOR_NAME =>]
+   --      EXPLICIT_GENERIC_ACTUAL_PARAMETER
+
+   --  EXPLICIT_GENERIC_ACTUAL_PARAMETER ::=
+   --    EXPRESSION      | variable_NAME   | subprogram_NAME
+   --  | entry_NAME      | SUBTYPE_MARK    | package_instance_NAME
+
+   --  Error recovery: cannot raise Error_Resync
+
+   function P_Generic_Association return Node_Id is
+      Scan_State         : Saved_Scan_State;
+      Param_Name_Node    : Node_Id;
+      Generic_Assoc_Node : Node_Id;
+
+   begin
+      Generic_Assoc_Node := New_Node (N_Generic_Association, Token_Ptr);
+
+      if Token in Token_Class_Desig then
+         Param_Name_Node := Token_Node;
+         Save_Scan_State (Scan_State); -- at designator
+         Scan; -- past simple name or operator symbol
+
+         if Token = Tok_Arrow then
+            Scan; -- past arrow
+            Set_Selector_Name (Generic_Assoc_Node, Param_Name_Node);
+         else
+            Restore_Scan_State (Scan_State); -- to designator
+         end if;
+      end if;
+
+      Set_Explicit_Generic_Actual_Parameter (Generic_Assoc_Node, P_Expression);
+      return Generic_Assoc_Node;
+   end P_Generic_Association;
+
+   ---------------------------------------------
+   -- 12.3  Explicit Generic Actual Parameter --
+   ---------------------------------------------
+
+   --  Parsed by P_Generic_Association (12.3)
+
+   --------------------------------------
+   -- 12.4  Formal Object Declarations --
+   --------------------------------------
+
+   --  FORMAL_OBJECT_DECLARATION ::=
+   --    DEFINING_IDENTIFIER_LIST :
+   --      MODE SUBTYPE_MARK [:= DEFAULT_EXPRESSION];
+
+   --  The caller has checked that the initial token is an identifier
+
+   --  Error recovery: cannot raise Error_Resync
+
+   procedure P_Formal_Object_Declarations (Decls : List_Id) is
+      Decl_Node  : Node_Id;
+      Scan_State : Saved_Scan_State;
+      Num_Idents : Nat;
+      Ident      : Nat;
+
+      Idents : array (Int range 1 .. 4096) of Entity_Id;
+      --  This array holds the list of defining identifiers. The upper bound
+      --  of 4096 is intended to be essentially infinite, and we do not even
+      --  bother to check for it being exceeded.
+
+   begin
+      Idents (1) := P_Defining_Identifier;
+      Num_Idents := 1;
+
+      while Comma_Present loop
+         Num_Idents := Num_Idents + 1;
+         Idents (Num_Idents) := P_Defining_Identifier;
+      end loop;
+
+      T_Colon;
+
+      --  If there are multiple identifiers, we repeatedly scan the
+      --  type and initialization expression information by resetting
+      --  the scan pointer (so that we get completely separate trees
+      --  for each occurrence).
+
+      if Num_Idents > 1 then
+         Save_Scan_State (Scan_State);
+      end if;
+
+      --  Loop through defining identifiers in list
+
+      Ident := 1;
+      Ident_Loop : loop
+         Decl_Node := New_Node (N_Formal_Object_Declaration, Token_Ptr);
+         Set_Defining_Identifier (Decl_Node, Idents (Ident));
+         P_Mode (Decl_Node);
+         Set_Subtype_Mark (Decl_Node, P_Subtype_Mark_Resync);
+         No_Constraint;
+         Set_Expression (Decl_Node, Init_Expr_Opt);
+
+         if Ident > 1 then
+            Set_Prev_Ids (Decl_Node, True);
+         end if;
+
+         if Ident < Num_Idents then
+            Set_More_Ids (Decl_Node, True);
+         end if;
+
+         Append (Decl_Node, Decls);
+
+         exit Ident_Loop when Ident = Num_Idents;
+         Ident := Ident + 1;
+         Restore_Scan_State (Scan_State);
+      end loop Ident_Loop;
+
+      TF_Semicolon;
+   end P_Formal_Object_Declarations;
+
+   -----------------------------------
+   -- 12.5  Formal Type Declaration --
+   -----------------------------------
+
+   --  FORMAL_TYPE_DECLARATION ::=
+   --    type DEFINING_IDENTIFIER [DISCRIMINANT_PART]
+   --      is FORMAL_TYPE_DEFINITION;
+
+   --  The caller has checked that the initial token is TYPE
+
+   --  Error recovery: cannot raise Error_Resync
+
+   function P_Formal_Type_Declaration return Node_Id is
+      Decl_Node  : Node_Id;
+
+   begin
+      Decl_Node := New_Node (N_Formal_Type_Declaration, Token_Ptr);
+      Scan; -- past TYPE
+      Set_Defining_Identifier (Decl_Node, P_Defining_Identifier);
+
+      if P_Unknown_Discriminant_Part_Opt then
+         Set_Unknown_Discriminants_Present (Decl_Node, True);
+      else
+         Set_Discriminant_Specifications
+           (Decl_Node, P_Known_Discriminant_Part_Opt);
+      end if;
+
+      T_Is;
+
+      Set_Formal_Type_Definition (Decl_Node, P_Formal_Type_Definition);
+      TF_Semicolon;
+      return Decl_Node;
+   end P_Formal_Type_Declaration;
+
+   ----------------------------------
+   -- 12.5  Formal Type Definition --
+   ----------------------------------
+
+   --  FORMAL_TYPE_DEFINITION ::=
+   --    FORMAL_PRIVATE_TYPE_DEFINITION
+   --  | FORMAL_DERIVED_TYPE_DEFINITION
+   --  | FORMAL_DISCRETE_TYPE_DEFINITION
+   --  | FORMAL_SIGNED_INTEGER_TYPE_DEFINITION
+   --  | FORMAL_MODULAR_TYPE_DEFINITION
+   --  | FORMAL_FLOATING_POINT_DEFINITION
+   --  | FORMAL_ORDINARY_FIXED_POINT_DEFINITION
+   --  | FORMAL_DECIMAL_FIXED_POINT_DEFINITION
+   --  | FORMAL_ARRAY_TYPE_DEFINITION
+   --  | FORMAL_ACCESS_TYPE_DEFINITION
+
+   --  FORMAL_ARRAY_TYPE_DEFINITION ::= ARRAY_TYPE_DEFINITION
+
+   --  FORMAL_ACCESS_TYPE_DEFINITION ::= ACCESS_TYPE_DEFINITION
+
+   function P_Formal_Type_Definition return Node_Id is
+      Scan_State : Saved_Scan_State;
+
+   begin
+      if Token_Name = Name_Abstract then
+         Check_95_Keyword (Tok_Abstract, Tok_Tagged);
+      end if;
+
+      if Token_Name = Name_Tagged then
+         Check_95_Keyword (Tok_Tagged, Tok_Private);
+         Check_95_Keyword (Tok_Tagged, Tok_Limited);
+      end if;
+
+      case Token is
+
+         --  Mostly we can tell what we have from the initial token. The one
+         --  exception is ABSTRACT, where we have to scan ahead to see if we
+         --  have a formal derived type or a formal private type definition.
+
+         when Tok_Abstract =>
+            Save_Scan_State (Scan_State);
+            Scan; -- past ABSTRACT
+
+            if Token = Tok_New then
+               Restore_Scan_State (Scan_State); -- to ABSTRACT
+               return P_Formal_Derived_Type_Definition;
+
+            else
+               Restore_Scan_State (Scan_State); -- to ABSTRACT
+               return P_Formal_Private_Type_Definition;
+            end if;
+
+         when Tok_Private | Tok_Limited | Tok_Tagged =>
+            return P_Formal_Private_Type_Definition;
+
+         when Tok_New =>
+            return P_Formal_Derived_Type_Definition;
+
+         when Tok_Left_Paren =>
+            return P_Formal_Discrete_Type_Definition;
+
+         when Tok_Range =>
+            return P_Formal_Signed_Integer_Type_Definition;
+
+         when Tok_Mod =>
+            return P_Formal_Modular_Type_Definition;
+
+         when Tok_Digits =>
+            return P_Formal_Floating_Point_Definition;
+
+         when Tok_Delta =>
+            return P_Formal_Fixed_Point_Definition;
+
+         when Tok_Array =>
+            return P_Array_Type_Definition;
+
+         when Tok_Access =>
+            return P_Access_Type_Definition;
+
+         when Tok_Record =>
+            Error_Msg_SC ("record not allowed in generic type definition!");
+            Discard_Junk_Node (P_Record_Definition);
+            return Error;
+
+         when others =>
+            Error_Msg_BC ("expecting generic type definition here");
+            Resync_Past_Semicolon;
+            return Error;
+
+      end case;
+   end P_Formal_Type_Definition;
+
+   --------------------------------------------
+   -- 12.5.1  Formal Private Type Definition --
+   --------------------------------------------
+
+   --  FORMAL_PRIVATE_TYPE_DEFINITION ::=
+   --    [[abstract] tagged] [limited] private
+
+   --  The caller has checked the initial token is PRIVATE, ABSTRACT,
+   --   TAGGED or LIMITED
+
+   --  Error recovery: cannot raise Error_Resync
+
+   function P_Formal_Private_Type_Definition return Node_Id is
+      Def_Node : Node_Id;
+
+   begin
+      Def_Node := New_Node (N_Formal_Private_Type_Definition, Token_Ptr);
+
+      if Token = Tok_Abstract then
+         Scan; -- past ABSTRACT
+
+         if Token_Name = Name_Tagged then
+            Check_95_Keyword (Tok_Tagged, Tok_Private);
+            Check_95_Keyword (Tok_Tagged, Tok_Limited);
+         end if;
+
+         if Token /= Tok_Tagged then
+            Error_Msg_SP ("ABSTRACT must be followed by TAGGED");
+         else
+            Set_Abstract_Present (Def_Node, True);
+         end if;
+      end if;
+
+      if Token = Tok_Tagged then
+         Set_Tagged_Present (Def_Node, True);
+         Scan; -- past TAGGED
+      end if;
+
+      if Token = Tok_Limited then
+         Set_Limited_Present (Def_Node, True);
+         Scan; -- past LIMITED
+      end if;
+
+      Set_Sloc (Def_Node, Token_Ptr);
+      T_Private;
+      return Def_Node;
+   end P_Formal_Private_Type_Definition;
+
+   --------------------------------------------
+   -- 12.5.1  Formal Derived Type Definition --
+   --------------------------------------------
+
+   --  FORMAL_DERIVED_TYPE_DEFINITION ::=
+   --    [abstract] new SUBTYPE_MARK [with private]
+
+   --  The caller has checked the initial token(s) is/are NEW or ASTRACT NEW
+
+   --  Error recovery: cannot raise Error_Resync
+
+   function P_Formal_Derived_Type_Definition return Node_Id is
+      Def_Node : Node_Id;
+
+   begin
+      Def_Node := New_Node (N_Formal_Derived_Type_Definition, Token_Ptr);
+
+      if Token = Tok_Abstract then
+         Set_Abstract_Present (Def_Node);
+         Scan; -- past ABSTRACT
+      end if;
+
+      Scan; -- past NEW;
+      Set_Subtype_Mark (Def_Node, P_Subtype_Mark);
+      No_Constraint;
+
+      if Token = Tok_With then
+         Scan; -- past WITH
+         Set_Private_Present (Def_Node, True);
+         T_Private;
+      end if;
+
+      return Def_Node;
+   end P_Formal_Derived_Type_Definition;
+
+   ---------------------------------------------
+   -- 12.5.2  Formal Discrete Type Definition --
+   ---------------------------------------------
+
+   --  FORMAL_DISCRETE_TYPE_DEFINITION ::= (<>)
+
+   --  The caller has checked the initial token is left paren
+
+   --  Error recovery: cannot raise Error_Resync
+
+   function P_Formal_Discrete_Type_Definition return Node_Id is
+      Def_Node : Node_Id;
+
+   begin
+      Def_Node := New_Node (N_Formal_Discrete_Type_Definition, Token_Ptr);
+      Scan; -- past left paren
+      T_Box;
+      T_Right_Paren;
+      return Def_Node;
+   end P_Formal_Discrete_Type_Definition;
+
+   ---------------------------------------------------
+   -- 12.5.2  Formal Signed Integer Type Definition --
+   ---------------------------------------------------
+
+   --  FORMAL_SIGNED_INTEGER_TYPE_DEFINITION ::= range <>
+
+   --  The caller has checked the initial token is RANGE
+
+   --  Error recovery: cannot raise Error_Resync
+
+   function P_Formal_Signed_Integer_Type_Definition return Node_Id is
+      Def_Node : Node_Id;
+
+   begin
+      Def_Node :=
+        New_Node (N_Formal_Signed_Integer_Type_Definition, Token_Ptr);
+      Scan; -- past RANGE
+      T_Box;
+      return Def_Node;
+   end P_Formal_Signed_Integer_Type_Definition;
+
+   --------------------------------------------
+   -- 12.5.2  Formal Modular Type Definition --
+   --------------------------------------------
+
+   --  FORMAL_MODULAR_TYPE_DEFINITION ::= mod <>
+
+   --  The caller has checked the initial token is MOD
+
+   --  Error recovery: cannot raise Error_Resync
+
+   function P_Formal_Modular_Type_Definition return Node_Id is
+      Def_Node : Node_Id;
+
+   begin
+      Def_Node :=
+        New_Node (N_Formal_Modular_Type_Definition, Token_Ptr);
+      Scan; -- past MOD
+      T_Box;
+      return Def_Node;
+   end P_Formal_Modular_Type_Definition;
+
+   ----------------------------------------------
+   -- 12.5.2  Formal Floating Point Definition --
+   ----------------------------------------------
+
+   --  FORMAL_FLOATING_POINT_DEFINITION ::= digits <>
+
+   --  The caller has checked the initial token is DIGITS
+
+   --  Error recovery: cannot raise Error_Resync
+
+   function P_Formal_Floating_Point_Definition return Node_Id is
+      Def_Node : Node_Id;
+
+   begin
+      Def_Node :=
+        New_Node (N_Formal_Floating_Point_Definition, Token_Ptr);
+      Scan; -- past DIGITS
+      T_Box;
+      return Def_Node;
+   end P_Formal_Floating_Point_Definition;
+
+   -------------------------------------------
+   -- 12.5.2  Formal Fixed Point Definition --
+   -------------------------------------------
+
+   --  This routine parses either a formal ordinary fixed point definition
+   --  or a formal decimal fixed point definition:
+
+   --  FORMAL_ORDINARY_FIXED_POINT_DEFINITION ::= delta <>
+
+   --  FORMAL_DECIMAL_FIXED_POINT_DEFINITION ::= delta <> digits <>
+
+   --  The caller has checked the initial token is DELTA
+
+   --  Error recovery: cannot raise Error_Resync
+
+   function P_Formal_Fixed_Point_Definition return Node_Id is
+      Def_Node   : Node_Id;
+      Delta_Sloc : Source_Ptr;
+
+   begin
+      Delta_Sloc := Token_Ptr;
+      Scan; -- past DELTA
+      T_Box;
+
+      if Token = Tok_Digits then
+         Def_Node :=
+           New_Node (N_Formal_Decimal_Fixed_Point_Definition, Delta_Sloc);
+         Scan; -- past DIGITS
+         T_Box;
+      else
+         Def_Node :=
+           New_Node (N_Formal_Ordinary_Fixed_Point_Definition, Delta_Sloc);
+      end if;
+
+      return Def_Node;
+   end P_Formal_Fixed_Point_Definition;
+
+   ----------------------------------------------------
+   -- 12.5.2  Formal Ordinary Fixed Point Definition --
+   ----------------------------------------------------
+
+   --  Parsed by P_Formal_Fixed_Point_Definition (12.5.2)
+
+   ---------------------------------------------------
+   -- 12.5.2  Formal Decimal Fixed Point Definition --
+   ---------------------------------------------------
+
+   --  Parsed by P_Formal_Fixed_Point_Definition (12.5.2)
+
+   ------------------------------------------
+   -- 12.5.3  Formal Array Type Definition --
+   ------------------------------------------
+
+   --  Parsed by P_Formal_Type_Definition (12.5)
+
+   -------------------------------------------
+   -- 12.5.4  Formal Access Type Definition --
+   -------------------------------------------
+
+   --  Parsed by P_Formal_Type_Definition (12.5)
+
+   -----------------------------------------
+   -- 12.6  Formal Subprogram Declaration --
+   -----------------------------------------
+
+   --  FORMAL_SUBPROGRAM_DECLARATION ::=
+   --    with SUBPROGRAM_SPECIFICATION [is SUBPROGRAM_DEFAULT];
+
+   --  SUBPROGRAM_DEFAULT ::= DEFAULT_NAME | <>
+
+   --  DEFAULT_NAME ::= NAME
+
+   --  The caller has checked that the initial tokens are WITH FUNCTION or
+   --  WITH PROCEDURE, and the initial WITH has been scanned out.
+
+   --  Note: we separate this into two procedures because the name is allowed
+   --  to be an operator symbol for a function, but not for a procedure.
+
+   --  Error recovery: cannot raise Error_Resync
+
+   function P_Formal_Subprogram_Declaration return Node_Id is
+      Def_Node : Node_Id;
+
+   begin
+      Def_Node := New_Node (N_Formal_Subprogram_Declaration, Prev_Token_Ptr);
+      Set_Specification (Def_Node, P_Subprogram_Specification);
+
+      if Token = Tok_Is then
+         T_Is; -- past IS, skip extra IS or ";"
+
+         if Token = Tok_Box then
+            Set_Box_Present (Def_Node, True);
+            Scan; -- past <>
+
+         else
+            Set_Default_Name (Def_Node, P_Name);
+         end if;
+
+      end if;
+
+      T_Semicolon;
+      return Def_Node;
+   end P_Formal_Subprogram_Declaration;
+
+   ------------------------------
+   -- 12.6  Subprogram Default --
+   ------------------------------
+
+   --  Parsed by P_Formal_Procedure_Declaration (12.6)
+
+   ------------------------
+   -- 12.6  Default Name --
+   ------------------------
+
+   --  Parsed by P_Formal_Procedure_Declaration (12.6)
+
+   --------------------------------------
+   -- 12.7  Formal Package Declaration --
+   --------------------------------------
+
+   --  FORMAL_PACKAGE_DECLARATION ::=
+   --    with package DEFINING_IDENTIFIER
+   --      is new generic_package_NAME FORMAL_PACKAGE_ACTUAL_PART;
+
+   --  FORMAL_PACKAGE_ACTUAL_PART ::=
+   --    (<>) | [GENERIC_ACTUAL_PART]
+
+   --  The caller has checked that the initial tokens are WITH PACKAGE,
+   --  and the initial WITH has been scanned out (so Token = Tok_Package).
+
+   --  Error recovery: cannot raise Error_Resync
+
+   function P_Formal_Package_Declaration return Node_Id is
+      Def_Node : Node_Id;
+      Scan_State : Saved_Scan_State;
+
+   begin
+      Def_Node := New_Node (N_Formal_Package_Declaration, Prev_Token_Ptr);
+      Scan; -- past PACKAGE
+      Set_Defining_Identifier (Def_Node, P_Defining_Identifier);
+      T_Is;
+      T_New;
+      Set_Name (Def_Node, P_Qualified_Simple_Name);
+
+      if Token = Tok_Left_Paren then
+         Save_Scan_State (Scan_State); -- at the left paren
+         Scan; -- past the left paren
+
+         if Token = Tok_Box then
+            Set_Box_Present (Def_Node, True);
+            Scan; -- past box
+            T_Right_Paren;
+
+         else
+            Restore_Scan_State (Scan_State); -- to the left paren
+            Set_Generic_Associations (Def_Node, P_Generic_Actual_Part_Opt);
+         end if;
+      end if;
+
+      T_Semicolon;
+      return Def_Node;
+   end P_Formal_Package_Declaration;
+
+   --------------------------------------
+   -- 12.7  Formal Package Actual Part --
+   --------------------------------------
+
+   --  Parsed by P_Formal_Package_Declaration (12.7)
+
+end Ch12;
diff --git a/gcc/ada/par-ch13.adb b/gcc/ada/par-ch13.adb
new file mode 100644 (file)
index 0000000..03bd7bf
--- /dev/null
@@ -0,0 +1,441 @@
+------------------------------------------------------------------------------
+--                                                                          --
+--                         GNAT COMPILER COMPONENTS                         --
+--                                                                          --
+--                             P A R . C H 1 3                              --
+--                                                                          --
+--                                 B o d y                                  --
+--                                                                          --
+--                            $Revision: 1.34 $
+--                                                                          --
+--          Copyright (C) 1992-2001 Free Software Foundation, Inc.          --
+--                                                                          --
+-- GNAT is free software;  you can  redistribute it  and/or modify it under --
+-- terms of the  GNU General Public License as published  by the Free Soft- --
+-- ware  Foundation;  either version 2,  or (at your option) any later ver- --
+-- sion.  GNAT is distributed in the hope that it will be useful, but WITH- --
+-- OUT 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  distributed with GNAT;  see file COPYING.  If not, write --
+-- to  the Free Software Foundation,  59 Temple Place - Suite 330,  Boston, --
+-- MA 02111-1307, USA.                                                      --
+--                                                                          --
+-- GNAT was originally developed  by the GNAT team at  New York University. --
+-- It is now maintained by Ada Core Technologies Inc (http://www.gnat.com). --
+--                                                                          --
+------------------------------------------------------------------------------
+
+pragma Style_Checks (All_Checks);
+--  Turn off subprogram body ordering check. Subprograms are in order
+--  by RM section rather than alphabetical
+
+separate (Par)
+package body Ch13 is
+
+   --  Local functions, used only in this chapter
+
+   function P_Component_Clause return Node_Id;
+   function P_Mod_Clause return Node_Id;
+
+   --------------------------------------------
+   -- 13.1  Representation Clause (also I.7) --
+   --------------------------------------------
+
+   --  REPRESENTATION_CLAUSE ::=
+   --    ATTRIBUTE_DEFINITION_CLAUSE
+   --  | ENUMERATION_REPRESENTATION_CLAUSE
+   --  | RECORD_REPRESENTATION_CLAUSE
+   --  | AT_CLAUSE
+
+   --  ATTRIBUTE_DEFINITION_CLAUSE ::=
+   --    for LOCAL_NAME'ATTRIBUTE_DESIGNATOR use EXPRESSION;
+   --  | for LOCAL_NAME'ATTRIBUTE_DESIGNATOR use NAME;
+
+   --  Note: in Ada 83, the expression must be a simple expression
+
+   --  AT_CLAUSE ::= for DIRECT_NAME use at EXPRESSION;
+
+   --  Note: in Ada 83, the expression must be a simple expression
+
+   --  ENUMERATION_REPRESENTATION_CLAUSE ::=
+   --    for first_subtype_LOCAL_NAME use ENUMERATION_AGGREGATE;
+
+   --  ENUMERATION_AGGREGATE ::= ARRAY_AGGREGATE
+
+   --  RECORD_REPRESENTATION_CLAUSE ::=
+   --    for first_subtype_LOCAL_NAME use
+   --      record [MOD_CLAUSE]
+   --        {COMPONENT_CLAUSE}
+   --      end record;
+
+   --  Note: for now we allow only a direct name as the local name in the
+   --  above constructs. This probably needs changing later on ???
+
+   --  The caller has checked that the initial token is FOR
+
+   --  Error recovery: cannot raise Error_Resync, if an error occurs,
+   --  the scan is repositioned past the next semicolon.
+
+   function P_Representation_Clause return Node_Id is
+      For_Loc         : Source_Ptr;
+      Name_Node       : Node_Id;
+      Prefix_Node     : Node_Id;
+      Attr_Name       : Name_Id;
+      Identifier_Node : Node_Id;
+      Rep_Clause_Node : Node_Id;
+      Expr_Node       : Node_Id;
+      Record_Items    : List_Id;
+
+   begin
+      For_Loc := Token_Ptr;
+      Scan; -- past FOR
+
+      --  Note that the name in a representation clause is always a simple
+      --  name, even in the attribute case, see AI-300 which made this so!
+
+      Identifier_Node := P_Identifier;
+
+      --  Check case of qualified name to give good error message
+
+      if Token = Tok_Dot then
+         Error_Msg_SC
+            ("representation clause requires simple name!");
+
+         loop
+            exit when Token /= Tok_Dot;
+            Scan; -- past dot
+            Discard_Junk_Node (P_Identifier);
+         end loop;
+      end if;
+
+      --  Attribute Definition Clause
+
+      if Token = Tok_Apostrophe then
+
+         --  Allow local names of the form a'b'.... This enables
+         --  us to parse class-wide streams attributes correctly.
+
+         Name_Node := Identifier_Node;
+         while Token = Tok_Apostrophe loop
+
+            Scan; -- past apostrophe
+
+            Identifier_Node := Token_Node;
+            Attr_Name := No_Name;
+
+            if Token = Tok_Identifier then
+               Attr_Name := Token_Name;
+
+               if not Is_Attribute_Name (Attr_Name) then
+                  Signal_Bad_Attribute;
+               end if;
+
+               if Style_Check then
+                  Style.Check_Attribute_Name (False);
+               end if;
+
+            --  Here for case of attribute designator is not an identifier
+
+            else
+               if Token = Tok_Delta then
+                  Attr_Name := Name_Delta;
+
+               elsif Token = Tok_Digits then
+                  Attr_Name := Name_Digits;
+
+               elsif Token = Tok_Access then
+                  Attr_Name := Name_Access;
+
+               else
+                  Error_Msg_AP ("attribute designator expected");
+                  raise Error_Resync;
+               end if;
+
+               if Style_Check then
+                  Style.Check_Attribute_Name (True);
+               end if;
+            end if;
+
+            --  We come here with an OK attribute scanned, and the
+            --  corresponding Attribute identifier node stored in Ident_Node.
+
+            Prefix_Node := Name_Node;
+            Name_Node := New_Node (N_Attribute_Reference, Prev_Token_Ptr);
+            Set_Prefix (Name_Node, Prefix_Node);
+            Set_Attribute_Name (Name_Node, Attr_Name);
+            Scan;
+         end loop;
+
+         Rep_Clause_Node := New_Node (N_Attribute_Definition_Clause, For_Loc);
+         Set_Name (Rep_Clause_Node, Prefix_Node);
+         Set_Chars (Rep_Clause_Node, Attr_Name);
+         T_Use;
+
+         Expr_Node := P_Expression_No_Right_Paren;
+         Check_Simple_Expression_In_Ada_83 (Expr_Node);
+         Set_Expression (Rep_Clause_Node, Expr_Node);
+
+      else
+         TF_Use;
+         Rep_Clause_Node := Empty;
+
+         --  AT follows USE (At Clause)
+
+         if Token = Tok_At then
+            Scan; -- past AT
+            Rep_Clause_Node := New_Node (N_At_Clause, For_Loc);
+            Set_Identifier (Rep_Clause_Node, Identifier_Node);
+            Expr_Node := P_Expression_No_Right_Paren;
+            Check_Simple_Expression_In_Ada_83 (Expr_Node);
+            Set_Expression (Rep_Clause_Node, Expr_Node);
+
+         --  RECORD follows USE (Record Representation Clause)
+
+         elsif Token = Tok_Record then
+            Record_Items := P_Pragmas_Opt;
+            Rep_Clause_Node :=
+              New_Node (N_Record_Representation_Clause, For_Loc);
+            Set_Identifier (Rep_Clause_Node, Identifier_Node);
+
+            Push_Scope_Stack;
+            Scope.Table (Scope.Last).Etyp := E_Record;
+            Scope.Table (Scope.Last).Ecol := Start_Column;
+            Scope.Table (Scope.Last).Sloc := Token_Ptr;
+            Scan; -- past RECORD
+            Record_Items := P_Pragmas_Opt;
+
+            --  Possible Mod Clause
+
+            if Token = Tok_At then
+               Set_Mod_Clause (Rep_Clause_Node, P_Mod_Clause);
+               Set_Pragmas_Before (Mod_Clause (Rep_Clause_Node), Record_Items);
+               Record_Items := P_Pragmas_Opt;
+            end if;
+
+            if No (Record_Items) then
+               Record_Items := New_List;
+            end if;
+
+            Set_Component_Clauses (Rep_Clause_Node, Record_Items);
+
+            --  Loop through component clauses
+
+            loop
+               if Token not in Token_Class_Name then
+                  exit when Check_End;
+               end if;
+
+               Append (P_Component_Clause, Record_Items);
+               P_Pragmas_Opt (Record_Items);
+            end loop;
+
+         --  Left paren follows USE (Enumeration Representation Clause)
+
+         elsif Token = Tok_Left_Paren then
+            Rep_Clause_Node :=
+              New_Node (N_Enumeration_Representation_Clause, For_Loc);
+            Set_Identifier (Rep_Clause_Node, Identifier_Node);
+            Set_Array_Aggregate (Rep_Clause_Node, P_Aggregate);
+
+         --  Some other token follows FOR (invalid representation clause)
+
+         else
+            Error_Msg_SC ("invalid representation clause");
+            raise Error_Resync;
+         end if;
+      end if;
+
+      TF_Semicolon;
+      return Rep_Clause_Node;
+
+   exception
+      when Error_Resync =>
+         Resync_Past_Semicolon;
+         return Error;
+
+   end P_Representation_Clause;
+
+   ----------------------
+   -- 13.1  Local Name --
+   ----------------------
+
+   --  Local name is always parsed by its parent. In the case of its use in
+   --  pragmas, the check for a local name is handled in Par.Prag and allows
+   --  all the possible forms of local name. For the uses in chapter 13, we
+   --  currently only allow a direct name, but this should probably change???
+
+   ---------------------------
+   -- 13.1  At Clause (I.7) --
+   ---------------------------
+
+   --  Parsed by P_Representation_Clause (13.1)
+
+   ---------------------------------------
+   -- 13.3  Attribute Definition Clause --
+   ---------------------------------------
+
+   --  Parsed by P_Representation_Clause (13.1)
+
+   ---------------------------------------------
+   -- 13.4  Enumeration Representation Clause --
+   ---------------------------------------------
+
+   --  Parsed by P_Representation_Clause (13.1)
+
+   ---------------------------------
+   -- 13.4  Enumeration Aggregate --
+   ---------------------------------
+
+   --  Parsed by P_Representation_Clause (13.1)
+
+   ------------------------------------------
+   -- 13.5.1  Record Representation Clause --
+   ------------------------------------------
+
+   --  Parsed by P_Representation_Clause (13.1)
+
+   ------------------------------
+   -- 13.5.1  Mod Clause (I.8) --
+   ------------------------------
+
+   --  MOD_CLAUSE ::= at mod static_EXPRESSION;
+
+   --  Note: in Ada 83, the expression must be a simple expression
+
+   --  The caller has checked that the initial Token is AT
+
+   --  Error recovery: cannot raise Error_Resync
+
+   --  Note: the caller is responsible for setting the Pragmas_Before field
+
+   function P_Mod_Clause return Node_Id is
+      Mod_Node  : Node_Id;
+      Expr_Node : Node_Id;
+
+   begin
+      Mod_Node := New_Node (N_Mod_Clause, Token_Ptr);
+      Scan; -- past AT
+      T_Mod;
+      Expr_Node := P_Expression_No_Right_Paren;
+      Check_Simple_Expression_In_Ada_83 (Expr_Node);
+      Set_Expression (Mod_Node, Expr_Node);
+      TF_Semicolon;
+      return Mod_Node;
+   end P_Mod_Clause;
+
+   ------------------------------
+   -- 13.5.1  Component Clause --
+   ------------------------------
+
+   --  COMPONENT_CLAUSE ::=
+   --    COMPONENT_CLAUSE_COMPONENT_NAME at POSITION
+   --      range FIRST_BIT .. LAST_BIT;
+
+   --  COMPONENT_CLAUSE_COMPONENT_NAME ::=
+   --    component_DIRECT_NAME
+   --  | component_DIRECT_NAME'ATTRIBUTE_DESIGNATOR
+   --  | FIRST_SUBTYPE_DIRECT_NAME'ATTRIBUTE_DESIGNATOR
+
+   --  POSITION ::= static_EXPRESSION
+
+   --  Note: in Ada 83, the expression must be a simple expression
+
+   --  FIRST_BIT ::= static_SIMPLE_EXPRESSION
+   --  LAST_BIT ::= static_SIMPLE_EXPRESSION
+
+   --  Note: the AARM V2.0 grammar has an error at this point, it uses
+   --  EXPRESSION instead of SIMPLE_EXPRESSION for FIRST_BIT and LAST_BIT
+
+   --  Error recovery: cannot raise Error_Resync
+
+   function P_Component_Clause return Node_Id is
+      Component_Node : Node_Id;
+      Comp_Name      : Node_Id;
+      Expr_Node      : Node_Id;
+
+   begin
+      Component_Node := New_Node (N_Component_Clause, Token_Ptr);
+      Comp_Name := P_Name;
+
+      if Nkind (Comp_Name) = N_Identifier
+        or else Nkind (Comp_Name) = N_Attribute_Reference
+      then
+         Set_Component_Name (Component_Node, Comp_Name);
+      else
+         Error_Msg_N
+           ("component name must be direct name or attribute", Comp_Name);
+         Set_Component_Name (Component_Node, Error);
+      end if;
+
+      Set_Sloc (Component_Node, Token_Ptr);
+      T_At;
+      Expr_Node := P_Expression_No_Right_Paren;
+      Check_Simple_Expression_In_Ada_83 (Expr_Node);
+      Set_Position (Component_Node, Expr_Node);
+      T_Range;
+      Expr_Node := P_Expression_No_Right_Paren;
+      Check_Simple_Expression_In_Ada_83 (Expr_Node);
+      Set_First_Bit (Component_Node, Expr_Node);
+      T_Dot_Dot;
+      Expr_Node := P_Expression_No_Right_Paren;
+      Check_Simple_Expression_In_Ada_83 (Expr_Node);
+      Set_Last_Bit (Component_Node, Expr_Node);
+      TF_Semicolon;
+      return Component_Node;
+   end P_Component_Clause;
+
+   ----------------------
+   -- 13.5.1  Position --
+   ----------------------
+
+   --  Parsed by P_Component_Clause (13.5.1)
+
+   -----------------------
+   -- 13.5.1  First Bit --
+   -----------------------
+
+   --  Parsed by P_Component_Clause (13.5.1)
+
+   ----------------------
+   -- 13.5.1  Last Bit --
+   ----------------------
+
+   --  Parsed by P_Component_Clause (13.5.1)
+
+   --------------------------
+   -- 13.8  Code Statement --
+   --------------------------
+
+   --  CODE_STATEMENT ::= QUALIFIED_EXPRESSION
+
+   --  On entry the caller has scanned the SUBTYPE_MARK (passed in as the
+   --  single argument, and the scan points to the apostrophe.
+
+   --  Error recovery: can raise Error_Resync
+
+   function P_Code_Statement (Subtype_Mark : Node_Id) return Node_Id is
+      Node1 : Node_Id;
+
+   begin
+      Scan; -- past apostrophe
+
+      --  If left paren, then we have a possible code statement
+
+      if Token = Tok_Left_Paren then
+         Node1 := New_Node (N_Code_Statement, Sloc (Subtype_Mark));
+         Set_Expression (Node1, P_Qualified_Expression (Subtype_Mark));
+         TF_Semicolon;
+         return Node1;
+
+      --  Otherwise we have an illegal range attribute. Note that P_Name
+      --  ensures that Token = Tok_Range is the only possibility left here.
+
+      else -- Token = Tok_Range
+         Error_Msg_SC ("RANGE attribute illegal here!");
+         raise Error_Resync;
+      end if;
+
+   end P_Code_Statement;
+
+end Ch13;
diff --git a/gcc/ada/par-ch2.adb b/gcc/ada/par-ch2.adb
new file mode 100644 (file)
index 0000000..0eeacea
--- /dev/null
@@ -0,0 +1,405 @@
+------------------------------------------------------------------------------
+--                                                                          --
+--                         GNAT COMPILER COMPONENTS                         --
+--                                                                          --
+--                              P A R . C H 2                               --
+--                                                                          --
+--                                 B o d y                                  --
+--                                                                          --
+--                            $Revision: 1.35 $                             --
+--                                                                          --
+--          Copyright (C) 1992-2001 Free Software Foundation, Inc.          --
+--                                                                          --
+-- GNAT is free software;  you can  redistribute it  and/or modify it under --
+-- terms of the  GNU General Public License as published  by the Free Soft- --
+-- ware  Foundation;  either version 2,  or (at your option) any later ver- --
+-- sion.  GNAT is distributed in the hope that it will be useful, but WITH- --
+-- OUT 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  distributed with GNAT;  see file COPYING.  If not, write --
+-- to  the Free Software Foundation,  59 Temple Place - Suite 330,  Boston, --
+-- MA 02111-1307, USA.                                                      --
+--                                                                          --
+-- GNAT was originally developed  by the GNAT team at  New York University. --
+-- It is now maintained by Ada Core Technologies Inc (http://www.gnat.com). --
+--                                                                          --
+------------------------------------------------------------------------------
+
+pragma Style_Checks (All_Checks);
+--  Turn off subprogram body ordering check. Subprograms are in order
+--  by RM section rather than alphabetical
+
+separate (Par)
+package body Ch2 is
+
+   --  Local functions, used only in this chapter
+
+   function P_Pragma_Argument_Association return Node_Id;
+
+   ---------------------
+   -- 2.3  Identifier --
+   ---------------------
+
+   --  IDENTIFIER ::= LETTER {[UNDERLINE] LETTER_OR_DIGIT}
+
+   --  LETTER_OR_DIGIT ::= IDENTIFIER_LETTER | DIGIT
+
+   --  An IDENTIFIER shall not be a reserved word
+
+   --  Error recovery: can raise Error_Resync (cannot return Error)
+
+   function P_Identifier return Node_Id is
+      Ident_Node : Node_Id;
+
+   begin
+      --  All set if we do indeed have an identifier
+
+      if Token = Tok_Identifier then
+         Ident_Node := Token_Node;
+         Scan; -- past Identifier
+         return Ident_Node;
+
+      --  If we have a reserved identifier, manufacture an identifier with
+      --  a corresponding name after posting an appropriate error message
+
+      elsif Is_Reserved_Identifier then
+         Scan_Reserved_Identifier (Force_Msg => False);
+         Ident_Node := Token_Node;
+         Scan; -- past the node
+         return Ident_Node;
+
+      --  Otherwise we have junk that cannot be interpreted as an identifier
+
+      else
+         T_Identifier; -- to give message
+         raise Error_Resync;
+      end if;
+   end P_Identifier;
+
+   --------------------------
+   -- 2.3  Letter Or Digit --
+   --------------------------
+
+   --  Parsed by P_Identifier (2.3)
+
+   --------------------------
+   -- 2.4  Numeric Literal --
+   --------------------------
+
+   --  NUMERIC_LITERAL ::= DECIMAL_LITERAL | BASED_LITERAL
+
+   --  Numeric literal is returned by the scanner as either
+   --  Tok_Integer_Literal or Tok_Real_Literal
+
+   ----------------------------
+   -- 2.4.1  Decimal Literal --
+   ----------------------------
+
+   --  DECIMAL_LITERAL ::= NUMERAL [.NUMERAL] [EXPONENT]
+
+   --  Handled by scanner as part of numeric lIteral handing (see 2.4)
+
+   --------------------
+   -- 2.4.1  Numeral --
+   --------------------
+
+   --  NUMERAL ::= DIGIT {[UNDERLINE] DIGIT}
+
+   --  Handled by scanner as part of numeric literal handling (see 2.4)
+
+   ---------------------
+   -- 2.4.1  Exponent --
+   ---------------------
+
+   --  EXPONENT ::= E [+] NUMERAL | E - NUMERAL
+
+   --  Handled by scanner as part of numeric literal handling (see 2.4)
+
+   --------------------------
+   -- 2.4.2  Based Literal --
+   --------------------------
+
+   --  BASED_LITERAL ::=
+   --   BASE # BASED_NUMERAL [.BASED_NUMERAL] # [EXPONENT]
+
+   --  Handled by scanner as part of numeric literal handling (see 2.4)
+
+   -----------------
+   -- 2.4.2  Base --
+   -----------------
+
+   --  BASE ::= NUMERAL
+
+   --  Handled by scanner as part of numeric literal handling (see 2.4)
+
+   --------------------------
+   -- 2.4.2  Based Numeral --
+   --------------------------
+
+   --  BASED_NUMERAL ::=
+   --    EXTENDED_DIGIT {[UNDERLINE] EXTENDED_DIGIT}
+
+   --  Handled by scanner as part of numeric literal handling (see 2.4)
+
+   ---------------------------
+   -- 2.4.2  Extended Digit --
+   ---------------------------
+
+   --  EXTENDED_DIGIT ::= DIGIT | A | B | C | D | E | F
+
+   --  Handled by scanner as part of numeric literal handling (see 2.4)
+
+   ----------------------------
+   -- 2.5  Character Literal --
+   ----------------------------
+
+   --  CHARACTER_LITERAL ::= ' GRAPHIC_CHARACTER '
+
+   --  Handled by the scanner and returned as Tok_Character_Literal
+
+   -------------------------
+   -- 2.6  String Literal --
+   -------------------------
+
+   --  STRING LITERAL ::= "{STRING_ELEMENT}"
+
+   --  Handled by the scanner and returned as Tok_Character_Literal
+   --  or if the string looks like an operator as Tok_Operator_Symbol.
+
+   -------------------------
+   -- 2.6  String Element --
+   -------------------------
+
+   --  STRING_ELEMENT ::= "" | non-quotation_mark_GRAPHIC_CHARACTER
+
+   --  A STRING_ELEMENT is either a pair of quotation marks ("),
+   --  or a single GRAPHIC_CHARACTER other than a quotation mark.
+
+   --  Handled by scanner as part of string literal handling (see 2.4)
+
+   ------------------
+   -- 2.7  Comment --
+   ------------------
+
+   --  A COMMENT starts with two adjacent hyphens and extends up to the
+   --  end of the line. A COMMENT may appear on any line of a program.
+
+   --  Handled by the scanner which simply skips past encountered comments
+
+   -----------------
+   -- 2.8  Pragma --
+   -----------------
+
+   --  PRAGMA ::= pragma IDENTIFIER
+   --    [(PRAGMA_ARGUMENT_ASSOCIATION {, PRAGMA_ARGUMENT_ASSOCIATION})];
+
+   --  The caller has checked that the initial token is PRAGMA
+
+   --  Error recovery: cannot raise Error_Resync
+
+   --  One special piece of processing is needed in this routine. As described
+   --  in the section on "Handling semicolon used in place of IS" in module
+   --  Parse, the parser detects the case of missing subprogram bodies to
+   --  allow recovery from this syntactic error. Pragma INTERFACE (and, for
+   --  Ada 95, pragma IMPORT) can appear in place of the body. The parser must
+   --  recognize the use of these two pragmas in this context, otherwise it
+   --  will think there are missing bodies, and try to change ; to IS, when
+   --  in fact the bodies ARE present, supplied by these pragmas.
+
+   function P_Pragma return Node_Id is
+
+      Interface_Check_Required : Boolean := False;
+      --  Set True if check of pragma INTERFACE is required
+
+      Import_Check_Required : Boolean := False;
+      --  Set True if check of pragma IMPORT is required
+
+      Arg_Count : Int := 0;
+      --  Number of argument associations processed
+
+      Pragma_Node   : Node_Id;
+      Pragma_Name   : Name_Id;
+      Semicolon_Loc : Source_Ptr;
+      Ident_Node    : Node_Id;
+      Assoc_Node    : Node_Id;
+
+   begin
+      Pragma_Node := New_Node (N_Pragma, Token_Ptr);
+      Scan; -- past PRAGMA
+      Pragma_Name := Token_Name;
+
+      if Style_Check then
+         Style.Check_Pragma_Name;
+      end if;
+
+      Ident_Node := P_Identifier;
+      Set_Chars (Pragma_Node, Pragma_Name);
+      Delete_Node (Ident_Node);
+
+      --  See if special INTERFACE/IMPORT check is required
+
+      if SIS_Entry_Active then
+         Interface_Check_Required := (Pragma_Name = Name_Interface);
+         Import_Check_Required    := (Pragma_Name = Name_Import);
+      else
+         Interface_Check_Required := False;
+         Import_Check_Required    := False;
+      end if;
+
+      --  Scan arguments. We assume that arguments are present if there is
+      --  a left paren, or if a semicolon is missing and there is another
+      --  token on the same line as the pragma name.
+
+      if Token = Tok_Left_Paren
+        or else (Token /= Tok_Semicolon
+                   and then not Token_Is_At_Start_Of_Line)
+      then
+         Set_Pragma_Argument_Associations (Pragma_Node, New_List);
+         T_Left_Paren;
+
+         loop
+            Arg_Count := Arg_Count + 1;
+            Assoc_Node := P_Pragma_Argument_Association;
+
+            if Arg_Count = 2
+              and then (Interface_Check_Required or else Import_Check_Required)
+            then
+               --  Here is where we cancel the SIS active status if this pragma
+               --  supplies a body for the currently active subprogram spec.
+
+               if Nkind (Expression (Assoc_Node)) in N_Direct_Name
+                 and then Chars (Expression (Assoc_Node)) = Chars (SIS_Labl)
+               then
+                  SIS_Entry_Active := False;
+               end if;
+            end if;
+
+            Append (Assoc_Node, Pragma_Argument_Associations (Pragma_Node));
+            exit when Token /= Tok_Comma;
+            Scan; -- past comma
+         end loop;
+
+         T_Right_Paren;
+      end if;
+
+      Semicolon_Loc := Token_Ptr;
+
+      if Token /= Tok_Semicolon then
+         T_Semicolon;
+         Resync_Past_Semicolon;
+      else
+         Scan; -- past semicolon
+      end if;
+
+      if Is_Pragma_Name (Chars (Pragma_Node)) then
+         return Par.Prag (Pragma_Node, Semicolon_Loc);
+
+      else
+         --  Unrecognized pragma, warning generated in Sem_Prag
+
+         return Pragma_Node;
+      end if;
+
+   exception
+      when Error_Resync =>
+         Resync_Past_Semicolon;
+         return Error;
+
+   end P_Pragma;
+
+   --  This routine is called if a pragma is encountered in an inappropriate
+   --  position, the pragma is scanned out and control returns to continue.
+
+   --  The caller has checked that the initial token is pragma
+
+   --  Error recovery: cannot raise Error_Resync
+
+   procedure P_Pragmas_Misplaced is
+   begin
+      while Token = Tok_Pragma loop
+         Error_Msg_SC ("pragma not allowed here");
+         Discard_Junk_Node (P_Pragma);
+      end loop;
+   end P_Pragmas_Misplaced;
+
+   --  This function is called to scan out an optional sequence of pragmas.
+   --  If no pragmas are found, then No_List is returned.
+
+   --  Error recovery: Cannot raise Error_Resync
+
+   function P_Pragmas_Opt return List_Id is
+      L : List_Id;
+
+   begin
+      if Token = Tok_Pragma then
+         L := New_List;
+         P_Pragmas_Opt (L);
+         return L;
+
+      else
+         return No_List;
+      end if;
+   end P_Pragmas_Opt;
+
+   --  This procedure is called to scan out an optional sequence of pragmas.
+   --  Any pragmas found are appended to the list provided as an argument.
+
+   --  Error recovery: Cannot raise Error_Resync
+
+   procedure P_Pragmas_Opt (List : List_Id) is
+      P : Node_Id;
+
+   begin
+      while Token = Tok_Pragma loop
+         P := P_Pragma;
+
+         if Chars (P) = Name_Assert or else Chars (P) = Name_Debug then
+            Error_Msg_Name_1 := Chars (P);
+            Error_Msg_N
+              ("pragma% must be in declaration/statement context", P);
+         else
+            Append (P, List);
+         end if;
+      end loop;
+   end P_Pragmas_Opt;
+
+   --------------------------------------
+   -- 2.8  Pragma_Argument Association --
+   --------------------------------------
+
+   --  PRAGMA_ARGUMENT_ASSOCIATION ::=
+   --    [pragma_argument_IDENTIFIER =>] NAME
+   --  | [pragma_argument_IDENTIFIER =>] EXPRESSION
+
+   --  Error recovery: cannot raise Error_Resync
+
+   function P_Pragma_Argument_Association return Node_Id is
+      Scan_State      : Saved_Scan_State;
+      Pragma_Arg_Node : Node_Id;
+      Identifier_Node : Node_Id;
+
+   begin
+      Pragma_Arg_Node := New_Node (N_Pragma_Argument_Association, Token_Ptr);
+      Set_Chars (Pragma_Arg_Node, No_Name);
+
+      if Token = Tok_Identifier then
+         Identifier_Node := Token_Node;
+         Save_Scan_State (Scan_State); -- at Identifier
+         Scan; -- past Identifier
+
+         if Token = Tok_Arrow then
+            Scan; -- past arrow
+            Set_Chars (Pragma_Arg_Node, Chars (Identifier_Node));
+            Delete_Node (Identifier_Node);
+         else
+            Restore_Scan_State (Scan_State); -- to Identifier
+         end if;
+      end if;
+
+      Set_Expression (Pragma_Arg_Node, P_Expression);
+      return Pragma_Arg_Node;
+
+   end P_Pragma_Argument_Association;
+
+end Ch2;
diff --git a/gcc/ada/par-ch3.adb b/gcc/ada/par-ch3.adb
new file mode 100644 (file)
index 0000000..937f02d
--- /dev/null
@@ -0,0 +1,3724 @@
+------------------------------------------------------------------------------
+--                                                                          --
+--                         GNAT COMPILER COMPONENTS                         --
+--                                                                          --
+--                              P A R . C H 3                               --
+--                                                                          --
+--                                 B o d y                                  --
+--                                                                          --
+--                            $Revision: 1.148 $
+--                                                                          --
+--          Copyright (C) 1992-2001, Free Software Foundation, Inc.         --
+--                                                                          --
+-- GNAT is free software;  you can  redistribute it  and/or modify it under --
+-- terms of the  GNU General Public License as published  by the Free Soft- --
+-- ware  Foundation;  either version 2,  or (at your option) any later ver- --
+-- sion.  GNAT is distributed in the hope that it will be useful, but WITH- --
+-- OUT 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  distributed with GNAT;  see file COPYING.  If not, write --
+-- to  the Free Software Foundation,  59 Temple Place - Suite 330,  Boston, --
+-- MA 02111-1307, USA.                                                      --
+--                                                                          --
+-- GNAT was originally developed  by the GNAT team at  New York University. --
+-- It is now maintained by Ada Core Technologies Inc (http://www.gnat.com). --
+--                                                                          --
+------------------------------------------------------------------------------
+
+pragma Style_Checks (All_Checks);
+--  Turn off subprogram body ordering check. Subprograms are in order
+--  by RM section rather than alphabetical
+
+with Sinfo.CN; use Sinfo.CN;
+
+separate (Par)
+
+package body Ch3 is
+
+   -----------------------
+   -- Local Subprograms --
+   -----------------------
+
+   function P_Component_List                               return Node_Id;
+   function P_Defining_Character_Literal                   return Node_Id;
+   function P_Delta_Constraint                             return Node_Id;
+   function P_Derived_Type_Def_Or_Private_Ext_Decl         return Node_Id;
+   function P_Digits_Constraint                            return Node_Id;
+   function P_Discriminant_Association                     return Node_Id;
+   function P_Enumeration_Literal_Specification            return Node_Id;
+   function P_Enumeration_Type_Definition                  return Node_Id;
+   function P_Fixed_Point_Definition                       return Node_Id;
+   function P_Floating_Point_Definition                    return Node_Id;
+   function P_Index_Or_Discriminant_Constraint             return Node_Id;
+   function P_Real_Range_Specification_Opt                 return Node_Id;
+   function P_Subtype_Declaration                          return Node_Id;
+   function P_Type_Declaration                             return Node_Id;
+   function P_Modular_Type_Definition                      return Node_Id;
+   function P_Variant                                      return Node_Id;
+   function P_Variant_Part                                 return Node_Id;
+
+   procedure P_Declarative_Items
+     (Decls   : List_Id;
+      Done    : out Boolean;
+      In_Spec : Boolean);
+   --  Scans out a single declarative item, or, in the case of a declaration
+   --  with a list of identifiers, a list of declarations, one for each of
+   --  the identifiers in the list. The declaration or declarations scanned
+   --  are appended to the given list. Done indicates whether or not there
+   --  may be additional declarative items to scan. If Done is True, then
+   --  a decision has been made that there are no more items to scan. If
+   --  Done is False, then there may be additional declarations to scan.
+   --  In_Spec is true if we are scanning a package declaration, and is used
+   --  to generate an appropriate message if a statement is encountered in
+   --  such a context.
+
+   procedure P_Identifier_Declarations
+     (Decls   : List_Id;
+      Done    : out Boolean;
+      In_Spec : Boolean);
+   --  Scans out a set of declarations for an identifier or list of
+   --  identifiers, and appends them to the given list. The parameters have
+   --  the same significance as for P_Declarative_Items.
+
+   procedure Statement_When_Declaration_Expected
+     (Decls   : List_Id;
+      Done    : out Boolean;
+      In_Spec : Boolean);
+   --  Called when a statement is found at a point where a declaration was
+   --  expected. The parameters are as described for P_Declarative_Items.
+
+   procedure Set_Declaration_Expected;
+   --  Posts a "declaration expected" error messages at the start of the
+   --  current token, and if this is the first such message issued, saves
+   --  the message id in Missing_Begin_Msg, for possible later replacement.
+
+   -------------------
+   -- Init_Expr_Opt --
+   -------------------
+
+   function Init_Expr_Opt (P : Boolean := False) return Node_Id is
+   begin
+      if Token = Tok_Colon_Equal
+        or else Token = Tok_Equal
+        or else Token = Tok_Colon
+        or else Token = Tok_Is
+      then
+         null;
+
+      --  One other possibility. If we have a literal followed by a semicolon,
+      --  we assume that we have a missing colon-equal.
+
+      elsif Token in Token_Class_Literal then
+         declare
+            Scan_State : Saved_Scan_State;
+
+         begin
+            Save_Scan_State (Scan_State);
+            Scan; -- past literal or identifier
+
+            if Token = Tok_Semicolon then
+               Restore_Scan_State (Scan_State);
+            else
+               Restore_Scan_State (Scan_State);
+               return Empty;
+            end if;
+         end;
+
+      --  Otherwise we definitely have no initialization expression
+
+      else
+         return Empty;
+      end if;
+
+      --  Merge here if we have an initialization expression
+
+      T_Colon_Equal;
+
+      if P then
+         return P_Expression;
+      else
+         return P_Expression_No_Right_Paren;
+      end if;
+   end Init_Expr_Opt;
+
+   ----------------------------
+   -- 3.1  Basic Declaration --
+   ----------------------------
+
+   --  Parsed by P_Basic_Declarative_Items (3.9)
+
+   ------------------------------
+   -- 3.1  Defining Identifier --
+   ------------------------------
+
+   --  DEFINING_IDENTIFIER ::= IDENTIFIER
+
+   --  Error recovery: can raise Error_Resync
+
+   function P_Defining_Identifier return Node_Id is
+      Ident_Node : Node_Id;
+
+   begin
+      --  Scan out the identifier. Note that this code is essentially identical
+      --  to P_Identifier, except that in the call to Scan_Reserved_Identifier
+      --  we set Force_Msg to True, since we want at least one message for each
+      --  separate declaration (but not use) of a reserved identifier.
+
+      if Token = Tok_Identifier then
+         null;
+
+      --  If we have a reserved identifier, manufacture an identifier with
+      --  a corresponding name after posting an appropriate error message
+
+      elsif Is_Reserved_Identifier then
+         Scan_Reserved_Identifier (Force_Msg => True);
+
+      --  Otherwise we have junk that cannot be interpreted as an identifier
+
+      else
+         T_Identifier; -- to give message
+         raise Error_Resync;
+      end if;
+
+      Ident_Node := Token_Node;
+      Scan; -- past the reserved identifier
+
+      if Ident_Node /= Error then
+         Change_Identifier_To_Defining_Identifier (Ident_Node);
+      end if;
+
+      return Ident_Node;
+   end P_Defining_Identifier;
+
+   -----------------------------
+   -- 3.2.1  Type Declaration --
+   -----------------------------
+
+   --  TYPE_DECLARATION ::=
+   --    FULL_TYPE_DECLARATION
+   --  | INCOMPLETE_TYPE_DECLARATION
+   --  | PRIVATE_TYPE_DECLARATION
+   --  | PRIVATE_EXTENSION_DECLARATION
+
+   --  FULL_TYPE_DECLARATION ::=
+   --    type DEFINING_IDENTIFIER [KNOWN_DISCRIMINANT_PART] is TYPE_DEFINITION;
+   --  | CONCURRENT_TYPE_DECLARATION
+
+   --  INCOMPLETE_TYPE_DECLARATION ::=
+   --    type DEFINING_IDENTIFIER [DISCRIMINANT_PART];
+
+   --  PRIVATE_TYPE_DECLARATION ::=
+   --    type DEFINING_IDENTIFIER [DISCRIMINANT_PART]
+   --      is [abstract] [tagged] [limited] private;
+
+   --  PRIVATE_EXTENSION_DECLARATION ::=
+   --    type DEFINING_IDENTIFIER [DISCRIMINANT_PART] is
+   --      [abstract] new ancestor_SUBTYPE_INDICATION with private;
+
+   --  TYPE_DEFINITION ::=
+   --    ENUMERATION_TYPE_DEFINITION  | INTEGER_TYPE_DEFINITION
+   --  | REAL_TYPE_DEFINITION         | ARRAY_TYPE_DEFINITION
+   --  | RECORD_TYPE_DEFINITION       | ACCESS_TYPE_DEFINITION
+   --  | DERIVED_TYPE_DEFINITION
+
+   --  INTEGER_TYPE_DEFINITION ::=
+   --    SIGNED_INTEGER_TYPE_DEFINITION
+   --    MODULAR_TYPE_DEFINITION
+
+   --  Error recovery: can raise Error_Resync
+
+   --  Note: The processing for full type declaration, incomplete type
+   --  declaration, private type declaration and type definition is
+   --  included in this function. The processing for concurrent type
+   --  declarations is NOT here, but rather in chapter 9 (i.e. this
+   --  function handles only declarations starting with TYPE).
+
+   function P_Type_Declaration return Node_Id is
+      Type_Loc         : Source_Ptr;
+      Type_Start_Col   : Column_Number;
+      Ident_Node       : Node_Id;
+      Decl_Node        : Node_Id;
+      Discr_List       : List_Id;
+      Unknown_Dis      : Boolean;
+      Discr_Sloc       : Source_Ptr;
+      Abstract_Present : Boolean;
+      Abstract_Loc     : Source_Ptr;
+      End_Labl         : Node_Id;
+
+      Typedef_Node : Node_Id;
+      --  Normally holds type definition, except in the case of a private
+      --  extension declaration, in which case it holds the declaration itself
+
+   begin
+      Type_Loc := Token_Ptr;
+      Type_Start_Col := Start_Column;
+      T_Type;
+      Ident_Node := P_Defining_Identifier;
+      Discr_Sloc := Token_Ptr;
+
+      if P_Unknown_Discriminant_Part_Opt then
+         Unknown_Dis := True;
+         Discr_List := No_List;
+      else
+         Unknown_Dis := False;
+         Discr_List := P_Known_Discriminant_Part_Opt;
+      end if;
+
+      --  Incomplete type declaration. We complete the processing for this
+      --  case here and return the resulting incomplete type declaration node
+
+      if Token = Tok_Semicolon then
+         Scan; -- past ;
+         Decl_Node := New_Node (N_Incomplete_Type_Declaration, Type_Loc);
+         Set_Defining_Identifier (Decl_Node, Ident_Node);
+         Set_Unknown_Discriminants_Present (Decl_Node, Unknown_Dis);
+         Set_Discriminant_Specifications (Decl_Node, Discr_List);
+         return Decl_Node;
+
+      else
+         Decl_Node := Empty;
+      end if;
+
+      --  Full type declaration or private type declaration, must have IS
+
+      if Token = Tok_Equal then
+         TF_Is;
+         Scan; -- past = used in place of IS
+
+      elsif Token = Tok_Renames then
+         Error_Msg_SC ("RENAMES should be IS");
+         Scan; -- past RENAMES used in place of IS
+
+      else
+         TF_Is;
+      end if;
+
+      --  First an error check, if we have two identifiers in a row, a likely
+      --  possibility is that the first of the identifiers is an incorrectly
+      --  spelled keyword.
+
+      if Token = Tok_Identifier then
+         declare
+            SS : Saved_Scan_State;
+            I2 : Boolean;
+
+         begin
+            Save_Scan_State (SS);
+            Scan; -- past initial identifier
+            I2 := (Token = Tok_Identifier);
+            Restore_Scan_State (SS);
+
+            if I2
+              and then
+                (Bad_Spelling_Of (Tok_Abstract) or else
+                 Bad_Spelling_Of (Tok_Access)   or else
+                 Bad_Spelling_Of (Tok_Aliased)  or else
+                 Bad_Spelling_Of (Tok_Constant))
+            then
+               null;
+            end if;
+         end;
+      end if;
+
+      --  Check for misuse of Ada 95 keyword abstract in Ada 83 mode
+
+      if Token_Name = Name_Abstract then
+         Check_95_Keyword (Tok_Abstract, Tok_Tagged);
+         Check_95_Keyword (Tok_Abstract, Tok_New);
+      end if;
+
+      --  Check cases of misuse of ABSTRACT
+
+      if Token = Tok_Abstract then
+         Abstract_Present := True;
+         Abstract_Loc     := Token_Ptr;
+         Scan; -- past ABSTRACT
+
+         if Token = Tok_Limited
+           or else Token = Tok_Private
+           or else Token = Tok_Record
+           or else Token = Tok_Null
+         then
+            Error_Msg_AP ("TAGGED expected");
+         end if;
+
+      else
+         Abstract_Present := False;
+         Abstract_Loc     := No_Location;
+      end if;
+
+      --  Check for misuse of Ada 95 keyword Tagged
+
+      if Token_Name = Name_Tagged then
+         Check_95_Keyword (Tok_Tagged, Tok_Private);
+         Check_95_Keyword (Tok_Tagged, Tok_Limited);
+         Check_95_Keyword (Tok_Tagged, Tok_Record);
+      end if;
+
+      --  Special check for misuse of Aliased
+
+      if Token = Tok_Aliased or else Token_Name = Name_Aliased then
+         Error_Msg_SC ("ALIASED not allowed in type definition");
+         Scan; -- past ALIASED
+      end if;
+
+      --  The following procesing deals with either a private type declaration
+      --  or a full type declaration. In the private type case, we build the
+      --  N_Private_Type_Declaration node, setting its Tagged_Present and
+      --  Limited_Present flags, on encountering the Private keyword, and
+      --  leave Typedef_Node set to Empty. For the full type declaration
+      --  case, Typedef_Node gets set to the type definition.
+
+      Typedef_Node := Empty;
+
+      --  Switch on token following the IS. The loop normally runs once. It
+      --  only runs more than once if an error is detected, to try again after
+      --  detecting and fixing up the error.
+
+      loop
+         case Token is
+
+            when Tok_Access =>
+               Typedef_Node := P_Access_Type_Definition;
+               TF_Semicolon;
+               exit;
+
+            when Tok_Array =>
+               Typedef_Node := P_Array_Type_Definition;
+               TF_Semicolon;
+               exit;
+
+            when Tok_Delta =>
+               Typedef_Node := P_Fixed_Point_Definition;
+               TF_Semicolon;
+               exit;
+
+            when Tok_Digits =>
+               Typedef_Node := P_Floating_Point_Definition;
+               TF_Semicolon;
+               exit;
+
+            when Tok_In =>
+               Ignore (Tok_In);
+
+            when Tok_Integer_Literal =>
+               T_Range;
+               Typedef_Node := P_Signed_Integer_Type_Definition;
+               TF_Semicolon;
+               exit;
+
+            when Tok_Null =>
+               Typedef_Node := P_Record_Definition;
+               TF_Semicolon;
+               exit;
+
+            when Tok_Left_Paren =>
+               Typedef_Node := P_Enumeration_Type_Definition;
+               TF_Semicolon;
+               exit;
+
+            when Tok_Mod =>
+               Typedef_Node := P_Modular_Type_Definition;
+               TF_Semicolon;
+               exit;
+
+            when Tok_New =>
+               Typedef_Node := P_Derived_Type_Def_Or_Private_Ext_Decl;
+               TF_Semicolon;
+               exit;
+
+            when Tok_Range =>
+               Typedef_Node := P_Signed_Integer_Type_Definition;
+               TF_Semicolon;
+               exit;
+
+            when Tok_Record =>
+               Typedef_Node := P_Record_Definition;
+
+               End_Labl :=
+                 Make_Identifier (Token_Ptr,
+                   Chars => Chars (Ident_Node));
+               Set_Comes_From_Source (End_Labl, False);
+
+               Set_End_Label (Typedef_Node, End_Labl);
+               TF_Semicolon;
+               exit;
+
+            when Tok_Tagged =>
+               Scan; -- past TAGGED
+
+               if Token = Tok_Abstract then
+                  Error_Msg_SC ("ABSTRACT must come before TAGGED");
+                  Abstract_Present := True;
+                  Abstract_Loc := Token_Ptr;
+                  Scan; -- past ABSTRACT
+               end if;
+
+               if Token = Tok_Limited then
+                  Scan; -- past LIMITED
+
+                  --  TAGGED LIMITED PRIVATE case
+
+                  if Token = Tok_Private then
+                     Decl_Node :=
+                       New_Node (N_Private_Type_Declaration, Type_Loc);
+                     Set_Tagged_Present (Decl_Node, True);
+                     Set_Limited_Present (Decl_Node, True);
+                     Scan; -- past PRIVATE
+
+                  --  TAGGED LIMITED RECORD
+
+                  else
+                     Typedef_Node := P_Record_Definition;
+                     Set_Tagged_Present (Typedef_Node, True);
+                     Set_Limited_Present (Typedef_Node, True);
+                  end if;
+
+               else
+                  --  TAGGED PRIVATE
+
+                  if Token = Tok_Private then
+                     Decl_Node :=
+                       New_Node (N_Private_Type_Declaration, Type_Loc);
+                     Set_Tagged_Present (Decl_Node, True);
+                     Scan; -- past PRIVATE
+
+                  --  TAGGED RECORD
+
+                  else
+                     Typedef_Node := P_Record_Definition;
+                     Set_Tagged_Present (Typedef_Node, True);
+                  end if;
+               end if;
+
+               TF_Semicolon;
+               exit;
+
+            when Tok_Private =>
+               Decl_Node := New_Node (N_Private_Type_Declaration, Type_Loc);
+               Scan; -- past PRIVATE
+               TF_Semicolon;
+               exit;
+
+            when Tok_Limited =>
+               Scan; -- past LIMITED
+
+               loop
+                  if Token = Tok_Tagged then
+                     Error_Msg_SC ("TAGGED must come before LIMITED");
+                     Scan; -- past TAGGED
+
+                  elsif Token = Tok_Abstract then
+                     Error_Msg_SC ("ABSTRACT must come before LIMITED");
+                     Scan; -- past ABSTRACT
+
+                  else
+                     exit;
+                  end if;
+               end loop;
+
+               --  LIMITED RECORD or LIMITED NULL RECORD
+
+               if Token = Tok_Record or else Token = Tok_Null then
+                  if Ada_83 then
+                     Error_Msg_SP
+                       ("(Ada 83) limited record declaration not allowed!");
+                  end if;
+
+                  Typedef_Node := P_Record_Definition;
+                  Set_Limited_Present (Typedef_Node, True);
+
+               --  LIMITED PRIVATE is the only remaining possibility here
+
+               else
+                  Decl_Node := New_Node (N_Private_Type_Declaration, Type_Loc);
+                  Set_Limited_Present (Decl_Node, True);
+                  T_Private; -- past PRIVATE (or complain if not there!)
+               end if;
+
+               TF_Semicolon;
+               exit;
+
+            --  Here we have an identifier after the IS, which is certainly
+            --  wrong and which might be one of several different mistakes.
+
+            when Tok_Identifier =>
+
+               --  First case, if identifier is on same line, then probably we
+               --  have something like "type X is Integer .." and the best
+               --  diagnosis is a missing NEW. Note: the missing new message
+               --  will be posted by P_Derived_Type_Def_Or_Private_Ext_Decl.
+
+               if not Token_Is_At_Start_Of_Line then
+                  Typedef_Node := P_Derived_Type_Def_Or_Private_Ext_Decl;
+                  TF_Semicolon;
+
+               --  If the identifier is at the start of the line, and is in the
+               --  same column as the type declaration itself then we consider
+               --  that we had a missing type definition on the previous line
+
+               elsif Start_Column <= Type_Start_Col then
+                  Error_Msg_AP ("type definition expected");
+                  Typedef_Node := Error;
+
+               --  If the identifier is at the start of the line, and is in
+               --  a column to the right of the type declaration line, then we
+               --  may have something like:
+
+               --    type x is
+               --       r : integer
+
+               --  and the best diagnosis is a missing record keyword
+
+               else
+                  Typedef_Node := P_Record_Definition;
+                  TF_Semicolon;
+               end if;
+
+               exit;
+
+            --  Anything else is an error
+
+            when others =>
+               if Bad_Spelling_Of (Tok_Access)
+                    or else
+                  Bad_Spelling_Of (Tok_Array)
+                    or else
+                  Bad_Spelling_Of (Tok_Delta)
+                    or else
+                  Bad_Spelling_Of (Tok_Digits)
+                    or else
+                  Bad_Spelling_Of (Tok_Limited)
+                    or else
+                  Bad_Spelling_Of (Tok_Private)
+                    or else
+                  Bad_Spelling_Of (Tok_Range)
+                    or else
+                  Bad_Spelling_Of (Tok_Record)
+                    or else
+                  Bad_Spelling_Of (Tok_Tagged)
+               then
+                  null;
+
+               else
+                  Error_Msg_AP ("type definition expected");
+                  raise Error_Resync;
+               end if;
+
+         end case;
+      end loop;
+
+      --  For the private type declaration case, the private type declaration
+      --  node has been built, with the Tagged_Present and Limited_Present
+      --  flags set as needed, and Typedef_Node is left set to Empty.
+
+      if No (Typedef_Node) then
+         Set_Unknown_Discriminants_Present (Decl_Node, Unknown_Dis);
+         Set_Abstract_Present (Decl_Node, Abstract_Present);
+
+      --  For a private extension declaration, Typedef_Node contains the
+      --  N_Private_Extension_Declaration node, which we now complete. Note
+      --  that the private extension declaration, unlike a full type
+      --  declaration, does permit unknown discriminants.
+
+      elsif Nkind (Typedef_Node) = N_Private_Extension_Declaration then
+         Decl_Node := Typedef_Node;
+         Set_Sloc (Decl_Node, Type_Loc);
+         Set_Unknown_Discriminants_Present (Decl_Node, Unknown_Dis);
+         Set_Abstract_Present (Typedef_Node, Abstract_Present);
+
+      --  In the full type declaration case, Typedef_Node has the type
+      --  definition and here is where we build the full type declaration
+      --  node. This is also where we check for improper use of an unknown
+      --  discriminant part (not allowed for full type declaration).
+
+      else
+         if Nkind (Typedef_Node) = N_Record_Definition
+           or else (Nkind (Typedef_Node) = N_Derived_Type_Definition
+                      and then Present (Record_Extension_Part (Typedef_Node)))
+         then
+            Set_Abstract_Present (Typedef_Node, Abstract_Present);
+
+         elsif Abstract_Present then
+            Error_Msg ("ABSTRACT not allowed here, ignored", Abstract_Loc);
+         end if;
+
+         Decl_Node := New_Node (N_Full_Type_Declaration, Type_Loc);
+         Set_Type_Definition (Decl_Node, Typedef_Node);
+
+         if Unknown_Dis then
+            Error_Msg
+              ("Full type declaration cannot have unknown discriminants",
+                Discr_Sloc);
+         end if;
+      end if;
+
+      --  Remaining processing is common for all three cases
+
+      Set_Defining_Identifier (Decl_Node, Ident_Node);
+      Set_Discriminant_Specifications (Decl_Node, Discr_List);
+      return Decl_Node;
+
+   end P_Type_Declaration;
+
+   ----------------------------------
+   -- 3.2.1  Full Type Declaration --
+   ----------------------------------
+
+   --  Parsed by P_Type_Declaration (3.2.1)
+
+   ----------------------------
+   -- 3.2.1  Type Definition --
+   ----------------------------
+
+   --  Parsed by P_Type_Declaration (3.2.1)
+
+   --------------------------------
+   -- 3.2.2  Subtype Declaration --
+   --------------------------------
+
+   --  SUBTYPE_DECLARATION ::=
+   --    subtype DEFINING_IDENTIFIER is SUBTYPE_INDICATION;
+
+   --  The caller has checked that the initial token is SUBTYPE
+
+   --  Error recovery: can raise Error_Resync
+
+   function P_Subtype_Declaration return Node_Id is
+      Decl_Node : Node_Id;
+
+   begin
+      Decl_Node := New_Node (N_Subtype_Declaration, Token_Ptr);
+      Scan; -- past SUBTYPE
+      Set_Defining_Identifier (Decl_Node, P_Defining_Identifier);
+      TF_Is;
+
+      if Token = Tok_New then
+         Error_Msg_SC ("NEW ignored (only allowed in type declaration)");
+         Scan; -- past NEW
+      end if;
+
+      Set_Subtype_Indication (Decl_Node, P_Subtype_Indication);
+      TF_Semicolon;
+      return Decl_Node;
+   end P_Subtype_Declaration;
+
+   -------------------------------
+   -- 3.2.2  Subtype Indication --
+   -------------------------------
+
+   --  SUBTYPE_INDICATION ::= SUBTYPE_MARK [CONSTRAINT]
+
+   --  Error recovery: can raise Error_Resync
+
+   function P_Subtype_Indication return Node_Id is
+      Type_Node : Node_Id;
+
+   begin
+      if Token = Tok_Identifier or else Token = Tok_Operator_Symbol then
+         Type_Node := P_Subtype_Mark;
+         return P_Subtype_Indication (Type_Node);
+
+      else
+         --  Check for error of using record definition and treat it nicely,
+         --  otherwise things are really messed up, so resynchronize.
+
+         if Token = Tok_Record then
+            Error_Msg_SC ("anonymous record definitions are not permitted");
+            Discard_Junk_Node (P_Record_Definition);
+            return Error;
+
+         else
+            Error_Msg_AP ("subtype indication expected");
+            raise Error_Resync;
+         end if;
+      end if;
+   end P_Subtype_Indication;
+
+   --  The following function is identical except that it is called with
+   --  the subtype mark already scanned out, and it scans out the constraint
+
+   --  Error recovery: can raise Error_Resync
+
+   function P_Subtype_Indication (Subtype_Mark : Node_Id) return Node_Id is
+      Indic_Node  : Node_Id;
+      Constr_Node : Node_Id;
+
+   begin
+      Constr_Node := P_Constraint_Opt;
+
+      if No (Constr_Node) then
+         return Subtype_Mark;
+      else
+         Indic_Node := New_Node (N_Subtype_Indication, Sloc (Subtype_Mark));
+         Set_Subtype_Mark (Indic_Node, Check_Subtype_Mark (Subtype_Mark));
+         Set_Constraint (Indic_Node, Constr_Node);
+         return Indic_Node;
+      end if;
+
+   end P_Subtype_Indication;
+
+   -------------------------
+   -- 3.2.2  Subtype Mark --
+   -------------------------
+
+   --  SUBTYPE_MARK ::= subtype_NAME;
+
+   --  Note: The subtype mark which appears after an IN or NOT IN
+   --  operator is parsed by P_Range_Or_Subtype_Mark (3.5)
+
+   --  Error recovery: cannot raise Error_Resync
+
+   function P_Subtype_Mark return Node_Id is
+   begin
+      return P_Subtype_Mark_Resync;
+
+   exception
+      when Error_Resync =>
+         return Error;
+   end P_Subtype_Mark;
+
+   --  This routine differs from P_Subtype_Mark in that it insists that an
+   --  identifier be present, and if it is not, it raises Error_Resync.
+
+   --  Error recovery: can raise Error_Resync
+
+   function P_Subtype_Mark_Resync return Node_Id is
+      Type_Node : Node_Id;
+
+   begin
+      if Token = Tok_Access then
+         Error_Msg_SC ("anonymous access type definition not allowed here");
+         Scan; -- past ACCESS
+      end if;
+
+      if Token = Tok_Array then
+         Error_Msg_SC ("anonymous array definition not allowed here");
+         Discard_Junk_Node (P_Array_Type_Definition);
+         return Empty;
+
+      else
+         Type_Node := P_Qualified_Simple_Name_Resync;
+
+         --  Check for a subtype mark attribute. The only valid possibilities
+         --  are 'CLASS and 'BASE. Anything else is a definite error. We may
+         --  as well catch it here.
+
+         if Token = Tok_Apostrophe then
+            return P_Subtype_Mark_Attribute (Type_Node);
+         else
+            return Type_Node;
+         end if;
+      end if;
+   end P_Subtype_Mark_Resync;
+
+   --  The following function is called to scan out a subtype mark attribute.
+   --  The caller has already scanned out the subtype mark, which is passed in
+   --  as the argument, and has checked that the current token is apostrophe.
+
+   --  Only a special subclass of attributes, called type attributes
+   --  (see Snames package) are allowed in this syntactic position.
+
+   --  Note: if the apostrophe is followed by other than an identifier, then
+   --  the input expression is returned unchanged, and the scan pointer is
+   --  left pointing to the apostrophe.
+
+   --  Error recovery: can raise Error_Resync
+
+   function P_Subtype_Mark_Attribute (Type_Node : Node_Id) return Node_Id is
+      Attr_Node  : Node_Id := Empty;
+      Scan_State : Saved_Scan_State;
+      Prefix     : Node_Id;
+
+   begin
+      Prefix := Check_Subtype_Mark (Type_Node);
+
+      if Prefix = Error then
+         raise Error_Resync;
+      end if;
+
+      --  Loop through attributes appearing (more than one can appear as for
+      --  for example in X'Base'Class). We are at an apostrophe on entry to
+      --  this loop, and it runs once for each attribute parsed, with
+      --  Prefix being the current possible prefix if it is an attribute.
+
+      loop
+         Save_Scan_State (Scan_State); -- at Apostrophe
+         Scan; -- past apostrophe
+
+         if Token /= Tok_Identifier then
+            Restore_Scan_State (Scan_State); -- to apostrophe
+            return Prefix; -- no attribute after all
+
+         elsif not Is_Type_Attribute_Name (Token_Name) then
+            Error_Msg_N
+              ("attribute & may not be used in a subtype mark", Token_Node);
+            raise Error_Resync;
+
+         else
+            Attr_Node :=
+              Make_Attribute_Reference (Prev_Token_Ptr,
+                Prefix => Prefix,
+                Attribute_Name => Token_Name);
+            Delete_Node (Token_Node);
+            Scan; -- past type attribute identifier
+         end if;
+
+         exit when Token /= Tok_Apostrophe;
+         Prefix := Attr_Node;
+      end loop;
+
+      --  Fall through here after scanning type attribute
+
+      return Attr_Node;
+   end P_Subtype_Mark_Attribute;
+
+   -----------------------
+   -- 3.2.2  Constraint --
+   -----------------------
+
+   --  CONSTRAINT ::= SCALAR_CONSTRAINT | COMPOSITE_CONSTRAINT
+
+   --  SCALAR_CONSTRAINT ::=
+   --    RANGE_CONSTRAINT | DIGITS_CONSTRAINT | DELTA_CONSTRAINT
+
+   --  COMPOSITE_CONSTRAINT ::=
+   --    INDEX_CONSTRAINT | DISCRIMINANT_CONSTRAINT
+
+   --  If no constraint is present, this function returns Empty
+
+   --  Error recovery: can raise Error_Resync
+
+   function P_Constraint_Opt return Node_Id is
+   begin
+      if Token = Tok_Range
+        or else Bad_Spelling_Of (Tok_Range)
+      then
+         return P_Range_Constraint;
+
+      elsif Token = Tok_Digits
+        or else Bad_Spelling_Of (Tok_Digits)
+      then
+         return P_Digits_Constraint;
+
+      elsif Token = Tok_Delta
+        or else Bad_Spelling_Of (Tok_Delta)
+      then
+         return P_Delta_Constraint;
+
+      elsif Token = Tok_Left_Paren then
+         return P_Index_Or_Discriminant_Constraint;
+
+      elsif Token = Tok_In then
+         Ignore (Tok_In);
+         return P_Constraint_Opt;
+
+      else
+         return Empty;
+      end if;
+
+   end P_Constraint_Opt;
+
+   ------------------------------
+   -- 3.2.2  Scalar Constraint --
+   ------------------------------
+
+   --  Parsed by P_Constraint_Opt (3.2.2)
+
+   ---------------------------------
+   -- 3.2.2  Composite Constraint --
+   ---------------------------------
+
+   --  Parsed by P_Constraint_Opt (3.2.2)
+
+   --------------------------------------------------------
+   -- 3.3  Identifier Declarations (Also 7.4, 8.5, 11.1) --
+   --------------------------------------------------------
+
+   --  This routine scans out a declaration starting with an identifier:
+
+   --  OBJECT_DECLARATION ::=
+   --    DEFINING_IDENTIFIER_LIST : [constant] [aliased]
+   --      SUBTYPE_INDICATION [:= EXPRESSION];
+   --  | DEFINING_IDENTIFIER_LIST : [constant] [aliased]
+   --      ARRAY_TYPE_DEFINITION [:= EXPRESSION];
+
+   --  NUMBER_DECLARATION ::=
+   --    DEFINING_IDENTIFIER_LIST : constant ::= static_EXPRESSION;
+
+   --  OBJECT_RENAMING_DECLARATION ::=
+   --    DEFINING_IDENTIFIER : SUBTYPE_MARK renames object_NAME;
+
+   --  EXCEPTION_RENAMING_DECLARATION ::=
+   --    DEFINING_IDENTIFIER : exception renames exception_NAME;
+
+   --  EXCEPTION_DECLARATION ::=
+   --    DEFINING_IDENTIFIER_LIST : exception;
+
+   --  Note that the ALIASED indication in an object declaration is
+   --  marked by a flag in the parent node.
+
+   --  The caller has checked that the initial token is an identifier
+
+   --  The value returned is a list of declarations, one for each identifier
+   --  in the list (as described in Sinfo, we always split up multiple
+   --  declarations into the equivalent sequence of single declarations
+   --  using the More_Ids and Prev_Ids flags to preserve the source).
+
+   --  If the identifier turns out to be a probable statement rather than
+   --  an identifier, then the scan is left pointing to the identifier and
+   --  No_List is returned.
+
+   --  Error recovery: can raise Error_Resync
+
+   procedure P_Identifier_Declarations
+     (Decls   : List_Id;
+      Done    : out Boolean;
+      In_Spec : Boolean)
+   is
+      Decl_Node  : Node_Id;
+      Type_Node  : Node_Id;
+      Ident_Sloc : Source_Ptr;
+      Scan_State : Saved_Scan_State;
+      List_OK    : Boolean := True;
+      Ident      : Nat;
+      Init_Expr  : Node_Id;
+      Init_Loc   : Source_Ptr;
+      Con_Loc    : Source_Ptr;
+
+      Idents : array (Int range 1 .. 4096) of Entity_Id;
+      --  Used to save identifiers in the identifier list. The upper bound
+      --  of 4096 is expected to be infinite in practice, and we do not even
+      --  bother to check if this upper bound is exceeded.
+
+      Num_Idents : Nat := 1;
+      --  Number of identifiers stored in Idents
+
+      procedure No_List;
+      --  This procedure is called in renames cases to make sure that we do
+      --  not have more than one identifier. If we do have more than one
+      --  then an error message is issued (and the declaration is split into
+      --  multiple declarations)
+
+      function Token_Is_Renames return Boolean;
+      --  Checks if current token is RENAMES, and if so, scans past it and
+      --  returns True, otherwise returns False. Includes checking for some
+      --  common error cases.
+
+      procedure No_List is
+      begin
+         if Num_Idents > 1 then
+            Error_Msg ("identifier list not allowed for RENAMES",
+                       Sloc (Idents (2)));
+         end if;
+
+         List_OK := False;
+      end No_List;
+
+      function Token_Is_Renames return Boolean is
+         At_Colon : Saved_Scan_State;
+
+      begin
+         if Token = Tok_Colon then
+            Save_Scan_State (At_Colon);
+            Scan; -- past colon
+            Check_Misspelling_Of (Tok_Renames);
+
+            if Token = Tok_Renames then
+               Error_Msg_SP ("extra "":"" ignored");
+               Scan; -- past RENAMES
+               return True;
+            else
+               Restore_Scan_State (At_Colon);
+               return False;
+            end if;
+
+         else
+            Check_Misspelling_Of (Tok_Renames);
+
+            if Token = Tok_Renames then
+               Scan; -- past RENAMES
+               return True;
+            else
+               return False;
+            end if;
+         end if;
+      end Token_Is_Renames;
+
+   --  Start of processing for P_Identifier_Declarations
+
+   begin
+      Ident_Sloc := Token_Ptr;
+      Save_Scan_State (Scan_State); -- at first identifier
+      Idents (1) := P_Defining_Identifier;
+
+      --  If we have a colon after the identifier, then we can assume that
+      --  this is in fact a valid identifier declaration and can steam ahead.
+
+      if Token = Tok_Colon then
+         Scan; -- past colon
+
+      --  If we have a comma, then scan out the list of identifiers
+
+      elsif Token = Tok_Comma then
+
+         while Comma_Present loop
+            Num_Idents := Num_Idents + 1;
+            Idents (Num_Idents) := P_Defining_Identifier;
+         end loop;
+
+         Save_Scan_State (Scan_State); -- at colon
+         T_Colon;
+
+      --  If we have identifier followed by := then we assume that what is
+      --  really meant is an assignment statement. The assignment statement
+      --  is scanned out and added to the list of declarations. An exception
+      --  occurs if the := is followed by the keyword constant, in which case
+      --  we assume it was meant to be a colon.
+
+      elsif Token = Tok_Colon_Equal then
+         Scan; -- past :=
+
+         if Token = Tok_Constant then
+            Error_Msg_SP ("colon expected");
+
+         else
+            Restore_Scan_State (Scan_State);
+            Statement_When_Declaration_Expected (Decls, Done, In_Spec);
+            return;
+         end if;
+
+      --  If we have an IS keyword, then assume the TYPE keyword was missing
+
+      elsif Token = Tok_Is then
+         Restore_Scan_State (Scan_State);
+         Append_To (Decls, P_Type_Declaration);
+         Done := False;
+         return;
+
+      --  Otherwise we have an error situation
+
+      else
+         Restore_Scan_State (Scan_State);
+
+         --  First case is possible misuse of PROTECTED in Ada 83 mode. If
+         --  so, fix the keyword and return to scan the protected declaration.
+
+         if Token_Name = Name_Protected then
+            Check_95_Keyword (Tok_Protected, Tok_Identifier);
+            Check_95_Keyword (Tok_Protected, Tok_Type);
+            Check_95_Keyword (Tok_Protected, Tok_Body);
+
+            if Token = Tok_Protected then
+               Done := False;
+               return;
+            end if;
+
+         --  Check misspelling possibilities. If so, correct the misspelling
+         --  and return to scan out the resulting declaration.
+
+         elsif Bad_Spelling_Of (Tok_Function)
+           or else Bad_Spelling_Of (Tok_Procedure)
+           or else Bad_Spelling_Of (Tok_Package)
+           or else Bad_Spelling_Of (Tok_Pragma)
+           or else Bad_Spelling_Of (Tok_Protected)
+           or else Bad_Spelling_Of (Tok_Generic)
+           or else Bad_Spelling_Of (Tok_Subtype)
+           or else Bad_Spelling_Of (Tok_Type)
+           or else Bad_Spelling_Of (Tok_Task)
+           or else Bad_Spelling_Of (Tok_Use)
+           or else Bad_Spelling_Of (Tok_For)
+         then
+            Done := False;
+            return;
+
+         --  Otherwise we definitely have an ordinary identifier with a junk
+         --  token after it. Just complain that we expect a declaration, and
+         --  skip to a semicolon
+
+         else
+            Set_Declaration_Expected;
+            Resync_Past_Semicolon;
+            Done := False;
+            return;
+         end if;
+      end if;
+
+      --  Come here with an identifier list and colon scanned out. We now
+      --  build the nodes for the declarative items. One node is built for
+      --  each identifier in the list, with the type information being
+      --  repeated by rescanning the appropriate section of source.
+
+      --  First an error check, if we have two identifiers in a row, a likely
+      --  possibility is that the first of the identifiers is an incorrectly
+      --  spelled keyword.
+
+      if Token = Tok_Identifier then
+         declare
+            SS : Saved_Scan_State;
+            I2 : Boolean;
+
+         begin
+            Save_Scan_State (SS);
+            Scan; -- past initial identifier
+            I2 := (Token = Tok_Identifier);
+            Restore_Scan_State (SS);
+
+            if I2
+              and then
+                (Bad_Spelling_Of (Tok_Access)   or else
+                 Bad_Spelling_Of (Tok_Aliased)  or else
+                 Bad_Spelling_Of (Tok_Constant))
+            then
+               null;
+            end if;
+         end;
+      end if;
+
+      --  Loop through identifiers
+
+      Ident := 1;
+      Ident_Loop : loop
+
+         --  Check for some cases of misused Ada 95 keywords
+
+         if Token_Name = Name_Aliased then
+            Check_95_Keyword (Tok_Aliased, Tok_Array);
+            Check_95_Keyword (Tok_Aliased, Tok_Identifier);
+            Check_95_Keyword (Tok_Aliased, Tok_Constant);
+         end if;
+
+         --  Constant cases
+
+         if Token = Tok_Constant then
+            Con_Loc := Token_Ptr;
+            Scan; -- past CONSTANT
+
+            --  Number declaration, initialization required
+
+            Init_Expr := Init_Expr_Opt;
+
+            if Present (Init_Expr) then
+               Decl_Node := New_Node (N_Number_Declaration, Ident_Sloc);
+               Set_Expression (Decl_Node, Init_Expr);
+
+            --  Constant object declaration
+
+            else
+               Decl_Node := New_Node (N_Object_Declaration, Ident_Sloc);
+               Set_Constant_Present (Decl_Node, True);
+
+               if Token_Name = Name_Aliased then
+                  Check_95_Keyword (Tok_Aliased, Tok_Array);
+                  Check_95_Keyword (Tok_Aliased, Tok_Identifier);
+               end if;
+
+               if Token = Tok_Aliased then
+                  Error_Msg_SC ("ALIASED should be before CONSTANT");
+                  Scan; -- past ALIASED
+                  Set_Aliased_Present (Decl_Node, True);
+               end if;
+
+               if Token = Tok_Array then
+                  Set_Object_Definition
+                    (Decl_Node, P_Array_Type_Definition);
+               else
+                  Set_Object_Definition (Decl_Node, P_Subtype_Indication);
+               end if;
+
+               if Token = Tok_Renames then
+                  Error_Msg
+                    ("CONSTANT not permitted in renaming declaration",
+                     Con_Loc);
+                  Scan; -- Past renames
+                  Discard_Junk_Node (P_Name);
+               end if;
+            end if;
+
+         --  Exception cases
+
+         elsif Token = Tok_Exception then
+            Scan; -- past EXCEPTION
+
+            if Token_Is_Renames then
+               No_List;
+               Decl_Node :=
+                 New_Node (N_Exception_Renaming_Declaration, Ident_Sloc);
+               Set_Name (Decl_Node, P_Qualified_Simple_Name_Resync);
+               No_Constraint;
+            else
+               Decl_Node := New_Node (N_Exception_Declaration, Prev_Token_Ptr);
+            end if;
+
+         --  Aliased case (note that an object definition is required)
+
+         elsif Token = Tok_Aliased then
+            Scan; -- past ALIASED
+            Decl_Node := New_Node (N_Object_Declaration, Ident_Sloc);
+            Set_Aliased_Present (Decl_Node, True);
+
+            if Token = Tok_Constant then
+               Scan; -- past CONSTANT
+               Set_Constant_Present (Decl_Node, True);
+            end if;
+
+            if Token = Tok_Array then
+               Set_Object_Definition
+                 (Decl_Node, P_Array_Type_Definition);
+            else
+               Set_Object_Definition (Decl_Node, P_Subtype_Indication);
+            end if;
+
+         --  Array case
+
+         elsif Token = Tok_Array then
+            Decl_Node := New_Node (N_Object_Declaration, Ident_Sloc);
+            Set_Object_Definition (Decl_Node, P_Array_Type_Definition);
+
+         --  Subtype indication case
+
+         else
+            Type_Node := P_Subtype_Mark;
+
+            --  Object renaming declaration
+
+            if Token_Is_Renames then
+               No_List;
+               Decl_Node :=
+                 New_Node (N_Object_Renaming_Declaration, Ident_Sloc);
+               Set_Subtype_Mark (Decl_Node, Type_Node);
+               Set_Name (Decl_Node, P_Name);
+
+            --  Object declaration
+
+            else
+               Decl_Node := New_Node (N_Object_Declaration, Ident_Sloc);
+               Set_Object_Definition
+                 (Decl_Node, P_Subtype_Indication (Type_Node));
+
+               --  RENAMES at this point means that we had the combination of
+               --  a constraint on the Type_Node and renames, which is illegal
+
+               if Token_Is_Renames then
+                  Error_Msg_N
+                    ("constraint not allowed in object renaming declaration",
+                     Constraint (Object_Definition (Decl_Node)));
+                  raise Error_Resync;
+               end if;
+            end if;
+         end if;
+
+         --  Scan out initialization, allowed only for object declaration
+
+         Init_Loc := Token_Ptr;
+         Init_Expr := Init_Expr_Opt;
+
+         if Present (Init_Expr) then
+            if Nkind (Decl_Node) = N_Object_Declaration then
+               Set_Expression (Decl_Node, Init_Expr);
+            else
+               Error_Msg ("initialization not allowed here", Init_Loc);
+            end if;
+         end if;
+
+         TF_Semicolon;
+         Set_Defining_Identifier (Decl_Node, Idents (Ident));
+
+         if List_OK then
+            if Ident < Num_Idents then
+               Set_More_Ids (Decl_Node, True);
+            end if;
+
+            if Ident > 1 then
+               Set_Prev_Ids (Decl_Node, True);
+            end if;
+         end if;
+
+         Append (Decl_Node, Decls);
+         exit Ident_Loop when Ident = Num_Idents;
+         Restore_Scan_State (Scan_State);
+         T_Colon;
+         Ident := Ident + 1;
+      end loop Ident_Loop;
+
+      Done := False;
+
+   end P_Identifier_Declarations;
+
+   -------------------------------
+   -- 3.3.1  Object Declaration --
+   -------------------------------
+
+   --  OBJECT DECLARATION ::=
+   --    DEFINING_IDENTIFIER_LIST : [aliased] [constant]
+   --      SUBTYPE_INDICATION [:= EXPRESSION];
+   --  | DEFINING_IDENTIFIER_LIST : [aliased] [constant]
+   --      ARRAY_TYPE_DEFINITION [:= EXPRESSION];
+   --  | SINGLE_TASK_DECLARATION
+   --  | SINGLE_PROTECTED_DECLARATION
+
+   --  Cases starting with TASK are parsed by P_Task (9.1)
+   --  Cases starting with PROTECTED are parsed by P_Protected (9.4)
+   --  All other cases are parsed by P_Identifier_Declarations (3.3)
+
+   -------------------------------------
+   -- 3.3.1  Defining Identifier List --
+   -------------------------------------
+
+   --  DEFINING_IDENTIFIER_LIST ::=
+   --    DEFINING_IDENTIFIER {, DEFINING_IDENTIFIER}
+
+   --  Always parsed by the construct in which it appears. See special
+   --  section on "Handling of Defining Identifier Lists" in this unit.
+
+   -------------------------------
+   -- 3.3.2  Number Declaration --
+   -------------------------------
+
+   --  Parsed by P_Identifier_Declarations (3.3)
+
+   -------------------------------------------------------------------------
+   -- 3.4  Derived Type Definition or Private Extension Declaration (7.3) --
+   -------------------------------------------------------------------------
+
+   --  DERIVED_TYPE_DEFINITION ::=
+   --    [abstract] new parent_SUBTYPE_INDICATION [RECORD_EXTENSION_PART]
+
+   --  PRIVATE_EXTENSION_DECLARATION ::=
+   --     type DEFINING_IDENTIFIER [DISCRIMINANT_PART] is
+   --       [abstract] new ancestor_SUBTYPE_INDICATION with PRIVATE;
+
+   --  RECORD_EXTENSION_PART ::= with RECORD_DEFINITION
+
+   --  The caller has already scanned out the part up to the NEW, and Token
+   --  either contains Tok_New (or ought to, if it doesn't this procedure
+   --  will post an appropriate "NEW expected" message).
+
+   --  Note: the caller is responsible for filling in the Sloc field of
+   --  the returned node in the private extension declaration case as
+   --  well as the stuff relating to the discriminant part.
+
+   --  Error recovery: can raise Error_Resync;
+
+   function P_Derived_Type_Def_Or_Private_Ext_Decl return Node_Id is
+      Typedef_Node  : Node_Id;
+      Typedecl_Node : Node_Id;
+
+   begin
+      Typedef_Node := New_Node (N_Derived_Type_Definition, Token_Ptr);
+      T_New;
+
+      if Token = Tok_Abstract then
+         Error_Msg_SC ("ABSTRACT must come before NEW, not after");
+         Scan;
+      end if;
+
+      Set_Subtype_Indication (Typedef_Node, P_Subtype_Indication);
+
+      --  Deal with record extension, note that we assume that a WITH is
+      --  missing in the case of "type X is new Y record ..." or in the
+      --  case of "type X is new Y null record".
+
+      if Token = Tok_With
+        or else Token = Tok_Record
+        or else Token = Tok_Null
+      then
+         T_With; -- past WITH or give error message
+
+         if Token = Tok_Limited then
+            Error_Msg_SC
+              ("LIMITED keyword not allowed in private extension");
+            Scan; -- ignore LIMITED
+         end if;
+
+         --  Private extension declaration
+
+         if Token = Tok_Private then
+            Scan; -- past PRIVATE
+
+            --  Throw away the type definition node and build the type
+            --  declaration node. Note the caller must set the Sloc,
+            --  Discriminant_Specifications, Unknown_Discriminants_Present,
+            --  and Defined_Identifier fields in the returned node.
+
+            Typedecl_Node :=
+              Make_Private_Extension_Declaration (No_Location,
+                Defining_Identifier => Empty,
+                Subtype_Indication  => Subtype_Indication (Typedef_Node),
+                Abstract_Present    => Abstract_Present (Typedef_Node));
+
+            Delete_Node (Typedef_Node);
+            return Typedecl_Node;
+
+         --  Derived type definition with record extension part
+
+         else
+            Set_Record_Extension_Part (Typedef_Node, P_Record_Definition);
+            return Typedef_Node;
+         end if;
+
+      --  Derived type definition with no record extension part
+
+      else
+         return Typedef_Node;
+      end if;
+   end P_Derived_Type_Def_Or_Private_Ext_Decl;
+
+   ---------------------------
+   -- 3.5  Range Constraint --
+   ---------------------------
+
+   --  RANGE_CONSTRAINT ::= range RANGE
+
+   --  The caller has checked that the initial token is RANGE
+
+   --  Error recovery: cannot raise Error_Resync
+
+   function P_Range_Constraint return Node_Id is
+      Range_Node : Node_Id;
+
+   begin
+      Range_Node := New_Node (N_Range_Constraint, Token_Ptr);
+      Scan; -- past RANGE
+      Set_Range_Expression (Range_Node, P_Range);
+      return Range_Node;
+   end P_Range_Constraint;
+
+   ----------------
+   -- 3.5  Range --
+   ----------------
+
+   --  RANGE ::=
+   --    RANGE_ATTRIBUTE_REFERENCE | SIMPLE_EXPRESSION .. SIMPLE_EXPRESSION
+
+   --  Note: the range that appears in a membership test is parsed by
+   --  P_Range_Or_Subtype_Mark (3.5).
+
+   --  Error recovery: cannot raise Error_Resync
+
+   function P_Range return Node_Id is
+      Expr_Node  : Node_Id;
+      Range_Node : Node_Id;
+
+   begin
+      Expr_Node := P_Simple_Expression_Or_Range_Attribute;
+
+      if Expr_Form = EF_Range_Attr then
+         return Expr_Node;
+
+      elsif Token = Tok_Dot_Dot then
+         Range_Node := New_Node (N_Range, Token_Ptr);
+         Set_Low_Bound (Range_Node, Expr_Node);
+         Scan; -- past ..
+         Expr_Node := P_Expression;
+         Check_Simple_Expression (Expr_Node);
+         Set_High_Bound (Range_Node, Expr_Node);
+         return Range_Node;
+
+      --  Anything else is an error
+
+      else
+         T_Dot_Dot; -- force missing .. message
+         return Error;
+      end if;
+   end P_Range;
+
+   ----------------------------------
+   -- 3.5  P_Range_Or_Subtype_Mark --
+   ----------------------------------
+
+   --  RANGE ::=
+   --    RANGE_ATTRIBUTE_REFERENCE
+   --  | SIMPLE_EXPRESSION .. SIMPLE_EXPRESSION
+
+   --  This routine scans out the range or subtype mark that forms the right
+   --  operand of a membership test.
+
+   --  Note: as documented in the Sinfo interface, although the syntax only
+   --  allows a subtype mark, we in fact allow any simple expression to be
+   --  returned from this routine. The semantics is responsible for issuing
+   --  an appropriate message complaining if the argument is not a name.
+   --  This simplifies the coding and error recovery processing in the
+   --  parser, and in any case it is preferable not to consider this a
+   --  syntax error and to continue with the semantic analysis.
+
+   --  Error recovery: cannot raise Error_Resync
+
+   function P_Range_Or_Subtype_Mark return Node_Id is
+      Expr_Node  : Node_Id;
+      Range_Node : Node_Id;
+
+   begin
+      Expr_Node := P_Simple_Expression_Or_Range_Attribute;
+
+      if Expr_Form = EF_Range_Attr then
+         return Expr_Node;
+
+      --  Simple_Expression .. Simple_Expression
+
+      elsif Token = Tok_Dot_Dot then
+         Check_Simple_Expression (Expr_Node);
+         Range_Node := New_Node (N_Range, Token_Ptr);
+         Set_Low_Bound (Range_Node, Expr_Node);
+         Scan; -- past ..
+         Set_High_Bound (Range_Node, P_Simple_Expression);
+         return Range_Node;
+
+      --  Case of subtype mark (optionally qualified simple name or an
+      --  attribute whose prefix is an optionally qualifed simple name)
+
+      elsif Expr_Form = EF_Simple_Name
+        or else Nkind (Expr_Node) = N_Attribute_Reference
+      then
+         --  Check for error of range constraint after a subtype mark
+
+         if Token = Tok_Range then
+            Error_Msg_SC
+              ("range constraint not allowed in membership test");
+            Scan; -- past RANGE
+            raise Error_Resync;
+
+         --  Check for error of DIGITS or DELTA after a subtype mark
+
+         elsif Token = Tok_Digits or else Token = Tok_Delta then
+            Error_Msg_SC
+               ("accuracy definition not allowed in membership test");
+            Scan; -- past DIGITS or DELTA
+            raise Error_Resync;
+
+         elsif Token = Tok_Apostrophe then
+            return P_Subtype_Mark_Attribute (Expr_Node);
+
+         else
+            return Expr_Node;
+         end if;
+
+      --  At this stage, we have some junk following the expression. We
+      --  really can't tell what is wrong, might be a missing semicolon,
+      --  or a missing THEN, or whatever. Our caller will figure it out!
+
+      else
+         return Expr_Node;
+      end if;
+   end P_Range_Or_Subtype_Mark;
+
+   ----------------------------------------
+   -- 3.5.1  Enumeration Type Definition --
+   ----------------------------------------
+
+   --  ENUMERATION_TYPE_DEFINITION ::=
+   --    (ENUMERATION_LITERAL_SPECIFICATION
+   --      {, ENUMERATION_LITERAL_SPECIFICATION})
+
+   --  The caller has already scanned out the TYPE keyword
+
+   --  Error recovery: can raise Error_Resync;
+
+   function P_Enumeration_Type_Definition return Node_Id is
+      Typedef_Node : Node_Id;
+
+   begin
+      Typedef_Node := New_Node (N_Enumeration_Type_Definition, Token_Ptr);
+      Set_Literals (Typedef_Node, New_List);
+
+      T_Left_Paren;
+
+      loop
+         Append (P_Enumeration_Literal_Specification, Literals (Typedef_Node));
+         exit when not Comma_Present;
+      end loop;
+
+      T_Right_Paren;
+      return Typedef_Node;
+   end P_Enumeration_Type_Definition;
+
+   ----------------------------------------------
+   -- 3.5.1  Enumeration Literal Specification --
+   ----------------------------------------------
+
+   --  ENUMERATION_LITERAL_SPECIFICATION ::=
+   --    DEFINING_IDENTIFIER | DEFINING_CHARACTER_LITERAL
+
+   --  Error recovery: can raise Error_Resync
+
+   function P_Enumeration_Literal_Specification return Node_Id is
+   begin
+      if Token = Tok_Char_Literal then
+         return P_Defining_Character_Literal;
+      else
+         return P_Defining_Identifier;
+      end if;
+   end P_Enumeration_Literal_Specification;
+
+   ---------------------------------------
+   -- 3.5.1  Defining_Character_Literal --
+   ---------------------------------------
+
+   --  DEFINING_CHARACTER_LITERAL ::= CHARACTER_LITERAL
+
+   --  Error recovery: cannot raise Error_Resync
+
+   --  The caller has checked that the current token is a character literal
+
+   function P_Defining_Character_Literal return Node_Id is
+      Literal_Node : Node_Id;
+
+   begin
+      Literal_Node := Token_Node;
+      Change_Character_Literal_To_Defining_Character_Literal (Literal_Node);
+      Scan; -- past character literal
+      return Literal_Node;
+   end P_Defining_Character_Literal;
+
+   ------------------------------------
+   -- 3.5.4  Integer Type Definition --
+   ------------------------------------
+
+   --  Parsed by P_Type_Declaration (3.2.1)
+
+   -------------------------------------------
+   -- 3.5.4  Signed Integer Type Definition --
+   -------------------------------------------
+
+   --  SIGNED_INTEGER_TYPE_DEFINITION ::=
+   --    range static_SIMPLE_EXPRESSION .. static_SIMPLE_EXPRESSION
+
+   --  Normally the initial token on entry is RANGE, but in some
+   --  error conditions, the range token was missing and control is
+   --  passed with Token pointing to first token of the first expression.
+
+   --  Error recovery: cannot raise Error_Resync
+
+   function P_Signed_Integer_Type_Definition return Node_Id is
+      Typedef_Node : Node_Id;
+      Expr_Node    : Node_Id;
+
+   begin
+      Typedef_Node := New_Node (N_Signed_Integer_Type_Definition, Token_Ptr);
+
+      if Token = Tok_Range then
+         Scan; -- past RANGE
+      end if;
+
+      Expr_Node := P_Expression;
+      Check_Simple_Expression (Expr_Node);
+      Set_Low_Bound (Typedef_Node, Expr_Node);
+      T_Dot_Dot;
+      Expr_Node := P_Expression;
+      Check_Simple_Expression (Expr_Node);
+      Set_High_Bound (Typedef_Node, Expr_Node);
+      return Typedef_Node;
+   end P_Signed_Integer_Type_Definition;
+
+   ------------------------------------
+   -- 3.5.4  Modular Type Definition --
+   ------------------------------------
+
+   --  MODULAR_TYPE_DEFINITION ::= mod static_EXPRESSION
+
+   --  The caller has checked that the initial token is MOD
+
+   --  Error recovery: cannot raise Error_Resync
+
+   function P_Modular_Type_Definition return Node_Id is
+      Typedef_Node : Node_Id;
+
+   begin
+      if Ada_83 then
+         Error_Msg_SC ("(Ada 83): modular types not allowed");
+      end if;
+
+      Typedef_Node := New_Node (N_Modular_Type_Definition, Token_Ptr);
+      Scan; -- past MOD
+      Set_Expression (Typedef_Node, P_Expression_No_Right_Paren);
+
+      --  Handle mod L..R cleanly
+
+      if Token = Tok_Dot_Dot then
+         Error_Msg_SC ("range not allowed for modular type");
+         Scan; -- past ..
+         Set_Expression (Typedef_Node, P_Expression_No_Right_Paren);
+      end if;
+
+      return Typedef_Node;
+   end P_Modular_Type_Definition;
+
+   ---------------------------------
+   -- 3.5.6  Real Type Definition --
+   ---------------------------------
+
+   --  Parsed by P_Type_Declaration (3.2.1)
+
+   --------------------------------------
+   -- 3.5.7  Floating Point Definition --
+   --------------------------------------
+
+   --  FLOATING_POINT_DEFINITION ::=
+   --    digits static_EXPRESSION [REAL_RANGE_SPECIFICATION]
+
+   --  Note: In Ada-83, the EXPRESSION must be a SIMPLE_EXPRESSION
+
+   --  The caller has checked that the initial token is DIGITS
+
+   --  Error recovery: cannot raise Error_Resync
+
+   function P_Floating_Point_Definition return Node_Id is
+      Digits_Loc : constant Source_Ptr := Token_Ptr;
+      Def_Node   : Node_Id;
+      Expr_Node  : Node_Id;
+
+   begin
+      Scan; -- past DIGITS
+      Expr_Node := P_Expression_No_Right_Paren;
+      Check_Simple_Expression_In_Ada_83 (Expr_Node);
+
+      --  Handle decimal fixed-point defn with DIGITS/DELTA in wrong order
+
+      if Token = Tok_Delta then
+         Error_Msg_SC ("DELTA must come before DIGITS");
+         Def_Node := New_Node (N_Decimal_Fixed_Point_Definition, Digits_Loc);
+         Scan; -- past DELTA
+         Set_Delta_Expression (Def_Node, P_Expression_No_Right_Paren);
+
+      --  OK floating-point definition
+
+      else
+         Def_Node := New_Node (N_Floating_Point_Definition, Digits_Loc);
+      end if;
+
+      Set_Digits_Expression (Def_Node, Expr_Node);
+      Set_Real_Range_Specification (Def_Node, P_Real_Range_Specification_Opt);
+      return Def_Node;
+   end P_Floating_Point_Definition;
+
+   -------------------------------------
+   -- 3.5.7  Real Range Specification --
+   -------------------------------------
+
+   --  REAL_RANGE_SPECIFICATION ::=
+   --    range static_SIMPLE_EXPRESSION .. static_SIMPLE_EXPRESSION
+
+   --  Error recovery: cannot raise Error_Resync
+
+   function P_Real_Range_Specification_Opt return Node_Id is
+      Specification_Node : Node_Id;
+      Expr_Node          : Node_Id;
+
+   begin
+      if Token = Tok_Range then
+         Specification_Node :=
+           New_Node (N_Real_Range_Specification, Token_Ptr);
+         Scan; -- past RANGE
+         Expr_Node := P_Expression_No_Right_Paren;
+         Check_Simple_Expression (Expr_Node);
+         Set_Low_Bound (Specification_Node, Expr_Node);
+         T_Dot_Dot;
+         Expr_Node := P_Expression_No_Right_Paren;
+         Check_Simple_Expression (Expr_Node);
+         Set_High_Bound (Specification_Node, Expr_Node);
+         return Specification_Node;
+      else
+         return Empty;
+      end if;
+   end P_Real_Range_Specification_Opt;
+
+   -----------------------------------
+   -- 3.5.9  Fixed Point Definition --
+   -----------------------------------
+
+   --  FIXED_POINT_DEFINITION ::=
+   --    ORDINARY_FIXED_POINT_DEFINITION | DECIMAL_FIXED_POINT_DEFINITION
+
+   --  ORDINARY_FIXED_POINT_DEFINITION ::=
+   --    delta static_EXPRESSION REAL_RANGE_SPECIFICATION
+
+   --  DECIMAL_FIXED_POINT_DEFINITION ::=
+   --    delta static_EXPRESSION
+   --      digits static_EXPRESSION [REAL_RANGE_SPECIFICATION]
+
+   --  The caller has checked that the initial token is DELTA
+
+   --  Error recovery: cannot raise Error_Resync
+
+   function P_Fixed_Point_Definition return Node_Id is
+      Delta_Node : Node_Id;
+      Delta_Loc  : Source_Ptr;
+      Def_Node   : Node_Id;
+      Expr_Node  : Node_Id;
+
+   begin
+      Delta_Loc := Token_Ptr;
+      Scan; -- past DELTA
+      Delta_Node := P_Expression_No_Right_Paren;
+      Check_Simple_Expression_In_Ada_83 (Delta_Node);
+
+      if Token = Tok_Digits then
+         if Ada_83 then
+            Error_Msg_SC ("(Ada 83) decimal fixed type not allowed!");
+         end if;
+
+         Def_Node := New_Node (N_Decimal_Fixed_Point_Definition, Delta_Loc);
+         Scan; -- past DIGITS
+         Expr_Node := P_Expression_No_Right_Paren;
+         Check_Simple_Expression_In_Ada_83 (Expr_Node);
+         Set_Digits_Expression (Def_Node, Expr_Node);
+
+      else
+         Def_Node := New_Node (N_Ordinary_Fixed_Point_Definition, Delta_Loc);
+
+         --  Range is required in ordinary fixed point case
+
+         if Token /= Tok_Range then
+            Error_Msg_AP ("range must be given for fixed-point type");
+            T_Range;
+         end if;
+      end if;
+
+      Set_Delta_Expression (Def_Node, Delta_Node);
+      Set_Real_Range_Specification (Def_Node, P_Real_Range_Specification_Opt);
+      return Def_Node;
+   end P_Fixed_Point_Definition;
+
+   --------------------------------------------
+   -- 3.5.9  Ordinary Fixed Point Definition --
+   --------------------------------------------
+
+   --  Parsed by P_Fixed_Point_Definition (3.5.9)
+
+   -------------------------------------------
+   -- 3.5.9  Decimal Fixed Point Definition --
+   -------------------------------------------
+
+   --  Parsed by P_Decimal_Point_Definition (3.5.9)
+
+   ------------------------------
+   -- 3.5.9  Digits Constraint --
+   ------------------------------
+
+   --  DIGITS_CONSTRAINT ::=
+   --    digits static_EXPRESSION [RANGE_CONSTRAINT]
+
+   --  Note: in Ada 83, the EXPRESSION must be a SIMPLE_EXPRESSION
+
+   --  The caller has checked that the initial token is DIGITS
+
+   function P_Digits_Constraint return Node_Id is
+      Constraint_Node : Node_Id;
+      Expr_Node : Node_Id;
+
+   begin
+      Constraint_Node := New_Node (N_Digits_Constraint, Token_Ptr);
+      Scan; -- past DIGITS
+      Expr_Node := P_Expression_No_Right_Paren;
+      Check_Simple_Expression_In_Ada_83 (Expr_Node);
+      Set_Digits_Expression (Constraint_Node, Expr_Node);
+
+      if Token = Tok_Range then
+         Set_Range_Constraint (Constraint_Node, P_Range_Constraint);
+      end if;
+
+      return Constraint_Node;
+   end P_Digits_Constraint;
+
+   -----------------------------
+   -- 3.5.9  Delta Constraint --
+   -----------------------------
+
+   --  DELTA CONSTRAINT ::= DELTA STATIC_EXPRESSION [RANGE_CONSTRAINT]
+
+   --  Note: this is an obsolescent feature in Ada 95 (I.3)
+
+   --  Note: in Ada 83, the EXPRESSION must be a SIMPLE_EXPRESSION
+
+   --  The caller has checked that the initial token is DELTA
+
+   --  Error recovery: cannot raise Error_Resync
+
+   function P_Delta_Constraint return Node_Id is
+      Constraint_Node : Node_Id;
+      Expr_Node : Node_Id;
+
+   begin
+      Constraint_Node := New_Node (N_Delta_Constraint, Token_Ptr);
+      Scan; -- past DELTA
+      Expr_Node := P_Expression_No_Right_Paren;
+      Check_Simple_Expression_In_Ada_83 (Expr_Node);
+      Set_Delta_Expression (Constraint_Node, Expr_Node);
+
+      if Token = Tok_Range then
+         Set_Range_Constraint (Constraint_Node, P_Range_Constraint);
+      end if;
+
+      return Constraint_Node;
+   end P_Delta_Constraint;
+
+   --------------------------------
+   -- 3.6  Array Type Definition --
+   --------------------------------
+
+   --  ARRAY_TYPE_DEFINITION ::=
+   --    UNCONSTRAINED_ARRAY_DEFINITION | CONSTRAINED_ARRAY_DEFINITION
+
+   --  UNCONSTRAINED_ARRAY_DEFINITION ::=
+   --    array (INDEX_SUBTYPE_DEFINITION {, INDEX_SUBTYPE_DEFINITION}) of
+   --      COMPONENT_DEFINITION
+
+   --  INDEX_SUBTYPE_DEFINITION ::= SUBTYPE_MARK range <>
+
+   --  CONSTRAINED_ARRAY_DEFINITION ::=
+   --    array (DISCRETE_SUBTYPE_DEFINITION {, DISCRETE_SUBTYPE_DEFINITION}) of
+   --      COMPONENT_DEFINITION
+
+   --  DISCRETE_SUBTYPE_DEFINITION ::=
+   --    DISCRETE_SUBTYPE_INDICATION | RANGE
+
+   --  COMPONENT_DEFINITION ::= [aliased] SUBTYPE_INDICATION
+
+   --  The caller has checked that the initial token is ARRAY
+
+   --  Error recovery: can raise Error_Resync
+
+   function P_Array_Type_Definition return Node_Id is
+      Array_Loc  : Source_Ptr;
+      Def_Node   : Node_Id;
+      Subs_List  : List_Id;
+      Scan_State : Saved_Scan_State;
+
+   begin
+      Array_Loc := Token_Ptr;
+      Scan; -- past ARRAY
+      Subs_List := New_List;
+      T_Left_Paren;
+
+      --  It's quite tricky to disentangle these two possibilities, so we do
+      --  a prescan to determine which case we have and then reset the scan.
+      --  The prescan skips past possible subtype mark tokens.
+
+      Save_Scan_State (Scan_State); -- just after paren
+
+      while Token in Token_Class_Desig or else
+            Token = Tok_Dot or else
+            Token = Tok_Apostrophe -- because of 'BASE, 'CLASS
+      loop
+         Scan;
+      end loop;
+
+      --  If we end up on RANGE <> then we have the unconstrained case. We
+      --  will also allow the RANGE to be omitted, just to improve error
+      --  handling for a case like array (integer <>) of integer;
+
+      Scan; -- past possible RANGE or <>
+
+      if (Prev_Token = Tok_Range and then Token = Tok_Box) or else
+         Prev_Token = Tok_Box
+      then
+         Def_Node := New_Node (N_Unconstrained_Array_Definition, Array_Loc);
+         Restore_Scan_State (Scan_State); -- to first subtype mark
+
+         loop
+            Append (P_Subtype_Mark_Resync, Subs_List);
+            T_Range;
+            T_Box;
+            exit when Token = Tok_Right_Paren or else Token = Tok_Of;
+            T_Comma;
+         end loop;
+
+         Set_Subtype_Marks (Def_Node, Subs_List);
+
+      else
+         Def_Node := New_Node (N_Constrained_Array_Definition, Array_Loc);
+         Restore_Scan_State (Scan_State); -- to first discrete range
+
+         loop
+            Append (P_Discrete_Subtype_Definition, Subs_List);
+            exit when not Comma_Present;
+         end loop;
+
+         Set_Discrete_Subtype_Definitions (Def_Node, Subs_List);
+      end if;
+
+      T_Right_Paren;
+      T_Of;
+
+      if Token = Tok_Aliased then
+         Set_Aliased_Present (Def_Node, True);
+         Scan; -- past ALIASED
+      end if;
+
+      Set_Subtype_Indication (Def_Node, P_Subtype_Indication);
+      return Def_Node;
+   end P_Array_Type_Definition;
+
+   -----------------------------------------
+   -- 3.6  Unconstrained Array Definition --
+   -----------------------------------------
+
+   --  Parsed by P_Array_Type_Definition (3.6)
+
+   ---------------------------------------
+   -- 3.6  Constrained Array Definition --
+   ---------------------------------------
+
+   --  Parsed by P_Array_Type_Definition (3.6)
+
+   --------------------------------------
+   -- 3.6  Discrete Subtype Definition --
+   --------------------------------------
+
+   --  DISCRETE_SUBTYPE_DEFINITION ::=
+   --    discrete_SUBTYPE_INDICATION | RANGE
+
+   --  Note: the discrete subtype definition appearing in a constrained
+   --  array definition is parsed by P_Array_Type_Definition (3.6)
+
+   --  Error recovery: cannot raise Error_Resync
+
+   function P_Discrete_Subtype_Definition return Node_Id is
+   begin
+
+      --  The syntax of a discrete subtype definition is identical to that
+      --  of a discrete range, so we simply share the same parsing code.
+
+      return P_Discrete_Range;
+   end P_Discrete_Subtype_Definition;
+
+   -------------------------------
+   -- 3.6  Component Definition --
+   -------------------------------
+
+   --  For the array case, parsed by P_Array_Type_Definition (3.6)
+   --  For the record case, parsed by P_Component_Declaration (3.8)
+
+   -----------------------------
+   -- 3.6.1  Index Constraint --
+   -----------------------------
+
+   --  Parsed by P_Index_Or_Discriminant_Constraint (3.7.1)
+
+   ---------------------------
+   -- 3.6.1  Discrete Range --
+   ---------------------------
+
+   --  DISCRETE_RANGE ::= discrete_SUBTYPE_INDICATION | RANGE
+
+   --  The possible forms for a discrete range are:
+
+      --   Subtype_Mark                           (SUBTYPE_INDICATION, 3.2.2)
+      --   Subtype_Mark range Range               (SUBTYPE_INDICATION, 3.2.2)
+      --   Range_Attribute                        (RANGE, 3.5)
+      --   Simple_Expression .. Simple_Expression (RANGE, 3.5)
+
+   --  Error recovery: cannot raise Error_Resync
+
+   function P_Discrete_Range return Node_Id is
+      Expr_Node  : Node_Id;
+      Range_Node : Node_Id;
+
+   begin
+      Expr_Node := P_Simple_Expression_Or_Range_Attribute;
+
+      if Expr_Form = EF_Range_Attr then
+         return Expr_Node;
+
+      elsif Token = Tok_Range then
+         if Expr_Form /= EF_Simple_Name then
+            Error_Msg_SC ("range must be preceded by subtype mark");
+         end if;
+
+         return P_Subtype_Indication (Expr_Node);
+
+      --  Check Expression .. Expression case
+
+      elsif Token = Tok_Dot_Dot then
+         Range_Node := New_Node (N_Range, Token_Ptr);
+         Set_Low_Bound (Range_Node, Expr_Node);
+         Scan; -- past ..
+         Expr_Node := P_Expression;
+         Check_Simple_Expression (Expr_Node);
+         Set_High_Bound (Range_Node, Expr_Node);
+         return Range_Node;
+
+      --  Otherwise we must have a subtype mark
+
+      elsif Expr_Form = EF_Simple_Name then
+         return Expr_Node;
+
+      --  If incorrect, complain that we expect ..
+
+      else
+         T_Dot_Dot;
+         return Expr_Node;
+      end if;
+   end P_Discrete_Range;
+
+   ----------------------------
+   -- 3.7  Discriminant Part --
+   ----------------------------
+
+   --  DISCRIMINANT_PART ::=
+   --    UNKNOWN_DISCRIMINANT_PART
+   --  | KNOWN_DISCRIMINANT_PART
+
+   --  A discriminant part is parsed by P_Known_Discriminant_Part_Opt (3.7)
+   --  or P_Unknown_Discriminant_Part (3.7), since we know which we want.
+
+   ------------------------------------
+   -- 3.7  Unknown Discriminant Part --
+   ------------------------------------
+
+   --  UNKNOWN_DISCRIMINANT_PART ::= (<>)
+
+   --  If no unknown discriminant part is present, then False is returned,
+   --  otherwise the unknown discriminant is scanned out and True is returned.
+
+   --  Error recovery: cannot raise Error_Resync
+
+   function P_Unknown_Discriminant_Part_Opt return Boolean is
+      Scan_State : Saved_Scan_State;
+
+   begin
+      if Token /= Tok_Left_Paren then
+         return False;
+
+      else
+         Save_Scan_State (Scan_State);
+         Scan; -- past the left paren
+
+         if Token = Tok_Box then
+
+            if Ada_83 then
+               Error_Msg_SC ("(Ada 83) unknown discriminant not allowed!");
+            end if;
+
+            Scan; -- past the box
+            T_Right_Paren; -- must be followed by right paren
+            return True;
+
+         else
+            Restore_Scan_State (Scan_State);
+            return False;
+         end if;
+      end if;
+   end P_Unknown_Discriminant_Part_Opt;
+
+   ----------------------------------
+   -- 3.7  Known Discriminant Part --
+   ----------------------------------
+
+   --  KNOWN_DISCRIMINANT_PART ::=
+   --    (DISCRIMINANT_SPECIFICATION {; DISCRIMINANT_SPECIFICATION})
+
+   --  DISCRIMINANT_SPECIFICATION ::=
+   --    DEFINING_IDENTIFIER_LIST : SUBTYPE_MARK
+   --      [:= DEFAULT_EXPRESSION]
+   --  | DEFINING_IDENTIFIER_LIST : ACCESS_DEFINITION
+   --      [:= DEFAULT_EXPRESSION]
+
+   --  If no known discriminant part is present, then No_List is returned
+
+   --  Error recovery: cannot raise Error_Resync
+
+   function P_Known_Discriminant_Part_Opt return List_Id is
+      Specification_Node : Node_Id;
+      Specification_List : List_Id;
+      Ident_Sloc         : Source_Ptr;
+      Scan_State         : Saved_Scan_State;
+      Num_Idents         : Nat;
+      Ident              : Nat;
+
+      Idents : array (Int range 1 .. 4096) of Entity_Id;
+      --  This array holds the list of defining identifiers. The upper bound
+      --  of 4096 is intended to be essentially infinite, and we do not even
+      --  bother to check for it being exceeded.
+
+   begin
+      if Token = Tok_Left_Paren then
+         Specification_List := New_List;
+         Scan; -- past (
+         P_Pragmas_Misplaced;
+
+         Specification_Loop : loop
+
+            Ident_Sloc := Token_Ptr;
+            Idents (1) := P_Defining_Identifier;
+            Num_Idents := 1;
+
+            while Comma_Present loop
+               Num_Idents := Num_Idents + 1;
+               Idents (Num_Idents) := P_Defining_Identifier;
+            end loop;
+
+            T_Colon;
+
+            --  If there are multiple identifiers, we repeatedly scan the
+            --  type and initialization expression information by resetting
+            --  the scan pointer (so that we get completely separate trees
+            --  for each occurrence).
+
+            if Num_Idents > 1 then
+               Save_Scan_State (Scan_State);
+            end if;
+
+            --  Loop through defining identifiers in list
+
+            Ident := 1;
+            Ident_Loop : loop
+               Specification_Node :=
+                 New_Node (N_Discriminant_Specification, Ident_Sloc);
+               Set_Defining_Identifier (Specification_Node, Idents (Ident));
+
+               if Token = Tok_Access then
+                  if Ada_83 then
+                     Error_Msg_SC
+                       ("(Ada 83) access discriminant not allowed!");
+                  end if;
+
+                  Set_Discriminant_Type
+                    (Specification_Node, P_Access_Definition);
+               else
+                  Set_Discriminant_Type
+                    (Specification_Node, P_Subtype_Mark);
+                  No_Constraint;
+               end if;
+
+               Set_Expression
+                 (Specification_Node, Init_Expr_Opt (True));
+
+               if Ident > 1 then
+                  Set_Prev_Ids (Specification_Node, True);
+               end if;
+
+               if Ident < Num_Idents then
+                  Set_More_Ids (Specification_Node, True);
+               end if;
+
+               Append (Specification_Node, Specification_List);
+               exit Ident_Loop when Ident = Num_Idents;
+               Ident := Ident + 1;
+               Restore_Scan_State (Scan_State);
+            end loop Ident_Loop;
+
+            exit Specification_Loop when Token /= Tok_Semicolon;
+            Scan; -- past ;
+            P_Pragmas_Misplaced;
+         end loop Specification_Loop;
+
+         T_Right_Paren;
+         return Specification_List;
+
+      else
+         return No_List;
+      end if;
+   end P_Known_Discriminant_Part_Opt;
+
+   -------------------------------------
+   -- 3.7  DIscriminant Specification --
+   -------------------------------------
+
+   --  Parsed by P_Known_Discriminant_Part_Opt (3.7)
+
+   -----------------------------
+   -- 3.7  Default Expression --
+   -----------------------------
+
+   --  Always parsed (simply as an Expression) by the parent construct
+
+   ------------------------------------
+   -- 3.7.1  Discriminant Constraint --
+   ------------------------------------
+
+   --  Parsed by P_Index_Or_Discriminant_Constraint (3.7.1)
+
+   --------------------------------------------------------
+   -- 3.7.1  Index or Discriminant Constraint (also 3.6) --
+   --------------------------------------------------------
+
+   --  DISCRIMINANT_CONSTRAINT ::=
+   --    (DISCRIMINANT_ASSOCIATION {, DISCRIMINANT_ASSOCIATION})
+
+   --  DISCRIMINANT_ASSOCIATION ::=
+   --    [discriminant_SELECTOR_NAME {| discriminant_SELECTOR_NAME} =>]
+   --      EXPRESSION
+
+   --  This routine parses either an index or a discriminant constraint. As
+   --  is clear from the above grammar, it is often possible to clearly
+   --  determine which of the two possibilities we have, but there are
+   --  cases (those in which we have a series of expressions of the same
+   --  syntactic form as subtype indications), where we cannot tell. Since
+   --  this means that in any case the semantic phase has to distinguish
+   --  between the two, there is not much point in the parser trying to
+   --  distinguish even those cases where the difference is clear. In any
+   --  case, if we have a situation like:
+
+   --     (A => 123, 235 .. 500)
+
+   --  it is not clear which of the two items is the wrong one, better to
+   --  let the semantic phase give a clear message. Consequently, this
+   --  routine in general returns a list of items which can be either
+   --  discrete ranges or discriminant associations.
+
+   --  The caller has checked that the initial token is a left paren
+
+   --  Error recovery: can raise Error_Resync
+
+   function P_Index_Or_Discriminant_Constraint return Node_Id is
+      Scan_State  : Saved_Scan_State;
+      Constr_Node : Node_Id;
+      Constr_List : List_Id;
+      Expr_Node   : Node_Id;
+      Result_Node : Node_Id;
+
+   begin
+      Result_Node := New_Node (N_Index_Or_Discriminant_Constraint, Token_Ptr);
+      Scan; -- past (
+      Constr_List := New_List;
+      Set_Constraints (Result_Node, Constr_List);
+
+      --  The two syntactic forms are a little mixed up, so what we are doing
+      --  here is looking at the first entry to determine which case we have
+
+      --  A discriminant constraint is a list of discriminant associations,
+      --  which have one of the following possible forms:
+
+      --    Expression
+      --    Id => Expression
+      --    Id | Id | .. | Id => Expression
+
+      --  An index constraint is a list of discrete ranges which have one
+      --  of the following possible forms:
+
+      --    Subtype_Mark
+      --    Subtype_Mark range Range
+      --    Range_Attribute
+      --    Simple_Expression .. Simple_Expression
+
+      --  Loop through discriminants in list
+
+      loop
+         --  Check cases of Id => Expression or Id | Id => Expression
+
+         if Token = Tok_Identifier then
+            Save_Scan_State (Scan_State); -- at Id
+            Scan; -- past Id
+
+            if Token = Tok_Arrow or else Token = Tok_Vertical_Bar then
+               Restore_Scan_State (Scan_State); -- to Id
+               Append (P_Discriminant_Association, Constr_List);
+               goto Loop_Continue;
+            else
+               Restore_Scan_State (Scan_State); -- to Id
+            end if;
+         end if;
+
+         --  Otherwise scan out an expression and see what we have got
+
+         Expr_Node := P_Expression_Or_Range_Attribute;
+
+         if Expr_Form = EF_Range_Attr then
+            Append (Expr_Node, Constr_List);
+
+         elsif Token = Tok_Range then
+            if Expr_Form /= EF_Simple_Name then
+               Error_Msg_SC ("subtype mark required before RANGE");
+            end if;
+
+            Append (P_Subtype_Indication (Expr_Node), Constr_List);
+            goto Loop_Continue;
+
+         --  Check Simple_Expression .. Simple_Expression case
+
+         elsif Token = Tok_Dot_Dot then
+            Check_Simple_Expression (Expr_Node);
+            Constr_Node := New_Node (N_Range, Token_Ptr);
+            Set_Low_Bound (Constr_Node, Expr_Node);
+            Scan; -- past ..
+            Expr_Node := P_Expression;
+            Check_Simple_Expression (Expr_Node);
+            Set_High_Bound (Constr_Node, Expr_Node);
+            Append (Constr_Node, Constr_List);
+            goto Loop_Continue;
+
+         --  Case of an expression which could be either form
+
+         else
+            Append (Expr_Node, Constr_List);
+            goto Loop_Continue;
+         end if;
+
+         --  Here with a single entry scanned
+
+         <<Loop_Continue>>
+            exit when not Comma_Present;
+
+      end loop;
+
+      T_Right_Paren;
+      return Result_Node;
+
+   end P_Index_Or_Discriminant_Constraint;
+
+   -------------------------------------
+   -- 3.7.1  Discriminant Association --
+   -------------------------------------
+
+   --  DISCRIMINANT_ASSOCIATION ::=
+   --    [discriminant_SELECTOR_NAME {| discriminant_SELECTOR_NAME} =>]
+   --      EXPRESSION
+
+   --  This routine is used only when the name list is present and the caller
+   --  has already checked this (by scanning ahead and repositioning the
+   --  scan).
+
+   --  Error_Recovery: cannot raise Error_Resync;
+
+   function P_Discriminant_Association return Node_Id is
+      Discr_Node : Node_Id;
+      Names_List : List_Id;
+      Ident_Sloc : Source_Ptr;
+
+   begin
+      Ident_Sloc := Token_Ptr;
+      Names_List := New_List;
+
+      loop
+         Append (P_Identifier, Names_List);
+         exit when Token /= Tok_Vertical_Bar;
+         Scan; -- past |
+      end loop;
+
+      Discr_Node := New_Node (N_Discriminant_Association, Ident_Sloc);
+      Set_Selector_Names (Discr_Node, Names_List);
+      TF_Arrow;
+      Set_Expression (Discr_Node, P_Expression);
+      return Discr_Node;
+   end P_Discriminant_Association;
+
+   ---------------------------------
+   -- 3.8  Record Type Definition --
+   ---------------------------------
+
+   --  RECORD_TYPE_DEFINITION ::=
+   --    [[abstract] tagged] [limited] RECORD_DEFINITION
+
+   --  There is no node in the tree for a record type definition. Instead
+   --  a record definition node appears, with possible Abstract_Present,
+   --  Tagged_Present, and Limited_Present flags set appropriately.
+
+   ----------------------------
+   -- 3.8  Record Definition --
+   ----------------------------
+
+   --  RECORD_DEFINITION ::=
+   --    record
+   --      COMPONENT_LIST
+   --    end record
+   --  | null record
+
+   --  Note: in the case where a record definition node is used to represent
+   --  a record type definition, the caller sets the Tagged_Present and
+   --  Limited_Present flags in the resulting N_Record_Definition node as
+   --  required.
+
+   --  Note that the RECORD token at the start may be missing in certain
+   --  error situations, so this function is expected to post the error
+
+   --  Error recovery: can raise Error_Resync
+
+   function P_Record_Definition return Node_Id is
+      Rec_Node : Node_Id;
+
+   begin
+      Rec_Node := New_Node (N_Record_Definition, Token_Ptr);
+
+      --  Null record case
+
+      if Token = Tok_Null then
+         Scan; -- past NULL
+         T_Record;
+         Set_Null_Present (Rec_Node, True);
+
+      --  Case starting with RECORD keyword. Build scope stack entry. For the
+      --  column, we use the first non-blank character on the line, to deal
+      --  with situations such as:
+
+      --    type X is record
+      --      ...
+      --    end record;
+
+      --  which is not official RM indentation, but is not uncommon usage
+
+      else
+         Push_Scope_Stack;
+         Scope.Table (Scope.Last).Etyp := E_Record;
+         Scope.Table (Scope.Last).Ecol := Start_Column;
+         Scope.Table (Scope.Last).Sloc := Token_Ptr;
+         Scope.Table (Scope.Last).Labl := Error;
+         Scope.Table (Scope.Last).Junk := (Token /= Tok_Record);
+
+         T_Record;
+
+         Set_Component_List (Rec_Node, P_Component_List);
+
+         loop
+            exit when Check_End;
+            Discard_Junk_Node (P_Component_List);
+         end loop;
+      end if;
+
+      return Rec_Node;
+   end P_Record_Definition;
+
+   -------------------------
+   -- 3.8  Component List --
+   -------------------------
+
+   --  COMPONENT_LIST ::=
+   --    COMPONENT_ITEM {COMPONENT_ITEM}
+   --  | {COMPONENT_ITEM} VARIANT_PART
+   --  | null;
+
+   --  Error recovery: cannot raise Error_Resync
+
+   function P_Component_List return Node_Id is
+      Component_List_Node : Node_Id;
+      Decls_List          : List_Id;
+      Scan_State          : Saved_Scan_State;
+
+   begin
+      Component_List_Node := New_Node (N_Component_List, Token_Ptr);
+      Decls_List := New_List;
+
+      if Token = Tok_Null then
+         Scan; -- past NULL
+         TF_Semicolon;
+         P_Pragmas_Opt (Decls_List);
+         Set_Null_Present (Component_List_Node, True);
+         return Component_List_Node;
+
+      else
+         P_Pragmas_Opt (Decls_List);
+
+         if Token /= Tok_Case then
+            Component_Scan_Loop : loop
+               P_Component_Items (Decls_List);
+               P_Pragmas_Opt (Decls_List);
+
+               exit Component_Scan_Loop when Token = Tok_End
+                 or else Token = Tok_Case
+                 or else Token = Tok_When;
+
+               --  We are done if we do not have an identifier. However, if
+               --  we have a misspelled reserved identifier that is in a column
+               --  to the right of the record definition, we will treat it as
+               --  an identifier. It turns out to be too dangerous in practice
+               --  to accept such a mis-spelled identifier which does not have
+               --  this additional clue that confirms the incorrect spelling.
+
+               if Token /= Tok_Identifier then
+                  if Start_Column > Scope.Table (Scope.Last).Ecol
+                    and then Is_Reserved_Identifier
+                  then
+                     Save_Scan_State (Scan_State); -- at reserved id
+                     Scan; -- possible reserved id
+
+                     if Token = Tok_Comma or else Token = Tok_Colon then
+                        Restore_Scan_State (Scan_State);
+                        Scan_Reserved_Identifier (Force_Msg => True);
+
+                     --  Note reserved identifier used as field name after
+                     --  all because not followed by colon or comma
+
+                     else
+                        Restore_Scan_State (Scan_State);
+                        exit Component_Scan_Loop;
+                     end if;
+
+                  --  Non-identifier that definitely was not reserved id
+
+                  else
+                     exit Component_Scan_Loop;
+                  end if;
+               end if;
+            end loop Component_Scan_Loop;
+         end if;
+
+         if Token = Tok_Case then
+            Set_Variant_Part (Component_List_Node, P_Variant_Part);
+
+            --  Check for junk after variant part
+
+            if Token = Tok_Identifier then
+               Save_Scan_State (Scan_State);
+               Scan; -- past identifier
+
+               if Token = Tok_Colon then
+                  Restore_Scan_State (Scan_State);
+                  Error_Msg_SC ("component may not follow variant part");
+                  Discard_Junk_Node (P_Component_List);
+
+               elsif Token = Tok_Case then
+                  Restore_Scan_State (Scan_State);
+                  Error_Msg_SC ("only one variant part allowed in a record");
+                  Discard_Junk_Node (P_Component_List);
+
+               else
+                  Restore_Scan_State (Scan_State);
+               end if;
+            end if;
+         end if;
+      end if;
+
+      Set_Component_Items (Component_List_Node, Decls_List);
+      return Component_List_Node;
+
+   end P_Component_List;
+
+   -------------------------
+   -- 3.8  Component Item --
+   -------------------------
+
+   --  COMPONENT_ITEM ::= COMPONENT_DECLARATION | REPRESENTATION_CLAUSE
+
+   --  COMPONENT_DECLARATION ::=
+   --    DEFINING_IDENTIFIER_LIST : COMPONENT_DEFINITION
+   --      [:= DEFAULT_EXPRESSION];
+
+   --  COMPONENT_DEFINITION ::= [aliased] SUBTYPE_INDICATION
+
+   --  Error recovery: cannot raise Error_Resync, if an error occurs,
+   --  the scan is positioned past the following semicolon.
+
+   --  Note: we do not yet allow representation clauses to appear as component
+   --  items, do we need to add this capability sometime in the future ???
+
+   procedure P_Component_Items (Decls : List_Id) is
+      Decl_Node  : Node_Id;
+      Scan_State : Saved_Scan_State;
+      Num_Idents : Nat;
+      Ident      : Nat;
+      Ident_Sloc : Source_Ptr;
+
+      Idents : array (Int range 1 .. 4096) of Entity_Id;
+      --  This array holds the list of defining identifiers. The upper bound
+      --  of 4096 is intended to be essentially infinite, and we do not even
+      --  bother to check for it being exceeded.
+
+   begin
+      if Token /= Tok_Identifier then
+         Error_Msg_SC ("component declaration expected");
+         Resync_Past_Semicolon;
+         return;
+      end if;
+
+      Ident_Sloc := Token_Ptr;
+      Idents (1) := P_Defining_Identifier;
+      Num_Idents := 1;
+
+      while Comma_Present loop
+         Num_Idents := Num_Idents + 1;
+         Idents (Num_Idents) := P_Defining_Identifier;
+      end loop;
+
+      T_Colon;
+
+      --  If there are multiple identifiers, we repeatedly scan the
+      --  type and initialization expression information by resetting
+      --  the scan pointer (so that we get completely separate trees
+      --  for each occurrence).
+
+      if Num_Idents > 1 then
+         Save_Scan_State (Scan_State);
+      end if;
+
+      --  Loop through defining identifiers in list
+
+      Ident := 1;
+      Ident_Loop : loop
+
+         --  The following block is present to catch Error_Resync
+         --  which causes the parse to be reset past the semicolon
+
+         begin
+            Decl_Node := New_Node (N_Component_Declaration, Ident_Sloc);
+            Set_Defining_Identifier (Decl_Node, Idents (Ident));
+
+            if Token = Tok_Constant then
+               Error_Msg_SC ("constant components are not permitted");
+               Scan;
+            end if;
+
+            if Token_Name = Name_Aliased then
+               Check_95_Keyword (Tok_Aliased, Tok_Identifier);
+            end if;
+
+            if Token = Tok_Aliased then
+               Scan; -- past ALIASED
+               Set_Aliased_Present (Decl_Node, True);
+            end if;
+
+            if Token = Tok_Array then
+               Error_Msg_SC ("anonymous arrays not allowed as components");
+               raise Error_Resync;
+            end if;
+
+            Set_Subtype_Indication (Decl_Node, P_Subtype_Indication);
+            Set_Expression (Decl_Node, Init_Expr_Opt);
+
+            if Ident > 1 then
+               Set_Prev_Ids (Decl_Node, True);
+            end if;
+
+            if Ident < Num_Idents then
+               Set_More_Ids (Decl_Node, True);
+            end if;
+
+            Append (Decl_Node, Decls);
+
+         exception
+            when Error_Resync =>
+               if Token /= Tok_End then
+                  Resync_Past_Semicolon;
+               end if;
+         end;
+
+         exit Ident_Loop when Ident = Num_Idents;
+         Ident := Ident + 1;
+         Restore_Scan_State (Scan_State);
+
+      end loop Ident_Loop;
+
+      TF_Semicolon;
+
+   end P_Component_Items;
+
+   --------------------------------
+   -- 3.8  Component Declaration --
+   --------------------------------
+
+   --  Parsed by P_Component_Items (3.8)
+
+   -------------------------
+   -- 3.8.1  Variant Part --
+   -------------------------
+
+   --  VARIANT_PART ::=
+   --    case discriminant_DIRECT_NAME is
+   --      VARIANT
+   --      {VARIANT}
+   --    end case;
+
+   --  The caller has checked that the initial token is CASE
+
+   --  Error recovery: cannot raise Error_Resync
+
+   function P_Variant_Part return Node_Id is
+      Variant_Part_Node : Node_Id;
+      Variants_List     : List_Id;
+      Case_Node         : Node_Id;
+      Case_Sloc         : Source_Ptr;
+
+   begin
+      Variant_Part_Node := New_Node (N_Variant_Part, Token_Ptr);
+      Push_Scope_Stack;
+      Scope.Table (Scope.Last).Etyp := E_Case;
+      Scope.Table (Scope.Last).Sloc := Token_Ptr;
+      Scope.Table (Scope.Last).Ecol := Start_Column;
+
+      Scan; -- past CASE
+      Case_Node := P_Expression;
+      Case_Sloc := Token_Ptr;
+      Set_Name (Variant_Part_Node, Case_Node);
+
+      if Nkind (Case_Node) /= N_Identifier then
+         Set_Name (Variant_Part_Node, Error);
+         Error_Msg ("discriminant name expected", Sloc (Case_Node));
+      end if;
+
+      TF_Is;
+      Variants_List := New_List;
+      P_Pragmas_Opt (Variants_List);
+
+      --  Test missing variant
+
+      if Token = Tok_End then
+         Error_Msg_BC ("WHEN expected (must have at least one variant)");
+      else
+         Append (P_Variant, Variants_List);
+      end if;
+
+      --  Loop through variants, note that we allow if in place of when,
+      --  this error will be detected and handled in P_Variant.
+
+      loop
+         P_Pragmas_Opt (Variants_List);
+
+         if Token /= Tok_When
+           and then Token /= Tok_If
+           and then Token /= Tok_Others
+         then
+            exit when Check_End;
+         end if;
+
+         Append (P_Variant, Variants_List);
+      end loop;
+
+      Set_Variants (Variant_Part_Node, Variants_List);
+      return Variant_Part_Node;
+
+   end P_Variant_Part;
+
+   --------------------
+   -- 3.8.1  Variant --
+   --------------------
+
+   --  VARIANT ::=
+   --    when DISCRETE_CHOICE_LIST =>
+   --      COMPONENT_LIST
+
+   --  Error recovery: cannot raise Error_Resync
+
+   --  The initial token on entry is either WHEN, IF or OTHERS
+
+   function P_Variant return Node_Id is
+      Variant_Node : Node_Id;
+
+   begin
+      --  Special check to recover nicely from use of IF in place of WHEN
+
+      if Token = Tok_If then
+         T_When;
+         Scan; -- past IF
+      else
+         T_When;
+      end if;
+
+      Variant_Node := New_Node (N_Variant, Prev_Token_Ptr);
+      Set_Discrete_Choices (Variant_Node, P_Discrete_Choice_List);
+      TF_Arrow;
+      Set_Component_List (Variant_Node, P_Component_List);
+      return Variant_Node;
+   end P_Variant;
+
+   ---------------------------------
+   -- 3.8.1  Discrete Choice List --
+   ---------------------------------
+
+   --  DISCRETE_CHOICE_LIST ::= DISCRETE_CHOICE {| DISCRETE_CHOICE}
+
+   --  DISCRETE_CHOICE ::= EXPRESSION | DISCRETE_RANGE | others
+
+   --  Note: in Ada 83, the expression must be a simple expression
+
+   --  Error recovery: cannot raise Error_Resync
+
+   function P_Discrete_Choice_List return List_Id is
+      Choices     : List_Id;
+      Expr_Node   : Node_Id;
+      Choice_Node : Node_Id;
+
+   begin
+      Choices := New_List;
+
+      loop
+         if Token = Tok_Others then
+            Append (New_Node (N_Others_Choice, Token_Ptr), Choices);
+            Scan; -- past OTHERS
+
+         else
+            begin
+               Expr_Node := No_Right_Paren (P_Expression_Or_Range_Attribute);
+
+               if Token = Tok_Colon
+                 and then Nkind (Expr_Node) = N_Identifier
+               then
+                  Error_Msg_SP ("label not permitted in this context");
+                  Scan; -- past colon
+
+               elsif Expr_Form = EF_Range_Attr then
+                  Append (Expr_Node, Choices);
+
+               elsif Token = Tok_Dot_Dot then
+                  Check_Simple_Expression (Expr_Node);
+                  Choice_Node := New_Node (N_Range, Token_Ptr);
+                  Set_Low_Bound (Choice_Node, Expr_Node);
+                  Scan; -- past ..
+                  Expr_Node := P_Expression_No_Right_Paren;
+                  Check_Simple_Expression (Expr_Node);
+                  Set_High_Bound (Choice_Node, Expr_Node);
+                  Append (Choice_Node, Choices);
+
+               elsif Expr_Form = EF_Simple_Name then
+                  if Token = Tok_Range then
+                     Append (P_Subtype_Indication (Expr_Node), Choices);
+
+                  elsif Token in Token_Class_Consk then
+                     Error_Msg_SC
+                        ("the only constraint allowed here " &
+                         "is a range constraint");
+                     Discard_Junk_Node (P_Constraint_Opt);
+                     Append (Expr_Node, Choices);
+
+                  else
+                     Append (Expr_Node, Choices);
+                  end if;
+
+               else
+                  Check_Simple_Expression_In_Ada_83 (Expr_Node);
+                  Append (Expr_Node, Choices);
+               end if;
+
+            exception
+               when Error_Resync =>
+                  Resync_Choice;
+                  return Error_List;
+            end;
+         end if;
+
+         if Token = Tok_Comma then
+            Error_Msg_SC (""","" should be ""|""");
+         else
+            exit when Token /= Tok_Vertical_Bar;
+         end if;
+
+         Scan; -- past | or comma
+      end loop;
+
+      return Choices;
+   end P_Discrete_Choice_List;
+
+   ----------------------------
+   -- 3.8.1  Discrete Choice --
+   ----------------------------
+
+   --  Parsed by P_Discrete_Choice_List (3.8.1)
+
+   ----------------------------------
+   -- 3.9.1  Record Extension Part --
+   ----------------------------------
+
+   --  RECORD_EXTENSION_PART ::= with RECORD_DEFINITION
+
+   --  Parsed by P_Derived_Type_Def_Or_Private_Ext_Decl (3.4)
+
+   ----------------------------------
+   -- 3.10  Access Type Definition --
+   ----------------------------------
+
+   --  ACCESS_TYPE_DEFINITION ::=
+   --    ACCESS_TO_OBJECT_DEFINITION
+   --  | ACCESS_TO_SUBPROGRAM_DEFINITION
+
+   --  ACCESS_TO_OBJECT_DEFINITION ::=
+   --    access [GENERAL_ACCESS_MODIFIER] SUBTYPE_INDICATION
+
+   --  GENERAL_ACCESS_MODIFIER ::= all | constant
+
+   --  ACCESS_TO_SUBPROGRAM_DEFINITION
+   --    access [protected] procedure PARAMETER_PROFILE
+   --  | access [protected] function PARAMETER_AND_RESULT_PROFILE
+
+   --  PARAMETER_PROFILE ::= [FORMAL_PART]
+
+   --  PARAMETER_AND_RESULT_PROFILE ::= [FORMAL_PART] RETURN SUBTYPE_MARK
+
+   --  The caller has checked that the initial token is ACCESS
+
+   --  Error recovery: can raise Error_Resync
+
+   function P_Access_Type_Definition return Node_Id is
+      Prot_Flag     : Boolean;
+      Access_Loc    : Source_Ptr;
+      Type_Def_Node : Node_Id;
+
+      procedure Check_Junk_Subprogram_Name;
+      --  Used in access to subprogram definition cases to check for an
+      --  identifier or operator symbol that does not belong.
+
+      procedure Check_Junk_Subprogram_Name is
+         Saved_State : Saved_Scan_State;
+
+      begin
+         if Token = Tok_Identifier or else Token = Tok_Operator_Symbol then
+            Save_Scan_State (Saved_State);
+            Scan; -- past possible junk subprogram name
+
+            if Token = Tok_Left_Paren or else Token = Tok_Semicolon then
+               Error_Msg_SP ("unexpected subprogram name ignored");
+               return;
+
+            else
+               Restore_Scan_State (Saved_State);
+            end if;
+         end if;
+      end Check_Junk_Subprogram_Name;
+
+   --  Start of processing for P_Access_Type_Definition
+
+   begin
+      Access_Loc := Token_Ptr;
+      Scan; -- past ACCESS
+
+      if Token_Name = Name_Protected then
+         Check_95_Keyword (Tok_Protected, Tok_Procedure);
+         Check_95_Keyword (Tok_Protected, Tok_Function);
+      end if;
+
+      Prot_Flag := (Token = Tok_Protected);
+
+      if Prot_Flag then
+         Scan; -- past PROTECTED
+         if Token /= Tok_Procedure and then Token /= Tok_Function then
+            Error_Msg_SC ("FUNCTION or PROCEDURE expected");
+         end if;
+      end if;
+
+      if Token = Tok_Procedure then
+         if Ada_83 then
+            Error_Msg_SC ("(Ada 83) access to procedure not allowed!");
+         end if;
+
+         Type_Def_Node := New_Node (N_Access_Procedure_Definition, Access_Loc);
+         Scan; -- past PROCEDURE
+         Check_Junk_Subprogram_Name;
+         Set_Parameter_Specifications (Type_Def_Node, P_Parameter_Profile);
+         Set_Protected_Present (Type_Def_Node, Prot_Flag);
+
+      elsif Token = Tok_Function then
+         if Ada_83 then
+            Error_Msg_SC ("(Ada 83) access to function not allowed!");
+         end if;
+
+         Type_Def_Node := New_Node (N_Access_Function_Definition, Access_Loc);
+         Scan; -- past FUNCTION
+         Check_Junk_Subprogram_Name;
+         Set_Parameter_Specifications (Type_Def_Node, P_Parameter_Profile);
+         Set_Protected_Present (Type_Def_Node, Prot_Flag);
+         TF_Return;
+         Set_Subtype_Mark (Type_Def_Node, P_Subtype_Mark);
+         No_Constraint;
+
+      else
+         Type_Def_Node :=
+           New_Node (N_Access_To_Object_Definition, Access_Loc);
+
+         if Token = Tok_All or else Token = Tok_Constant then
+            if Ada_83 then
+               Error_Msg_SC ("(Ada 83) access modifier not allowed!");
+            end if;
+
+            if Token = Tok_All then
+               Set_All_Present (Type_Def_Node, True);
+
+            else
+               Set_Constant_Present (Type_Def_Node, True);
+            end if;
+
+            Scan; -- past ALL or CONSTANT
+         end if;
+
+         Set_Subtype_Indication (Type_Def_Node, P_Subtype_Indication);
+      end if;
+
+      return Type_Def_Node;
+   end P_Access_Type_Definition;
+
+   ---------------------------------------
+   -- 3.10  Access To Object Definition --
+   ---------------------------------------
+
+   --  Parsed by P_Access_Type_Definition (3.10)
+
+   -----------------------------------
+   -- 3.10  General Access Modifier --
+   -----------------------------------
+
+   --  Parsed by P_Access_Type_Definition (3.10)
+
+   -------------------------------------------
+   -- 3.10  Access To Subprogram Definition --
+   -------------------------------------------
+
+   --  Parsed by P_Access_Type_Definition (3.10)
+
+   -----------------------------
+   -- 3.10  Access Definition --
+   -----------------------------
+
+   --  ACCESS_DEFINITION ::= access SUBTYPE_MARK
+
+   --  The caller has checked that the initial token is ACCESS
+
+   --  Error recovery: cannot raise Error_Resync
+
+   function P_Access_Definition return Node_Id is
+      Def_Node : Node_Id;
+
+   begin
+      Def_Node := New_Node (N_Access_Definition, Token_Ptr);
+      Scan; -- past ACCESS
+      Set_Subtype_Mark (Def_Node, P_Subtype_Mark);
+      No_Constraint;
+      return Def_Node;
+   end P_Access_Definition;
+
+   -----------------------------------------
+   -- 3.10.1  Incomplete Type Declaration --
+   -----------------------------------------
+
+   --  Parsed by P_Type_Declaration (3.2.1)
+
+   ----------------------------
+   -- 3.11  Declarative Part --
+   ----------------------------
+
+   --  DECLARATIVE_PART ::= {DECLARATIVE_ITEM}
+
+   --  Error recovery: cannot raise Error_Resync (because P_Declarative_Items
+   --  handles errors, and returns cleanly after an error has occurred)
+
+   function P_Declarative_Part return List_Id is
+      Decls : List_Id;
+      Done  : Boolean;
+
+   begin
+      --  Indicate no bad declarations detected yet. This will be reset by
+      --  P_Declarative_Items if a bad declaration is discovered.
+
+      Missing_Begin_Msg := No_Error_Msg;
+
+      --  Get rid of active SIS entry from outer scope. This means we will
+      --  miss some nested cases, but it doesn't seem worth the effort. See
+      --  discussion in Par for further details
+
+      SIS_Entry_Active := False;
+      Decls := New_List;
+
+      --  Loop to scan out the declarations
+
+      loop
+         P_Declarative_Items (Decls, Done, In_Spec => False);
+         exit when Done;
+      end loop;
+
+      --  Get rid of active SIS entry which is left set only if we scanned a
+      --  procedure declaration and have not found the body. We could give
+      --  an error message, but that really would be usurping the role of
+      --  semantic analysis (this really is a missing body case).
+
+      SIS_Entry_Active := False;
+      return Decls;
+   end P_Declarative_Part;
+
+   ----------------------------
+   -- 3.11  Declarative Item --
+   ----------------------------
+
+   --  DECLARATIVE_ITEM ::= BASIC_DECLARATIVE_ITEM | BODY
+
+   --  Can return Error if a junk declaration is found, or Empty if no
+   --  declaration is found (i.e. a token ending declarations, such as
+   --  BEGIN or END is encountered).
+
+   --  Error recovery: cannot raise Error_Resync. If an error resync occurs,
+   --  then the scan is set past the next semicolon and Error is returned.
+
+   procedure P_Declarative_Items
+     (Decls   : List_Id;
+      Done    : out Boolean;
+      In_Spec : Boolean)
+   is
+      Scan_State : Saved_Scan_State;
+
+   begin
+      if Style_Check then Style.Check_Indentation; end if;
+
+      case Token is
+
+         when Tok_Function =>
+            Check_Bad_Layout;
+            Append (P_Subprogram (Pf_Decl_Gins_Pbod_Rnam_Stub), Decls);
+            Done := False;
+
+         when Tok_For =>
+            Check_Bad_Layout;
+
+            --  Check for loop (premature statement)
+
+            Save_Scan_State (Scan_State);
+            Scan; -- past FOR
+
+            if Token = Tok_Identifier then
+               Scan; -- past identifier
+
+               if Token = Tok_In then
+                  Restore_Scan_State (Scan_State);
+                  Statement_When_Declaration_Expected (Decls, Done, In_Spec);
+                  return;
+               end if;
+            end if;
+
+            --  Not a loop, so must be rep clause
+
+            Restore_Scan_State (Scan_State);
+            Append (P_Representation_Clause, Decls);
+            Done := False;
+
+         when Tok_Generic =>
+            Check_Bad_Layout;
+            Append (P_Generic, Decls);
+            Done := False;
+
+         when Tok_Identifier =>
+            Check_Bad_Layout;
+            P_Identifier_Declarations (Decls, Done, In_Spec);
+
+         when Tok_Package =>
+            Check_Bad_Layout;
+            Append (P_Package (Pf_Decl_Gins_Pbod_Rnam_Stub), Decls);
+            Done := False;
+
+         when Tok_Pragma =>
+            Append (P_Pragma, Decls);
+            Done := False;
+
+         when Tok_Procedure =>
+            Check_Bad_Layout;
+            Append (P_Subprogram (Pf_Decl_Gins_Pbod_Rnam_Stub), Decls);
+            Done := False;
+
+         when Tok_Protected =>
+            Check_Bad_Layout;
+            Scan; -- past PROTECTED
+            Append (P_Protected, Decls);
+            Done := False;
+
+         when Tok_Subtype =>
+            Check_Bad_Layout;
+            Append (P_Subtype_Declaration, Decls);
+            Done := False;
+
+         when Tok_Task =>
+            Check_Bad_Layout;
+            Scan; -- past TASK
+            Append (P_Task, Decls);
+            Done := False;
+
+         when Tok_Type =>
+            Check_Bad_Layout;
+            Append (P_Type_Declaration, Decls);
+            Done := False;
+
+         when Tok_Use =>
+            Check_Bad_Layout;
+            Append (P_Use_Clause, Decls);
+            Done := False;
+
+         when Tok_With =>
+            Check_Bad_Layout;
+            Error_Msg_SC ("WITH can only appear in context clause");
+            raise Error_Resync;
+
+         --  BEGIN terminates the scan of a sequence of declarations unless
+         --  there is a missing subprogram body, see section on handling
+         --  semicolon in place of IS. We only treat the begin as satisfying
+         --  the subprogram declaration if it falls in the expected column
+         --  or to its right.
+
+         when Tok_Begin =>
+            if SIS_Entry_Active and then Start_Column >= SIS_Ecol then
+
+               --  Here we have the case where a BEGIN is encountered during
+               --  declarations in a declarative part, or at the outer level,
+               --  and there is a subprogram declaration outstanding for which
+               --  no body has been supplied. This is the case where we assume
+               --  that the semicolon in the subprogram declaration should
+               --  really have been is. The active SIS entry describes the
+               --  subprogram declaration. On return the declaration has been
+               --  modified to become a body.
+
+               declare
+                  Specification_Node : Node_Id;
+                  Decl_Node          : Node_Id;
+                  Body_Node          : Node_Id;
+
+               begin
+                  --  First issue the error message. If we had a missing
+                  --  semicolon in the declaration, then change the message
+                  --  to <missing "is">
+
+                  if SIS_Missing_Semicolon_Message /= No_Error_Msg then
+                     Change_Error_Text     -- Replace: "missing "";"" "
+                       (SIS_Missing_Semicolon_Message, "missing ""is""");
+
+                  --  Otherwise we saved the semicolon position, so complain
+
+                  else
+                     Error_Msg (""";"" should be IS", SIS_Semicolon_Sloc);
+                  end if;
+
+                  --  The next job is to fix up any declarations that occurred
+                  --  between the procedure header and the BEGIN. These got
+                  --  chained to the outer declarative region (immediately
+                  --  after the procedure declaration) and they should be
+                  --  chained to the subprogram itself, which is a body
+                  --  rather than a spec.
+
+                  Specification_Node := Specification (SIS_Declaration_Node);
+                  Change_Node (SIS_Declaration_Node, N_Subprogram_Body);
+                  Body_Node := SIS_Declaration_Node;
+                  Set_Specification (Body_Node, Specification_Node);
+                  Set_Declarations (Body_Node, New_List);
+
+                  loop
+                     Decl_Node := Remove_Next (Body_Node);
+                     exit when Decl_Node = Empty;
+                     Append (Decl_Node, Declarations (Body_Node));
+                  end loop;
+
+                  --  Now make the scope table entry for the Begin-End and
+                  --  scan it out
+
+                  Push_Scope_Stack;
+                  Scope.Table (Scope.Last).Sloc := SIS_Sloc;
+                  Scope.Table (Scope.Last).Etyp := E_Name;
+                  Scope.Table (Scope.Last).Ecol := SIS_Ecol;
+                  Scope.Table (Scope.Last).Labl := SIS_Labl;
+                  Scope.Table (Scope.Last).Lreq := False;
+                  SIS_Entry_Active := False;
+                  Scan; -- past BEGIN
+                  Set_Handled_Statement_Sequence (Body_Node,
+                    P_Handled_Sequence_Of_Statements);
+                  End_Statements (Handled_Statement_Sequence (Body_Node));
+               end;
+
+               Done := False;
+
+            else
+               Done := True;
+            end if;
+
+            --  Normally an END terminates the scan for basic declarative
+            --  items. The one exception is END RECORD, which is probably
+            --  left over from some other junk.
+
+            when Tok_End =>
+               Save_Scan_State (Scan_State); -- at END
+               Scan; -- past END
+
+               if Token = Tok_Record then
+                  Error_Msg_SP ("no RECORD for this `end record`!");
+                  Scan; -- past RECORD
+                  TF_Semicolon;
+
+               else
+                  Restore_Scan_State (Scan_State); -- to END
+                  Done := True;
+               end if;
+
+         --  The following tokens which can only be the start of a statement
+         --  are considered to end a declarative part (i.e. we have a missing
+         --  BEGIN situation). We are fairly conservative in making this
+         --  judgment, because it is a real mess to go into statement mode
+         --  prematurely in reponse to a junk declaration.
+
+         when Tok_Abort     |
+              Tok_Accept    |
+              Tok_Declare   |
+              Tok_Delay     |
+              Tok_Exit      |
+              Tok_Goto      |
+              Tok_If        |
+              Tok_Loop      |
+              Tok_Null      |
+              Tok_Requeue   |
+              Tok_Select    |
+              Tok_While     =>
+
+            --  But before we decide that it's a statement, let's check for
+            --  a reserved word misused as an identifier.
+
+            if Is_Reserved_Identifier then
+               Save_Scan_State (Scan_State);
+               Scan; -- past the token
+
+               --  If reserved identifier not followed by colon or comma, then
+               --  this is most likely an assignment statement to the bad id.
+
+               if Token /= Tok_Colon and then Token /= Tok_Comma then
+                  Restore_Scan_State (Scan_State);
+                  Statement_When_Declaration_Expected (Decls, Done, In_Spec);
+                  return;
+
+               --  Otherwise we have a declaration of the bad id
+
+               else
+                  Restore_Scan_State (Scan_State);
+                  Scan_Reserved_Identifier (Force_Msg => True);
+                  P_Identifier_Declarations (Decls, Done, In_Spec);
+               end if;
+
+            --  If not reserved identifier, then it's definitely a statement
+
+            else
+               Statement_When_Declaration_Expected (Decls, Done, In_Spec);
+               return;
+            end if;
+
+         --  The token RETURN may well also signal a missing BEGIN situation,
+         --  however, we never let it end the declarative part, because it may
+         --  also be part of a half-baked function declaration.
+
+         when Tok_Return =>
+            Error_Msg_SC ("misplaced RETURN statement");
+            raise Error_Resync;
+
+         --  PRIVATE definitely terminates the declarations in a spec,
+         --  and is an error in a body.
+
+         when Tok_Private =>
+            if In_Spec then
+               Done := True;
+            else
+               Error_Msg_SC ("PRIVATE not allowed in body");
+               Scan; -- past PRIVATE
+            end if;
+
+         --  An end of file definitely terminates the declarations!
+
+         when Tok_EOF =>
+            Done := True;
+
+         --  The remaining tokens do not end the scan, but cannot start a
+         --  valid declaration, so we signal an error and resynchronize.
+         --  But first check for misuse of a reserved identifier.
+
+         when others =>
+
+            --  Here we check for a reserved identifier
+
+            if Is_Reserved_Identifier then
+               Save_Scan_State (Scan_State);
+               Scan; -- past the token
+
+               if Token /= Tok_Colon and then Token /= Tok_Comma then
+                  Restore_Scan_State (Scan_State);
+                  Set_Declaration_Expected;
+                  raise Error_Resync;
+               else
+                  Restore_Scan_State (Scan_State);
+                  Scan_Reserved_Identifier (Force_Msg => True);
+                  Check_Bad_Layout;
+                  P_Identifier_Declarations (Decls, Done, In_Spec);
+               end if;
+
+            else
+               Set_Declaration_Expected;
+               raise Error_Resync;
+            end if;
+      end case;
+
+   --  To resynchronize after an error, we scan to the next semicolon and
+   --  return with Done = False, indicating that there may still be more
+   --  valid declarations to come.
+
+   exception
+      when Error_Resync =>
+         Resync_Past_Semicolon;
+         Done := False;
+
+   end P_Declarative_Items;
+
+   ----------------------------------
+   -- 3.11  Basic Declarative Item --
+   ----------------------------------
+
+   --  BASIC_DECLARATIVE_ITEM ::=
+   --    BASIC_DECLARATION | REPRESENTATION_CLAUSE | USE_CLAUSE
+
+   --  Scan zero or more basic declarative items
+
+   --  Error recovery: cannot raise Error_Resync. If an error is detected, then
+   --  the scan pointer is repositioned past the next semicolon, and the scan
+   --  for declarative items continues.
+
+   function P_Basic_Declarative_Items return List_Id is
+      Decl  : Node_Id;
+      Decls : List_Id;
+      Kind  : Node_Kind;
+      Done  : Boolean;
+
+   begin
+      --  Get rid of active SIS entry from outer scope. This means we will
+      --  miss some nested cases, but it doesn't seem worth the effort. See
+      --  discussion in Par for further details
+
+      SIS_Entry_Active := False;
+
+      --  Loop to scan out declarations
+
+      Decls := New_List;
+
+      loop
+         P_Declarative_Items (Decls, Done, In_Spec => True);
+         exit when Done;
+      end loop;
+
+      --  Get rid of active SIS entry. This is set only if we have scanned a
+      --  procedure declaration and have not found the body. We could give
+      --  an error message, but that really would be usurping the role of
+      --  semantic analysis (this really is a case of a missing body).
+
+      SIS_Entry_Active := False;
+
+      --  Test for assorted illegal declarations not diagnosed elsewhere.
+
+      Decl := First (Decls);
+
+      while Present (Decl) loop
+         Kind := Nkind (Decl);
+
+         --  Test for body scanned, not acceptable as basic decl item
+
+         if Kind = N_Subprogram_Body or else
+            Kind = N_Package_Body or else
+            Kind = N_Task_Body or else
+            Kind = N_Protected_Body
+         then
+            Error_Msg
+              ("proper body not allowed in package spec", Sloc (Decl));
+
+         --  Test for body stub scanned, not acceptable as basic decl item
+
+         elsif Kind in N_Body_Stub then
+            Error_Msg
+              ("body stub not allowed in package spec", Sloc (Decl));
+
+         elsif Kind = N_Assignment_Statement then
+            Error_Msg
+              ("assignment statement not allowed in package spec",
+                 Sloc (Decl));
+         end if;
+
+         Next (Decl);
+      end loop;
+
+      return Decls;
+   end P_Basic_Declarative_Items;
+
+   ----------------
+   -- 3.11  Body --
+   ----------------
+
+   --  For proper body, see below
+   --  For body stub, see 10.1.3
+
+   -----------------------
+   -- 3.11  Proper Body --
+   -----------------------
+
+   --  Subprogram body is parsed by P_Subprogram (6.1)
+   --  Package body is parsed by P_Package (7.1)
+   --  Task body is parsed by P_Task (9.1)
+   --  Protected body is parsed by P_Protected (9.4)
+
+   ------------------------------
+   -- Set_Declaration_Expected --
+   ------------------------------
+
+   procedure Set_Declaration_Expected is
+   begin
+      Error_Msg_SC ("declaration expected");
+
+      if Missing_Begin_Msg = No_Error_Msg then
+         Missing_Begin_Msg := Get_Msg_Id;
+      end if;
+   end Set_Declaration_Expected;
+
+   ----------------------
+   -- Skip_Declaration --
+   ----------------------
+
+   procedure Skip_Declaration (S : List_Id) is
+      Dummy_Done : Boolean;
+
+   begin
+      P_Declarative_Items (S, Dummy_Done, False);
+   end Skip_Declaration;
+
+   -----------------------------------------
+   -- Statement_When_Declaration_Expected --
+   -----------------------------------------
+
+   procedure Statement_When_Declaration_Expected
+     (Decls   : List_Id;
+      Done    : out Boolean;
+      In_Spec : Boolean)
+   is
+   begin
+      --  Case of second occurrence of statement in one declaration sequence
+
+      if Missing_Begin_Msg /= No_Error_Msg then
+
+         --  In the procedure spec case, just ignore it, we only give one
+         --  message for the first occurrence, since otherwise we may get
+         --  horrible cascading if BODY was missing in the header line.
+
+         if In_Spec then
+            null;
+
+         --  In the declarative part case, take a second statement as a sure
+         --  sign that we really have a missing BEGIN, and end the declarative
+         --  part now. Note that the caller will fix up the first message to
+         --  say "missing BEGIN" so that's how the error will be signalled.
+
+         else
+            Done := True;
+            return;
+         end if;
+
+      --  Case of first occurrence of unexpected statement
+
+      else
+         --  If we are in a package spec, then give message of statement
+         --  not allowed in package spec. This message never gets changed.
+
+         if In_Spec then
+            Error_Msg_SC ("statement not allowed in package spec");
+
+         --  If in declarative part, then we give the message complaining
+         --  about finding a statement when a declaration is expected. This
+         --  gets changed to a complaint about a missing BEGIN if we later
+         --  find that no BEGIN is present.
+
+         else
+            Error_Msg_SC ("statement not allowed in declarative part");
+         end if;
+
+         --  Capture message Id. This is used for two purposes, first to
+         --  stop multiple messages, see test above, and second, to allow
+         --  the replacement of the message in the declarative part case.
+
+         Missing_Begin_Msg := Get_Msg_Id;
+      end if;
+
+      --  In all cases except the case in which we decided to terminate the
+      --  declaration sequence on a second error, we scan out the statement
+      --  and append it to the list of declarations (note that the semantics
+      --  can handle statements in a declaration list so if we proceed to
+      --  call the semantic phase, all will be (reasonably) well!
+
+      Append_List_To (Decls, P_Sequence_Of_Statements (SS_Unco));
+
+      --  Done is set to False, since we want to continue the scan of
+      --  declarations, hoping that this statement was a temporary glitch.
+      --  If we indeed are now in the statement part (i.e. this was a missing
+      --  BEGIN, then it's not terrible, we will simply keep calling this
+      --  procedure to process the statements one by one, and then finally
+      --  hit the missing BEGIN, which will clean up the error message.
+
+      Done := False;
+
+   end Statement_When_Declaration_Expected;
+
+end Ch3;
diff --git a/gcc/ada/par-ch4.adb b/gcc/ada/par-ch4.adb
new file mode 100644 (file)
index 0000000..30fba56
--- /dev/null
@@ -0,0 +1,2298 @@
+------------------------------------------------------------------------------
+--                                                                          --
+--                         GNAT COMPILER COMPONENTS                         --
+--                                                                          --
+--                              P A R . C H 4                               --
+--                                                                          --
+--                                 B o d y                                  --
+--                                                                          --
+--                            $Revision: 1.91 $
+--                                                                          --
+--          Copyright (C) 1992-2001 Free Software Foundation, Inc.          --
+--                                                                          --
+-- GNAT is free software;  you can  redistribute it  and/or modify it under --
+-- terms of the  GNU General Public License as published  by the Free Soft- --
+-- ware  Foundation;  either version 2,  or (at your option) any later ver- --
+-- sion.  GNAT is distributed in the hope that it will be useful, but WITH- --
+-- OUT 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  distributed with GNAT;  see file COPYING.  If not, write --
+-- to  the Free Software Foundation,  59 Temple Place - Suite 330,  Boston, --
+-- MA 02111-1307, USA.                                                      --
+--                                                                          --
+-- GNAT was originally developed  by the GNAT team at  New York University. --
+-- It is now maintained by Ada Core Technologies Inc (http://www.gnat.com). --
+--                                                                          --
+------------------------------------------------------------------------------
+
+pragma Style_Checks (All_Checks);
+--  Turn off subprogram body ordering check. Subprograms are in order
+--  by RM section rather than alphabetical
+
+separate (Par)
+package body Ch4 is
+
+   -----------------------
+   -- Local Subprograms --
+   -----------------------
+
+   function P_Aggregate_Or_Paren_Expr                 return Node_Id;
+   function P_Allocator                               return Node_Id;
+   function P_Record_Or_Array_Component_Association   return Node_Id;
+   function P_Factor                                  return Node_Id;
+   function P_Primary                                 return Node_Id;
+   function P_Relation                                return Node_Id;
+   function P_Term                                    return Node_Id;
+
+   function P_Binary_Adding_Operator                  return Node_Kind;
+   function P_Logical_Operator                        return Node_Kind;
+   function P_Multiplying_Operator                    return Node_Kind;
+   function P_Relational_Operator                     return Node_Kind;
+   function P_Unary_Adding_Operator                   return Node_Kind;
+
+   procedure Bad_Range_Attribute (Loc : Source_Ptr);
+   --  Called to place complaint about bad range attribute at the given
+   --  source location. Terminates by raising Error_Resync.
+
+   function P_Range_Attribute_Reference
+     (Prefix_Node : Node_Id)
+      return        Node_Id;
+   --  Scan a range attribute reference. The caller has scanned out the
+   --  prefix. The current token is known to be an apostrophe and the
+   --  following token is known to be RANGE.
+
+   procedure Set_Op_Name (Node : Node_Id);
+   --  Procedure to set name field (Chars) in operator node
+
+   -------------------------
+   -- Bad_Range_Attribute --
+   -------------------------
+
+   procedure Bad_Range_Attribute (Loc : Source_Ptr) is
+   begin
+      Error_Msg ("range attribute cannot be used in expression", Loc);
+      Resync_Expression;
+   end Bad_Range_Attribute;
+
+   ------------------
+   -- Set_Op_Name --
+   ------------------
+
+   procedure Set_Op_Name (Node : Node_Id) is
+      type Name_Of_Type is array (N_Op) of Name_Id;
+      Name_Of : Name_Of_Type := Name_Of_Type'(
+         N_Op_And                    => Name_Op_And,
+         N_Op_Or                     => Name_Op_Or,
+         N_Op_Xor                    => Name_Op_Xor,
+         N_Op_Eq                     => Name_Op_Eq,
+         N_Op_Ne                     => Name_Op_Ne,
+         N_Op_Lt                     => Name_Op_Lt,
+         N_Op_Le                     => Name_Op_Le,
+         N_Op_Gt                     => Name_Op_Gt,
+         N_Op_Ge                     => Name_Op_Ge,
+         N_Op_Add                    => Name_Op_Add,
+         N_Op_Subtract               => Name_Op_Subtract,
+         N_Op_Concat                 => Name_Op_Concat,
+         N_Op_Multiply               => Name_Op_Multiply,
+         N_Op_Divide                 => Name_Op_Divide,
+         N_Op_Mod                    => Name_Op_Mod,
+         N_Op_Rem                    => Name_Op_Rem,
+         N_Op_Expon                  => Name_Op_Expon,
+         N_Op_Plus                   => Name_Op_Add,
+         N_Op_Minus                  => Name_Op_Subtract,
+         N_Op_Abs                    => Name_Op_Abs,
+         N_Op_Not                    => Name_Op_Not,
+
+         --  We don't really need these shift operators, since they never
+         --  appear as operators in the source, but the path of least
+         --  resistance is to put them in (the aggregate must be complete)
+
+         N_Op_Rotate_Left            => Name_Rotate_Left,
+         N_Op_Rotate_Right           => Name_Rotate_Right,
+         N_Op_Shift_Left             => Name_Shift_Left,
+         N_Op_Shift_Right            => Name_Shift_Right,
+         N_Op_Shift_Right_Arithmetic => Name_Shift_Right_Arithmetic);
+
+   begin
+      if Nkind (Node) in N_Op then
+         Set_Chars (Node, Name_Of (Nkind (Node)));
+      end if;
+   end Set_Op_Name;
+
+   --------------------------
+   -- 4.1  Name (also 6.4) --
+   --------------------------
+
+   --  NAME ::=
+   --    DIRECT_NAME        | EXPLICIT_DEREFERENCE
+   --  | INDEXED_COMPONENT  | SLICE
+   --  | SELECTED_COMPONENT | ATTRIBUTE
+   --  | TYPE_CONVERSION    | FUNCTION_CALL
+   --  | CHARACTER_LITERAL
+
+   --  DIRECT_NAME ::= IDENTIFIER | OPERATOR_SYMBOL
+
+   --  PREFIX ::= NAME | IMPLICIT_DEREFERENCE
+
+   --  EXPLICIT_DEREFERENCE ::= NAME . all
+
+   --  IMPLICIT_DEREFERENCE ::= NAME
+
+   --  INDEXED_COMPONENT ::= PREFIX (EXPRESSION {, EXPRESSION})
+
+   --  SLICE ::= PREFIX (DISCRETE_RANGE)
+
+   --  SELECTED_COMPONENT ::= PREFIX . SELECTOR_NAME
+
+   --  SELECTOR_NAME ::= IDENTIFIER | CHARACTER_LITERAL | OPERATOR_SYMBOL
+
+   --  ATTRIBUTE_REFERENCE ::= PREFIX ' ATTRIBUTE_DESIGNATOR
+
+   --  ATTRIBUTE_DESIGNATOR ::=
+   --    IDENTIFIER [(static_EXPRESSION)]
+   --  | access | delta | digits
+
+   --  FUNCTION_CALL ::=
+   --    function_NAME
+   --  | function_PREFIX ACTUAL_PARAMETER_PART
+
+   --  ACTUAL_PARAMETER_PART ::=
+   --    (PARAMETER_ASSOCIATION {,PARAMETER_ASSOCIATION})
+
+   --  PARAMETER_ASSOCIATION ::=
+   --    [formal_parameter_SELECTOR_NAME =>] EXPLICIT_ACTUAL_PARAMETER
+
+   --  EXPLICIT_ACTUAL_PARAMETER ::= EXPRESSION | variable_NAME
+
+   --  Note: syntactically a procedure call looks just like a function call,
+   --  so this routine is in practice used to scan out procedure calls as well.
+
+   --  On return, Expr_Form is set to either EF_Name or EF_Simple_Name
+
+   --  Error recovery: can raise Error_Resync
+
+   --  Note: if on return Token = Tok_Apostrophe, then the apostrophe must be
+   --  followed by either a left paren (qualified expression case), or by
+   --  range (range attribute case). All other uses of apostrophe (i.e. all
+   --  other attributes) are handled in this routine.
+
+   --  Error recovery: can raise Error_Resync
+
+   function P_Name return Node_Id is
+      Scan_State  : Saved_Scan_State;
+      Name_Node   : Node_Id;
+      Prefix_Node : Node_Id;
+      Ident_Node  : Node_Id;
+      Expr_Node   : Node_Id;
+      Range_Node  : Node_Id;
+      Arg_Node    : Node_Id;
+
+      Arg_List  : List_Id := No_List; -- kill junk warning
+      Attr_Name : Name_Id := No_Name; -- kill junk warning
+
+   begin
+      if Token not in Token_Class_Name then
+         Error_Msg_AP ("name expected");
+         raise Error_Resync;
+      end if;
+
+      --  Loop through designators in qualified name
+
+      Name_Node := Token_Node;
+
+      loop
+         Scan; -- past designator
+         exit when Token /= Tok_Dot;
+         Save_Scan_State (Scan_State); -- at dot
+         Scan; -- past dot
+
+         --  If we do not have another designator after the dot, then join
+         --  the normal circuit to handle a dot extension (may be .all or
+         --  character literal case). Otherwise loop back to scan the next
+         --  designator.
+
+         if Token not in Token_Class_Desig then
+            goto Scan_Name_Extension_Dot;
+         else
+            Prefix_Node := Name_Node;
+            Name_Node := New_Node (N_Selected_Component, Prev_Token_Ptr);
+            Set_Prefix (Name_Node, Prefix_Node);
+            Set_Selector_Name (Name_Node, Token_Node);
+         end if;
+      end loop;
+
+      --  We have now scanned out a qualified designator. If the last token is
+      --  an operator symbol, then we certainly do not have the Snam case, so
+      --  we can just use the normal name extension check circuit
+
+      if Prev_Token = Tok_Operator_Symbol then
+         goto Scan_Name_Extension;
+      end if;
+
+      --  We have scanned out a qualified simple name, check for name extension
+      --  Note that we know there is no dot here at this stage, so the only
+      --  possible cases of name extension are apostrophe and left paren.
+
+      if Token = Tok_Apostrophe then
+         Save_Scan_State (Scan_State); -- at apostrophe
+         Scan; -- past apostrophe
+
+         --  If left paren, then this might be a qualified expression, but we
+         --  are only in the business of scanning out names, so return with
+         --  Token backed up to point to the apostrophe. The treatment for
+         --  the range attribute is similar (we do not consider x'range to
+         --  be a name in this grammar).
+
+         if Token = Tok_Left_Paren or else Token = Tok_Range then
+            Restore_Scan_State (Scan_State); -- to apostrophe
+            Expr_Form := EF_Simple_Name;
+            return Name_Node;
+
+         --  Otherwise we have the case of a name extended by an attribute
+
+         else
+            goto Scan_Name_Extension_Apostrophe;
+         end if;
+
+      --  Check case of qualified simple name extended by a left parenthesis
+
+      elsif Token = Tok_Left_Paren then
+         Scan; -- past left paren
+         goto Scan_Name_Extension_Left_Paren;
+
+      --  Otherwise the qualified simple name is not extended, so return
+
+      else
+         Expr_Form := EF_Simple_Name;
+         return Name_Node;
+      end if;
+
+      --  Loop scanning past name extensions. A label is used for control
+      --  transfer for this loop for ease of interfacing with the finite state
+      --  machine in the parenthesis scanning circuit, and also to allow for
+      --  passing in control to the appropriate point from the above code.
+
+      <<Scan_Name_Extension>>
+
+         --  Character literal used as name cannot be extended. Also this
+         --  cannot be a call, since the name for a call must be a designator.
+         --  Return in these cases, or if there is no name extension
+
+         if Token not in Token_Class_Namext
+           or else Prev_Token = Tok_Char_Literal
+         then
+            Expr_Form := EF_Name;
+            return Name_Node;
+         end if;
+
+      --  Merge here when we know there is a name extension
+
+      <<Scan_Name_Extension_OK>>
+
+         if Token = Tok_Left_Paren then
+            Scan; -- past left paren
+            goto Scan_Name_Extension_Left_Paren;
+
+         elsif Token = Tok_Apostrophe then
+            Save_Scan_State (Scan_State); -- at apostrophe
+            Scan; -- past apostrophe
+            goto Scan_Name_Extension_Apostrophe;
+
+         else -- Token = Tok_Dot
+            Save_Scan_State (Scan_State); -- at dot
+            Scan; -- past dot
+            goto Scan_Name_Extension_Dot;
+         end if;
+
+      --  Case of name extended by dot (selection), dot is already skipped
+      --  and the scan state at the point of the dot is saved in Scan_State.
+
+      <<Scan_Name_Extension_Dot>>
+
+         --  Explicit dereference case
+
+         if Token = Tok_All then
+            Prefix_Node := Name_Node;
+            Name_Node := New_Node (N_Explicit_Dereference, Token_Ptr);
+            Set_Prefix (Name_Node, Prefix_Node);
+            Scan; -- past ALL
+            goto Scan_Name_Extension;
+
+         --  Selected component case
+
+         elsif Token in Token_Class_Name then
+            Prefix_Node := Name_Node;
+            Name_Node := New_Node (N_Selected_Component, Prev_Token_Ptr);
+            Set_Prefix (Name_Node, Prefix_Node);
+            Set_Selector_Name (Name_Node, Token_Node);
+            Scan; -- past selector
+            goto Scan_Name_Extension;
+
+         --  Reserved identifier as selector
+
+         elsif Is_Reserved_Identifier then
+            Scan_Reserved_Identifier (Force_Msg => False);
+            Prefix_Node := Name_Node;
+            Name_Node := New_Node (N_Selected_Component, Prev_Token_Ptr);
+            Set_Prefix (Name_Node, Prefix_Node);
+            Set_Selector_Name (Name_Node, Token_Node);
+            Scan; -- past identifier used as selector
+            goto Scan_Name_Extension;
+
+         --  If dot is at end of line and followed by nothing legal,
+         --  then assume end of name and quit (dot will be taken as
+         --  an erroneous form of some other punctuation by our caller).
+
+         elsif Token_Is_At_Start_Of_Line then
+            Restore_Scan_State (Scan_State);
+            return Name_Node;
+
+         --  Here if nothing legal after the dot
+
+         else
+            Error_Msg_AP ("selector expected");
+            raise Error_Resync;
+         end if;
+
+      --  Here for an apostrophe as name extension. The scan position at the
+      --  apostrophe has already been saved, and the apostrophe scanned out.
+
+      <<Scan_Name_Extension_Apostrophe>>
+
+         Scan_Apostrophe : declare
+            function Apostrophe_Should_Be_Semicolon return Boolean;
+            --  Checks for case where apostrophe should probably be
+            --  a semicolon, and if so, gives appropriate message,
+            --  resets the scan pointer to the apostrophe, changes
+            --  the current token to Tok_Semicolon, and returns True.
+            --  Otherwise returns False.
+
+            function Apostrophe_Should_Be_Semicolon return Boolean is
+            begin
+               if Token_Is_At_Start_Of_Line then
+                  Restore_Scan_State (Scan_State); -- to apostrophe
+                  Error_Msg_SC ("""''"" should be "";""");
+                  Token := Tok_Semicolon;
+                  return True;
+               else
+                  return False;
+               end if;
+            end Apostrophe_Should_Be_Semicolon;
+
+         --  Start of processing for Scan_Apostrophe
+
+         begin
+            --  If range attribute after apostrophe, then return with Token
+            --  pointing to the apostrophe. Note that in this case the prefix
+            --  need not be a simple name (cases like A.all'range). Similarly
+            --  if there is a left paren after the apostrophe, then we also
+            --  return with Token pointing to the apostrophe (this is the
+            --  qualified expression case).
+
+            if Token = Tok_Range or else Token = Tok_Left_Paren then
+               Restore_Scan_State (Scan_State); -- to apostrophe
+               Expr_Form := EF_Name;
+               return Name_Node;
+
+            --  Here for cases where attribute designator is an identifier
+
+            elsif Token = Tok_Identifier then
+               Attr_Name := Token_Name;
+
+               if not Is_Attribute_Name (Attr_Name) then
+                  if Apostrophe_Should_Be_Semicolon then
+                     Expr_Form := EF_Name;
+                     return Name_Node;
+                  else
+                     Signal_Bad_Attribute;
+                  end if;
+               end if;
+
+               if Style_Check then
+                  Style.Check_Attribute_Name (False);
+               end if;
+
+               Delete_Node (Token_Node);
+
+            --  Here for case of attribute designator is not an identifier
+
+            else
+               if Token = Tok_Delta then
+                  Attr_Name := Name_Delta;
+
+               elsif Token = Tok_Digits then
+                  Attr_Name := Name_Digits;
+
+               elsif Token = Tok_Access then
+                  Attr_Name := Name_Access;
+
+               elsif Apostrophe_Should_Be_Semicolon then
+                  Expr_Form := EF_Name;
+                  return Name_Node;
+
+               else
+                  Error_Msg_AP ("attribute designator expected");
+                  raise Error_Resync;
+               end if;
+
+               if Style_Check then
+                  Style.Check_Attribute_Name (True);
+               end if;
+            end if;
+
+            --  We come here with an OK attribute scanned, and the
+            --  corresponding Attribute identifier node stored in Ident_Node.
+
+            Prefix_Node := Name_Node;
+            Name_Node := New_Node (N_Attribute_Reference, Prev_Token_Ptr);
+            Scan; -- past attribute designator
+            Set_Prefix (Name_Node, Prefix_Node);
+            Set_Attribute_Name (Name_Node, Attr_Name);
+
+            --  Scan attribute arguments/designator
+
+            if Token = Tok_Left_Paren then
+               Set_Expressions (Name_Node, New_List);
+               Scan; -- past left paren
+
+               loop
+                  declare
+                     Expr : constant Node_Id := P_Expression;
+
+                  begin
+                     if Token = Tok_Arrow then
+                        Error_Msg_SC
+                          ("named parameters not permitted for attributes");
+                        Scan; -- past junk arrow
+
+                     else
+                        Append (Expr, Expressions (Name_Node));
+                        exit when not Comma_Present;
+                     end if;
+                  end;
+               end loop;
+
+               T_Right_Paren;
+            end if;
+
+            goto Scan_Name_Extension;
+         end Scan_Apostrophe;
+
+      --  Here for left parenthesis extending name (left paren skipped)
+
+      <<Scan_Name_Extension_Left_Paren>>
+
+         --  We now have to scan through a list of items, terminated by a
+         --  right parenthesis. The scan is handled by a finite state
+         --  machine. The possibilities are:
+
+         --   (discrete_range)
+
+         --      This is a slice. This case is handled in LP_State_Init.
+
+         --   (expression, expression, ..)
+
+         --      This is interpreted as an indexed component, i.e. as a
+         --      case of a name which can be extended in the normal manner.
+         --      This case is handled by LP_State_Name or LP_State_Expr.
+
+         --   (..., identifier => expression , ...)
+
+         --      If there is at least one occurence of identifier => (but
+         --      none of the other cases apply), then we have a call.
+
+         --  Test for Id => case
+
+         if Token = Tok_Identifier then
+            Save_Scan_State (Scan_State); -- at Id
+            Scan; -- past Id
+
+            --  Test for => (allow := as an error substitute)
+
+            if Token = Tok_Arrow or else Token = Tok_Colon_Equal then
+               Restore_Scan_State (Scan_State); -- to Id
+               Arg_List := New_List;
+               goto LP_State_Call;
+
+            else
+               Restore_Scan_State (Scan_State); -- to Id
+            end if;
+         end if;
+
+         --  Here we have an expression after all
+
+         Expr_Node := P_Expression_Or_Range_Attribute;
+
+         --  Check cases of discrete range for a slice
+
+         --  First possibility: Range_Attribute_Reference
+
+         if Expr_Form = EF_Range_Attr then
+            Range_Node := Expr_Node;
+
+         --  Second possibility: Simple_expression .. Simple_expression
+
+         elsif Token = Tok_Dot_Dot then
+            Check_Simple_Expression (Expr_Node);
+            Range_Node := New_Node (N_Range, Token_Ptr);
+            Set_Low_Bound (Range_Node, Expr_Node);
+            Scan; -- past ..
+            Expr_Node := P_Expression;
+            Check_Simple_Expression (Expr_Node);
+            Set_High_Bound (Range_Node, Expr_Node);
+
+         --  Third possibility: Type_name range Range
+
+         elsif Token = Tok_Range then
+            if Expr_Form /= EF_Simple_Name then
+               Error_Msg_SC ("subtype mark must precede RANGE");
+               raise Error_Resync;
+            end if;
+
+            Range_Node := P_Subtype_Indication (Expr_Node);
+
+         --  Otherwise we just have an expression. It is true that we might
+         --  have a subtype mark without a range constraint but this case
+         --  is syntactically indistinguishable from the expression case.
+
+         else
+            Arg_List := New_List;
+            goto LP_State_Expr;
+         end if;
+
+         --  Fall through here with unmistakable Discrete range scanned,
+         --  which means that we definitely have the case of a slice. The
+         --  Discrete range is in Range_Node.
+
+         if Token = Tok_Comma then
+            Error_Msg_SC ("slice cannot have more than one dimension");
+            raise Error_Resync;
+
+         elsif Token /= Tok_Right_Paren then
+            T_Right_Paren;
+            raise Error_Resync;
+
+         else
+            Scan; -- past right paren
+            Prefix_Node := Name_Node;
+            Name_Node := New_Node (N_Slice, Sloc (Prefix_Node));
+            Set_Prefix (Name_Node, Prefix_Node);
+            Set_Discrete_Range (Name_Node, Range_Node);
+
+            --  An operator node is legal as a prefix to other names,
+            --  but not for a slice.
+
+            if Nkind (Prefix_Node) = N_Operator_Symbol then
+               Error_Msg_N ("illegal prefix for slice", Prefix_Node);
+            end if;
+
+            --  If we have a name extension, go scan it
+
+            if Token in Token_Class_Namext then
+               goto Scan_Name_Extension_OK;
+
+            --  Otherwise return (a slice is a name, but is not a call)
+
+            else
+               Expr_Form := EF_Name;
+               return Name_Node;
+            end if;
+         end if;
+
+      --  In LP_State_Expr, we have scanned one or more expressions, and
+      --  so we have a call or an indexed component which is a name. On
+      --  entry we have the expression just scanned in Expr_Node and
+      --  Arg_List contains the list of expressions encountered so far
+
+      <<LP_State_Expr>>
+         Append (Expr_Node, Arg_List);
+
+         if Token = Tok_Arrow then
+            Error_Msg
+              ("expect identifier in parameter association",
+                Sloc (Expr_Node));
+            Scan;  --   past arrow.
+
+         elsif not Comma_Present then
+            T_Right_Paren;
+            Prefix_Node := Name_Node;
+            Name_Node := New_Node (N_Indexed_Component, Sloc (Prefix_Node));
+            Set_Prefix (Name_Node, Prefix_Node);
+            Set_Expressions (Name_Node, Arg_List);
+            goto Scan_Name_Extension;
+         end if;
+
+         --  Comma present (and scanned out), test for identifier => case
+         --  Test for identifer => case
+
+         if Token = Tok_Identifier then
+            Save_Scan_State (Scan_State); -- at Id
+            Scan; -- past Id
+
+            --  Test for => (allow := as error substitute)
+
+            if Token = Tok_Arrow or else Token = Tok_Colon_Equal then
+               Restore_Scan_State (Scan_State); -- to Id
+               goto LP_State_Call;
+
+            --  Otherwise it's just an expression after all, so backup
+
+            else
+               Restore_Scan_State (Scan_State); -- to Id
+            end if;
+         end if;
+
+         --  Here we have an expression after all, so stay in this state
+
+         Expr_Node := P_Expression;
+         goto LP_State_Expr;
+
+      --  LP_State_Call corresponds to the situation in which at least
+      --  one instance of Id => Expression has been encountered, so we
+      --  know that we do not have a name, but rather a call. We enter
+      --  it with the scan pointer pointing to the next argument to scan,
+      --  and Arg_List containing the list of arguments scanned so far.
+
+      <<LP_State_Call>>
+
+         --  Test for case of Id => Expression (named parameter)
+
+         if Token = Tok_Identifier then
+            Save_Scan_State (Scan_State); -- at Id
+            Ident_Node := Token_Node;
+            Scan; -- past Id
+
+            --  Deal with => (allow := as erroneous substitute)
+
+            if Token = Tok_Arrow or else Token = Tok_Colon_Equal then
+               Arg_Node :=
+                 New_Node (N_Parameter_Association, Prev_Token_Ptr);
+               Set_Selector_Name (Arg_Node, Ident_Node);
+               T_Arrow;
+               Set_Explicit_Actual_Parameter (Arg_Node, P_Expression);
+               Append (Arg_Node, Arg_List);
+
+               --  If a comma follows, go back and scan next entry
+
+               if Comma_Present then
+                  goto LP_State_Call;
+
+               --  Otherwise we have the end of a call
+
+               else
+                  Prefix_Node := Name_Node;
+                  Name_Node :=
+                    New_Node (N_Function_Call, Sloc (Prefix_Node));
+                  Set_Name (Name_Node, Prefix_Node);
+                  Set_Parameter_Associations (Name_Node, Arg_List);
+                  T_Right_Paren;
+
+                  if Token in Token_Class_Namext then
+                     goto Scan_Name_Extension_OK;
+
+                  --  This is a case of a call which cannot be a name
+
+                  else
+                     Expr_Form := EF_Name;
+                     return Name_Node;
+                  end if;
+               end if;
+
+            --  Not named parameter: Id started an expression after all
+
+            else
+               Restore_Scan_State (Scan_State); -- to Id
+            end if;
+         end if;
+
+         --  Here if entry did not start with Id => which means that it
+         --  is a positional parameter, which is not allowed, since we
+         --  have seen at least one named parameter already.
+
+         Error_Msg_SC
+            ("positional parameter association " &
+              "not allowed after named one");
+
+         Expr_Node := P_Expression;
+
+         --  Leaving the '>' in an association is not unusual, so suggest
+         --  a possible fix.
+
+         if Nkind (Expr_Node) = N_Op_Eq then
+            Error_Msg_N ("\maybe `=>` was intended", Expr_Node);
+         end if;
+
+         --  We go back to scanning out expressions, so that we do not get
+         --  multiple error messages when several positional parameters
+         --  follow a named parameter.
+
+         goto LP_State_Expr;
+
+         --  End of treatment for name extensions starting with left paren
+
+      --  End of loop through name extensions
+
+   end P_Name;
+
+   --  This function parses a restricted form of Names which are either
+   --  designators, or designators preceded by a sequence of prefixes
+   --  that are direct names.
+
+   --  Error recovery: cannot raise Error_Resync
+
+   function P_Function_Name return Node_Id is
+      Designator_Node : Node_Id;
+      Prefix_Node     : Node_Id;
+      Selector_Node   : Node_Id;
+      Dot_Sloc        : Source_Ptr := No_Location;
+
+   begin
+      --  Prefix_Node is set to the gathered prefix so far, Empty means that
+      --  no prefix has been scanned. This allows us to build up the result
+      --  in the required right recursive manner.
+
+      Prefix_Node := Empty;
+
+      --  Loop through prefixes
+
+      loop
+         Designator_Node := Token_Node;
+
+         if Token not in Token_Class_Desig then
+            return P_Identifier; -- let P_Identifier issue the error message
+
+         else -- Token in Token_Class_Desig
+            Scan; -- past designator
+            exit when Token /= Tok_Dot;
+         end if;
+
+         --  Here at a dot, with token just before it in Designator_Node
+
+         if No (Prefix_Node) then
+            Prefix_Node := Designator_Node;
+         else
+            Selector_Node := New_Node (N_Selected_Component, Dot_Sloc);
+            Set_Prefix (Selector_Node, Prefix_Node);
+            Set_Selector_Name (Selector_Node, Designator_Node);
+            Prefix_Node := Selector_Node;
+         end if;
+
+         Dot_Sloc := Token_Ptr;
+         Scan; -- past dot
+      end loop;
+
+      --  Fall out of the loop having just scanned a designator
+
+      if No (Prefix_Node) then
+         return Designator_Node;
+      else
+         Selector_Node := New_Node (N_Selected_Component, Dot_Sloc);
+         Set_Prefix (Selector_Node, Prefix_Node);
+         Set_Selector_Name (Selector_Node, Designator_Node);
+         return Selector_Node;
+      end if;
+
+   exception
+      when Error_Resync =>
+         return Error;
+
+   end P_Function_Name;
+
+   --  This function parses a restricted form of Names which are either
+   --  identifiers, or identifiers preceded by a sequence of prefixes
+   --  that are direct names.
+
+   --  Error recovery: cannot raise Error_Resync
+
+   function P_Qualified_Simple_Name return Node_Id is
+      Designator_Node : Node_Id;
+      Prefix_Node     : Node_Id;
+      Selector_Node   : Node_Id;
+      Dot_Sloc        : Source_Ptr := No_Location;
+
+   begin
+      --  Prefix node is set to the gathered prefix so far, Empty means that
+      --  no prefix has been scanned. This allows us to build up the result
+      --  in the required right recursive manner.
+
+      Prefix_Node := Empty;
+
+      --  Loop through prefixes
+
+      loop
+         Designator_Node := Token_Node;
+
+         if Token = Tok_Identifier then
+            Scan; -- past identifier
+            exit when Token /= Tok_Dot;
+
+         elsif Token not in Token_Class_Desig then
+            return P_Identifier; -- let P_Identifier issue the error message
+
+         else
+            Scan; -- past designator
+
+            if Token /= Tok_Dot then
+               Error_Msg_SP ("identifier expected");
+               return Error;
+            end if;
+         end if;
+
+         --  Here at a dot, with token just before it in Designator_Node
+
+         if No (Prefix_Node) then
+            Prefix_Node := Designator_Node;
+         else
+            Selector_Node := New_Node (N_Selected_Component, Dot_Sloc);
+            Set_Prefix (Selector_Node, Prefix_Node);
+            Set_Selector_Name (Selector_Node, Designator_Node);
+            Prefix_Node := Selector_Node;
+         end if;
+
+         Dot_Sloc := Token_Ptr;
+         Scan; -- past dot
+      end loop;
+
+      --  Fall out of the loop having just scanned an identifier
+
+      if No (Prefix_Node) then
+         return Designator_Node;
+      else
+         Selector_Node := New_Node (N_Selected_Component, Dot_Sloc);
+         Set_Prefix (Selector_Node, Prefix_Node);
+         Set_Selector_Name (Selector_Node, Designator_Node);
+         return Selector_Node;
+      end if;
+
+   exception
+      when Error_Resync =>
+         return Error;
+
+   end P_Qualified_Simple_Name;
+
+   --  This procedure differs from P_Qualified_Simple_Name only in that it
+   --  raises Error_Resync if any error is encountered. It only returns after
+   --  scanning a valid qualified simple name.
+
+   --  Error recovery: can raise Error_Resync
+
+   function P_Qualified_Simple_Name_Resync return Node_Id is
+      Designator_Node : Node_Id;
+      Prefix_Node     : Node_Id;
+      Selector_Node   : Node_Id;
+      Dot_Sloc        : Source_Ptr := No_Location;
+
+   begin
+      Prefix_Node := Empty;
+
+      --  Loop through prefixes
+
+      loop
+         Designator_Node := Token_Node;
+
+         if Token = Tok_Identifier then
+            Scan; -- past identifier
+            exit when Token /= Tok_Dot;
+
+         elsif Token not in Token_Class_Desig then
+            Discard_Junk_Node (P_Identifier); -- to issue the error message
+            raise Error_Resync;
+
+         else
+            Scan; -- past designator
+
+            if Token /= Tok_Dot then
+               Error_Msg_SP ("identifier expected");
+               raise Error_Resync;
+            end if;
+         end if;
+
+         --  Here at a dot, with token just before it in Designator_Node
+
+         if No (Prefix_Node) then
+            Prefix_Node := Designator_Node;
+         else
+            Selector_Node := New_Node (N_Selected_Component, Dot_Sloc);
+            Set_Prefix (Selector_Node, Prefix_Node);
+            Set_Selector_Name (Selector_Node, Designator_Node);
+            Prefix_Node := Selector_Node;
+         end if;
+
+         Dot_Sloc := Token_Ptr;
+         Scan; -- past period
+      end loop;
+
+      --  Fall out of the loop having just scanned an identifier
+
+      if No (Prefix_Node) then
+         return Designator_Node;
+      else
+         Selector_Node := New_Node (N_Selected_Component, Dot_Sloc);
+         Set_Prefix (Selector_Node, Prefix_Node);
+         Set_Selector_Name (Selector_Node, Designator_Node);
+         return Selector_Node;
+      end if;
+
+   end P_Qualified_Simple_Name_Resync;
+
+   ----------------------
+   -- 4.1  Direct_Name --
+   ----------------------
+
+   --  Parsed by P_Name and other functions in section 4.1
+
+   -----------------
+   -- 4.1  Prefix --
+   -----------------
+
+   --  Parsed by P_Name (4.1)
+
+   -------------------------------
+   -- 4.1  Explicit Dereference --
+   -------------------------------
+
+   --  Parsed by P_Name (4.1)
+
+   -------------------------------
+   -- 4.1  Implicit_Dereference --
+   -------------------------------
+
+   --  Parsed by P_Name (4.1)
+
+   ----------------------------
+   -- 4.1  Indexed Component --
+   ----------------------------
+
+   --  Parsed by P_Name (4.1)
+
+   ----------------
+   -- 4.1  Slice --
+   ----------------
+
+   --  Parsed by P_Name (4.1)
+
+   -----------------------------
+   -- 4.1  Selected_Component --
+   -----------------------------
+
+   --  Parsed by P_Name (4.1)
+
+   ------------------------
+   -- 4.1  Selector Name --
+   ------------------------
+
+   --  Parsed by P_Name (4.1)
+
+   ------------------------------
+   -- 4.1  Attribute Reference --
+   ------------------------------
+
+   --  Parsed by P_Name (4.1)
+
+   -------------------------------
+   -- 4.1  Attribute Designator --
+   -------------------------------
+
+   --  Parsed by P_Name (4.1)
+
+   --------------------------------------
+   -- 4.1.4  Range Attribute Reference --
+   --------------------------------------
+
+   --  RANGE_ATTRIBUTE_REFERENCE ::= PREFIX ' RANGE_ATTRIBUTE_DESIGNATOR
+
+   --  RANGE_ATTRIBUTE_DESIGNATOR ::= range [(static_EXPRESSION)]
+
+   --  In the grammar, a RANGE attribute is simply a name, but its use is
+   --  highly restricted, so in the parser, we do not regard it as a name.
+   --  Instead, P_Name returns without scanning the 'RANGE part of the
+   --  attribute, and the caller uses the following function to construct
+   --  a range attribute in places where it is appropriate.
+
+   --  Note that RANGE here is treated essentially as an identifier,
+   --  rather than a reserved word.
+
+   --  The caller has parsed the prefix, i.e. a name, and Token points to
+   --  the apostrophe. The token after the apostrophe is known to be RANGE
+   --  at this point. The prefix node becomes the prefix of the attribute.
+
+   --  Error_Recovery: Cannot raise Error_Resync
+
+   function P_Range_Attribute_Reference
+     (Prefix_Node : Node_Id)
+      return        Node_Id
+   is
+      Attr_Node  : Node_Id;
+
+   begin
+      Attr_Node := New_Node (N_Attribute_Reference, Token_Ptr);
+      Set_Prefix (Attr_Node, Prefix_Node);
+      Scan; -- past apostrophe
+
+      if Style_Check then
+         Style.Check_Attribute_Name (True);
+      end if;
+
+      Set_Attribute_Name (Attr_Node, Name_Range);
+      Scan; -- past RANGE
+
+      if Token = Tok_Left_Paren then
+         Scan; -- past left paren
+         Set_Expressions (Attr_Node, New_List (P_Expression));
+         T_Right_Paren;
+      end if;
+
+      return Attr_Node;
+   end P_Range_Attribute_Reference;
+
+   ---------------------------------------
+   -- 4.1.4  Range Attribute Designator --
+   ---------------------------------------
+
+   --  Parsed by P_Range_Attribute_Reference (4.4)
+
+   --------------------
+   -- 4.3  Aggregate --
+   --------------------
+
+   --  AGGREGATE ::= RECORD_AGGREGATE | EXTENSION_AGGREGATE | ARRAY_AGGREGATE
+
+   --  Parsed by P_Aggregate_Or_Paren_Expr (4.3), except in the case where
+   --  an aggregate is known to be required (code statement, extension
+   --  aggregate), in which cases this routine performs the necessary check
+   --  that we have an aggregate rather than a parenthesized expression
+
+   --  Error recovery: can raise Error_Resync
+
+   function P_Aggregate return Node_Id is
+      Aggr_Sloc : constant Source_Ptr := Token_Ptr;
+      Aggr_Node : constant Node_Id    := P_Aggregate_Or_Paren_Expr;
+
+   begin
+      if Nkind (Aggr_Node) /= N_Aggregate
+           and then
+         Nkind (Aggr_Node) /= N_Extension_Aggregate
+      then
+         Error_Msg
+           ("aggregate may not have single positional component", Aggr_Sloc);
+         return Error;
+      else
+         return Aggr_Node;
+      end if;
+   end P_Aggregate;
+
+   -------------------------------------------------
+   -- 4.3  Aggregate or Parenthesized Expresssion --
+   -------------------------------------------------
+
+   --  This procedure parses out either an aggregate or a parenthesized
+   --  expression (these two constructs are closely related, since a
+   --  parenthesized expression looks like an aggregate with a single
+   --  positional component).
+
+   --  AGGREGATE ::=
+   --    RECORD_AGGREGATE | EXTENSION_AGGREGATE | ARRAY_AGGREGATE
+
+   --  RECORD_AGGREGATE ::= (RECORD_COMPONENT_ASSOCIATION_LIST)
+
+   --  RECORD_COMPONENT_ASSOCIATION_LIST ::=
+   --     RECORD_COMPONENT_ASSOCIATION {, RECORD_COMPONENT_ASSOCIATION}
+   --   | null record
+
+   --  RECORD_COMPONENT_ASSOCIATION ::=
+   --    [COMPONENT_CHOICE_LIST =>] EXPRESSION
+
+   --  COMPONENT_CHOICE_LIST ::=
+   --    component_SELECTOR_NAME {| component_SELECTOR_NAME}
+   --  | others
+
+   --  EXTENSION_AGGREGATE ::=
+   --    (ANCESTOR_PART with RECORD_COMPONENT_ASSOCIATION_LIST)
+
+   --  ANCESTOR_PART ::= EXPRESSION | SUBTYPE_MARK
+
+   --  ARRAY_AGGREGATE ::=
+   --    POSITIONAL_ARRAY_AGGREGATE | NAMED_ARRAY_AGGREGATE
+
+   --  POSITIONAL_ARRAY_AGGREGATE ::=
+   --    (EXPRESSION, EXPRESSION {, EXPRESSION})
+   --  | (EXPRESSION {, EXPRESSION}, others => EXPRESSION)
+
+   --  NAMED_ARRAY_AGGREGATE ::=
+   --    (ARRAY_COMPONENT_ASSOCIATION {, ARRAY_COMPONENT_ASSOCIATION})
+
+   --  PRIMARY ::= (EXPRESSION);
+
+   --  Error recovery: can raise Error_Resync
+
+   function P_Aggregate_Or_Paren_Expr return Node_Id is
+      Aggregate_Node : Node_Id;
+      Expr_List      : List_Id;
+      Assoc_List     : List_Id;
+      Expr_Node      : Node_Id;
+      Lparen_Sloc    : Source_Ptr;
+      Scan_State     : Saved_Scan_State;
+
+   begin
+      Lparen_Sloc := Token_Ptr;
+      T_Left_Paren;
+
+      --  Note: the mechanism used here of rescanning the initial expression
+      --  is distinctly unpleasant, but it saves a lot of fiddling in scanning
+      --  out the discrete choice list.
+
+      --  Deal with expression and extension aggregate cases first
+
+      if Token /= Tok_Others then
+         Save_Scan_State (Scan_State); -- at start of expression
+
+         --  Deal with (NULL RECORD) case
+
+         if Token = Tok_Null then
+            Scan; -- past NULL
+
+            if Token = Tok_Record then
+               Aggregate_Node := New_Node (N_Aggregate, Lparen_Sloc);
+               Set_Null_Record_Present (Aggregate_Node, True);
+               Scan; -- past RECORD
+               T_Right_Paren;
+               return Aggregate_Node;
+            else
+               Restore_Scan_State (Scan_State); -- to NULL that must be expr
+            end if;
+         end if;
+
+         Expr_Node := P_Expression_Or_Range_Attribute;
+
+         --  Extension aggregate case
+
+         if Token = Tok_With then
+
+            if Nkind (Expr_Node) = N_Attribute_Reference
+              and then Attribute_Name (Expr_Node) = Name_Range
+            then
+               Bad_Range_Attribute (Sloc (Expr_Node));
+               return Error;
+            end if;
+
+            if Ada_83 then
+               Error_Msg_SC ("(Ada 83) extension aggregate not allowed");
+            end if;
+
+            Aggregate_Node := New_Node (N_Extension_Aggregate, Lparen_Sloc);
+            Set_Ancestor_Part (Aggregate_Node, Expr_Node);
+            Scan; -- past WITH
+
+            --  Deal with WITH NULL RECORD case
+
+            if Token = Tok_Null then
+               Save_Scan_State (Scan_State); -- at NULL
+               Scan; -- past NULL
+
+               if Token = Tok_Record then
+                  Scan; -- past RECORD
+                  Set_Null_Record_Present (Aggregate_Node, True);
+                  T_Right_Paren;
+                  return Aggregate_Node;
+
+               else
+                  Restore_Scan_State (Scan_State); -- to NULL that must be expr
+               end if;
+            end if;
+
+            if Token /= Tok_Others then
+               Save_Scan_State (Scan_State);
+               Expr_Node := P_Expression;
+            else
+               Expr_Node := Empty;
+            end if;
+
+         --  Expression case
+
+         elsif Token = Tok_Right_Paren or else Token in Token_Class_Eterm then
+
+            if Nkind (Expr_Node) = N_Attribute_Reference
+              and then Attribute_Name (Expr_Node) = Name_Range
+            then
+               Bad_Range_Attribute (Sloc (Expr_Node));
+               return Error;
+            end if;
+
+            --  Bump paren count of expression, note that if the paren count
+            --  is already at the maximum, then we leave it alone. This will
+            --  cause some failures in pathalogical conformance tests, which
+            --  we do not shed a tear over!
+
+            if Expr_Node /= Error then
+               if Paren_Count (Expr_Node) /= Paren_Count_Type'Last then
+                  Set_Paren_Count (Expr_Node, Paren_Count (Expr_Node) + 1);
+               end if;
+            end if;
+
+            T_Right_Paren; -- past right paren (error message if none)
+            return Expr_Node;
+
+         --  Normal aggregate case
+
+         else
+            Aggregate_Node := New_Node (N_Aggregate, Lparen_Sloc);
+         end if;
+
+      --  Others case
+
+      else
+         Aggregate_Node := New_Node (N_Aggregate, Lparen_Sloc);
+         Expr_Node := Empty;
+      end if;
+
+      --  Prepare to scan list of component associations
+
+      Expr_List  := No_List; -- don't set yet, maybe all named entries
+      Assoc_List := No_List; -- don't set yet, maybe all positional entries
+
+      --  This loop scans through component associations. On entry to the
+      --  loop, an expression has been scanned at the start of the current
+      --  association unless initial token was OTHERS, in which case
+      --  Expr_Node is set to Empty.
+
+      loop
+         --  Deal with others association first. This is a named association
+
+         if No (Expr_Node) then
+            if No (Assoc_List) then
+               Assoc_List := New_List;
+            end if;
+
+            Append (P_Record_Or_Array_Component_Association, Assoc_List);
+
+         --  Improper use of WITH
+
+         elsif Token = Tok_With then
+            Error_Msg_SC ("WITH must be preceded by single expression in " &
+                             "extension aggregate");
+            raise Error_Resync;
+
+         --  Assume positional case if comma, right paren, or literal or
+         --  identifier or OTHERS follows (the latter cases are missing
+         --  comma cases). Also assume positional if a semicolon follows,
+         --  which can happen if there are missing parens
+
+         elsif Token = Tok_Comma
+           or else Token = Tok_Right_Paren
+           or else Token = Tok_Others
+           or else Token in Token_Class_Lit_Or_Name
+           or else Token = Tok_Semicolon
+         then
+            if Present (Assoc_List) then
+               Error_Msg_BC
+                  ("""=>"" expected (positional association cannot follow " &
+                   "named association)");
+            end if;
+
+            if No (Expr_List) then
+               Expr_List := New_List;
+            end if;
+
+            Append (Expr_Node, Expr_List);
+
+         --  Anything else is assumed to be a named association
+
+         else
+            Restore_Scan_State (Scan_State); -- to start of expression
+
+            if No (Assoc_List) then
+               Assoc_List := New_List;
+            end if;
+
+            Append (P_Record_Or_Array_Component_Association, Assoc_List);
+         end if;
+
+         exit when not Comma_Present;
+
+         --  If we are at an expression terminator, something is seriously
+         --  wrong, so let's get out now, before we start eating up stuff
+         --  that doesn't belong to us!
+
+         if Token in Token_Class_Eterm then
+            Error_Msg_AP ("expecting expression or component association");
+            exit;
+         end if;
+
+         --  Otherwise initiate for reentry to top of loop by scanning an
+         --  initial expression, unless the first token is OTHERS.
+
+         if Token = Tok_Others then
+            Expr_Node := Empty;
+         else
+            Save_Scan_State (Scan_State); -- at start of expression
+            Expr_Node := P_Expression;
+         end if;
+      end loop;
+
+      --  All component associations (positional and named) have been scanned
+
+      T_Right_Paren;
+      Set_Expressions (Aggregate_Node, Expr_List);
+      Set_Component_Associations (Aggregate_Node, Assoc_List);
+      return Aggregate_Node;
+   end P_Aggregate_Or_Paren_Expr;
+
+   ------------------------------------------------
+   -- 4.3  Record or Array Component Association --
+   ------------------------------------------------
+
+   --  RECORD_COMPONENT_ASSOCIATION ::=
+   --    [COMPONENT_CHOICE_LIST =>] EXPRESSION
+
+   --  COMPONENT_CHOICE_LIST =>
+   --    component_SELECTOR_NAME {| component_SELECTOR_NAME}
+   --  | others
+
+   --  ARRAY_COMPONENT_ASSOCIATION ::=
+   --    DISCRETE_CHOICE_LIST => EXPRESSION
+
+   --  Note: this routine only handles the named cases, including others.
+   --  Cases where the component choice list is not present have already
+   --  been handled directly.
+
+   --  Error recovery: can raise Error_Resync
+
+   function P_Record_Or_Array_Component_Association return Node_Id is
+      Assoc_Node : Node_Id;
+
+   begin
+      Assoc_Node := New_Node (N_Component_Association, Token_Ptr);
+      Set_Choices (Assoc_Node, P_Discrete_Choice_List);
+      Set_Sloc (Assoc_Node, Token_Ptr);
+      TF_Arrow;
+      Set_Expression (Assoc_Node, P_Expression);
+      return Assoc_Node;
+   end P_Record_Or_Array_Component_Association;
+
+   -----------------------------
+   -- 4.3.1  Record Aggregate --
+   -----------------------------
+
+   --  Case of enumeration aggregate is parsed by P_Aggregate (4.3)
+   --  All other cases are parsed by P_Aggregate_Or_Paren_Expr (4.3)
+
+   ----------------------------------------------
+   -- 4.3.1  Record Component Association List --
+   ----------------------------------------------
+
+   --  Parsed by P_Aggregate_Or_Paren_Expr (4.3)
+
+   ----------------------------------
+   -- 4.3.1  Component Choice List --
+   ----------------------------------
+
+   --  Parsed by P_Aggregate_Or_Paren_Expr (4.3)
+
+   --------------------------------
+   -- 4.3.1  Extension Aggregate --
+   --------------------------------
+
+   --  Parsed by P_Aggregate_Or_Paren_Expr (4.3)
+
+   --------------------------
+   -- 4.3.1  Ancestor Part --
+   --------------------------
+
+   --  Parsed by P_Aggregate_Or_Paren_Expr (4.3)
+
+   ----------------------------
+   -- 4.3.1  Array Aggregate --
+   ----------------------------
+
+   --  Parsed by P_Aggregate_Or_Paren_Expr (4.3)
+
+   ---------------------------------------
+   -- 4.3.1  Positional Array Aggregate --
+   ---------------------------------------
+
+   --  Parsed by P_Aggregate_Or_Paren_Expr (4.3)
+
+   ----------------------------------
+   -- 4.3.1  Named Array Aggregate --
+   ----------------------------------
+
+   --  Parsed by P_Aggregate_Or_Paren_Expr (4.3)
+
+   ----------------------------------------
+   -- 4.3.1  Array Component Association --
+   ----------------------------------------
+
+   --  Parsed by P_Aggregate_Or_Paren_Expr (4.3)
+
+   ---------------------
+   -- 4.4  Expression --
+   ---------------------
+
+   --  EXPRESSION ::=
+   --    RELATION {and RELATION} | RELATION {and then RELATION}
+   --  | RELATION {or RELATION}  | RELATION {or else RELATION}
+   --  | RELATION {xor RELATION}
+
+   --  On return, Expr_Form indicates the categorization of the expression
+   --  EF_Range_Attr is not a possible value (if a range attribute is found,
+   --  an error message is given, and Error is returned).
+
+   --  Error recovery: cannot raise Error_Resync
+
+   function P_Expression return Node_Id is
+      Logical_Op      : Node_Kind;
+      Prev_Logical_Op : Node_Kind;
+      Op_Location     : Source_Ptr;
+      Node1           : Node_Id;
+      Node2           : Node_Id;
+
+   begin
+      Node1 := P_Relation;
+
+      if Token in Token_Class_Logop then
+         Prev_Logical_Op := N_Empty;
+
+         loop
+            Op_Location := Token_Ptr;
+            Logical_Op := P_Logical_Operator;
+
+            if Prev_Logical_Op /= N_Empty and then
+               Logical_Op /= Prev_Logical_Op
+            then
+               Error_Msg
+                 ("mixed logical operators in expression", Op_Location);
+               Prev_Logical_Op := N_Empty;
+            else
+               Prev_Logical_Op := Logical_Op;
+            end if;
+
+            Node2 := Node1;
+            Node1 := New_Node (Logical_Op, Op_Location);
+            Set_Left_Opnd (Node1, Node2);
+            Set_Right_Opnd (Node1, P_Relation);
+            Set_Op_Name (Node1);
+            exit when Token not in Token_Class_Logop;
+         end loop;
+
+         Expr_Form := EF_Non_Simple;
+      end if;
+
+      if Token = Tok_Apostrophe then
+         Bad_Range_Attribute (Token_Ptr);
+         return Error;
+      else
+         return Node1;
+      end if;
+
+   end P_Expression;
+
+   --  This function is identical to the normal P_Expression, except that it
+   --  checks that the expression scan did not stop on a right paren. It is
+   --  called in all contexts where a right parenthesis cannot legitimately
+   --  follow an expression.
+
+   function P_Expression_No_Right_Paren return Node_Id is
+   begin
+      return No_Right_Paren (P_Expression);
+   end P_Expression_No_Right_Paren;
+
+   ----------------------------------------
+   -- 4.4  Expression_Or_Range_Attribute --
+   ----------------------------------------
+
+   --  EXPRESSION ::=
+   --    RELATION {and RELATION} | RELATION {and then RELATION}
+   --  | RELATION {or RELATION}  | RELATION {or else RELATION}
+   --  | RELATION {xor RELATION}
+
+   --  RANGE_ATTRIBUTE_REFERENCE ::= PREFIX ' RANGE_ATTRIBUTE_DESIGNATOR
+
+   --  RANGE_ATTRIBUTE_DESIGNATOR ::= range [(static_EXPRESSION)]
+
+   --  On return, Expr_Form indicates the categorization of the expression
+   --  and EF_Range_Attr is one of the possibilities.
+
+   --  Error recovery: cannot raise Error_Resync
+
+   --  In the grammar, a RANGE attribute is simply a name, but its use is
+   --  highly restricted, so in the parser, we do not regard it as a name.
+   --  Instead, P_Name returns without scanning the 'RANGE part of the
+   --  attribute, and P_Expression_Or_Range_Attribute handles the range
+   --  attribute reference. In the normal case where a range attribute is
+   --  not allowed, an error message is issued by P_Expression.
+
+   function P_Expression_Or_Range_Attribute return Node_Id is
+      Logical_Op      : Node_Kind;
+      Prev_Logical_Op : Node_Kind;
+      Op_Location     : Source_Ptr;
+      Node1           : Node_Id;
+      Node2           : Node_Id;
+      Attr_Node       : Node_Id;
+
+   begin
+      Node1 := P_Relation;
+
+      if Token = Tok_Apostrophe then
+         Attr_Node := P_Range_Attribute_Reference (Node1);
+         Expr_Form := EF_Range_Attr;
+         return Attr_Node;
+
+      elsif Token in Token_Class_Logop then
+         Prev_Logical_Op := N_Empty;
+
+         loop
+            Op_Location := Token_Ptr;
+            Logical_Op := P_Logical_Operator;
+
+            if Prev_Logical_Op /= N_Empty and then
+               Logical_Op /= Prev_Logical_Op
+            then
+               Error_Msg
+                 ("mixed logical operators in expression", Op_Location);
+               Prev_Logical_Op := N_Empty;
+            else
+               Prev_Logical_Op := Logical_Op;
+            end if;
+
+            Node2 := Node1;
+            Node1 := New_Node (Logical_Op, Op_Location);
+            Set_Left_Opnd (Node1, Node2);
+            Set_Right_Opnd (Node1, P_Relation);
+            Set_Op_Name (Node1);
+            exit when Token not in Token_Class_Logop;
+         end loop;
+
+         Expr_Form := EF_Non_Simple;
+      end if;
+
+      if Token = Tok_Apostrophe then
+         Bad_Range_Attribute (Token_Ptr);
+         return Error;
+      else
+         return Node1;
+      end if;
+   end P_Expression_Or_Range_Attribute;
+
+   -------------------
+   -- 4.4  Relation --
+   -------------------
+
+   --  RELATION ::=
+   --    SIMPLE_EXPRESSION [RELATIONAL_OPERATOR SIMPLE_EXPRESSION]
+   --  | SIMPLE_EXPRESSION [not] in RANGE
+   --  | SIMPLE_EXPRESSION [not] in SUBTYPE_MARK
+
+   --  On return, Expr_Form indicates the categorization of the expression
+
+   --  Note: if Token = Tok_Apostrophe on return, then Expr_Form is set to
+   --  EF_Simple_Name and the following token is RANGE (range attribute case).
+
+   --  Error recovery: cannot raise Error_Resync. If an error occurs within an
+   --  expression, then tokens are scanned until either a non-expression token,
+   --  a right paren (not matched by a left paren) or a comma, is encountered.
+
+   function P_Relation return Node_Id is
+      Node1, Node2 : Node_Id;
+      Optok        : Source_Ptr;
+
+   begin
+      Node1 := P_Simple_Expression;
+
+      if Token not in Token_Class_Relop then
+         return Node1;
+
+      else
+         --  Here we have a relational operator following. If so then scan it
+         --  out. Note that the assignment symbol := is treated as a relational
+         --  operator to improve the error recovery when it is misused for =.
+         --  P_Relational_Operator also parses the IN and NOT IN operations.
+
+         Optok := Token_Ptr;
+         Node2 := New_Node (P_Relational_Operator, Optok);
+         Set_Left_Opnd (Node2, Node1);
+         Set_Op_Name (Node2);
+
+         --  Case of IN or NOT IN
+
+         if Prev_Token = Tok_In then
+            Set_Right_Opnd (Node2, P_Range_Or_Subtype_Mark);
+
+         --  Case of relational operator (= /= < <= > >=)
+
+         else
+            Set_Right_Opnd (Node2, P_Simple_Expression);
+         end if;
+
+         Expr_Form := EF_Non_Simple;
+
+         if Token in Token_Class_Relop then
+            Error_Msg_SC ("unexpected relational operator");
+            raise Error_Resync;
+         end if;
+
+         return Node2;
+      end if;
+
+   --  If any error occurs, then scan to the next expression terminator symbol
+   --  or comma or right paren at the outer (i.e. current) parentheses level.
+   --  The flags are set to indicate a normal simple expression.
+
+   exception
+      when Error_Resync =>
+         Resync_Expression;
+         Expr_Form := EF_Simple;
+         return Error;
+   end P_Relation;
+
+   ----------------------------
+   -- 4.4  Simple Expression --
+   ----------------------------
+
+   --  SIMPLE_EXPRESSION ::=
+   --    [UNARY_ADDING_OPERATOR] TERM {BINARY_ADDING_OPERATOR TERM}
+
+   --  On return, Expr_Form indicates the categorization of the expression
+
+   --  Note: if Token = Tok_Apostrophe on return, then Expr_Form is set to
+   --  EF_Simple_Name and the following token is RANGE (range attribute case).
+
+   --  Error recovery: cannot raise Error_Resync. If an error occurs within an
+   --  expression, then tokens are scanned until either a non-expression token,
+   --  a right paren (not matched by a left paren) or a comma, is encountered.
+
+   --  Note: P_Simple_Expression is called only internally by higher level
+   --  expression routines. In cases in the grammar where a simple expression
+   --  is required, the approach is to scan an expression, and then post an
+   --  appropriate error message if the expression obtained is not simple. This
+   --  gives better error recovery and treatment.
+
+   function P_Simple_Expression return Node_Id is
+      Scan_State : Saved_Scan_State;
+      Node1      : Node_Id;
+      Node2      : Node_Id;
+      Tokptr     : Source_Ptr;
+
+   begin
+      --  Check for cases starting with a name. There are two reasons for
+      --  special casing. First speed things up by catching a common case
+      --  without going through several routine layers. Second the caller must
+      --  be informed via Expr_Form when the simple expression is a name.
+
+      if Token in Token_Class_Name then
+         Node1 := P_Name;
+
+         --  Deal with apostrophe cases
+
+         if Token = Tok_Apostrophe then
+            Save_Scan_State (Scan_State); -- at apostrophe
+            Scan; -- past apostrophe
+
+            --  If qualified expression, scan it out and fall through
+
+            if Token = Tok_Left_Paren then
+               Node1 := P_Qualified_Expression (Node1);
+               Expr_Form := EF_Simple;
+
+            --  If range attribute, then we return with Token pointing to the
+            --  apostrophe. Note: avoid the normal error check on exit. We
+            --  know that the expression really is complete in this case!
+
+            else -- Token = Tok_Range then
+               Restore_Scan_State (Scan_State); -- to apostrophe
+               Expr_Form := EF_Simple_Name;
+               return Node1;
+            end if;
+         end if;
+
+         --  If an expression terminator follows, the previous processing
+         --  completely scanned out the expression (a common case), and
+         --  left Expr_Form set appropriately for returning to our caller.
+
+         if Token in Token_Class_Sterm then
+            null;
+
+         --  If we do not have an expression terminator, then complete the
+         --  scan of a simple expression. This code duplicates the code
+         --  found in P_Term and P_Factor.
+
+         else
+            if Token = Tok_Double_Asterisk then
+               if Style_Check then Style.Check_Exponentiation_Operator; end if;
+               Node2 := New_Node (N_Op_Expon, Token_Ptr);
+               Scan; -- past **
+               Set_Left_Opnd (Node2, Node1);
+               Set_Right_Opnd (Node2, P_Primary);
+               Set_Op_Name (Node2);
+               Node1 := Node2;
+            end if;
+
+            loop
+               exit when Token not in Token_Class_Mulop;
+               Tokptr := Token_Ptr;
+               Node2 := New_Node (P_Multiplying_Operator, Tokptr);
+               if Style_Check then Style.Check_Binary_Operator; end if;
+               Scan; -- past operator
+               Set_Left_Opnd (Node2, Node1);
+               Set_Right_Opnd (Node2, P_Factor);
+               Set_Op_Name (Node2);
+               Node1 := Node2;
+            end loop;
+
+            loop
+               exit when Token not in Token_Class_Binary_Addop;
+               Tokptr := Token_Ptr;
+               Node2 := New_Node (P_Binary_Adding_Operator, Tokptr);
+               if Style_Check then Style.Check_Binary_Operator; end if;
+               Scan; -- past operator
+               Set_Left_Opnd (Node2, Node1);
+               Set_Right_Opnd (Node2, P_Term);
+               Set_Op_Name (Node2);
+               Node1 := Node2;
+            end loop;
+
+            Expr_Form := EF_Simple;
+         end if;
+
+      --  Cases where simple expression does not start with a name
+
+      else
+         --  Scan initial sign and initial Term
+
+         if Token in Token_Class_Unary_Addop then
+            Tokptr := Token_Ptr;
+            Node1 := New_Node (P_Unary_Adding_Operator, Tokptr);
+            if Style_Check then Style.Check_Unary_Plus_Or_Minus; end if;
+            Scan; -- past operator
+            Set_Right_Opnd (Node1, P_Term);
+            Set_Op_Name (Node1);
+         else
+            Node1 := P_Term;
+         end if;
+
+         --  Scan out sequence of terms separated by binary adding operators
+
+         loop
+            exit when Token not in Token_Class_Binary_Addop;
+            Tokptr := Token_Ptr;
+            Node2 := New_Node (P_Binary_Adding_Operator, Tokptr);
+            Scan; -- past operator
+            Set_Left_Opnd (Node2, Node1);
+            Set_Right_Opnd (Node2, P_Term);
+            Set_Op_Name (Node2);
+            Node1 := Node2;
+         end loop;
+
+         --  All done, we clearly do not have name or numeric literal so this
+         --  is a case of a simple expression which is some other possibility.
+
+         Expr_Form := EF_Simple;
+      end if;
+
+      --  Come here at end of simple expression, where we do a couple of
+      --  special checks to improve error recovery.
+
+      --  Special test to improve error recovery. If the current token
+      --  is a period, then someone is trying to do selection on something
+      --  that is not a name, e.g. a qualified expression.
+
+      if Token = Tok_Dot then
+         Error_Msg_SC ("prefix for selection is not a name");
+         raise Error_Resync;
+      end if;
+
+      --  Special test to improve error recovery: If the current token is
+      --  not the first token on a line (as determined by checking the
+      --  previous token position with the start of the current line),
+      --  then we insist that we have an appropriate terminating token.
+      --  Consider the following two examples:
+
+      --   1)  if A nad B then ...
+
+      --   2)  A := B
+      --       C := D
+
+      --  In the first example, we would like to issue a binary operator
+      --  expected message and resynchronize to the then. In the second
+      --  example, we do not want to issue a binary operator message, so
+      --  that instead we will get the missing semicolon message. This
+      --  distinction is of course a heuristic which does not always work,
+      --  but in practice it is quite effective.
+
+      --  Note: the one case in which we do not go through this circuit is
+      --  when we have scanned a range attribute and want to return with
+      --  Token pointing to the apostrophe. The apostrophe is not normally
+      --  an expression terminator, and is not in Token_Class_Sterm, but
+      --  in this special case we know that the expression is complete.
+
+      if not Token_Is_At_Start_Of_Line
+         and then Token not in Token_Class_Sterm
+      then
+         Error_Msg_AP ("binary operator expected");
+         raise Error_Resync;
+      else
+         return Node1;
+      end if;
+
+   --  If any error occurs, then scan to next expression terminator symbol
+   --  or comma, right paren or vertical bar at the outer (i.e. current) paren
+   --  level. Expr_Form is set to indicate a normal simple expression.
+
+   exception
+      when Error_Resync =>
+         Resync_Expression;
+         Expr_Form := EF_Simple;
+         return Error;
+
+   end P_Simple_Expression;
+
+   -----------------------------------------------
+   -- 4.4  Simple Expression or Range Attribute --
+   -----------------------------------------------
+
+   --  SIMPLE_EXPRESSION ::=
+   --    [UNARY_ADDING_OPERATOR] TERM {BINARY_ADDING_OPERATOR TERM}
+
+   --  RANGE_ATTRIBUTE_REFERENCE ::= PREFIX ' RANGE_ATTRIBUTE_DESIGNATOR
+
+   --  RANGE_ATTRIBUTE_DESIGNATOR ::= range [(static_EXPRESSION)]
+
+   --  Error recovery: cannot raise Error_Resync
+
+   function P_Simple_Expression_Or_Range_Attribute return Node_Id is
+      Sexpr     : Node_Id;
+      Attr_Node : Node_Id;
+
+   begin
+      Sexpr := P_Simple_Expression;
+
+      if Token = Tok_Apostrophe then
+         Attr_Node := P_Range_Attribute_Reference (Sexpr);
+         Expr_Form := EF_Range_Attr;
+         return Attr_Node;
+
+      else
+         return Sexpr;
+      end if;
+   end P_Simple_Expression_Or_Range_Attribute;
+
+   ---------------
+   -- 4.4  Term --
+   ---------------
+
+   --  TERM ::= FACTOR {MULTIPLYING_OPERATOR FACTOR}
+
+   --  Error recovery: can raise Error_Resync
+
+   function P_Term return Node_Id is
+      Node1, Node2 : Node_Id;
+      Tokptr       : Source_Ptr;
+
+   begin
+      Node1 := P_Factor;
+
+      loop
+         exit when Token not in Token_Class_Mulop;
+         Tokptr := Token_Ptr;
+         Node2 := New_Node (P_Multiplying_Operator, Tokptr);
+         Scan; -- past operator
+         Set_Left_Opnd (Node2, Node1);
+         Set_Right_Opnd (Node2, P_Factor);
+         Set_Op_Name (Node2);
+         Node1 := Node2;
+      end loop;
+
+      return Node1;
+   end P_Term;
+
+   -----------------
+   -- 4.4  Factor --
+   -----------------
+
+   --  FACTOR ::= PRIMARY [** PRIMARY] | abs PRIMARY | not PRIMARY
+
+   --  Error recovery: can raise Error_Resync
+
+   function P_Factor return Node_Id is
+      Node1 : Node_Id;
+      Node2 : Node_Id;
+
+   begin
+      if Token = Tok_Abs then
+         Node1 := New_Node (N_Op_Abs, Token_Ptr);
+         if Style_Check then Style.Check_Abs_Not; end if;
+         Scan; -- past ABS
+         Set_Right_Opnd (Node1, P_Primary);
+         Set_Op_Name (Node1);
+         return Node1;
+
+      elsif Token = Tok_Not then
+         Node1 := New_Node (N_Op_Not, Token_Ptr);
+         if Style_Check then Style.Check_Abs_Not; end if;
+         Scan; -- past NOT
+         Set_Right_Opnd (Node1, P_Primary);
+         Set_Op_Name (Node1);
+         return Node1;
+
+      else
+         Node1 := P_Primary;
+
+         if Token = Tok_Double_Asterisk then
+            Node2 := New_Node (N_Op_Expon, Token_Ptr);
+            Scan; -- past **
+            Set_Left_Opnd (Node2, Node1);
+            Set_Right_Opnd (Node2, P_Primary);
+            Set_Op_Name (Node2);
+            return Node2;
+         else
+            return Node1;
+         end if;
+      end if;
+   end P_Factor;
+
+   ------------------
+   -- 4.4  Primary --
+   ------------------
+
+   --  PRIMARY ::=
+   --    NUMERIC_LITERAL  | null
+   --  | STRING_LITERAL   | AGGREGATE
+   --  | NAME             | QUALIFIED_EXPRESSION
+   --  | ALLOCATOR        | (EXPRESSION)
+
+   --  Error recovery: can raise Error_Resync
+
+   function P_Primary return Node_Id is
+      Scan_State : Saved_Scan_State;
+      Node1      : Node_Id;
+
+   begin
+      --  The loop runs more than once only if misplaced pragmas are found
+
+      loop
+         case Token is
+
+            --  Name token can start a name, call or qualified expression, all
+            --  of which are acceptable possibilities for primary. Note also
+            --  that string literal is included in name (as operator symbol)
+            --  and type conversion is included in name (as indexed component).
+
+            when Tok_Char_Literal | Tok_Operator_Symbol | Tok_Identifier =>
+               Node1 := P_Name;
+
+               --  All done unless apostrophe follows
+
+               if Token /= Tok_Apostrophe then
+                  return Node1;
+
+               --  Apostrophe following means that we have either just parsed
+               --  the subtype mark of a qualified expression, or the prefix
+               --  or a range attribute.
+
+               else -- Token = Tok_Apostrophe
+                  Save_Scan_State (Scan_State); -- at apostrophe
+                  Scan; -- past apostrophe
+
+                  --  If range attribute, then this is always an error, since
+                  --  the only legitimate case (where the scanned expression is
+                  --  a qualified simple name) is handled at the level of the
+                  --  Simple_Expression processing. This case corresponds to a
+                  --  usage such as 3 + A'Range, which is always illegal.
+
+                  if Token = Tok_Range then
+                     Restore_Scan_State (Scan_State); -- to apostrophe
+                     Bad_Range_Attribute (Token_Ptr);
+                     return Error;
+
+                  --  If left paren, then we have a qualified expression.
+                  --  Note that P_Name guarantees that in this case, where
+                  --  Token = Tok_Apostrophe on return, the only two possible
+                  --  tokens following the apostrophe are left paren and
+                  --  RANGE, so we know we have a left paren here.
+
+                  else -- Token = Tok_Left_Paren
+                     return P_Qualified_Expression (Node1);
+
+                  end if;
+               end if;
+
+            --  Numeric or string literal
+
+            when Tok_Integer_Literal |
+                 Tok_Real_Literal    |
+                 Tok_String_Literal  =>
+
+               Node1 := Token_Node;
+               Scan; -- past number
+               return Node1;
+
+            --  Left paren, starts aggregate or parenthesized expression
+
+            when Tok_Left_Paren =>
+               return P_Aggregate_Or_Paren_Expr;
+
+            --  Allocator
+
+            when Tok_New =>
+               return P_Allocator;
+
+            --  Null
+
+            when Tok_Null =>
+               Scan; -- past NULL
+               return New_Node (N_Null, Prev_Token_Ptr);
+
+            --  Pragma, not allowed here, so just skip past it
+
+            when Tok_Pragma =>
+               P_Pragmas_Misplaced;
+
+            --  Anything else is illegal as the first token of a primary, but
+            --  we test for a reserved identifier so that it is treated nicely
+
+            when others =>
+               if Is_Reserved_Identifier then
+                  return P_Identifier;
+
+               elsif Prev_Token = Tok_Comma then
+                  Error_Msg_SP ("extra "","" ignored");
+                  raise Error_Resync;
+
+               else
+                  Error_Msg_AP ("missing operand");
+                  raise Error_Resync;
+               end if;
+
+         end case;
+      end loop;
+   end P_Primary;
+
+   ---------------------------
+   -- 4.5  Logical Operator --
+   ---------------------------
+
+   --  LOGICAL_OPERATOR  ::=  and | or | xor
+
+   --  Note: AND THEN and OR ELSE are also treated as logical operators
+   --  by the parser (even though they are not operators semantically)
+
+   --  The value returned is the appropriate Node_Kind code for the operator
+   --  On return, Token points to the token following the scanned operator.
+
+   --  The caller has checked that the first token is a legitimate logical
+   --  operator token (i.e. is either XOR, AND, OR).
+
+   --  Error recovery: cannot raise Error_Resync
+
+   function P_Logical_Operator return Node_Kind is
+   begin
+      if Token = Tok_And then
+         if Style_Check then Style.Check_Binary_Operator; end if;
+         Scan; -- past AND
+
+         if Token = Tok_Then then
+            Scan; -- past THEN
+            return N_And_Then;
+         else
+            return N_Op_And;
+         end if;
+
+      elsif Token = Tok_Or then
+         if Style_Check then Style.Check_Binary_Operator; end if;
+         Scan; -- past OR
+
+         if Token = Tok_Else then
+            Scan; -- past ELSE
+            return N_Or_Else;
+         else
+            return N_Op_Or;
+         end if;
+
+      else -- Token = Tok_Xor
+         if Style_Check then Style.Check_Binary_Operator; end if;
+         Scan; -- past XOR
+         return N_Op_Xor;
+      end if;
+   end P_Logical_Operator;
+
+   ------------------------------
+   -- 4.5  Relational Operator --
+   ------------------------------
+
+   --  RELATIONAL_OPERATOR ::= = | /= | < | <= | > | >=
+
+   --  The value returned is the appropriate Node_Kind code for the operator.
+   --  On return, Token points to the operator token, NOT past it.
+
+   --  The caller has checked that the first token is a legitimate relational
+   --  operator token (i.e. is one of the operator tokens listed above).
+
+   --  Error recovery: cannot raise Error_Resync
+
+   function P_Relational_Operator return Node_Kind is
+      Op_Kind : Node_Kind;
+      Relop_Node : constant array (Token_Class_Relop) of Node_Kind :=
+        (Tok_Less           => N_Op_Lt,
+         Tok_Equal          => N_Op_Eq,
+         Tok_Greater        => N_Op_Gt,
+         Tok_Not_Equal      => N_Op_Ne,
+         Tok_Greater_Equal  => N_Op_Ge,
+         Tok_Less_Equal     => N_Op_Le,
+         Tok_In             => N_In,
+         Tok_Not            => N_Not_In,
+         Tok_Box            => N_Op_Ne);
+
+   begin
+      if Token = Tok_Box then
+         Error_Msg_SC ("""<>"" should be ""/=""");
+      end if;
+
+      Op_Kind := Relop_Node (Token);
+      if Style_Check then Style.Check_Binary_Operator; end if;
+      Scan; -- past operator token
+
+      if Prev_Token = Tok_Not then
+         T_In;
+      end if;
+
+      return Op_Kind;
+   end P_Relational_Operator;
+
+   ---------------------------------
+   -- 4.5  Binary Adding Operator --
+   ---------------------------------
+
+   --  BINARY_ADDING_OPERATOR ::= + | - | &
+
+   --  The value returned is the appropriate Node_Kind code for the operator.
+   --  On return, Token points to the operator token (NOT past it).
+
+   --  The caller has checked that the first token is a legitimate adding
+   --  operator token (i.e. is one of the operator tokens listed above).
+
+   --  Error recovery: cannot raise Error_Resync
+
+   function P_Binary_Adding_Operator return Node_Kind is
+      Addop_Node : constant array (Token_Class_Binary_Addop) of Node_Kind :=
+        (Tok_Ampersand      => N_Op_Concat,
+         Tok_Minus          => N_Op_Subtract,
+         Tok_Plus           => N_Op_Add);
+   begin
+      return Addop_Node (Token);
+   end P_Binary_Adding_Operator;
+
+   --------------------------------
+   -- 4.5  Unary Adding Operator --
+   --------------------------------
+
+   --  UNARY_ADDING_OPERATOR ::= + | -
+
+   --  The value returned is the appropriate Node_Kind code for the operator.
+   --  On return, Token points to the operator token (NOT past it).
+
+   --  The caller has checked that the first token is a legitimate adding
+   --  operator token (i.e. is one of the operator tokens listed above).
+
+   --  Error recovery: cannot raise Error_Resync
+
+   function P_Unary_Adding_Operator return Node_Kind is
+      Addop_Node : constant array (Token_Class_Unary_Addop) of Node_Kind :=
+        (Tok_Minus          => N_Op_Minus,
+         Tok_Plus           => N_Op_Plus);
+   begin
+      return Addop_Node (Token);
+   end P_Unary_Adding_Operator;
+
+   -------------------------------
+   -- 4.5  Multiplying Operator --
+   -------------------------------
+
+   --  MULTIPLYING_OPERATOR ::= * | / | mod | rem
+
+   --  The value returned is the appropriate Node_Kind code for the operator.
+   --  On return, Token points to the operator token (NOT past it).
+
+   --  The caller has checked that the first token is a legitimate multiplying
+   --  operator token (i.e. is one of the operator tokens listed above).
+
+   --  Error recovery: cannot raise Error_Resync
+
+   function P_Multiplying_Operator return Node_Kind is
+      Mulop_Node : constant array (Token_Class_Mulop) of Node_Kind :=
+        (Tok_Asterisk       => N_Op_Multiply,
+         Tok_Mod            => N_Op_Mod,
+         Tok_Rem            => N_Op_Rem,
+         Tok_Slash          => N_Op_Divide);
+   begin
+      return Mulop_Node (Token);
+   end P_Multiplying_Operator;
+
+   --------------------------------------
+   -- 4.5  Highest Precedence Operator --
+   --------------------------------------
+
+   --  Parsed by P_Factor (4.4)
+
+   --  Note: this rule is not in fact used by the grammar at any point!
+
+   --------------------------
+   -- 4.6  Type Conversion --
+   --------------------------
+
+   --  Parsed by P_Primary as a Name (4.1)
+
+   -------------------------------
+   -- 4.7  Qualified Expression --
+   -------------------------------
+
+   --  QUALIFIED_EXPRESSION ::=
+   --    SUBTYPE_MARK ' (EXPRESSION) | SUBTYPE_MARK ' AGGREGATE
+
+   --  The caller has scanned the name which is the Subtype_Mark parameter
+   --  and scanned past the single quote following the subtype mark. The
+   --  caller has not checked that this name is in fact appropriate for
+   --  a subtype mark name (i.e. it is a selected component or identifier).
+
+   --  Error_Recovery: cannot raise Error_Resync
+
+   function  P_Qualified_Expression (Subtype_Mark : Node_Id) return Node_Id is
+      Qual_Node : Node_Id;
+
+   begin
+      Qual_Node := New_Node (N_Qualified_Expression, Prev_Token_Ptr);
+      Set_Subtype_Mark (Qual_Node, Check_Subtype_Mark (Subtype_Mark));
+      Set_Expression (Qual_Node, P_Aggregate_Or_Paren_Expr);
+      return Qual_Node;
+   end P_Qualified_Expression;
+
+   --------------------
+   -- 4.8  Allocator --
+   --------------------
+
+   --  ALLOCATOR ::=
+   --   new SUBTYPE_INDICATION | new QUALIFIED_EXPRESSION
+
+   --  The caller has checked that the initial token is NEW
+
+   --  Error recovery: can raise Error_Resync
+
+   function P_Allocator return Node_Id is
+      Alloc_Node  : Node_Id;
+      Type_Node   : Node_Id;
+
+   begin
+      Alloc_Node := New_Node (N_Allocator, Token_Ptr);
+      T_New;
+      Type_Node := P_Subtype_Mark_Resync;
+
+      if Token = Tok_Apostrophe then
+         Scan; -- past apostrophe
+         Set_Expression (Alloc_Node, P_Qualified_Expression (Type_Node));
+      else
+         Set_Expression (Alloc_Node, P_Subtype_Indication (Type_Node));
+      end if;
+
+      return Alloc_Node;
+   end P_Allocator;
+
+end Ch4;
diff --git a/gcc/ada/par-ch5.adb b/gcc/ada/par-ch5.adb
new file mode 100644 (file)
index 0000000..2ec5672
--- /dev/null
@@ -0,0 +1,2184 @@
+------------------------------------------------------------------------------
+--                                                                          --
+--                         GNAT COMPILER COMPONENTS                         --
+--                                                                          --
+--                              P A R . C H 5                               --
+--                                                                          --
+--                                 B o d y                                  --
+--                                                                          --
+--                            $Revision: 1.95 $
+--                                                                          --
+--          Copyright (C) 1992-2001, Free Software Foundation, Inc.         --
+--                                                                          --
+-- GNAT is free software;  you can  redistribute it  and/or modify it under --
+-- terms of the  GNU General Public License as published  by the Free Soft- --
+-- ware  Foundation;  either version 2,  or (at your option) any later ver- --
+-- sion.  GNAT is distributed in the hope that it will be useful, but WITH- --
+-- OUT 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  distributed with GNAT;  see file COPYING.  If not, write --
+-- to  the Free Software Foundation,  59 Temple Place - Suite 330,  Boston, --
+-- MA 02111-1307, USA.                                                      --
+--                                                                          --
+-- GNAT was originally developed  by the GNAT team at  New York University. --
+-- It is now maintained by Ada Core Technologies Inc (http://www.gnat.com). --
+--                                                                          --
+------------------------------------------------------------------------------
+
+pragma Style_Checks (All_Checks);
+--  Turn off subprogram body ordering check. Subprograms are in order
+--  by RM section rather than alphabetical
+
+separate (Par)
+package body Ch5 is
+
+   --  Local functions, used only in this chapter
+
+   function P_Case_Statement                     return Node_Id;
+   function P_Case_Statement_Alternative         return Node_Id;
+   function P_Condition                          return Node_Id;
+   function P_Exit_Statement                     return Node_Id;
+   function P_Goto_Statement                     return Node_Id;
+   function P_If_Statement                       return Node_Id;
+   function P_Label                              return Node_Id;
+   function P_Loop_Parameter_Specification       return Node_Id;
+   function P_Null_Statement                     return Node_Id;
+
+   function P_Assignment_Statement (LHS : Node_Id)  return Node_Id;
+   --  Parse assignment statement. On entry, the caller has scanned the left
+   --  hand side (passed in as Lhs), and the colon-equal (or some symbol
+   --  taken to be an error equivalent such as equal).
+
+   function P_Begin_Statement (Block_Name : Node_Id := Empty) return Node_Id;
+   --  Parse begin-end statement. If Block_Name is non-Empty on entry, it is
+   --  the N_Identifier node for the label on the block. If Block_Name is
+   --  Empty on entry (the default), then the block statement is unlabeled.
+
+   function P_Declare_Statement (Block_Name : Node_Id := Empty) return Node_Id;
+   --  Parse declare block. If Block_Name is non-Empty on entry, it is
+   --  the N_Identifier node for the label on the block. If Block_Name is
+   --  Empty on entry (the default), then the block statement is unlabeled.
+
+   function P_For_Statement (Loop_Name : Node_Id := Empty) return Node_Id;
+   --  Parse for statement. If Loop_Name is non-Empty on entry, it is
+   --  the N_Identifier node for the label on the loop. If Loop_Name is
+   --  Empty on entry (the default), then the for statement is unlabeled.
+
+   function P_Loop_Statement (Loop_Name : Node_Id := Empty) return Node_Id;
+   --  Parse loop statement. If Loop_Name is non-Empty on entry, it is
+   --  the N_Identifier node for the label on the loop. If Loop_Name is
+   --  Empty on entry (the default), then the loop statement is unlabeled.
+
+   function P_While_Statement (Loop_Name : Node_Id := Empty) return Node_Id;
+   --  Parse while statement. If Loop_Name is non-Empty on entry, it is
+   --  the N_Identifier node for the label on the loop. If Loop_Name is
+   --  Empty on entry (the default), then the while statement is unlabeled.
+
+   function Set_Loop_Block_Name (L : Character) return Name_Id;
+   --  Given a letter 'L' for a loop or 'B' for a block, returns a name
+   --  of the form L_nn or B_nn where nn is a serial number obtained by
+   --  incrementing the variable Loop_Block_Count.
+
+   procedure Then_Scan;
+   --  Scan past THEN token, testing for illegal junk after it
+
+   ---------------------------------
+   -- 5.1  Sequence of Statements --
+   ---------------------------------
+
+   --  SEQUENCE_OF_STATEMENTS ::= STATEMENT {STATEMENT}
+
+   --  STATEMENT ::=
+   --    {LABEL} SIMPLE_STATEMENT | {LABEL} COMPOUND_STATEMENT
+
+   --  SIMPLE_STATEMENT ::=      NULL_STATEMENT
+   --  | ASSIGNMENT_STATEMENT  | EXIT_STATEMENT
+   --  | GOTO_STATEMENT        | PROCEDURE_CALL_STATEMENT
+   --  | RETURN_STATEMENT      | ENTRY_CALL_STATEMENT
+   --  | REQUEUE_STATEMENT     | DELAY_STATEMENT
+   --  | ABORT_STATEMENT       | RAISE_STATEMENT
+   --  | CODE_STATEMENT
+
+   --  COMPOUND_STATEMENT ::=
+   --    IF_STATEMENT         | CASE_STATEMENT
+   --  | LOOP_STATEMENT       | BLOCK_STATEMENT
+   --  | ACCEPT_STATEMENT     | SELECT_STATEMENT
+
+   --  This procedure scans a sequence of statements. The caller sets SS_Flags
+   --  to indicate acceptable termination conditions for the sequence:
+
+   --    SS_Flags.Eftm Terminate on ELSIF
+   --    SS_Flags.Eltm Terminate on ELSE
+   --    SS_Flags.Extm Terminate on EXCEPTION
+   --    SS_Flags.Ortm Terminate on OR
+   --    SS_Flags.Tatm Terminate on THEN ABORT (Token = ABORT on return)
+   --    SS_Flags.Whtm Terminate on WHEN
+   --    SS_Flags.Unco Unconditional terminate after scanning one statement
+
+   --  In addition, the scan is always terminated by encountering END or the
+   --  end of file (EOF) condition. If one of the six above terminators is
+   --  encountered with the corresponding SS_Flags flag not set, then the
+   --  action taken is as follows:
+
+   --    If the keyword occurs to the left of the expected column of the end
+   --    for the current sequence (as recorded in the current end context),
+   --    then it is assumed to belong to an outer context, and is considered
+   --    to terminate the sequence of statements.
+
+   --    If the keyword occurs to the right of, or in the expected column of
+   --    the end for the current sequence, then an error message is output,
+   --    the keyword together with its associated context is skipped, and
+   --    the statement scan continues until another terminator is found.
+
+   --  Note that the first action means that control can return to the caller
+   --  with Token set to a terminator other than one of those specified by the
+   --  SS parameter. The caller should treat such a case as equivalent to END.
+
+   --  In addition, the flag SS_Flags.Sreq is set to True to indicate that at
+   --  least one real statement (other than a pragma) is required in the
+   --  statement sequence. During the processing of the sequence, this
+   --  flag is manipulated to indicate the current status of the requirement
+   --  for a statement. For example, it is turned off by the occurrence of a
+   --  statement, and back on by a label (which requires a following statement)
+
+   --  Error recovery: cannot raise Error_Resync. If an error occurs during
+   --  parsing a statement, then the scan pointer is advanced past the next
+   --  semicolon and the parse continues.
+
+   function P_Sequence_Of_Statements (SS_Flags : SS_Rec) return List_Id is
+
+      Statement_Required : Boolean;
+      --  This flag indicates if a subsequent statement (other than a pragma)
+      --  is required. It is initialized from the Sreq flag, and modified as
+      --  statements are scanned (a statement turns it off, and a label turns
+      --  it back on again since a statement must follow a label).
+
+      Declaration_Found : Boolean := False;
+      --  This flag is set True if a declaration is encountered, so that the
+      --  error message about declarations in the statement part is only
+      --  given once for a given sequence of statements.
+
+      Scan_State_Label : Saved_Scan_State;
+      Scan_State       : Saved_Scan_State;
+
+      Statement_List : List_Id;
+      Block_Label    : Name_Id;
+      Id_Node        : Node_Id;
+      Name_Node      : Node_Id;
+
+      procedure Junk_Declaration;
+      --  Procedure called to handle error of declaration encountered in
+      --  statement sequence.
+
+      procedure Test_Statement_Required;
+      --  Flag error if Statement_Required flag set
+
+      procedure Junk_Declaration is
+      begin
+         if (not Declaration_Found) or All_Errors_Mode then
+            Error_Msg_SC ("declarations must come before BEGIN");
+            Declaration_Found := True;
+         end if;
+
+         Skip_Declaration (Statement_List);
+      end Junk_Declaration;
+
+      procedure Test_Statement_Required is
+      begin
+         if Statement_Required then
+            Error_Msg_BC ("statement expected");
+         end if;
+      end Test_Statement_Required;
+
+   --  Start of processing for P_Sequence_Of_Statements
+
+   begin
+      Statement_List := New_List;
+      Statement_Required := SS_Flags.Sreq;
+
+      loop
+         while Token = Tok_Semicolon loop
+            Error_Msg_SC ("unexpected semicolon ignored");
+            Scan; -- past junk semicolon
+         end loop;
+
+         begin
+            if Style_Check then Style.Check_Indentation; end if;
+
+            --  Deal with reserved identifier (in assignment or call)
+
+            if Is_Reserved_Identifier then
+               Save_Scan_State (Scan_State); -- at possible bad identifier
+               Scan; -- and scan past it
+
+               --  We have an reserved word which is spelled in identifier
+               --  style, so the question is whether it really is intended
+               --  to be an identifier.
+
+               if
+                  --  If followed by a semicolon, then it is an identifier,
+                  --  with the exception of the cases tested for below.
+
+                  (Token = Tok_Semicolon
+                    and then Prev_Token /= Tok_Return
+                    and then Prev_Token /= Tok_Null
+                    and then Prev_Token /= Tok_Raise
+                    and then Prev_Token /= Tok_End
+                    and then Prev_Token /= Tok_Exit)
+
+                  --  If followed by colon, colon-equal, or dot, then we
+                  --  definitely  have an identifier (could not be reserved)
+
+                  or else Token = Tok_Colon
+                  or else Token = Tok_Colon_Equal
+                  or else Token = Tok_Dot
+
+                  --  Left paren means we have an identifier except for those
+                  --  reserved words that can legitimately be followed by a
+                  --  left paren.
+
+                  or else
+                    (Token = Tok_Left_Paren
+                      and then Prev_Token /= Tok_Case
+                      and then Prev_Token /= Tok_Delay
+                      and then Prev_Token /= Tok_If
+                      and then Prev_Token /= Tok_Elsif
+                      and then Prev_Token /= Tok_Return
+                      and then Prev_Token /= Tok_When
+                      and then Prev_Token /= Tok_While
+                      and then Prev_Token /= Tok_Separate)
+               then
+                  --  Here we have an apparent reserved identifier and the
+                  --  token past it is appropriate to this usage (and would
+                  --  be a definite error if this is not an identifier). What
+                  --  we do is to use P_Identifier to fix up the identifier,
+                  --  and then fall into the normal processing.
+
+                  Restore_Scan_State (Scan_State); -- back to the ID
+                  Scan_Reserved_Identifier (Force_Msg => False);
+
+                  --  Not a reserved identifier after all (or at least we can't
+                  --  be sure that it is), so reset the scan and continue.
+
+               else
+                  Restore_Scan_State (Scan_State); -- back to the reserved word
+               end if;
+            end if;
+
+            --  Now look to see what kind of statement we have
+
+            case Token is
+
+               --  Case of end or EOF
+
+               when Tok_End | Tok_EOF =>
+
+                  --  These tokens always terminate the statement sequence
+
+                  Test_Statement_Required;
+                  exit;
+
+               --  Case of ELSIF
+
+               when Tok_Elsif =>
+
+                  --  Terminate if Eftm set or if the ELSIF is to the left
+                  --  of the expected column of the end for this sequence
+
+                  if SS_Flags.Eftm
+                     or else Start_Column < Scope.Table (Scope.Last).Ecol
+                  then
+                     Test_Statement_Required;
+                     exit;
+
+                  --  Otherwise complain and skip past ELSIF Condition then
+
+                  else
+                     Error_Msg_SC ("ELSIF not allowed here");
+                     Scan; -- past ELSIF
+                     Discard_Junk_Node (P_Expression_No_Right_Paren);
+                     Then_Scan;
+                     Statement_Required := False;
+                  end if;
+
+               --  Case of ELSE
+
+               when Tok_Else =>
+
+                  --  Terminate if Eltm set or if the else is to the left
+                  --  of the expected column of the end for this sequence
+
+                  if SS_Flags.Eltm
+                     or else Start_Column < Scope.Table (Scope.Last).Ecol
+                  then
+                     Test_Statement_Required;
+                     exit;
+
+                  --  Otherwise complain and skip past else
+
+                  else
+                     Error_Msg_SC ("ELSE not allowed here");
+                     Scan; -- past ELSE
+                     Statement_Required := False;
+                  end if;
+
+               --  Case of exception
+
+               when Tok_Exception =>
+                  Test_Statement_Required;
+
+                  --  If Extm not set and the exception is not to the left
+                  --  of the expected column of the end for this sequence, then
+                  --  we assume it belongs to the current sequence, even though
+                  --  it is not permitted.
+
+                  if not SS_Flags.Extm and then
+                     Start_Column >= Scope.Table (Scope.Last).Ecol
+
+                  then
+                     Error_Msg_SC ("exception handler not permitted here");
+                     Scan; -- past EXCEPTION
+                     Discard_Junk_List (Parse_Exception_Handlers);
+                  end if;
+
+                  --  Always return, in the case where we scanned out handlers
+                  --  that we did not expect, Parse_Exception_Handlers returned
+                  --  with Token being either end or EOF, so we are OK
+
+                  exit;
+
+               --  Case of OR
+
+               when Tok_Or =>
+
+                  --  Terminate if Ortm set or if the or is to the left
+                  --  of the expected column of the end for this sequence
+
+                  if SS_Flags.Ortm
+                     or else Start_Column < Scope.Table (Scope.Last).Ecol
+                  then
+                     Test_Statement_Required;
+                     exit;
+
+                  --  Otherwise complain and skip past or
+
+                  else
+                     Error_Msg_SC ("OR not allowed here");
+                     Scan; -- past or
+                     Statement_Required := False;
+                  end if;
+
+               --  Case of THEN (deal also with THEN ABORT)
+
+               when Tok_Then =>
+                  Save_Scan_State (Scan_State); -- at THEN
+                  Scan; -- past THEN
+
+                  --  Terminate if THEN ABORT allowed (ATC case)
+
+                  exit when SS_Flags.Tatm and then Token = Tok_Abort;
+
+                  --  Otherwise we treat THEN as some kind of mess where we
+                  --  did not see the associated IF, but we pick up assuming
+                  --  it had been there!
+
+                  Restore_Scan_State (Scan_State); -- to THEN
+                  Append_To (Statement_List, P_If_Statement);
+                  Statement_Required := False;
+
+               --  Case of WHEN (error because we are not in a case)
+
+               when Tok_When | Tok_Others =>
+
+                  --  Terminate if Whtm set or if the WHEN is to the left
+                  --  of the expected column of the end for this sequence
+
+                  if SS_Flags.Whtm
+                     or else Start_Column < Scope.Table (Scope.Last).Ecol
+                  then
+                     Test_Statement_Required;
+                     exit;
+
+                  --  Otherwise complain and skip when Choice {| Choice} =>
+
+                  else
+                     Error_Msg_SC ("WHEN not allowed here");
+                     Scan; -- past when
+                     Discard_Junk_List (P_Discrete_Choice_List);
+                     TF_Arrow;
+                     Statement_Required := False;
+                  end if;
+
+               --  Cases of statements starting with an identifier
+
+               when Tok_Identifier =>
+                  Check_Bad_Layout;
+
+                  --  Save scan pointers and line number in case block label
+
+                  Id_Node := Token_Node;
+                  Block_Label := Token_Name;
+                  Save_Scan_State (Scan_State_Label); -- at possible label
+                  Scan; -- past Id
+
+                  --  Check for common case of assignment, since it occurs
+                  --  frequently, and we want to process it efficiently.
+
+                  if Token = Tok_Colon_Equal then
+                     Scan; -- past the colon-equal
+                     Append_To (Statement_List,
+                       P_Assignment_Statement (Id_Node));
+                     Statement_Required := False;
+
+                  --  Check common case of procedure call, another case that
+                  --  we want to speed up as much as possible.
+
+                  elsif Token = Tok_Semicolon then
+                     Append_To (Statement_List,
+                       P_Statement_Name (Id_Node));
+                     Scan; -- past semicolon
+                     Statement_Required := False;
+
+                  --  Check for case of "go to" in place of "goto"
+
+                  elsif Token = Tok_Identifier
+                    and then Block_Label = Name_Go
+                    and then Token_Name = Name_To
+                  then
+                     Error_Msg_SP ("goto is one word");
+                     Append_To (Statement_List, P_Goto_Statement);
+                     Statement_Required := False;
+
+                  --  Check common case of = used instead of :=, just so we
+                  --  give a better error message for this special misuse.
+
+                  elsif Token = Tok_Equal then
+                     T_Colon_Equal; -- give := expected message
+                     Append_To (Statement_List,
+                       P_Assignment_Statement (Id_Node));
+                     Statement_Required := False;
+
+                  --  Check case of loop label or block label
+
+                  elsif Token = Tok_Colon
+                    or else (Token in Token_Class_Labeled_Stmt
+                              and then not Token_Is_At_Start_Of_Line)
+                  then
+                     T_Colon; -- past colon (if there, or msg for missing one)
+
+                     --  Test for more than one label
+
+                     loop
+                        exit when Token /= Tok_Identifier;
+                        Save_Scan_State (Scan_State); -- at second Id
+                        Scan; -- past Id
+
+                        if Token = Tok_Colon then
+                           Error_Msg_SP
+                              ("only one label allowed on block or loop");
+                           Scan; -- past colon on extra label
+
+                           --  Use the second label as the "real" label
+
+                           Scan_State_Label := Scan_State;
+
+                           --  We will set Error_name as the Block_Label since
+                           --  we really don't know which of the labels might
+                           --  be used at the end of the loop or block!
+
+                           Block_Label := Error_Name;
+
+                        --  If Id with no colon, then backup to point to the
+                        --  Id and we will issue the message below when we try
+                        --  to scan out the statement as some other form.
+
+                        else
+                           Restore_Scan_State (Scan_State); -- to second Id
+                           exit;
+                        end if;
+                     end loop;
+
+                     --  Loop_Statement (labeled Loop_Statement)
+
+                     if Token = Tok_Loop then
+                        Append_To (Statement_List,
+                          P_Loop_Statement (Id_Node));
+
+                     --  While statement (labeled loop statement with WHILE)
+
+                     elsif Token = Tok_While then
+                        Append_To (Statement_List,
+                          P_While_Statement (Id_Node));
+
+                     --  Declare statement (labeled block statement with
+                     --  DECLARE part)
+
+                     elsif Token = Tok_Declare then
+                        Append_To (Statement_List,
+                          P_Declare_Statement (Id_Node));
+
+                     --  Begin statement (labeled block statement with no
+                     --  DECLARE part)
+
+                     elsif Token = Tok_Begin then
+                        Append_To (Statement_List,
+                          P_Begin_Statement (Id_Node));
+
+                     --  For statement (labeled loop statement with FOR)
+
+                     elsif Token = Tok_For then
+                        Append_To (Statement_List,
+                          P_For_Statement (Id_Node));
+
+                     --  Improper statement follows label. If we have an
+                     --  expression token, then assume the colon was part
+                     --  of a misplaced declaration.
+
+                     elsif Token not in Token_Class_Eterm then
+                        Restore_Scan_State (Scan_State_Label);
+                        Junk_Declaration;
+
+                     --  Otherwise complain we have inappropriate statement
+
+                     else
+                        Error_Msg_AP
+                          ("loop or block statement must follow label");
+                     end if;
+
+                     Statement_Required := False;
+
+                  --  Here we have an identifier followed by something
+                  --  other than a colon, semicolon or assignment symbol.
+                  --  The only valid possibility is a name extension symbol
+
+                  elsif Token in Token_Class_Namext then
+                     Restore_Scan_State (Scan_State_Label); -- to Id
+                     Name_Node := P_Name;
+
+                     --  Skip junk right parens in this context
+
+                     while Token = Tok_Right_Paren loop
+                        Error_Msg_SC ("extra right paren");
+                        Scan; -- past )
+                     end loop;
+
+                     --  Check context following call
+
+                     if Token = Tok_Colon_Equal then
+                        Scan; -- past colon equal
+                        Append_To (Statement_List,
+                          P_Assignment_Statement (Name_Node));
+                        Statement_Required := False;
+
+                     --  Check common case of = used instead of :=
+
+                     elsif Token = Tok_Equal then
+                        T_Colon_Equal; -- give := expected message
+                        Append_To (Statement_List,
+                          P_Assignment_Statement (Name_Node));
+                        Statement_Required := False;
+
+                     --  Check apostrophe cases
+
+                     elsif Token = Tok_Apostrophe then
+                        Append_To (Statement_List,
+                          P_Code_Statement (Name_Node));
+                        Statement_Required := False;
+
+                     --  The only other valid item after a name is ; which
+                     --  means that the item we just scanned was a call.
+
+                     elsif Token = Tok_Semicolon then
+                        Append_To (Statement_List,
+                          P_Statement_Name (Name_Node));
+                        Scan; -- past semicolon
+                        Statement_Required := False;
+
+                        --  Else we have a missing semicolon
+
+                     else
+                        TF_Semicolon;
+                        Statement_Required := False;
+                     end if;
+
+                  --  If junk after identifier, check if identifier is an
+                  --  instance of an incorrectly spelled keyword. If so, we
+                  --  do nothing. The Bad_Spelling_Of will have reset Token
+                  --  to the appropriate keyword, so the next time round the
+                  --  loop we will process the modified token. Note that we
+                  --  check for ELSIF before ELSE here. That's not accidental.
+                  --  We don't want to identify a misspelling of ELSE as
+                  --  ELSIF, and in particular we do not want to treat ELSEIF
+                  --  as ELSE IF.
+
+                  else
+                     Restore_Scan_State (Scan_State_Label); -- to identifier
+
+                     if Bad_Spelling_Of (Tok_Abort)
+                       or else Bad_Spelling_Of (Tok_Accept)
+                       or else Bad_Spelling_Of (Tok_Case)
+                       or else Bad_Spelling_Of (Tok_Declare)
+                       or else Bad_Spelling_Of (Tok_Delay)
+                       or else Bad_Spelling_Of (Tok_Elsif)
+                       or else Bad_Spelling_Of (Tok_Else)
+                       or else Bad_Spelling_Of (Tok_End)
+                       or else Bad_Spelling_Of (Tok_Exception)
+                       or else Bad_Spelling_Of (Tok_Exit)
+                       or else Bad_Spelling_Of (Tok_For)
+                       or else Bad_Spelling_Of (Tok_Goto)
+                       or else Bad_Spelling_Of (Tok_If)
+                       or else Bad_Spelling_Of (Tok_Loop)
+                       or else Bad_Spelling_Of (Tok_Or)
+                       or else Bad_Spelling_Of (Tok_Pragma)
+                       or else Bad_Spelling_Of (Tok_Raise)
+                       or else Bad_Spelling_Of (Tok_Requeue)
+                       or else Bad_Spelling_Of (Tok_Return)
+                       or else Bad_Spelling_Of (Tok_Select)
+                       or else Bad_Spelling_Of (Tok_When)
+                       or else Bad_Spelling_Of (Tok_While)
+                     then
+                        null;
+
+                     --  If not a bad spelling, then we really have junk
+
+                     else
+                        Scan; -- past identifier again
+
+                        --  If next token is first token on line, then we
+                        --  consider that we were missing a semicolon after
+                        --  the identifier, and process it as a procedure
+                        --  call with no parameters.
+
+                        if Token_Is_At_Start_Of_Line then
+                           Append_To (Statement_List,
+                             P_Statement_Name (Id_Node));
+                           T_Semicolon; -- to give error message
+                           Statement_Required := False;
+
+                        --  Otherwise we give a missing := message and
+                        --  simply abandon the junk that is there now.
+
+                        else
+                           T_Colon_Equal; -- give := expected message
+                           raise Error_Resync;
+                        end if;
+
+                     end if;
+                  end if;
+
+               --  Statement starting with operator symbol. This could be
+               --  a call, a name starting an assignment, or a qualified
+               --  expression.
+
+               when Tok_Operator_Symbol =>
+                  Check_Bad_Layout;
+                  Name_Node := P_Name;
+
+                  --  An attempt at a range attribute or a qualified expression
+                  --  must be illegal here (a code statement cannot possibly
+                  --  allow qualification by a function name).
+
+                  if Token = Tok_Apostrophe then
+                     Error_Msg_SC ("apostrophe illegal here");
+                     raise Error_Resync;
+                  end if;
+
+                  --  Scan possible assignment if we have a name
+
+                  if Expr_Form = EF_Name
+                    and then Token = Tok_Colon_Equal
+                  then
+                     Scan; -- past colon equal
+                     Append_To (Statement_List,
+                       P_Assignment_Statement (Name_Node));
+                  else
+                     Append_To (Statement_List,
+                       P_Statement_Name (Name_Node));
+                  end if;
+
+                  TF_Semicolon;
+                  Statement_Required := False;
+
+               --  Label starting with << which must precede real statement
+
+               when Tok_Less_Less =>
+                  Append_To (Statement_List, P_Label);
+                  Statement_Required := True;
+
+               --  Pragma appearing as a statement in a statement sequence
+
+               when Tok_Pragma =>
+                  Check_Bad_Layout;
+                  Append_To (Statement_List, P_Pragma);
+
+               --  Abort_Statement
+
+               when Tok_Abort =>
+                  Check_Bad_Layout;
+                  Append_To (Statement_List, P_Abort_Statement);
+                  Statement_Required := False;
+
+               --  Accept_Statement
+
+               when Tok_Accept =>
+                  Check_Bad_Layout;
+                  Append_To (Statement_List, P_Accept_Statement);
+                  Statement_Required := False;
+
+               --  Begin_Statement (Block_Statement with no declare, no label)
+
+               when Tok_Begin =>
+                  Check_Bad_Layout;
+                  Append_To (Statement_List, P_Begin_Statement);
+                  Statement_Required := False;
+
+               --  Case_Statement
+
+               when Tok_Case =>
+                  Check_Bad_Layout;
+                  Append_To (Statement_List, P_Case_Statement);
+                  Statement_Required := False;
+
+               --  Block_Statement with DECLARE and no label
+
+               when Tok_Declare =>
+                  Check_Bad_Layout;
+                  Append_To (Statement_List, P_Declare_Statement);
+                  Statement_Required := False;
+
+               --  Delay_Statement
+
+               when Tok_Delay =>
+                  Check_Bad_Layout;
+                  Append_To (Statement_List, P_Delay_Statement);
+                  Statement_Required := False;
+
+               --  Exit_Statement
+
+               when Tok_Exit =>
+                  Check_Bad_Layout;
+                  Append_To (Statement_List, P_Exit_Statement);
+                  Statement_Required := False;
+
+               --  Loop_Statement with FOR and no label
+
+               when Tok_For =>
+                  Check_Bad_Layout;
+                  Append_To (Statement_List, P_For_Statement);
+                  Statement_Required := False;
+
+               --  Goto_Statement
+
+               when Tok_Goto =>
+                  Check_Bad_Layout;
+                  Append_To (Statement_List, P_Goto_Statement);
+                  Statement_Required := False;
+
+               --  If_Statement
+
+               when Tok_If =>
+                  Check_Bad_Layout;
+                  Append_To (Statement_List, P_If_Statement);
+                  Statement_Required := False;
+
+               --  Loop_Statement
+
+               when Tok_Loop =>
+                  Check_Bad_Layout;
+                  Append_To (Statement_List, P_Loop_Statement);
+                  Statement_Required := False;
+
+               --  Null_Statement
+
+               when Tok_Null =>
+                  Check_Bad_Layout;
+                  Append_To (Statement_List, P_Null_Statement);
+                  Statement_Required := False;
+
+               --  Raise_Statement
+
+               when Tok_Raise =>
+                  Check_Bad_Layout;
+                  Append_To (Statement_List, P_Raise_Statement);
+                  Statement_Required := False;
+
+               --  Requeue_Statement
+
+               when Tok_Requeue =>
+                  Check_Bad_Layout;
+                  Append_To (Statement_List, P_Requeue_Statement);
+                  Statement_Required := False;
+
+               --  Return_Statement
+
+               when Tok_Return =>
+                  Check_Bad_Layout;
+                  Append_To (Statement_List, P_Return_Statement);
+                  Statement_Required := False;
+
+               --  Select_Statement
+
+               when Tok_Select =>
+                  Check_Bad_Layout;
+                  Append_To (Statement_List, P_Select_Statement);
+                  Statement_Required := False;
+
+               --  While_Statement (Block_Statement with while and no loop)
+
+               when Tok_While =>
+                  Check_Bad_Layout;
+                  Append_To (Statement_List, P_While_Statement);
+                  Statement_Required := False;
+
+               --  Anything else is some kind of junk, signal an error message
+               --  and then raise Error_Resync, to merge with the normal
+               --  handling of a bad statement.
+
+               when others =>
+
+                  if Token in Token_Class_Declk then
+                     Junk_Declaration;
+
+                  else
+                     Error_Msg_BC ("statement expected");
+                     raise Error_Resync;
+                  end if;
+            end case;
+
+         --  On error resynchronization, skip past next semicolon, and, since
+         --  we are still in the statement loop, look for next statement. We
+         --  set Statement_Required False to avoid an unnecessary error message
+         --  complaining that no statement was found (i.e. we consider the
+         --  junk to satisfy the requirement for a statement being present).
+
+         exception
+            when Error_Resync =>
+               Resync_Past_Semicolon_Or_To_Loop_Or_Then;
+               Statement_Required := False;
+         end;
+
+         exit when SS_Flags.Unco;
+
+      end loop;
+
+      return Statement_List;
+
+   end P_Sequence_Of_Statements;
+
+   --------------------
+   -- 5.1  Statement --
+   --------------------
+
+   --  Parsed by P_Sequence_Of_Statements (5.1), except for the case
+   --  of a statement of the form of a name, which is handled here. The
+   --  argument passed in is the tree for the name which has been scanned
+   --  The returned value is the corresponding statement form.
+
+   --  This routine is also used by Par.Prag for processing the procedure
+   --  call that appears as the second argument of a pragma Assert.
+
+   --  Error recovery: cannot raise Error_Resync
+
+   function P_Statement_Name (Name_Node : Node_Id) return Node_Id is
+      Stmt_Node : Node_Id;
+
+   begin
+      --  Case of Indexed component, which is a procedure call with arguments
+
+      if Nkind (Name_Node) = N_Indexed_Component then
+         declare
+            Prefix_Node : Node_Id := Prefix (Name_Node);
+            Exprs_Node  : List_Id := Expressions (Name_Node);
+         begin
+            Change_Node (Name_Node, N_Procedure_Call_Statement);
+            Set_Name (Name_Node, Prefix_Node);
+            Set_Parameter_Associations (Name_Node, Exprs_Node);
+            return Name_Node;
+         end;
+
+      --  Case of function call node, which is a really a procedure call
+
+      elsif Nkind (Name_Node) = N_Function_Call then
+         declare
+            Fname_Node  : Node_Id := Name (Name_Node);
+            Params_List : List_Id := Parameter_Associations (Name_Node);
+
+         begin
+            Change_Node (Name_Node, N_Procedure_Call_Statement);
+            Set_Name (Name_Node, Fname_Node);
+            Set_Parameter_Associations (Name_Node, Params_List);
+            return Name_Node;
+         end;
+
+      --  Case of call to attribute that denotes a procedure. Here we
+      --  just leave the attribute reference unchanged.
+
+      elsif Nkind (Name_Node) = N_Attribute_Reference
+        and then Is_Procedure_Attribute_Name (Attribute_Name (Name_Node))
+      then
+         return Name_Node;
+
+      --  All other cases of names are parameterless procedure calls
+
+      else
+         Stmt_Node :=
+           New_Node (N_Procedure_Call_Statement, Sloc (Name_Node));
+         Set_Name (Stmt_Node, Name_Node);
+         return Stmt_Node;
+      end if;
+
+   end P_Statement_Name;
+
+   ---------------------------
+   -- 5.1  Simple Statement --
+   ---------------------------
+
+   --  Parsed by P_Sequence_Of_Statements (5.1)
+
+   -----------------------------
+   -- 5.1  Compound Statement --
+   -----------------------------
+
+   --  Parsed by P_Sequence_Of_Statements (5.1)
+
+   -------------------------
+   -- 5.1  Null Statement --
+   -------------------------
+
+   --  NULL_STATEMENT ::= null;
+
+   --  The caller has already checked that the current token is null
+
+   --  Error recovery: cannot raise Error_Resync
+
+   function P_Null_Statement return Node_Id is
+      Null_Stmt_Node : Node_Id;
+
+   begin
+      Null_Stmt_Node := New_Node (N_Null_Statement, Token_Ptr);
+      Scan; -- past NULL
+      TF_Semicolon;
+      return Null_Stmt_Node;
+   end P_Null_Statement;
+
+   ----------------
+   -- 5.1  Label --
+   ----------------
+
+   --  LABEL ::= <<label_STATEMENT_IDENTIFIER>>
+
+   --  STATEMENT_INDENTIFIER ::= DIRECT_NAME
+
+   --  The IDENTIFIER of a STATEMENT_IDENTIFIER shall be an identifier
+   --  (not an OPERATOR_SYMBOL)
+
+   --  The caller has already checked that the current token is <<
+
+   --  Error recovery: can raise Error_Resync
+
+   function P_Label return Node_Id is
+      Label_Node : Node_Id;
+
+   begin
+      Label_Node := New_Node (N_Label, Token_Ptr);
+      Scan; -- past <<
+      Set_Identifier (Label_Node, P_Identifier);
+      T_Greater_Greater;
+      Append_Elmt (Label_Node, Label_List);
+      return Label_Node;
+   end P_Label;
+
+   -------------------------------
+   -- 5.1  Statement Identifier --
+   -------------------------------
+
+   --  Statement label is parsed by P_Label (5.1)
+
+   --  Loop label is parsed by P_Loop_Statement (5.5), P_For_Statement (5.5)
+   --   or P_While_Statement (5.5)
+
+   --  Block label is parsed by P_Begin_Statement (5.6) or
+   --   P_Declare_Statement (5.6)
+
+   -------------------------------
+   -- 5.2  Assignment Statement --
+   -------------------------------
+
+   --  ASSIGNMENT_STATEMENT ::=
+   --    variable_NAME := EXPRESSION;
+
+   --  Error recovery: can raise Error_Resync
+
+   function P_Assignment_Statement (LHS : Node_Id) return Node_Id is
+      Assign_Node : Node_Id;
+
+   begin
+      Assign_Node := New_Node (N_Assignment_Statement, Prev_Token_Ptr);
+      Set_Name (Assign_Node, LHS);
+      Set_Expression (Assign_Node, P_Expression_No_Right_Paren);
+      TF_Semicolon;
+      return Assign_Node;
+   end P_Assignment_Statement;
+
+   -----------------------
+   -- 5.3  If Statement --
+   -----------------------
+
+   --  IF_STATEMENT ::=
+   --    if CONDITION then
+   --      SEQUENCE_OF_STATEMENTS
+   --    {elsif CONDITION then
+   --      SEQUENCE_OF_STATEMENTS}
+   --    [else
+   --      SEQUENCE_OF_STATEMENTS]
+   --    end if;
+
+   --  The caller has checked that the initial token is IF (or in the error
+   --  case of a mysterious THEN, the initial token may simply be THEN, in
+   --  which case, no condition (or IF) was scanned).
+
+   --  Error recovery: can raise Error_Resync
+
+   function P_If_Statement return Node_Id is
+      If_Node    : Node_Id;
+      Elsif_Node : Node_Id;
+      Loc        : Source_Ptr;
+
+      procedure Add_Elsif_Part;
+      --  An internal procedure used to scan out a single ELSIF part. On entry
+      --  the ELSIF (or an ELSE which has been determined should be ELSIF) is
+      --  scanned out and is in Prev_Token.
+
+      procedure Check_If_Column;
+      --  An internal procedure used to check that THEN, ELSE ELSE, or ELSIF
+      --  appear in the right place if column checking is enabled (i.e. if
+      --  they are the first token on the line, then they must appear in
+      --  the same column as the opening IF).
+
+      procedure Check_Then_Column;
+      --  This procedure carries out the style checks for a THEN token
+      --  Note that the caller has set Loc to the Source_Ptr value for
+      --  the previous IF or ELSIF token. These checks apply only to a
+      --  THEN at the start of a line.
+
+      function Else_Should_Be_Elsif return Boolean;
+      --  An internal routine used to do a special error recovery check when
+      --  an ELSE is encountered. It determines if the ELSE should be treated
+      --  as an ELSIF. A positive decision (TRUE returned, is made if the ELSE
+      --  is followed by a sequence of tokens, starting on the same line as
+      --  the ELSE, which are not expression terminators, followed by a THEN.
+      --  On entry, the ELSE has been scanned out.
+
+      procedure Add_Elsif_Part is
+      begin
+         if No (Elsif_Parts (If_Node)) then
+            Set_Elsif_Parts (If_Node, New_List);
+         end if;
+
+         Elsif_Node := New_Node (N_Elsif_Part, Prev_Token_Ptr);
+         Loc := Prev_Token_Ptr;
+         Set_Condition (Elsif_Node, P_Condition);
+         Check_Then_Column;
+         Then_Scan;
+         Set_Then_Statements
+           (Elsif_Node, P_Sequence_Of_Statements (SS_Eftm_Eltm_Sreq));
+         Append (Elsif_Node, Elsif_Parts (If_Node));
+      end Add_Elsif_Part;
+
+      procedure Check_If_Column is
+      begin
+         if Style.RM_Column_Check and then Token_Is_At_Start_Of_Line
+           and then Start_Column /= Scope.Table (Scope.Last).Ecol
+         then
+            Error_Msg_Col := Scope.Table (Scope.Last).Ecol;
+            Error_Msg_SC ("(style) this token should be@");
+         end if;
+      end Check_If_Column;
+
+      procedure Check_Then_Column is
+      begin
+         if Token_Is_At_Start_Of_Line and then Token = Tok_Then then
+            Check_If_Column;
+            if Style_Check then Style.Check_Then (Loc); end if;
+         end if;
+      end Check_Then_Column;
+
+      function Else_Should_Be_Elsif return Boolean is
+         Scan_State : Saved_Scan_State;
+
+      begin
+         if Token_Is_At_Start_Of_Line then
+            return False;
+
+         else
+            Save_Scan_State (Scan_State);
+
+            loop
+               if Token in Token_Class_Eterm then
+                  Restore_Scan_State (Scan_State);
+                  return False;
+               else
+                  Scan; -- past non-expression terminating token
+
+                  if Token = Tok_Then then
+                     Restore_Scan_State (Scan_State);
+                     return True;
+                  end if;
+               end if;
+            end loop;
+         end if;
+      end Else_Should_Be_Elsif;
+
+   --  Start of processing for P_If_Statement
+
+   begin
+      If_Node := New_Node (N_If_Statement, Token_Ptr);
+
+      Push_Scope_Stack;
+      Scope.Table (Scope.Last).Etyp := E_If;
+      Scope.Table (Scope.Last).Ecol := Start_Column;
+      Scope.Table (Scope.Last).Sloc := Token_Ptr;
+      Scope.Table (Scope.Last).Labl := Error;
+      Scope.Table (Scope.Last).Node := If_Node;
+
+      if Token = Tok_If then
+         Loc := Token_Ptr;
+         Scan; -- past IF
+         Set_Condition (If_Node, P_Condition);
+
+         --  Deal with misuse of IF expression => used instead
+         --  of WHEN expression =>
+
+         if Token = Tok_Arrow then
+            Error_Msg_SC ("THEN expected");
+            Scan; -- past the arrow
+            Pop_Scope_Stack; -- remove unneeded entry
+            raise Error_Resync;
+         end if;
+
+         Check_Then_Column;
+
+      else
+         Error_Msg_SC ("no IF for this THEN");
+         Set_Condition (If_Node, Error);
+      end if;
+
+      Then_Scan;
+
+      Set_Then_Statements
+        (If_Node, P_Sequence_Of_Statements (SS_Eftm_Eltm_Sreq));
+
+      --  This loop scans out else and elsif parts
+
+      loop
+         if Token = Tok_Elsif then
+            Check_If_Column;
+
+            if Present (Else_Statements (If_Node)) then
+               Error_Msg_SP ("ELSIF cannot appear after ELSE");
+            end if;
+
+            Scan; -- past ELSIF
+            Add_Elsif_Part;
+
+         elsif Token = Tok_Else then
+            Check_If_Column;
+            Scan; -- past ELSE
+
+            if Else_Should_Be_Elsif then
+               Error_Msg_SP ("ELSE should be ELSIF");
+               Add_Elsif_Part;
+
+            else
+               --  Here we have an else that really is an else
+
+               if Present (Else_Statements (If_Node)) then
+                  Error_Msg_SP ("Only one ELSE part allowed");
+                  Append_List
+                    (P_Sequence_Of_Statements (SS_Eftm_Eltm_Sreq),
+                     Else_Statements (If_Node));
+               else
+                  Set_Else_Statements
+                    (If_Node, P_Sequence_Of_Statements (SS_Eftm_Eltm_Sreq));
+               end if;
+            end if;
+
+         --  If anything other than ELSE or ELSIF, exit the loop. The token
+         --  had better be END (and in fact it had better be END IF), but
+         --  we will let End_Statements take care of checking that.
+
+         else
+            exit;
+         end if;
+      end loop;
+
+      End_Statements;
+      return If_Node;
+
+   end P_If_Statement;
+
+   --------------------
+   -- 5.3  Condition --
+   --------------------
+
+   --  CONDITION ::= boolean_EXPRESSION
+
+   function P_Condition return Node_Id is
+      Cond : Node_Id;
+
+   begin
+      Cond := P_Expression_No_Right_Paren;
+
+      --  It is never possible for := to follow a condition, so if we get
+      --  a := we assume it is a mistyped equality. Note that we do not try
+      --  to reconstruct the tree correctly in this case, but we do at least
+      --  give an accurate error message.
+
+      while Token = Tok_Colon_Equal loop
+         Error_Msg_SC (""":="" should be ""=""");
+         Scan; -- past junk :=
+         Discard_Junk_Node (P_Expression_No_Right_Paren);
+      end loop;
+
+      return Cond;
+   end P_Condition;
+
+   -------------------------
+   -- 5.4  Case Statement --
+   -------------------------
+
+   --  CASE_STATEMENT ::=
+   --    case EXPRESSION is
+   --      CASE_STATEMENT_ALTERNATIVE
+   --      {CASE_STATEMENT_ALTERNATIVE}
+   --    end case;
+
+   --  The caller has checked that the first token is CASE
+
+   --  Can raise Error_Resync
+
+   function P_Case_Statement return Node_Id is
+      Case_Node         : Node_Id;
+      Alternatives_List : List_Id;
+      First_When_Loc    : Source_Ptr;
+
+   begin
+      Case_Node := New_Node (N_Case_Statement, Token_Ptr);
+
+      Push_Scope_Stack;
+      Scope.Table (Scope.Last).Etyp := E_Case;
+      Scope.Table (Scope.Last).Ecol := Start_Column;
+      Scope.Table (Scope.Last).Sloc := Token_Ptr;
+      Scope.Table (Scope.Last).Labl := Error;
+      Scope.Table (Scope.Last).Node := Case_Node;
+
+      Scan; -- past CASE
+      Set_Expression (Case_Node, P_Expression_No_Right_Paren);
+      TF_Is;
+
+      --  Prepare to parse case statement alternatives
+
+      Alternatives_List := New_List;
+      P_Pragmas_Opt (Alternatives_List);
+      First_When_Loc := Token_Ptr;
+
+      --  Loop through case statement alternatives
+
+      loop
+         --  If we have a WHEN or OTHERS, then that's fine keep going. Note
+         --  that it is a semantic check to ensure the proper use of OTHERS
+
+         if Token = Tok_When or else Token = Tok_Others then
+            Append (P_Case_Statement_Alternative, Alternatives_List);
+
+         --  If we have an END, then probably we are at the end of the case
+         --  but we only exit if Check_End thinks the END was reasonable.
+
+         elsif Token = Tok_End then
+            exit when Check_End;
+
+         --  Here if token is other than WHEN, OTHERS or END. We definitely
+         --  have an error, but the question is whether or not to get out of
+         --  the case statement. We don't want to get out early, or we will
+         --  get a slew of junk error messages for subsequent when tokens.
+
+         --  If the token is not at the start of the line, or if it is indented
+         --  with respect to the current case statement, then the best guess is
+         --  that we are still supposed to be inside the case statement. We
+         --  complain about the missing WHEN, and discard the junk statements.
+
+         elsif not Token_Is_At_Start_Of_Line
+           or else Start_Column > Scope.Table (Scope.Last).Ecol
+         then
+            Error_Msg_BC ("WHEN (case statement alternative) expected");
+
+            --  Here is a possibility for infinite looping if we don't make
+            --  progress. So try to process statements, otherwise exit
+
+            declare
+               Error_Ptr : constant Source_Ptr := Scan_Ptr;
+            begin
+               Discard_Junk_List (P_Sequence_Of_Statements (SS_Whtm));
+               exit when Scan_Ptr = Error_Ptr and then Check_End;
+            end;
+
+         --  Here we have a junk token at the start of the line and it is
+         --  not indented. If Check_End thinks there is a missing END, then
+         --  we will get out of the case, otherwise we keep going.
+
+         else
+            exit when Check_End;
+         end if;
+      end loop;
+
+      --  Make sure we have at least one alternative
+
+      if No (First_Non_Pragma (Alternatives_List)) then
+         Error_Msg
+            ("WHEN expected, must have at least one alternative in case",
+             First_When_Loc);
+         return Error;
+
+      else
+         Set_Alternatives (Case_Node, Alternatives_List);
+         return Case_Node;
+      end if;
+   end P_Case_Statement;
+
+   -------------------------------------
+   -- 5.4  Case Statement Alternative --
+   -------------------------------------
+
+   --  CASE_STATEMENT_ALTERNATIVE ::=
+   --    when DISCRETE_CHOICE_LIST =>
+   --      SEQUENCE_OF_STATEMENTS
+
+   --  The caller has checked that the initial token is WHEN or OTHERS
+   --  Error recovery: can raise Error_Resync
+
+   function P_Case_Statement_Alternative return Node_Id is
+      Case_Alt_Node : Node_Id;
+
+   begin
+      if Style_Check then Style.Check_Indentation; end if;
+      Case_Alt_Node := New_Node (N_Case_Statement_Alternative, Token_Ptr);
+      T_When; -- past WHEN (or give error in OTHERS case)
+      Set_Discrete_Choices (Case_Alt_Node, P_Discrete_Choice_List);
+      TF_Arrow;
+      Set_Statements (Case_Alt_Node, P_Sequence_Of_Statements (SS_Sreq_Whtm));
+      return Case_Alt_Node;
+   end P_Case_Statement_Alternative;
+
+   -------------------------
+   -- 5.5  Loop Statement --
+   -------------------------
+
+   --  LOOP_STATEMENT ::=
+   --    [LOOP_STATEMENT_IDENTIFIER:]
+   --      [ITERATION_SCHEME] loop
+   --        SEQUENCE_OF_STATEMENTS
+   --      end loop [loop_IDENTIFIER];
+
+   --  ITERATION_SCHEME ::=
+   --    while CONDITION
+   --  | for LOOP_PARAMETER_SPECIFICATION
+
+   --  The parsing of loop statements is handled by one of three functions
+   --  P_Loop_Statement, P_For_Statement or P_While_Statement depending
+   --  on the initial keyword in the construct (excluding the identifier)
+
+   --  P_Loop_Statement
+
+   --  This function parses the case where no iteration scheme is present
+
+   --  The caller has checked that the initial token is LOOP. The parameter
+   --  is the node identifiers for the loop label if any (or is set to Empty
+   --  if there is no loop label).
+
+   --  Error recovery : cannot raise Error_Resync
+
+   function P_Loop_Statement (Loop_Name : Node_Id := Empty) return Node_Id is
+      Loop_Node : Node_Id;
+
+   begin
+      Push_Scope_Stack;
+      Scope.Table (Scope.Last).Labl := Loop_Name;
+      Scope.Table (Scope.Last).Ecol := Start_Column;
+      Scope.Table (Scope.Last).Sloc := Token_Ptr;
+      Scope.Table (Scope.Last).Etyp := E_Loop;
+
+      Loop_Node := New_Node (N_Loop_Statement, Token_Ptr);
+      TF_Loop;
+
+      if No (Loop_Name) then
+         Set_Has_Created_Identifier (Loop_Node, True);
+         Set_Identifier (Loop_Node,
+           Make_Identifier (Sloc (Loop_Node), Set_Loop_Block_Name ('L')));
+      else
+         Set_Identifier (Loop_Node, Loop_Name);
+      end if;
+
+      Append_Elmt (Loop_Node, Label_List);
+
+      Set_Statements (Loop_Node, P_Sequence_Of_Statements (SS_Sreq));
+      End_Statements (Loop_Node);
+      return Loop_Node;
+   end P_Loop_Statement;
+
+   --  P_For_Statement
+
+   --  This function parses a loop statement with a FOR iteration scheme
+
+   --  The caller has checked that the initial token is FOR. The parameter
+   --  is the node identifier for the block label if any (or is set to Empty
+   --  if there is no block label).
+
+   --  Note: the caller fills in the Identifier field if a label was present
+
+   --  Error recovery: can raise Error_Resync
+
+   function P_For_Statement (Loop_Name : Node_Id := Empty) return Node_Id is
+      Loop_Node        : Node_Id;
+      Iter_Scheme_Node : Node_Id;
+      Loop_For_Flag    : Boolean;
+
+   begin
+      Push_Scope_Stack;
+      Scope.Table (Scope.Last).Labl := Loop_Name;
+      Scope.Table (Scope.Last).Ecol := Start_Column;
+      Scope.Table (Scope.Last).Sloc := Token_Ptr;
+      Scope.Table (Scope.Last).Etyp := E_Loop;
+
+      Loop_For_Flag := (Prev_Token = Tok_Loop);
+      Scan; -- past FOR
+      Iter_Scheme_Node := New_Node (N_Iteration_Scheme, Token_Ptr);
+      Set_Loop_Parameter_Specification
+         (Iter_Scheme_Node, P_Loop_Parameter_Specification);
+
+      --  The following is a special test so that a miswritten for loop such
+      --  as "loop for I in 1..10;" is handled nicely, without making an extra
+      --  entry in the scope stack. We don't bother to actually fix up the
+      --  tree in this case since it's not worth the effort. Instead we just
+      --  eat up the loop junk, leaving the entry for what now looks like an
+      --  unmodified loop intact.
+
+      if Loop_For_Flag and then Token = Tok_Semicolon then
+         Error_Msg_SC ("LOOP belongs here, not before FOR");
+         Pop_Scope_Stack;
+         return Error;
+
+      --  Normal case
+
+      else
+         Loop_Node := New_Node (N_Loop_Statement, Token_Ptr);
+         TF_Loop;
+         Set_Statements (Loop_Node, P_Sequence_Of_Statements (SS_Sreq));
+         End_Statements (Loop_Node);
+         Set_Iteration_Scheme (Loop_Node, Iter_Scheme_Node);
+
+         if No (Loop_Name) then
+            Set_Has_Created_Identifier (Loop_Node, True);
+            Set_Identifier (Loop_Node,
+              Make_Identifier (Sloc (Loop_Node), Set_Loop_Block_Name ('L')));
+         else
+            Set_Identifier (Loop_Node, Loop_Name);
+         end if;
+
+         Append_Elmt (Loop_Node, Label_List);
+
+         return Loop_Node;
+      end if;
+
+   end P_For_Statement;
+
+   --  P_While_Statement
+
+   --  This procedure scans a loop statement with a WHILE iteration scheme
+
+   --  The caller has checked that the initial token is WHILE. The parameter
+   --  is the node identifier for the block label if any (or is set to Empty
+   --  if there is no block label).
+
+   --  Error recovery: cannot raise Error_Resync
+
+   function P_While_Statement (Loop_Name : Node_Id := Empty) return Node_Id is
+      Loop_Node        : Node_Id;
+      Iter_Scheme_Node : Node_Id;
+      Loop_While_Flag  : Boolean;
+
+   begin
+      Push_Scope_Stack;
+      Scope.Table (Scope.Last).Labl := Loop_Name;
+      Scope.Table (Scope.Last).Ecol := Start_Column;
+      Scope.Table (Scope.Last).Sloc := Token_Ptr;
+      Scope.Table (Scope.Last).Etyp := E_Loop;
+
+      Loop_While_Flag := (Prev_Token = Tok_Loop);
+      Iter_Scheme_Node := New_Node (N_Iteration_Scheme, Token_Ptr);
+      Scan; -- past WHILE
+      Set_Condition (Iter_Scheme_Node, P_Condition);
+
+      --  The following is a special test so that a miswritten for loop such
+      --  as "loop while I > 10;" is handled nicely, without making an extra
+      --  entry in the scope stack. We don't bother to actually fix up the
+      --  tree in this case since it's not worth the effort. Instead we just
+      --  eat up the loop junk, leaving the entry for what now looks like an
+      --  unmodified loop intact.
+
+      if Loop_While_Flag and then Token = Tok_Semicolon then
+         Error_Msg_SC ("LOOP belongs here, not before WHILE");
+         Pop_Scope_Stack;
+         return Error;
+
+      --  Normal case
+
+      else
+         Loop_Node := New_Node (N_Loop_Statement, Token_Ptr);
+         TF_Loop;
+         Set_Statements (Loop_Node, P_Sequence_Of_Statements (SS_Sreq));
+         End_Statements (Loop_Node);
+         Set_Iteration_Scheme (Loop_Node, Iter_Scheme_Node);
+
+         if No (Loop_Name) then
+            Set_Has_Created_Identifier (Loop_Node, True);
+            Set_Identifier (Loop_Node,
+              Make_Identifier (Sloc (Loop_Node), Set_Loop_Block_Name ('L')));
+         else
+            Set_Identifier (Loop_Node, Loop_Name);
+         end if;
+
+         Append_Elmt (Loop_Node, Label_List);
+
+         return Loop_Node;
+      end if;
+
+   end P_While_Statement;
+
+   ---------------------------------------
+   -- 5.5  Loop Parameter Specification --
+   ---------------------------------------
+
+   --  LOOP_PARAMETER_SPECIFICATION ::=
+   --    DEFINING_IDENTIFIER in [reverse] DISCRETE_SUBTYPE_DEFINITION
+
+   --  Error recovery: cannot raise Error_Resync
+
+   function P_Loop_Parameter_Specification return Node_Id is
+      Loop_Param_Specification_Node : Node_Id;
+
+      ID_Node    : Node_Id;
+      Scan_State : Saved_Scan_State;
+
+   begin
+      Loop_Param_Specification_Node :=
+        New_Node (N_Loop_Parameter_Specification, Token_Ptr);
+
+      Save_Scan_State (Scan_State);
+      ID_Node := P_Defining_Identifier;
+      Set_Defining_Identifier (Loop_Param_Specification_Node, ID_Node);
+
+      if Token = Tok_Left_Paren then
+         Error_Msg_SC ("subscripted loop parameter not allowed");
+         Restore_Scan_State (Scan_State);
+         Discard_Junk_Node (P_Name);
+
+      elsif Token = Tok_Dot then
+         Error_Msg_SC ("selected loop parameter not allowed");
+         Restore_Scan_State (Scan_State);
+         Discard_Junk_Node (P_Name);
+      end if;
+
+      T_In;
+
+      if Token = Tok_Reverse then
+         Scan; -- past REVERSE
+         Set_Reverse_Present (Loop_Param_Specification_Node, True);
+      end if;
+
+      Set_Discrete_Subtype_Definition
+        (Loop_Param_Specification_Node, P_Discrete_Subtype_Definition);
+      return Loop_Param_Specification_Node;
+
+   exception
+      when Error_Resync =>
+         return Error;
+   end P_Loop_Parameter_Specification;
+
+   --------------------------
+   -- 5.6  Block Statement --
+   --------------------------
+
+   --  BLOCK_STATEMENT ::=
+   --    [block_STATEMENT_IDENTIFIER:]
+   --      [declare
+   --        DECLARATIVE_PART]
+   --      begin
+   --        HANDLED_SEQUENCE_OF_STATEMENTS
+   --      end [block_IDENTIFIER];
+
+   --  The parsing of block statements is handled by one of the two functions
+   --  P_Declare_Statement or P_Begin_Statement depending on whether or not
+   --  a declare section is present
+
+   --  P_Declare_Statement
+
+   --  This function parses a block statement with DECLARE present
+
+   --  The caller has checked that the initial token is DECLARE.
+
+   --  Error recovery: cannot raise Error_Resync
+
+   function P_Declare_Statement
+     (Block_Name : Node_Id := Empty)
+      return       Node_Id
+   is
+      Block_Node : Node_Id;
+
+   begin
+      Block_Node := New_Node (N_Block_Statement, Token_Ptr);
+
+      Push_Scope_Stack;
+      Scope.Table (Scope.Last).Etyp := E_Name;
+      Scope.Table (Scope.Last).Lreq := Present (Block_Name);
+      Scope.Table (Scope.Last).Ecol := Start_Column;
+      Scope.Table (Scope.Last).Labl := Block_Name;
+      Scope.Table (Scope.Last).Sloc := Token_Ptr;
+
+      Scan; -- past DECLARE
+
+      if No (Block_Name) then
+         Set_Has_Created_Identifier (Block_Node, True);
+         Set_Identifier (Block_Node,
+           Make_Identifier (Sloc (Block_Node), Set_Loop_Block_Name ('B')));
+      else
+         Set_Identifier (Block_Node, Block_Name);
+      end if;
+
+      Append_Elmt (Block_Node, Label_List);
+      Parse_Decls_Begin_End (Block_Node);
+      return Block_Node;
+   end P_Declare_Statement;
+
+   --  P_Begin_Statement
+
+   --  This function parses a block statement with no DECLARE present
+
+   --  The caller has checked that the initial token is BEGIN
+
+   --  Error recovery: cannot raise Error_Resync
+
+   function P_Begin_Statement
+     (Block_Name : Node_Id := Empty)
+      return       Node_Id
+   is
+      Block_Node : Node_Id;
+
+   begin
+      Block_Node := New_Node (N_Block_Statement, Token_Ptr);
+
+      Push_Scope_Stack;
+      Scope.Table (Scope.Last).Etyp := E_Name;
+      Scope.Table (Scope.Last).Lreq := Present (Block_Name);
+      Scope.Table (Scope.Last).Ecol := Start_Column;
+      Scope.Table (Scope.Last).Labl := Block_Name;
+      Scope.Table (Scope.Last).Sloc := Token_Ptr;
+
+      if No (Block_Name) then
+         Set_Has_Created_Identifier (Block_Node, True);
+         Set_Identifier (Block_Node,
+           Make_Identifier (Sloc (Block_Node), Set_Loop_Block_Name ('B')));
+      else
+         Set_Identifier (Block_Node, Block_Name);
+      end if;
+
+      Append_Elmt (Block_Node, Label_List);
+
+      Scope.Table (Scope.Last).Ecol := Start_Column;
+      Scope.Table (Scope.Last).Sloc := Token_Ptr;
+      Scan; -- past BEGIN
+      Set_Handled_Statement_Sequence
+        (Block_Node, P_Handled_Sequence_Of_Statements);
+      End_Statements (Handled_Statement_Sequence (Block_Node));
+      return Block_Node;
+   end P_Begin_Statement;
+
+   -------------------------
+   -- 5.7  Exit Statement --
+   -------------------------
+
+   --  EXIT_STATEMENT ::=
+   --    exit [loop_NAME] [when CONDITION];
+
+   --  The caller has checked that the initial token is EXIT
+
+   --  Error recovery: can raise Error_Resync
+
+   function P_Exit_Statement return Node_Id is
+      Exit_Node : Node_Id;
+
+      function Missing_Semicolon_On_Exit return Boolean;
+      --  This function deals with the following specialized situation
+      --
+      --    when 'x' =>
+      --       exit [identifier]
+      --    when 'y' =>
+      --
+      --  This looks like a messed up EXIT WHEN, when in fact the problem
+      --  is a missing semicolon. It is called with Token pointing to the
+      --  WHEN token, and returns True if a semicolon is missing before
+      --  the WHEN as in the above example.
+
+      function Missing_Semicolon_On_Exit return Boolean is
+         State : Saved_Scan_State;
+
+      begin
+         if not Token_Is_At_Start_Of_Line then
+            return False;
+
+         elsif Scope.Table (Scope.Last).Etyp /= E_Case then
+            return False;
+
+         else
+            Save_Scan_State (State);
+            Scan; -- past WHEN
+            Scan; -- past token after WHEN
+
+            if Token = Tok_Arrow then
+               Restore_Scan_State (State);
+               return True;
+            else
+               Restore_Scan_State (State);
+               return False;
+            end if;
+         end if;
+      end Missing_Semicolon_On_Exit;
+
+   --  Start of processing for P_Exit_Statement
+
+   begin
+      Exit_Node := New_Node (N_Exit_Statement, Token_Ptr);
+      Scan; -- past EXIT
+
+      if Token = Tok_Identifier then
+         Set_Name (Exit_Node, P_Qualified_Simple_Name);
+
+      elsif Style_Check then
+         --  This EXIT has no name, so check that
+         --  the innermost loop is unnamed too.
+
+         Check_No_Exit_Name :
+         for J in reverse 1 .. Scope.Last loop
+            if Scope.Table (J).Etyp = E_Loop then
+               if Present (Scope.Table (J).Labl) then
+
+                  --  Innermost loop in fact had a name, style check fails
+
+                  Style.No_Exit_Name (Scope.Table (J).Labl);
+               end if;
+
+               exit Check_No_Exit_Name;
+            end if;
+         end loop Check_No_Exit_Name;
+      end if;
+
+      if Token = Tok_When and then not Missing_Semicolon_On_Exit then
+         Scan; -- past WHEN
+         Set_Condition (Exit_Node, P_Condition);
+
+      --  Allow IF instead of WHEN, giving error message
+
+      elsif Token = Tok_If then
+         T_When;
+         Scan; -- past IF used in place of WHEN
+         Set_Condition (Exit_Node, P_Expression_No_Right_Paren);
+      end if;
+
+      TF_Semicolon;
+      return Exit_Node;
+   end P_Exit_Statement;
+
+   -------------------------
+   -- 5.8  Goto Statement --
+   -------------------------
+
+   --  GOTO_STATEMENT ::= goto label_NAME;
+
+   --  The caller has checked that the initial token is GOTO  (or TO in the
+   --  error case where GO and TO were incorrectly separated).
+
+   --  Error recovery: can raise Error_Resync
+
+   function P_Goto_Statement return Node_Id is
+      Goto_Node : Node_Id;
+
+   begin
+      Goto_Node := New_Node (N_Goto_Statement, Token_Ptr);
+      Scan; -- past GOTO (or TO)
+      Set_Name (Goto_Node, P_Qualified_Simple_Name_Resync);
+      No_Constraint;
+      TF_Semicolon;
+      return Goto_Node;
+   end P_Goto_Statement;
+
+   ---------------------------
+   -- Parse_Decls_Begin_End --
+   ---------------------------
+
+   --  This function parses the construct:
+
+   --      DECLARATIVE_PART
+   --    begin
+   --      HANDLED_SEQUENCE_OF_STATEMENTS
+   --    end [NAME];
+
+   --  The caller has built the scope stack entry, and created the node to
+   --  whose Declarations and Handled_Statement_Sequence fields are to be
+   --  set. On return these fields are filled in (except in the case of a
+   --  task body, where the handled statement sequence is optional, and may
+   --  thus be Empty), and the scan is positioned past the End sequence.
+
+   --  If the BEGIN is missing, then the parent node is used to help construct
+   --  an appropriate missing BEGIN message. Possibilities for the parent are:
+
+   --    N_Block_Statement     declare block
+   --    N_Entry_Body          entry body
+   --    N_Package_Body        package body (begin part optional)
+   --    N_Subprogram_Body     procedure or function body
+   --    N_Task_Body           task body
+
+   --  Note: in the case of a block statement, there is definitely a DECLARE
+   --  present (because a Begin statement without a DECLARE is handled by the
+   --  P_Begin_Statement procedure, which does not call Parse_Decls_Begin_End.
+
+   --  Error recovery: cannot raise Error_Resync
+
+   procedure Parse_Decls_Begin_End (Parent : Node_Id) is
+      Body_Decl    : Node_Id;
+      Body_Sloc    : Source_Ptr;
+      Decls        : List_Id;
+      Decl         : Node_Id;
+      Parent_Nkind : Node_Kind;
+      Spec_Node    : Node_Id;
+      HSS          : Node_Id;
+
+      procedure Missing_Begin (Msg : String);
+      --  Called to post a missing begin message. In the normal case this is
+      --  posted at the start of the current token. A special case arises when
+      --  P_Declarative_Items has previously found a missing begin, in which
+      --  case we replace the original error message.
+
+      procedure Set_Null_HSS (Parent : Node_Id);
+      --  Construct an empty handled statement sequence and install in Parent
+      --  Leaves HSS set to reference the newly constructed statement sequence.
+
+      -------------------
+      -- Missing_Begin --
+      -------------------
+
+      procedure Missing_Begin (Msg : String) is
+      begin
+         if Missing_Begin_Msg = No_Error_Msg then
+            Error_Msg_BC (Msg);
+         else
+            Change_Error_Text (Missing_Begin_Msg, Msg);
+
+            --  Purge any messages issued after than, since a missing begin
+            --  can cause a lot of havoc, and it is better not to dump these
+            --  cascaded messages on the user.
+
+            Purge_Messages (Get_Location (Missing_Begin_Msg), Prev_Token_Ptr);
+         end if;
+      end Missing_Begin;
+
+      ------------------
+      -- Set_Null_HSS --
+      ------------------
+
+      procedure Set_Null_HSS (Parent : Node_Id) is
+         Null_Stm : Node_Id;
+
+      begin
+         Null_Stm :=
+           Make_Null_Statement (Token_Ptr);
+         Set_Comes_From_Source (Null_Stm, False);
+
+         HSS :=
+           Make_Handled_Sequence_Of_Statements (Token_Ptr,
+             Statements => New_List (Null_Stm));
+         Set_Comes_From_Source (HSS, False);
+
+         Set_Handled_Statement_Sequence (Parent, HSS);
+      end Set_Null_HSS;
+
+   --  Start of processing for Parse_Decls_Begin_End
+
+   begin
+      Decls := P_Declarative_Part;
+
+      --  Check for misplacement of later vs basic declarations in Ada 83
+
+      if Ada_83 then
+         Decl := First (Decls);
+
+         --  Loop through sequence of basic declarative items
+
+         Outer : while Present (Decl) loop
+            if Nkind (Decl) /= N_Subprogram_Body
+              and then Nkind (Decl) /= N_Package_Body
+              and then Nkind (Decl) /= N_Task_Body
+              and then Nkind (Decl) not in  N_Body_Stub
+            then
+               Next (Decl);
+
+            --  Once a body is encountered, we only allow later declarative
+            --  items. The inner loop checks the rest of the list.
+
+            else
+               Body_Sloc := Sloc (Decl);
+
+               Inner : while Present (Decl) loop
+                  if Nkind (Decl) not in N_Later_Decl_Item
+                    and then Nkind (Decl) /= N_Pragma
+                  then
+                     if Ada_83 then
+                        Error_Msg_Sloc := Body_Sloc;
+                        Error_Msg_N
+                          ("(Ada 83) decl cannot appear after body#", Decl);
+                     end if;
+                  end if;
+
+                  Next (Decl);
+               end loop Inner;
+            end if;
+         end loop Outer;
+      end if;
+
+      --  Here is where we deal with the case of IS used instead of semicolon.
+      --  Specifically, if the last declaration in the declarative part is a
+      --  subprogram body still marked as having a bad IS, then this is where
+      --  we decide that the IS should really have been a semicolon and that
+      --  the body should have been a declaration. Note that if the bad IS
+      --  had turned out to be OK (i.e. a decent begin/end was found for it),
+      --  then the Bad_Is_Detected flag would have been reset by now.
+
+      Body_Decl := Last (Decls);
+
+      if Present (Body_Decl)
+        and then Nkind (Body_Decl) = N_Subprogram_Body
+        and then Bad_Is_Detected (Body_Decl)
+      then
+         --  OK, we have the case of a bad IS, so we need to fix up the tree.
+         --  What we have now is a subprogram body with attached declarations
+         --  and a possible statement sequence.
+
+         --  First step is to take the declarations that were part of the bogus
+         --  subprogram body and append them to the outer declaration chain.
+         --  In other words we append them past the body (which we will later
+         --  convert into a declaration).
+
+         Append_List (Declarations (Body_Decl), Decls);
+
+         --  Now take the handled statement sequence of the bogus body and
+         --  set it as the statement sequence for the outer construct. Note
+         --  that it may be empty (we specially allowed a missing BEGIN for
+         --  a subprogram body marked as having a bad IS -- see below).
+
+         Set_Handled_Statement_Sequence (Parent,
+           Handled_Statement_Sequence (Body_Decl));
+
+         --  Next step is to convert the old body node to a declaration node
+
+         Spec_Node := Specification (Body_Decl);
+         Change_Node (Body_Decl, N_Subprogram_Declaration);
+         Set_Specification (Body_Decl, Spec_Node);
+
+         --  Final step is to put the declarations for the parent where
+         --  they belong, and then fall through the IF to scan out the
+         --  END statements.
+
+         Set_Declarations (Parent, Decls);
+
+      --  This is the normal case (i.e. any case except the bad IS case)
+      --  If we have a BEGIN, then scan out the sequence of statements, and
+      --  also reset the expected column for the END to match the BEGIN.
+
+      else
+         Set_Declarations (Parent, Decls);
+
+         if Token = Tok_Begin then
+            if Style_Check then Style.Check_Indentation; end if;
+
+            Error_Msg_Col := Scope.Table (Scope.Last).Ecol;
+
+            if Style.RM_Column_Check
+              and then Token_Is_At_Start_Of_Line
+              and then Start_Column /= Error_Msg_Col
+            then
+               Error_Msg_SC ("(style) BEGIN in wrong column, should be@");
+
+            else
+               Scope.Table (Scope.Last).Ecol := Start_Column;
+            end if;
+
+            Scope.Table (Scope.Last).Sloc := Token_Ptr;
+            Scan; -- past BEGIN
+            Set_Handled_Statement_Sequence (Parent,
+              P_Handled_Sequence_Of_Statements);
+
+         --  No BEGIN present
+
+         else
+            Parent_Nkind := Nkind (Parent);
+
+            --  A special check for the missing IS case. If we have a
+            --  subprogram body that was marked as having a suspicious
+            --  IS, and the current token is END, then we simply confirm
+            --  the suspicion, and do not require a BEGIN to be present
+
+            if Parent_Nkind = N_Subprogram_Body
+              and then Token  = Tok_End
+              and then Scope.Table (Scope.Last).Etyp = E_Suspicious_Is
+            then
+               Scope.Table (Scope.Last).Etyp := E_Bad_Is;
+
+            --  Otherwise BEGIN is not required for a package body, so we
+            --  don't mind if it is missing, but we do construct a dummy
+            --  one (so that we have somewhere to set End_Label).
+
+            --  However if we have something other than a BEGIN which
+            --  looks like it might be statements, then we signal a missing
+            --  BEGIN for these cases as well. We define "something which
+            --  looks like it might be statements" as a token other than
+            --  END, EOF, or a token which starts declarations.
+
+            elsif Parent_Nkind = N_Package_Body
+              and then (Token = Tok_End
+                          or else Token = Tok_EOF
+                          or else Token in Token_Class_Declk)
+            then
+               Set_Null_HSS (Parent);
+
+            --  These are cases in which a BEGIN is required and not present
+
+            else
+               Set_Null_HSS (Parent);
+
+               --  Prepare to issue error message
+
+               Error_Msg_Sloc := Scope.Table (Scope.Last).Sloc;
+               Error_Msg_Node_1 := Scope.Table (Scope.Last).Labl;
+
+               --  Now issue appropriate message
+
+               if Parent_Nkind = N_Block_Statement then
+                  Missing_Begin ("missing BEGIN for DECLARE#!");
+
+               elsif Parent_Nkind = N_Entry_Body then
+                  Missing_Begin ("missing BEGIN for ENTRY#!");
+
+               elsif Parent_Nkind = N_Subprogram_Body then
+                  if Nkind (Specification (Parent))
+                               = N_Function_Specification
+                  then
+                     Missing_Begin ("missing BEGIN for function&#!");
+                  else
+                     Missing_Begin ("missing BEGIN for procedure&#!");
+                  end if;
+
+               --  The case for package body arises only when
+               --  we have possible statement junk present.
+
+               elsif Parent_Nkind = N_Package_Body then
+                  Missing_Begin ("missing BEGIN for package body&#!");
+
+               else
+                  pragma Assert (Parent_Nkind = N_Task_Body);
+                  Missing_Begin ("missing BEGIN for task body&#!");
+               end if;
+
+               --  Here we pick up the statements after the BEGIN that
+               --  should have been present but was not. We don't insist
+               --  on statements being present if P_Declarative_Part had
+               --  already found a missing BEGIN, since it might have
+               --  swallowed a lone statement into the declarative part.
+
+               if Missing_Begin_Msg /= No_Error_Msg
+                 and then Token = Tok_End
+               then
+                  null;
+               else
+                  Set_Handled_Statement_Sequence (Parent,
+                    P_Handled_Sequence_Of_Statements);
+               end if;
+            end if;
+         end if;
+      end if;
+
+      --  Here with declarations and handled statement sequence scanned
+
+      if Present (Handled_Statement_Sequence (Parent)) then
+         End_Statements (Handled_Statement_Sequence (Parent));
+      else
+         End_Statements;
+      end if;
+
+      --  We know that End_Statements removed an entry from the scope stack
+      --  (because it is required to do so under all circumstances). We can
+      --  therefore reference the entry it removed one past the stack top.
+      --  What we are interested in is whether it was a case of a bad IS.
+
+      if Scope.Table (Scope.Last + 1).Etyp = E_Bad_Is then
+         Error_Msg ("IS should be "";""", Scope.Table (Scope.Last + 1).S_Is);
+         Set_Bad_Is_Detected (Parent, True);
+      end if;
+
+   end Parse_Decls_Begin_End;
+
+   -------------------------
+   -- Set_Loop_Block_Name --
+   -------------------------
+
+   function Set_Loop_Block_Name (L : Character) return Name_Id is
+   begin
+      Name_Buffer (1) := L;
+      Name_Buffer (2) := '_';
+      Name_Len := 2;
+      Loop_Block_Count := Loop_Block_Count + 1;
+      Add_Nat_To_Name_Buffer (Loop_Block_Count);
+      return Name_Find;
+   end Set_Loop_Block_Name;
+
+   ---------------
+   -- Then_Scan --
+   ---------------
+
+   procedure Then_Scan is
+   begin
+      TF_Then;
+
+      while Token = Tok_Then loop
+         Error_Msg_SC ("redundant THEN");
+         TF_Then;
+      end loop;
+
+      if Token = Tok_And or else Token = Tok_Or then
+         Error_Msg_SC ("unexpected logical operator");
+         Scan;
+
+         if (Prev_Token = Tok_And and then Token = Tok_Then)
+              or else
+            (Prev_Token = Tok_Or  and then Token = Tok_Else)
+         then
+            Scan;
+         end if;
+
+         Discard_Junk_Node (P_Expression);
+      end if;
+
+      if Token = Tok_Then then
+         Scan;
+      end if;
+   end Then_Scan;
+
+end Ch5;
diff --git a/gcc/ada/par-ch6.adb b/gcc/ada/par-ch6.adb
new file mode 100644 (file)
index 0000000..d5d1d3d
--- /dev/null
@@ -0,0 +1,1165 @@
+------------------------------------------------------------------------------
+--                                                                          --
+--                         GNAT COMPILER COMPONENTS                         --
+--                                                                          --
+--                              P A R . C H 6                               --
+--                                                                          --
+--                                 B o d y                                  --
+--                                                                          --
+--                            $Revision: 1.81 $
+--                                                                          --
+--          Copyright (C) 1992-2001 Free Software Foundation, Inc.          --
+--                                                                          --
+-- GNAT is free software;  you can  redistribute it  and/or modify it under --
+-- terms of the  GNU General Public License as published  by the Free Soft- --
+-- ware  Foundation;  either version 2,  or (at your option) any later ver- --
+-- sion.  GNAT is distributed in the hope that it will be useful, but WITH- --
+-- OUT 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  distributed with GNAT;  see file COPYING.  If not, write --
+-- to  the Free Software Foundation,  59 Temple Place - Suite 330,  Boston, --
+-- MA 02111-1307, USA.                                                      --
+--                                                                          --
+-- GNAT was originally developed  by the GNAT team at  New York University. --
+-- It is now maintained by Ada Core Technologies Inc (http://www.gnat.com). --
+--                                                                          --
+------------------------------------------------------------------------------
+
+pragma Style_Checks (All_Checks);
+--  Turn off subprogram body ordering check. Subprograms are in order
+--  by RM section rather than alphabetical
+
+with Sinfo.CN; use Sinfo.CN;
+
+separate (Par)
+package body Ch6 is
+
+   --  Local subprograms, used only in this chapter
+
+   function P_Defining_Designator        return Node_Id;
+   function P_Defining_Operator_Symbol   return Node_Id;
+
+   procedure Check_Junk_Semicolon_Before_Return;
+   --  Check for common error of junk semicolon before RETURN keyword of
+   --  function specification. If present, skip over it with appropriate
+   --  error message, leaving Scan_Ptr pointing to the RETURN after. This
+   --  routine also deals with a possibly misspelled version of Return.
+
+   ----------------------------------------
+   -- Check_Junk_Semicolon_Before_Return --
+   ----------------------------------------
+
+   procedure Check_Junk_Semicolon_Before_Return is
+      Scan_State : Saved_Scan_State;
+
+   begin
+      if Token = Tok_Semicolon then
+         Save_Scan_State (Scan_State);
+         Scan; -- past the semicolon
+
+         if Token = Tok_Return then
+            Restore_Scan_State (Scan_State);
+            Error_Msg_SC ("Unexpected semicolon ignored");
+            Scan; -- rescan past junk semicolon
+
+         else
+            Restore_Scan_State (Scan_State);
+         end if;
+
+      elsif Bad_Spelling_Of (Tok_Return) then
+         null;
+      end if;
+   end Check_Junk_Semicolon_Before_Return;
+
+   -----------------------------------------------------
+   -- 6.1  Subprogram (Also 6.3, 8.5.4, 10.1.3, 12.3) --
+   -----------------------------------------------------
+
+   --  This routine scans out a subprogram declaration, subprogram body,
+   --  subprogram renaming declaration or subprogram generic instantiation.
+
+   --  SUBPROGRAM_DECLARATION ::= SUBPROGRAM_SPECIFICATION;
+
+   --  ABSTRACT_SUBPROGRAM_DECLARATION ::=
+   --    SUBPROGRAM_SPECIFICATION is abstract;
+
+   --  SUBPROGRAM_SPECIFICATION ::=
+   --      procedure DEFINING_PROGRAM_UNIT_NAME PARAMETER_PROFILE
+   --    | function DEFINING_DESIGNATOR PARAMETER_AND_RESULT_PROFILE
+
+   --  PARAMETER_PROFILE ::= [FORMAL_PART]
+
+   --  PARAMETER_AND_RESULT_PROFILE ::= [FORMAL_PART] return SUBTYPE_MARK
+
+   --  SUBPROGRAM_BODY ::=
+   --    SUBPROGRAM_SPECIFICATION is
+   --      DECLARATIVE_PART
+   --    begin
+   --      HANDLED_SEQUENCE_OF_STATEMENTS
+   --    end [DESIGNATOR];
+
+   --  SUBPROGRAM_RENAMING_DECLARATION ::=
+   --    SUBPROGRAM_SPECIFICATION renames callable_entity_NAME;
+
+   --  SUBPROGRAM_BODY_STUB ::=
+   --    SUBPROGRAM_SPECIFICATION is separate;
+
+   --  GENERIC_INSTANTIATION ::=
+   --    procedure DEFINING_PROGRAM_UNIT_NAME is
+   --      new generic_procedure_NAME [GENERIC_ACTUAL_PART];
+   --  | function DEFINING_DESIGNATOR is
+   --      new generic_function_NAME [GENERIC_ACTUAL_PART];
+
+   --  The value in Pf_Flags indicates which of these possible declarations
+   --  is acceptable to the caller:
+
+   --    Pf_Flags.Decl                 Set if declaration OK
+   --    Pf_Flags.Gins                 Set if generic instantiation OK
+   --    Pf_Flags.Pbod                 Set if proper body OK
+   --    Pf_Flags.Rnam                 Set if renaming declaration OK
+   --    Pf_Flags.Stub                 Set if body stub OK
+
+   --  If an inappropriate form is encountered, it is scanned out but an
+   --  error message indicating that it is appearing in an inappropriate
+   --  context is issued. The only possible values for Pf_Flags are those
+   --  defined as constants in the Par package.
+
+   --  The caller has checked that the initial token is FUNCTION or PROCEDURE
+
+   --  Error recovery: cannot raise Error_Resync
+
+   function P_Subprogram (Pf_Flags : Pf_Rec) return Node_Id is
+      Specification_Node : Node_Id;
+      Name_Node   : Node_Id;
+      Fpart_List  : List_Id;
+      Fpart_Sloc  : Source_Ptr;
+      Return_Node : Node_Id;
+      Inst_Node   : Node_Id;
+      Body_Node   : Node_Id;
+      Decl_Node   : Node_Id;
+      Rename_Node : Node_Id;
+      Absdec_Node : Node_Id;
+      Stub_Node   : Node_Id;
+      Fproc_Sloc  : Source_Ptr;
+      Func        : Boolean;
+      Scan_State  : Saved_Scan_State;
+
+   begin
+      --  Set up scope stack entry. Note that the Labl field will be set later
+
+      SIS_Entry_Active := False;
+      SIS_Missing_Semicolon_Message := No_Error_Msg;
+      Push_Scope_Stack;
+      Scope.Table (Scope.Last).Sloc := Token_Ptr;
+      Scope.Table (Scope.Last).Etyp := E_Name;
+      Scope.Table (Scope.Last).Ecol := Start_Column;
+      Scope.Table (Scope.Last).Lreq := False;
+
+      Func := (Token = Tok_Function);
+      Fproc_Sloc := Token_Ptr;
+      Scan; -- past FUNCTION or PROCEDURE
+      Ignore (Tok_Type);
+      Ignore (Tok_Body);
+
+      if Func then
+         Name_Node := P_Defining_Designator;
+
+         if Nkind (Name_Node) = N_Defining_Operator_Symbol
+           and then Scope.Last = 1
+         then
+            Error_Msg_SP ("operator symbol not allowed at library level");
+            Name_Node := New_Entity (N_Defining_Identifier, Sloc (Name_Node));
+
+            --  Set name from file name, we need some junk name, and that's
+            --  as good as anything. This is only approximate, since we do
+            --  not do anything with non-standard name translations.
+
+            Get_Name_String (File_Name (Current_Source_File));
+
+            for J in 1 .. Name_Len loop
+               if Name_Buffer (J) = '.' then
+                  Name_Len := J - 1;
+                  exit;
+               end if;
+            end loop;
+
+            Set_Chars (Name_Node, Name_Find);
+            Set_Error_Posted (Name_Node);
+         end if;
+
+      else
+         Name_Node := P_Defining_Program_Unit_Name;
+      end if;
+
+      Scope.Table (Scope.Last).Labl := Name_Node;
+
+      if Token = Tok_Colon then
+         Error_Msg_SC ("redundant colon ignored");
+         Scan; -- past colon
+      end if;
+
+      --  Deal with generic instantiation, the one case in which we do not
+      --  have a subprogram specification as part of whatever we are parsing
+
+      if Token = Tok_Is then
+         Save_Scan_State (Scan_State); -- at the IS
+         T_Is; -- checks for redundant IS's
+
+         if Token = Tok_New then
+            if not Pf_Flags.Gins then
+               Error_Msg_SC ("generic instantation not allowed here!");
+            end if;
+
+            Scan; -- past NEW
+
+            if Func then
+               Inst_Node := New_Node (N_Function_Instantiation, Fproc_Sloc);
+               Set_Name (Inst_Node, P_Function_Name);
+            else
+               Inst_Node := New_Node (N_Procedure_Instantiation, Fproc_Sloc);
+               Set_Name (Inst_Node, P_Qualified_Simple_Name);
+            end if;
+
+            Set_Defining_Unit_Name (Inst_Node, Name_Node);
+            Set_Generic_Associations (Inst_Node, P_Generic_Actual_Part_Opt);
+            TF_Semicolon;
+            Pop_Scope_Stack; -- Don't need scope stack entry in this case
+            return Inst_Node;
+
+         else
+            Restore_Scan_State (Scan_State); -- to the IS
+         end if;
+      end if;
+
+      --  If not a generic instantiation, then we definitely have a subprogram
+      --  specification (all possibilities at this stage include one here)
+
+      Fpart_Sloc := Token_Ptr;
+
+      Check_Misspelling_Of (Tok_Return);
+
+      --  Scan formal part. First a special error check. If we have an
+      --  identifier here, then we have a definite error. If this identifier
+      --  is on the same line as the designator, then we assume it is the
+      --  first formal after a missing left parenthesis
+
+      if Token = Tok_Identifier
+        and then not Token_Is_At_Start_Of_Line
+      then
+            T_Left_Paren; -- to generate message
+            Fpart_List := P_Formal_Part;
+
+      --  Otherwise scan out an optional formal part in the usual manner
+
+      else
+         Fpart_List := P_Parameter_Profile;
+      end if;
+
+      --  We treat what we have as a function specification if FUNCTION was
+      --  used, or if a RETURN is present. This gives better error recovery
+      --  since later RETURN statements will be valid in either case.
+
+      Check_Junk_Semicolon_Before_Return;
+      Return_Node := Error;
+
+      if Token = Tok_Return then
+         if not Func then
+            Error_Msg ("PROCEDURE should be FUNCTION", Fproc_Sloc);
+            Func := True;
+         end if;
+
+         Scan; -- past RETURN
+         Return_Node := P_Subtype_Mark;
+         No_Constraint;
+
+      else
+         if Func then
+            Ignore (Tok_Right_Paren);
+            TF_Return;
+         end if;
+      end if;
+
+      if Func then
+         Specification_Node :=
+           New_Node (N_Function_Specification, Fproc_Sloc);
+         Set_Subtype_Mark (Specification_Node, Return_Node);
+
+      else
+         Specification_Node :=
+           New_Node (N_Procedure_Specification, Fproc_Sloc);
+      end if;
+
+      Set_Defining_Unit_Name (Specification_Node, Name_Node);
+      Set_Parameter_Specifications (Specification_Node, Fpart_List);
+
+      --  Error check: barriers not allowed on protected functions/procedures
+
+      if Token = Tok_When then
+         if Func then
+            Error_Msg_SC ("barrier not allowed on function, only on entry");
+         else
+            Error_Msg_SC ("barrier not allowed on procedure, only on entry");
+         end if;
+
+         Scan; -- past WHEN
+         Discard_Junk_Node (P_Expression);
+      end if;
+
+      --  Deal with case of semicolon ending a subprogram declaration
+
+      if Token = Tok_Semicolon then
+         if not Pf_Flags.Decl then
+            T_Is;
+         end if;
+
+         Scan; -- past semicolon
+
+         --  If semicolon is immediately followed by IS, then ignore the
+         --  semicolon, and go process the body.
+
+         if Token = Tok_Is then
+            Error_Msg_SP ("unexpected semicolon ignored");
+            T_Is; -- ignroe redundant IS's
+            goto Subprogram_Body;
+
+         --  If BEGIN follows in an appropriate column, we immediately
+         --  commence the error action of assuming that the previous
+         --  subprogram declaration should have been a subprogram body,
+         --  i.e. that the terminating semicolon should have been IS.
+
+         elsif Token = Tok_Begin
+            and then Start_Column >= Scope.Table (Scope.Last).Ecol
+         then
+            Error_Msg_SP (""";"" should be IS!");
+            goto Subprogram_Body;
+
+         else
+            goto Subprogram_Declaration;
+         end if;
+
+      --  Case of not followed by semicolon
+
+      else
+         --  Subprogram renaming declaration case
+
+         Check_Misspelling_Of (Tok_Renames);
+
+         if Token = Tok_Renames then
+            if not Pf_Flags.Rnam then
+               Error_Msg_SC ("renaming declaration not allowed here!");
+            end if;
+
+            Rename_Node :=
+              New_Node (N_Subprogram_Renaming_Declaration, Token_Ptr);
+            Scan; -- past RENAMES
+            Set_Name (Rename_Node, P_Name);
+            Set_Specification (Rename_Node, Specification_Node);
+            TF_Semicolon;
+            Pop_Scope_Stack;
+            return Rename_Node;
+
+         --  Case of IS following subprogram specification
+
+         elsif Token = Tok_Is then
+            T_Is; -- ignore redundant Is's
+
+            if Token_Name = Name_Abstract then
+               Check_95_Keyword (Tok_Abstract, Tok_Semicolon);
+            end if;
+
+            --  Deal nicely with (now obsolete) use of <> in place of abstract
+
+            if Token = Tok_Box then
+               Error_Msg_SC ("ABSTRACT expected");
+               Token := Tok_Abstract;
+            end if;
+
+            --  Abstract subprogram declaration case
+
+            if Token = Tok_Abstract then
+               Absdec_Node :=
+                 New_Node (N_Abstract_Subprogram_Declaration, Token_Ptr);
+               Set_Specification (Absdec_Node, Specification_Node);
+               Pop_Scope_Stack; -- discard unneeded entry
+               Scan; -- past ABSTRACT
+               TF_Semicolon;
+               return Absdec_Node;
+
+            --  Check for IS NEW with Formal_Part present and handle nicely
+
+            elsif Token = Tok_New then
+               Error_Msg
+                 ("formal part not allowed in instantiation", Fpart_Sloc);
+               Scan; -- past NEW
+
+               if Func then
+                  Inst_Node := New_Node (N_Function_Instantiation, Fproc_Sloc);
+               else
+                  Inst_Node :=
+                    New_Node (N_Procedure_Instantiation, Fproc_Sloc);
+               end if;
+
+               Set_Defining_Unit_Name (Inst_Node, Name_Node);
+               Set_Name (Inst_Node, P_Name);
+               Set_Generic_Associations (Inst_Node, P_Generic_Actual_Part_Opt);
+               TF_Semicolon;
+               Pop_Scope_Stack; -- Don't need scope stack entry in this case
+               return Inst_Node;
+
+            else
+               goto Subprogram_Body;
+            end if;
+
+         --  Here we have a missing IS or missing semicolon, we always guess
+         --  a missing semicolon, since we are pretty good at fixing up a
+         --  semicolon which should really be an IS
+
+         else
+            Error_Msg_AP ("missing "";""");
+            SIS_Missing_Semicolon_Message := Get_Msg_Id;
+            goto Subprogram_Declaration;
+         end if;
+      end if;
+
+      --  Processing for subprogram body
+
+      <<Subprogram_Body>>
+         if not Pf_Flags.Pbod then
+            Error_Msg_SP ("subprogram body not allowed here!");
+         end if;
+
+         --  Subprogram body stub case
+
+         if Separate_Present then
+            if not Pf_Flags.Stub then
+               Error_Msg_SC ("body stub not allowed here!");
+            end if;
+
+            if Nkind (Name_Node) = N_Defining_Operator_Symbol then
+               Error_Msg
+                 ("operator symbol cannot be used as subunit name",
+                  Sloc (Name_Node));
+            end if;
+
+            Stub_Node :=
+              New_Node (N_Subprogram_Body_Stub, Sloc (Specification_Node));
+            Set_Specification (Stub_Node, Specification_Node);
+            Scan; -- past SEPARATE
+            Pop_Scope_Stack;
+            TF_Semicolon;
+            return Stub_Node;
+
+         --  Subprogram body case
+
+         else
+            --  Here is the test for a suspicious IS (i.e. one that looks
+            --  like it might more properly be a semicolon). See separate
+            --  section discussing use of IS instead of semicolon in
+            --  package Parse.
+
+            if (Token in Token_Class_Declk
+                  or else
+                Token = Tok_Identifier)
+              and then Start_Column <= Scope.Table (Scope.Last).Ecol
+              and then Scope.Last /= 1
+            then
+               Scope.Table (Scope.Last).Etyp := E_Suspicious_Is;
+               Scope.Table (Scope.Last).S_Is := Prev_Token_Ptr;
+            end if;
+
+            Body_Node :=
+              New_Node (N_Subprogram_Body, Sloc (Specification_Node));
+            Set_Specification (Body_Node, Specification_Node);
+            Parse_Decls_Begin_End (Body_Node);
+            return Body_Node;
+         end if;
+
+      --  Processing for subprogram declaration
+
+      <<Subprogram_Declaration>>
+         Decl_Node :=
+           New_Node (N_Subprogram_Declaration, Sloc (Specification_Node));
+         Set_Specification (Decl_Node, Specification_Node);
+
+         --  If this is a context in which a subprogram body is permitted,
+         --  set active SIS entry in case (see section titled "Handling
+         --  Semicolon Used in Place of IS" in body of Parser package)
+         --  Note that SIS_Missing_Semicolon_Message is already set properly.
+
+         if Pf_Flags.Pbod then
+            SIS_Labl := Scope.Table (Scope.Last).Labl;
+            SIS_Sloc := Scope.Table (Scope.Last).Sloc;
+            SIS_Ecol := Scope.Table (Scope.Last).Ecol;
+            SIS_Declaration_Node := Decl_Node;
+            SIS_Semicolon_Sloc := Prev_Token_Ptr;
+            SIS_Entry_Active := True;
+         end if;
+
+         Pop_Scope_Stack;
+         return Decl_Node;
+
+   end P_Subprogram;
+
+   ---------------------------------
+   -- 6.1  Subprogram Declaration --
+   ---------------------------------
+
+   --  Parsed by P_Subprogram (6.1)
+
+   ------------------------------------------
+   -- 6.1  Abstract Subprogram Declaration --
+   ------------------------------------------
+
+   --  Parsed by P_Subprogram (6.1)
+
+   -----------------------------------
+   -- 6.1  Subprogram Specification --
+   -----------------------------------
+
+   --  SUBPROGRAM_SPECIFICATION ::=
+   --      procedure DEFINING_PROGRAM_UNIT_NAME PARAMETER_PROFILE
+   --    | function DEFINING_DESIGNATOR PARAMETER_AND_RESULT_PROFILE
+
+   --  PARAMETER_PROFILE ::= [FORMAL_PART]
+
+   --  PARAMETER_AND_RESULT_PROFILE ::= [FORMAL_PART] return SUBTYPE_MARK
+
+   --  Subprogram specifications that appear in subprogram declarations
+   --  are parsed by P_Subprogram (6.1). This routine is used in other
+   --  contexts where subprogram specifications occur.
+
+   --  Note: this routine does not affect the scope stack in any way
+
+   --  Error recovery: can raise Error_Resync
+
+   function P_Subprogram_Specification return Node_Id is
+      Specification_Node : Node_Id;
+
+   begin
+      if Token = Tok_Function then
+         Specification_Node := New_Node (N_Function_Specification, Token_Ptr);
+         Scan; -- past FUNCTION
+         Ignore (Tok_Body);
+         Set_Defining_Unit_Name (Specification_Node, P_Defining_Designator);
+         Set_Parameter_Specifications
+           (Specification_Node, P_Parameter_Profile);
+         Check_Junk_Semicolon_Before_Return;
+         TF_Return;
+         Set_Subtype_Mark (Specification_Node, P_Subtype_Mark);
+         No_Constraint;
+         return Specification_Node;
+
+      elsif Token = Tok_Procedure then
+         Specification_Node := New_Node (N_Procedure_Specification, Token_Ptr);
+         Scan; -- past PROCEDURE
+         Ignore (Tok_Body);
+         Set_Defining_Unit_Name
+           (Specification_Node, P_Defining_Program_Unit_Name);
+         Set_Parameter_Specifications
+           (Specification_Node, P_Parameter_Profile);
+         return Specification_Node;
+
+      else
+         Error_Msg_SC ("subprogram specification expected");
+         raise Error_Resync;
+      end if;
+   end P_Subprogram_Specification;
+
+   ---------------------
+   -- 6.1  Designator --
+   ---------------------
+
+   --  DESIGNATOR ::=
+   --    [PARENT_UNIT_NAME .] IDENTIFIER | OPERATOR_SYMBOL
+
+   --  The caller has checked that the initial token is an identifier,
+   --  operator symbol, or string literal. Note that we don't bother to
+   --  do much error diagnosis in this routine, since it is only used for
+   --  the label on END lines, and the routines in package Par.Endh will
+   --  check that the label is appropriate.
+
+   --  Error recovery: cannot raise Error_Resync
+
+   function P_Designator return Node_Id is
+      Ident_Node  : Node_Id;
+      Name_Node   : Node_Id;
+      Prefix_Node : Node_Id;
+
+      function Real_Dot return Boolean;
+      --  Tests if a current token is an interesting period, i.e. is followed
+      --  by an identifier or operator symbol or string literal. If not, it is
+      --  probably just incorrect punctuation to be caught by our caller. Note
+      --  that the case of an operator symbol or string literal is also an
+      --  error, but that is an error that we catch here. If the result is
+      --  True, a real dot has been scanned and we are positioned past it,
+      --  if the result is False, the scan position is unchanged.
+
+      function Real_Dot return Boolean is
+         Scan_State  : Saved_Scan_State;
+
+      begin
+         if Token /= Tok_Dot then
+            return False;
+
+         else
+            Save_Scan_State (Scan_State);
+            Scan; -- past dot
+
+            if Token = Tok_Identifier
+              or else Token = Tok_Operator_Symbol
+              or else Token = Tok_String_Literal
+            then
+               return True;
+
+            else
+               Restore_Scan_State (Scan_State);
+               return False;
+            end if;
+         end if;
+      end Real_Dot;
+
+   --  Start of processing for P_Designator
+
+   begin
+      Ident_Node := Token_Node;
+      Scan; -- past initial token
+
+      if Prev_Token = Tok_Operator_Symbol
+        or else Prev_Token = Tok_String_Literal
+        or else not Real_Dot
+      then
+         return Ident_Node;
+
+      --  Child name case
+
+      else
+         Prefix_Node := Ident_Node;
+
+         --  Loop through child names, on entry to this loop, Prefix contains
+         --  the name scanned so far, and Ident_Node is the last identifier.
+
+         loop
+            Name_Node := New_Node (N_Selected_Component, Prev_Token_Ptr);
+            Set_Prefix (Name_Node, Prefix_Node);
+            Ident_Node := P_Identifier;
+            Set_Selector_Name (Name_Node, Ident_Node);
+            Prefix_Node := Name_Node;
+            exit when not Real_Dot;
+         end loop;
+
+         --  On exit from the loop, Ident_Node is the last identifier scanned,
+         --  i.e. the defining identifier, and Prefix_Node is a node for the
+         --  entire name, structured (incorrectly!) as a selected component.
+
+         Name_Node := Prefix (Prefix_Node);
+         Change_Node (Prefix_Node, N_Designator);
+         Set_Name (Prefix_Node, Name_Node);
+         Set_Identifier (Prefix_Node, Ident_Node);
+         return Prefix_Node;
+      end if;
+
+   exception
+      when Error_Resync =>
+         while Token = Tok_Dot or else Token = Tok_Identifier loop
+            Scan;
+         end loop;
+
+         return Error;
+   end P_Designator;
+
+   ------------------------------
+   -- 6.1  Defining Designator --
+   ------------------------------
+
+   --  DEFINING_DESIGNATOR ::=
+   --    DEFINING_PROGRAM_UNIT_NAME | DEFINING_OPERATOR_SYMBOL
+
+   --  Error recovery: cannot raise Error_Resync
+
+   function P_Defining_Designator return Node_Id is
+   begin
+      if Token = Tok_Operator_Symbol then
+         return P_Defining_Operator_Symbol;
+
+      elsif Token = Tok_String_Literal then
+         Error_Msg_SC ("invalid operator name");
+         Scan; -- past junk string
+         return Error;
+
+      else
+         return P_Defining_Program_Unit_Name;
+      end if;
+   end P_Defining_Designator;
+
+   -------------------------------------
+   -- 6.1  Defining Program Unit Name --
+   -------------------------------------
+
+   --  DEFINING_PROGRAM_UNIT_NAME ::=
+   --    [PARENT_UNIT_NAME .] DEFINING_IDENTIFIER
+
+   --  Note: PARENT_UNIT_NAME may be present only in 95 mode at the outer level
+
+   --  Error recovery: cannot raise Error_Resync
+
+   function P_Defining_Program_Unit_Name return Node_Id is
+      Ident_Node  : Node_Id;
+      Name_Node   : Node_Id;
+      Prefix_Node : Node_Id;
+
+   begin
+      --  Set identifier casing if not already set and scan initial identifier
+
+      if Token = Tok_Identifier
+        and then Identifier_Casing (Current_Source_File) = Unknown
+      then
+         Set_Identifier_Casing (Current_Source_File, Determine_Token_Casing);
+      end if;
+
+      Ident_Node := P_Identifier;
+      Merge_Identifier (Ident_Node, Tok_Return);
+
+      --  Normal case (not child library unit name)
+
+      if Token /= Tok_Dot then
+         Change_Identifier_To_Defining_Identifier (Ident_Node);
+         return Ident_Node;
+
+      --  Child library unit name case
+
+      else
+         if Scope.Last > 1 then
+            Error_Msg_SP ("child unit allowed only at library level");
+            raise Error_Resync;
+
+         elsif Ada_83 then
+            Error_Msg_SP ("(Ada 83) child unit not allowed!");
+
+         end if;
+
+         Prefix_Node := Ident_Node;
+
+         --  Loop through child names, on entry to this loop, Prefix contains
+         --  the name scanned so far, and Ident_Node is the last identifier.
+
+         loop
+            exit when Token /= Tok_Dot;
+            Name_Node := New_Node (N_Selected_Component, Token_Ptr);
+            Scan; -- past period
+            Set_Prefix (Name_Node, Prefix_Node);
+            Ident_Node := P_Identifier;
+            Set_Selector_Name (Name_Node, Ident_Node);
+            Prefix_Node := Name_Node;
+         end loop;
+
+         --  On exit from the loop, Ident_Node is the last identifier scanned,
+         --  i.e. the defining identifier, and Prefix_Node is a node for the
+         --  entire name, structured (incorrectly!) as a selected component.
+
+         Name_Node := Prefix (Prefix_Node);
+         Change_Node (Prefix_Node, N_Defining_Program_Unit_Name);
+         Set_Name (Prefix_Node, Name_Node);
+         Change_Identifier_To_Defining_Identifier (Ident_Node);
+         Set_Defining_Identifier (Prefix_Node, Ident_Node);
+
+         --  All set with unit name parsed
+
+         return Prefix_Node;
+      end if;
+
+   exception
+      when Error_Resync =>
+         while Token = Tok_Dot or else Token = Tok_Identifier loop
+            Scan;
+         end loop;
+
+         return Error;
+   end P_Defining_Program_Unit_Name;
+
+   --------------------------
+   -- 6.1  Operator Symbol --
+   --------------------------
+
+   --  OPERATOR_SYMBOL ::= STRING_LITERAL
+
+   --  Operator symbol is returned by the scanner as Tok_Operator_Symbol
+
+   -----------------------------------
+   -- 6.1  Defining Operator Symbol --
+   -----------------------------------
+
+   --  DEFINING_OPERATOR_SYMBOL ::= OPERATOR_SYMBOL
+
+   --  The caller has checked that the initial symbol is an operator symbol
+
+   function P_Defining_Operator_Symbol return Node_Id is
+      Op_Node : Node_Id;
+
+   begin
+      Op_Node := Token_Node;
+      Change_Operator_Symbol_To_Defining_Operator_Symbol (Op_Node);
+      Scan; -- past operator symbol
+      return Op_Node;
+   end P_Defining_Operator_Symbol;
+
+   ----------------------------
+   -- 6.1  Parameter_Profile --
+   ----------------------------
+
+   --  PARAMETER_PROFILE ::= [FORMAL_PART]
+
+   --  Empty is returned if no formal part is present
+
+   --  Error recovery: cannot raise Error_Resync
+
+   function P_Parameter_Profile return List_Id is
+   begin
+      if Token = Tok_Left_Paren then
+         Scan; -- part left paren
+         return P_Formal_Part;
+      else
+         return No_List;
+      end if;
+   end P_Parameter_Profile;
+
+   ---------------------------------------
+   -- 6.1  Parameter And Result Profile --
+   ---------------------------------------
+
+   --  Parsed by its parent construct, which uses P_Parameter_Profile to
+   --  parse the parameters, and P_Subtype_Mark to parse the return type.
+
+   ----------------------
+   -- 6.1  Formal part --
+   ----------------------
+
+   --  FORMAL_PART ::= (PARAMETER_SPECIFICATION {; PARAMETER_SPECIFICATION})
+
+   --  PARAMETER_SPECIFICATION ::=
+   --    DEFINING_IDENTIFIER_LIST : MODE SUBTYPE_MARK
+   --      [:= DEFAULT_EXPRESSION]
+   --  | DEFINING_IDENTIFIER_LIST : ACCESS_DEFINITION
+   --      [:= DEFAULT_EXPRESSION]
+
+   --  This scans the construct Formal_Part. The caller has already checked
+   --  that the initial token is a left parenthesis, and skipped past it, so
+   --  that on entry Token is the first token following the left parenthesis.
+
+   --  Error recovery: cannot raise Error_Resync
+
+   function P_Formal_Part return List_Id is
+      Specification_List : List_Id;
+      Specification_Node : Node_Id;
+      Scan_State         : Saved_Scan_State;
+      Num_Idents         : Nat;
+      Ident              : Nat;
+      Ident_Sloc         : Source_Ptr;
+
+      Idents : array (Int range 1 .. 4096) of Entity_Id;
+      --  This array holds the list of defining identifiers. The upper bound
+      --  of 4096 is intended to be essentially infinite, and we do not even
+      --  bother to check for it being exceeded.
+
+   begin
+      Specification_List := New_List;
+
+      Specification_Loop : loop
+         begin
+            if Token = Tok_Pragma then
+               P_Pragmas_Misplaced;
+            end if;
+
+            Ignore (Tok_Left_Paren);
+            Ident_Sloc := Token_Ptr;
+            Idents (1) := P_Defining_Identifier;
+            Num_Idents := 1;
+
+            Ident_Loop : loop
+               exit Ident_Loop when Token = Tok_Colon;
+
+               --  The only valid tokens are colon and comma, so if we have
+               --  neither do a bit of investigation to see which is the
+               --  better choice for insertion.
+
+               if Token /= Tok_Comma then
+
+                  --  Assume colon if IN or OUT keyword found
+
+                  exit Ident_Loop when Token = Tok_In or else Token = Tok_Out;
+
+                  --  Otherwise scan ahead
+
+                  Save_Scan_State (Scan_State);
+                  Look_Ahead : loop
+
+                     --  If we run into a semicolon, then assume that a
+                     --  colon was missing, e.g.  Parms (X Y; ...). Also
+                     --  assume missing colon on EOF (a real disaster!)
+                     --  and on a right paren, e.g. Parms (X Y), and also
+                     --  on an assignment symbol, e.g. Parms (X Y := ..)
+
+                     if Token = Tok_Semicolon
+                       or else Token = Tok_Right_Paren
+                       or else Token = Tok_EOF
+                       or else Token = Tok_Colon_Equal
+                     then
+                        Restore_Scan_State (Scan_State);
+                        exit Ident_Loop;
+
+                     --  If we run into a colon, assume that we had a missing
+                     --  comma, e.g. Parms (A B : ...). Also assume a missing
+                     --  comma if we hit another comma, e.g. Parms (A B, C ..)
+
+                     elsif Token = Tok_Colon
+                       or else Token = Tok_Comma
+                     then
+                        Restore_Scan_State (Scan_State);
+                        exit Look_Ahead;
+                     end if;
+
+                     Scan;
+                  end loop Look_Ahead;
+               end if;
+
+               --  Here if a comma is present, or to be assumed
+
+               T_Comma;
+               Num_Idents := Num_Idents + 1;
+               Idents (Num_Idents) := P_Defining_Identifier;
+            end loop Ident_Loop;
+
+            --  Fall through the loop on encountering a colon, or deciding
+            --  that there is a missing colon.
+
+            T_Colon;
+
+            --  If there are multiple identifiers, we repeatedly scan the
+            --  type and initialization expression information by resetting
+            --  the scan pointer (so that we get completely separate trees
+            --  for each occurrence).
+
+            if Num_Idents > 1 then
+               Save_Scan_State (Scan_State);
+            end if;
+
+            --  Loop through defining identifiers in list
+
+            Ident := 1;
+
+            Ident_List_Loop : loop
+               Specification_Node :=
+                 New_Node (N_Parameter_Specification, Ident_Sloc);
+               Set_Defining_Identifier (Specification_Node, Idents (Ident));
+
+               if Token = Tok_Access then
+                  if Ada_83 then
+                     Error_Msg_SC ("(Ada 83) access parameters not allowed");
+                  end if;
+
+                  Set_Parameter_Type
+                    (Specification_Node, P_Access_Definition);
+
+               else
+                  P_Mode (Specification_Node);
+
+                  if Token = Tok_Procedure
+                       or else
+                     Token = Tok_Function
+                  then
+                     Error_Msg_SC ("formal subprogram parameter not allowed");
+                     Scan;
+
+                     if Token = Tok_Left_Paren then
+                        Discard_Junk_List (P_Formal_Part);
+                     end if;
+
+                     if Token = Tok_Return then
+                        Scan;
+                        Discard_Junk_Node (P_Subtype_Mark);
+                     end if;
+
+                     Set_Parameter_Type (Specification_Node, Error);
+
+                  else
+                     Set_Parameter_Type (Specification_Node, P_Subtype_Mark);
+                     No_Constraint;
+                  end if;
+               end if;
+
+               Set_Expression (Specification_Node, Init_Expr_Opt (True));
+
+               if Ident > 1 then
+                  Set_Prev_Ids (Specification_Node, True);
+               end if;
+
+               if Ident < Num_Idents then
+                  Set_More_Ids (Specification_Node, True);
+               end if;
+
+               Append (Specification_Node, Specification_List);
+               exit Ident_List_Loop when Ident = Num_Idents;
+               Ident := Ident + 1;
+               Restore_Scan_State (Scan_State);
+            end loop Ident_List_Loop;
+
+         exception
+            when Error_Resync =>
+               Resync_Semicolon_List;
+         end;
+
+         if Token = Tok_Semicolon then
+            Scan; -- past semicolon
+
+            --  If we have RETURN or IS after the semicolon, then assume
+            --  that semicolon should have been a right parenthesis and exit
+
+            if Token = Tok_Is or else Token = Tok_Return then
+               Error_Msg_SP ("expected "")"" in place of "";""");
+               exit Specification_Loop;
+            end if;
+
+         elsif Token = Tok_Right_Paren then
+            Scan; -- past right paren
+            exit Specification_Loop;
+
+         --  Special check for common error of using comma instead of semicolon
+
+         elsif Token = Tok_Comma then
+            T_Semicolon;
+            Scan; -- past comma
+
+         --  Special check for omitted separator
+
+         elsif Token = Tok_Identifier then
+            T_Semicolon;
+
+         --  If nothing sensible, skip to next semicolon or right paren
+
+         else
+            T_Semicolon;
+            Resync_Semicolon_List;
+
+            if Token = Tok_Semicolon then
+               Scan; -- past semicolon
+            else
+               T_Right_Paren;
+               exit Specification_Loop;
+            end if;
+         end if;
+      end loop Specification_Loop;
+
+      return Specification_List;
+   end P_Formal_Part;
+
+   ----------------------------------
+   -- 6.1  Parameter Specification --
+   ----------------------------------
+
+   --  Parsed by P_Formal_Part (6.1)
+
+   ---------------
+   -- 6.1  Mode --
+   ---------------
+
+   --  MODE ::= [in] | in out | out
+
+   --  There is no explicit node in the tree for the Mode. Instead the
+   --  In_Present and Out_Present flags are set in the parent node to
+   --  record the presence of keywords specifying the mode.
+
+   --  Error_Recovery: cannot raise Error_Resync
+
+   procedure P_Mode (Node : Node_Id) is
+   begin
+      if Token = Tok_In then
+         Scan; -- past IN
+         Set_In_Present (Node, True);
+      end if;
+
+      if Token = Tok_Out then
+         Scan; -- past OUT
+         Set_Out_Present (Node, True);
+      end if;
+
+      if Token = Tok_In then
+         Error_Msg_SC ("IN must preceed OUT in parameter mode");
+         Scan; -- past IN
+         Set_In_Present (Node, True);
+      end if;
+   end P_Mode;
+
+   --------------------------
+   -- 6.3  Subprogram Body --
+   --------------------------
+
+   --  Parsed by P_Subprogram (6.1)
+
+   -----------------------------------
+   -- 6.4  Procedure Call Statement --
+   -----------------------------------
+
+   --  Parsed by P_Sequence_Of_Statements (5.1)
+
+   ------------------------
+   -- 6.4  Function Call --
+   ------------------------
+
+   --  Parsed by P_Call_Or_Name (4.1)
+
+   --------------------------------
+   -- 6.4  Actual Parameter Part --
+   --------------------------------
+
+   --  Parsed by P_Call_Or_Name (4.1)
+
+   --------------------------------
+   -- 6.4  Parameter Association --
+   --------------------------------
+
+   --  Parsed by P_Call_Or_Name (4.1)
+
+   ------------------------------------
+   -- 6.4  Explicit Actual Parameter --
+   ------------------------------------
+
+   --  Parsed by P_Call_Or_Name (4.1)
+
+   ---------------------------
+   -- 6.5  Return Statement --
+   ---------------------------
+
+   --  RETURN_STATEMENT ::= return [EXPRESSION];
+
+   --  The caller has checked that the initial token is RETURN
+
+   --  Error recovery: can raise Error_Resync
+
+   function P_Return_Statement return Node_Id is
+      Return_Node : Node_Id;
+
+   begin
+      Return_Node := New_Node (N_Return_Statement, Token_Ptr);
+
+      --  Sloc points to RETURN
+      --  Expression (Op3)
+
+      Scan; -- past RETURN
+
+      if Token /= Tok_Semicolon then
+
+         --  If no semicolon, then scan an expression, except that
+         --  we avoid trying to scan an expression if we are at an
+         --  expression terminator since in that case the best error
+         --  message is probably that we have a missing semicolon.
+
+         if Token not in Token_Class_Eterm then
+            Set_Expression (Return_Node, P_Expression_No_Right_Paren);
+         end if;
+      end if;
+
+      TF_Semicolon;
+      return Return_Node;
+   end P_Return_Statement;
+
+end Ch6;
diff --git a/gcc/ada/par-ch7.adb b/gcc/ada/par-ch7.adb
new file mode 100644 (file)
index 0000000..de63213
--- /dev/null
@@ -0,0 +1,282 @@
+------------------------------------------------------------------------------
+--                                                                          --
+--                         GNAT COMPILER COMPONENTS                         --
+--                                                                          --
+--                              P A R . C H 7                               --
+--                                                                          --
+--                                 B o d y                                  --
+--                                                                          --
+--                            $Revision: 1.29 $
+--                                                                          --
+--          Copyright (C) 1992-2001 Free Software Foundation, Inc.          --
+--                                                                          --
+-- GNAT is free software;  you can  redistribute it  and/or modify it under --
+-- terms of the  GNU General Public License as published  by the Free Soft- --
+-- ware  Foundation;  either version 2,  or (at your option) any later ver- --
+-- sion.  GNAT is distributed in the hope that it will be useful, but WITH- --
+-- OUT 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  distributed with GNAT;  see file COPYING.  If not, write --
+-- to  the Free Software Foundation,  59 Temple Place - Suite 330,  Boston, --
+-- MA 02111-1307, USA.                                                      --
+--                                                                          --
+-- GNAT was originally developed  by the GNAT team at  New York University. --
+-- It is now maintained by Ada Core Technologies Inc (http://www.gnat.com). --
+--                                                                          --
+------------------------------------------------------------------------------
+
+pragma Style_Checks (All_Checks);
+--  Turn off subprogram body ordering check. Subprograms are in order
+--  by RM section rather than alphabetical
+
+separate (Par)
+package body Ch7 is
+
+   ---------------------------------------------
+   -- 7.1  Package (also 8.5.3, 10.1.3, 12.3) --
+   ---------------------------------------------
+
+   --  This routine scans out a package declaration, package body, or a
+   --  renaming declaration or generic instantiation starting with PACKAGE
+
+   --  PACKAGE_DECLARATION ::= PACKAGE_SPECIFICATION;
+
+   --  PACKAGE_SPECIFICATION ::=
+   --    package DEFINING_PROGRAM_UNIT_NAME is
+   --      {BASIC_DECLARATIVE_ITEM}
+   --    [private
+   --      {BASIC_DECLARATIVE_ITEM}]
+   --    end [[PARENT_UNIT_NAME .] IDENTIFIER]
+
+   --  PACKAGE_BODY ::=
+   --    package body DEFINING_PROGRAM_UNIT_NAME is
+   --      DECLARATIVE_PART
+   --    [begin
+   --      HANDLED_SEQUENCE_OF_STATEMENTS]
+   --    end [[PARENT_UNIT_NAME .] IDENTIFIER]
+
+   --  PACKAGE_RENAMING_DECLARATION ::=
+   --    package DEFINING_IDENTIFIER renames package_NAME;
+
+   --  PACKAGE_BODY_STUB ::=
+   --    package body DEFINING_IDENTIFIER is separate;
+
+   --  The value in Pf_Flags indicates which of these possible declarations
+   --  is acceptable to the caller:
+
+   --    Pf_Flags.Spcn                 Set if specification OK
+   --    Pf_Flags.Decl                 Set if declaration OK
+   --    Pf_Flags.Gins                 Set if generic instantiation OK
+   --    Pf_Flags.Pbod                 Set if proper body OK
+   --    Pf_Flags.Rnam                 Set if renaming declaration OK
+   --    Pf_Flags.Stub                 Set if body stub OK
+
+   --  If an inappropriate form is encountered, it is scanned out but an
+   --  error message indicating that it is appearing in an inappropriate
+   --  context is issued. The only possible settings for Pf_Flags are those
+   --  defined as constants in package Par.
+
+   --  Note: in all contexts where a package specification is required, there
+   --  is a terminating semicolon. This semicolon is scanned out in the case
+   --  where Pf_Flags is set to Pf_Spcn, even though it is not strictly part
+   --  of the package specification (it's just too much trouble, and really
+   --  quite unnecessary, to deal with scanning out an END where the semicolon
+   --  after the END is not considered to be part of the END.
+
+   --  The caller has checked that the initial token is PACKAGE
+
+   --  Error recovery: cannot raise Error_Resync
+
+   function P_Package (Pf_Flags : Pf_Rec) return Node_Id is
+      Package_Node       : Node_Id;
+      Specification_Node : Node_Id;
+      Name_Node          : Node_Id;
+      Package_Sloc       : Source_Ptr;
+
+   begin
+      Push_Scope_Stack;
+      Scope.Table (Scope.Last).Etyp := E_Name;
+      Scope.Table (Scope.Last).Ecol := Start_Column;
+      Scope.Table (Scope.Last).Lreq := False;
+
+      Package_Sloc := Token_Ptr;
+      Scan; -- past PACKAGE
+
+      if Token = Tok_Type then
+         Error_Msg_SC ("TYPE not allowed here");
+         Scan; -- past TYPE
+      end if;
+
+      --  Case of package body. Note that we demand a package body if that
+      --  is the only possibility (even if the BODY keyword is not present)
+
+      if Token = Tok_Body or else Pf_Flags = Pf_Pbod then
+         if not Pf_Flags.Pbod then
+            Error_Msg_SC ("package body cannot appear here!");
+         end if;
+
+         T_Body;
+         Name_Node := P_Defining_Program_Unit_Name;
+         Scope.Table (Scope.Last).Labl := Name_Node;
+         TF_Is;
+
+         if Separate_Present then
+            if not Pf_Flags.Stub then
+               Error_Msg_SC ("body stub cannot appear here!");
+            end if;
+
+            Scan; -- past SEPARATE
+            TF_Semicolon;
+            Pop_Scope_Stack;
+
+            Package_Node := New_Node (N_Package_Body_Stub, Package_Sloc);
+            Set_Defining_Identifier (Package_Node, Name_Node);
+
+         else
+            Package_Node := New_Node (N_Package_Body, Package_Sloc);
+            Set_Defining_Unit_Name (Package_Node, Name_Node);
+            Parse_Decls_Begin_End (Package_Node);
+         end if;
+
+         return Package_Node;
+
+      --  Cases other than Package_Body
+
+      else
+         Name_Node := P_Defining_Program_Unit_Name;
+         Scope.Table (Scope.Last).Labl := Name_Node;
+
+         --  Case of renaming declaration
+
+         Check_Misspelling_Of (Tok_Renames);
+
+         if Token = Tok_Renames then
+            if not Pf_Flags.Rnam then
+               Error_Msg_SC ("renaming declaration cannot appear here!");
+            end if;
+
+            Scan; -- past RENAMES;
+
+            Package_Node :=
+              New_Node (N_Package_Renaming_Declaration, Package_Sloc);
+            Set_Defining_Unit_Name (Package_Node, Name_Node);
+            Set_Name (Package_Node, P_Qualified_Simple_Name);
+
+            No_Constraint;
+            TF_Semicolon;
+            Pop_Scope_Stack;
+            return Package_Node;
+
+         else
+            TF_Is;
+
+            --  Case of generic instantiation
+
+            if Token = Tok_New then
+               if not Pf_Flags.Gins then
+                  Error_Msg_SC
+                     ("generic instantiation cannot appear here!");
+               end if;
+
+               Scan; -- past NEW
+
+               Package_Node :=
+                  New_Node (N_Package_Instantiation, Package_Sloc);
+               Set_Defining_Unit_Name (Package_Node, Name_Node);
+               Set_Name (Package_Node, P_Qualified_Simple_Name);
+               Set_Generic_Associations
+                 (Package_Node, P_Generic_Actual_Part_Opt);
+               TF_Semicolon;
+               Pop_Scope_Stack;
+
+            --  Case of package declaration or package specification
+
+            else
+               Specification_Node :=
+                 New_Node (N_Package_Specification, Package_Sloc);
+
+               Set_Defining_Unit_Name (Specification_Node, Name_Node);
+               Set_Visible_Declarations
+                 (Specification_Node, P_Basic_Declarative_Items);
+
+               if Token = Tok_Private then
+                  Error_Msg_Col := Scope.Table (Scope.Last).Ecol;
+
+                  if Style.RM_Column_Check then
+                     if Token_Is_At_Start_Of_Line
+                       and then Start_Column /= Error_Msg_Col
+                     then
+                        Error_Msg_SC
+                          ("(style) PRIVATE in wrong column, should be@");
+                     end if;
+                  end if;
+
+                  Scan; -- past PRIVATE
+                  Set_Private_Declarations
+                    (Specification_Node, P_Basic_Declarative_Items);
+
+                  --  Deal gracefully with multiple PRIVATE parts
+
+                  while Token = Tok_Private loop
+                     Error_Msg_SC
+                       ("only one private part allowed per package");
+                     Scan; -- past PRIVATE
+                     Append_List (P_Basic_Declarative_Items,
+                       Private_Declarations (Specification_Node));
+                  end loop;
+               end if;
+
+               if Pf_Flags = Pf_Spcn then
+                  Package_Node := Specification_Node;
+               else
+                  Package_Node :=
+                    New_Node (N_Package_Declaration, Package_Sloc);
+                  Set_Specification (Package_Node, Specification_Node);
+               end if;
+
+               if Token = Tok_Begin then
+                  Error_Msg_SC ("begin block not allowed in package spec");
+                  Scan; -- past BEGIN
+                  Discard_Junk_List (P_Sequence_Of_Statements (SS_None));
+               end if;
+
+               End_Statements (Specification_Node);
+            end if;
+
+            return Package_Node;
+         end if;
+      end if;
+   end P_Package;
+
+   ------------------------------
+   -- 7.1  Package Declaration --
+   ------------------------------
+
+   --  Parsed by P_Package (7.1)
+
+   --------------------------------
+   -- 7.1  Package Specification --
+   --------------------------------
+
+   --  Parsed by P_Package (7.1)
+
+   -----------------------
+   -- 7.1  Package Body --
+   -----------------------
+
+   --  Parsed by P_Package (7.1)
+
+   -----------------------------------
+   -- 7.3  Private Type Declaration --
+   -----------------------------------
+
+   --  Parsed by P_Type_Declaration (3.2.1)
+
+   ----------------------------------------
+   -- 7.3  Private Extension Declaration --
+   ----------------------------------------
+
+   --  Parsed by P_Type_Declaration (3.2.1)
+
+end Ch7;
diff --git a/gcc/ada/par-ch8.adb b/gcc/ada/par-ch8.adb
new file mode 100644 (file)
index 0000000..9d1b386
--- /dev/null
@@ -0,0 +1,175 @@
+------------------------------------------------------------------------------
+--                                                                          --
+--                         GNAT COMPILER COMPONENTS                         --
+--                                                                          --
+--                              P A R . C H 8                               --
+--                                                                          --
+--                                 B o d y                                  --
+--                                                                          --
+--                            $Revision: 1.16 $
+--                                                                          --
+--          Copyright (C) 1992-2001 Free Software Foundation, Inc.          --
+--                                                                          --
+-- GNAT is free software;  you can  redistribute it  and/or modify it under --
+-- terms of the  GNU General Public License as published  by the Free Soft- --
+-- ware  Foundation;  either version 2,  or (at your option) any later ver- --
+-- sion.  GNAT is distributed in the hope that it will be useful, but WITH- --
+-- OUT 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  distributed with GNAT;  see file COPYING.  If not, write --
+-- to  the Free Software Foundation,  59 Temple Place - Suite 330,  Boston, --
+-- MA 02111-1307, USA.                                                      --
+--                                                                          --
+-- GNAT was originally developed  by the GNAT team at  New York University. --
+-- It is now maintained by Ada Core Technologies Inc (http://www.gnat.com). --
+--                                                                          --
+------------------------------------------------------------------------------
+
+pragma Style_Checks (All_Checks);
+--  Turn off subprogram body ordering check. Subprograms are in order
+--  by RM section rather than alphabetical
+
+separate (Par)
+package body Ch8 is
+
+   -----------------------
+   -- Local Subprograms --
+   -----------------------
+
+   function P_Use_Package_Clause                           return Node_Id;
+   function P_Use_Type_Clause                              return Node_Id;
+
+   ---------------------
+   -- 8.4  Use Clause --
+   ---------------------
+
+   --  USE_CLAUSE ::= USE_PACKAGE_CLAUSE | USE_TYPE_CLAUSE
+
+   --  The caller has checked that the initial token is USE
+
+   --  Error recovery: cannot raise Error_Resync
+
+   function P_Use_Clause return Node_Id is
+   begin
+      Scan; -- past USE
+
+      if Token = Tok_Type then
+         return P_Use_Type_Clause;
+
+      else
+         return P_Use_Package_Clause;
+      end if;
+   end P_Use_Clause;
+
+   -----------------------------
+   -- 8.4  Use Package Clause --
+   -----------------------------
+
+   --  USE_PACKAGE_CLAUSE ::= use package_NAME {, package_NAME};
+
+   --  The caller has scanned out the USE keyword
+
+   --  Error recovery: cannot raise Error_Resync
+
+   function P_Use_Package_Clause return Node_Id is
+      Use_Node : Node_Id;
+
+   begin
+      Use_Node := New_Node (N_Use_Package_Clause, Prev_Token_Ptr);
+      Set_Names (Use_Node, New_List);
+
+      if Token = Tok_Package then
+         Error_Msg_SC ("PACKAGE should not appear here");
+         Scan; -- past PACKAGE
+      end if;
+
+      loop
+         Append (P_Qualified_Simple_Name, Names (Use_Node));
+         exit when Token /= Tok_Comma;
+         Scan; -- past comma
+      end loop;
+
+      TF_Semicolon;
+      return Use_Node;
+   end P_Use_Package_Clause;
+
+   --------------------------
+   -- 8.4  Use Type Clause --
+   --------------------------
+
+   --  USE_TYPE_CLAUSE ::= use type SUBTYPE_MARK {, SUBTYPE_MARK};
+
+   --  The caller has checked that the initial token is USE, scanned it out
+   --  and that the current token is TYPE.
+
+   --  Error recovery: cannot raise Error_Resync
+
+   function P_Use_Type_Clause return Node_Id is
+      Use_Node : Node_Id;
+
+   begin
+      Use_Node := New_Node (N_Use_Type_Clause, Prev_Token_Ptr);
+      Set_Subtype_Marks (Use_Node, New_List);
+
+      if Ada_83 then
+         Error_Msg_SC ("(Ada 83) use type not allowed!");
+      end if;
+
+      Scan; -- past TYPE
+
+      loop
+         Append (P_Subtype_Mark, Subtype_Marks (Use_Node));
+         No_Constraint;
+         exit when Token /= Tok_Comma;
+         Scan; -- past comma
+      end loop;
+
+      TF_Semicolon;
+      return Use_Node;
+   end P_Use_Type_Clause;
+
+   -------------------------------
+   -- 8.5  Renaming Declaration --
+   -------------------------------
+
+   --  Object renaming declarations and exception renaming declarations
+   --  are parsed by P_Identifier_Declaration (3.3.1)
+
+   --  Subprogram renaming declarations are parsed by P_Subprogram (6.1)
+
+   --  Package renaming declarations are parsed by P_Package (7.1)
+
+   --  Generic renaming declarations are parsed by P_Generic (12.1)
+
+   ----------------------------------------
+   -- 8.5.1  Object Renaming Declaration --
+   ----------------------------------------
+
+   --  Parsed by P_Identifier_Declarations (3.3.1)
+
+   ----------------------------------------
+   -- 8.5.2  Exception Renaming Declaration --
+   ----------------------------------------
+
+   --  Parsed by P_Identifier_Declarations (3.3.1)
+
+   -----------------------------------------
+   -- 8.5.3  Package Renaming Declaration --
+   -----------------------------------------
+
+   --  Parsed by P_Package (7.1)
+
+   --------------------------------------------
+   -- 8.5.4  Subprogram Renaming Declaration --
+   --------------------------------------------
+
+   --  Parsed by P_Subprogram (6.1)
+
+   -----------------------------------------
+   -- 8.5.2  Generic Renaming Declaration --
+   -----------------------------------------
+
+   --  Parsed by P_Generic (12.1)
+
+end Ch8;
diff --git a/gcc/ada/par-ch9.adb b/gcc/ada/par-ch9.adb
new file mode 100644 (file)
index 0000000..87d6be6
--- /dev/null
@@ -0,0 +1,1616 @@
+------------------------------------------------------------------------------
+--                                                                          --
+--                         GNAT COMPILER COMPONENTS                         --
+--                                                                          --
+--                              P A R . C H 9                               --
+--                                                                          --
+--                                 B o d y                                  --
+--                                                                          --
+--                            $Revision: 1.82 $
+--                                                                          --
+--          Copyright (C) 1992-2001 Free Software Foundation, Inc.          --
+--                                                                          --
+-- GNAT is free software;  you can  redistribute it  and/or modify it under --
+-- terms of the  GNU General Public License as published  by the Free Soft- --
+-- ware  Foundation;  either version 2,  or (at your option) any later ver- --
+-- sion.  GNAT is distributed in the hope that it will be useful, but WITH- --
+-- OUT 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  distributed with GNAT;  see file COPYING.  If not, write --
+-- to  the Free Software Foundation,  59 Temple Place - Suite 330,  Boston, --
+-- MA 02111-1307, USA.                                                      --
+--                                                                          --
+-- GNAT was originally developed  by the GNAT team at  New York University. --
+-- It is now maintained by Ada Core Technologies Inc (http://www.gnat.com). --
+--                                                                          --
+------------------------------------------------------------------------------
+
+pragma Style_Checks (All_Checks);
+--  Turn off subprogram body ordering check. Subprograms are in order
+--  by RM section rather than alphabetical
+
+separate (Par)
+package body Ch9 is
+
+   --  Local subprograms, used only in this chapter
+
+   function P_Accept_Alternative                   return Node_Id;
+   function P_Delay_Alternative                    return Node_Id;
+   function P_Delay_Relative_Statement             return Node_Id;
+   function P_Delay_Until_Statement                return Node_Id;
+   function P_Entry_Barrier                        return Node_Id;
+   function P_Entry_Body_Formal_Part               return Node_Id;
+   function P_Entry_Declaration                    return Node_Id;
+   function P_Entry_Index_Specification            return Node_Id;
+   function P_Protected_Definition                 return Node_Id;
+   function P_Protected_Operation_Declaration_Opt  return Node_Id;
+   function P_Protected_Operation_Items            return List_Id;
+   function P_Task_Definition                      return Node_Id;
+   function P_Task_Items                           return List_Id;
+
+   -----------------------------
+   -- 9.1  Task (also 10.1.3) --
+   -----------------------------
+
+   --  TASK_TYPE_DECLARATION ::=
+   --    task type DEFINING_IDENTIFIER [KNOWN_DISCRIMINANT_PART]
+   --      [is TASK_DEFINITION];
+
+   --  SINGLE_TASK_DECLARATION ::=
+   --    task DEFINING_IDENTIFIER [is TASK_DEFINITION];
+
+   --  TASK_BODY ::=
+   --    task body DEFINING_IDENTIFIER is
+   --      DECLARATIVE_PART
+   --    begin
+   --      HANDLED_SEQUENCE_OF_STATEMENTS
+   --    end [task_IDENTIFIER]
+
+   --  TASK_BODY_STUB ::=
+   --    task body DEFINING_IDENTIFIER is separate;
+
+   --  This routine scans out a task declaration, task body, or task stub
+
+   --  The caller has checked that the initial token is TASK and scanned
+   --  past it, so that Token is set to the token after TASK
+
+   --  Error recovery: cannot raise Error_Resync
+
+   function P_Task return Node_Id is
+      Name_Node  : Node_Id;
+      Task_Node  : Node_Id;
+      Task_Sloc  : Source_Ptr;
+
+   begin
+      Push_Scope_Stack;
+      Scope.Table (Scope.Last).Etyp := E_Name;
+      Scope.Table (Scope.Last).Ecol := Start_Column;
+      Scope.Table (Scope.Last).Sloc := Token_Ptr;
+      Scope.Table (Scope.Last).Lreq := False;
+      Task_Sloc := Prev_Token_Ptr;
+
+      if Token = Tok_Body then
+         Scan; -- past BODY
+         Name_Node := P_Defining_Identifier;
+         Scope.Table (Scope.Last).Labl := Name_Node;
+
+         if Token = Tok_Left_Paren then
+            Error_Msg_SC ("discriminant part not allowed in task body");
+            Discard_Junk_List (P_Known_Discriminant_Part_Opt);
+         end if;
+
+         TF_Is;
+
+         --  Task stub
+
+         if Token = Tok_Separate then
+            Scan; -- past SEPARATE
+            Task_Node := New_Node (N_Task_Body_Stub, Task_Sloc);
+            Set_Defining_Identifier (Task_Node, Name_Node);
+            TF_Semicolon;
+            Pop_Scope_Stack; -- remove unused entry
+
+         --  Task body
+
+         else
+            Task_Node := New_Node (N_Task_Body, Task_Sloc);
+            Set_Defining_Identifier (Task_Node, Name_Node);
+            Parse_Decls_Begin_End (Task_Node);
+         end if;
+
+         return Task_Node;
+
+      --  Otherwise we must have a task declaration
+
+      else
+         if Token = Tok_Type then
+            Scan; -- past TYPE
+            Task_Node := New_Node (N_Task_Type_Declaration, Task_Sloc);
+            Name_Node := P_Defining_Identifier;
+            Set_Defining_Identifier (Task_Node, Name_Node);
+            Scope.Table (Scope.Last).Labl := Name_Node;
+            Set_Discriminant_Specifications
+              (Task_Node, P_Known_Discriminant_Part_Opt);
+
+         else
+            Task_Node := New_Node (N_Single_Task_Declaration, Task_Sloc);
+            Name_Node := P_Defining_Identifier;
+            Set_Defining_Identifier (Task_Node, Name_Node);
+            Scope.Table (Scope.Last).Labl := Name_Node;
+
+            if Token = Tok_Left_Paren then
+               Error_Msg_SC ("discriminant part not allowed for single task");
+               Discard_Junk_List (P_Known_Discriminant_Part_Opt);
+            end if;
+
+         end if;
+
+         --  Parse optional task definition. Note that P_Task_Definition scans
+         --  out the semicolon as well as the task definition itself.
+
+         if Token = Tok_Semicolon then
+
+            --  A little check, if the next token after semicolon is
+            --  Entry, then surely the semicolon should really be IS
+
+            Scan; -- past semicolon
+
+            if Token = Tok_Entry then
+               Error_Msg_SP (""";"" should be IS");
+               Set_Task_Definition (Task_Node, P_Task_Definition);
+            else
+               Pop_Scope_Stack; -- Remove unused entry
+            end if;
+         else
+            TF_Is; -- must have IS if no semicolon
+            Set_Task_Definition (Task_Node, P_Task_Definition);
+         end if;
+
+         return Task_Node;
+      end if;
+   end P_Task;
+
+   --------------------------------
+   -- 9.1  Task Type Declaration --
+   --------------------------------
+
+   --  Parsed by P_Task (9.1)
+
+   ----------------------------------
+   -- 9.1  Single Task Declaration --
+   ----------------------------------
+
+   --  Parsed by P_Task (9.1)
+
+   --------------------------
+   -- 9.1  Task Definition --
+   --------------------------
+
+   --  TASK_DEFINITION ::=
+   --      {TASK_ITEM}
+   --    [private
+   --      {TASK_ITEM}]
+   --    end [task_IDENTIFIER];
+
+   --  The caller has already made the scope stack entry
+
+   --  Note: there is a small deviation from official syntax here in that we
+   --  regard the semicolon after end as part of the Task_Definition, and in
+   --  the official syntax, it's part of the enclosing declaration. The reason
+   --  for this deviation is that otherwise the end processing would have to
+   --  be special cased, which would be a nuisance!
+
+   --  Error recovery:  cannot raise Error_Resync
+
+   function P_Task_Definition return Node_Id is
+      Def_Node  : Node_Id;
+
+   begin
+      Def_Node := New_Node (N_Task_Definition, Token_Ptr);
+      Set_Visible_Declarations (Def_Node, P_Task_Items);
+
+      if Token = Tok_Private then
+         Scan; -- past PRIVATE
+         Set_Private_Declarations (Def_Node, P_Task_Items);
+
+         --  Deal gracefully with multiple PRIVATE parts
+
+         while Token = Tok_Private loop
+            Error_Msg_SC ("Only one private part allowed per task");
+            Scan; -- past PRIVATE
+            Append_List (P_Task_Items, Private_Declarations (Def_Node));
+         end loop;
+      end if;
+
+      End_Statements (Def_Node);
+      return Def_Node;
+   end P_Task_Definition;
+
+   --------------------
+   -- 9.1  Task Item --
+   --------------------
+
+   --  TASK_ITEM ::= ENTRY_DECLARATION | REPRESENTATION_CLAUSE
+
+   --  This subprogram scans a (possibly empty) list of task items and pragmas
+
+   --  Error recovery:  cannot raise Error_Resync
+
+   --  Note: a pragma can also be returned in this position
+
+   function P_Task_Items return List_Id is
+      Items      : List_Id;
+      Item_Node  : Node_Id;
+      Decl_Sloc  : Source_Ptr;
+
+   begin
+      --  Get rid of active SIS entry from outer scope. This means we will
+      --  miss some nested cases, but it doesn't seem worth the effort. See
+      --  discussion in Par for further details
+
+      SIS_Entry_Active := False;
+
+      --  Loop to scan out task items
+
+      Items := New_List;
+
+      Decl_Loop : loop
+         Decl_Sloc := Token_Ptr;
+
+         if Token = Tok_Pragma then
+            Append (P_Pragma, Items);
+
+         elsif Token = Tok_Entry then
+            Append (P_Entry_Declaration, Items);
+
+         elsif Token = Tok_For then
+            --  Representation clause in task declaration. The only rep
+            --  clause which is legal in a protected is an address clause,
+            --  so that is what we try to scan out.
+
+            Item_Node := P_Representation_Clause;
+
+            if Nkind (Item_Node) = N_At_Clause then
+               Append (Item_Node, Items);
+
+            elsif Nkind (Item_Node) = N_Attribute_Definition_Clause
+              and then Chars (Item_Node) = Name_Address
+            then
+               Append (Item_Node, Items);
+
+            else
+               Error_Msg
+                 ("the only representation clause " &
+                  "allowed here is an address clause!", Decl_Sloc);
+            end if;
+
+         elsif Token = Tok_Identifier
+           or else Token in Token_Class_Declk
+         then
+            Error_Msg_SC ("Illegal declaration in task definition");
+            Resync_Past_Semicolon;
+
+         else
+            exit Decl_Loop;
+         end if;
+      end loop Decl_Loop;
+
+      return Items;
+   end P_Task_Items;
+
+   --------------------
+   -- 9.1  Task Body --
+   --------------------
+
+   --  Parsed by P_Task (9.1)
+
+   ----------------------------------
+   -- 9.4  Protected (also 10.1.3) --
+   ----------------------------------
+
+   --  PROTECTED_TYPE_DECLARATION ::=
+   --    protected type DEFINING_IDENTIFIER [KNOWN_DISCRIMINANT_PART]
+   --      is PROTECTED_DEFINITION;
+
+   --  SINGLE_PROTECTED_DECLARATION ::=
+   --    protected DEFINING_IDENTIFIER is PROTECTED_DEFINITION;
+
+   --  PROTECTED_BODY ::=
+   --    protected body DEFINING_IDENTIFIER is
+   --      {PROTECTED_OPERATION_ITEM}
+   --    end [protected_IDENTIFIER];
+
+   --  PROTECTED_BODY_STUB ::=
+   --    protected body DEFINING_IDENTIFIER is separate;
+
+   --  This routine scans out a protected declaration, protected body
+   --  or a protected stub.
+
+   --  The caller has checked that the initial token is PROTECTED and
+   --  scanned past it, so Token is set to the following token.
+
+   --  Error recovery: cannot raise Error_Resync
+
+   function P_Protected return Node_Id is
+      Name_Node      : Node_Id;
+      Protected_Node : Node_Id;
+      Protected_Sloc : Source_Ptr;
+
+   begin
+      Push_Scope_Stack;
+      Scope.Table (Scope.Last).Etyp := E_Name;
+      Scope.Table (Scope.Last).Ecol := Start_Column;
+      Scope.Table (Scope.Last).Lreq := False;
+      Protected_Sloc := Prev_Token_Ptr;
+
+      if Token = Tok_Body then
+         Scan; -- past BODY
+         Name_Node := P_Defining_Identifier;
+         Scope.Table (Scope.Last).Labl := Name_Node;
+
+         if Token = Tok_Left_Paren then
+            Error_Msg_SC ("discriminant part not allowed in protected body");
+            Discard_Junk_List (P_Known_Discriminant_Part_Opt);
+         end if;
+
+         TF_Is;
+
+         --  Protected stub
+
+         if Token = Tok_Separate then
+            Scan; -- past SEPARATE
+            Protected_Node := New_Node (N_Protected_Body_Stub, Protected_Sloc);
+            Set_Defining_Identifier (Protected_Node, Name_Node);
+            TF_Semicolon;
+            Pop_Scope_Stack; -- remove unused entry
+
+         --  Protected body
+
+         else
+            Protected_Node := New_Node (N_Protected_Body, Protected_Sloc);
+            Set_Defining_Identifier (Protected_Node, Name_Node);
+            Set_Declarations (Protected_Node, P_Protected_Operation_Items);
+            End_Statements (Protected_Node);
+         end if;
+
+         return Protected_Node;
+
+      --  Otherwise we must have a protected declaration
+
+      else
+         if Token = Tok_Type then
+            Scan; -- past TYPE
+            Protected_Node :=
+              New_Node (N_Protected_Type_Declaration, Protected_Sloc);
+            Name_Node := P_Defining_Identifier;
+            Set_Defining_Identifier (Protected_Node, Name_Node);
+            Scope.Table (Scope.Last).Labl := Name_Node;
+            Set_Discriminant_Specifications
+              (Protected_Node, P_Known_Discriminant_Part_Opt);
+
+         else
+            Protected_Node :=
+              New_Node (N_Single_Protected_Declaration, Protected_Sloc);
+            Name_Node := P_Defining_Identifier;
+            Set_Defining_Identifier (Protected_Node, Name_Node);
+
+            if Token = Tok_Left_Paren then
+               Error_Msg_SC
+                 ("discriminant part not allowed for single protected");
+               Discard_Junk_List (P_Known_Discriminant_Part_Opt);
+            end if;
+
+            Scope.Table (Scope.Last).Labl := Name_Node;
+         end if;
+
+         T_Is;
+         Set_Protected_Definition (Protected_Node, P_Protected_Definition);
+         return Protected_Node;
+      end if;
+   end P_Protected;
+
+   -------------------------------------
+   -- 9.4  Protected Type Declaration --
+   -------------------------------------
+
+   --  Parsed by P_Protected (9.4)
+
+   ---------------------------------------
+   -- 9.4  Single Protected Declaration --
+   ---------------------------------------
+
+   --  Parsed by P_Protected (9.4)
+
+   -------------------------------
+   -- 9.4  Protected Definition --
+   -------------------------------
+
+   --  PROTECTED_DEFINITION ::=
+   --      {PROTECTED_OPERATION_DECLARATION}
+   --    [private
+   --      {PROTECTED_ELEMENT_DECLARATION}]
+   --    end [protected_IDENTIFIER]
+
+   --  PROTECTED_ELEMENT_DECLARATION ::=
+   --    PROTECTED_OPERATION_DECLARATION
+   --  | COMPONENT_DECLARATION
+
+   --  The caller has already established the scope stack entry
+
+   --  Error recovery: cannot raise Error_Resync
+
+   function P_Protected_Definition return Node_Id is
+      Def_Node  : Node_Id;
+      Item_Node : Node_Id;
+
+   begin
+      Def_Node := New_Node (N_Protected_Definition, Token_Ptr);
+
+      --  Get rid of active SIS entry from outer scope. This means we will
+      --  miss some nested cases, but it doesn't seem worth the effort. See
+      --  discussion in Par for further details
+
+      SIS_Entry_Active := False;
+
+      --  Loop to scan visible declarations (protected operation declarations)
+
+      Set_Visible_Declarations (Def_Node, New_List);
+
+      loop
+         Item_Node := P_Protected_Operation_Declaration_Opt;
+         exit when No (Item_Node);
+         Append (Item_Node, Visible_Declarations (Def_Node));
+      end loop;
+
+      --  Deal with PRIVATE part (including graceful handling
+      --  of multiple PRIVATE parts).
+
+      Private_Loop : while Token = Tok_Private loop
+         if No (Private_Declarations (Def_Node)) then
+            Set_Private_Declarations (Def_Node, New_List);
+         else
+            Error_Msg_SC ("duplicate private part");
+         end if;
+
+         Scan; -- past PRIVATE
+
+         Declaration_Loop : loop
+            if Token = Tok_Identifier then
+               P_Component_Items (Private_Declarations (Def_Node));
+            else
+               Item_Node := P_Protected_Operation_Declaration_Opt;
+               exit Declaration_Loop when No (Item_Node);
+               Append (Item_Node, Private_Declarations (Def_Node));
+            end if;
+         end loop Declaration_Loop;
+      end loop Private_Loop;
+
+      End_Statements (Def_Node);
+      return Def_Node;
+   end P_Protected_Definition;
+
+   ------------------------------------------
+   -- 9.4  Protected Operation Declaration --
+   ------------------------------------------
+
+   --  PROTECTED_OPERATION_DECLARATION ::=
+   --    SUBPROGRAM_DECLARATION
+   --  | ENTRY_DECLARATION
+   --  | REPRESENTATION_CLAUSE
+
+   --  Error recovery: cannot raise Error_Resync
+
+   --  Note: a pragma can also be returned in this position
+
+   --  We are not currently permitting representation clauses to appear as
+   --  protected operation declarations, do we have to rethink this???
+
+   function P_Protected_Operation_Declaration_Opt return Node_Id is
+      L : List_Id;
+      P : Source_Ptr;
+
+   begin
+      --  This loop runs more than once only when a junk declaration
+      --  is skipped.
+
+      loop
+         if Token = Tok_Pragma then
+            return P_Pragma;
+
+         elsif Token = Tok_Entry then
+            return P_Entry_Declaration;
+
+         elsif Token = Tok_Function or else Token = Tok_Procedure then
+            return P_Subprogram (Pf_Decl);
+
+         elsif Token = Tok_Identifier then
+            L := New_List;
+            P := Token_Ptr;
+            Skip_Declaration (L);
+
+            if Nkind (First (L)) = N_Object_Declaration then
+               Error_Msg
+                 ("component must be declared in private part of " &
+                  "protected type", P);
+            else
+               Error_Msg
+                 ("illegal declaration in protected definition", P);
+            end if;
+
+         elsif Token in Token_Class_Declk then
+            Error_Msg_SC ("illegal declaration in protected definition");
+            Resync_Past_Semicolon;
+
+            --  Return now to avoid cascaded messages if next declaration
+            --  is a valid component declaration.
+
+            return Error;
+
+         elsif Token = Tok_For then
+            Error_Msg_SC
+              ("representation clause not allowed in protected definition");
+            Resync_Past_Semicolon;
+
+         else
+            return Empty;
+         end if;
+      end loop;
+   end P_Protected_Operation_Declaration_Opt;
+
+   -----------------------------------
+   -- 9.4  Protected Operation Item --
+   -----------------------------------
+
+   --  PROTECTED_OPERATION_ITEM ::=
+   --    SUBPROGRAM_DECLARATION
+   --  | SUBPROGRAM_BODY
+   --  | ENTRY_BODY
+   --  | REPRESENTATION_CLAUSE
+
+   --  This procedure parses and returns a list of protected operation items
+
+   --  We are not currently permitting representation clauses to appear
+   --  as protected operation items, do we have to rethink this???
+
+   function P_Protected_Operation_Items return List_Id is
+      Item_List : List_Id;
+
+   begin
+      Item_List := New_List;
+
+      loop
+         if Token = Tok_Entry or else Bad_Spelling_Of (Tok_Entry) then
+            Append (P_Entry_Body, Item_List);
+
+         elsif Token = Tok_Function or else Bad_Spelling_Of (Tok_Function)
+                 or else
+               Token = Tok_Procedure or else Bad_Spelling_Of (Tok_Procedure)
+         then
+            Append (P_Subprogram (Pf_Decl_Pbod), Item_List);
+
+         elsif Token = Tok_Pragma or else Bad_Spelling_Of (Tok_Pragma) then
+            P_Pragmas_Opt (Item_List);
+
+         elsif Token = Tok_Private or else Bad_Spelling_Of (Tok_Private) then
+            Error_Msg_SC ("PRIVATE not allowed in protected body");
+            Scan; -- past PRIVATE
+
+         elsif Token = Tok_Identifier then
+            Error_Msg_SC
+              ("all components must be declared in spec!");
+            Resync_Past_Semicolon;
+
+         elsif Token in Token_Class_Declk then
+            Error_Msg_SC ("this declaration not allowed in protected body");
+            Resync_Past_Semicolon;
+
+         else
+            exit;
+         end if;
+      end loop;
+
+      return Item_List;
+   end P_Protected_Operation_Items;
+
+   ------------------------------
+   -- 9.5.2  Entry Declaration --
+   ------------------------------
+
+   --  ENTRY_DECLARATION ::=
+   --    entry DEFINING_IDENTIFIER [(DISCRETE_SUBTYPE_DEFINITION)]
+   --      PARAMETER_PROFILE;
+
+   --  The caller has checked that the initial token is ENTRY
+
+   --  Error recovery: cannot raise Error_Resync
+
+   function P_Entry_Declaration return Node_Id is
+      Decl_Node  : Node_Id;
+      Scan_State : Saved_Scan_State;
+
+   begin
+      Decl_Node := New_Node (N_Entry_Declaration, Token_Ptr);
+      Scan; -- past ENTRY
+
+      Set_Defining_Identifier (Decl_Node, P_Defining_Identifier);
+
+      --  If left paren, could be (Discrete_Subtype_Definition) or Formal_Part
+
+      if Token = Tok_Left_Paren then
+         Scan; -- past (
+
+         --  If identifier after left paren, could still be either
+
+         if Token = Tok_Identifier then
+            Save_Scan_State (Scan_State); -- at Id
+            Scan; -- past Id
+
+            --  If comma or colon after Id, must be Formal_Part
+
+            if Token = Tok_Comma or else Token = Tok_Colon then
+               Restore_Scan_State (Scan_State); -- to Id
+               Set_Parameter_Specifications (Decl_Node, P_Formal_Part);
+
+            --  Else if Id wi no comma or colon, must be discrete subtype defn
+
+            else
+               Restore_Scan_State (Scan_State); -- to Id
+               Set_Discrete_Subtype_Definition
+                 (Decl_Node, P_Discrete_Subtype_Definition);
+               T_Right_Paren;
+               Set_Parameter_Specifications (Decl_Node, P_Parameter_Profile);
+            end if;
+
+         --  If no Id, must be discrete subtype definition
+
+         else
+            Set_Discrete_Subtype_Definition
+              (Decl_Node, P_Discrete_Subtype_Definition);
+            T_Right_Paren;
+            Set_Parameter_Specifications (Decl_Node, P_Parameter_Profile);
+         end if;
+      end if;
+
+      --  Error recovery check for illegal return
+
+      if Token = Tok_Return then
+         Error_Msg_SC ("entry cannot have return value!");
+         Scan;
+         Discard_Junk_Node (P_Subtype_Indication);
+      end if;
+
+      --  Error recovery check for improper use of entry barrier in spec
+
+      if Token = Tok_When then
+         Error_Msg_SC ("barrier not allowed here (belongs in body)");
+         Scan; -- past WHEN;
+         Discard_Junk_Node (P_Expression_No_Right_Paren);
+      end if;
+
+      TF_Semicolon;
+      return Decl_Node;
+   end P_Entry_Declaration;
+
+   -----------------------------
+   -- 9.5.2  Accept Statement --
+   -----------------------------
+
+   --  ACCEPT_STATEMENT ::=
+   --    accept entry_DIRECT_NAME
+   --      [(ENTRY_INDEX)] PARAMETER_PROFILE [do
+   --        HANDLED_SEQUENCE_OF_STATEMENTS
+   --    end [entry_IDENTIFIER]];
+
+   --  The caller has checked that the initial token is ACCEPT
+
+   --  Error recovery: cannot raise Error_Resync. If an error occurs, the
+   --  scan is resynchronized past the next semicolon and control returns.
+
+   function P_Accept_Statement return Node_Id is
+      Scan_State  : Saved_Scan_State;
+      Accept_Node : Node_Id;
+      Hand_Seq    : Node_Id;
+
+   begin
+      Push_Scope_Stack;
+      Scope.Table (Scope.Last).Sloc := Token_Ptr;
+      Scope.Table (Scope.Last).Ecol := Start_Column;
+
+      Accept_Node := New_Node (N_Accept_Statement, Token_Ptr);
+      Scan; -- past ACCEPT
+      Scope.Table (Scope.Last).Labl := Token_Node;
+
+      Set_Entry_Direct_Name (Accept_Node, P_Identifier);
+
+      --  Left paren could be (Entry_Index) or Formal_Part, determine which
+
+      if Token = Tok_Left_Paren then
+         Save_Scan_State (Scan_State); -- at left paren
+         Scan; -- past left paren
+
+         --  If first token after left paren not identifier, then Entry_Index
+
+         if Token /= Tok_Identifier then
+            Set_Entry_Index (Accept_Node, P_Expression);
+            T_Right_Paren;
+            Set_Parameter_Specifications (Accept_Node, P_Parameter_Profile);
+
+         --  First token after left paren is identifier, could be either case
+
+         else -- Token = Tok_Identifier
+            Scan; -- past identifier
+
+            --  If identifier followed by comma or colon, must be Formal_Part
+
+            if Token = Tok_Comma or else Token = Tok_Colon then
+               Restore_Scan_State (Scan_State); -- to left paren
+               Set_Parameter_Specifications (Accept_Node, P_Parameter_Profile);
+
+            --  If identifier not followed by comma/colon, must be entry index
+
+            else
+               Restore_Scan_State (Scan_State); -- to left paren
+               Scan; -- past left paren (again!)
+               Set_Entry_Index (Accept_Node, P_Expression);
+               T_Right_Paren;
+               Set_Parameter_Specifications (Accept_Node, P_Parameter_Profile);
+            end if;
+         end if;
+      end if;
+
+      --  Scan out DO if present
+
+      if Token = Tok_Do then
+         Scope.Table (Scope.Last).Etyp := E_Name;
+         Scope.Table (Scope.Last).Lreq := False;
+         Scan; -- past DO
+         Hand_Seq := P_Handled_Sequence_Of_Statements;
+         Set_Handled_Statement_Sequence (Accept_Node, Hand_Seq);
+         End_Statements (Handled_Statement_Sequence (Accept_Node));
+
+         --  Exception handlers not allowed in Ada 95 node
+
+         if Present (Exception_Handlers (Hand_Seq)) then
+            if Ada_83 then
+               Error_Msg_N
+                 ("(Ada 83) exception handlers in accept not allowed",
+                  First_Non_Pragma (Exception_Handlers (Hand_Seq)));
+            end if;
+         end if;
+
+      else
+         Pop_Scope_Stack; -- discard unused entry
+         TF_Semicolon;
+      end if;
+
+      return Accept_Node;
+
+   --  If error, resynchronize past semicolon
+
+   exception
+      when Error_Resync =>
+         Resync_Past_Semicolon;
+         return Error;
+
+   end P_Accept_Statement;
+
+   ------------------------
+   -- 9.5.2  Entry Index --
+   ------------------------
+
+   --  Parsed by P_Expression (4.4)
+
+   -----------------------
+   -- 9.5.2  Entry Body --
+   -----------------------
+
+   --  ENTRY_BODY ::=
+   --    entry DEFINING_IDENTIFIER ENTRY_BODY_FORMAL_PART ENTRY_BARRIER is
+   --      DECLARATIVE_PART
+   --    begin
+   --      HANDLED_SEQUENCE_OF_STATEMENTS
+   --    end [entry_IDENTIFIER];
+
+   --  The caller has checked that the initial token is ENTRY
+
+   --  Error_Recovery: cannot raise Error_Resync
+
+   function P_Entry_Body return Node_Id is
+      Entry_Node       : Node_Id;
+      Formal_Part_Node : Node_Id;
+      Name_Node        : Node_Id;
+
+   begin
+      Push_Scope_Stack;
+      Entry_Node := New_Node (N_Entry_Body, Token_Ptr);
+      Scan; -- past ENTRY
+
+      Scope.Table (Scope.Last).Ecol := Start_Column;
+      Scope.Table (Scope.Last).Lreq := False;
+      Scope.Table (Scope.Last).Etyp := E_Name;
+
+      Name_Node := P_Defining_Identifier;
+      Set_Defining_Identifier (Entry_Node, Name_Node);
+      Scope.Table (Scope.Last).Labl := Name_Node;
+
+      Formal_Part_Node := P_Entry_Body_Formal_Part;
+      Set_Entry_Body_Formal_Part (Entry_Node, Formal_Part_Node);
+
+      Set_Condition (Formal_Part_Node, P_Entry_Barrier);
+      Parse_Decls_Begin_End (Entry_Node);
+      return Entry_Node;
+   end P_Entry_Body;
+
+   -----------------------------------
+   -- 9.5.2  Entry Body Formal Part --
+   -----------------------------------
+
+   --  ENTRY_BODY_FORMAL_PART ::=
+   --    [(ENTRY_INDEX_SPECIFICATION)] [PARAMETER_PART]
+
+   --  Error_Recovery: cannot raise Error_Resync
+
+   function P_Entry_Body_Formal_Part return Node_Id is
+      Fpart_Node : Node_Id;
+      Scan_State : Saved_Scan_State;
+
+   begin
+      Fpart_Node := New_Node (N_Entry_Body_Formal_Part, Token_Ptr);
+
+      --  See if entry index specification present, and if so parse it
+
+      if Token = Tok_Left_Paren then
+         Save_Scan_State (Scan_State); -- at left paren
+         Scan; -- past left paren
+
+         if Token = Tok_For then
+            Set_Entry_Index_Specification
+              (Fpart_Node, P_Entry_Index_Specification);
+            T_Right_Paren;
+         else
+            Restore_Scan_State (Scan_State); -- to left paren
+         end if;
+
+      --  Check for (common?) case of left paren omitted before FOR. This
+      --  is a tricky case, because the corresponding missing left paren
+      --  can cause real havoc if a formal part is present which gets
+      --  treated as part of the discrete subtype definition of the
+      --  entry index specification, so just give error and resynchronize
+
+      elsif Token = Tok_For then
+         T_Left_Paren; -- to give error message
+         Resync_To_When;
+      end if;
+
+      Set_Parameter_Specifications (Fpart_Node, P_Parameter_Profile);
+      return Fpart_Node;
+   end P_Entry_Body_Formal_Part;
+
+   --------------------------
+   -- 9.5.2  Entry Barrier --
+   --------------------------
+
+   --  ENTRY_BARRIER ::= when CONDITION
+
+   --  Error_Recovery: cannot raise Error_Resync
+
+   function P_Entry_Barrier return Node_Id is
+      Bnode : Node_Id;
+
+   begin
+      if Token = Tok_When then
+         Scan; -- past WHEN;
+         Bnode := P_Expression_No_Right_Paren;
+
+         if Token = Tok_Colon_Equal then
+            Error_Msg_SC (""":="" should be ""=""");
+            Scan;
+            Bnode := P_Expression_No_Right_Paren;
+         end if;
+
+      else
+         T_When; -- to give error message
+         Bnode := Error;
+      end if;
+
+      TF_Is;
+      return Bnode;
+   end P_Entry_Barrier;
+
+   --------------------------------------
+   -- 9.5.2  Entry Index Specification --
+   --------------------------------------
+
+   --  ENTRY_INDEX_SPECIFICATION ::=
+   --    for DEFINING_IDENTIFIER in DISCRETE_SUBTYPE_DEFINITION
+
+   --  Error recovery: can raise Error_Resync
+
+   function P_Entry_Index_Specification return Node_Id is
+      Iterator_Node : Node_Id;
+
+   begin
+      Iterator_Node := New_Node (N_Entry_Index_Specification, Token_Ptr);
+      T_For; -- past FOR
+      Set_Defining_Identifier (Iterator_Node, P_Defining_Identifier);
+      T_In;
+      Set_Discrete_Subtype_Definition
+        (Iterator_Node, P_Discrete_Subtype_Definition);
+      return Iterator_Node;
+   end P_Entry_Index_Specification;
+
+   ---------------------------------
+   -- 9.5.3  Entry Call Statement --
+   ---------------------------------
+
+   --  Parsed by P_Name (4.1). Within a select, an entry call is parsed
+   --  by P_Select_Statement (9.7)
+
+   ------------------------------
+   -- 9.5.4  Requeue Statement --
+   ------------------------------
+
+   --  REQUEUE_STATEMENT ::= requeue entry_NAME [with abort];
+
+   --  The caller has checked that the initial token is requeue
+
+   --  Error recovery: can raise Error_Resync
+
+   function P_Requeue_Statement return Node_Id is
+      Requeue_Node : Node_Id;
+
+   begin
+      Requeue_Node := New_Node (N_Requeue_Statement, Token_Ptr);
+      Scan; -- past REQUEUE
+      Set_Name (Requeue_Node, P_Name);
+
+      if Token = Tok_With then
+         Scan; -- past WITH
+         T_Abort;
+         Set_Abort_Present (Requeue_Node, True);
+      end if;
+
+      TF_Semicolon;
+      return Requeue_Node;
+   end P_Requeue_Statement;
+
+   --------------------------
+   -- 9.6  Delay Statement --
+   --------------------------
+
+   --  DELAY_STATEMENT ::=
+   --    DELAY_UNTIL_STATEMENT
+   --  | DELAY_RELATIVE_STATEMENT
+
+   --  The caller has checked that the initial token is DELAY
+
+   --  Error recovery: cannot raise Error_Resync
+
+   function P_Delay_Statement return Node_Id is
+   begin
+      Scan; -- past DELAY
+
+      --  The following check for delay until misused in Ada 83 doesn't catch
+      --  all cases, but it's good enough to catch most of them!
+
+      if Token_Name = Name_Until then
+         Check_95_Keyword (Tok_Until, Tok_Left_Paren);
+         Check_95_Keyword (Tok_Until, Tok_Identifier);
+      end if;
+
+      if Token = Tok_Until then
+         return P_Delay_Until_Statement;
+      else
+         return P_Delay_Relative_Statement;
+      end if;
+   end P_Delay_Statement;
+
+   --------------------------------
+   -- 9.6  Delay Until Statement --
+   --------------------------------
+
+   --  DELAY_UNTIL_STATEMENT ::= delay until delay_EXPRESSION;
+
+   --  The caller has checked that the initial token is DELAY, scanned it
+   --  out and checked that the current token is UNTIL
+
+   --  Error recovery: cannot raise Error_Resync
+
+   function P_Delay_Until_Statement return Node_Id is
+      Delay_Node : Node_Id;
+
+   begin
+      Delay_Node := New_Node (N_Delay_Until_Statement, Prev_Token_Ptr);
+      Scan; -- past UNTIL
+      Set_Expression (Delay_Node, P_Expression_No_Right_Paren);
+      TF_Semicolon;
+      return Delay_Node;
+   end P_Delay_Until_Statement;
+
+   -----------------------------------
+   -- 9.6  Delay Relative Statement --
+   -----------------------------------
+
+   --  DELAY_RELATIVE_STATEMENT ::= delay delay_EXPRESSION;
+
+   --  The caller has checked that the initial token is DELAY, scanned it
+   --  out and determined that the current token is not UNTIL
+
+   --  Error recovery: cannot raise Error_Resync
+
+   function P_Delay_Relative_Statement return Node_Id is
+      Delay_Node : Node_Id;
+
+   begin
+      Delay_Node := New_Node (N_Delay_Relative_Statement, Prev_Token_Ptr);
+      Set_Expression (Delay_Node, P_Expression_No_Right_Paren);
+      Check_Simple_Expression_In_Ada_83 (Expression (Delay_Node));
+      TF_Semicolon;
+      return Delay_Node;
+   end P_Delay_Relative_Statement;
+
+   ---------------------------
+   -- 9.7  Select Statement --
+   ---------------------------
+
+   --  SELECT_STATEMENT ::=
+   --    SELECTIVE_ACCEPT
+   --  | TIMED_ENTRY_CALL
+   --  | CONDITIONAL_ENTRY_CALL
+   --  | ASYNCHRONOUS_SELECT
+
+   --  SELECTIVE_ACCEPT ::=
+   --    select
+   --      [GUARD]
+   --        SELECT_ALTERNATIVE
+   --    {or
+   --      [GUARD]
+   --        SELECT_ALTERNATIVE
+   --    [else
+   --      SEQUENCE_OF_STATEMENTS]
+   --    end select;
+
+   --  GUARD ::= when CONDITION =>
+
+   --  Note: the guard preceding a select alternative is included as part
+   --  of the node generated for a selective accept alternative.
+
+   --  SELECT_ALTERNATIVE ::=
+   --    ACCEPT_ALTERNATIVE
+   --  | DELAY_ALTERNATIVE
+   --  | TERMINATE_ALTERNATIVE
+
+   --  TIMED_ENTRY_CALL ::=
+   --    select
+   --      ENTRY_CALL_ALTERNATIVE
+   --    or
+   --      DELAY_ALTERNATIVE
+   --    end select;
+
+   --  CONDITIONAL_ENTRY_CALL ::=
+   --    select
+   --      ENTRY_CALL_ALTERNATIVE
+   --    else
+   --      SEQUENCE_OF_STATEMENTS
+   --    end select;
+
+   --  ENTRY_CALL_ALTERNATIVE ::=
+   --    ENTRY_CALL_STATEMENT [SEQUENCE_OF_STATEMENTS]
+
+   --  ASYNCHRONOUS_SELECT ::=
+   --    select
+   --      TRIGGERING_ALTERNATIVE
+   --    then abort
+   --      ABORTABLE_PART
+   --    end select;
+
+   --  TRIGGERING_ALTERNATIVE ::=
+   --    TRIGGERING_STATEMENT [SEQUENCE_OF_STATEMENTS]
+
+   --  TRIGGERING_STATEMENT ::= ENTRY_CALL_STATEMENT | DELAY_STATEMENT
+
+   --  The caller has checked that the initial token is SELECT
+
+   --  Error recovery: can raise Error_Resync
+
+   function P_Select_Statement return Node_Id is
+      Select_Node    : Node_Id;
+      Select_Sloc    : Source_Ptr;
+      Stmnt_Sloc     : Source_Ptr;
+      Ecall_Node     : Node_Id;
+      Alternative    : Node_Id;
+      Select_Pragmas : List_Id;
+      Alt_Pragmas    : List_Id;
+      Statement_List : List_Id;
+      Alt_List       : List_Id;
+      Cond_Expr      : Node_Id;
+      Delay_Stmnt    : Node_Id;
+
+   begin
+      Push_Scope_Stack;
+      Scope.Table (Scope.Last).Etyp := E_Select;
+      Scope.Table (Scope.Last).Ecol := Start_Column;
+      Scope.Table (Scope.Last).Sloc := Token_Ptr;
+      Scope.Table (Scope.Last).Labl := Error;
+
+      Select_Sloc := Token_Ptr;
+      Scan; -- past SELECT
+      Stmnt_Sloc := Token_Ptr;
+      Select_Pragmas := P_Pragmas_Opt;
+
+      --  If first token after select is designator, then we have an entry
+      --  call, which must be the start of a conditional entry call, timed
+      --  entry call or asynchronous select
+
+      if Token in Token_Class_Desig then
+
+         --  Scan entry call statement
+
+         begin
+            Ecall_Node := P_Name;
+
+            --  ??  The following two clauses exactly parallel code in ch5
+            --      and should be commoned sometime
+
+            if Nkind (Ecall_Node) = N_Indexed_Component then
+               declare
+                  Prefix_Node : Node_Id := Prefix (Ecall_Node);
+                  Exprs_Node  : List_Id := Expressions (Ecall_Node);
+               begin
+                  Change_Node (Ecall_Node, N_Procedure_Call_Statement);
+                  Set_Name (Ecall_Node, Prefix_Node);
+                  Set_Parameter_Associations (Ecall_Node, Exprs_Node);
+               end;
+
+            elsif Nkind (Ecall_Node) = N_Function_Call then
+               declare
+                  Fname_Node  : Node_Id := Name (Ecall_Node);
+                  Params_List : List_Id := Parameter_Associations (Ecall_Node);
+
+               begin
+                  Change_Node (Ecall_Node, N_Procedure_Call_Statement);
+                  Set_Name (Ecall_Node, Fname_Node);
+                  Set_Parameter_Associations (Ecall_Node, Params_List);
+               end;
+
+            elsif Nkind (Ecall_Node) = N_Identifier
+              or else Nkind (Ecall_Node) = N_Selected_Component
+            then
+               --  Case of a call to a parameterless entry.
+
+               declare
+                  C_Node : constant Node_Id :=
+                         New_Node (N_Procedure_Call_Statement, Stmnt_Sloc);
+               begin
+                  Set_Name (C_Node, Ecall_Node);
+                  Set_Parameter_Associations (C_Node, No_List);
+                  Ecall_Node := C_Node;
+               end;
+            end if;
+
+            TF_Semicolon;
+
+         exception
+            when Error_Resync =>
+               Resync_Past_Semicolon;
+               return Error;
+         end;
+
+         Statement_List := P_Sequence_Of_Statements (SS_Eltm_Ortm_Tatm);
+
+         --  OR follows, we have a timed entry call
+
+         if Token = Tok_Or then
+            Scan; -- past OR
+            Alt_Pragmas := P_Pragmas_Opt;
+
+            Select_Node := New_Node (N_Timed_Entry_Call, Select_Sloc);
+            Set_Entry_Call_Alternative (Select_Node,
+              Make_Entry_Call_Alternative (Stmnt_Sloc,
+                Entry_Call_Statement => Ecall_Node,
+                Pragmas_Before       => Select_Pragmas,
+                Statements           => Statement_List));
+
+            --  Only possibility is delay alternative. If we have anything
+            --  else, give message, and treat as conditional entry call.
+
+            if Token /= Tok_Delay then
+               Error_Msg_SC
+                 ("only allowed alternative in timed entry call is delay!");
+               Discard_Junk_List (P_Sequence_Of_Statements (SS_Sreq));
+               Set_Delay_Alternative (Select_Node, Error);
+
+            else
+               Set_Delay_Alternative (Select_Node, P_Delay_Alternative);
+               Set_Pragmas_Before
+                 (Delay_Alternative (Select_Node), Alt_Pragmas);
+            end if;
+
+         --  ELSE follows, we have a conditional entry call
+
+         elsif Token = Tok_Else then
+            Scan; -- past ELSE
+            Select_Node := New_Node (N_Conditional_Entry_Call, Select_Sloc);
+
+            Set_Entry_Call_Alternative (Select_Node,
+              Make_Entry_Call_Alternative (Stmnt_Sloc,
+                Entry_Call_Statement => Ecall_Node,
+                Pragmas_Before       => Select_Pragmas,
+                Statements           => Statement_List));
+
+            Set_Else_Statements
+              (Select_Node, P_Sequence_Of_Statements (SS_Sreq));
+
+         --  Only remaining case is THEN ABORT (asynchronous select)
+
+         elsif Token = Tok_Abort then
+            Select_Node :=
+              Make_Asynchronous_Select (Select_Sloc,
+                Triggering_Alternative =>
+                  Make_Triggering_Alternative (Stmnt_Sloc,
+                    Triggering_Statement => Ecall_Node,
+                    Pragmas_Before       => Select_Pragmas,
+                    Statements           => Statement_List),
+                Abortable_Part => P_Abortable_Part);
+
+         --  Else error
+
+         else
+            if Ada_83 then
+               Error_Msg_BC ("OR or ELSE expected");
+            else
+               Error_Msg_BC ("OR or ELSE or THEN ABORT expected");
+            end if;
+
+            Select_Node := Error;
+         end if;
+
+         End_Statements;
+
+      --  Here we have a selective accept or an an asynchronous select (first
+      --  token after SELECT is other than a designator token).
+
+      else
+         --  If we have delay with no guard, could be asynchronous select
+
+         if Token = Tok_Delay then
+            Delay_Stmnt := P_Delay_Statement;
+            Statement_List := P_Sequence_Of_Statements (SS_Eltm_Ortm_Tatm);
+
+            --  Asynchronous select
+
+            if Token = Tok_Abort then
+               Select_Node :=
+                 Make_Asynchronous_Select (Select_Sloc,
+                   Triggering_Alternative =>
+                     Make_Triggering_Alternative (Stmnt_Sloc,
+                       Triggering_Statement => Delay_Stmnt,
+                       Pragmas_Before       => Select_Pragmas,
+                       Statements           => Statement_List),
+                     Abortable_Part => P_Abortable_Part);
+
+               End_Statements;
+               return Select_Node;
+
+            --  Delay which was not an asynchronous select. Must be a selective
+            --  accept, and since at least one accept statement is required,
+            --  we must have at least one OR phrase present.
+
+            else
+               Alt_List := New_List (
+                 Make_Delay_Alternative (Stmnt_Sloc,
+                   Delay_Statement => Delay_Stmnt,
+                   Pragmas_Before  => Select_Pragmas,
+                   Statements      => Statement_List));
+               T_Or;
+               Alt_Pragmas := P_Pragmas_Opt;
+            end if;
+
+         --  If not a delay statement, then must be another possibility for
+         --  a selective accept alternative, or perhaps a guard is present
+
+         else
+            Alt_List := New_List;
+            Alt_Pragmas := Select_Pragmas;
+         end if;
+
+         Select_Node := New_Node (N_Selective_Accept, Select_Sloc);
+         Set_Select_Alternatives (Select_Node, Alt_List);
+
+         --  Scan out selective accept alternatives. On entry to this loop,
+         --  we are just past a SELECT or OR token, and any pragmas that
+         --  immediately follow the SELECT or OR are in Alt_Pragmas.
+
+         loop
+            if Token = Tok_When then
+
+               if Present (Alt_Pragmas) then
+                  Error_Msg_SC ("pragmas may not precede guard");
+               end if;
+
+               Scan; --  past WHEN
+               Cond_Expr := P_Expression_No_Right_Paren;
+               T_Arrow;
+               Alt_Pragmas := P_Pragmas_Opt;
+
+            else
+               Cond_Expr := Empty;
+            end if;
+
+            if Token = Tok_Accept then
+               Alternative := P_Accept_Alternative;
+
+               --  Check for junk attempt at asynchronous select using
+               --  an Accept alternative as the triggering statement
+
+               if Token = Tok_Abort
+                 and then Is_Empty_List (Alt_List)
+                 and then No (Cond_Expr)
+               then
+                  Error_Msg
+                    ("triggering statement must be entry call or delay",
+                     Sloc (Alternative));
+                  Scan; -- past junk ABORT
+                  Discard_Junk_List (P_Sequence_Of_Statements (SS_Sreq));
+                  End_Statements;
+                  return Error;
+               end if;
+
+            elsif Token = Tok_Delay then
+               Alternative := P_Delay_Alternative;
+
+            elsif Token = Tok_Terminate then
+               Alternative := P_Terminate_Alternative;
+
+            else
+               Error_Msg_SC
+                 ("Select alternative (ACCEPT, ABORT, DELAY) expected");
+               Alternative := Error;
+
+               if Token = Tok_Semicolon then
+                  Scan; -- past junk semicolon
+               end if;
+            end if;
+
+            --  THEN ABORT at this stage is just junk
+
+            if Token = Tok_Abort then
+               Error_Msg_SP ("misplaced `THEN ABORT`");
+               Scan; -- past junk ABORT
+               Discard_Junk_List (P_Sequence_Of_Statements (SS_Sreq));
+               End_Statements;
+               return Error;
+
+            else
+               if Alternative /= Error then
+                  Set_Condition (Alternative, Cond_Expr);
+                  Set_Pragmas_Before (Alternative, Alt_Pragmas);
+                  Append (Alternative, Alt_List);
+               end if;
+
+               exit when Token /= Tok_Or;
+            end if;
+
+            T_Or;
+            Alt_Pragmas := P_Pragmas_Opt;
+         end loop;
+
+         if Token = Tok_Else then
+            Scan; -- past ELSE
+            Set_Else_Statements
+              (Select_Node, P_Sequence_Of_Statements (SS_Ortm_Sreq));
+
+            if Token = Tok_Or then
+               Error_Msg_SC ("select alternative cannot follow else part!");
+            end if;
+         end if;
+
+         End_Statements;
+      end if;
+
+      return Select_Node;
+   end P_Select_Statement;
+
+   -----------------------------
+   -- 9.7.1  Selective Accept --
+   -----------------------------
+
+   --  Parsed by P_Select_Statement (9.7)
+
+   ------------------
+   -- 9.7.1  Guard --
+   ------------------
+
+   --  Parsed by P_Select_Statement (9.7)
+
+   -------------------------------
+   -- 9.7.1  Select Alternative --
+   -------------------------------
+
+   --  SELECT_ALTERNATIVE ::=
+   --    ACCEPT_ALTERNATIVE
+   --  | DELAY_ALTERNATIVE
+   --  | TERMINATE_ALTERNATIVE
+
+   --  Note: the guard preceding a select alternative is included as part
+   --  of the node generated for a selective accept alternative.
+
+   --  Error recovery: cannot raise Error_Resync
+
+   -------------------------------
+   -- 9.7.1  Accept Alternative --
+   -------------------------------
+
+   --  ACCEPT_ALTERNATIVE ::=
+   --    ACCEPT_STATEMENT [SEQUENCE_OF_STATEMENTS]
+
+   --  Error_Recovery: Cannot raise Error_Resync
+
+   --  Note: the caller is responsible for setting the Pragmas_Before
+   --  field of the returned N_Terminate_Alternative node.
+
+   function P_Accept_Alternative return Node_Id is
+      Accept_Alt_Node : Node_Id;
+
+   begin
+      Accept_Alt_Node := New_Node (N_Accept_Alternative, Token_Ptr);
+      Set_Accept_Statement (Accept_Alt_Node, P_Accept_Statement);
+
+      --  Note: the reason that we accept THEN ABORT as a terminator for
+      --  the sequence of statements is for error recovery which allows
+      --  for misuse of an accept statement as a triggering statememt.
+
+      Set_Statements
+        (Accept_Alt_Node, P_Sequence_Of_Statements (SS_Eltm_Ortm_Tatm));
+      return Accept_Alt_Node;
+   end P_Accept_Alternative;
+
+   ------------------------------
+   -- 9.7.1  Delay Alternative --
+   ------------------------------
+
+   --  DELAY_ALTERNATIVE ::=
+   --    DELAY_STATEMENT [SEQUENCE_OF_STATEMENTS]
+
+   --  Error_Recovery: Cannot raise Error_Resync
+
+   --  Note: the caller is responsible for setting the Pragmas_Before
+   --  field of the returned N_Terminate_Alternative node.
+
+   function P_Delay_Alternative return Node_Id is
+      Delay_Alt_Node : Node_Id;
+
+   begin
+      Delay_Alt_Node := New_Node (N_Delay_Alternative, Token_Ptr);
+      Set_Delay_Statement (Delay_Alt_Node, P_Delay_Statement);
+
+      --  Note: the reason that we accept THEN ABORT as a terminator for
+      --  the sequence of statements is for error recovery which allows
+      --  for misuse of an accept statement as a triggering statememt.
+
+      Set_Statements
+        (Delay_Alt_Node, P_Sequence_Of_Statements (SS_Eltm_Ortm_Tatm));
+      return Delay_Alt_Node;
+   end P_Delay_Alternative;
+
+   ----------------------------------
+   -- 9.7.1  Terminate Alternative --
+   ----------------------------------
+
+   --  TERMINATE_ALTERNATIVE ::= terminate;
+
+   --  Error_Recovery: Cannot raise Error_Resync
+
+   --  Note: the caller is responsible for setting the Pragmas_Before
+   --  field of the returned N_Terminate_Alternative node.
+
+   function P_Terminate_Alternative return Node_Id is
+      Terminate_Alt_Node : Node_Id;
+
+   begin
+      Terminate_Alt_Node := New_Node (N_Terminate_Alternative, Token_Ptr);
+      Scan; -- past TERMINATE
+      TF_Semicolon;
+
+      --  For all other select alternatives, the sequence of statements
+      --  after the alternative statement will swallow up any pragmas
+      --  coming in this position. But the terminate alternative has no
+      --  sequence of statements, so the pragmas here must be treated
+      --  specially.
+
+      Set_Pragmas_After (Terminate_Alt_Node, P_Pragmas_Opt);
+      return Terminate_Alt_Node;
+   end P_Terminate_Alternative;
+
+   -----------------------------
+   -- 9.7.2  Timed Entry Call --
+   -----------------------------
+
+   --  Parsed by P_Select_Statement (9.7)
+
+   -----------------------------------
+   -- 9.7.2  Entry Call Alternative --
+   -----------------------------------
+
+   --  Parsed by P_Select_Statement (9.7)
+
+   -----------------------------------
+   -- 9.7.3  Conditional Entry Call --
+   -----------------------------------
+
+   --  Parsed by P_Select_Statement (9.7)
+
+   --------------------------------
+   -- 9.7.4  Asynchronous Select --
+   --------------------------------
+
+   --  Parsed by P_Select_Statement (9.7)
+
+   -----------------------------------
+   -- 9.7.4  Triggering Alternative --
+   -----------------------------------
+
+   --  Parsed by P_Select_Statement (9.7)
+
+   ---------------------------------
+   -- 9.7.4  Triggering Statement --
+   ---------------------------------
+
+   --  Parsed by P_Select_Statement (9.7)
+
+   ---------------------------
+   -- 9.7.4  Abortable Part --
+   ---------------------------
+
+   --  ABORTABLE_PART ::= SEQUENCE_OF_STATEMENTS
+
+   --  The caller has verified that THEN ABORT is present, and Token is
+   --  pointing to the ABORT on entry (or if not, then we have an error)
+
+   --  Error recovery: cannot raise Error_Resync
+
+   function P_Abortable_Part return Node_Id is
+      Abortable_Part_Node : Node_Id;
+
+   begin
+      Abortable_Part_Node := New_Node (N_Abortable_Part, Token_Ptr);
+      T_Abort; -- scan past ABORT
+
+      if Ada_83 then
+         Error_Msg_SP ("(Ada 83) asynchronous select not allowed!");
+      end if;
+
+      Set_Statements (Abortable_Part_Node, P_Sequence_Of_Statements (SS_Sreq));
+      return Abortable_Part_Node;
+   end P_Abortable_Part;
+
+   --------------------------
+   -- 9.8  Abort Statement --
+   --------------------------
+
+   --  ABORT_STATEMENT ::= abort task_NAME {, task_NAME};
+
+   --  The caller has checked that the initial token is ABORT
+
+   --  Error recovery: cannot raise Error_Resync
+
+   function P_Abort_Statement return Node_Id is
+      Abort_Node : Node_Id;
+
+   begin
+      Abort_Node := New_Node (N_Abort_Statement, Token_Ptr);
+      Scan; -- past ABORT
+      Set_Names (Abort_Node, New_List);
+
+      loop
+         Append (P_Name, Names (Abort_Node));
+         exit when Token /= Tok_Comma;
+         Scan; -- past comma
+      end loop;
+
+      TF_Semicolon;
+      return Abort_Node;
+   end P_Abort_Statement;
+
+end Ch9;
diff --git a/gcc/ada/par-endh.adb b/gcc/ada/par-endh.adb
new file mode 100644 (file)
index 0000000..fa5b8c2
--- /dev/null
@@ -0,0 +1,1191 @@
+------------------------------------------------------------------------------
+--                                                                          --
+--                         GNAT COMPILER COMPONENTS                         --
+--                                                                          --
+--                             P A R . E N D H                              --
+--                                                                          --
+--                                 B o d y                                  --
+--                                                                          --
+--                            $Revision: 1.61 $
+--                                                                          --
+--          Copyright (C) 1992-2001, Free Software Foundation, Inc.         --
+--                                                                          --
+-- GNAT is free software;  you can  redistribute it  and/or modify it under --
+-- terms of the  GNU General Public License as published  by the Free Soft- --
+-- ware  Foundation;  either version 2,  or (at your option) any later ver- --
+-- sion.  GNAT is distributed in the hope that it will be useful, but WITH- --
+-- OUT 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  distributed with GNAT;  see file COPYING.  If not, write --
+-- to  the Free Software Foundation,  59 Temple Place - Suite 330,  Boston, --
+-- MA 02111-1307, USA.                                                      --
+--                                                                          --
+-- GNAT was originally developed  by the GNAT team at  New York University. --
+-- It is now maintained by Ada Core Technologies Inc (http://www.gnat.com). --
+--                                                                          --
+------------------------------------------------------------------------------
+
+with Stringt; use Stringt;
+with Uintp;   use Uintp;
+
+with GNAT.Spelling_Checker; use GNAT.Spelling_Checker;
+
+separate (Par)
+package body Endh is
+
+   ----------------
+   -- Local Data --
+   ----------------
+
+   type End_Action_Type is (
+   --  Type used to describe the result of the Pop_End_Context call
+
+      Accept_As_Scanned,
+      --  Current end sequence is entirely c correct. In this case Token and
+      --  the scan pointer are left pointing past the end sequence (i.e. they
+      --  are unchanged from the values set on entry to Pop_End_Context).
+
+      Insert_And_Accept,
+      --  Current end sequence is to be left in place to satisfy some outer
+      --  scope. Token and the scan pointer are set to point to the end
+      --  token, and should be left there. A message has been generated
+      --  indicating a missing end sequence. This status is also used for
+      --  the case when no end token is present.
+
+      Skip_And_Accept,
+      --  The end sequence is incorrect (and an error message has been
+      --  posted), but it will still be accepted. In this case Token and
+      --  the scan pointer point back to the end token, and the caller
+      --  should skip past the end sequence before proceeding.
+
+      Skip_And_Reject);
+      --  The end sequence is judged to belong to an unrecognized inner
+      --  scope. An appropriate message has been issued and the caller
+      --  should skip past the end sequence and then proceed as though
+      --  no end sequence had been encountered.
+
+   End_Action : End_Action_Type;
+   --  The variable set by Pop_End_Context call showing which of the four
+   --  decisions described above is judged the best.
+
+   End_Sloc : Source_Ptr;
+   --  Source location of END token
+
+   End_OK : Boolean;
+   --  Set False if error is found in END line
+
+   End_Column : Column_Number;
+   --  Column of END line
+
+   End_Type : SS_End_Type;
+   --  Type of END expected. The special value E_Dummy is set to indicate that
+   --  no END token was present (so a missing END inserted message is needed)
+
+   End_Labl : Node_Id;
+   --  Node_Id value for explicit name on END line, or for compiler supplied
+   --  name in the case where an optional name is not given. Empty if no name
+   --  appears. If non-empty, then it is either an N_Designator node for a
+   --  child unit or a node with a Chars field identifying the actual label.
+
+   End_Labl_Present : Boolean;
+   --  Indicates that the value in End_Labl was for an explicit label.
+
+   Syntax_OK : Boolean;
+   --  Set True if the entry is syntactically correct
+
+   Token_OK : Boolean;
+   --  Set True if the keyword in the END sequence matches, or if neither
+   --  the END sequence nor the END stack entry has a keyword.
+
+   Label_OK : Boolean;
+   --  Set True if both the END sequence and the END stack entry contained
+   --  labels (other than No_Name or Error_Name) and the labels matched.
+   --  This is a stronger condition than SYNTAX_OK, since it means that a
+   --  label was present, even in a case where it was optional. Note that
+   --  the case of no label required, and no label present does NOT set
+   --  Label_OK to True, it is True only if a positive label match is found.
+
+   Column_OK : Boolean;
+   --  Column_OK is set True if the END sequence appears in the expected column
+
+   Scan_State : Saved_Scan_State;
+   --  Save state at start of END sequence, in case we decide not to eat it up
+
+   -----------------------
+   -- Local Subprograms --
+   -----------------------
+
+   procedure Evaluate_End_Entry (SS_Index : Int);
+   --  Compare scanned END entry (as recorded by a prior call to P_End_Scan)
+   --  with a specified entry in the scope stack (the single parameter is the
+   --  entry index in the scope stack). Note that Scan is not called. The above
+   --  variables xxx_OK are set to indicate the result of the evaluation.
+
+   procedure Output_End_Deleted;
+   --  Output a message complaining that the current END structure does not
+   --  match anything and is being deleted.
+
+   procedure Output_End_Expected (Ins : Boolean);
+   --  Output a message at the start of the current token which is always an
+   --  END, complaining that the END is not of the right form. The message
+   --  indicates the expected form. The information for the message is taken
+   --  from the top entry in the scope stack. The Ins parameter is True if
+   --  an end is being inserted, and false if an existing end is being
+   --  replaced. Note that in the case of a suspicious IS for the Ins case,
+   --  we do not output the message, but instead simply mark the scope stack
+   --  entry as being a case of a bad IS.
+
+   procedure Output_End_Missing;
+   --  Output a message just before the current token, complaining that the
+   --  END is not of the right form. The message indicates the expected form.
+   --  The information for the message is taken from the top entry in the
+   --  scope stack. Note that in the case of a suspicious IS, we do not output
+   --  the message, but instead simply mark the scope stack entry as a bad IS.
+
+   procedure Pop_End_Context;
+   --  Pop_End_Context is called after processing a construct, to pop the
+   --  top entry off the end stack. It decides on the appropriate action to
+   --  to take, signalling the result by setting End_Action as described in
+   --  the global variable section.
+
+   function Same_Label (Label1, Label2 : Node_Id) return Boolean;
+   --  This function compares the two names associated with the given nodes.
+   --  If they are both simple (i.e. have Chars fields), then they have to
+   --  be the same name. Otherwise they must both be N_Selected_Component
+   --  nodes, referring to the same set of names, or Label1 is an N_Designator
+   --  referring to the same set of names as the N_Defining_Program_Unit_Name
+   --  in Label2. Any other combination returns False. This routine is used
+   --  to compare the End_Labl scanned from the End line with the saved label
+   --  value in the scope stack.
+
+   ---------------
+   -- Check_End --
+   ---------------
+
+   function Check_End return Boolean is
+      Name_On_Separate_Line : Boolean;
+      --  Set True if the name on an END line is on a separate source line
+      --  from the END. This is highly suspicious, but is allowed. The point
+      --  is that we want to make sure that we don't just have a missing
+      --  semicolon misleading us into swallowing an identifier from the
+      --  following line.
+
+      Name_Scan_State : Saved_Scan_State;
+      --  Save state at start of name if Name_On_Separate_Line is TRUE
+
+      Span_Node : constant Node_Id := Scope.Table (Scope.Last).Node;
+
+   begin
+      End_Labl_Present := False;
+      End_Labl := Empty;
+
+      --  Our first task is to scan out the END sequence if one is present.
+      --  If none is present, signal by setting End_Type to E_Dummy.
+
+      if Token /= Tok_End then
+         End_Type := E_Dummy;
+
+      else
+         Save_Scan_State (Scan_State); -- at END
+         End_Sloc := Token_Ptr;
+         End_Column := Start_Column;
+         End_OK := True;
+         Scan; -- past END
+
+         --  Set End_Span if expected. note that this will be useless
+         --  if we do not have the right ending keyword, but in this
+         --  case we have a malformed program anyway, and the setting
+         --  of End_Span will simply be unreliable in this case anyway.
+
+         if Present (Span_Node) then
+            Set_End_Location (Span_Node, Token_Ptr);
+         end if;
+
+         --  Cases of keywords where no label is allowed
+
+         if Token = Tok_Case then
+            End_Type := E_Case;
+            Scan; -- past CASE
+
+         elsif Token = Tok_If then
+            End_Type := E_If;
+            Scan; -- past IF
+
+         elsif Token = Tok_Record then
+            End_Type := E_Record;
+            Scan; -- past RECORD
+
+         elsif Token = Tok_Select then
+            End_Type := E_Select;
+            Scan; -- past SELECT
+
+         --  Cases which do allow labels
+
+         else
+            --  LOOP
+
+            if Token = Tok_Loop then
+               Scan; -- past LOOP
+               End_Type := E_Loop;
+
+            --  FOR or WHILE allowed (signalling error) to substitute for LOOP
+            --  if on the same line as the END
+
+            elsif (Token = Tok_For or else Token = Tok_While)
+              and then not Token_Is_At_Start_Of_Line
+            then
+               Scan; -- past FOR or WHILE
+               End_Type := E_Loop;
+               End_OK := False;
+
+            --  Cases with no keyword
+
+            else
+               End_Type := E_Name;
+            end if;
+
+            --  Now see if a name is present
+
+            if Token = Tok_Identifier or else
+               Token = Tok_String_Literal or else
+               Token = Tok_Operator_Symbol
+            then
+               if Token_Is_At_Start_Of_Line then
+                  Name_On_Separate_Line := True;
+                  Save_Scan_State (Name_Scan_State);
+               else
+                  Name_On_Separate_Line := False;
+               end if;
+
+               End_Labl := P_Designator;
+               End_Labl_Present := True;
+
+               --  We have now scanned out a name. Here is where we do a check
+               --  to catch the cases like:
+               --
+               --    end loop
+               --    X := 3;
+               --
+               --  where the missing semicolon might make us swallow up the X
+               --  as a bogus end label. In a situation like this, where the
+               --  apparent name is on a separate line, we accept it only if
+               --  it matches the label and is followed by a semicolon.
+
+               if Name_On_Separate_Line then
+                  if Token /= Tok_Semicolon or else
+                    not Same_Label (End_Labl, Scope.Table (Scope.Last).Labl)
+                  then
+                     Restore_Scan_State (Name_Scan_State);
+                     End_Labl := Empty;
+                     End_Labl_Present := False;
+                  end if;
+               end if;
+
+            --  Here for case of name allowed, but no name present. We will
+            --  supply an implicit matching name, with source location set
+            --  to the scan location past the END token.
+
+            else
+               End_Labl := Scope.Table (Scope.Last).Labl;
+
+               if End_Labl > Empty_Or_Error then
+
+                  --  The task here is to construct a designator from the
+                  --  opening label, with the components all marked as not
+                  --  from source, and Is_End_Label set in the identifier
+                  --  or operator symbol. The location for all components
+                  --  is the curent token location.
+
+                  --  Case of child unit name
+
+                  if Nkind (End_Labl) = N_Defining_Program_Unit_Name then
+                     declare
+                        Eref : constant Node_Id :=
+                                 Make_Identifier (Token_Ptr,
+                                   Chars =>
+                                     Chars (Defining_Identifier (End_Labl)));
+
+                        function Copy_Name (N : Node_Id) return Node_Id;
+                        --  Copies a selected component or identifier
+
+                        function Copy_Name (N : Node_Id) return Node_Id is
+                           R : Node_Id;
+
+                        begin
+                           if Nkind (N) = N_Selected_Component then
+                              return
+                                Make_Selected_Component (Token_Ptr,
+                                  Prefix        =>
+                                    Copy_Name (Prefix (N)),
+                                  Selector_Name =>
+                                    Copy_Name (Selector_Name (N)));
+
+                           else
+                              R :=
+                                Make_Identifier (Token_Ptr,
+                                  Chars => Chars (N));
+                              Set_Comes_From_Source (N, False);
+                              return R;
+                           end if;
+                        end Copy_Name;
+
+                     begin
+                        Set_Comes_From_Source (Eref, False);
+
+                        End_Labl :=
+                          Make_Designator (Token_Ptr,
+                            Name       => Copy_Name (Name (End_Labl)),
+                            Identifier => Eref);
+                     end;
+
+                  --  Simple identifier case
+
+                  elsif Nkind (End_Labl) = N_Defining_Identifier
+                    or else Nkind (End_Labl) = N_Identifier
+                  then
+                     End_Labl :=
+                       Make_Identifier (Token_Ptr,
+                         Chars => Chars (End_Labl));
+
+                  elsif Nkind (End_Labl) = N_Defining_Operator_Symbol
+                    or else Nkind (End_Labl) = N_Operator_Symbol
+                  then
+                     Get_Decoded_Name_String (Chars (End_Labl));
+
+                     End_Labl :=
+                       Make_Operator_Symbol (Token_Ptr,
+                         Chars  => Chars (End_Labl),
+                         Strval => String_From_Name_Buffer);
+                  end if;
+
+                  Set_Comes_From_Source (End_Labl, False);
+                  End_Labl_Present := False;
+
+                  --  Do style check for missing label
+
+                  if Style_Check
+                    and then End_Type = E_Name
+                    and then Present (Scope.Table (Scope.Last).Labl)
+                  then
+                     Style.No_End_Name (Scope.Table (Scope.Last).Labl);
+                  end if;
+               end if;
+            end if;
+         end if;
+
+         --  Except in case of END RECORD, semicolon must follow. For END
+         --  RECORD, a semicolon does follow, but it is part of a higher level
+         --  construct. In any case, a missing semicolon is not serious enough
+         --  to consider the END statement to be bad in the sense that we
+         --  are dealing with (i.e. to be suspicious that it is not in fact
+         --  the END statement we are looking for!)
+
+         if End_Type /= E_Record then
+            if Token = Tok_Semicolon then
+               T_Semicolon;
+
+            --  Semicolon is missing. If the missing semicolon is at the end
+            --  of the line, i.e. we are at the start of the line now, then
+            --  a missing semicolon gets flagged, but is not serious enough
+            --  to consider the END statement to be bad in the sense that we
+            --  are dealing with (i.e. to be suspicious that this END is not
+            --  the END statement we are looking for).
+
+            --  Similarly, if we are at a colon, we flag it but a colon for
+            --  a semicolon is not serious enough to consider the END to be
+            --  incorrect. Same thing for a period in place of a semicolon.
+
+            elsif Token_Is_At_Start_Of_Line
+              or else Token = Tok_Colon
+              or else Token = Tok_Dot
+            then
+               T_Semicolon;
+
+            --  If the missing semicolon is not at the start of the line,
+            --  then we do consider the END line to be dubious in this sense.
+
+            else
+               End_OK := False;
+            end if;
+         end if;
+      end if;
+
+      --  Now we call the Pop_End_Context routine to get a recommendation
+      --  as to what should be done with the END sequence we have scanned.
+
+      Pop_End_Context;
+
+      --  Remaining action depends on End_Action set by Pop_End_Context
+
+      case End_Action is
+
+         --  Accept_As_Scanned. In this case, Pop_End_Context left Token
+         --  pointing past the last token of a syntactically correct END
+
+         when Accept_As_Scanned =>
+
+            --  Syntactically correct included the possibility of a missing
+            --  semicolon. If we do have a missing semicolon, then we have
+            --  already given a message, but now we scan out possible rubbish
+            --  on the same line as the END
+
+            while not Token_Is_At_Start_Of_Line
+              and then Prev_Token /= Tok_Record
+              and then Prev_Token /= Tok_Semicolon
+              and then Token /= Tok_End
+              and then Token /= Tok_EOF
+            loop
+               Scan; -- past junk
+            end loop;
+
+            return True;
+
+         --  Insert_And_Accept. In this case, Pop_End_Context has reset Token
+         --  to point to the start of the END sequence, and recommends that it
+         --  be left in place to satisfy an outer scope level END. This means
+         --  that we proceed as though an END were present, and leave the scan
+         --  pointer unchanged.
+
+         when Insert_And_Accept =>
+            return True;
+
+         --  Skip_And_Accept. In this case, Pop_End_Context has reset Token
+         --  to point to the start of the END sequence. This END sequence is
+         --  syntactically incorrect, and an appropriate error message has
+         --  already been posted. Pop_End_Context recommends accepting the
+         --  END sequence as the one we want, so we skip past it and then
+         --  proceed as though an END were present.
+
+         when Skip_And_Accept =>
+            End_Skip;
+            return True;
+
+         --  Skip_And_Reject. In this case, Pop_End_Context has reset Token
+         --  to point to the start of the END sequence. This END sequence is
+         --  syntactically incorrect, and an appropriate error message has
+         --  already been posted. Pop_End_Context recommends entirely ignoring
+         --  this END sequence, so we skip past it and then return False, since
+         --  as far as the caller is concerned, no END sequence is present.
+
+         when Skip_And_Reject =>
+            End_Skip;
+            return False;
+      end case;
+   end Check_End;
+
+   --------------
+   -- End Skip --
+   --------------
+
+   --  This procedure skips past an END sequence. On entry Token contains
+   --  Tok_End, and we know that the END sequence is syntactically incorrect,
+   --  and that an appropriate error message has already been posted. The
+   --  mission is simply to position the scan pointer to be the best guess of
+   --  the position after the END sequence. We do not issue any additional
+   --  error messages while carrying this out.
+
+   --  Error recovery: does not raise Error_Resync
+
+   procedure End_Skip is
+   begin
+      Scan; -- past END
+
+      --  If the scan past the END leaves us on the next line, that's probably
+      --  where we should quit the scan, since it is likely that what we have
+      --  is a missing semicolon. Consider the following:
+
+      --       END
+      --       Process_Input;
+
+      --  This will have looked like a syntactically valid END sequence to the
+      --  initial scan of the END, but subsequent checking will have determined
+      --  that the label Process_Input is not an appropriate label. The real
+      --  error is a missing semicolon after the END, and by leaving the scan
+      --  pointer just past the END, we will improve the error recovery.
+
+      if Token_Is_At_Start_Of_Line then
+         return;
+      end if;
+
+      --  If there is a semicolon after the END, scan it out and we are done
+
+      if Token = Tok_Semicolon then
+         T_Semicolon;
+         return;
+      end if;
+
+      --  Otherwise skip past a token after the END on the same line. Note
+      --  that we do not eat a token on the following line since it seems
+      --  very unlikely in any case that the END gets separated from its
+      --  token, and we do not want to swallow up a keyword that starts a
+      --  legitimate construct following the bad END.
+
+      if not Token_Is_At_Start_Of_Line
+        and then
+
+         --  Cases of normal tokens following an END
+
+          (Token = Tok_Case   or else
+           Token = Tok_For    or else
+           Token = Tok_If     or else
+           Token = Tok_Loop   or else
+           Token = Tok_Record or else
+           Token = Tok_Select or else
+
+         --  Cases of bogus keywords ending loops
+
+           Token = Tok_For    or else
+           Token = Tok_While  or else
+
+         --  Cases of operator symbol names without quotes
+
+           Token = Tok_Abs    or else
+           Token = Tok_And    or else
+           Token = Tok_Mod    or else
+           Token = Tok_Not    or else
+           Token = Tok_Or     or else
+           Token = Tok_Xor)
+
+      then
+         Scan; -- past token after END
+
+         --  If that leaves us on the next line, then we are done. This is the
+         --  same principle described above for the case of END at line end
+
+         if Token_Is_At_Start_Of_Line then
+            return;
+
+         --  If we just scanned out record, then we are done, since the
+         --  semicolon after END RECORD is not part of the END sequence
+
+         elsif Prev_Token = Tok_Record then
+            return;
+
+         --  If we have a semicolon, scan it out and we are done
+
+         elsif Token = Tok_Semicolon then
+            T_Semicolon;
+            return;
+         end if;
+      end if;
+
+      --  Check for a label present on the same line
+
+      loop
+         if Token_Is_At_Start_Of_Line then
+            return;
+         end if;
+
+         if Token /= Tok_Identifier
+           and then Token /= Tok_Operator_Symbol
+           and then Token /= Tok_String_Literal
+         then
+            exit;
+         end if;
+
+         Scan; -- past identifier, operator symbol or string literal
+
+         if Token_Is_At_Start_Of_Line then
+            return;
+         elsif Token = Tok_Dot then
+            Scan; -- past dot
+         end if;
+      end loop;
+
+      --  Skip final semicolon
+
+      if Token = Tok_Semicolon then
+         T_Semicolon;
+
+      --  If we don't have a final semicolon, skip until we either encounter
+      --  an END token, or a semicolon or the start of the next line. This
+      --  allows general junk to follow the end line (normally it is hard to
+      --  think that anyone will put anything deliberate here, and remember
+      --  that we know there is a missing semicolon in any case). We also
+      --  quite on an EOF (or else we would get stuck in an infinite loop
+      --  if there is no line end at the end of the last line of the file)
+
+      else
+         while Token /= Tok_End
+           and then Token /= Tok_EOF
+           and then Token /= Tok_Semicolon
+           and then not Token_Is_At_Start_Of_Line
+         loop
+            Scan; -- past junk token on same line
+         end loop;
+      end if;
+
+      return;
+   end End_Skip;
+
+   --------------------
+   -- End Statements --
+   --------------------
+
+   --  This procedure is called when END is required or expected to terminate
+   --  a sequence of statements. The caller has already made an appropriate
+   --  entry on the scope stack to describe the expected form of the END.
+   --  End_Statements should only be used in cases where the only appropriate
+   --  terminator is END.
+
+   --  Error recovery: cannot raise Error_Resync;
+
+   procedure End_Statements (Parent : Node_Id := Empty) is
+   begin
+      --  This loop runs more than once in the case where Check_End rejects
+      --  the END sequence, as indicated by Check_End returning False.
+
+      loop
+         if Check_End then
+            if Present (Parent) then
+               Set_End_Label (Parent, End_Labl);
+            end if;
+
+            return;
+         end if;
+
+         --  Extra statements past the bogus END are discarded. This is not
+         --  ideal for maximum error recovery, but it's too much trouble to
+         --  find an appropriate place to put them!
+
+         Discard_Junk_List (P_Sequence_Of_Statements (SS_None));
+      end loop;
+   end End_Statements;
+
+   ------------------------
+   -- Evaluate End Entry --
+   ------------------------
+
+   procedure Evaluate_End_Entry (SS_Index : Int) is
+   begin
+      Column_OK := (End_Column = Scope.Table (SS_Index).Ecol);
+
+      Token_OK  := (End_Type = Scope.Table (SS_Index).Etyp or else
+                     (End_Type = E_Name and then
+                       Scope.Table (SS_Index).Etyp >= E_Name));
+
+      Label_OK := End_Labl_Present
+                    and then
+                      (Same_Label (End_Labl, Scope.Table (SS_Index).Labl)
+                        or else Scope.Table (SS_Index).Labl = Error);
+
+      --  Compute setting of Syntax_OK. We definitely have a syntax error
+      --  if the Token does not match properly or if P_End_Scan detected
+      --  a syntax error such as a missing semicolon.
+
+      if not Token_OK or not End_OK then
+         Syntax_OK := False;
+
+      --  Final check is that label is OK. Certainly it is OK if there
+      --  was an exact match on the label (the END label = the stack label)
+
+      elsif Label_OK then
+         Syntax_OK := True;
+
+      --  Case of label present
+
+      elsif End_Labl_Present then
+
+         --  If probably misspelling, then complain, and pretend it is OK
+
+         declare
+            Nam : constant Node_Or_Entity_Id := Scope.Table (SS_Index).Labl;
+
+         begin
+            if Nkind (End_Labl) in N_Has_Chars
+              and then Nkind (Nam) in N_Has_Chars
+              and then Chars (End_Labl) > Error_Name
+              and then Chars (Nam) > Error_Name
+            then
+               Get_Name_String (Chars (End_Labl));
+               Error_Msg_Name_1 := Chars (Nam);
+
+               if Error_Msg_Name_1 > Error_Name then
+                  declare
+                     S : String (1 .. Name_Len) := Name_Buffer (1 .. Name_Len);
+
+                  begin
+                     Get_Name_String (Error_Msg_Name_1);
+
+                     if Is_Bad_Spelling_Of
+                         (Name_Buffer (1 .. Name_Len), S)
+                     then
+                        Error_Msg_N ("misspelling of %", End_Labl);
+                        Syntax_OK := True;
+                        return;
+                     end if;
+                  end;
+               end if;
+            end if;
+         end;
+
+         Syntax_OK := False;
+
+      --  Otherwise we have cases of no label on the END line. For the loop
+      --  case, this is acceptable only if the loop is unlabeled.
+
+      elsif End_Type = E_Loop then
+         Syntax_OK := (Scope.Table (SS_Index).Labl = Empty);
+
+      --  Cases where a label is definitely allowed on the END line
+
+      elsif End_Type = E_Name then
+         Syntax_OK := (Scope.Table (SS_Index).Labl = Empty or else
+                         not Scope.Table (SS_Index).Lreq);
+
+      --  Otherwise we have cases which don't allow labels anyway, so we
+      --  certainly accept an END which does not have a label.
+
+      else
+         Syntax_OK := True;
+      end if;
+   end Evaluate_End_Entry;
+
+   ------------------------
+   -- Output End Deleted --
+   ------------------------
+
+   procedure Output_End_Deleted is
+   begin
+
+      if End_Type = E_Loop then
+         Error_Msg_SC ("no LOOP for this `END LOOP`!");
+
+      elsif End_Type = E_Case then
+         Error_Msg_SC ("no CASE for this `END CASE`");
+
+      elsif End_Type = E_If then
+         Error_Msg_SC ("no IF for this `END IF`!");
+
+      elsif End_Type = E_Record then
+         Error_Msg_SC ("no RECORD for this `END RECORD`!");
+
+      elsif End_Type = E_Select then
+         Error_Msg_SC ("no SELECT for this `END SELECT`!");
+
+      else
+         Error_Msg_SC ("no BEGIN for this END!");
+      end if;
+   end Output_End_Deleted;
+
+   -------------------------
+   -- Output End Expected --
+   -------------------------
+
+   procedure Output_End_Expected (Ins : Boolean) is
+      End_Type : SS_End_Type;
+
+   begin
+      --  Suppress message if this was a potentially junk entry (e.g. a
+      --  record entry where no record keyword was present.
+
+      if Scope.Table (Scope.Last).Junk then
+         return;
+      end if;
+
+      End_Type := Scope.Table (Scope.Last).Etyp;
+      Error_Msg_Col    := Scope.Table (Scope.Last).Ecol;
+      Error_Msg_Node_1 := Scope.Table (Scope.Last).Labl;
+      Error_Msg_Sloc   := Scope.Table (Scope.Last).Sloc;
+
+      --  Suppress message if error was posted on opening label
+
+      if Present (Error_Msg_Node_1)
+        and then Error_Posted (Error_Msg_Node_1)
+      then
+         return;
+      end if;
+
+      if End_Type = E_Case then
+         Error_Msg_SC ("`END CASE;` expected@ for CASE#!");
+
+      elsif End_Type = E_If then
+         Error_Msg_SC ("`END IF;` expected@ for IF#!");
+
+      elsif End_Type = E_Loop then
+         if Error_Msg_Node_1 = Empty then
+            Error_Msg_SC
+              ("`END LOOP;` expected@ for LOOP#!");
+         else
+            Error_Msg_SC ("`END LOOP &;` expected@!");
+         end if;
+
+      elsif End_Type = E_Record then
+         Error_Msg_SC
+           ("`END RECORD;` expected@ for RECORD#!");
+
+      elsif End_Type = E_Select then
+         Error_Msg_SC
+           ("`END SELECT;` expected@ for SELECT#!");
+
+      --  All remaining cases are cases with a name (we do not treat
+      --  the suspicious is cases specially for a replaced end, only
+      --  for an inserted end).
+
+      elsif End_Type = E_Name or else (not Ins) then
+         if Error_Msg_Node_1 = Empty then
+            Error_Msg_SC ("`END;` expected@ for BEGIN#!");
+         else
+            Error_Msg_SC ("`END &;` expected@!");
+         end if;
+
+      --  The other possibility is a missing END for a subprogram with a
+      --  suspicious IS (that probably should have been a semicolon). The
+      --  Missing IS confirms the suspicion!
+
+      else -- End_Type = E_Suspicious_Is or E_Bad_Is
+         Scope.Table (Scope.Last).Etyp := E_Bad_Is;
+      end if;
+   end Output_End_Expected;
+
+   ------------------------
+   -- Output End Missing --
+   ------------------------
+
+   procedure Output_End_Missing is
+      End_Type : SS_End_Type;
+
+   begin
+      --  Suppress message if this was a potentially junk entry (e.g. a
+      --  record entry where no record keyword was present.
+
+      if Scope.Table (Scope.Last).Junk then
+         return;
+      end if;
+
+      End_Type := Scope.Table (Scope.Last).Etyp;
+      Error_Msg_Node_1 := Scope.Table (Scope.Last).Labl;
+      Error_Msg_Sloc   := Scope.Table (Scope.Last).Sloc;
+
+      if End_Type = E_Case then
+         Error_Msg_BC ("missing `END CASE;` for CASE#!");
+
+      elsif End_Type = E_If then
+         Error_Msg_BC ("missing `END IF;` for IF#!");
+
+      elsif End_Type = E_Loop then
+         if Error_Msg_Node_1 = Empty then
+            Error_Msg_BC ("missing `END LOOP;` for LOOP#!");
+         else
+            Error_Msg_BC ("missing `END LOOP &;`!");
+         end if;
+
+      elsif End_Type = E_Record then
+         Error_Msg_SC
+           ("missing `END RECORD;` for RECORD#!");
+
+      elsif End_Type = E_Select then
+         Error_Msg_BC
+           ("missing `END SELECT;` for SELECT#!");
+
+      elsif End_Type = E_Name then
+         if Error_Msg_Node_1 = Empty then
+            Error_Msg_BC ("missing `END;` for BEGIN#!");
+         else
+            Error_Msg_BC ("missing `END &;`!");
+         end if;
+
+      else -- End_Type = E_Suspicious_Is or E_Bad_Is
+         Scope.Table (Scope.Last).Etyp := E_Bad_Is;
+      end if;
+   end Output_End_Missing;
+
+   ---------------------
+   -- Pop End Context --
+   ---------------------
+
+   procedure Pop_End_Context is
+
+      Pretty_Good : Boolean;
+      --  This flag is set True if the END sequence is syntactically incorrect,
+      --  but is (from a heuristic point of view), pretty likely to be simply
+      --  a misspelling of the intended END.
+
+      Outer_Match : Boolean;
+      --  This flag is set True if we decide that the current END sequence
+      --  belongs to some outer level entry in the scope stack, and thus
+      --  we will NOT eat it up in matching the current expected END.
+
+   begin
+      --  If not at END, then output END expected message
+
+      if End_Type = E_Dummy then
+         Output_End_Missing;
+         Pop_Scope_Stack;
+         End_Action := Insert_And_Accept;
+         return;
+
+      --  Otherwise we do have an END present
+
+      else
+         --  A special check. If we have END; followed by an end of file,
+         --  WITH or SEPARATE, then if we are not at the outer level, then
+         --  we have a sytax error. Consider the example:
+
+         --   ...
+         --      declare
+         --         X : Integer;
+         --      begin
+         --         X := Father (A);
+         --         Process (X, X);
+         --   end;
+         --   with Package1;
+         --   ...
+
+         --  Now the END; here is a syntactically correct closer for the
+         --  declare block, but if we eat it up, then we obviously have
+         --  a missing END for the outer context (since WITH can only appear
+         --  at the outer level.
+
+         --  In this situation, we always reserve the END; for the outer level,
+         --  even if it is in the wrong column. This is because it's much more
+         --  useful to have the error message point to the DECLARE than to the
+         --  package header in this case.
+
+         --  We also reserve an end with a name before the end of file if the
+         --  name is the one we expect at the outer level.
+
+         if (Token = Tok_EOF or else
+             Token = Tok_With or else
+             Token = Tok_Separate)
+           and then End_Type >= E_Name
+           and then (not End_Labl_Present
+                      or else Same_Label (End_Labl, Scope.Table (1).Labl))
+           and then Scope.Last > 1
+         then
+            Restore_Scan_State (Scan_State); -- to END
+            Output_End_Expected (Ins => True);
+            Pop_Scope_Stack;
+            End_Action := Insert_And_Accept;
+            return;
+         end if;
+
+         --  Otherwise we go through the normal END evaluation procedure
+
+         Evaluate_End_Entry (Scope.Last);
+
+         --  If top entry in stack is syntactically correct, then we have
+         --  scanned it out and everything is fine. This is the required
+         --  action to properly process correct Ada programs.
+
+         if Syntax_OK then
+
+            --  Complain if checking columns and END is not in right column.
+            --  Right in this context means exactly right, or on the same
+            --  line as the opener.
+
+            if Style.RM_Column_Check then
+               if End_Column /= Scope.Table (Scope.Last).Ecol
+                 and then Current_Line_Start > Scope.Table (Scope.Last).Sloc
+               then
+                  Error_Msg_Col := Scope.Table (Scope.Last).Ecol;
+                  Error_Msg
+                    ("(style) END in wrong column, should be@", End_Sloc);
+               end if;
+            end if;
+
+            --  One final check. If the end had a label, check for an exact
+            --  duplicate of this end sequence, and if so, skip it with an
+            --  appropriate message.
+
+            if End_Labl_Present and then Token = Tok_End then
+               declare
+                  Scan_State : Saved_Scan_State;
+                  End_Loc    : constant Source_Ptr := Token_Ptr;
+                  Nxt_Labl   : Node_Id;
+                  Dup_Found  : Boolean := False;
+
+               begin
+                  Save_Scan_State (Scan_State);
+
+                  Scan; -- past END
+
+                  if Token = Tok_Identifier
+                    or else Token = Tok_Operator_Symbol
+                  then
+                     Nxt_Labl := P_Designator;
+
+                     --  We only consider it an error if the label is a match
+                     --  and would be wrong for the level one above us, and
+                     --  the indentation is the same.
+
+                     if Token = Tok_Semicolon
+                       and then Same_Label (End_Labl, Nxt_Labl)
+                       and then End_Column = Start_Column
+                       and then
+                         (Scope.Last = 1
+                            or else
+                              (No (Scope.Table (Scope.Last - 1).Labl)
+                                or else
+                               not Same_Label
+                                     (End_Labl,
+                                      Scope.Table (Scope.Last - 1).Labl)))
+                     then
+                        T_Semicolon;
+                        Error_Msg ("duplicate end line ignored", End_Loc);
+                        Dup_Found := True;
+                     end if;
+                  end if;
+
+                  if not Dup_Found then
+                     Restore_Scan_State (Scan_State);
+                  end if;
+               end;
+            end if;
+
+            --  All OK, so return to caller indicating END is OK
+
+            Pop_Scope_Stack;
+            End_Action := Accept_As_Scanned;
+            return;
+         end if;
+
+         --  If that check failed, then we definitely have an error. The issue
+         --  is how to choose among three possible courses of action:
+
+         --   1. Ignore the current END text completely, scanning past it,
+         --      deciding that it belongs neither to the current context,
+         --      nor to any outer context.
+
+         --   2. Accept the current END text, scanning past it, and issuing
+         --      an error message that it does not have the right form.
+
+         --   3. Leave the current END text in place, NOT scanning past it,
+         --      issuing an error message indicating the END expected for the
+         --      current context. In this case, the END is available to match
+         --      some outer END context.
+
+         --  From a correct functioning point of view, it does not make any
+         --  difference which of these three approaches we take, the program
+         --  will work correctly in any case. However, making an accurate
+         --  choice among these alternatives, i.e. choosing the one that
+         --  corresponds to what the programmer had in mind, does make a
+         --  significant difference in the quality of error recovery.
+
+         Restore_Scan_State (Scan_State); -- to END
+
+         --  First we see how good the current END entry is with respect to
+         --  what we expect. It is considered pretty good if the token is OK,
+         --  and either the label or the column matches. an END for RECORD is
+         --  always considered to be pretty good in the record case. This is
+         --  because not only does a record disallow a nested structure, but
+         --  also it is unlikely that such nesting could occur by accident.
+
+         Pretty_Good := (Token_OK and (Column_OK or Label_OK))
+                          or else Scope.Table (Scope.Last).Etyp = E_Record;
+
+         --  Next check, if there is a deeper entry in the stack which
+         --  has a very high probability of being acceptable, then insert
+         --  the END entry we want, leaving the higher level entry for later
+
+         for J in reverse 1 .. Scope.Last - 1 loop
+            Evaluate_End_Entry (J);
+
+            --  To even consider the deeper entry to be immediately acceptable,
+            --  it must be syntactically correct. Furthermore it must either
+            --  have a correct label, or the correct column. If the current
+            --  entry was a close match (Pretty_Good set), then we are even
+            --  more strict in accepting the outer level one: even if it has
+            --  the right label, it must have the right column as well.
+
+            if Syntax_OK then
+               if Pretty_Good then
+                  Outer_Match := Label_OK and Column_OK;
+               else
+                  Outer_Match := Label_OK or Column_OK;
+               end if;
+            else
+               Outer_Match := False;
+            end if;
+
+            --  If the outer entry does convincingly match the END text, then
+            --  back up the scan to the start of the END sequence, issue an
+            --  error message indicating the END we expected, and return with
+            --  Token pointing to the END (case 3 from above discussion).
+
+            if Outer_Match then
+               Output_End_Missing;
+               Pop_Scope_Stack;
+               End_Action := Insert_And_Accept;
+               return;
+            end if;
+         end loop;
+
+         --  Here we have a situation in which the current END entry is
+         --  syntactically incorrect, but there is no deeper entry in the
+         --  END stack which convincingly matches it.
+
+         --  If the END text was judged to be a Pretty_Good match for the
+         --  expected token or if it appears left of the expected column,
+         --  then we will accept it as the one we want, scanning past it, even
+         --  though it is not completely right (we issue a message showing what
+         --  we expected it to be). This is action 2 from the discussion above.
+         --  There is one other special case to consider: the LOOP case.
+         --  Consider the example:
+
+         --     Lbl: loop
+         --             null;
+         --          end loop;
+
+         --  Here the column lines up with Lbl, so END LOOP is to the right,
+         --  but it is still acceptable. LOOP is the one case where alignment
+         --  practices vary substantially in practice.
+
+         if Pretty_Good
+            or else End_Column <= Scope.Table (Scope.Last).Ecol
+            or else (End_Type = Scope.Table (Scope.Last).Etyp
+                        and then End_Type = E_Loop)
+         then
+            Output_End_Expected (Ins => False);
+            Pop_Scope_Stack;
+            End_Action := Skip_And_Accept;
+            return;
+
+         --  Here we have the case where the END is to the right of the
+         --  expected column and does not have a correct label to convince
+         --  us that it nevertheless belongs to the current scope. For this
+         --  we consider that it probably belongs not to the current context,
+         --  but to some inner context that was not properly recognized (due to
+         --  other syntax errors), and for which no proper scope stack entry
+         --  was made. The proper action in this case is to delete the END text
+         --  and return False to the caller as a signal to keep on looking for
+         --  an acceptable END. This is action 1 from the discussion above.
+
+         else
+            Output_End_Deleted;
+            End_Action := Skip_And_Reject;
+            return;
+         end if;
+      end if;
+   end Pop_End_Context;
+
+   ----------------
+   -- Same_Label --
+   ----------------
+
+   function Same_Label (Label1, Label2 : Node_Id) return Boolean is
+   begin
+      if Nkind (Label1) in N_Has_Chars
+        and then Nkind (Label2) in N_Has_Chars
+      then
+         return Chars (Label1) = Chars (Label2);
+
+      elsif Nkind (Label1) = N_Selected_Component
+        and then Nkind (Label2) = N_Selected_Component
+      then
+         return Same_Label (Prefix (Label1), Prefix (Label2)) and then
+           Same_Label (Selector_Name (Label1), Selector_Name (Label2));
+
+      elsif Nkind (Label1) = N_Designator
+        and then Nkind (Label2) = N_Defining_Program_Unit_Name
+      then
+         return Same_Label (Name (Label1), Name (Label2)) and then
+           Same_Label (Identifier (Label1), Defining_Identifier (Label2));
+
+      else
+         return False;
+      end if;
+   end Same_Label;
+
+end Endh;
diff --git a/gcc/ada/par-labl.adb b/gcc/ada/par-labl.adb
new file mode 100644 (file)
index 0000000..e43d3f3
--- /dev/null
@@ -0,0 +1,202 @@
+------------------------------------------------------------------------------
+--                                                                          --
+--                         GNAT COMPILER COMPONENTS                         --
+--                                                                          --
+--                             P A R . L A B L                              --
+--                                                                          --
+--                                 B o d y                                  --
+--                                                                          --
+--                            $Revision: 1.18 $                             --
+--                                                                          --
+--          Copyright (C) 1992-1998, Free Software Foundation, Inc.         --
+--                                                                          --
+-- GNAT is free software;  you can  redistribute it  and/or modify it under --
+-- terms of the  GNU General Public License as published  by the Free Soft- --
+-- ware  Foundation;  either version 2,  or (at your option) any later ver- --
+-- sion.  GNAT is distributed in the hope that it will be useful, but WITH- --
+-- OUT 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  distributed with GNAT;  see file COPYING.  If not, write --
+-- to  the Free Software Foundation,  59 Temple Place - Suite 330,  Boston, --
+-- MA 02111-1307, USA.                                                      --
+--                                                                          --
+-- GNAT was originally developed  by the GNAT team at  New York University. --
+-- It is now maintained by Ada Core Technologies Inc (http://www.gnat.com). --
+--                                                                          --
+------------------------------------------------------------------------------
+
+separate (Par)
+procedure Labl is
+   Enclosing_Body_Or_Block : Node_Id;
+   --  Innermost enclosing body or block statement
+
+   Label_Decl_Node : Node_Id;
+   --  Implicit label declaration node
+
+   Defining_Ident_Node : Node_Id;
+   --  Defining identifier node for implicit label declaration
+
+   Next_Label_Elmt : Elmt_Id;
+   --  Next element on label element list
+
+   Label_Node : Node_Id;
+   --  Next label node to process
+
+   function Find_Enclosing_Body_Or_Block (N : Node_Id) return Node_Id;
+   --  Find the innermost body or block that encloses N.
+
+   function Find_Enclosing_Body (N : Node_Id) return Node_Id;
+   --  Find the innermost body that encloses N.
+
+   procedure Check_Distinct_Labels;
+   --  Checks the rule in RM-5.1(11), which requires distinct identifiers
+   --  for all the labels in a given body.
+
+   ---------------------------
+   -- Check_Distinct_Labels --
+   ---------------------------
+
+   procedure Check_Distinct_Labels is
+      Label_Id : constant Node_Id := Identifier (Label_Node);
+
+      Enclosing_Body : constant Node_Id :=
+                         Find_Enclosing_Body (Enclosing_Body_Or_Block);
+      --  Innermost enclosing body
+
+      Next_Other_Label_Elmt : Elmt_Id := First_Elmt (Label_List);
+      --  Next element on label element list
+
+      Other_Label : Node_Id;
+      --  Next label node to process
+
+   begin
+      --  Loop through all the labels, and if we find some other label
+      --  (i.e. not Label_Node) that has the same identifier,
+      --  and whose innermost enclosing body is the same,
+      --  then we have an error.
+
+      --  Note that in the worst case, this is quadratic in the number
+      --  of labels.  However, labels are not all that common, and this
+      --  is only called for explicit labels.
+      --  ???Nonetheless, the efficiency could be improved. For example,
+      --  call Labl for each body, rather than once per compilation.
+
+      while Present (Next_Other_Label_Elmt) loop
+         Other_Label := Node (Next_Other_Label_Elmt);
+
+         exit when Label_Node = Other_Label;
+
+         if Chars (Label_Id) = Chars (Identifier (Other_Label))
+           and then Enclosing_Body = Find_Enclosing_Body (Other_Label)
+         then
+            Error_Msg_Sloc := Sloc (Other_Label);
+            Error_Msg_N ("& conflicts with label#", Label_Id);
+            exit;
+         end if;
+
+         Next_Elmt (Next_Other_Label_Elmt);
+      end loop;
+   end Check_Distinct_Labels;
+
+   -------------------------
+   -- Find_Enclosing_Body --
+   -------------------------
+
+   function Find_Enclosing_Body (N : Node_Id) return Node_Id is
+      Result : Node_Id := N;
+
+   begin
+      --  This is the same as Find_Enclosing_Body_Or_Block, except
+      --  that we skip block statements and accept statements, instead
+      --  of stopping at them.
+
+      while Present (Result)
+        and then Nkind (Result) /= N_Entry_Body
+        and then Nkind (Result) /= N_Task_Body
+        and then Nkind (Result) /= N_Package_Body
+        and then Nkind (Result) /= N_Subprogram_Body
+      loop
+         Result := Parent (Result);
+      end loop;
+
+      return Result;
+   end Find_Enclosing_Body;
+
+   ----------------------------------
+   -- Find_Enclosing_Body_Or_Block --
+   ----------------------------------
+
+   function Find_Enclosing_Body_Or_Block (N : Node_Id) return Node_Id is
+      Result : Node_Id := Parent (N);
+
+   begin
+      --  Climb up the parent chain until we find a body or block.
+
+      while Present (Result)
+        and then Nkind (Result) /= N_Accept_Statement
+        and then Nkind (Result) /= N_Entry_Body
+        and then Nkind (Result) /= N_Task_Body
+        and then Nkind (Result) /= N_Package_Body
+        and then Nkind (Result) /= N_Subprogram_Body
+        and then Nkind (Result) /= N_Block_Statement
+      loop
+         Result := Parent (Result);
+      end loop;
+
+      return Result;
+   end Find_Enclosing_Body_Or_Block;
+
+--  Start of processing for Par.Labl
+
+begin
+   Next_Label_Elmt := First_Elmt (Label_List);
+
+   while Present (Next_Label_Elmt) loop
+      Label_Node := Node (Next_Label_Elmt);
+
+      if not Comes_From_Source (Label_Node) then
+         goto Next_Label;
+      end if;
+
+      --  Find the innermost enclosing body or block, which is where
+      --  we need to implicitly declare this label
+
+      Enclosing_Body_Or_Block := Find_Enclosing_Body_Or_Block (Label_Node);
+
+      --  If we didn't find a parent, then the label in question never got
+      --  hooked into a reasonable declarative part. This happens only in
+      --  error situations, and we simply ignore the entry (we aren't going
+      --  to get into the semantics in any case given the error).
+
+      if Present (Enclosing_Body_Or_Block) then
+         Check_Distinct_Labels;
+
+         --  Now create the implicit label declaration node and its
+         --  corresponding defining identifier. Note that the defining
+         --  occurrence of a label is the implicit label declaration that
+         --  we are creating. The label itself is an applied occurrence.
+
+         Label_Decl_Node :=
+           New_Node (N_Implicit_Label_Declaration, Sloc (Label_Node));
+         Defining_Ident_Node :=
+           New_Entity (N_Defining_Identifier, Sloc (Identifier (Label_Node)));
+         Set_Chars (Defining_Ident_Node, Chars (Identifier (Label_Node)));
+         Set_Defining_Identifier (Label_Decl_Node, Defining_Ident_Node);
+         Set_Label_Construct (Label_Decl_Node, Label_Node);
+
+         --  Now attach the implicit label declaration to the appropriate
+         --  declarative region, creating a declaration list if none exists
+
+         if not Present (Declarations (Enclosing_Body_Or_Block)) then
+            Set_Declarations (Enclosing_Body_Or_Block, New_List);
+         end if;
+
+         Append (Label_Decl_Node, Declarations (Enclosing_Body_Or_Block));
+      end if;
+
+      <<Next_Label>>
+         Next_Elmt (Next_Label_Elmt);
+   end loop;
+
+end Labl;
diff --git a/gcc/ada/par-load.adb b/gcc/ada/par-load.adb
new file mode 100644 (file)
index 0000000..39934ca
--- /dev/null
@@ -0,0 +1,410 @@
+------------------------------------------------------------------------------
+--                                                                          --
+--                         GNAT COMPILER COMPONENTS                         --
+--                                                                          --
+--                             P A R . L O A D                              --
+--                                                                          --
+--                                 B o d y                                  --
+--                                                                          --
+--                            $Revision: 1.60 $
+--                                                                          --
+--          Copyright (C) 1992-2001 Free Software Foundation, Inc.          --
+--                                                                          --
+-- GNAT is free software;  you can  redistribute it  and/or modify it under --
+-- terms of the  GNU General Public License as published  by the Free Soft- --
+-- ware  Foundation;  either version 2,  or (at your option) any later ver- --
+-- sion.  GNAT is distributed in the hope that it will be useful, but WITH- --
+-- OUT 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  distributed with GNAT;  see file COPYING.  If not, write --
+-- to  the Free Software Foundation,  59 Temple Place - Suite 330,  Boston, --
+-- MA 02111-1307, USA.                                                      --
+--                                                                          --
+-- GNAT was originally developed  by the GNAT team at  New York University. --
+-- It is now maintained by Ada Core Technologies Inc (http://www.gnat.com). --
+--                                                                          --
+------------------------------------------------------------------------------
+
+--  The Par.Load procedure loads all units that are definitely required before
+--  it makes any sense at all to proceed with semantic analysis, including
+--  with'ed units, corresponding specs for bodies, parents of child specs,
+--  and parents of subunits. All these units are loaded and pointers installed
+--  in the tree as described in the spec of package Lib.
+
+with Fname;    use Fname;
+with Fname.UF; use Fname.UF;
+with Lib.Load; use Lib.Load;
+with Uname;    use Uname;
+with Namet;    use Namet;
+with Casing;   use Casing;
+with Opt;      use Opt;
+with Osint;    use Osint;
+with Sinput.L; use Sinput.L;
+with Stylesw;  use Stylesw;
+with Validsw;  use Validsw;
+
+separate (Par)
+procedure Load is
+
+   File_Name : File_Name_Type;
+   --  Name of file for current unit, derived from unit name
+
+   Cur_Unum : Unit_Number_Type := Current_Source_Unit;
+   --  Unit number of unit that we just finished parsing. Note that we need
+   --  to capture this, because Source_Unit will change as we parse new
+   --  source files in the multiple main source file case.
+
+   Curunit : constant Node_Id := Cunit (Cur_Unum);
+   --  Compilation unit node for current compilation unit
+
+   Loc : Source_Ptr := Sloc (Curunit);
+   --  Source location for compilation unit node
+
+   Save_Style_Check  : Boolean;
+   Save_Style_Checks : Style_Check_Options;
+   --  Save style check so it can be restored later
+
+   Save_Validity_Check  : Boolean;
+   Save_Validity_Checks : Validity_Check_Options;
+   --  Save validity check so it can be restored later
+
+   With_Cunit : Node_Id;
+   --  Compilation unit node for withed unit
+
+   Context_Node : Node_Id;
+   --  Next node in context items list
+
+   With_Node : Node_Id;
+   --  N_With_Clause node
+
+   Spec_Name : Unit_Name_Type;
+   --  Unit name of required spec
+
+   Body_Name : Unit_Name_Type;
+   --  Unit name of corresponding body
+
+   Unum : Unit_Number_Type;
+   --  Unit number of loaded unit
+
+   function Same_File_Name_Except_For_Case
+     (Expected_File_Name : File_Name_Type;
+      Actual_File_Name   : File_Name_Type)
+      return               Boolean;
+   --  Given an actual file name and an expected file name (the latter being
+   --  derived from the unit name), determine if they are the same except for
+   --  possibly different casing of letters.
+
+   function Same_File_Name_Except_For_Case
+     (Expected_File_Name : File_Name_Type;
+      Actual_File_Name   : File_Name_Type)
+      return               Boolean
+   is
+   begin
+      Get_Name_String (Actual_File_Name);
+      Canonical_Case_File_Name (Name_Buffer (1 .. Name_Len));
+
+      declare
+         Lower_Case_Actual_File_Name : String (1 .. Name_Len);
+
+      begin
+         Lower_Case_Actual_File_Name := Name_Buffer (1 .. Name_Len);
+         Get_Name_String (Expected_File_Name);
+         Canonical_Case_File_Name (Name_Buffer (1 .. Name_Len));
+         return Lower_Case_Actual_File_Name = Name_Buffer (1 .. Name_Len);
+      end;
+
+   end Same_File_Name_Except_For_Case;
+
+--  Start of processing for Load
+
+begin
+   --  Don't do any loads if we already had a fatal error
+
+   if Fatal_Error (Cur_Unum) then
+      return;
+   end if;
+
+   Save_Style_Check_Options (Save_Style_Checks);
+   Save_Style_Check := Opt.Style_Check;
+
+   Save_Validity_Check_Options (Save_Validity_Checks);
+   Save_Validity_Check := Opt.Validity_Checks_On;
+
+   --  If main unit, set Main_Unit_Entity (this will get overwritten if
+   --  the main unit has a separate spec, that happens later on in Load)
+
+   if Cur_Unum = Main_Unit then
+      Main_Unit_Entity := Cunit_Entity (Main_Unit);
+   end if;
+
+   --  If we have no unit name, things are seriously messed up by previous
+   --  errors, and we should not try to continue compilation.
+
+   if Unit_Name (Cur_Unum) = No_Name then
+      raise Unrecoverable_Error;
+   end if;
+
+   --  Next step, make sure that the unit name matches the file name
+   --  and issue a warning message if not. We only output this for the
+   --  main unit, since for other units it is more serious and is
+   --  caught in a separate test below.
+
+   File_Name :=
+     Get_File_Name
+       (Unit_Name (Cur_Unum),
+        Subunit => Nkind (Unit (Cunit (Cur_Unum))) = N_Subunit);
+
+   if Cur_Unum = Main_Unit
+     and then File_Name /= Unit_File_Name (Cur_Unum)
+     and then (File_Names_Case_Sensitive
+                or not Same_File_Name_Except_For_Case
+                         (File_Name, Unit_File_Name (Cur_Unum)))
+   then
+      Error_Msg_Name_1 := File_Name;
+      Error_Msg
+        ("?file name does not match unit name, should be{", Sloc (Curunit));
+   end if;
+
+   --  For units other than the main unit, the expected unit name is set and
+   --  must be the same as the actual unit name, or we are in big trouble, and
+   --  abandon the compilation since there are situations where this really
+   --  gets us into bad trouble (e.g. some subunit situations).
+
+   if Cur_Unum /= Main_Unit
+     and then Expected_Unit (Cur_Unum) /= Unit_Name (Cur_Unum)
+   then
+      Loc := Error_Location (Cur_Unum);
+      Error_Msg_Name_1 := Unit_File_Name (Cur_Unum);
+      Get_Name_String (Error_Msg_Name_1);
+
+      --  Check for predefined file case
+
+      if Name_Len > 1
+        and then Name_Buffer (2) = '-'
+        and then (Name_Buffer (1) = 'a'
+                    or else
+                  Name_Buffer (1) = 's'
+                    or else
+                  Name_Buffer (1) = 'i'
+                    or else
+                  Name_Buffer (1) = 'g')
+      then
+         --  In the predefined file case, we know the user did not construct
+         --  their own package, but we got the wrong one. This means that the
+         --  name supplied by the user crunched to something we recognized,
+         --  but then the file did not contain the unit expected. Most likely
+         --  this is due to a misspelling, e.g.
+
+         --    with Ada.Calender;
+
+         --  This crunches to a-calend, which indeed contains the unit
+         --  Ada.Calendar, and we can diagnose the misspelling. This is
+         --  a simple heuristic, but it catches many common cases of
+         --  misspelling of predefined unit names without needing a full
+         --  list of them.
+
+         Error_Msg_Name_1 := Expected_Unit (Cur_Unum);
+         Error_Msg ("% is not a predefined library unit!", Loc);
+         Error_Msg_Name_1 := Unit_Name (Cur_Unum);
+         Error_Msg ("possible misspelling of %!", Loc);
+
+      --  Non-predefined file name case
+
+      else
+         Error_Msg ("file { does not contain expected unit!", Loc);
+         Error_Msg_Unit_1 := Expected_Unit (Cur_Unum);
+         Error_Msg ("expected unit $!", Loc);
+         Error_Msg_Unit_1 := Unit_Name (Cur_Unum);
+         Error_Msg ("found unit $!", Loc);
+      end if;
+
+      raise Unrecoverable_Error;
+   end if;
+
+   --  If current unit is a body, load its corresponding spec
+
+   if Nkind (Unit (Curunit)) = N_Package_Body
+     or else Nkind (Unit (Curunit)) = N_Subprogram_Body
+   then
+      Spec_Name := Get_Spec_Name (Unit_Name (Cur_Unum));
+      Unum :=
+        Load_Unit
+          (Load_Name  => Spec_Name,
+           Required   => False,
+           Subunit    => False,
+           Error_Node => Curunit,
+           Corr_Body  => Cur_Unum);
+
+      --  If we successfully load the unit, then set the spec pointer. Once
+      --  again note that if the loaded unit has a fatal error, Load will
+      --  have set our Fatal_Error flag to propagate this condition.
+
+      if Unum /= No_Unit then
+         Set_Library_Unit (Curunit, Cunit (Unum));
+
+         --  If this is a separate spec for the main unit, then we reset
+         --  Main_Unit_Entity to point to the entity for this separate spec
+
+         if Cur_Unum = Main_Unit then
+            Main_Unit_Entity := Cunit_Entity (Unum);
+         end if;
+
+      --  If we don't find the spec, then if we have a subprogram body, we
+      --  are still OK, we just have a case of a body acting as its own spec
+
+      elsif Nkind (Unit (Curunit)) = N_Subprogram_Body then
+         Set_Acts_As_Spec (Curunit, True);
+         Set_Library_Unit (Curunit, Curunit);
+
+      --  Otherwise we do have an error, repeat the load request for the spec
+      --  with Required set True to generate an appropriate error message.
+
+      else
+         Unum :=
+           Load_Unit
+             (Load_Name  => Spec_Name,
+              Required   => True,
+              Subunit    => False,
+              Error_Node => Curunit);
+         return;
+      end if;
+
+   --  If current unit is a child unit spec, load its parent
+
+   elsif Nkind (Unit (Curunit)) = N_Package_Declaration
+     or else Nkind (Unit (Curunit)) =  N_Subprogram_Declaration
+     or else Nkind (Unit (Curunit)) in N_Generic_Declaration
+     or else Nkind (Unit (Curunit)) in N_Generic_Instantiation
+     or else Nkind (Unit (Curunit)) in N_Renaming_Declaration
+   then
+      --  Turn style and validity checks off for parent unit
+
+      if not GNAT_Mode then
+         Reset_Style_Check_Options;
+         Reset_Validity_Check_Options;
+      end if;
+
+      Spec_Name := Get_Parent_Spec_Name (Unit_Name (Cur_Unum));
+
+      if Spec_Name /= No_Name then
+         Unum :=
+           Load_Unit
+             (Load_Name  => Spec_Name,
+              Required   => True,
+              Subunit    => False,
+              Error_Node => Curunit);
+
+         if Unum /= No_Unit then
+            Set_Parent_Spec (Unit (Curunit), Cunit (Unum));
+         end if;
+      end if;
+
+   --  If current unit is a subunit, then load its parent body
+
+   elsif Nkind (Unit (Curunit)) = N_Subunit then
+      Body_Name := Get_Parent_Body_Name (Unit_Name (Cur_Unum));
+      Unum :=
+        Load_Unit
+          (Load_Name  => Body_Name,
+           Required   => True,
+           Subunit    => True,
+           Error_Node => Name (Unit (Curunit)));
+
+      if Unum /= No_Unit then
+         Set_Library_Unit (Curunit, Cunit (Unum));
+      end if;
+
+   end if;
+
+   --  Now we load with'ed units, with style/validity checks turned off
+
+   if not GNAT_Mode then
+      Reset_Style_Check_Options;
+      Reset_Validity_Check_Options;
+   end if;
+
+   --  Loop through context items
+
+   Context_Node := First (Context_Items (Curunit));
+   while Present (Context_Node) loop
+
+      if Nkind (Context_Node) = N_With_Clause then
+         With_Node := Context_Node;
+         Spec_Name := Get_Unit_Name (With_Node);
+
+         Unum :=
+           Load_Unit
+             (Load_Name  => Spec_Name,
+              Required   => False,
+              Subunit    => False,
+              Error_Node => With_Node,
+              Renamings  => True);
+
+         --  If we find the unit, then set spec pointer in the N_With_Clause
+         --  to point to the compilation unit for the spec. Remember that
+         --  the Load routine itself sets our Fatal_Error flag if the loaded
+         --  unit gets a fatal error, so we don't need to worry about that.
+
+         if Unum /= No_Unit then
+            Set_Library_Unit (With_Node, Cunit (Unum));
+
+         --  If the spec isn't found, then try finding the corresponding
+         --  body, since it is possible that we have a subprogram body
+         --  that is acting as a spec (since no spec is present).
+
+         else
+            Body_Name := Get_Body_Name (Spec_Name);
+            Unum :=
+              Load_Unit
+                (Load_Name  => Body_Name,
+                 Required   => False,
+                 Subunit    => False,
+                 Error_Node => With_Node,
+                 Renamings  => True);
+
+            --  If we got a subprogram body, then mark that we are using
+            --  the body as a spec in the file table, and set the spec
+            --  pointer in the N_With_Clause to point to the body entity.
+
+            if Unum /= No_Unit
+              and then Nkind (Unit (Cunit (Unum))) = N_Subprogram_Body
+            then
+               With_Cunit := Cunit (Unum);
+               Set_Library_Unit (With_Node, With_Cunit);
+               Set_Acts_As_Spec (With_Cunit, True);
+               Set_Library_Unit (With_Cunit, With_Cunit);
+
+            --  If we couldn't find the body, or if it wasn't a body spec
+            --  then we are in trouble. We make one more call to Load to
+            --  require the spec. We know it will fail of course, the
+            --  purpose is to generate the required error message (we prefer
+            --  that this message refer to the missing spec, not the body)
+
+            else
+               Unum :=
+                 Load_Unit
+                   (Load_Name  => Spec_Name,
+                    Required   => True,
+                    Subunit    => False,
+                    Error_Node => With_Node,
+                    Renamings  => True);
+
+               --  Here we create a dummy package unit for the missing unit
+
+               Unum := Create_Dummy_Package_Unit (With_Node, Spec_Name);
+               Set_Library_Unit (With_Node, Cunit (Unum));
+            end if;
+         end if;
+      end if;
+
+      Next (Context_Node);
+   end loop;
+
+   --  Restore style/validity check mode for main unit
+
+   Set_Style_Check_Options (Save_Style_Checks);
+   Opt.Style_Check := Save_Style_Check;
+   Set_Validity_Check_Options (Save_Validity_Checks);
+   Opt.Validity_Checks_On := Save_Validity_Check;
+end Load;
diff --git a/gcc/ada/par-prag.adb b/gcc/ada/par-prag.adb
new file mode 100644 (file)
index 0000000..bfca40e
--- /dev/null
@@ -0,0 +1,950 @@
+------------------------------------------------------------------------------
+--                                                                          --
+--                         GNAT COMPILER COMPONENTS                         --
+--                                                                          --
+--                             P A R . P R A G                              --
+--                                                                          --
+--                                 B o d y                                  --
+--                                                                          --
+--                            $Revision: 1.149 $
+--                                                                          --
+--          Copyright (C) 1992-2001 Free Software Foundation, Inc.          --
+--                                                                          --
+-- GNAT is free software;  you can  redistribute it  and/or modify it under --
+-- terms of the  GNU General Public License as published  by the Free Soft- --
+-- ware  Foundation;  either version 2,  or (at your option) any later ver- --
+-- sion.  GNAT is distributed in the hope that it will be useful, but WITH- --
+-- OUT 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  distributed with GNAT;  see file COPYING.  If not, write --
+-- to  the Free Software Foundation,  59 Temple Place - Suite 330,  Boston, --
+-- MA 02111-1307, USA.                                                      --
+--                                                                          --
+-- GNAT was originally developed  by the GNAT team at  New York University. --
+-- It is now maintained by Ada Core Technologies Inc (http://www.gnat.com). --
+--                                                                          --
+------------------------------------------------------------------------------
+
+--  Generally the parser checks the basic syntax of pragmas, but does not
+--  do specialized syntax checks for individual pragmas, these are deferred
+--  to semantic analysis time (see unit Sem_Prag). There are some pragmas
+--  which require recognition and either partial or complete processing
+--  during parsing, and this unit performs this required processing.
+
+with Fname.UF; use Fname.UF;
+with Osint;    use Osint;
+with Stringt;  use Stringt;
+with Stylesw;  use Stylesw;
+with Uintp;    use Uintp;
+with Uname;    use Uname;
+
+separate (Par)
+
+function Prag (Pragma_Node : Node_Id; Semi : Source_Ptr) return Node_Id is
+   Pragma_Name : constant Name_Id    := Chars (Pragma_Node);
+   Pragma_Sloc : constant Source_Ptr := Sloc (Pragma_Node);
+   Arg_Count   : Nat;
+   Arg_Node    : Node_Id;
+
+   -----------------------
+   -- Local Subprograms --
+   -----------------------
+
+   function Arg1 return Node_Id;
+   function Arg2 return Node_Id;
+   function Arg3 return Node_Id;
+   function Arg4 return Node_Id;
+   --  Obtain specified Pragma_Argument_Association. It is allowable to call
+   --  the routine for the argument one past the last present argument, but
+   --  that is the only case in which a non-present argument can be referenced.
+
+   procedure Check_Arg_Count (Required : Int);
+   --  Check argument count for pragma = Required.
+   --  If not give error and raise Error_Resync.
+
+   procedure Check_Arg_Is_String_Literal (Arg : Node_Id);
+   --  Check the expression of the specified argument to make sure that it
+   --  is a string literal. If not give error and raise Error_Resync.
+
+   procedure Check_Arg_Is_On_Or_Off (Arg : Node_Id);
+   --  Check the expression of the specified argument to make sure that it
+   --  is an identifier which is either ON or OFF, and if not, then issue
+   --  an error message and raise Error_Resync.
+
+   procedure Check_No_Identifier (Arg : Node_Id);
+   --  Checks that the given argument does not have an identifier. If an
+   --  identifier is present, then an error message is issued, and
+   --  Error_Resync is raised.
+
+   procedure Check_Optional_Identifier (Arg : Node_Id; Id : Name_Id);
+   --  Checks if the given argument has an identifier, and if so, requires
+   --  it to match the given identifier name. If there is a non-matching
+   --  identifier, then an error message is given and Error_Resync raised.
+
+   procedure Check_Required_Identifier (Arg : Node_Id; Id : Name_Id);
+   --  Same as Check_Optional_Identifier, except that the name is required
+   --  to be present and to match the given Id value.
+
+   ----------
+   -- Arg1 --
+   ----------
+
+   function Arg1 return Node_Id is
+   begin
+      return First (Pragma_Argument_Associations (Pragma_Node));
+   end Arg1;
+
+   ----------
+   -- Arg2 --
+   ----------
+
+   function Arg2 return Node_Id is
+   begin
+      return Next (Arg1);
+   end Arg2;
+
+   ----------
+   -- Arg3 --
+   ----------
+
+   function Arg3 return Node_Id is
+   begin
+      return Next (Arg2);
+   end Arg3;
+
+   ----------
+   -- Arg4 --
+   ----------
+
+   function Arg4 return Node_Id is
+   begin
+      return Next (Arg3);
+   end Arg4;
+
+   ---------------------
+   -- Check_Arg_Count --
+   ---------------------
+
+   procedure Check_Arg_Count (Required : Int) is
+   begin
+      if Arg_Count /= Required then
+         Error_Msg ("wrong number of arguments for pragma%", Pragma_Sloc);
+         raise Error_Resync;
+      end if;
+   end Check_Arg_Count;
+
+   ----------------------------
+   -- Check_Arg_Is_On_Or_Off --
+   ----------------------------
+
+   procedure Check_Arg_Is_On_Or_Off (Arg : Node_Id) is
+      Argx : constant Node_Id := Expression (Arg);
+
+   begin
+      if Nkind (Expression (Arg)) /= N_Identifier
+        or else (Chars (Argx) /= Name_On
+                   and then
+                 Chars (Argx) /= Name_Off)
+      then
+         Error_Msg_Name_2 := Name_On;
+         Error_Msg_Name_3 := Name_Off;
+
+         Error_Msg
+           ("argument for pragma% must be% or%", Sloc (Argx));
+         raise Error_Resync;
+      end if;
+   end Check_Arg_Is_On_Or_Off;
+
+   ---------------------------------
+   -- Check_Arg_Is_String_Literal --
+   ---------------------------------
+
+   procedure Check_Arg_Is_String_Literal (Arg : Node_Id) is
+   begin
+      if Nkind (Expression (Arg)) /= N_String_Literal then
+         Error_Msg
+           ("argument for pragma% must be string literal",
+             Sloc (Expression (Arg)));
+         raise Error_Resync;
+      end if;
+   end Check_Arg_Is_String_Literal;
+
+   -------------------------
+   -- Check_No_Identifier --
+   -------------------------
+
+   procedure Check_No_Identifier (Arg : Node_Id) is
+   begin
+      if Chars (Arg) /= No_Name then
+         Error_Msg_N ("pragma% does not permit named arguments", Arg);
+         raise Error_Resync;
+      end if;
+   end Check_No_Identifier;
+
+   -------------------------------
+   -- Check_Optional_Identifier --
+   -------------------------------
+
+   procedure Check_Optional_Identifier (Arg : Node_Id; Id : Name_Id) is
+   begin
+      if Present (Arg) and then Chars (Arg) /= No_Name then
+         if Chars (Arg) /= Id then
+            Error_Msg_Name_2 := Id;
+            Error_Msg_N ("pragma% argument expects identifier%", Arg);
+         end if;
+      end if;
+   end Check_Optional_Identifier;
+
+   -------------------------------
+   -- Check_Required_Identifier --
+   -------------------------------
+
+   procedure Check_Required_Identifier (Arg : Node_Id; Id : Name_Id) is
+   begin
+      if Chars (Arg) /= Id then
+         Error_Msg_Name_2 := Id;
+         Error_Msg_N ("pragma% argument must have identifier%", Arg);
+      end if;
+   end Check_Required_Identifier;
+
+   ----------
+   -- Prag --
+   ----------
+
+begin
+   Error_Msg_Name_1 := Pragma_Name;
+
+   --  Count number of arguments. This loop also checks if any of the arguments
+   --  are Error, indicating a syntax error as they were parsed. If so, we
+   --  simply return, because we get into trouble with cascaded errors if we
+   --  try to perform our error checks on junk arguments.
+
+   Arg_Count := 0;
+
+   if Present (Pragma_Argument_Associations (Pragma_Node)) then
+      Arg_Node := Arg1;
+
+      while Arg_Node /= Empty loop
+         Arg_Count := Arg_Count + 1;
+
+         if Expression (Arg_Node) = Error then
+            return Error;
+         end if;
+
+         Next (Arg_Node);
+      end loop;
+   end if;
+
+   --  Remaining processing is pragma dependent
+
+   case Get_Pragma_Id (Pragma_Name) is
+
+      ------------
+      -- Ada_83 --
+      ------------
+
+      --  This pragma must be processed at parse time, since we want to set
+      --  the Ada 83 and Ada 95 switches properly at parse time to recognize
+      --  Ada 83 syntax or Ada 95 syntax as appropriate.
+
+      when Pragma_Ada_83 =>
+         Ada_83 := True;
+         Ada_95 := False;
+
+      ------------
+      -- Ada_95 --
+      ------------
+
+      --  This pragma must be processed at parse time, since we want to set
+      --  the Ada 83 and Ada_95 switches properly at parse time to recognize
+      --  Ada 83 syntax or Ada 95 syntax as appropriate.
+
+      when Pragma_Ada_95 =>
+         Ada_83 := False;
+         Ada_95 := True;
+
+      -----------
+      -- Debug --
+      -----------
+
+      --  pragma Debug (PROCEDURE_CALL_STATEMENT);
+
+      --  This has to be processed by the parser because of the very peculiar
+      --  form of the second parameter, which is syntactically from a formal
+      --  point of view a function call (since it must be an expression), but
+      --  semantically we treat it as a procedure call (which has exactly the
+      --  same syntactic form, so that's why we can get away with this!)
+
+      when Pragma_Debug =>
+         Check_Arg_Count (1);
+         Check_No_Identifier (Arg1);
+
+         declare
+            Expr : constant Node_Id := New_Copy (Expression (Arg1));
+
+         begin
+            if Nkind (Expr) /= N_Indexed_Component
+              and then Nkind (Expr) /= N_Function_Call
+              and then Nkind (Expr) /= N_Identifier
+              and then Nkind (Expr) /= N_Selected_Component
+            then
+               Error_Msg
+                 ("argument of pragma% is not procedure call", Sloc (Expr));
+               raise Error_Resync;
+            else
+               Set_Debug_Statement
+                 (Pragma_Node, P_Statement_Name (Expr));
+            end if;
+         end;
+
+      -------------------------------
+      -- Extensions_Allowed (GNAT) --
+      -------------------------------
+
+      --  pragma Extensions_Allowed (Off | On)
+
+      --  The processing for pragma Extensions_Allowed must be done at
+      --  parse time, since extensions mode may affect what is accepted.
+
+      when Pragma_Extensions_Allowed =>
+         Check_Arg_Count (1);
+         Check_No_Identifier (Arg1);
+         Check_Arg_Is_On_Or_Off (Arg1);
+         Opt.Extensions_Allowed := (Chars (Expression (Arg1)) = Name_On);
+
+      ----------------
+      -- List (2.8) --
+      ----------------
+
+      --  pragma List (Off | On)
+
+      --  The processing for pragma List must be done at parse time,
+      --  since a listing can be generated in parse only mode.
+
+      when Pragma_List =>
+         Check_Arg_Count (1);
+         Check_No_Identifier (Arg1);
+         Check_Arg_Is_On_Or_Off (Arg1);
+
+         --  We unconditionally make a List_On entry for the pragma, so that
+         --  in the List (Off) case, the pragma will print even in a region
+         --  of code with listing turned off (this is required!)
+
+         List_Pragmas.Increment_Last;
+         List_Pragmas.Table (List_Pragmas.Last) :=
+           (Ptyp => List_On, Ploc => Sloc (Pragma_Node));
+
+         --  Now generate the list off entry for pragma List (Off)
+
+         if Chars (Expression (Arg1)) = Name_Off then
+            List_Pragmas.Increment_Last;
+            List_Pragmas.Table (List_Pragmas.Last) :=
+              (Ptyp => List_Off, Ploc => Semi);
+         end if;
+
+      ----------------
+      -- Page (2.8) --
+      ----------------
+
+      --  pragma Page;
+
+      --  Processing for this pragma must be done at parse time, since a
+      --  listing can be generated in parse only mode with semantics off.
+
+      when Pragma_Page =>
+         Check_Arg_Count (0);
+         List_Pragmas.Increment_Last;
+         List_Pragmas.Table (List_Pragmas.Last) := (Page, Semi);
+
+      -----------------------------
+      -- Source_File_Name (GNAT) --
+      -----------------------------
+
+      --  There are five forms of this pragma:
+
+      --  pragma Source_File_Name (
+      --    [UNIT_NAME      =>] unit_NAME,
+      --     BODY_FILE_NAME =>  STRING_LITERAL);
+
+      --  pragma Source_File_Name (
+      --    [UNIT_NAME      =>] unit_NAME,
+      --     SPEC_FILE_NAME =>  STRING_LITERAL);
+
+      --  pragma Source_File_Name (
+      --     BODY_FILE_NAME  => STRING_LITERAL
+      --  [, DOT_REPLACEMENT => STRING_LITERAL]
+      --  [, CASING          => CASING_SPEC]);
+
+      --  pragma Source_File_Name (
+      --     SPEC_FILE_NAME  => STRING_LITERAL
+      --  [, DOT_REPLACEMENT => STRING_LITERAL]
+      --  [, CASING          => CASING_SPEC]);
+
+      --  pragma Source_File_Name (
+      --     SUBUNIT_FILE_NAME  => STRING_LITERAL
+      --  [, DOT_REPLACEMENT    => STRING_LITERAL]
+      --  [, CASING             => CASING_SPEC]);
+
+      --  CASING_SPEC ::= Uppercase | Lowercase | Mixedcase
+
+      --  Note: we process this during parsing, since we need to have the
+      --  source file names set well before the semantic analysis starts,
+      --  since we load the spec and with'ed packages before analysis.
+
+      when Pragma_Source_File_Name => Source_File_Name : declare
+         Unam  : Unit_Name_Type;
+         Expr1 : Node_Id;
+         Pat   : String_Ptr;
+         Typ   : Character;
+         Dot   : String_Ptr;
+         Cas   : Casing_Type;
+         Nast  : Nat;
+
+         function Get_Fname (Arg : Node_Id) return Name_Id;
+         --  Process file name from unit name form of pragma
+
+         function Get_String_Argument (Arg : Node_Id) return String_Ptr;
+         --  Process string literal value from argument
+
+         procedure Process_Casing (Arg : Node_Id);
+         --  Process Casing argument of pattern form of pragma
+
+         procedure Process_Dot_Replacement (Arg : Node_Id);
+         --  Process Dot_Replacement argument of patterm form of pragma
+
+         ---------------
+         -- Get_Fname --
+         ---------------
+
+         function Get_Fname (Arg : Node_Id) return Name_Id is
+         begin
+            String_To_Name_Buffer (Strval (Expression (Arg)));
+
+            for J in 1 .. Name_Len loop
+               if Is_Directory_Separator (Name_Buffer (J)) then
+                  Error_Msg
+                    ("directory separator character not allowed",
+                     Sloc (Expression (Arg)) + Source_Ptr (J));
+               end if;
+            end loop;
+
+            return Name_Find;
+         end Get_Fname;
+
+         -------------------------
+         -- Get_String_Argument --
+         -------------------------
+
+         function Get_String_Argument (Arg : Node_Id) return String_Ptr is
+            Str : String_Id;
+
+         begin
+            if Nkind (Expression (Arg)) /= N_String_Literal
+              and then
+               Nkind (Expression (Arg)) /= N_Operator_Symbol
+            then
+               Error_Msg_N
+                 ("argument for pragma% must be string literal", Arg);
+               raise Error_Resync;
+            end if;
+
+            Str := Strval (Expression (Arg));
+
+            --  Check string has no wide chars
+
+            for J in 1 .. String_Length (Str) loop
+               if Get_String_Char (Str, J) > 255 then
+                  Error_Msg
+                    ("wide character not allowed in pattern for pragma%",
+                     Sloc (Expression (Arg2)) + Text_Ptr (J) - 1);
+               end if;
+            end loop;
+
+            --  Acquire string
+
+            String_To_Name_Buffer (Str);
+            return new String'(Name_Buffer (1 .. Name_Len));
+         end Get_String_Argument;
+
+         --------------------
+         -- Process_Casing --
+         --------------------
+
+         procedure Process_Casing (Arg : Node_Id) is
+            Expr : constant Node_Id := Expression (Arg);
+
+         begin
+            Check_Required_Identifier (Arg, Name_Casing);
+
+            if Nkind (Expr) = N_Identifier then
+               if Chars (Expr) = Name_Lowercase then
+                  Cas := All_Lower_Case;
+                  return;
+               elsif Chars (Expr) = Name_Uppercase then
+                  Cas := All_Upper_Case;
+                  return;
+               elsif Chars (Expr) = Name_Mixedcase then
+                  Cas := Mixed_Case;
+                  return;
+               end if;
+            end if;
+
+            Error_Msg_N
+              ("Casing argument for pragma% must be " &
+               "one of Mixedcase, Lowercase, Uppercase",
+               Arg);
+         end Process_Casing;
+
+         -----------------------------
+         -- Process_Dot_Replacement --
+         -----------------------------
+
+         procedure Process_Dot_Replacement (Arg : Node_Id) is
+         begin
+            Check_Required_Identifier (Arg, Name_Dot_Replacement);
+            Dot := Get_String_Argument (Arg);
+         end Process_Dot_Replacement;
+
+      --  Start of processing for Source_File_Name pragma
+
+      begin
+         --  We permit from 1 to 3 arguments
+
+         if Arg_Count not in 1 .. 3 then
+            Check_Arg_Count (1);
+         end if;
+
+         Expr1 := Expression (Arg1);
+
+         --  If first argument is identifier or selected component, then
+         --  we have the specific file case of the Source_File_Name pragma,
+         --  and the first argument is a unit name.
+
+         if Nkind (Expr1) = N_Identifier
+           or else
+             (Nkind (Expr1) = N_Selected_Component
+               and then
+              Nkind (Selector_Name (Expr1)) = N_Identifier)
+         then
+            Check_Arg_Count (2);
+
+            Check_Optional_Identifier (Arg1, Name_Unit_Name);
+            Unam := Get_Unit_Name (Expr1);
+
+            Check_Arg_Is_String_Literal (Arg2);
+
+            if Chars (Arg2) = Name_Spec_File_Name then
+               Set_File_Name (Get_Spec_Name (Unam), Get_Fname (Arg2));
+
+            elsif Chars (Arg2) = Name_Body_File_Name then
+               Set_File_Name (Unam, Get_Fname (Arg2));
+
+            else
+               Error_Msg_N ("pragma% argument has incorrect identifier", Arg2);
+               return Pragma_Node;
+            end if;
+
+         --  If the first argument is not an identifier, then we must have
+         --  the pattern form of the pragma, and the first argument must be
+         --  the pattern string with an appropriate name.
+
+         else
+            if Chars (Arg1) = Name_Spec_File_Name then
+               Typ := 's';
+
+            elsif Chars (Arg1) = Name_Body_File_Name then
+               Typ := 'b';
+
+            elsif Chars (Arg1) = Name_Subunit_File_Name then
+               Typ := 'u';
+
+            elsif Chars (Arg1) = Name_Unit_Name then
+               Error_Msg_N
+                 ("Unit_Name parameter for pragma% must be an identifier",
+                  Arg1);
+               raise Error_Resync;
+
+            else
+               Error_Msg_N ("pragma% argument has incorrect identifier", Arg1);
+               raise Error_Resync;
+            end if;
+
+            Pat := Get_String_Argument (Arg1);
+
+            --  Check pattern has exactly one asterisk
+
+            Nast := 0;
+            for J in Pat'Range loop
+               if Pat (J) = '*' then
+                  Nast := Nast + 1;
+               end if;
+            end loop;
+
+            if Nast /= 1 then
+               Error_Msg_N
+                 ("file name pattern must have exactly one * character",
+                  Arg2);
+               return Pragma_Node;
+            end if;
+
+            --  Set defaults for Casing and Dot_Separator parameters
+
+            Cas := All_Lower_Case;
+
+            Dot := new String'(".");
+
+            --  Process second and third arguments if present
+
+            if Arg_Count > 1 then
+               if Chars (Arg2) = Name_Casing then
+                  Process_Casing (Arg2);
+
+                  if Arg_Count = 3 then
+                     Process_Dot_Replacement (Arg3);
+                  end if;
+
+               else
+                  Process_Dot_Replacement (Arg2);
+
+                  if Arg_Count = 3 then
+                     Process_Casing (Arg3);
+                  end if;
+               end if;
+            end if;
+
+            Set_File_Name_Pattern (Pat, Typ, Dot, Cas);
+         end if;
+      end Source_File_Name;
+
+      -----------------------------
+      -- Source_Reference (GNAT) --
+      -----------------------------
+
+      --  pragma Source_Reference
+      --    (INTEGER_LITERAL [, STRING_LITERAL] );
+
+      --  Processing for this pragma must be done at parse time, since error
+      --  messages needing the proper line numbers can be generated in parse
+      --  only mode with semantic checking turned off, and indeed we usually
+      --  turn off semantic checking anyway if any parse errors are found.
+
+      when Pragma_Source_Reference => Source_Reference : declare
+         Fname : Name_Id;
+
+      begin
+         if Arg_Count /= 1 then
+            Check_Arg_Count (2);
+            Check_No_Identifier (Arg2);
+         end if;
+
+         --  Check that this is first line of file. We skip this test if
+         --  we are in syntax check only mode, since we may be dealing with
+         --  multiple compilation units.
+
+         if Get_Physical_Line_Number (Pragma_Sloc) /= 1
+           and then Num_SRef_Pragmas (Current_Source_File) = 0
+           and then Operating_Mode /= Check_Syntax
+         then
+            Error_Msg
+              ("first % pragma must be first line of file", Pragma_Sloc);
+            raise Error_Resync;
+         end if;
+
+         Check_No_Identifier (Arg1);
+
+         if Arg_Count = 1 then
+            if Num_SRef_Pragmas (Current_Source_File) = 0 then
+               Error_Msg
+                 ("file name required for first % pragma in file",
+                  Pragma_Sloc);
+               raise Error_Resync;
+
+            else
+               Fname := No_Name;
+            end if;
+
+         --  File name present
+
+         else
+            Check_Arg_Is_String_Literal (Arg2);
+            String_To_Name_Buffer (Strval (Expression (Arg2)));
+            Fname := Name_Find;
+
+            if Num_SRef_Pragmas (Current_Source_File) > 0 then
+               if Fname /= Full_Ref_Name (Current_Source_File) then
+                  Error_Msg
+                    ("file name must be same in all % pragmas", Pragma_Sloc);
+                  raise Error_Resync;
+               end if;
+            end if;
+         end if;
+
+         if Nkind (Expression (Arg1)) /= N_Integer_Literal then
+            Error_Msg
+              ("argument for pragma% must be integer literal",
+                Sloc (Expression (Arg1)));
+            raise Error_Resync;
+
+         --  OK, this source reference pragma is effective, however, we
+         --  ignore it if it is not in the first unit in the multiple unit
+         --  case. This is because the only purpose in this case is to
+         --  provide source pragmas for subsequent use by gnatchop.
+
+         else
+            if Num_Library_Units = 1 then
+               Register_Source_Ref_Pragma
+                 (Fname,
+                  Strip_Directory (Fname),
+                  UI_To_Int (Intval (Expression (Arg1))),
+                  Get_Physical_Line_Number (Pragma_Sloc) + 1);
+            end if;
+         end if;
+      end Source_Reference;
+
+      -------------------------
+      -- Style_Checks (GNAT) --
+      -------------------------
+
+      --  pragma Style_Checks (On | Off | ALL_CHECKS | STRING_LITERAL);
+
+      --  This is processed by the parser since some of the style
+      --  checks take place during source scanning and parsing.
+
+      when Pragma_Style_Checks => Style_Checks : declare
+         A  : Node_Id;
+         S  : String_Id;
+         C  : Char_Code;
+         OK : Boolean := True;
+
+      begin
+         --  Two argument case is only for semantics
+
+         if Arg_Count = 2 then
+            null;
+
+         else
+            Check_Arg_Count (1);
+            Check_No_Identifier (Arg1);
+            A := Expression (Arg1);
+
+            if Nkind (A) = N_String_Literal then
+               S   := Strval (A);
+
+               declare
+                  Slen    : Natural := Natural (String_Length (S));
+                  Options : String (1 .. Slen);
+                  J       : Natural;
+                  Ptr     : Natural;
+
+               begin
+                  J := 1;
+                  loop
+                     C := Get_String_Char (S, Int (J));
+
+                     if not In_Character_Range (C) then
+                        OK := False;
+                        Ptr := J;
+                        exit;
+
+                     else
+                        Options (J) := Get_Character (C);
+                     end if;
+
+                     if J = Slen then
+                        Set_Style_Check_Options (Options, OK, Ptr);
+                        exit;
+
+                     else
+                        J := J + 1;
+                     end if;
+                  end loop;
+
+                  if not OK then
+                     Error_Msg
+                       ("invalid style check option",
+                        Sloc (Expression (Arg1)) + Source_Ptr (Ptr));
+                     raise Error_Resync;
+                  end if;
+               end;
+
+            elsif Nkind (A) /= N_Identifier then
+               OK := False;
+
+            elsif Chars (A) = Name_All_Checks then
+               Stylesw.Set_Default_Style_Check_Options;
+
+            elsif Chars (A) = Name_On then
+               Style_Check := True;
+
+            elsif Chars (A) = Name_Off then
+               Style_Check := False;
+
+            else
+               OK := False;
+            end if;
+
+            if not OK then
+               Error_Msg ("incorrect argument for pragma%", Sloc (A));
+               raise Error_Resync;
+            end if;
+         end if;
+      end Style_Checks;
+
+      ---------------------
+      -- Warnings (GNAT) --
+      ---------------------
+
+      --  pragma Warnings (On | Off, [LOCAL_NAME])
+
+      --  The one argument case is processed by the parser, since it may
+      --  control parser warnings as well as semantic warnings, and in any
+      --  case we want to be absolutely sure that the range in the warnings
+      --  table is set well before any semantic analysis is performed.
+
+      when Pragma_Warnings =>
+         if Arg_Count = 1 then
+            Check_No_Identifier (Arg1);
+            Check_Arg_Is_On_Or_Off (Arg1);
+
+            if Chars (Expression (Arg1)) = Name_On then
+               Set_Warnings_Mode_On (Pragma_Sloc);
+            else
+               Set_Warnings_Mode_Off (Pragma_Sloc);
+            end if;
+         end if;
+
+      -----------------------
+      -- All Other Pragmas --
+      -----------------------
+
+      --  For all other pragmas, checking and processing is handled
+      --  entirely in Sem_Prag, and no further checking is done by Par.
+
+      when Pragma_Abort_Defer              |
+           Pragma_AST_Entry                |
+           Pragma_All_Calls_Remote         |
+           Pragma_Annotate                 |
+           Pragma_Assert                   |
+           Pragma_Asynchronous             |
+           Pragma_Atomic                   |
+           Pragma_Atomic_Components        |
+           Pragma_Attach_Handler           |
+           Pragma_CPP_Class                |
+           Pragma_CPP_Constructor          |
+           Pragma_CPP_Virtual              |
+           Pragma_CPP_Vtable               |
+           Pragma_C_Pass_By_Copy           |
+           Pragma_Comment                  |
+           Pragma_Common_Object            |
+           Pragma_Complex_Representation   |
+           Pragma_Component_Alignment      |
+           Pragma_Controlled               |
+           Pragma_Convention               |
+           Pragma_Discard_Names            |
+           Pragma_Eliminate                |
+           Pragma_Elaborate                |
+           Pragma_Elaborate_All            |
+           Pragma_Elaborate_Body           |
+           Pragma_Elaboration_Checks       |
+           Pragma_Export                   |
+           Pragma_Export_Exception         |
+           Pragma_Export_Function          |
+           Pragma_Export_Object            |
+           Pragma_Export_Procedure         |
+           Pragma_Export_Valued_Procedure  |
+           Pragma_Extend_System            |
+           Pragma_External_Name_Casing     |
+           Pragma_Finalize_Storage_Only    |
+           Pragma_Float_Representation     |
+           Pragma_Ident                    |
+           Pragma_Import                   |
+           Pragma_Import_Exception         |
+           Pragma_Import_Function          |
+           Pragma_Import_Object            |
+           Pragma_Import_Procedure         |
+           Pragma_Import_Valued_Procedure  |
+           Pragma_Initialize_Scalars       |
+           Pragma_Inline                   |
+           Pragma_Inline_Always            |
+           Pragma_Inline_Generic           |
+           Pragma_Inspection_Point         |
+           Pragma_Interface                |
+           Pragma_Interface_Name           |
+           Pragma_Interrupt_Handler        |
+           Pragma_Interrupt_Priority       |
+           Pragma_Java_Constructor         |
+           Pragma_Java_Interface           |
+           Pragma_License                  |
+           Pragma_Link_With                |
+           Pragma_Linker_Alias             |
+           Pragma_Linker_Options           |
+           Pragma_Linker_Section           |
+           Pragma_Locking_Policy           |
+           Pragma_Long_Float               |
+           Pragma_Machine_Attribute        |
+           Pragma_Main                     |
+           Pragma_Main_Storage             |
+           Pragma_Memory_Size              |
+           Pragma_No_Return                |
+           Pragma_No_Run_Time              |
+           Pragma_Normalize_Scalars        |
+           Pragma_Optimize                 |
+           Pragma_Pack                     |
+           Pragma_Passive                  |
+           Pragma_Polling                  |
+           Pragma_Preelaborate             |
+           Pragma_Priority                 |
+           Pragma_Propagate_Exceptions     |
+           Pragma_Psect_Object             |
+           Pragma_Pure                     |
+           Pragma_Pure_Function            |
+           Pragma_Queuing_Policy           |
+           Pragma_Remote_Call_Interface    |
+           Pragma_Remote_Types             |
+           Pragma_Restrictions             |
+           Pragma_Restricted_Run_Time      |
+           Pragma_Ravenscar                |
+           Pragma_Reviewable               |
+           Pragma_Share_Generic            |
+           Pragma_Shared                   |
+           Pragma_Shared_Passive           |
+           Pragma_Storage_Size             |
+           Pragma_Storage_Unit             |
+           Pragma_Stream_Convert           |
+           Pragma_Subtitle                 |
+           Pragma_Suppress                 |
+           Pragma_Suppress_All             |
+           Pragma_Suppress_Debug_Info      |
+           Pragma_Suppress_Initialization  |
+           Pragma_System_Name              |
+           Pragma_Task_Dispatching_Policy  |
+           Pragma_Task_Info                |
+           Pragma_Task_Name                |
+           Pragma_Task_Storage             |
+           Pragma_Time_Slice               |
+           Pragma_Title                    |
+           Pragma_Unchecked_Union          |
+           Pragma_Unimplemented_Unit       |
+           Pragma_Unreserve_All_Interrupts |
+           Pragma_Unsuppress               |
+           Pragma_Use_VADS_Size            |
+           Pragma_Volatile                 |
+           Pragma_Volatile_Components      |
+           Pragma_Weak_External            |
+           Pragma_Validity_Checks          =>
+         null;
+
+   end case;
+
+   return Pragma_Node;
+
+   --------------------
+   -- Error Handling --
+   --------------------
+
+exception
+   when Error_Resync =>
+      return Error;
+
+end Prag;
diff --git a/gcc/ada/par-sync.adb b/gcc/ada/par-sync.adb
new file mode 100644 (file)
index 0000000..d1ba793
--- /dev/null
@@ -0,0 +1,312 @@
+------------------------------------------------------------------------------
+--                                                                          --
+--                         GNAT COMPILER COMPONENTS                         --
+--                                                                          --
+--                             P A R . S Y N C                              --
+--                                                                          --
+--                                 B o d y                                  --
+--                                                                          --
+--                            $Revision: 1.19 $
+--                                                                          --
+--          Copyright (C) 1992-2001 Free Software Foundation, Inc.          --
+--                                                                          --
+-- GNAT is free software;  you can  redistribute it  and/or modify it under --
+-- terms of the  GNU General Public License as published  by the Free Soft- --
+-- ware  Foundation;  either version 2,  or (at your option) any later ver- --
+-- sion.  GNAT is distributed in the hope that it will be useful, but WITH- --
+-- OUT 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  distributed with GNAT;  see file COPYING.  If not, write --
+-- to  the Free Software Foundation,  59 Temple Place - Suite 330,  Boston, --
+-- MA 02111-1307, USA.                                                      --
+--                                                                          --
+-- GNAT was originally developed  by the GNAT team at  New York University. --
+-- It is now maintained by Ada Core Technologies Inc (http://www.gnat.com). --
+--                                                                          --
+------------------------------------------------------------------------------
+
+separate (Par)
+package body Sync is
+
+   procedure Resync_Init;
+   --  This routine is called on initiating a resynchronization action
+
+   procedure Resync_Resume;
+   --  This routine is called on completing a resynchronization action
+
+   -------------------
+   -- Resync_Choice --
+   -------------------
+
+   procedure Resync_Choice is
+   begin
+      Resync_Init;
+
+      --  Loop till we get a token that terminates a choice. Note that EOF is
+      --  one such token, so we are sure to get out of this loop eventually!
+
+      while Token not in Token_Class_Cterm loop
+         Scan;
+      end loop;
+
+      Resync_Resume;
+   end Resync_Choice;
+
+   ------------------
+   -- Resync_Cunit --
+   ------------------
+
+   procedure Resync_Cunit is
+   begin
+      Resync_Init;
+
+      while Token not in Token_Class_Cunit
+        and then Token /= Tok_EOF
+      loop
+         Scan;
+      end loop;
+
+      Resync_Resume;
+   end Resync_Cunit;
+
+   -----------------------
+   -- Resync_Expression --
+   -----------------------
+
+   procedure Resync_Expression is
+      Paren_Count : Int;
+
+   begin
+      Resync_Init;
+      Paren_Count := 0;
+
+      loop
+         --  Terminating tokens are those in class Eterm and also RANGE,
+         --  DIGITS or DELTA if not preceded by an apostrophe (if they are
+         --  preceded by an apostrophe, then they are attributes). In addiion,
+         --  at the outer parentheses level only, we also consider a comma,
+         --  right parenthesis or vertical bar to terminate an expression.
+
+         if Token in Token_Class_Eterm
+
+           or else (Token in Token_Class_Atkwd
+                     and then Prev_Token /= Tok_Apostrophe)
+
+           or else (Paren_Count = 0
+                     and then
+                       (Token = Tok_Comma
+                         or else Token = Tok_Right_Paren
+                         or else Token = Tok_Vertical_Bar))
+         then
+            --  A special check: if we stop on the ELSE of OR ELSE or the
+            --  THEN of AND THEN, keep going, because this is not really an
+            --  expression terminator after all. Also, keep going past WITH
+            --  since this can be part of an extension aggregate
+
+            if (Token = Tok_Else and then Prev_Token = Tok_Or)
+               or else (Token = Tok_Then and then Prev_Token = Tok_And)
+               or else Token = Tok_With
+            then
+               null;
+            else
+               exit;
+            end if;
+         end if;
+
+         if Token = Tok_Left_Paren then
+            Paren_Count := Paren_Count + 1;
+
+         elsif Token = Tok_Right_Paren then
+            Paren_Count := Paren_Count - 1;
+
+         end if;
+
+         Scan; -- past token to be skipped
+      end loop;
+
+      Resync_Resume;
+   end Resync_Expression;
+
+   -----------------
+   -- Resync_Init --
+   -----------------
+
+   procedure Resync_Init is
+   begin
+      --  The following check makes sure we do not get stuck in an infinite
+      --  loop resynchonizing and getting nowhere. If we are called to do a
+      --  resynchronize and we are exactly at the same point that we left off
+      --  on the last resynchronize call, then we force at least one token to
+      --  be skipped so that we make progress!
+
+      if Token_Ptr = Last_Resync_Point then
+         Scan; -- to skip at least one token
+      end if;
+
+      --  Output extra error message if debug R flag is set
+
+      if Debug_Flag_R then
+         Error_Msg_SC ("resynchronizing!");
+      end if;
+   end Resync_Init;
+
+   ---------------------------
+   -- Resync_Past_Semicolon --
+   ---------------------------
+
+   procedure Resync_Past_Semicolon is
+   begin
+      Resync_Init;
+
+      loop
+         --  Done if we are at a semicolon
+
+         if Token = Tok_Semicolon then
+            Scan; -- past semicolon
+            exit;
+
+         --  Done if we are at a token which normally appears only after
+         --  a semicolon. One special glitch is that the keyword private is
+         --  in this category only if it does NOT appear after WITH.
+
+         elsif Token in Token_Class_After_SM
+            and then (Token /= Tok_Private or else Prev_Token /= Tok_With)
+         then
+            exit;
+
+         --  Otherwise keep going
+
+         else
+            Scan;
+         end if;
+      end loop;
+
+      --  Fall out of loop with resyncrhonization complete
+
+      Resync_Resume;
+   end Resync_Past_Semicolon;
+
+   ----------------------------------------------
+   -- Resync_Past_Semicolon_Or_To_Loop_Or_Then --
+   ----------------------------------------------
+
+   procedure Resync_Past_Semicolon_Or_To_Loop_Or_Then is
+   begin
+      Resync_Init;
+
+      loop
+         --  Done if at semicolon
+
+         if Token = Tok_Semicolon then
+            Scan; -- past the semicolon
+            exit;
+
+         --  Done if we are at a token which normally appears only after
+         --  a semicolon. One special glitch is that the keyword private is
+         --  in this category only if it does NOT appear after WITH.
+
+         elsif (Token in Token_Class_After_SM
+                  and then (Token /= Tok_Private
+                              or else Prev_Token /= Tok_With))
+         then
+            exit;
+
+         --  Done if we are at THEN or LOOP
+
+         elsif Token = Tok_Then or else Token = Tok_Loop then
+            exit;
+
+         --  Otherwise keep going
+
+         else
+            Scan;
+         end if;
+      end loop;
+
+      --  Fall out of loop with resyncrhonization complete
+
+      Resync_Resume;
+   end Resync_Past_Semicolon_Or_To_Loop_Or_Then;
+
+   -------------------
+   -- Resync_Resume --
+   -------------------
+
+   procedure Resync_Resume is
+   begin
+      --  Save resync point (see special test in Resync_Init)
+
+      Last_Resync_Point := Token_Ptr;
+
+      if Debug_Flag_R then
+         Error_Msg_SC ("resuming here!");
+      end if;
+   end Resync_Resume;
+
+   --------------------
+   -- Resync_To_When --
+   --------------------
+
+   procedure Resync_To_When is
+   begin
+      Resync_Init;
+
+      loop
+         --  Done if at semicolon, WHEN or IS
+
+         if Token = Tok_Semicolon
+           or else Token = Tok_When
+           or else Token = Tok_Is
+         then
+            exit;
+
+         --  Otherwise keep going
+
+         else
+            Scan;
+         end if;
+      end loop;
+
+      --  Fall out of loop with resyncrhonization complete
+
+      Resync_Resume;
+   end Resync_To_When;
+
+   ---------------------------
+   -- Resync_Semicolon_List --
+   ---------------------------
+
+   procedure Resync_Semicolon_List is
+      Paren_Count : Int;
+
+   begin
+      Resync_Init;
+      Paren_Count := 0;
+
+      loop
+         if Token = Tok_EOF
+           or else Token = Tok_Semicolon
+           or else Token = Tok_Is
+           or else Token in Token_Class_After_SM
+         then
+            exit;
+
+         elsif Token = Tok_Left_Paren then
+            Paren_Count := Paren_Count + 1;
+
+         elsif Token = Tok_Right_Paren then
+            if Paren_Count = 0 then
+               exit;
+            else
+               Paren_Count := Paren_Count - 1;
+            end if;
+         end if;
+
+         Scan;
+      end loop;
+
+      Resync_Resume;
+   end Resync_Semicolon_List;
+
+end Sync;
diff --git a/gcc/ada/par-tchk.adb b/gcc/ada/par-tchk.adb
new file mode 100644 (file)
index 0000000..4d49e7a
--- /dev/null
@@ -0,0 +1,812 @@
+------------------------------------------------------------------------------
+--                                                                          --
+--                         GNAT COMPILER COMPONENTS                         --
+--                                                                          --
+--                             P A R . T C H K                              --
+--                                                                          --
+--                                 B o d y                                  --
+--                                                                          --
+--                            $Revision: 1.37 $
+--                                                                          --
+--          Copyright (C) 1992-2001 Free Software Foundation, Inc.          --
+--                                                                          --
+-- GNAT is free software;  you can  redistribute it  and/or modify it under --
+-- terms of the  GNU General Public License as published  by the Free Soft- --
+-- ware  Foundation;  either version 2,  or (at your option) any later ver- --
+-- sion.  GNAT is distributed in the hope that it will be useful, but WITH- --
+-- OUT 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  distributed with GNAT;  see file COPYING.  If not, write --
+-- to  the Free Software Foundation,  59 Temple Place - Suite 330,  Boston, --
+-- MA 02111-1307, USA.                                                      --
+--                                                                          --
+-- GNAT was originally developed  by the GNAT team at  New York University. --
+-- It is now maintained by Ada Core Technologies Inc (http://www.gnat.com). --
+--                                                                          --
+------------------------------------------------------------------------------
+
+--  Token scan routines.
+
+--  Error recovery: none of the T_xxx or TF_xxx routines raise Error_Resync
+
+separate (Par)
+package body Tchk is
+
+   type Position is (SC, BC, AP);
+   --  Specify position of error message (see Error_Msg_SC/BC/AP)
+
+   -----------------------
+   -- Local Subprograms --
+   -----------------------
+
+   procedure Check_Token (T : Token_Type; P : Position);
+   pragma Inline (Check_Token);
+   --  Called by T_xx routines to check for reserved keyword token. P is the
+   --  position of the error message if the token is missing (see Wrong_Token)
+
+   procedure Wrong_Token (T : Token_Type; P : Position);
+   --  Called when scanning a reserved keyword when the keyword is not
+   --  present. T is the token type for the keyword, and P indicates the
+   --  position to be used to place a message relative to the current
+   --  token if the keyword is not located nearby.
+
+   -----------------
+   -- Check_Token --
+   -----------------
+
+   procedure Check_Token (T : Token_Type; P : Position) is
+   begin
+      if Token = T then
+         Scan;
+         return;
+      else
+         Wrong_Token (T, P);
+      end if;
+   end Check_Token;
+
+   -------------
+   -- T_Abort --
+   -------------
+
+   procedure T_Abort is
+   begin
+      Check_Token (Tok_Abort, SC);
+   end T_Abort;
+
+   -------------
+   -- T_Arrow --
+   -------------
+
+   procedure T_Arrow is
+   begin
+      if Token = Tok_Arrow then
+         Scan;
+
+      --  A little recovery helper, accept then in place of =>
+
+      elsif Token = Tok_Then then
+         Error_Msg_BC ("missing ""=>""");
+         Scan; -- past THEN used in place of =>
+
+      elsif Token = Tok_Colon_Equal then
+         Error_Msg_SC (""":="" should be ""=>""");
+         Scan; -- past := used in place of =>
+
+      else
+         Error_Msg_AP ("missing ""=>""");
+      end if;
+   end T_Arrow;
+
+   ----------
+   -- T_At --
+   ----------
+
+   procedure T_At is
+   begin
+      Check_Token (Tok_At, SC);
+   end T_At;
+
+   ------------
+   -- T_Body --
+   ------------
+
+   procedure T_Body is
+   begin
+      Check_Token (Tok_Body, BC);
+   end T_Body;
+
+   -----------
+   -- T_Box --
+   -----------
+
+   procedure T_Box is
+   begin
+      if Token = Tok_Box then
+         Scan;
+      else
+         Error_Msg_AP ("missing ""<>""");
+      end if;
+   end T_Box;
+
+   -------------
+   -- T_Colon --
+   -------------
+
+   procedure T_Colon is
+   begin
+      if Token = Tok_Colon then
+         Scan;
+      else
+         Error_Msg_AP ("missing "":""");
+      end if;
+   end T_Colon;
+
+   -------------------
+   -- T_Colon_Equal --
+   -------------------
+
+   procedure T_Colon_Equal is
+   begin
+      if Token = Tok_Colon_Equal then
+         Scan;
+
+      elsif Token = Tok_Equal then
+         Error_Msg_SC ("""="" should be "":=""");
+         Scan;
+
+      elsif Token = Tok_Colon then
+         Error_Msg_SC (""":"" should be "":=""");
+         Scan;
+
+      elsif Token = Tok_Is then
+         Error_Msg_SC ("IS should be "":=""");
+         Scan;
+
+      else
+         Error_Msg_AP ("missing "":=""");
+      end if;
+   end T_Colon_Equal;
+
+   -------------
+   -- T_Comma --
+   -------------
+
+   procedure T_Comma is
+   begin
+      if Token = Tok_Comma then
+         Scan;
+
+      else
+         if Token = Tok_Pragma then
+            P_Pragmas_Misplaced;
+         end if;
+
+         if Token = Tok_Comma then
+            Scan;
+         else
+            Error_Msg_AP ("missing "",""");
+         end if;
+      end if;
+
+      if Token = Tok_Pragma then
+         P_Pragmas_Misplaced;
+      end if;
+   end T_Comma;
+
+   ---------------
+   -- T_Dot_Dot --
+   ---------------
+
+   procedure T_Dot_Dot is
+   begin
+      if Token = Tok_Dot_Dot then
+         Scan;
+      else
+         Error_Msg_AP ("missing ""..""");
+      end if;
+   end T_Dot_Dot;
+
+   -----------
+   -- T_For --
+   -----------
+
+   procedure T_For is
+   begin
+      Check_Token (Tok_For, AP);
+   end T_For;
+
+   -----------------------
+   -- T_Greater_Greater --
+   -----------------------
+
+   procedure T_Greater_Greater is
+   begin
+      if Token = Tok_Greater_Greater then
+         Scan;
+      else
+         Error_Msg_AP ("missing "">>""");
+      end if;
+   end T_Greater_Greater;
+
+   ------------------
+   -- T_Identifier --
+   ------------------
+
+   procedure T_Identifier is
+   begin
+      if Token = Tok_Identifier then
+         Scan;
+      elsif Token in Token_Class_Literal then
+         Error_Msg_SC ("identifier expected");
+         Scan;
+      else
+         Error_Msg_AP ("identifier expected");
+      end if;
+   end T_Identifier;
+
+   ----------
+   -- T_In --
+   ----------
+
+   procedure T_In is
+   begin
+      Check_Token (Tok_In, AP);
+   end T_In;
+
+   ----------
+   -- T_Is --
+   ----------
+
+   procedure T_Is is
+   begin
+      if Token = Tok_Is then
+         Scan;
+
+         Ignore (Tok_Semicolon);
+
+      --  Allow OF, => or = to substitute for IS with complaint
+
+      elsif Token = Tok_Arrow
+        or else Token = Tok_Of
+        or else Token = Tok_Equal
+      then
+         Error_Msg_SC ("missing IS");
+         Scan; -- token used in place of IS
+      else
+         Wrong_Token (Tok_Is, AP);
+      end if;
+
+      while Token = Tok_Is loop
+         Error_Msg_SC ("extra IS ignored");
+         Scan;
+      end loop;
+   end T_Is;
+
+   ------------------
+   -- T_Left_Paren --
+   ------------------
+
+   procedure T_Left_Paren is
+   begin
+      if Token = Tok_Left_Paren then
+         Scan;
+      else
+         Error_Msg_AP ("missing ""(""");
+      end if;
+   end T_Left_Paren;
+
+   ------------
+   -- T_Loop --
+   ------------
+
+   procedure T_Loop is
+   begin
+      if Token = Tok_Do then
+         Error_Msg_SC ("LOOP expected");
+         Scan;
+      else
+         Check_Token (Tok_Loop, AP);
+      end if;
+   end T_Loop;
+
+   -----------
+   -- T_Mod --
+   -----------
+
+   procedure T_Mod is
+   begin
+      Check_Token (Tok_Mod, AP);
+   end T_Mod;
+
+   -----------
+   -- T_New --
+   -----------
+
+   procedure T_New is
+   begin
+      Check_Token (Tok_New, AP);
+   end T_New;
+
+   ----------
+   -- T_Of --
+   ----------
+
+   procedure T_Of is
+   begin
+      Check_Token (Tok_Of, AP);
+   end T_Of;
+
+   ----------
+   -- T_Or --
+   ----------
+
+   procedure T_Or is
+   begin
+      Check_Token (Tok_Or, AP);
+   end T_Or;
+
+   ---------------
+   -- T_Private --
+   ---------------
+
+   procedure T_Private is
+   begin
+      Check_Token (Tok_Private, SC);
+   end T_Private;
+
+   -------------
+   -- T_Range --
+   -------------
+
+   procedure T_Range is
+   begin
+      Check_Token (Tok_Range, AP);
+   end T_Range;
+
+   --------------
+   -- T_Record --
+   --------------
+
+   procedure T_Record is
+   begin
+      Check_Token (Tok_Record, AP);
+   end T_Record;
+
+   -------------------
+   -- T_Right_Paren --
+   -------------------
+
+   procedure T_Right_Paren is
+   begin
+      if Token = Tok_Right_Paren then
+         Scan;
+      else
+         Error_Msg_AP ("missing "")""");
+      end if;
+   end T_Right_Paren;
+
+   -----------------
+   -- T_Semicolon --
+   -----------------
+
+   procedure T_Semicolon is
+   begin
+
+      if Token = Tok_Semicolon then
+         Scan;
+
+         if Token = Tok_Semicolon then
+            Error_Msg_SC ("extra "";"" ignored");
+            Scan;
+         end if;
+
+      elsif Token = Tok_Colon then
+         Error_Msg_SC (""":"" should be "";""");
+         Scan;
+
+      elsif Token = Tok_Comma then
+         Error_Msg_SC (""","" should be "";""");
+         Scan;
+
+      elsif Token = Tok_Dot then
+         Error_Msg_SC ("""."" should be "";""");
+         Scan;
+
+      --  An interesting little kludge here. If the previous token is a
+      --  semicolon, then there is no way that we can legitimately need
+      --  another semicolon. This could only arise in an error situation
+      --  where an error has already been signalled. By simply ignoring
+      --  the request for a semicolon in this case, we avoid some spurious
+      --  missing semicolon messages.
+
+      elsif Prev_Token = Tok_Semicolon then
+         return;
+
+      --  If the current token is | then this is a reasonable
+      --  place to suggest the possibility of a "C" confusion :-)
+
+      elsif Token = Tok_Vertical_Bar then
+         Error_Msg_SC ("unexpected occurrence of ""|"", did you mean OR'?");
+         Resync_Past_Semicolon;
+
+      --  Otherwise we really do have a missing semicolon
+
+      else
+         Error_Msg_AP ("missing "";""");
+         return;
+      end if;
+
+   end T_Semicolon;
+
+   ------------
+   -- T_Then --
+   ------------
+
+   procedure T_Then is
+   begin
+      Check_Token (Tok_Then, AP);
+   end T_Then;
+
+   ------------
+   -- T_Type --
+   ------------
+
+   procedure T_Type is
+   begin
+      Check_Token (Tok_Type, BC);
+   end T_Type;
+
+   -----------
+   -- T_Use --
+   -----------
+
+   procedure T_Use is
+   begin
+      Check_Token (Tok_Use, SC);
+   end T_Use;
+
+   ------------
+   -- T_When --
+   ------------
+
+   procedure T_When is
+   begin
+      Check_Token (Tok_When, SC);
+   end T_When;
+
+   ------------
+   -- T_With --
+   ------------
+
+   procedure T_With is
+   begin
+      Check_Token (Tok_With, BC);
+   end T_With;
+
+   --------------
+   -- TF_Arrow --
+   --------------
+
+   procedure TF_Arrow is
+      Scan_State : Saved_Scan_State;
+
+   begin
+      if Token = Tok_Arrow then
+         Scan; -- skip arrow and we are done
+
+      elsif Token = Tok_Colon_Equal then
+         T_Arrow; -- Let T_Arrow give the message
+
+      else
+         T_Arrow; -- give missing arrow message
+         Save_Scan_State (Scan_State); -- at start of junk tokens
+
+         loop
+            if Prev_Token_Ptr < Current_Line_Start
+              or else Token = Tok_Semicolon
+              or else Token = Tok_EOF
+            then
+               Restore_Scan_State (Scan_State); -- to where we were!
+               return;
+            end if;
+
+            Scan; -- continue search!
+
+            if Token = Tok_Arrow then
+               Scan; -- past arrow
+               return;
+            end if;
+         end loop;
+      end if;
+   end TF_Arrow;
+
+   -----------
+   -- TF_Is --
+   -----------
+
+   procedure TF_Is is
+      Scan_State : Saved_Scan_State;
+
+   begin
+      if Token = Tok_Is then
+         T_Is; -- past IS and we are done
+
+      --  Allow OF or => or = in place of IS (with error message)
+
+      elsif Token = Tok_Of
+        or else Token = Tok_Arrow
+        or else Token = Tok_Equal
+      then
+         T_Is; -- give missing IS message and skip bad token
+
+      else
+         T_Is; -- give missing IS message
+         Save_Scan_State (Scan_State); -- at start of junk tokens
+
+         loop
+            if Prev_Token_Ptr < Current_Line_Start
+              or else Token = Tok_Semicolon
+              or else Token = Tok_EOF
+            then
+               Restore_Scan_State (Scan_State); -- to where we were!
+               return;
+            end if;
+
+            Scan; -- continue search!
+
+            if Token = Tok_Is
+              or else Token = Tok_Of
+              or else Token = Tok_Arrow
+            then
+               Scan; -- past IS or OF or =>
+               return;
+            end if;
+         end loop;
+      end if;
+   end TF_Is;
+
+   -------------
+   -- TF_Loop --
+   -------------
+
+   procedure TF_Loop is
+      Scan_State : Saved_Scan_State;
+
+   begin
+      if Token = Tok_Loop then
+         Scan; -- past LOOP and we are done
+
+      --  Allow DO or THEN in place of LOOP
+
+      elsif Token = Tok_Then or else Token = Tok_Do then
+         T_Loop; -- give missing LOOP message
+
+      else
+         T_Loop; -- give missing LOOP message
+         Save_Scan_State (Scan_State); -- at start of junk tokens
+
+         loop
+            if Prev_Token_Ptr < Current_Line_Start
+              or else Token = Tok_Semicolon
+              or else Token = Tok_EOF
+            then
+               Restore_Scan_State (Scan_State); -- to where we were!
+               return;
+            end if;
+
+            Scan; -- continue search!
+
+            if Token = Tok_Loop or else Token = Tok_Then then
+               Scan; -- past loop or then (message already generated)
+               return;
+            end if;
+         end loop;
+      end if;
+   end TF_Loop;
+
+   --------------
+   -- TF_Return--
+   --------------
+
+   procedure TF_Return is
+      Scan_State : Saved_Scan_State;
+
+   begin
+      if Token = Tok_Return then
+         Scan; -- skip RETURN and we are done
+
+      else
+         Error_Msg_SC ("missing RETURN");
+         Save_Scan_State (Scan_State); -- at start of junk tokens
+
+         loop
+            if Prev_Token_Ptr < Current_Line_Start
+              or else Token = Tok_Semicolon
+              or else Token = Tok_EOF
+            then
+               Restore_Scan_State (Scan_State); -- to where we were!
+               return;
+            end if;
+
+            Scan; -- continue search!
+
+            if Token = Tok_Return then
+               Scan; -- past RETURN
+               return;
+            end if;
+         end loop;
+      end if;
+   end TF_Return;
+
+   ------------------
+   -- TF_Semicolon --
+   ------------------
+
+   procedure TF_Semicolon is
+      Scan_State : Saved_Scan_State;
+
+   begin
+      if Token = Tok_Semicolon then
+         T_Semicolon;
+         return;
+
+      --  An interesting little kludge here. If the previous token is a
+      --  semicolon, then there is no way that we can legitimately need
+      --  another semicolon. This could only arise in an error situation
+      --  where an error has already been signalled. By simply ignoring
+      --  the request for a semicolon in this case, we avoid some spurious
+      --  missing semicolon messages.
+
+      elsif Prev_Token = Tok_Semicolon then
+         return;
+
+      else
+         if Token = Tok_Pragma then
+            P_Pragmas_Misplaced;
+
+            if Token = Tok_Semicolon then
+               T_Semicolon;
+               return;
+            end if;
+         end if;
+
+         T_Semicolon; -- give missing semicolon message
+         Save_Scan_State (Scan_State); -- at start of junk tokens
+
+         loop
+            if Prev_Token_Ptr < Current_Line_Start
+              or else Token = Tok_EOF
+            then
+               Restore_Scan_State (Scan_State); -- to where we were
+               return;
+            end if;
+
+            Scan; -- continue search
+
+            if Token = Tok_Semicolon then
+               T_Semicolon;
+               return;
+
+            elsif Token in Token_Class_After_SM then
+               return;
+            end if;
+         end loop;
+      end if;
+   end TF_Semicolon;
+
+   -------------
+   -- TF_Then --
+   -------------
+
+   procedure TF_Then is
+      Scan_State : Saved_Scan_State;
+
+   begin
+      if Token = Tok_Then then
+         Scan; -- past THEN and we are done
+
+      else
+         T_Then; -- give missing THEN message
+         Save_Scan_State (Scan_State); -- at start of junk tokens
+
+         loop
+            if Prev_Token_Ptr < Current_Line_Start
+              or else Token = Tok_Semicolon
+              or else Token = Tok_EOF
+            then
+               Restore_Scan_State (Scan_State); -- to where we were
+               return;
+            end if;
+
+            Scan; -- continue search!
+
+            if Token = Tok_Then then
+               Scan; -- past THEN
+               return;
+            end if;
+         end loop;
+      end if;
+   end TF_Then;
+
+   ------------
+   -- TF_Use --
+   ------------
+
+   procedure TF_Use is
+      Scan_State : Saved_Scan_State;
+
+   begin
+      if Token = Tok_Use then
+         Scan; -- past USE and we are done
+
+      else
+         T_Use; -- give USE expected message
+         Save_Scan_State (Scan_State); -- at start of junk tokens
+
+         loop
+            if Prev_Token_Ptr < Current_Line_Start
+              or else Token = Tok_Semicolon
+              or else Token = Tok_EOF
+            then
+               Restore_Scan_State (Scan_State); -- to where we were
+               return;
+            end if;
+
+            Scan; -- continue search!
+
+            if Token = Tok_Use then
+               Scan; -- past use
+               return;
+            end if;
+         end loop;
+      end if;
+   end TF_Use;
+
+   -----------------
+   -- Wrong_Token --
+   -----------------
+
+   procedure Wrong_Token (T : Token_Type; P : Position) is
+      Missing : constant String := "missing ";
+      Image : constant String := Token_Type'Image (T);
+      Tok_Name : constant String := Image (5 .. Image'Length);
+      M : String (1 .. Missing'Length + Tok_Name'Length);
+
+   begin
+      --  Set M to Missing & Tok_Name.
+
+      M (1 .. Missing'Length) := Missing;
+      M (Missing'Length + 1 .. M'Last) := Tok_Name;
+
+      if Token = Tok_Semicolon then
+         Scan;
+
+         if Token = T then
+            Error_Msg_SP ("extra "";"" ignored");
+            Scan;
+         else
+            Error_Msg_SP (M);
+         end if;
+
+      elsif Token = Tok_Comma then
+         Scan;
+
+         if Token = T then
+            Error_Msg_SP ("extra "","" ignored");
+            Scan;
+
+         else
+            Error_Msg_SP (M);
+         end if;
+
+      else
+         case P is
+            when SC => Error_Msg_SC (M);
+            when BC => Error_Msg_BC (M);
+            when AP => Error_Msg_AP (M);
+         end case;
+      end if;
+   end Wrong_Token;
+
+end Tchk;
diff --git a/gcc/ada/par-util.adb b/gcc/ada/par-util.adb
new file mode 100644 (file)
index 0000000..f8082b6
--- /dev/null
@@ -0,0 +1,638 @@
+------------------------------------------------------------------------------
+--                                                                          --
+--                         GNAT COMPILER COMPONENTS                         --
+--                                                                          --
+--                             P A R . U T I L                              --
+--                                                                          --
+--                                 B o d y                                  --
+--                                                                          --
+--                            $Revision: 1.64 $
+--                                                                          --
+--          Copyright (C) 1992-2001, Free Software Foundation, Inc.
+--                                                                          --
+-- GNAT is free software;  you can  redistribute it  and/or modify it under --
+-- terms of the  GNU General Public License as published  by the Free Soft- --
+-- ware  Foundation;  either version 2,  or (at your option) any later ver- --
+-- sion.  GNAT is distributed in the hope that it will be useful, but WITH- --
+-- OUT 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  distributed with GNAT;  see file COPYING.  If not, write --
+-- to  the Free Software Foundation,  59 Temple Place - Suite 330,  Boston, --
+-- MA 02111-1307, USA.                                                      --
+--                                                                          --
+-- GNAT was originally developed  by the GNAT team at  New York University. --
+-- It is now maintained by Ada Core Technologies Inc (http://www.gnat.com). --
+--                                                                          --
+------------------------------------------------------------------------------
+
+with Uintp; use Uintp;
+
+with GNAT.Spelling_Checker; use GNAT.Spelling_Checker;
+
+separate (Par)
+package body Util is
+
+   ---------------------
+   -- Bad_Spelling_Of --
+   ---------------------
+
+   function Bad_Spelling_Of (T : Token_Type) return Boolean is
+      Tname : constant String := Token_Type'Image (T);
+      --  Characters of token name
+
+      S : String (1 .. Tname'Last - 4);
+      --  Characters of token name folded to lower case, omitting TOK_ at start
+
+      M1 : String (1 .. 42) := "incorrect spelling of keyword ************";
+      M2 : String (1 .. 44) := "illegal abbreviation of keyword ************";
+      --  Buffers used to construct error message
+
+      P1 : constant := 30;
+      P2 : constant := 32;
+      --  Starting subscripts in M1, M2 for keyword name
+
+      SL : constant Natural := S'Length;
+      --  Length of expected token name excluding TOK_ at start
+
+   begin
+      if Token /= Tok_Identifier then
+         return False;
+      end if;
+
+      for J in S'Range loop
+         S (J) := Fold_Lower (Tname (Integer (J) + 4));
+      end loop;
+
+      Get_Name_String (Token_Name);
+
+      --  A special check for case of PROGRAM used for PROCEDURE
+
+      if T = Tok_Procedure
+        and then Name_Len = 7
+        and then Name_Buffer (1 .. 7) = "program"
+      then
+         Error_Msg_SC ("PROCEDURE expected");
+         Token := T;
+         return True;
+
+      --  A special check for an illegal abbrevation
+
+      elsif Name_Len < S'Length
+        and then Name_Len >= 4
+        and then Name_Buffer (1 .. Name_Len) = S (1 .. Name_Len)
+      then
+         for J in 1 .. S'Last loop
+            M2 (P2 + J - 1) := Fold_Upper (S (J));
+         end loop;
+
+         Error_Msg_SC (M2 (1 .. P2 - 1 + S'Last));
+         Token := T;
+         return True;
+      end if;
+
+      --  Now we go into the full circuit to check for a misspelling
+
+      --  Never consider something a misspelling if either the actual or
+      --  expected string is less than 3 characters (before this check we
+      --  used to consider i to be a misspelled if in some cases!)
+
+      if SL < 3 or else Name_Len < 3 then
+         return False;
+
+      --  Special case: prefix matches, i.e. the leading characters of the
+      --  token that we have exactly match the required keyword. If there
+      --  are at least two characters left over, assume that we have a case
+      --  of two keywords joined together which should not be joined.
+
+      elsif Name_Len > SL + 1
+        and then S = Name_Buffer (1 .. SL)
+      then
+         Scan_Ptr := Token_Ptr + S'Length;
+         Error_Msg_S ("missing space");
+         Token := T;
+         return True;
+      end if;
+
+      if Is_Bad_Spelling_Of (Name_Buffer (1 .. Name_Len), S) then
+
+         for J in 1 .. S'Last loop
+            M1 (P1 + J - 1) := Fold_Upper (S (J));
+         end loop;
+
+         Error_Msg_SC (M1 (1 .. P1 - 1 + S'Last));
+         Token := T;
+         return True;
+
+      else
+         return False;
+      end if;
+
+   end Bad_Spelling_Of;
+
+   ----------------------
+   -- Check_95_Keyword --
+   ----------------------
+
+   --  On entry, the caller has checked that current token is an identifier
+   --  whose name matches the name of the 95 keyword New_Tok.
+
+   procedure Check_95_Keyword (Token_95, Next : Token_Type) is
+      Scan_State : Saved_Scan_State;
+
+   begin
+      Save_Scan_State (Scan_State); -- at identifier/keyword
+      Scan; -- past identifier/keyword
+
+      if Token = Next then
+         Restore_Scan_State (Scan_State); -- to identifier
+         Error_Msg_Name_1 := Token_Name;
+         Error_Msg_SC ("(Ada 83) keyword* cannot be used!");
+         Token := Token_95;
+      else
+         Restore_Scan_State (Scan_State); -- to identifier
+      end if;
+   end Check_95_Keyword;
+
+   ----------------------
+   -- Check_Bad_Layout --
+   ----------------------
+
+   procedure Check_Bad_Layout is
+   begin
+      if Style.RM_Column_Check and then Token_Is_At_Start_Of_Line
+        and then Start_Column <= Scope.Table (Scope.Last).Ecol
+      then
+         Error_Msg_BC ("(style) incorrect layout");
+      end if;
+   end Check_Bad_Layout;
+
+   --------------------------
+   -- Check_Misspelling_Of --
+   --------------------------
+
+   procedure Check_Misspelling_Of (T : Token_Type) is
+   begin
+      if Bad_Spelling_Of (T) then
+         null;
+      end if;
+   end Check_Misspelling_Of;
+
+   -----------------------------
+   -- Check_Simple_Expression --
+   -----------------------------
+
+   procedure Check_Simple_Expression (E : Node_Id) is
+   begin
+      if Expr_Form = EF_Non_Simple then
+         Error_Msg_N ("this expression must be parenthesized", E);
+      end if;
+   end Check_Simple_Expression;
+
+   ---------------------------------------
+   -- Check_Simple_Expression_In_Ada_83 --
+   ---------------------------------------
+
+   procedure Check_Simple_Expression_In_Ada_83 (E : Node_Id) is
+   begin
+      if Expr_Form = EF_Non_Simple then
+         if Ada_83 then
+            Error_Msg_N ("(Ada 83) this expression must be parenthesized!", E);
+         end if;
+      end if;
+   end Check_Simple_Expression_In_Ada_83;
+
+   ------------------------
+   -- Check_Subtype_Mark --
+   ------------------------
+
+   function Check_Subtype_Mark (Mark : Node_Id) return Node_Id is
+   begin
+      if Nkind (Mark) = N_Identifier
+        or else Nkind (Mark) = N_Selected_Component
+        or else (Nkind (Mark) = N_Attribute_Reference
+                  and then Is_Type_Attribute_Name (Attribute_Name (Mark)))
+        or else Mark = Error
+      then
+         return Mark;
+      else
+         Error_Msg ("subtype mark expected", Sloc (Mark));
+         return Error;
+      end if;
+   end Check_Subtype_Mark;
+
+   -------------------
+   -- Comma_Present --
+   -------------------
+
+   function Comma_Present return Boolean is
+      Scan_State  : Saved_Scan_State;
+      Paren_Count : Nat;
+
+   begin
+      --  First check, if a comma is present, then a comma is present!
+
+      if Token = Tok_Comma then
+         T_Comma;
+         return True;
+
+      --  If we have a right paren, then that is taken as ending the list
+      --  i.e. no comma is present.
+
+      elsif Token = Tok_Right_Paren then
+         return False;
+
+      --  If pragmas, then get rid of them and make a recursive call
+      --  to process what follows these pragmas.
+
+      elsif Token = Tok_Pragma then
+         P_Pragmas_Misplaced;
+         return Comma_Present;
+
+      --  At this stage we have an error, and the goal is to decide on whether
+      --  or not we should diagnose an error and report a (non-existent)
+      --  comma as being present, or simply to report no comma is present
+
+      --  If we are a semicolon, then the question is whether we have a missing
+      --  right paren, or whether the semicolon should have been a comma. To
+      --  guess the right answer, we scan ahead keeping track of the paren
+      --  level, looking for a clue that helps us make the right decision.
+
+      --  This approach is highly accurate in the single error case, and does
+      --  not make bad mistakes in the multiple error case (indeed we can't
+      --  really make a very bad decision at this point in any case).
+
+      elsif Token = Tok_Semicolon then
+         Save_Scan_State (Scan_State);
+         Scan; -- past semicolon
+
+         --  Check for being followed by identifier => which almost certainly
+         --  means we are still in a parameter list and the comma should have
+         --  been a semicolon (such a sequence could not follow a semicolon)
+
+         if Token = Tok_Identifier then
+            Scan;
+
+            if Token = Tok_Arrow then
+               goto Assume_Comma;
+            end if;
+         end if;
+
+         --  If that test didn't work, loop ahead looking for a comma or
+         --  semicolon at the same parenthesis level. Always remember that
+         --  we can't go badly wrong in an error situation like this!
+
+         Paren_Count := 0;
+
+         --  Here is the look ahead loop, Paren_Count tells us whether the
+         --  token we are looking at is at the same paren level as the
+         --  suspicious semicolon that we are trying to figure out.
+
+         loop
+
+            --  If we hit another semicolon or an end of file, and we have
+            --  not seen a right paren or another comma on the way, then
+            --  probably the semicolon did end the list. Indeed that is
+            --  certainly the only single error correction possible here.
+
+            if Token = Tok_Semicolon or else Token = Tok_EOF then
+               Restore_Scan_State (Scan_State);
+               return False;
+
+            --  A comma at the same paren level as the semicolon is a strong
+            --  indicator that the semicolon should have been a comma, indeed
+            --  again this is the only possible single error correction.
+
+            elsif Token = Tok_Comma then
+               exit when Paren_Count = 0;
+
+            --  A left paren just bumps the paren count
+
+            elsif Token = Tok_Left_Paren then
+               Paren_Count := Paren_Count + 1;
+
+            --  A right paren that is at the same paren level as the semicolon
+            --  also means that the only possible single error correction is
+            --  to assume that the semicolon should have been a comma. If we
+            --  are not at the same paren level, then adjust the paren level.
+
+            elsif Token = Tok_Right_Paren then
+               exit when Paren_Count = 0;
+               Paren_Count := Paren_Count - 1;
+            end if;
+
+            --  Keep going, we haven't made a decision yet
+
+            Scan;
+         end loop;
+
+         --  If we fall through the loop, it means that we found a terminating
+         --  right paren or another comma. In either case it is reasonable to
+         --  assume that the semicolon was really intended to be a comma. Also
+         --  come here for the identifier arrow case.
+
+         <<Assume_Comma>>
+            Restore_Scan_State (Scan_State);
+            Error_Msg_SC (""";"" illegal here, replaced by "",""");
+            Scan; -- past the semicolon
+            return True;
+
+      --  If we are not at semicolon or a right paren, then we base the
+      --  decision on whether or not the next token can be part of an
+      --  expression. If not, then decide that no comma is present (the
+      --  caller will eventually generate a missing right parent message)
+
+      elsif Token in Token_Class_Eterm then
+         return False;
+
+      --  Otherwise we assume a comma is present, even if none is present,
+      --  since the next token must be part of an expression, so if we were
+      --  at the end of the list, then there is more than one error present.
+
+      else
+         T_Comma; -- to give error
+         return True;
+      end if;
+   end Comma_Present;
+
+   -----------------------
+   -- Discard_Junk_List --
+   -----------------------
+
+   procedure Discard_Junk_List (L : List_Id) is
+   begin
+      null;
+   end Discard_Junk_List;
+
+   -----------------------
+   -- Discard_Junk_Node --
+   -----------------------
+
+   procedure Discard_Junk_Node (N : Node_Id) is
+   begin
+      null;
+   end Discard_Junk_Node;
+
+   ------------
+   -- Ignore --
+   ------------
+
+   procedure Ignore (T : Token_Type) is
+   begin
+      if Token = T then
+         if T = Tok_Comma then
+            Error_Msg_SC ("unexpected "","" ignored");
+
+         elsif T = Tok_Left_Paren then
+            Error_Msg_SC ("unexpected ""("" ignored");
+
+         elsif T = Tok_Right_Paren then
+            Error_Msg_SC ("unexpected "")"" ignored");
+
+         elsif T = Tok_Semicolon then
+            Error_Msg_SC ("unexpected "";"" ignored");
+
+         else
+            declare
+               Tname : constant String := Token_Type'Image (Token);
+               Msg   : String := "unexpected keyword ????????????????????????";
+
+            begin
+               --  Loop to copy characters of keyword name (ignoring Tok_)
+
+               for J in 5 .. Tname'Last loop
+                  Msg (J + 14) := Fold_Upper (Tname (J));
+               end loop;
+
+               Msg (Tname'Last + 15 .. Tname'Last + 22) := " ignored";
+               Error_Msg_SC (Msg (1 .. Tname'Last + 22));
+            end;
+         end if;
+
+         Scan; -- Scan past ignored token
+      end if;
+   end Ignore;
+
+   ----------------------------
+   -- Is_Reserved_Identifier --
+   ----------------------------
+
+   function Is_Reserved_Identifier return Boolean is
+   begin
+      if not Is_Reserved_Keyword (Token) then
+         return False;
+
+      else
+         declare
+            Ident_Casing : constant Casing_Type :=
+                             Identifier_Casing (Current_Source_File);
+
+            Key_Casing   : constant Casing_Type :=
+                             Keyword_Casing (Current_Source_File);
+
+         begin
+            --  If the casing of identifiers and keywords is different in
+            --  this source file, and the casing of this token matches the
+            --  keyword casing, then we return False, since it is pretty
+            --  clearly intended to be a keyword.
+
+            if Ident_Casing /= Unknown
+              and then Key_Casing /= Unknown
+              and then Ident_Casing /= Key_Casing
+              and then Determine_Token_Casing = Key_Casing
+            then
+               return False;
+
+            --  Otherwise assume that an identifier was intended
+
+            else
+               return True;
+            end if;
+         end;
+      end if;
+   end Is_Reserved_Identifier;
+
+   ----------------------
+   -- Merge_Identifier --
+   ----------------------
+
+   procedure Merge_Identifier (Prev : Node_Id; Nxt : Token_Type) is
+   begin
+      if Token /= Tok_Identifier then
+         return;
+      end if;
+
+      declare
+         S : Saved_Scan_State;
+         T : Token_Type;
+
+      begin
+         Save_Scan_State (S);
+         Scan;
+         T := Token;
+         Restore_Scan_State (S);
+
+         if T /= Nxt then
+            return;
+         end if;
+      end;
+
+      --  Check exactly one space between identifiers
+
+      if Source (Token_Ptr - 1) /= ' '
+        or else Int (Token_Ptr) /=
+                  Int (Prev_Token_Ptr) + Length_Of_Name (Chars (Prev)) + 1
+      then
+         return;
+      end if;
+
+      --  Do the merge
+
+      Get_Name_String (Chars (Token_Node));
+
+      declare
+         Buf : String (1 .. Name_Len) := Name_Buffer (1 .. Name_Len);
+
+      begin
+         Get_Name_String (Chars (Prev));
+         Add_Char_To_Name_Buffer ('_');
+         Add_Str_To_Name_Buffer (Buf);
+         Set_Chars (Prev, Name_Find);
+      end;
+
+      Error_Msg_Node_1 := Prev;
+      Error_Msg_SC
+        ("unexpected identifier, possibly & was meant here");
+      Scan;
+   end Merge_Identifier;
+
+   -------------------
+   -- No_Constraint --
+   -------------------
+
+   procedure No_Constraint is
+   begin
+      if Token in Token_Class_Consk then
+         Error_Msg_SC ("constraint not allowed here");
+         Discard_Junk_Node (P_Constraint_Opt);
+      end if;
+   end No_Constraint;
+
+   --------------------
+   -- No_Right_Paren --
+   --------------------
+
+   function No_Right_Paren (Expr : Node_Id) return Node_Id is
+   begin
+      if Token = Tok_Right_Paren then
+         Error_Msg_SC ("unexpected right parenthesis");
+         Resync_Expression;
+         return Error;
+      else
+         return Expr;
+      end if;
+   end No_Right_Paren;
+
+   ---------------------
+   -- Pop_Scope_Stack --
+   ---------------------
+
+   procedure Pop_Scope_Stack is
+   begin
+      pragma Assert (Scope.Last > 0);
+      Scope.Decrement_Last;
+
+      if Debug_Flag_P then
+         Error_Msg_Uint_1 := UI_From_Int (Scope.Last);
+         Error_Msg_SC ("decrement scope stack ptr, new value = ^!");
+      end if;
+   end Pop_Scope_Stack;
+
+   ----------------------
+   -- Push_Scope_Stack --
+   ----------------------
+
+   procedure Push_Scope_Stack is
+   begin
+      Scope.Increment_Last;
+      Scope.Table (Scope.Last).Junk := False;
+      Scope.Table (Scope.Last).Node := Empty;
+
+      if Debug_Flag_P then
+         Error_Msg_Uint_1 := UI_From_Int (Scope.Last);
+         Error_Msg_SC ("increment scope stack ptr, new value = ^!");
+      end if;
+   end Push_Scope_Stack;
+
+   ----------------------
+   -- Separate_Present --
+   ----------------------
+
+   function Separate_Present return Boolean is
+      Scan_State : Saved_Scan_State;
+
+   begin
+      if Token = Tok_Separate then
+         return True;
+
+      elsif Token /= Tok_Identifier then
+         return False;
+
+      else
+         Save_Scan_State (Scan_State);
+         Scan; -- past identifier
+
+         if Token = Tok_Semicolon then
+            Restore_Scan_State (Scan_State);
+            return Bad_Spelling_Of (Tok_Separate);
+
+         else
+            Restore_Scan_State (Scan_State);
+            return False;
+         end if;
+      end if;
+   end Separate_Present;
+
+   --------------------------
+   -- Signal_Bad_Attribute --
+   --------------------------
+
+   procedure Signal_Bad_Attribute is
+   begin
+      Error_Msg_N ("unrecognized attribute&", Token_Node);
+
+      --  Check for possible misspelling
+
+      Get_Name_String (Token_Name);
+
+      declare
+         AN : constant String := Name_Buffer (1 .. Name_Len);
+
+      begin
+         Error_Msg_Name_1 := First_Attribute_Name;
+         while Error_Msg_Name_1 <= Last_Attribute_Name loop
+            Get_Name_String (Error_Msg_Name_1);
+
+            if Is_Bad_Spelling_Of
+                 (AN, Name_Buffer (1 .. Name_Len))
+            then
+               Error_Msg_N
+                 ("\possible misspelling of %", Token_Node);
+               exit;
+            end if;
+
+            Error_Msg_Name_1 := Error_Msg_Name_1 + 1;
+         end loop;
+      end;
+   end Signal_Bad_Attribute;
+
+   -------------------------------
+   -- Token_Is_At_Start_Of_Line --
+   -------------------------------
+
+   function Token_Is_At_Start_Of_Line return Boolean is
+   begin
+      return (Token_Ptr = First_Non_Blank_Location or else Token = Tok_EOF);
+   end Token_Is_At_Start_Of_Line;
+
+end Util;
diff --git a/gcc/ada/par.adb b/gcc/ada/par.adb
new file mode 100644 (file)
index 0000000..f45a83b
--- /dev/null
@@ -0,0 +1,1181 @@
+------------------------------------------------------------------------------
+--                                                                          --
+--                         GNAT COMPILER COMPONENTS                         --
+--                                                                          --
+--                                  P A R                                   --
+--                                                                          --
+--                                 B o d y                                  --
+--                                                                          --
+--                            $Revision: 1.126 $
+--                                                                          --
+--          Copyright (C) 1992-2001 Free Software Foundation, Inc.          --
+--                                                                          --
+-- GNAT is free software;  you can  redistribute it  and/or modify it under --
+-- terms of the  GNU General Public License as published  by the Free Soft- --
+-- ware  Foundation;  either version 2,  or (at your option) any later ver- --
+-- sion.  GNAT is distributed in the hope that it will be useful, but WITH- --
+-- OUT 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  distributed with GNAT;  see file COPYING.  If not, write --
+-- to  the Free Software Foundation,  59 Temple Place - Suite 330,  Boston, --
+-- MA 02111-1307, USA.                                                      --
+--                                                                          --
+-- GNAT was originally developed  by the GNAT team at  New York University. --
+-- It is now maintained by Ada Core Technologies Inc (http://www.gnat.com). --
+--                                                                          --
+------------------------------------------------------------------------------
+
+with Atree;    use Atree;
+with Casing;   use Casing;
+with Csets;    use Csets;
+with Debug;    use Debug;
+with Elists;   use Elists;
+with Errout;   use Errout;
+with Fname;    use Fname;
+with Lib;      use Lib;
+with Namet;    use Namet;
+with Nlists;   use Nlists;
+with Nmake;    use Nmake;
+with Opt;      use Opt;
+with Output;   use Output;
+with Scans;    use Scans;
+with Scn;      use Scn;
+with Sinput;   use Sinput;
+with Sinput.L; use Sinput.L;
+with Sinfo;    use Sinfo;
+with Snames;   use Snames;
+with Style;
+with Table;
+
+function Par (Configuration_Pragmas : Boolean) return List_Id is
+
+   Num_Library_Units : Natural := 0;
+   --  Count number of units parsed (relevant only in syntax check only mode,
+   --  since in semantics check mode only a single unit is permitted anyway)
+
+   Unit_Node : Node_Id;
+   --  Stores compilation unit node for current unit
+
+   Save_Config_Switches : Config_Switches_Type;
+   --  Variable used to save values of config switches while we parse the
+   --  new unit, to be restored on exit for proper recursive behavior.
+
+   Loop_Block_Count : Nat := 0;
+   --  Counter used for constructing loop/block names (see the routine
+   --  Par.Ch5.Get_Loop_Block_Name)
+
+   --------------------
+   -- Error Recovery --
+   --------------------
+
+   --  When an error is encountered, a call is made to one of the Error_Msg
+   --  routines to record the error. If the syntax scan is not derailed by the
+   --  error (e.g. a complaint that logical operators are inconsistent in an
+   --  EXPRESSION), then control returns from the Error_Msg call, and the
+   --  parse continues unimpeded.
+
+   --  If on the other hand, the Error_Msg represents a situation from which
+   --  the parser cannot recover locally, the exception Error_Resync is raised
+   --  immediately after the call to Error_Msg. Handlers for Error_Resync
+   --  are located at strategic points to resynchronize the parse. For example,
+   --  when an error occurs in a statement, the handler skips to the next
+   --  semicolon and continues the scan from there.
+
+   --  Each parsing procedure contains a note with the heading "Error recovery"
+   --  which shows if it can propagate the Error_Resync exception. In order
+   --  not to propagate the exception, a procedure must either contain its own
+   --  handler for this exception, or it must not call any other routines which
+   --  propagate the exception.
+
+   --  Note: the arrangement of Error_Resync handlers is such that it should
+   --  never be possible to transfer control through a procedure which made
+   --  an entry in the scope stack, invalidating the contents of the stack.
+
+   Error_Resync : exception;
+   --  Exception raised on error that is not handled locally, see above.
+
+   Last_Resync_Point : Source_Ptr;
+   --  The resynchronization routines in Par.Sync run a risk of getting
+   --  stuck in an infinite loop if they do not skip a token, and the caller
+   --  keeps repeating the same resync call. On the other hand, if they skip
+   --  a token unconditionally, some recovery opportunities are missed. The
+   --  variable Last_Resync_Point records the token location previously set
+   --  by a Resync call, and if a subsequent Resync call occurs at the same
+   --  location, then the Resync routine does guarantee to skip a token.
+
+   --------------------------------------------
+   -- Handling Semicolon Used in Place of IS --
+   --------------------------------------------
+
+   --  The following global variables are used in handling the error situation
+   --  of using a semicolon in place of IS in a subprogram declaration as in:
+
+   --    procedure X (Y : Integer);
+   --       Q : Integer;
+   --    begin
+   --       ...
+   --    end;
+
+   --  The two contexts in which this can appear are at the outer level, and
+   --  within a declarative region. At the outer level, we know something is
+   --  wrong as soon as we see the Q (or begin, if there are no declarations),
+   --  and we can immediately decide that the semicolon should have been IS.
+
+   --  The situation in a declarative region is more complex. The declaration
+   --  of Q could belong to the outer region, and we do not know that we have
+   --  an error until we hit the begin. It is still not clear at this point
+   --  from a syntactic point of view that something is wrong, because the
+   --  begin could belong to the enclosing subprogram or package. However, we
+   --  can incorporate a bit of semantic knowledge and note that the body of
+   --  X is missing, so we definitely DO have an error. We diagnose this error
+   --  as semicolon in place of IS on the subprogram line.
+
+   --  There are two styles for this diagnostic. If the begin immediately
+   --  follows the semicolon, then we can place a flag (IS expected) right
+   --  on the semicolon. Otherwise we do not detect the error until we hit
+   --  the begin which refers back to the line with the semicolon.
+
+   --  To control the process in the second case, the following global
+   --  variables are set to indicate that we have a subprogram declaration
+   --  whose body is required and has not yet been found. The prefix SIS
+   --  stands for "Subprogram IS" handling.
+
+   SIS_Entry_Active : Boolean;
+   --  Set True to indicate that an entry is active (i.e. that a subprogram
+   --  declaration has been encountered, and no body for this subprogram has
+   --  been encountered). The remaining fields are valid only if this is True.
+
+   SIS_Labl : Node_Id;
+   --  Subprogram designator
+
+   SIS_Sloc : Source_Ptr;
+   --  Source location of FUNCTION/PROCEDURE keyword
+
+   SIS_Ecol : Column_Number;
+   --  Column number of FUNCTION/PROCEDURE keyword
+
+   SIS_Semicolon_Sloc : Source_Ptr;
+   --  Source location of semicolon at end of subprogram declaration
+
+   SIS_Declaration_Node : Node_Id;
+   --  Pointer to tree node for subprogram declaration
+
+   SIS_Missing_Semicolon_Message : Error_Msg_Id;
+   --  Used to save message ID of missing semicolon message (which will be
+   --  modified to missing IS if necessary). Set to No_Error_Msg in the
+   --  normal (non-error) case.
+
+   --  Five things can happen to an active SIS entry
+
+   --   1. If a BEGIN is encountered with an SIS entry active, then we have
+   --   exactly the situation in which we know the body of the subprogram is
+   --   missing. After posting an error message, we change the spec to a body,
+   --   rechaining the declarations that intervened between the spec and BEGIN.
+
+   --   2. Another subprogram declaration or body is encountered. In this
+   --   case the entry gets overwritten with the information for the new
+   --   subprogram declaration. We don't catch some nested cases this way,
+   --   but it doesn't seem worth the effort.
+
+   --   3. A nested declarative region (e.g. package declaration or package
+   --   body) is encountered. The SIS active indication is reset at the start
+   --   of such a nested region. Again, like case 2, this causes us to miss
+   --   some nested cases, but it doesn't seen worth the effort to stack and
+   --   unstack the SIS information. Maybe we will reconsider this if we ever
+   --   get a complaint about a missed case :-)
+
+   --   4. We encounter a valid pragma INTERFACE or IMPORT that effectively
+   --   supplies the missing body. In this case we reset the entry.
+
+   --   5. We encounter the end of the declarative region without encoutering
+   --   a BEGIN first. In this situation we simply reset the entry. We know
+   --   that there is a missing body, but it seems more reasonable to let the
+   --   later semantic checking discover this.
+
+   --------------------------------------------
+   -- Handling IS Used in Place of Semicolon --
+   --------------------------------------------
+
+   --  This is a somewhat trickier situation, and we can't catch it in all
+   --  cases, but we do our best to detect common situations resulting from
+   --  a "cut and paste" operation which forgets to change the IS to semicolon.
+   --  Consider the following example:
+
+   --    package body X is
+   --      procedure A;
+   --      procedure B is
+   --      procedure C;
+   --      ...
+   --      procedure D is
+   --      begin
+   --         ...
+   --      end;
+   --    begin
+   --      ...
+   --    end;
+
+   --  The trouble is that the section of text from PROCEDURE B through END;
+   --  consitutes a valid procedure body, and the danger is that we find out
+   --  far too late that something is wrong (indeed most compilers will behave
+   --  uncomfortably on the above example).
+
+   --  We have two approaches to helping to control this situation. First we
+   --  make every attempt to avoid swallowing the last END; if we can be
+   --  sure that some error will result from doing so. In particular, we won't
+   --  accept the END; unless it is exactly correct (in particular it must not
+   --  have incorrect name tokens), and we won't accept it if it is immediately
+   --  followed by end of file, WITH or SEPARATE (all tokens that unmistakeably
+   --  signal the start of a compilation unit, and which therefore allow us to
+   --  reserve the END; for the outer level.) For more details on this aspect
+   --  of the handling, see package Par.Endh.
+
+   --  If we can avoid eating up the END; then the result in the absense of
+   --  any additional steps would be to post a missing END referring back to
+   --  the subprogram with the bogus IS. Similarly, if the enclosing package
+   --  has no BEGIN, then the result is a missing BEGIN message, which again
+   --  refers back to the subprogram header.
+
+   --  Such an error message is not too bad (it's already a big improvement
+   --  over what many parsers do), but it's not ideal, because the declarations
+   --  following the IS have been absorbed into the wrong scope. In the above
+   --  case, this could result for example in a bogus complaint that the body
+   --  of D was missing from the package.
+
+   --  To catch at least some of these cases, we take the following additional
+   --  steps. First, a subprogram body is marked as having a suspicious IS if
+   --  the declaration line is followed by a line which starts with a symbol
+   --  that can start a declaration in the same column, or to the left of the
+   --  column in which the FUNCTION or PROCEDURE starts (normal style is to
+   --  indent any declarations which really belong a subprogram). If such a
+   --  subprogram encounters a missing BEGIN or missing END, then we decide
+   --  that the IS should have been a semicolon, and the subprogram body node
+   --  is marked (by setting the Bad_Is_Detected flag true. Note that we do
+   --  not do this for library level procedures, only for nested procedures,
+   --  since for library level procedures, we must have a body.
+
+   --  The processing for a declarative part checks to see if the last
+   --  declaration scanned is marked in this way, and if it is, the tree
+   --  is modified to reflect the IS being interpreted as a semicolon.
+
+   ---------------------------------------------------
+   -- Parser Type Definitions and Control Variables --
+   ---------------------------------------------------
+
+   --  The following variable and associated type declaration are used by the
+   --  expression parsing routines to return more detailed information about
+   --  the categorization of a parsed expression.
+
+   type Expr_Form_Type is (
+      EF_Simple_Name,  -- Simple name, i.e. possibly qualified identifier
+      EF_Name,         -- Simple expression which could also be a name
+      EF_Simple,       -- Simple expression which is not call or name
+      EF_Range_Attr,   -- Range attribute reference
+      EF_Non_Simple);  -- Expression that is not a simple expression
+
+   Expr_Form : Expr_Form_Type;
+
+   --  The following type is used for calls to P_Subprogram, P_Package, P_Task,
+   --  P_Protected to indicate which of several possibilities is acceptable.
+
+   type Pf_Rec is record
+      Spcn : Boolean;                  -- True if specification OK
+      Decl : Boolean;                  -- True if declaration OK
+      Gins : Boolean;                  -- True if generic instantiation OK
+      Pbod : Boolean;                  -- True if proper body OK
+      Rnam : Boolean;                  -- True if renaming declaration OK
+      Stub : Boolean;                  -- True if body stub OK
+      Fil1 : Boolean;                  -- Filler to fill to 8 bits
+      Fil2 : Boolean;                  -- Filler to fill to 8 bits
+   end record;
+   pragma Pack (Pf_Rec);
+
+   function T return Boolean renames True;
+   function F return Boolean renames False;
+
+   Pf_Decl_Gins_Pbod_Rnam_Stub : constant Pf_Rec :=
+                                             Pf_Rec'(F, T, T, T, T, T, F, F);
+   Pf_Decl                     : constant Pf_Rec :=
+                                             Pf_Rec'(F, T, F, F, F, F, F, F);
+   Pf_Decl_Gins_Pbod_Rnam      : constant Pf_Rec :=
+                                             Pf_Rec'(F, T, T, T, T, F, F, F);
+   Pf_Decl_Pbod                : constant Pf_Rec :=
+                                             Pf_Rec'(F, T, F, T, F, F, F, F);
+   Pf_Pbod                     : constant Pf_Rec :=
+                                             Pf_Rec'(F, F, F, T, F, F, F, F);
+   Pf_Spcn                     : constant Pf_Rec :=
+                                             Pf_Rec'(T, F, F, F, F, F, F, F);
+   --  The above are the only allowed values of Pf_Rec arguments
+
+   type SS_Rec is record
+      Eftm : Boolean;      -- ELSIF can terminate sequence
+      Eltm : Boolean;      -- ELSE can terminate sequence
+      Extm : Boolean;      -- EXCEPTION can terminate sequence
+      Ortm : Boolean;      -- OR can terminate sequence
+      Sreq : Boolean;      -- at least one statement required
+      Tatm : Boolean;      -- THEN ABORT can terminate sequence
+      Whtm : Boolean;      -- WHEN can terminate sequence
+      Unco : Boolean;      -- Unconditional terminate after one statement
+   end record;
+   pragma Pack (SS_Rec);
+
+   SS_Eftm_Eltm_Sreq : constant SS_Rec := SS_Rec'(T, T, F, F, T, F, F, F);
+   SS_Eltm_Ortm_Tatm : constant SS_Rec := SS_Rec'(F, T, F, T, F, T, F, F);
+   SS_Extm_Sreq      : constant SS_Rec := SS_Rec'(F, F, T, F, T, F, F, F);
+   SS_None           : constant SS_Rec := SS_Rec'(F, F, F, F, F, F, F, F);
+   SS_Ortm_Sreq      : constant SS_Rec := SS_Rec'(F, F, F, T, T, F, F, F);
+   SS_Sreq           : constant SS_Rec := SS_Rec'(F, F, F, F, T, F, F, F);
+   SS_Sreq_Whtm      : constant SS_Rec := SS_Rec'(F, F, F, F, T, F, T, F);
+   SS_Whtm           : constant SS_Rec := SS_Rec'(F, F, F, F, F, F, T, F);
+   SS_Unco           : constant SS_Rec := SS_Rec'(F, F, F, F, F, F, F, T);
+
+   Label_List : Elist_Id;
+   --  List of label nodes for labels appearing in the current compilation.
+   --  Used by Par.Labl to construct the corresponding implicit declarations.
+
+   -----------------
+   -- Scope Table --
+   -----------------
+
+   --  The scope table, also referred to as the scope stack, is used to
+   --  record the current scope context. It is organized as a stack, with
+   --  inner nested entries corresponding to higher entries on the stack.
+   --  An entry is made when the parser encounters the opening of a nested
+   --  construct (such as a record, task, package etc.), and then package
+   --  Par.Endh uses this stack to deal with END lines (including properly
+   --  dealing with END nesting errors).
+
+   type SS_End_Type is
+   --  Type of end entry required for this scope. The last two entries are
+   --  used only in the subprogram body case to mark the case of a suspicious
+   --  IS, or a bad IS (i.e. suspicions confirmed by missing BEGIN or END).
+   --  See separate section on dealing with IS used in place of semicolon.
+   --  Note that for many purposes E_Name, E_Suspicious_Is and E_Bad_Is are
+   --  treated the same (E_Suspicious_Is and E_Bad_Is are simply special cases
+   --  of E_Name). They are placed at the end of the enumeration so that a
+   --  test for >= E_Name catches all three cases efficiently.
+
+      (E_Dummy,           -- dummy entry at outer level
+       E_Case,            -- END CASE;
+       E_If,              -- END IF;
+       E_Loop,            -- END LOOP;
+       E_Record,          -- END RECORD;
+       E_Select,          -- END SELECT;
+       E_Name,            -- END [name];
+       E_Suspicious_Is,   -- END [name]; (case of suspicious IS)
+       E_Bad_Is);         -- END [name]; (case of bad IS)
+
+   --  The following describes a single entry in the scope table
+
+   type Scope_Table_Entry is record
+      Etyp : SS_End_Type;
+      --  Type of end entry, as per above description
+
+      Lreq : Boolean;
+      --  A flag indicating whether the label, if present, is required to
+      --  appear on the end line. It is referenced only in the case of
+      --  Etyp = E_Name or E_Suspicious_Is where the name may or may not be
+      --  required (yes for labeled block, no in other cases). Note that for
+      --  all cases except begin, the question of whether a label is required
+      --  can be determined from the other fields (for loop, it is required if
+      --  it is present, and for the other constructs it is never required or
+      --  allowed).
+
+      Ecol : Column_Number;
+      --  Contains the absolute column number (with tabs expanded) of the
+      --  the expected column of the end assuming normal Ada indentation
+      --  usage. If the RM_Column_Check mode is set, this value is used for
+      --  generating error messages about indentation. Otherwise it is used
+      --  only to control heuristic error recovery actions.
+
+      Labl : Node_Id;
+      --  This field is used only for the LOOP and BEGIN cases, and is the
+      --  Node_Id value of the label name. For all cases except child units,
+      --  this value is an entity whose Chars field contains the name pointer
+      --  that identifies the label uniquely. For the child unit case the Labl
+      --  field references an N_Defining_Program_Unit_Name node for the name.
+      --  For cases other than LOOP or BEGIN, the Label field is set to Error,
+      --  indicating that it is an error to have a label on the end line.
+
+      Decl : List_Id;
+      --  Points to the list of declarations (i.e. the declarative part)
+      --  associated with this construct. It is set only in the END [name]
+      --  cases, and is set to No_List for all other cases which do not have a
+      --  declarative unit associated with them. This is used for determining
+      --  the proper location for implicit label declarations.
+
+      Node : Node_Id;
+      --  Empty except in the case of entries for IF and CASE statements,
+      --  in which case it contains the N_If_Statement or N_Case_Statement
+      --  node. This is used for setting the End_Span field.
+
+      Sloc : Source_Ptr;
+      --  Source location of the opening token of the construct. This is
+      --  used to refer back to this line in error messages (such as missing
+      --  or incorrect end lines). The Sloc field is not used, and is not set,
+      --  if a label is present (the Labl field provides the text name of the
+      --  label in this case, which is fine for error messages).
+
+      S_Is : Source_Ptr;
+      --  S_Is is relevant only if Etyp is set to E_Suspicious_Is or
+      --  E_Bad_Is. It records the location of the IS that is considered
+      --  to be suspicious.
+
+      Junk : Boolean;
+      --  A boolean flag that is set true if the opening entry is the dubious
+      --  result of some prior error, e.g. a record entry where the record
+      --  keyword was missing. It is used to suppress the issuing of a
+      --  corresponding junk complaint about the end line (we do not want
+      --  to complain about a missing end record when there was no record).
+   end record;
+
+   --  The following declares the scope table itself. The Last field is the
+   --  stack pointer, so that Scope.Table (Scope.Last) is the top entry. The
+   --  oldest entry, at Scope_Stack (0), is a dummy entry with Etyp set to
+   --  E_Dummy, and the other fields undefined. This dummy entry ensures that
+   --  Scope_Stack (Scope_Stack_Ptr).Etyp can always be tested, and that the
+   --  scope stack pointer is always in range.
+
+   package Scope is new Table.Table (
+     Table_Component_Type => Scope_Table_Entry,
+     Table_Index_Type     => Int,
+     Table_Low_Bound      => 0,
+     Table_Initial        => 50,
+     Table_Increment      => 100,
+     Table_Name           => "Scope");
+
+   ---------------------------------
+   -- Parsing Routines by Chapter --
+   ---------------------------------
+
+   --  Uncommented declarations in this section simply parse the construct
+   --  corresponding to their name, and return an ID value for the Node or
+   --  List that is created.
+
+   package Ch2 is
+      function P_Identifier                           return Node_Id;
+      function P_Pragma                               return Node_Id;
+
+      function P_Pragmas_Opt return List_Id;
+      --  This function scans for a sequence of pragmas in other than a
+      --  declaration sequence or statement sequence context. All pragmas
+      --  can appear except pragmas Assert and Debug, which are only allowed
+      --  in a declaration or statement sequence context.
+
+      procedure P_Pragmas_Misplaced;
+      --  Skips misplaced pragmas with a complaint
+
+      procedure P_Pragmas_Opt (List : List_Id);
+      --  Parses optional pragmas and appends them to the List
+   end Ch2;
+
+   package Ch3 is
+      Missing_Begin_Msg : Error_Msg_Id;
+      --  This variable is set by a call to P_Declarative_Part. Normally it
+      --  is set to No_Error_Msg, indicating that no special processing is
+      --  required by the caller. The special case arises when a statement
+      --  is found in the sequence of declarations. In this case the Id of
+      --  the message issued ("declaration expected") is preserved in this
+      --  variable, then the caller can change it to an appropriate missing
+      --  begin message if indeed the BEGIN is missing.
+
+      function P_Access_Definition                    return Node_Id;
+      function P_Access_Type_Definition               return Node_Id;
+      function P_Array_Type_Definition                return Node_Id;
+      function P_Basic_Declarative_Items              return List_Id;
+      function P_Constraint_Opt                       return Node_Id;
+      function P_Declarative_Part                     return List_Id;
+      function P_Defining_Identifier                  return Node_Id;
+      function P_Discrete_Choice_List                 return List_Id;
+      function P_Discrete_Range                       return Node_Id;
+      function P_Discrete_Subtype_Definition          return Node_Id;
+      function P_Known_Discriminant_Part_Opt          return List_Id;
+      function P_Signed_Integer_Type_Definition       return Node_Id;
+      function P_Range                                return Node_Id;
+      function P_Range_Or_Subtype_Mark                return Node_Id;
+      function P_Range_Constraint                     return Node_Id;
+      function P_Record_Definition                    return Node_Id;
+      function P_Subtype_Indication                   return Node_Id;
+      function P_Subtype_Mark                         return Node_Id;
+      function P_Subtype_Mark_Resync                  return Node_Id;
+      function P_Unknown_Discriminant_Part_Opt        return Boolean;
+
+      procedure P_Component_Items (Decls : List_Id);
+      --  Scan out one or more component items and append them to the
+      --  given list. Only scans out more than one declaration in the
+      --  case where the source has a single declaration with multiple
+      --  defining identifiers.
+
+      function Init_Expr_Opt (P : Boolean := False) return Node_Id;
+      --  If an initialization expression is present (:= expression), then
+      --  it is scanned out and returned, otherwise Empty is returned if no
+      --  initialization expression is present. This procedure also handles
+      --  certain common error cases cleanly. The parameter P indicates if
+      --  a right paren can follow the expression (default = no right paren
+      --  allowed).
+
+      procedure Skip_Declaration (S : List_Id);
+      --  Used when scanning statements to skip past a mispaced declaration
+      --  The declaration is scanned out and appended to the given list.
+      --  Token is known to be a declaration token (in Token_Class_Declk)
+      --  on entry, so there definition is a declaration to be scanned.
+
+      function P_Subtype_Indication (Subtype_Mark : Node_Id) return Node_Id;
+      --  This version of P_Subtype_Indication is called when the caller has
+      --  already scanned out the subtype mark which is passed as a parameter.
+
+      function P_Subtype_Mark_Attribute (Type_Node : Node_Id) return Node_Id;
+      --  Parse a subtype mark attribute. The caller has already parsed the
+      --  subtype mark, which is passed in as the argument, and has checked
+      --  that the current token is apostrophe.
+
+   end Ch3;
+
+   package Ch4 is
+      function P_Aggregate                            return Node_Id;
+      function P_Expression                           return Node_Id;
+      function P_Expression_No_Right_Paren            return Node_Id;
+      function P_Expression_Or_Range_Attribute        return Node_Id;
+      function P_Function_Name                        return Node_Id;
+      function P_Name                                 return Node_Id;
+      function P_Qualified_Simple_Name                return Node_Id;
+      function P_Qualified_Simple_Name_Resync         return Node_Id;
+      function P_Simple_Expression                    return Node_Id;
+      function P_Simple_Expression_Or_Range_Attribute return Node_Id;
+
+      function P_Qualified_Expression
+        (Subtype_Mark : Node_Id)
+         return         Node_Id;
+      --  This routine scans out a qualified expression when the caller has
+      --  already scanned out the name and apostrophe of the construct.
+
+   end Ch4;
+
+   package Ch5 is
+
+      function P_Statement_Name (Name_Node : Node_Id) return Node_Id;
+      --  Given a node representing a name (which is a call), converts it
+      --  to the syntactically corresponding procedure call statement.
+
+      function P_Sequence_Of_Statements (SS_Flags : SS_Rec) return List_Id;
+      --  The argument indicates the acceptable termination tokens.
+      --  See body in Par.Ch5 for details of the use of this parameter.
+
+      procedure Parse_Decls_Begin_End (Parent : Node_Id);
+      --  Parses declarations and handled statement sequence, setting
+      --  fields of Parent node appropriately.
+
+   end Ch5;
+
+   package Ch6 is
+      function P_Designator                           return Node_Id;
+      function P_Defining_Program_Unit_Name           return Node_Id;
+      function P_Formal_Part                          return List_Id;
+      function P_Parameter_Profile                    return List_Id;
+      function P_Return_Statement                     return Node_Id;
+      function P_Subprogram_Specification             return Node_Id;
+
+      procedure P_Mode (Node : Node_Id);
+      --  Sets In_Present and/or Out_Present flags in Node scanning past
+      --  IN, OUT or IN OUT tokens in the source.
+
+      function P_Subprogram (Pf_Flags : Pf_Rec)       return Node_Id;
+      --  Scans out any construct starting with either of the keywords
+      --  PROCEDURE or FUNCTION. The parameter indicates which possible
+      --  possible kinds of construct (body, spec, instantiation etc.)
+      --  are permissible in the current context.
+
+   end Ch6;
+
+   package Ch7 is
+      function P_Package (Pf_Flags : Pf_Rec) return Node_Id;
+      --  Scans out any construct starting with the keyword PACKAGE. The
+      --  parameter indicates which possible kinds of construct (body, spec,
+      --  instantiation etc.) are permissible in the current context.
+   end Ch7;
+
+   package Ch8 is
+      function P_Use_Clause                           return Node_Id;
+   end Ch8;
+
+   package Ch9 is
+      function P_Abort_Statement                      return Node_Id;
+      function P_Abortable_Part                       return Node_Id;
+      function P_Accept_Statement                     return Node_Id;
+      function P_Delay_Statement                      return Node_Id;
+      function P_Entry_Body                           return Node_Id;
+      function P_Protected                            return Node_Id;
+      function P_Requeue_Statement                    return Node_Id;
+      function P_Select_Statement                     return Node_Id;
+      function P_Task                                 return Node_Id;
+      function P_Terminate_Alternative                return Node_Id;
+   end Ch9;
+
+   package Ch10 is
+      function P_Compilation_Unit                     return Node_Id;
+      --  Note: this function scans a single compilation unit, and
+      --  checks that an end of file follows this unit, diagnosing
+      --  any unexpected input as an error, and then skipping it, so
+      --  that Token is set to Tok_EOF on return. An exception is in
+      --  syntax-only mode, where multiple compilation units are
+      --  permitted. In this case, P_Compilation_Unit does not check
+      --  for end of file and there may be more compilation units to
+      --  scan. The caller can uniquely detect this situation by the
+      --  fact that Token is not set to Tok_EOF on return.
+   end Ch10;
+
+   package Ch11 is
+      function P_Handled_Sequence_Of_Statements       return Node_Id;
+      function P_Raise_Statement                      return Node_Id;
+
+      function Parse_Exception_Handlers               return List_Id;
+      --  Parses the partial construct EXCEPTION followed by a list of
+      --  exception handlers which appears in a number of productions,
+      --  and returns the list of exception handlers.
+
+   end Ch11;
+
+   package Ch12 is
+      function P_Generic                              return Node_Id;
+      function P_Generic_Actual_Part_Opt              return List_Id;
+   end Ch12;
+
+   package Ch13 is
+      function P_Representation_Clause                return Node_Id;
+
+      function P_Code_Statement (Subtype_Mark : Node_Id) return Node_Id;
+      --  Function to parse a code statement. The caller has scanned out
+      --  the name to be used as the subtype mark (but has not checked that
+      --  it is suitable for use as a subtype mark, i.e. is either an
+      --  identifier or a selected component). The current token is an
+      --  apostrophe and the following token is either a left paren or
+      --  RANGE (the latter being an error to be caught by P_Code_Statement.
+   end Ch13;
+
+   --  Note: the parsing for annexe J features (i.e. obsolescent features)
+   --  is found in the logical section where these features would be if
+   --  they were not obsolescent. In particular:
+
+   --    Delta constraint is parsed by P_Delta_Constraint (3.5.9)
+   --    At clause is parsed by P_At_Clause (13.1)
+   --    Mod clause is parsed by P_Mod_Clause (13.5.1)
+
+   ------------------
+   -- End Handling --
+   ------------------
+
+   --  Routines for handling end lines, including scope recovery
+
+   package Endh is
+
+      function Check_End return Boolean;
+      --  Called when an end sequence is required. In the absence of an error
+      --  situation, Token contains Tok_End on entry, but in a missing end
+      --  case, this may not be the case. Pop_End_Context is used to determine
+      --  the appropriate action to be taken. The returned result is True if
+      --  an End sequence was encountered and False if no End sequence was
+      --  present. This occurs if the END keyword encountered was determined
+      --  to be improper and deleted (i.e. Pop_End_Context set End_Action to
+      --  Skip_And_Reject). Note that the END sequence includes a semicolon,
+      --  except in the case of END RECORD, where a semicolon follows the END
+      --  RECORD, but is not part of the record type definition itself.
+
+      procedure End_Skip;
+      --  Skip past an end sequence. On entry Token contains Tok_End, and we
+      --  we know that the end sequence is syntactically incorrect, and that
+      --  an appropriate error message has already been posted. The mission
+      --  is simply to position the scan pointer to be the best guess of the
+      --  position after the end sequence. We do not issue any additional
+      --  error messages while carrying this out.
+
+      procedure End_Statements (Parent : Node_Id := Empty);
+      --  Called when an end is required or expected to terminate a sequence
+      --  of statements. The caller has already made an appropriate entry in
+      --  the Scope.Table to describe the expected form of the end. This can
+      --  only be used in cases where the only appropriate terminator is end.
+      --  If Parent is non-empty, then if a correct END line is encountered,
+      --  the End_Label field of Parent is set appropriately.
+
+   end Endh;
+
+   ------------------------------------
+   -- Resynchronization After Errors --
+   ------------------------------------
+
+   --  These procedures are used to resynchronize after errors. Following an
+   --  error which is not immediately locally recoverable, the exception
+   --  Error_Resync is raised. The handler for Error_Resync typically calls
+   --  one of these recovery procedures to resynchronize the source position
+   --  to a point from which parsing can be restarted.
+
+   --  Note: these procedures output an information message that tokens are
+   --  being skipped, but this message is output only if the option for
+   --  Multiple_Errors_Per_Line is set in Options.
+
+   package Sync is
+
+      procedure Resync_Choice;
+      --  Used if an error occurs scanning a choice. The scan pointer is
+      --  advanced to the next vertical bar, arrow, or semicolon, whichever
+      --  comes first. We also quit if we encounter an end of file.
+
+      procedure Resync_Expression;
+      --  Used if an error is detected during the parsing of an expression.
+      --  It skips past tokens until either a token which cannot be part of
+      --  an expression is encountered (an expression terminator), or if a
+      --  comma or right parenthesis or vertical bar is encountered at the
+      --  current parenthesis level (a parenthesis level counter is maintained
+      --  to carry out this test).
+
+      procedure Resync_Past_Semicolon;
+      --  Used if an error occurs while scanning a sequence of declarations.
+      --  The scan pointer is positioned past the next semicolon and the scan
+      --  resumes. The scan is also resumed on encountering a token which
+      --  starts a declaration (but we make sure to skip at least one token
+      --  in this case, to avoid getting stuck in a loop).
+
+      procedure Resync_Past_Semicolon_Or_To_Loop_Or_Then;
+      --  Used if an error occurs while scanning a sequence of statements.
+      --  The scan pointer is positioned past the next semicolon, or to the
+      --  next occurrence of either then or loop, and the scan resumes.
+
+      procedure Resync_To_When;
+      --  Used when an error occurs scanning an entry index specification.
+      --  The scan pointer is positioned to the next WHEN (or to IS or
+      --  semicolon if either of these appear before WHEN, indicating
+      --  another error has occurred).
+
+      procedure Resync_Semicolon_List;
+      --  Used if an error occurs while scanning a parenthesized list of items
+      --  separated by semicolons. The scan pointer is advanced to the next
+      --  semicolon or right parenthesis at the outer parenthesis level, or
+      --  to the next is or RETURN keyword occurence, whichever comes first.
+
+      procedure Resync_Cunit;
+      --  Synchronize to next token which could be the start of a compilation
+      --  unit, or to the end of file token.
+
+   end Sync;
+
+   -------------------------
+   -- Token Scan Routines --
+   -------------------------
+
+   --  Routines to check for expected tokens
+
+   package Tchk is
+
+      --  Procedures with names of the form T_xxx, where Tok_xxx is a token
+      --  name, check that the current token matches the required token, and
+      --  if so, scan past it. If not, an error is issued indicating that
+      --  the required token is not present (xxx expected). In most cases, the
+      --  scan pointer is not moved in the not-found case, but there are some
+      --  exceptions to this, see for example T_Id, where the scan pointer is
+      --  moved across a literal appearing where an identifier is expected.
+
+      procedure T_Abort;
+      procedure T_Arrow;
+      procedure T_At;
+      procedure T_Body;
+      procedure T_Box;
+      procedure T_Colon;
+      procedure T_Colon_Equal;
+      procedure T_Comma;
+      procedure T_Dot_Dot;
+      procedure T_For;
+      procedure T_Greater_Greater;
+      procedure T_Identifier;
+      procedure T_In;
+      procedure T_Is;
+      procedure T_Left_Paren;
+      procedure T_Loop;
+      procedure T_Mod;
+      procedure T_New;
+      procedure T_Of;
+      procedure T_Or;
+      procedure T_Private;
+      procedure T_Range;
+      procedure T_Record;
+      procedure T_Right_Paren;
+      procedure T_Semicolon;
+      procedure T_Then;
+      procedure T_Type;
+      procedure T_Use;
+      procedure T_When;
+      procedure T_With;
+
+      --  Procedures have names of the form TF_xxx, where Tok_xxx is a token
+      --  name check that the current token matches the required token, and
+      --  if so, scan past it. If not, an error message is issued indicating
+      --  that the required token is not present (xxx expected).
+
+      --  If the missing token is at the end of the line, then control returns
+      --  immediately after posting the message. If there are remaining tokens
+      --  on the current line, a search is conducted to see if the token
+      --  appears later on the current line, as follows:
+
+      --  A call to Scan_Save is issued and a forward search for the token
+      --  is carried out. If the token is found on the current line before a
+      --  semicolon, then it is scanned out and the scan continues from that
+      --  point. If not the scan is restored to the point where it was missing.
+
+      procedure TF_Arrow;
+      procedure TF_Is;
+      procedure TF_Loop;
+      procedure TF_Return;
+      procedure TF_Semicolon;
+      procedure TF_Then;
+      procedure TF_Use;
+
+   end Tchk;
+
+   ----------------------
+   -- Utility Routines --
+   ----------------------
+
+   package Util is
+
+      function Bad_Spelling_Of (T : Token_Type) return Boolean;
+      --  This function is called in an error situation. It checks if the
+      --  current token is an identifier whose name is a plausible bad
+      --  spelling of the given keyword token, and if so, issues an error
+      --  message, sets Token from T, and returns True. Otherwise Token is
+      --  unchanged, and False is returned.
+
+      procedure Check_Bad_Layout;
+      --  Check for bad indentation in RM checking mode. Used for statements
+      --  and declarations. Checks if current token is at start of line and
+      --  is exdented from the current expected end column, and if so an
+      --  error message is generated.
+
+      procedure Check_Misspelling_Of (T : Token_Type);
+      pragma Inline (Check_Misspelling_Of);
+      --  This is similar to the function above, except that it does not
+      --  return a result. It is typically used in a situation where any
+      --  identifier is an error, and it makes sense to simply convert it
+      --  to the given token if it is a plausible misspelling of it.
+
+      procedure Check_95_Keyword (Token_95, Next : Token_Type);
+      --  This routine checks if the token after the current one matches the
+      --  Next argument. If so, the scan is backed up to the current token
+      --  and Token_Type is changed to Token_95 after issuing an appropriate
+      --  error message ("(Ada 83) keyword xx cannot be used"). If not,
+      --  the scan is backed up with Token_Type unchanged. This routine
+      --  is used to deal with an attempt to use a 95 keyword in Ada 83
+      --  mode. The caller has typically checked that the current token,
+      --  an identifier, matches one of the 95 keywords.
+
+      procedure Check_Simple_Expression (E : Node_Id);
+      --  Given an expression E, that has just been scanned, so that Expr_Form
+      --  is still set, outputs an error if E is a non-simple expression. E is
+      --  not modified by this call.
+
+      procedure Check_Simple_Expression_In_Ada_83 (E : Node_Id);
+      --  Like Check_Simple_Expression, except that the error message is only
+      --  given when operating in Ada 83 mode, and includes "in Ada 83".
+
+      function Check_Subtype_Mark (Mark : Node_Id) return Node_Id;
+      --  Called to check that a node representing a name (or call) is
+      --  suitable for a subtype mark, i.e, that it is an identifier or
+      --  a selected component. If so, or if it is already Error, then
+      --  it is returned unchanged. Otherwise an error message is issued
+      --  and Error is returned.
+
+      function Comma_Present return Boolean;
+      --  Used in comma delimited lists to determine if a comma is present, or
+      --  can reasonably be assumed to have been present (an error message is
+      --  generated in the latter case). If True is returned, the scan has been
+      --  positioned past the comma. If False is returned, the scan position
+      --  is unchanged. Note that all comma-delimited lists are terminated by
+      --  a right paren, so the only legitimate tokens when Comma_Present is
+      --  called are right paren and comma. If some other token is found, then
+      --  Comma_Present has the job of deciding whether it is better to pretend
+      --  a comma was present, post a message for a missing comma and return
+      --  True, or return False and let the caller diagnose the missing right
+      --  parenthesis.
+
+      procedure Discard_Junk_Node (N : Node_Id);
+      procedure Discard_Junk_List (L : List_Id);
+      pragma Inline (Discard_Junk_Node);
+      pragma Inline (Discard_Junk_List);
+      --  These procedures do nothing at all, their effect is simply to discard
+      --  the argument. A typical use is to skip by some junk that is not
+      --  expected in the current context.
+
+      procedure Ignore (T : Token_Type);
+      --  If current token matches T, then give an error message and skip
+      --  past it, otherwise the call has no effect at all. T may be any
+      --  reserved word token, or comma, left or right paren, or semicolon.
+
+      function Is_Reserved_Identifier return Boolean;
+      --  Test if current token is a reserved identifier. This test is based
+      --  on the token being a keyword and being spelled in typical identifier
+      --  style (i.e. starting with an upper case letter).
+
+      procedure Merge_Identifier (Prev : Node_Id; Nxt : Token_Type);
+      --  Called when the previous token is an identifier (whose Token_Node
+      --  value is given by Prev) to check if current token is an identifier
+      --  that can be merged with the previous one adding an underscore. The
+      --  merge is only attempted if the following token matches Nxt. If all
+      --  conditions are met, an error message is issued, and the merge is
+      --  carried out, modifying the Chars field of Prev.
+
+      procedure No_Constraint;
+      --  Called in a place where no constraint is allowed, but one might
+      --  appear due to a common error (e.g. after the type mark in a procedure
+      --  parameter. If a constraint is present, an error message is posted,
+      --  and the constraint is scanned and discarded.
+
+      function No_Right_Paren (Expr : Node_Id) return Node_Id;
+      --  Function to check for no right paren at end of expression, returns
+      --  its argument if no right paren, else flags paren and returns Error.
+
+      procedure Push_Scope_Stack;
+      pragma Inline (Push_Scope_Stack);
+      --  Push a new entry onto the scope stack. Scope.Last (the stack pointer)
+      --  is incremented. The Junk field is preinitialized to False. The caller
+      --  is expected to fill in all remaining entries of the new new top stack
+      --  entry at Scope.Table (Scope.Last).
+
+      procedure Pop_Scope_Stack;
+      --  Pop an entry off the top of the scope stack. Scope_Last (the scope
+      --  table stack pointer) is decremented by one. It is a fatal error to
+      --  try to pop off the dummy entry at the bottom of the stack (i.e.
+      --  Scope.Last must be non-zero at the time of call).
+
+      function Separate_Present return Boolean;
+      --  Determines if the current token is either Tok_Separate, or an
+      --  identifier that is a possible misspelling of "separate" followed
+      --  by a semicolon. True is returned if so, otherwise False.
+
+      procedure Signal_Bad_Attribute;
+      --  The current token is an identifier that is supposed to be an
+      --  attribute identifier but is not. This routine posts appropriate
+      --  error messages, including a check for a near misspelling.
+
+      function Token_Is_At_Start_Of_Line return Boolean;
+      pragma Inline (Token_Is_At_Start_Of_Line);
+      --  Determines if the current token is the first token on the line
+
+   end Util;
+
+   ---------------------------------------
+   -- Specialized Syntax Check Routines --
+   ---------------------------------------
+
+   function Prag (Pragma_Node : Node_Id; Semi : Source_Ptr) return Node_Id;
+   --  This function is passed a tree for a pragma that has been scanned out.
+   --  The pragma is syntactically well formed according to the general syntax
+   --  for pragmas and the pragma identifier is for one of the recognized
+   --  pragmas. It performs specific syntactic checks for specific pragmas.
+   --  The result is the input node if it is OK, or Error otherwise. The
+   --  reason that this is separated out is to facilitate the addition
+   --  of implementation defined pragmas. The second parameter records the
+   --  location of the semicolon following the pragma (this is needed for
+   --  correct processing of the List and Page pragmas). The returned value
+   --  is a copy of Pragma_Node, or Error if an error is found.
+
+   -------------------------
+   -- Subsidiary Routines --
+   -------------------------
+
+   procedure Labl;
+   --  This procedure creates implicit label declarations for all label that
+   --  are declared in the current unit. Note that this could conceptually
+   --  be done at the point where the labels are declared, but it is tricky
+   --  to do it then, since the tree is not hooked up at the point where the
+   --  label is declared (e.g. a sequence of statements is not yet attached
+   --  to its containing scope at the point a label in the sequence is found)
+
+   procedure Load;
+   --  This procedure loads all subsidiary units that are required by this
+   --  unit, including with'ed units, specs for bodies, and parents for child
+   --  units. It does not load bodies for inlined procedures and generics,
+   --  since we don't know till semantic analysis is complete what is needed.
+
+   -----------
+   -- Stubs --
+   -----------
+
+   --  The package bodies can see all routines defined in all other subpackages
+
+   use Ch2;
+   use Ch3;
+   use Ch4;
+   use Ch5;
+   use Ch6;
+   use Ch7;
+   use Ch8;
+   use Ch9;
+   use Ch10;
+   use Ch11;
+   use Ch12;
+   use Ch13;
+
+   use Endh;
+   use Tchk;
+   use Sync;
+   use Util;
+
+   package body Ch2 is separate;
+   package body Ch3 is separate;
+   package body Ch4 is separate;
+   package body Ch5 is separate;
+   package body Ch6 is separate;
+   package body Ch7 is separate;
+   package body Ch8 is separate;
+   package body Ch9 is separate;
+   package body Ch10 is separate;
+   package body Ch11 is separate;
+   package body Ch12 is separate;
+   package body Ch13 is separate;
+
+   package body Endh is separate;
+   package body Tchk is separate;
+   package body Sync is separate;
+   package body Util is separate;
+
+   function Prag (Pragma_Node : Node_Id; Semi : Source_Ptr) return Node_Id
+     is separate;
+
+   procedure Labl is separate;
+   procedure Load is separate;
+
+   ---------
+   -- Par --
+   ---------
+
+--  This function is the parse routine called at the outer level. It parses
+--  the current compilation unit and adds implicit label declarations.
+
+begin
+   --  Deal with configuration pragmas case first
+
+   if Configuration_Pragmas then
+      declare
+         Ecount  : constant Int := Errors_Detected;
+         Pragmas : List_Id := Empty_List;
+         P_Node  : Node_Id;
+
+      begin
+         loop
+            if Token = Tok_EOF then
+               return Pragmas;
+
+            elsif Token /= Tok_Pragma then
+               Error_Msg_SC ("only pragmas allowed in configuration file");
+               return Error_List;
+
+            else
+               P_Node := P_Pragma;
+
+               if Errors_Detected > Ecount then
+                  return Error_List;
+               end if;
+
+               if Chars (P_Node) > Last_Configuration_Pragma_Name
+                 and then Chars (P_Node) /= Name_Source_Reference
+               then
+                  Error_Msg_SC
+                    ("only configuration pragmas allowed " &
+                     "in configuration file");
+                  return Error_List;
+               end if;
+
+               Append (P_Node, Pragmas);
+            end if;
+         end loop;
+      end;
+
+   --  Normal case of compilation unit
+
+   else
+      Save_Opt_Config_Switches (Save_Config_Switches);
+
+      --  Special processing for language defined units. For this purpose
+      --  we do NOT consider the renamings in annex J as predefined. That
+      --  allows users to compile their own versions of these files, and
+      --  in particular, in the VMS implementation, the DEC versions can
+      --  be substituted for the standard Ada 95 versions.
+
+      if Is_Predefined_File_Name
+           (Fname => File_Name (Current_Source_File),
+            Renamings_Included => False)
+      then
+         Set_Opt_Config_Switches
+           (Is_Internal_File_Name (File_Name (Current_Source_File)));
+
+         --  If this is the main unit, disallow compilation unless the -gnatg
+         --  (GNAT mode) switch is set (from a user point of view, the rule is
+         --  that language defined units cannot be recompiled).
+
+         --  However, an exception is s-rpc, and its children. We test this
+         --  by looking at the character after the minus, the rule is that
+         --  System.RPC and its children are the only children in System
+         --  whose second level name can start with the letter r.
+
+         Get_Name_String (File_Name (Current_Source_File));
+
+         if (Name_Len < 3 or else Name_Buffer (1 .. 3) /= "s-r")
+           and then Current_Source_Unit = Main_Unit
+           and then not GNAT_Mode
+           and then Operating_Mode = Generate_Code
+         then
+            Error_Msg_SC ("language defined units may not be recompiled");
+         end if;
+      end if;
+
+      --  The following loop runs more than once only in syntax check mode
+      --  where we allow multiple compilation units in the same file.
+
+      loop
+         Set_Opt_Config_Switches
+           (Is_Internal_File_Name (File_Name (Current_Source_File)));
+
+         --  Initialize scope table and other parser control variables
+
+         Compiler_State := Parsing;
+         Scope.Init;
+         Scope.Increment_Last;
+         Scope.Table (0).Etyp := E_Dummy;
+         SIS_Entry_Active := False;
+         Last_Resync_Point := No_Location;
+
+         Label_List := New_Elmt_List;
+         Unit_Node := P_Compilation_Unit;
+
+         --  If we are not at an end of file, then this means that we are
+         --  in syntax scan mode, and we can have another compilation unit,
+         --  otherwise we will exit from the loop.
+
+         exit when Token = Tok_EOF;
+         Restore_Opt_Config_Switches (Save_Config_Switches);
+         Set_Comes_From_Source_Default (False);
+      end loop;
+
+      --  Now that we have completely parsed the source file, we can
+      --  complete the source file table entry.
+
+      Complete_Source_File_Entry;
+
+      --  An internal error check, the scope stack should now be empty
+
+      pragma Assert (Scope.Last = 0);
+
+      --  Remaining steps are to create implicit label declarations and to
+      --  load required subsidiary sources. These steps are required only
+      --  if we are doing semantic checking.
+
+      if Operating_Mode /= Check_Syntax or else Debug_Flag_F then
+         Par.Labl;
+         Par.Load;
+      end if;
+
+      --  Restore settings of switches saved on entry
+
+      Restore_Opt_Config_Switches (Save_Config_Switches);
+      Set_Comes_From_Source_Default (False);
+      return Empty_List;
+   end if;
+
+end Par;
diff --git a/gcc/ada/par.ads b/gcc/ada/par.ads
new file mode 100644 (file)
index 0000000..c1110a0
--- /dev/null
@@ -0,0 +1,44 @@
+------------------------------------------------------------------------------
+--                                                                          --
+--                         GNAT COMPILER COMPONENTS                         --
+--                                                                          --
+--                                  P A R                                   --
+--                                                                          --
+--                                 S p e c                                  --
+--                                                                          --
+--                            $Revision: 1.14 $                             --
+--                                                                          --
+--     Copyright (C) 1992,1993,1994,1995 Free Software Foundation, Inc.     --
+--                                                                          --
+-- GNAT is free software;  you can  redistribute it  and/or modify it under --
+-- terms of the  GNU General Public License as published  by the Free Soft- --
+-- ware  Foundation;  either version 2,  or (at your option) any later ver- --
+-- sion.  GNAT is distributed in the hope that it will be useful, but WITH- --
+-- OUT 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  distributed with GNAT;  see file COPYING.  If not, write --
+-- to  the Free Software Foundation,  59 Temple Place - Suite 330,  Boston, --
+-- MA 02111-1307, USA.                                                      --
+--                                                                          --
+-- GNAT was originally developed  by the GNAT team at  New York University. --
+-- It is now maintained by Ada Core Technologies Inc (http://www.gnat.com). --
+--                                                                          --
+------------------------------------------------------------------------------
+
+--  The Par function and its subunits contains all the parsing routines
+--  for the top down recursive descent parser that constructs the parse tree
+
+with Types; use Types;
+
+function Par (Configuration_Pragmas : Boolean) return List_Id;
+--  Top level parsing routine. There are two cases:
+--
+--  If Configuration_Pragmas is False, Par parses a compilation unit in the
+--  current source file and sets the Cunit, Cunit_Entity and Unit_Name fields
+--  of the units table entry for Current_Source_Unit. On return the parse tree
+--  is complete, and decorated with any required implicit label declarations.
+--  The value returned in this case is always No_List.
+--
+--  If Configuration_Pragmas is True, Par parses a list of configuration
+--  pragmas from the current source file, and returns the list of pragmas.
diff --git a/gcc/ada/prj-attr.adb b/gcc/ada/prj-attr.adb
new file mode 100644 (file)
index 0000000..aa79302
--- /dev/null
@@ -0,0 +1,211 @@
+------------------------------------------------------------------------------
+--                                                                          --
+--                         GNAT COMPILER COMPONENTS                         --
+--                                                                          --
+--                              P R J . A T T R                             --
+--                                                                          --
+--                                 B o d y                                  --
+--                                                                          --
+--                            $Revision: 1.4 $
+--                                                                          --
+--             Copyright (C) 2001 Free Software Foundation, Inc.            --
+--                                                                          --
+-- GNAT is free software;  you can  redistribute it  and/or modify it under --
+-- terms of the  GNU General Public License as published  by the Free Soft- --
+-- ware  Foundation;  either version 2,  or (at your option) any later ver- --
+-- sion.  GNAT is distributed in the hope that it will be useful, but WITH- --
+-- OUT 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  distributed with GNAT;  see file COPYING.  If not, write --
+-- to  the Free Software Foundation,  59 Temple Place - Suite 330,  Boston, --
+-- MA 02111-1307, USA.                                                      --
+--                                                                          --
+-- GNAT was originally developed  by the GNAT team at  New York University. --
+-- It is now maintained by Ada Core Technologies Inc (http://www.gnat.com). --
+--                                                                          --
+------------------------------------------------------------------------------
+
+with Ada.Characters.Handling; use Ada.Characters.Handling;
+with Namet;     use Namet;
+with Output;    use Output;
+
+package body Prj.Attr is
+
+   --  Names end with '#'
+   --  Package names are preceded by 'P'
+   --  Attribute names are preceded by two capital letters:
+   --    'S' for Single or 'L' for list, then
+   --    'V' for single variable, 'A' for associative array, or 'B' for both.
+   --  End is indicated by two consecutive '#'.
+
+   Initialisation_Data : constant String :=
+
+   --  project attributes
+
+     "SVobject_dir#" &
+     "LVsource_dirs#" &
+     "LVsource_files#" &
+     "SVsource_list_file#" &
+     "SVlibrary_dir#" &
+     "SVlibrary_name#" &
+     "SVlibrary_kind#" &
+     "SVlibrary_elaboration#" &
+     "SVlibrary_version#" &
+     "LVmain#" &
+
+   --  package Naming
+
+     "Pnaming#" &
+     "SVspecification_append#" &
+     "SVbody_append#" &
+     "SVseparate_append#" &
+     "SVcasing#" &
+     "SVdot_replacement#" &
+     "SAspecification#" &
+     "SAbody_part#" &
+
+   --  package Compiler
+
+     "Pcompiler#" &
+     "LBswitches#" &
+     "SVlocal_configuration_pragmas#" &
+
+   --  package gnatmake
+
+     "Pgnatmake#" &
+     "LBswitches#" &
+     "SVglobal_configuration_pragmas#" &
+
+   --  package gnatls
+
+     "Pgnatls#" &
+     "LVswitches#" &
+
+   --  package gnatbind
+
+     "Pgnatbind#" &
+     "LBswitches#" &
+
+   --  package gnatlink
+
+     "Pgnatlink#" &
+     "LBswitches#" &
+
+     "#";
+
+   ----------------
+   -- Initialize --
+   ----------------
+
+   procedure Initialize is
+      Start             : Positive           := Initialisation_Data'First;
+      Finish            : Positive           := Start;
+      Current_Package   : Package_Node_Id    := Empty_Package;
+      Current_Attribute : Attribute_Node_Id  := Empty_Attribute;
+      Is_An_Attribute   : Boolean            := False;
+      Kind_1            : Variable_Kind      := Undefined;
+      Kind_2            : Attribute_Kind     := Single;
+      Package_Name      : Name_Id            := No_Name;
+      Attribute_Name    : Name_Id            := No_Name;
+      First_Attribute   : Attribute_Node_Id  := Attribute_First;
+   begin
+
+      --  Make sure the two tables are empty
+
+      Attributes.Set_Last (Attributes.First);
+      Package_Attributes.Set_Last (Package_Attributes.First);
+
+      while Initialisation_Data (Start) /= '#' loop
+         Is_An_Attribute := True;
+         case Initialisation_Data (Start) is
+            when 'P' =>
+               --  New allowed package
+               Start := Start + 1;
+               Finish := Start;
+               while Initialisation_Data (Finish) /= '#' loop
+                  Finish := Finish + 1;
+               end loop;
+               Name_Len := Finish - Start;
+               Name_Buffer (1 .. Name_Len) :=
+                 To_Lower (Initialisation_Data (Start .. Finish - 1));
+               Package_Name := Name_Find;
+               for Index in Package_First .. Package_Attributes.Last loop
+                  if Package_Name = Package_Attributes.Table (Index).Name then
+                     Write_Line ("Duplicate package name """ &
+                                 Initialisation_Data (Start .. Finish - 1) &
+                                 """ in Prj.Attr body.");
+                     raise Program_Error;
+                  end if;
+               end loop;
+
+               Is_An_Attribute := False;
+               Current_Attribute := Empty_Attribute;
+               Package_Attributes.Increment_Last;
+               Current_Package := Package_Attributes.Last;
+               Package_Attributes.Table (Current_Package).Name :=
+                 Package_Name;
+               Start := Finish + 1;
+            when 'S' =>
+               Kind_1 := Single;
+            when 'L' =>
+               Kind_1 := List;
+            when others =>
+               raise Program_Error;
+         end case;
+
+         if Is_An_Attribute then
+            --  New attribute
+            Start := Start + 1;
+            case Initialisation_Data (Start) is
+               when 'V' =>
+                  Kind_2 := Single;
+               when 'A' =>
+                  Kind_2 := Associative_Array;
+               when 'B' =>
+                  Kind_2 := Both;
+               when others =>
+                  raise Program_Error;
+            end case;
+            Start := Start + 1;
+            Finish := Start;
+            while Initialisation_Data (Finish) /= '#' loop
+               Finish := Finish + 1;
+            end loop;
+            Name_Len := Finish - Start;
+            Name_Buffer (1 .. Name_Len) :=
+              To_Lower (Initialisation_Data (Start .. Finish - 1));
+            Attribute_Name := Name_Find;
+            Attributes.Increment_Last;
+            if Current_Attribute = Empty_Attribute then
+               First_Attribute := Attributes.Last;
+               if Current_Package /= Empty_Package then
+                  Package_Attributes.Table (Current_Package).First_Attribute
+                    := Attributes.Last;
+               end if;
+            else
+               --  Check that there are no duplicate attributes
+               for Index in First_Attribute .. Attributes.Last - 1 loop
+                  if Attribute_Name =
+                    Attributes.Table (Index).Name then
+                     Write_Line ("Duplicate attribute name """ &
+                                 Initialisation_Data (Start .. Finish - 1) &
+                                 """ in Prj.Attr body.");
+                     raise Program_Error;
+                  end if;
+               end loop;
+               Attributes.Table (Current_Attribute).Next :=
+                 Attributes.Last;
+            end if;
+            Current_Attribute := Attributes.Last;
+            Attributes.Table (Current_Attribute) :=
+              (Name    => Attribute_Name,
+               Kind_1  => Kind_1,
+               Kind_2  => Kind_2,
+               Next    => Empty_Attribute);
+            Start := Finish + 1;
+         end if;
+      end loop;
+   end Initialize;
+
+end Prj.Attr;
diff --git a/gcc/ada/prj-attr.ads b/gcc/ada/prj-attr.ads
new file mode 100644 (file)
index 0000000..ba4bb2e
--- /dev/null
@@ -0,0 +1,108 @@
+------------------------------------------------------------------------------
+--                                                                          --
+--                         GNAT COMPILER COMPONENTS                         --
+--                                                                          --
+--                              P R J . A T T R                             --
+--                                                                          --
+--                                 S p e c                                  --
+--                                                                          --
+--                            $Revision: 1.1 $
+--                                                                          --
+--             Copyright (C) 2001 Free Software Foundation, Inc.            --
+--                                                                          --
+-- GNAT is free software;  you can  redistribute it  and/or modify it under --
+-- terms of the  GNU General Public License as published  by the Free Soft- --
+-- ware  Foundation;  either version 2,  or (at your option) any later ver- --
+-- sion.  GNAT is distributed in the hope that it will be useful, but WITH- --
+-- OUT 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  distributed with GNAT;  see file COPYING.  If not, write --
+-- to  the Free Software Foundation,  59 Temple Place - Suite 330,  Boston, --
+-- MA 02111-1307, USA.                                                      --
+--                                                                          --
+-- GNAT was originally developed  by the GNAT team at  New York University. --
+-- It is now maintained by Ada Core Technologies Inc (http://www.gnat.com). --
+--                                                                          --
+------------------------------------------------------------------------------
+--
+--  This package defines allowed packages and attributes in GNAT project
+--  files.
+
+with Types; use Types;
+with Table;
+
+package Prj.Attr is
+
+   --  Define the allowed attributes
+
+   Attributes_Initial   : constant := 50;
+   Attributes_Increment : constant := 50;
+
+   Attribute_Node_Low_Bound  : constant := 0;
+   Attribute_Node_High_Bound : constant := 099_999_999;
+
+   type Attribute_Node_Id is
+     range Attribute_Node_Low_Bound .. Attribute_Node_High_Bound;
+
+   First_Attribute_Node_Id : constant Attribute_Node_Id
+     := Attribute_Node_Low_Bound;
+
+   Empty_Attribute : constant Attribute_Node_Id
+     := Attribute_Node_Low_Bound;
+
+   type Attribute_Kind is (Single, Associative_Array, Both);
+
+   type Attribute_Record is record
+      Name     : Name_Id;
+      Kind_1   : Variable_Kind;
+      Kind_2   : Attribute_Kind;
+      Next     : Attribute_Node_Id;
+   end record;
+
+   package Attributes is
+      new Table.Table (Table_Component_Type => Attribute_Record,
+                       Table_Index_Type     => Attribute_Node_Id,
+                       Table_Low_Bound      => First_Attribute_Node_Id,
+                       Table_Initial        => Attributes_Initial,
+                       Table_Increment      => Attributes_Increment,
+                       Table_Name           => "Prj.Attr.Attributes");
+
+   Attribute_First : constant Attribute_Node_Id := First_Attribute_Node_Id + 1;
+
+   --  Define the allowed packages
+
+   Packages_Initial   : constant := 10;
+   Packages_Increment : constant := 10;
+
+   Package_Node_Low_Bound  : constant := 0;
+   Package_Node_High_Bound : constant := 099_999_999;
+
+   type Package_Node_Id is
+     range Package_Node_Low_Bound .. Package_Node_High_Bound;
+
+   First_Package_Node_Id : constant Package_Node_Id
+     := Package_Node_Low_Bound;
+
+   Empty_Package : constant Package_Node_Id := Package_Node_Low_Bound;
+
+   type Package_Record is record
+      Name            : Name_Id;
+      First_Attribute : Attribute_Node_Id;
+   end record;
+
+   package Package_Attributes is
+      new Table.Table (Table_Component_Type => Package_Record,
+                       Table_Index_Type     => Package_Node_Id,
+                       Table_Low_Bound      => First_Package_Node_Id,
+                       Table_Initial        => Packages_Initial,
+                       Table_Increment      => Packages_Increment,
+                       Table_Name           => "Prj.Attr.Packages");
+
+   Package_First : constant Package_Node_Id := Package_Node_Low_Bound + 1;
+
+   procedure Initialize;
+   --  Initialize the two tables above (Attributes and Package_Attributes).
+   --  This procedure should be called by Prj.Initialize.
+
+end Prj.Attr;
diff --git a/gcc/ada/prj-com.adb b/gcc/ada/prj-com.adb
new file mode 100644 (file)
index 0000000..3447e18
--- /dev/null
@@ -0,0 +1,49 @@
+------------------------------------------------------------------------------
+--                                                                          --
+--                         GNAT COMPILER COMPONENTS                         --
+--                                                                          --
+--                              P R J . C O M                               --
+--                                                                          --
+--                                 B o d y                                  --
+--                                                                          --
+--                            $Revision: 1.1 $
+--                                                                          --
+--             Copyright (C) 2000 Free Software Foundation, Inc.            --
+--                                                                          --
+-- GNAT is free software;  you can  redistribute it  and/or modify it under --
+-- terms of the  GNU General Public License as published  by the Free Soft- --
+-- ware  Foundation;  either version 2,  or (at your option) any later ver- --
+-- sion.  GNAT is distributed in the hope that it will be useful, but WITH- --
+-- OUT 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  distributed with GNAT;  see file COPYING.  If not, write --
+-- to  the Free Software Foundation,  59 Temple Place - Suite 330,  Boston, --
+-- MA 02111-1307, USA.                                                      --
+--                                                                          --
+-- GNAT was originally developed  by the GNAT team at  New York University. --
+-- It is now maintained by Ada Core Technologies Inc (http://www.gnat.com). --
+--                                                                          --
+------------------------------------------------------------------------------
+
+with Namet;   use Namet;
+with Stringt; use Stringt;
+
+package body Prj.Com is
+
+   ----------
+   -- Hash --
+   ----------
+
+   function Hash (Name : Name_Id) return Header_Num is
+   begin
+      return Hash (Get_Name_String (Name));
+   end Hash;
+
+   function Hash (Name : String_Id) return Header_Num is
+   begin
+      String_To_Name_Buffer (Name);
+      return Hash (Name_Buffer (1 .. Name_Len));
+   end Hash;
+
+end Prj.Com;
diff --git a/gcc/ada/prj-com.ads b/gcc/ada/prj-com.ads
new file mode 100644 (file)
index 0000000..ddb7d0f
--- /dev/null
@@ -0,0 +1,92 @@
+------------------------------------------------------------------------------
+--                                                                          --
+--                         GNAT COMPILER COMPONENTS                         --
+--                                                                          --
+--                              P R J . C O M                               --
+--                                                                          --
+--                                 S p e c                                  --
+--                                                                          --
+--                            $Revision: 1.3 $                              --
+--                                                                          --
+--          Copyright (C) 1992-2000 Free Software Foundation, Inc.          --
+--                                                                          --
+-- GNAT is free software;  you can  redistribute it  and/or modify it under --
+-- terms of the  GNU General Public License as published  by the Free Soft- --
+-- ware  Foundation;  either version 2,  or (at your option) any later ver- --
+-- sion.  GNAT is distributed in the hope that it will be useful, but WITH- --
+-- OUT 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  distributed with GNAT;  see file COPYING.  If not, write --
+-- to  the Free Software Foundation,  59 Temple Place - Suite 330,  Boston, --
+-- MA 02111-1307, USA.                                                      --
+--                                                                          --
+-- GNAT was originally developed  by the GNAT team at  New York University. --
+-- It is now maintained by Ada Core Technologies Inc (http://www.gnat.com). --
+--                                                                          --
+------------------------------------------------------------------------------
+
+--  The following package declares data types for GNAT project.
+--  These data types are used in the bodies of the Prj hierarchy.
+
+with GNAT.HTable;
+with Table;
+with Types; use Types;
+
+package Prj.Com is
+
+   --  At one point, this package was private.
+   --  It cannot be private, because it is used outside of
+   --  the Prj hierarchy.
+
+   Tool_Name : Name_Id := No_Name;
+
+   Current_Verbosity : Verbosity := Default;
+
+   type Spec_Or_Body is
+     (Specification, Body_Part);
+
+   type File_Name_Data is record
+      Name         : Name_Id := No_Name;
+      Path         : Name_Id := No_Name;
+      Project      : Project_Id := No_Project;
+      Needs_Pragma : Boolean := False;
+   end record;
+   --  File and Path name of a spec or body.
+
+   type File_Names_Data is array (Spec_Or_Body) of File_Name_Data;
+
+   type Unit_Id is new Nat;
+   No_Unit : constant Unit_Id := 0;
+   type Unit_Data is record
+      Name       : Name_Id    := No_Name;
+      File_Names : File_Names_Data;
+   end record;
+   --  File and Path names of a unit, with a reference to its
+   --  GNAT Project File.
+
+   package Units is new Table.Table
+     (Table_Component_Type => Unit_Data,
+      Table_Index_Type     => Unit_Id,
+      Table_Low_Bound      => 1,
+      Table_Initial        => 100,
+      Table_Increment      => 100,
+      Table_Name           => "Prj.Com.Units");
+
+   type Header_Num is range 0 .. 2047;
+
+   function Hash is new GNAT.HTable.Hash (Header_Num => Header_Num);
+
+   function Hash (Name : Name_Id) return Header_Num;
+
+   function Hash (Name : String_Id) return Header_Num;
+
+   package Units_Htable is new GNAT.HTable.Simple_HTable
+     (Header_Num => Header_Num,
+      Element    => Unit_Id,
+      No_Element => No_Unit,
+      Key        => Name_Id,
+      Hash       => Hash,
+      Equal      => "=");
+
+end Prj.Com;
diff --git a/gcc/ada/prj-dect.adb b/gcc/ada/prj-dect.adb
new file mode 100644 (file)
index 0000000..65f7e43
--- /dev/null
@@ -0,0 +1,942 @@
+------------------------------------------------------------------------------
+--                                                                          --
+--                         GNAT COMPILER COMPONENTS                         --
+--                                                                          --
+--                              P R J . D E C T                             --
+--                                                                          --
+--                                 B o d y                                  --
+--                                                                          --
+--                            $Revision: 1.5 $
+--                                                                          --
+--             Copyright (C) 2001 Free Software Foundation, Inc.            --
+--                                                                          --
+-- GNAT is free software;  you can  redistribute it  and/or modify it under --
+-- terms of the  GNU General Public License as published  by the Free Soft- --
+-- ware  Foundation;  either version 2,  or (at your option) any later ver- --
+-- sion.  GNAT is distributed in the hope that it will be useful, but WITH- --
+-- OUT 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  distributed with GNAT;  see file COPYING.  If not, write --
+-- to  the Free Software Foundation,  59 Temple Place - Suite 330,  Boston, --
+-- MA 02111-1307, USA.                                                      --
+--                                                                          --
+-- GNAT was originally developed  by the GNAT team at  New York University. --
+-- It is now maintained by Ada Core Technologies Inc (http://www.gnat.com). --
+--                                                                          --
+------------------------------------------------------------------------------
+
+with Errout;     use Errout;
+with Prj.Strt;
+with Prj.Tree;   use Prj.Tree;
+with Scans;      use Scans;
+with Sinfo;      use Sinfo;
+with Types;      use Types;
+with Prj.Attr;   use Prj.Attr;
+
+package body Prj.Dect is
+
+   type Zone is (In_Project, In_Package, In_Case_Construction);
+
+   procedure Parse_Attribute_Declaration
+     (Attribute         : out Project_Node_Id;
+      First_Attribute   : Attribute_Node_Id;
+      Current_Project   : Project_Node_Id;
+      Current_Package   : Project_Node_Id);
+   --  Parse an attribute declaration.
+
+   procedure Parse_Case_Construction
+     (Case_Construction : out Project_Node_Id;
+      First_Attribute   : Attribute_Node_Id;
+      Current_Project   : Project_Node_Id;
+      Current_Package   : Project_Node_Id);
+   --  Parse a case construction
+
+   procedure Parse_Declarative_Items
+     (Declarations      : out Project_Node_Id;
+      In_Zone           : Zone;
+      First_Attribute   : Attribute_Node_Id;
+      Current_Project   : Project_Node_Id;
+      Current_Package   : Project_Node_Id);
+   --  Parse declarative items. Depending on In_Zone, some declarative
+   --  items may be forbiden.
+
+   procedure Parse_Package_Declaration
+     (Package_Declaration : out Project_Node_Id;
+      Current_Project     : Project_Node_Id);
+   --  Parse a package declaration
+
+   procedure Parse_String_Type_Declaration
+     (String_Type       : out Project_Node_Id;
+      Current_Project   : Project_Node_Id;
+      First_Attribute   : Attribute_Node_Id);
+   --  type <name> is ( <literal_string> { , <literal_string> } ) ;
+
+   procedure Parse_Variable_Declaration
+     (Variable          : out Project_Node_Id;
+      First_Attribute   : Attribute_Node_Id;
+      Current_Project   : Project_Node_Id;
+      Current_Package   : Project_Node_Id);
+   --  Parse a variable assignment
+   --  <variable_Name> := <expression>; OR
+   --  <variable_Name> : <string_type_Name> := <string_expression>;
+
+   -----------
+   -- Parse --
+   -----------
+
+   procedure Parse
+     (Declarations    : out Project_Node_Id;
+      Current_Project : Project_Node_Id;
+      Modifying       : Project_Node_Id)
+   is
+      First_Declarative_Item : Project_Node_Id := Empty_Node;
+
+   begin
+      Declarations := Default_Project_Node (Of_Kind => N_Project_Declaration);
+      Set_Location_Of (Declarations, To => Token_Ptr);
+      Set_Modified_Project_Of (Declarations, To => Modifying);
+      Parse_Declarative_Items
+        (Declarations    => First_Declarative_Item,
+         In_Zone         => In_Project,
+         First_Attribute => Prj.Attr.Attribute_First,
+         Current_Project => Current_Project,
+         Current_Package => Empty_Node);
+      Set_First_Declarative_Item_Of
+        (Declarations, To => First_Declarative_Item);
+   end Parse;
+
+   ---------------------------------
+   -- Parse_Attribute_Declaration --
+   ---------------------------------
+
+   procedure Parse_Attribute_Declaration
+     (Attribute       : out Project_Node_Id;
+      First_Attribute : Attribute_Node_Id;
+      Current_Project : Project_Node_Id;
+      Current_Package : Project_Node_Id)
+   is
+      Current_Attribute : Attribute_Node_Id := First_Attribute;
+
+   begin
+      Attribute := Default_Project_Node (Of_Kind => N_Attribute_Declaration);
+      Set_Location_Of (Attribute, To => Token_Ptr);
+
+      --  Scan past "for"
+
+      Scan;
+
+      Expect (Tok_Identifier, "identifier");
+
+      if Token = Tok_Identifier then
+         Set_Name_Of (Attribute, To => Token_Name);
+         Set_Location_Of (Attribute, To => Token_Ptr);
+         while Current_Attribute /= Empty_Attribute
+           and then
+             Attributes.Table (Current_Attribute).Name /= Token_Name
+         loop
+            Current_Attribute := Attributes.Table (Current_Attribute).Next;
+         end loop;
+
+         if Current_Attribute = Empty_Attribute then
+            Error_Msg ("undefined attribute", Token_Ptr);
+         end if;
+
+         Scan;
+      end if;
+
+      if Token = Tok_Left_Paren then
+         if Current_Attribute /= Empty_Attribute
+           and then Attributes.Table (Current_Attribute).Kind_2 = Single
+         then
+            Error_Msg ("this attribute cannot be an associative array",
+                       Location_Of (Attribute));
+         end if;
+
+         Scan;
+         Expect (Tok_String_Literal, "literal string");
+
+         if Token = Tok_String_Literal then
+            Set_Associative_Array_Index_Of (Attribute, Strval (Token_Node));
+            Scan;
+         end if;
+
+         Expect (Tok_Right_Paren, ")");
+
+         if Token = Tok_Right_Paren then
+            Scan;
+         end if;
+
+      else
+         if Current_Attribute /= Empty_Attribute
+           and then
+             Attributes.Table (Current_Attribute).Kind_2 = Associative_Array
+         then
+            Error_Msg ("this attribute need to be an associative array",
+                       Location_Of (Attribute));
+         end if;
+      end if;
+
+      if Current_Attribute /= Empty_Attribute then
+         Set_Expression_Kind_Of
+           (Attribute, To => Attributes.Table (Current_Attribute).Kind_1);
+      end if;
+
+      Expect (Tok_Use, "use");
+
+      if Token = Tok_Use then
+         Scan;
+
+         declare
+            Expression_Location : constant Source_Ptr := Token_Ptr;
+            Expression          : Project_Node_Id     := Empty_Node;
+
+         begin
+            Prj.Strt.Parse_Expression
+              (Expression      => Expression,
+               Current_Project => Current_Project,
+               Current_Package => Current_Package);
+            Set_Expression_Of (Attribute, To => Expression);
+
+            if Current_Attribute /= Empty_Attribute
+              and then Expression /= Empty_Node
+              and then Attributes.Table (Current_Attribute).Kind_1 /=
+                                          Expression_Kind_Of (Expression)
+            then
+               Error_Msg
+                 ("wrong expression kind for the attribute",
+                  Expression_Location);
+            end if;
+         end;
+      end if;
+
+   end Parse_Attribute_Declaration;
+
+   -----------------------------
+   -- Parse_Case_Construction --
+   -----------------------------
+
+   procedure Parse_Case_Construction
+     (Case_Construction : out Project_Node_Id;
+      First_Attribute   : Attribute_Node_Id;
+      Current_Project   : Project_Node_Id;
+      Current_Package   : Project_Node_Id)
+   is
+      Current_Item      : Project_Node_Id := Empty_Node;
+      Next_Item         : Project_Node_Id := Empty_Node;
+      First_Case_Item   : Boolean := True;
+
+      Variable_Location : Source_Ptr := No_Location;
+
+      String_Type       : Project_Node_Id := Empty_Node;
+
+      Case_Variable     : Project_Node_Id := Empty_Node;
+
+      First_Declarative_Item : Project_Node_Id := Empty_Node;
+
+      First_Choice      : Project_Node_Id := Empty_Node;
+
+   begin
+      Case_Construction  :=
+        Default_Project_Node (Of_Kind => N_Case_Construction);
+      Set_Location_Of (Case_Construction, To => Token_Ptr);
+
+      --  Scan past "case"
+
+      Scan;
+
+      --  Get the switch variable
+
+      Expect (Tok_Identifier, "identifier");
+
+      if Token = Tok_Identifier then
+         Variable_Location := Token_Ptr;
+         Prj.Strt.Parse_Variable_Reference
+           (Variable        => Case_Variable,
+            Current_Project => Current_Project,
+            Current_Package => Current_Package);
+         Set_Case_Variable_Reference_Of
+           (Case_Construction, To => Case_Variable);
+
+      else
+         if Token /= Tok_Is then
+            Scan;
+         end if;
+      end if;
+
+      if Case_Variable /= Empty_Node then
+         String_Type := String_Type_Of (Case_Variable);
+
+         if String_Type = Empty_Node then
+            Error_Msg ("this variable is not typed", Variable_Location);
+         end if;
+      end if;
+
+      Expect (Tok_Is, "is");
+
+      if Token = Tok_Is then
+
+         --  Scan past "is"
+
+         Scan;
+      end if;
+
+      Prj.Strt.Start_New_Case_Construction (String_Type);
+
+      When_Loop :
+
+      while Token = Tok_When loop
+
+         if First_Case_Item then
+            Current_Item := Default_Project_Node (Of_Kind => N_Case_Item);
+            Set_First_Case_Item_Of (Case_Construction, To => Current_Item);
+            First_Case_Item := False;
+
+         else
+            Next_Item := Default_Project_Node (Of_Kind => N_Case_Item);
+            Set_Next_Case_Item (Current_Item, To => Next_Item);
+            Current_Item := Next_Item;
+         end if;
+
+         Set_Location_Of (Current_Item, To => Token_Ptr);
+
+         --  Scan past "when"
+
+         Scan;
+
+         if Token = Tok_Others then
+
+            --  Scan past "others"
+
+            Scan;
+
+            Expect (Tok_Arrow, "=>");
+
+            --  Empty_Node in Field1 of a Case_Item indicates
+            --  the "when others =>" branch.
+
+            Set_First_Choice_Of (Current_Item, To => Empty_Node);
+
+            Parse_Declarative_Items
+              (Declarations    => First_Declarative_Item,
+               In_Zone         => In_Case_Construction,
+               First_Attribute => First_Attribute,
+               Current_Project => Current_Project,
+               Current_Package => Current_Package);
+
+            --  "when others =>" must be the last branch, so save the
+            --  Case_Item and exit
+
+            Set_First_Declarative_Item_Of
+              (Current_Item, To => First_Declarative_Item);
+            exit When_Loop;
+
+         else
+            Prj.Strt.Parse_Choice_List (First_Choice => First_Choice);
+            Set_First_Choice_Of (Current_Item, To => First_Choice);
+
+            Expect (Tok_Arrow, "=>");
+
+            Parse_Declarative_Items
+              (Declarations    => First_Declarative_Item,
+               In_Zone         => In_Case_Construction,
+               First_Attribute => First_Attribute,
+               Current_Project => Current_Project,
+               Current_Package => Current_Package);
+
+            Set_First_Declarative_Item_Of
+              (Current_Item, To => First_Declarative_Item);
+
+         end if;
+      end loop When_Loop;
+
+      Prj.Strt.End_Case_Construction;
+
+      Expect (Tok_End, "end case");
+
+      if Token = Tok_End then
+
+         --  Scan past "end"
+
+         Scan;
+
+         Expect (Tok_Case, "case");
+
+      end if;
+
+      --  Scan past "case"
+
+      Scan;
+
+      Expect (Tok_Semicolon, ";");
+
+   end Parse_Case_Construction;
+
+   -----------------------------
+   -- Parse_Declarative_Items --
+   -----------------------------
+
+   procedure Parse_Declarative_Items
+     (Declarations    : out Project_Node_Id;
+      In_Zone         : Zone;
+      First_Attribute : Attribute_Node_Id;
+      Current_Project : Project_Node_Id;
+      Current_Package : Project_Node_Id)
+   is
+      Current_Declarative_Item : Project_Node_Id := Empty_Node;
+      Next_Declarative_Item    : Project_Node_Id := Empty_Node;
+      Current_Declaration      : Project_Node_Id := Empty_Node;
+      Item_Location            : Source_Ptr      := No_Location;
+
+   begin
+      Declarations := Empty_Node;
+
+      loop
+         --  We are always positioned at the token that precedes
+         --  the first token of the declarative element.
+         --  Scan past it
+
+         Scan;
+
+         Item_Location := Token_Ptr;
+
+         case Token is
+            when Tok_Identifier =>
+
+               if In_Zone = In_Case_Construction then
+                  Error_Msg ("a variable cannot be declared here",
+                             Token_Ptr);
+               end if;
+
+               Parse_Variable_Declaration
+                 (Current_Declaration,
+                  First_Attribute => First_Attribute,
+                  Current_Project => Current_Project,
+                  Current_Package => Current_Package);
+
+            when Tok_For =>
+
+               Parse_Attribute_Declaration
+                 (Attribute       => Current_Declaration,
+                  First_Attribute => First_Attribute,
+                  Current_Project => Current_Project,
+                  Current_Package => Current_Package);
+
+            when Tok_Package =>
+
+               --  Package declaration
+
+               if In_Zone /= In_Project then
+                  Error_Msg ("a package cannot be declared here", Token_Ptr);
+               end if;
+
+               Parse_Package_Declaration
+                 (Package_Declaration => Current_Declaration,
+                  Current_Project     => Current_Project);
+
+            when Tok_Type =>
+
+               --  Type String Declaration
+
+               if In_Zone /= In_Project then
+                  Error_Msg ("a string type cannot be declared here",
+                             Token_Ptr);
+               end if;
+
+               Parse_String_Type_Declaration
+                 (String_Type     => Current_Declaration,
+                  Current_Project => Current_Project,
+                  First_Attribute => First_Attribute);
+
+            when Tok_Case =>
+
+               --  Case construction
+
+               Parse_Case_Construction
+                 (Case_Construction => Current_Declaration,
+                  First_Attribute   => First_Attribute,
+                  Current_Project   => Current_Project,
+                  Current_Package   => Current_Package);
+
+            when others =>
+               exit;
+
+               --  We are leaving Parse_Declarative_Items positionned
+               --  at the first token after the list of declarative items.
+               --  It could be "end" (for a project, a package declaration or
+               --  a case construction) or "when" (for a case construction)
+
+         end case;
+
+         Expect (Tok_Semicolon, "; after declarative items");
+
+         if Current_Declarative_Item = Empty_Node then
+            Current_Declarative_Item :=
+              Default_Project_Node (Of_Kind => N_Declarative_Item);
+            Declarations  := Current_Declarative_Item;
+
+         else
+            Next_Declarative_Item :=
+              Default_Project_Node (Of_Kind => N_Declarative_Item);
+            Set_Next_Declarative_Item
+              (Current_Declarative_Item, To => Next_Declarative_Item);
+            Current_Declarative_Item := Next_Declarative_Item;
+         end if;
+
+         Set_Current_Item_Node
+           (Current_Declarative_Item, To => Current_Declaration);
+         Set_Location_Of (Current_Declarative_Item, To => Item_Location);
+
+      end loop;
+
+   end Parse_Declarative_Items;
+
+   -------------------------------
+   -- Parse_Package_Declaration --
+   -------------------------------
+
+   procedure Parse_Package_Declaration
+     (Package_Declaration : out Project_Node_Id;
+      Current_Project     : Project_Node_Id)
+   is
+      First_Attribute        : Attribute_Node_Id := Empty_Attribute;
+      Current_Package        : Package_Node_Id   := Empty_Package;
+      First_Declarative_Item : Project_Node_Id   := Empty_Node;
+
+   begin
+      Package_Declaration :=
+        Default_Project_Node (Of_Kind => N_Package_Declaration);
+      Set_Location_Of (Package_Declaration, To => Token_Ptr);
+
+      --  Scan past "package"
+
+      Scan;
+
+      Expect (Tok_Identifier, "identifier");
+
+      if Token = Tok_Identifier then
+
+         Set_Name_Of (Package_Declaration, To => Token_Name);
+
+         for Index in Package_Attributes.First .. Package_Attributes.Last loop
+            if Token_Name = Package_Attributes.Table (Index).Name then
+               First_Attribute :=
+                 Package_Attributes.Table (Index).First_Attribute;
+               Current_Package := Index;
+               exit;
+            end if;
+         end loop;
+
+         if Current_Package  = Empty_Package then
+            Error_Msg ("not an allowed package name", Token_Ptr);
+
+         else
+            Set_Package_Id_Of (Package_Declaration, To => Current_Package);
+
+            declare
+               Current : Project_Node_Id := First_Package_Of (Current_Project);
+
+            begin
+               while Current /= Empty_Node
+                 and then Name_Of (Current) /= Token_Name
+               loop
+                  Current := Next_Package_In_Project (Current);
+               end loop;
+
+               if Current /= Empty_Node then
+                  Error_Msg
+                    ("package declared twice in the same project", Token_Ptr);
+
+               else
+                  --  Add the package to the project list
+
+                  Set_Next_Package_In_Project
+                    (Package_Declaration,
+                     To => First_Package_Of (Current_Project));
+                  Set_First_Package_Of
+                    (Current_Project, To => Package_Declaration);
+               end if;
+            end;
+         end if;
+
+         --  Scan past the package name
+
+         Scan;
+
+      end if;
+
+      if Token = Tok_Renames then
+         --  Scan past "renames"
+         Scan;
+
+         Expect (Tok_Identifier, "identifier");
+
+         if Token = Tok_Identifier then
+            declare
+               Project_Name : Name_Id := Token_Name;
+               Clause       : Project_Node_Id :=
+                                First_With_Clause_Of (Current_Project);
+               The_Project  : Project_Node_Id := Empty_Node;
+
+            begin
+               while Clause /= Empty_Node loop
+                  The_Project := Project_Node_Of (Clause);
+                  exit when Name_Of (The_Project) = Project_Name;
+                  Clause := Next_With_Clause_Of (Clause);
+               end loop;
+
+               if Clause = Empty_Node then
+                  Error_Msg ("not an imported project", Token_Ptr);
+               else
+                  Set_Project_Of_Renamed_Package_Of
+                    (Package_Declaration, To => The_Project);
+               end if;
+            end;
+
+            Scan;
+            Expect (Tok_Dot, ".");
+
+            if Token = Tok_Dot then
+               Scan;
+               Expect (Tok_Identifier, "identifier");
+
+               if Token = Tok_Identifier then
+                  if Name_Of (Package_Declaration) /= Token_Name then
+                     Error_Msg ("not the same package name", Token_Ptr);
+                  elsif
+                    Project_Of_Renamed_Package_Of (Package_Declaration)
+                                                              /= Empty_Node
+                  then
+                     declare
+                        Current : Project_Node_Id :=
+                                    First_Package_Of
+                                      (Project_Of_Renamed_Package_Of
+                                         (Package_Declaration));
+
+                     begin
+                        while Current /= Empty_Node
+                          and then Name_Of (Current) /= Token_Name
+                        loop
+                           Current := Next_Package_In_Project (Current);
+                        end loop;
+
+                        if Current = Empty_Node then
+                           Error_Msg
+                             ("not a package declared by the project",
+                              Token_Ptr);
+                        end if;
+                     end;
+                  end if;
+
+                  Scan;
+               end if;
+            end if;
+         end if;
+
+         Expect (Tok_Semicolon, ";");
+
+      elsif Token = Tok_Is then
+
+         Parse_Declarative_Items
+           (Declarations    => First_Declarative_Item,
+            In_Zone         => In_Package,
+            First_Attribute => First_Attribute,
+            Current_Project => Current_Project,
+            Current_Package => Package_Declaration);
+
+         Set_First_Declarative_Item_Of
+           (Package_Declaration, To => First_Declarative_Item);
+
+         Expect (Tok_End, "end");
+
+         if Token = Tok_End then
+
+            --  Scan past "end"
+
+            Scan;
+         end if;
+
+         --  We should have the name of the package after "end"
+
+         Expect (Tok_Identifier, "identifier");
+
+         if Token = Tok_Identifier
+           and then Name_Of (Package_Declaration) /= No_Name
+           and then Token_Name /= Name_Of (Package_Declaration)
+         then
+            Error_Msg_Name_1 := Name_Of (Package_Declaration);
+            Error_Msg ("expected {", Token_Ptr);
+         end if;
+
+         if Token /= Tok_Semicolon then
+
+            --  Scan past the package name
+
+            Scan;
+         end if;
+
+         Expect (Tok_Semicolon, ";");
+
+      else
+         Error_Msg ("expected ""is"" or ""renames""", Token_Ptr);
+      end if;
+
+   end Parse_Package_Declaration;
+
+   -----------------------------------
+   -- Parse_String_Type_Declaration --
+   -----------------------------------
+
+   procedure Parse_String_Type_Declaration
+     (String_Type     : out Project_Node_Id;
+      Current_Project : Project_Node_Id;
+      First_Attribute : Attribute_Node_Id)
+   is
+      Current      : Project_Node_Id := Empty_Node;
+      First_String : Project_Node_Id := Empty_Node;
+
+   begin
+      String_Type :=
+        Default_Project_Node (Of_Kind => N_String_Type_Declaration);
+
+      Set_Location_Of (String_Type, To => Token_Ptr);
+
+      --  Scan past "type"
+
+      Scan;
+
+      Expect (Tok_Identifier, "identifier");
+
+      if Token = Tok_Identifier then
+         Set_Name_Of (String_Type, To => Token_Name);
+
+         Current := First_String_Type_Of (Current_Project);
+         while Current /= Empty_Node
+           and then
+           Name_Of (Current) /= Token_Name
+         loop
+            Current := Next_String_Type (Current);
+         end loop;
+
+         if Current /= Empty_Node then
+            Error_Msg ("duplicate string type name", Token_Ptr);
+         else
+            Current := First_Variable_Of (Current_Project);
+            while Current /= Empty_Node
+              and then Name_Of (Current) /= Token_Name
+            loop
+               Current := Next_Variable (Current);
+            end loop;
+
+            if Current /= Empty_Node then
+               Error_Msg ("already a variable name", Token_Ptr);
+            else
+               Set_Next_String_Type
+                 (String_Type, To => First_String_Type_Of (Current_Project));
+               Set_First_String_Type_Of (Current_Project, To => String_Type);
+            end if;
+         end if;
+
+         --  Scan past the name
+
+         Scan;
+      end if;
+
+      Expect (Tok_Is, "is");
+
+      if Token = Tok_Is then
+         Scan;
+      end if;
+
+      Expect (Tok_Left_Paren, "(");
+
+      if Token = Tok_Left_Paren then
+         Scan;
+      end if;
+
+      Prj.Strt.Parse_String_Type_List (First_String => First_String);
+      Set_First_Literal_String (String_Type, To => First_String);
+
+      Expect (Tok_Right_Paren, ")");
+
+      if Token = Tok_Right_Paren then
+         Scan;
+      end if;
+
+   end Parse_String_Type_Declaration;
+
+   --------------------------------
+   -- Parse_Variable_Declaration --
+   --------------------------------
+
+   procedure Parse_Variable_Declaration
+     (Variable        : out Project_Node_Id;
+      First_Attribute : Attribute_Node_Id;
+      Current_Project : Project_Node_Id;
+      Current_Package : Project_Node_Id)
+   is
+      Expression_Location      : Source_Ptr;
+      String_Type_Name         : Name_Id := No_Name;
+      Project_String_Type_Name : Name_Id := No_Name;
+      Type_Location            : Source_Ptr := No_Location;
+      Project_Location         : Source_Ptr := No_Location;
+      Expression               : Project_Node_Id := Empty_Node;
+      Variable_Name            : constant Name_Id := Token_Name;
+
+   begin
+      Variable :=
+        Default_Project_Node (Of_Kind => N_Variable_Declaration);
+      Set_Name_Of (Variable, To => Variable_Name);
+      Set_Location_Of (Variable, To => Token_Ptr);
+
+      --  Scan past the variable name
+
+      Scan;
+
+      if Token = Tok_Colon then
+
+         --  Typed string variable declaration
+
+         Scan;
+         Set_Kind_Of (Variable, N_Typed_Variable_Declaration);
+         Expect (Tok_Identifier, "identifier");
+
+         if Token = Tok_Identifier then
+            String_Type_Name := Token_Name;
+            Type_Location := Token_Ptr;
+            Scan;
+
+            if Token = Tok_Dot then
+               Project_String_Type_Name := String_Type_Name;
+               Project_Location := Type_Location;
+
+               --  Scan past the dot
+
+               Scan;
+               Expect (Tok_Identifier, "identifier");
+
+               if Token = Tok_Identifier then
+                  String_Type_Name := Token_Name;
+                  Type_Location := Token_Ptr;
+                  Scan;
+               else
+                  String_Type_Name := No_Name;
+               end if;
+            end if;
+
+            if String_Type_Name /= No_Name then
+               declare
+                  Current : Project_Node_Id :=
+                              First_String_Type_Of (Current_Project);
+
+               begin
+                  if Project_String_Type_Name /= No_Name then
+                     declare
+                        The_Project_Name_And_Node : constant
+                          Tree_Private_Part.Project_Name_And_Node :=
+                          Tree_Private_Part.Projects_Htable.Get
+                                                    (Project_String_Type_Name);
+
+                        use Tree_Private_Part;
+
+                     begin
+                        if The_Project_Name_And_Node =
+                          Tree_Private_Part.No_Project_Name_And_Node
+                        then
+                           Error_Msg ("unknown project", Project_Location);
+                           Current := Empty_Node;
+                        else
+                           Current :=
+                             First_String_Type_Of
+                                         (The_Project_Name_And_Node.Node);
+                        end if;
+                     end;
+                  end if;
+
+                  while Current /= Empty_Node
+                    and then Name_Of (Current) /= String_Type_Name
+                  loop
+                     Current := Next_String_Type (Current);
+                  end loop;
+
+                  if Current = Empty_Node then
+                     Error_Msg ("unknown string type", Type_Location);
+                  else
+                     Set_String_Type_Of
+                       (Variable, To => Current);
+                  end if;
+               end;
+            end if;
+         end if;
+      end if;
+
+      Expect (Tok_Colon_Equal, ":=");
+
+      if Token = Tok_Colon_Equal then
+         Scan;
+      end if;
+
+      --  Get the single string or string list value
+
+      Expression_Location := Token_Ptr;
+
+      Prj.Strt.Parse_Expression
+        (Expression      => Expression,
+         Current_Project => Current_Project,
+         Current_Package => Current_Package);
+      Set_Expression_Of (Variable, To => Expression);
+
+      if Expression /= Empty_Node then
+         Set_Expression_Kind_Of
+           (Variable, To => Expression_Kind_Of (Expression));
+      end if;
+
+      declare
+         The_Variable : Project_Node_Id := Empty_Node;
+
+      begin
+         if Current_Package /= Empty_Node then
+            The_Variable :=  First_Variable_Of (Current_Package);
+         elsif Current_Project /= Empty_Node then
+            The_Variable :=  First_Variable_Of (Current_Project);
+         end if;
+
+         while The_Variable /= Empty_Node
+           and then Name_Of (The_Variable) /= Variable_Name
+         loop
+            The_Variable := Next_Variable (The_Variable);
+         end loop;
+
+         if The_Variable = Empty_Node then
+            if Current_Package /= Empty_Node then
+               Set_Next_Variable
+                 (Variable, To => First_Variable_Of (Current_Package));
+               Set_First_Variable_Of (Current_Package, To => Variable);
+
+            elsif Current_Project /= Empty_Node then
+               Set_Next_Variable
+                 (Variable, To => First_Variable_Of (Current_Project));
+               Set_First_Variable_Of (Current_Project, To => Variable);
+            end if;
+
+         else
+            if Expression_Kind_Of (Variable) /= Undefined then
+               if Expression_Kind_Of (The_Variable) = Undefined then
+                  Set_Expression_Kind_Of
+                    (The_Variable, To => Expression_Kind_Of (Variable));
+
+               else
+                  if Expression_Kind_Of (The_Variable) /=
+                                                 Expression_Kind_Of (Variable)
+                  then
+                     Error_Msg ("wrong expression kind for the variable",
+                                Expression_Location);
+                  end if;
+               end if;
+            end if;
+         end if;
+      end;
+
+   end Parse_Variable_Declaration;
+
+end Prj.Dect;
diff --git a/gcc/ada/prj-dect.ads b/gcc/ada/prj-dect.ads
new file mode 100644 (file)
index 0000000..3072c57
--- /dev/null
@@ -0,0 +1,41 @@
+------------------------------------------------------------------------------
+--                                                                          --
+--                         GNAT COMPILER COMPONENTS                         --
+--                                                                          --
+--                              P R J . D E C T                             --
+--                                                                          --
+--                                 S p e c                                  --
+--                                                                          --
+--                            $Revision: 1.2 $
+--                                                                          --
+--             Copyright (C) 2000 Free Software Foundation, Inc.            --
+--                                                                          --
+-- GNAT is free software;  you can  redistribute it  and/or modify it under --
+-- terms of the  GNU General Public License as published  by the Free Soft- --
+-- ware  Foundation;  either version 2,  or (at your option) any later ver- --
+-- sion.  GNAT is distributed in the hope that it will be useful, but WITH- --
+-- OUT 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  distributed with GNAT;  see file COPYING.  If not, write --
+-- to  the Free Software Foundation,  59 Temple Place - Suite 330,  Boston, --
+-- MA 02111-1307, USA.                                                      --
+--                                                                          --
+-- GNAT was originally developed  by the GNAT team at  New York University. --
+-- It is now maintained by Ada Core Technologies Inc (http://www.gnat.com). --
+--                                                                          --
+------------------------------------------------------------------------------
+--
+--  Parse a list of declarative items in a project file.
+
+with Prj.Tree;
+
+private package Prj.Dect is
+
+   procedure Parse
+     (Declarations    : out Prj.Tree.Project_Node_Id;
+      Current_Project : Prj.Tree.Project_Node_Id;
+      Modifying       : Prj.Tree.Project_Node_Id);
+   --  Parse project declarative items.
+
+end Prj.Dect;
diff --git a/gcc/ada/prj-env.adb b/gcc/ada/prj-env.adb
new file mode 100644 (file)
index 0000000..171a2d0
--- /dev/null
@@ -0,0 +1,1471 @@
+------------------------------------------------------------------------------
+--                                                                          --
+--                         GNAT COMPILER COMPONENTS                         --
+--                                                                          --
+--                              P R J . E N V                               --
+--                                                                          --
+--                                 B o d y                                  --
+--                                                                          --
+--                            $Revision: 1.17 $
+--                                                                          --
+--             Copyright (C) 2001 Free Software Foundation, Inc.            --
+--                                                                          --
+-- GNAT is free software;  you can  redistribute it  and/or modify it under --
+-- terms of the  GNU General Public License as published  by the Free Soft- --
+-- ware  Foundation;  either version 2,  or (at your option) any later ver- --
+-- sion.  GNAT is distributed in the hope that it will be useful, but WITH- --
+-- OUT 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  distributed with GNAT;  see file COPYING.  If not, write --
+-- to  the Free Software Foundation,  59 Temple Place - Suite 330,  Boston, --
+-- MA 02111-1307, USA.                                                      --
+--                                                                          --
+-- GNAT was originally developed  by the GNAT team at  New York University. --
+-- It is now maintained by Ada Core Technologies Inc (http://www.gnat.com). --
+--                                                                          --
+------------------------------------------------------------------------------
+
+with GNAT.OS_Lib; use GNAT.OS_Lib;
+with Namet;       use Namet;
+with Opt;
+with Osint;       use Osint;
+with Output;      use Output;
+with Prj.Com;     use Prj.Com;
+with Prj.Util;
+with Snames;      use Snames;
+with Stringt;     use Stringt;
+with Table;
+
+package body Prj.Env is
+
+   type Naming_Id is new Nat;
+   No_Naming : constant Naming_Id := 0;
+
+   Ada_Path_Buffer : String_Access := new String (1 .. 1_000);
+   --  A buffer where values for ADA_INCLUDE_PATH
+   --  and ADA_OBJECTS_PATH are stored.
+
+   Ada_Path_Length : Natural := 0;
+   --  Index of the last valid character in Ada_Path_Buffer.
+
+   package Namings is new Table.Table (
+     Table_Component_Type => Naming_Data,
+     Table_Index_Type     => Naming_Id,
+     Table_Low_Bound      => 1,
+     Table_Initial        => 5,
+     Table_Increment      => 100,
+     Table_Name           => "Prj.Env.Namings");
+
+   Default_Naming : constant Naming_Id := Namings.First;
+
+   Global_Configuration_Pragmas : Name_Id;
+   Local_Configuration_Pragmas  : Name_Id;
+
+   -----------------------
+   -- Local Subprograms --
+   -----------------------
+
+   function Body_Path_Name_Of (Unit : Unit_Id) return String;
+   --  Returns the path name of the body of a unit.
+   --  Compute it first, if necessary.
+
+   function Spec_Path_Name_Of (Unit : Unit_Id) return String;
+   --  Returns the path name of the spec of a unit.
+   --  Compute it first, if necessary.
+
+   procedure Add_To_Path (Path : String);
+   --  Add Path to global variable Ada_Path_Buffer
+   --  Increment Ada_Path_Length
+
+   ----------------------
+   -- Ada_Include_Path --
+   ----------------------
+
+   function Ada_Include_Path (Project : Project_Id) return String_Access is
+
+      procedure Add (Project : Project_Id);
+      --  Add all the source directories of a project to the path,
+      --  only if this project has not been visited.
+      --  Call itself recursively for projects being modified,
+      --  and imported projects.
+      --  Add the project to the list Seen if this is the first time
+      --  we call Add for this project.
+
+      ---------
+      -- Add --
+      ---------
+
+      procedure Add (Project : Project_Id) is
+      begin
+         --  If Seen is empty, then the project cannot have been
+         --  visited.
+
+         if not Projects.Table (Project).Seen then
+            Projects.Table (Project).Seen := True;
+
+            declare
+               Data : Project_Data := Projects.Table (Project);
+               List : Project_List := Data.Imported_Projects;
+
+               Current : String_List_Id := Data.Source_Dirs;
+               Source_Dir : String_Element;
+
+            begin
+               --  Add to path all source directories of this project
+
+               while Current /= Nil_String loop
+                  if Ada_Path_Length > 0 then
+                     Add_To_Path (Path => (1 => Path_Separator));
+                  end if;
+
+                  Source_Dir := String_Elements.Table (Current);
+                  String_To_Name_Buffer (Source_Dir.Value);
+
+                  declare
+                     New_Path : constant String :=
+                       Name_Buffer (1 .. Name_Len);
+                  begin
+                     Add_To_Path (New_Path);
+                  end;
+
+                  Current := Source_Dir.Next;
+               end loop;
+
+               --  Call Add to the project being modified, if any
+
+               if Data.Modifies /= No_Project then
+                  Add (Data.Modifies);
+               end if;
+
+               --  Call Add for each imported project, if any
+
+               while List /= Empty_Project_List loop
+                  Add (Project_Lists.Table (List).Project);
+                  List := Project_Lists.Table (List).Next;
+               end loop;
+            end;
+         end if;
+
+      end Add;
+
+   --  Start of processing for Ada_Include_Path
+
+   begin
+      --  If it is the first time we call this function for
+      --  this project, compute the source path
+
+      if Projects.Table (Project).Include_Path = null then
+         Ada_Path_Length := 0;
+
+         for Index in 1 .. Projects.Last loop
+            Projects.Table (Index).Seen := False;
+         end loop;
+
+         Add (Project);
+         Projects.Table (Project).Include_Path :=
+           new String'(Ada_Path_Buffer (1 .. Ada_Path_Length));
+      end if;
+
+      return Projects.Table (Project).Include_Path;
+   end Ada_Include_Path;
+
+   ----------------------
+   -- Ada_Objects_Path --
+   ----------------------
+
+   function Ada_Objects_Path
+     (Project             : Project_Id;
+      Including_Libraries : Boolean := True)
+     return String_Access is
+
+      procedure Add (Project : Project_Id);
+      --  Add all the object directory of a project to the path,
+      --  only if this project has not been visited.
+      --  Call itself recursively for projects being modified,
+      --  and imported projects.
+      --  Add the project to the list Seen if this is the first time
+      --  we call Add for this project.
+
+      ---------
+      -- Add --
+      ---------
+
+      procedure Add (Project : Project_Id) is
+      begin
+
+         --  If this project has not been seen yet
+
+         if not Projects.Table (Project).Seen then
+            Projects.Table (Project).Seen := True;
+
+            declare
+               Data : Project_Data := Projects.Table (Project);
+               List : Project_List := Data.Imported_Projects;
+
+            begin
+               --  Add to path the object directory of this project
+               --  except if we don't include library project and
+               --  this is a library project.
+
+               if (Data.Library and then Including_Libraries)
+                 or else
+                 (Data.Object_Directory /= No_Name
+                   and then
+                   (not Including_Libraries or else not Data.Library))
+               then
+                  if Ada_Path_Length > 0 then
+                     Add_To_Path (Path => (1 => Path_Separator));
+                  end if;
+
+                  --  For a library project, att the library directory
+
+                  if Data.Library then
+                     declare
+                        New_Path : constant String :=
+                          Get_Name_String (Data.Library_Dir);
+                     begin
+                        Add_To_Path (New_Path);
+                     end;
+                  else
+
+                     --  For a non library project, add the object directory
+                     declare
+                        New_Path : constant String :=
+                          Get_Name_String (Data.Object_Directory);
+                     begin
+                        Add_To_Path (New_Path);
+                     end;
+                  end if;
+               end if;
+
+               --  Call Add to the project being modified, if any
+
+               if Data.Modifies /= No_Project then
+                  Add (Data.Modifies);
+               end if;
+
+               --  Call Add for each imported project, if any
+
+               while List /= Empty_Project_List loop
+                  Add (Project_Lists.Table (List).Project);
+                  List := Project_Lists.Table (List).Next;
+               end loop;
+            end;
+
+         end if;
+      end Add;
+
+   --  Start of processing for Ada_Objects_Path
+
+   begin
+      --  If it is the first time we call this function for
+      --  this project, compute the objects path
+
+      if Projects.Table (Project).Objects_Path = null then
+         Ada_Path_Length := 0;
+
+         for Index in 1 .. Projects.Last loop
+            Projects.Table (Index).Seen := False;
+         end loop;
+
+         Add (Project);
+         Projects.Table (Project).Objects_Path :=
+           new String'(Ada_Path_Buffer (1 .. Ada_Path_Length));
+      end if;
+
+      return Projects.Table (Project).Objects_Path;
+   end Ada_Objects_Path;
+
+   -----------------
+   -- Add_To_Path --
+   -----------------
+
+   procedure Add_To_Path (Path : String) is
+   begin
+      --  If Ada_Path_Buffer is too small, double it
+
+      if Ada_Path_Length + Path'Length > Ada_Path_Buffer'Last then
+         declare
+            New_Ada_Path_Buffer : constant String_Access :=
+                                    new String
+                                      (1 .. Ada_Path_Buffer'Last +
+                                                 Ada_Path_Buffer'Last);
+
+         begin
+            New_Ada_Path_Buffer (1 .. Ada_Path_Length) :=
+              Ada_Path_Buffer (1 .. Ada_Path_Length);
+            Ada_Path_Buffer := New_Ada_Path_Buffer;
+         end;
+      end if;
+
+      Ada_Path_Buffer
+        (Ada_Path_Length + 1 .. Ada_Path_Length + Path'Length) := Path;
+      Ada_Path_Length := Ada_Path_Length + Path'Length;
+   end Add_To_Path;
+
+   -----------------------
+   -- Body_Path_Name_Of --
+   -----------------------
+
+   function Body_Path_Name_Of (Unit : Unit_Id) return String is
+      Data : Unit_Data := Units.Table (Unit);
+
+   begin
+      --  If we don't know the path name of the body of this unit,
+      --  we compute it, and we store it.
+
+      if Data.File_Names (Body_Part).Path = No_Name then
+         declare
+            Current_Source : String_List_Id :=
+              Projects.Table (Data.File_Names (Body_Part).Project).Sources;
+            Path : GNAT.OS_Lib.String_Access;
+
+         begin
+            --  By default, put the file name
+
+            Data.File_Names (Body_Part).Path :=
+              Data.File_Names (Body_Part).Name;
+
+            --  For each source directory
+
+            while Current_Source /= Nil_String loop
+               String_To_Name_Buffer
+                 (String_Elements.Table (Current_Source).Value);
+               Path :=
+                 Locate_Regular_File
+                 (Namet.Get_Name_String
+                  (Data.File_Names (Body_Part).Name),
+                  Name_Buffer (1 .. Name_Len));
+
+               --  If the file is in this directory,
+               --  then we store the path, and we are done.
+
+               if Path /= null then
+                  Name_Len := Path'Length;
+                  Name_Buffer (1 .. Name_Len) := Path.all;
+                  Data.File_Names (Body_Part).Path := Name_Enter;
+                  exit;
+
+               else
+                  Current_Source :=
+                    String_Elements.Table (Current_Source).Next;
+               end if;
+            end loop;
+
+            Units.Table (Unit) := Data;
+         end;
+      end if;
+
+      --  Returned the value stored
+
+      return Namet.Get_Name_String (Data.File_Names (Body_Part).Path);
+   end Body_Path_Name_Of;
+
+   --------------------------------
+   -- Create_Config_Pragmas_File --
+   --------------------------------
+
+   procedure Create_Config_Pragmas_File
+     (For_Project  : Project_Id;
+      Main_Project : Project_Id)
+   is
+      File_Name : Temp_File_Name;
+      File      : File_Descriptor := Invalid_FD;
+
+      The_Packages : Package_Id;
+      Gnatmake     : Prj.Package_Id;
+      Compiler     : Prj.Package_Id;
+
+      Current_Unit : Unit_Id := Units.First;
+
+      First_Project : Project_List := Empty_Project_List;
+
+      Current_Project : Project_List;
+      Current_Naming  : Naming_Id;
+
+      Global_Attribute : Variable_Value := Nil_Variable_Value;
+      Local_Attribute  : Variable_Value := Nil_Variable_Value;
+
+      Global_Attribute_Present : Boolean := False;
+      Local_Attribute_Present  : Boolean := False;
+
+      procedure Check (Project : Project_Id);
+
+      procedure Check_Temp_File;
+      --  Check that a temporary file has been opened.
+      --  If not, create one, and put its name in the project data,
+      --  with the indication that it is a temporary file.
+
+      procedure Copy_File (Name : String_Id);
+      --  Copy a configuration pragmas file into the temp file.
+
+      procedure Put
+        (Unit_Name : Name_Id;
+         File_Name : Name_Id;
+         Unit_Kind : Spec_Or_Body);
+      --  Put an SFN pragma in the temporary file.
+
+      procedure Put (File : File_Descriptor; S : String);
+
+      procedure Put_Line (File : File_Descriptor; S : String);
+
+      -----------
+      -- Check --
+      -----------
+
+      procedure Check (Project : Project_Id) is
+         Data : constant Project_Data := Projects.Table (Project);
+
+      begin
+         if Current_Verbosity = High then
+            Write_Str ("Checking project file """);
+            Write_Str (Namet.Get_Name_String (Data.Name));
+            Write_Str (""".");
+            Write_Eol;
+         end if;
+
+         --  Is this project in the list of the visited project?
+
+         Current_Project := First_Project;
+         while Current_Project /= Empty_Project_List
+           and then Project_Lists.Table (Current_Project).Project /= Project
+         loop
+            Current_Project := Project_Lists.Table (Current_Project).Next;
+         end loop;
+
+         --  If it is not, put it in the list, and visit it
+
+         if Current_Project = Empty_Project_List then
+            Project_Lists.Increment_Last;
+            Project_Lists.Table (Project_Lists.Last) :=
+              (Project => Project, Next => First_Project);
+            First_Project := Project_Lists.Last;
+
+            --  Is the naming scheme of this project one that we know?
+
+            Current_Naming := Default_Naming;
+            while Current_Naming <= Namings.Last and then
+              not Same_Naming_Scheme
+              (Left => Namings.Table (Current_Naming),
+               Right => Data.Naming) loop
+               Current_Naming := Current_Naming + 1;
+            end loop;
+
+            --  If we don't know it, add it
+
+            if Current_Naming > Namings.Last then
+               Namings.Increment_Last;
+               Namings.Table (Namings.Last) := Data.Naming;
+
+               --  We need a temporary file to be created
+
+               Check_Temp_File;
+
+               --  Put the SFN pragmas for the naming scheme
+
+               --  Spec
+
+               Put_Line
+                 (File, "pragma Source_File_Name");
+               Put_Line
+                 (File, "  (Spec_File_Name  => ""*" &
+                  Namet.Get_Name_String (Data.Naming.Specification_Append) &
+                  """,");
+               Put_Line
+                 (File, "   Casing          => " &
+                  Image (Data.Naming.Casing) & ",");
+               Put_Line
+                 (File, "   Dot_Replacement => """ &
+                 Namet.Get_Name_String (Data.Naming.Dot_Replacement) &
+                  """);");
+
+               --  and body
+
+               Put_Line
+                 (File, "pragma Source_File_Name");
+               Put_Line
+                 (File, "  (Body_File_Name  => ""*" &
+                  Namet.Get_Name_String (Data.Naming.Body_Append) &
+                  """,");
+               Put_Line
+                 (File, "   Casing          => " &
+                  Image (Data.Naming.Casing) & ",");
+               Put_Line
+                 (File, "   Dot_Replacement => """ &
+                  Namet.Get_Name_String (Data.Naming.Dot_Replacement) &
+                  """);");
+
+               --  and maybe separate
+
+               if Data.Naming.Body_Append /= Data.Naming.Separate_Append then
+                  Put_Line
+                    (File, "pragma Source_File_Name");
+                  Put_Line
+                    (File, "  (Subunit_File_Name  => ""*" &
+                     Namet.Get_Name_String (Data.Naming.Separate_Append) &
+                     """,");
+                  Put_Line
+                    (File, "   Casing          => " &
+                     Image (Data.Naming.Casing) &
+                     ",");
+                  Put_Line
+                    (File, "   Dot_Replacement => """ &
+                     Namet.Get_Name_String (Data.Naming.Dot_Replacement) &
+                     """);");
+               end if;
+            end if;
+
+            if Data.Modifies /= No_Project then
+               Check (Data.Modifies);
+            end if;
+
+            declare
+               Current : Project_List := Data.Imported_Projects;
+
+            begin
+               while Current /= Empty_Project_List loop
+                  Check (Project_Lists.Table (Current).Project);
+                  Current := Project_Lists.Table (Current).Next;
+               end loop;
+            end;
+         end if;
+      end Check;
+
+      ---------------------
+      -- Check_Temp_File --
+      ---------------------
+
+      procedure Check_Temp_File is
+      begin
+         if File = Invalid_FD then
+            GNAT.OS_Lib.Create_Temp_File (File, Name => File_Name);
+            if File = Invalid_FD then
+               Osint.Fail
+                 ("unable to create temporary configuration pragmas file");
+            elsif Opt.Verbose_Mode then
+               Write_Str ("Creating temp file """);
+               Write_Str (File_Name);
+               Write_Line ("""");
+            end if;
+         end if;
+      end Check_Temp_File;
+
+      ---------------
+      -- Copy_File --
+      ---------------
+
+      procedure Copy_File (Name : in String_Id) is
+         Input         : File_Descriptor;
+         Buffer        : String (1 .. 1_000);
+         Input_Length  : Integer;
+         Output_Length : Integer;
+
+      begin
+         Check_Temp_File;
+         String_To_Name_Buffer (Name);
+
+         if Opt.Verbose_Mode then
+            Write_Str ("Copying config pragmas file """);
+            Write_Str (Name_Buffer (1 .. Name_Len));
+            Write_Line (""" into temp file");
+         end if;
+
+         declare
+            Name : constant String :=
+              Name_Buffer (1 .. Name_Len)  & ASCII.NUL;
+         begin
+            Input := Open_Read (Name'Address, Binary);
+         end;
+
+         if Input = Invalid_FD then
+            Osint.Fail
+              ("cannot open configuration pragmas file " &
+               Name_Buffer (1 .. Name_Len));
+         end if;
+
+         loop
+            Input_Length := Read (Input, Buffer'Address, Buffer'Length);
+            Output_Length := Write (File, Buffer'Address, Input_Length);
+
+            if Output_Length /= Input_Length then
+               Osint.Fail ("disk full");
+            end if;
+
+            exit when Input_Length < Buffer'Length;
+         end loop;
+
+         Close (Input);
+
+      end Copy_File;
+
+      ---------
+      -- Put --
+      ---------
+
+      procedure Put
+        (Unit_Name : Name_Id;
+         File_Name : Name_Id;
+         Unit_Kind : Spec_Or_Body)
+      is
+      begin
+         --  A temporary file needs to be open
+
+         Check_Temp_File;
+
+         --  Put the pragma SFN for the unit kind (spec or body)
+
+         Put (File, "pragma Source_File_Name (");
+         Put (File, Namet.Get_Name_String (Unit_Name));
+
+         if Unit_Kind = Specification then
+            Put (File, ", Spec_File_Name => """);
+         else
+            Put (File, ", Body_File_Name => """);
+         end if;
+
+         Put (File, Namet.Get_Name_String (File_Name));
+         Put_Line (File, """);");
+      end Put;
+
+      procedure Put (File : File_Descriptor; S : String) is
+         Last : Natural;
+
+      begin
+         Last := Write (File, S (S'First)'Address, S'Length);
+
+         if Last /= S'Length then
+            Osint.Fail ("Disk full");
+         end if;
+
+         if Current_Verbosity = High then
+            Write_Str (S);
+         end if;
+      end Put;
+
+      --------------
+      -- Put_Line --
+      --------------
+
+      procedure Put_Line (File : File_Descriptor; S : String) is
+         S0   : String (1 .. S'Length + 1);
+         Last : Natural;
+
+      begin
+         --  Add an ASCII.LF to the string. As this gnat.adc
+         --  is supposed to be used only by the compiler, we don't
+         --  care about the characters for the end of line.
+         --  The truth is we could have put a space, but it is
+         --  more convenient to be able to read gnat.adc during
+         --  development. And the development was done under UNIX.
+         --  Hence the ASCII.LF.
+
+         S0 (1 .. S'Length) := S;
+         S0 (S0'Last) := ASCII.LF;
+         Last := Write (File, S0'Address, S0'Length);
+
+         if Last /= S'Length + 1 then
+            Osint.Fail ("Disk full");
+         end if;
+
+         if Current_Verbosity = High then
+            Write_Line (S);
+         end if;
+      end Put_Line;
+
+   --  Start of processing for Create_Config_Pragmas_File
+
+   begin
+
+      if not Projects.Table (For_Project).Config_Checked then
+
+         --  Remove any memory of processed naming schemes, if any
+
+         Namings.Set_Last (Default_Naming);
+
+         --  Check the naming schemes
+
+         Check (For_Project);
+
+         --  Visit all the units and process those that need an SFN pragma
+
+         while Current_Unit <= Units.Last loop
+            declare
+               Unit : constant Unit_Data :=
+                 Units.Table (Current_Unit);
+
+            begin
+               if Unit.File_Names (Specification).Needs_Pragma then
+                  Put (Unit.Name,
+                       Unit.File_Names (Specification).Name,
+                       Specification);
+               end if;
+
+               if Unit.File_Names (Body_Part).Needs_Pragma then
+                  Put (Unit.Name,
+                       Unit.File_Names (Body_Part).Name,
+                       Body_Part);
+               end if;
+
+               Current_Unit := Current_Unit + 1;
+            end;
+         end loop;
+
+         The_Packages := Projects.Table (Main_Project).Decl.Packages;
+         Gnatmake :=
+           Prj.Util.Value_Of
+           (Name        => Name_Gnatmake,
+            In_Packages => The_Packages);
+
+         if Gnatmake /= No_Package then
+            Global_Attribute := Prj.Util.Value_Of
+              (Variable_Name => Global_Configuration_Pragmas,
+               In_Variables => Packages.Table (Gnatmake).Decl.Attributes);
+            Global_Attribute_Present :=
+              Global_Attribute /= Nil_Variable_Value
+              and then String_Length (Global_Attribute.Value) > 0;
+         end if;
+
+         The_Packages := Projects.Table (For_Project).Decl.Packages;
+         Compiler :=
+           Prj.Util.Value_Of
+           (Name        => Name_Compiler,
+            In_Packages => The_Packages);
+
+         if Compiler /= No_Package then
+            Local_Attribute := Prj.Util.Value_Of
+              (Variable_Name => Local_Configuration_Pragmas,
+               In_Variables => Packages.Table (Compiler).Decl.Attributes);
+            Local_Attribute_Present :=
+              Local_Attribute /= Nil_Variable_Value
+              and then String_Length (Local_Attribute.Value) > 0;
+         end if;
+
+         if Global_Attribute_Present then
+
+            if File /= Invalid_FD
+              or else Local_Attribute_Present
+            then
+               Copy_File (Global_Attribute.Value);
+            else
+               String_To_Name_Buffer (Global_Attribute.Value);
+               Projects.Table (For_Project).Config_File_Name := Name_Find;
+            end if;
+         end if;
+
+         if Local_Attribute_Present then
+
+            if File /= Invalid_FD then
+               Copy_File (Local_Attribute.Value);
+
+            else
+               String_To_Name_Buffer (Local_Attribute.Value);
+               Projects.Table (For_Project).Config_File_Name := Name_Find;
+            end if;
+
+         end if;
+
+         if File /= Invalid_FD then
+            GNAT.OS_Lib.Close (File);
+
+            if Opt.Verbose_Mode then
+               Write_Str ("Closing configuration file """);
+               Write_Str (File_Name);
+               Write_Line ("""");
+            end if;
+
+            Name_Len := File_Name'Length;
+            Name_Buffer (1 .. Name_Len) := File_Name;
+            Projects.Table (For_Project).Config_File_Name := Name_Find;
+            Projects.Table (For_Project).Config_File_Temp := True;
+         end if;
+
+         Projects.Table (For_Project).Config_Checked := True;
+
+      end if;
+
+   end Create_Config_Pragmas_File;
+
+   ------------------------------------
+   -- File_Name_Of_Library_Unit_Body --
+   ------------------------------------
+
+   function File_Name_Of_Library_Unit_Body
+     (Name    : String;
+      Project : Project_Id)
+      return    String
+   is
+      Data          : constant Project_Data := Projects.Table (Project);
+      Original_Name : String := Name;
+
+      Extended_Spec_Name : String :=
+                             Name & Namet.Get_Name_String
+                                      (Data.Naming.Specification_Append);
+      Extended_Body_Name : String :=
+                             Name & Namet.Get_Name_String
+                                      (Data.Naming.Body_Append);
+
+      Unit : Unit_Data;
+
+      The_Original_Name : Name_Id;
+      The_Spec_Name     : Name_Id;
+      The_Body_Name     : Name_Id;
+
+   begin
+      Canonical_Case_File_Name (Original_Name);
+      Name_Len := Original_Name'Length;
+      Name_Buffer (1 .. Name_Len) := Original_Name;
+      The_Original_Name := Name_Find;
+
+      Canonical_Case_File_Name (Extended_Spec_Name);
+      Name_Len := Extended_Spec_Name'Length;
+      Name_Buffer (1 .. Name_Len) := Extended_Spec_Name;
+      The_Spec_Name := Name_Find;
+
+      Canonical_Case_File_Name (Extended_Body_Name);
+      Name_Len := Extended_Body_Name'Length;
+      Name_Buffer (1 .. Name_Len) := Extended_Body_Name;
+      The_Body_Name := Name_Find;
+
+      if Current_Verbosity = High then
+         Write_Str  ("Looking for file name of """);
+         Write_Str  (Name);
+         Write_Char ('"');
+         Write_Eol;
+         Write_Str  ("   Extended Spec Name = """);
+         Write_Str  (Extended_Spec_Name);
+         Write_Char ('"');
+         Write_Eol;
+         Write_Str  ("   Extended Body Name = """);
+         Write_Str  (Extended_Body_Name);
+         Write_Char ('"');
+         Write_Eol;
+      end if;
+
+      --  For every unit
+
+      for Current in reverse Units.First .. Units.Last loop
+         Unit := Units.Table (Current);
+
+         --  If it is a unit of the same project
+
+         if Unit.File_Names (Body_Part).Project = Project then
+            declare
+               Current_Name : constant Name_Id :=
+                                Unit.File_Names (Body_Part).Name;
+
+            begin
+               --  If there is a body
+
+               if Current_Name /= No_Name then
+                  if Current_Verbosity = High then
+                     Write_Str  ("   Comparing with """);
+                     Write_Str  (Get_Name_String (Current_Name));
+                     Write_Char ('"');
+                     Write_Eol;
+                  end if;
+
+                  --  If it has the name of the original name,
+                  --  return the original name
+
+                  if Unit.Name = The_Original_Name
+                    or else Current_Name = The_Original_Name
+                  then
+                     if Current_Verbosity = High then
+                        Write_Line ("   OK");
+                     end if;
+
+                     return Get_Name_String (Current_Name);
+
+                  --  If it has the name of the extended body name,
+                  --  return the extended body name
+
+                  elsif Current_Name = The_Body_Name then
+                     if Current_Verbosity = High then
+                        Write_Line ("   OK");
+                     end if;
+
+                     return Extended_Body_Name;
+
+                  else
+                     if Current_Verbosity = High then
+                        Write_Line ("   not good");
+                     end if;
+                  end if;
+               end if;
+            end;
+         end if;
+
+         --  If it is a unit of the same project
+
+         if Units.Table (Current).File_Names (Specification).Project =
+                                                                 Project
+         then
+            declare
+               Current_Name : constant Name_Id :=
+                                Unit.File_Names (Specification).Name;
+
+            begin
+               --  If there is a spec
+
+               if Current_Name /= No_Name then
+                  if Current_Verbosity = High then
+                     Write_Str  ("   Comparing with """);
+                     Write_Str  (Get_Name_String (Current_Name));
+                     Write_Char ('"');
+                     Write_Eol;
+                  end if;
+
+                  --  If it has the same name as the original name,
+                  --  return the original name
+
+                  if Unit.Name = The_Original_Name
+                    or else Current_Name = The_Original_Name
+                  then
+                     if Current_Verbosity = High then
+                        Write_Line ("   OK");
+                     end if;
+
+                     return Get_Name_String (Current_Name);
+
+                  --  If it has the same name as the extended spec name,
+                  --  return the extended spec name
+
+                  elsif Current_Name = The_Spec_Name then
+                     if Current_Verbosity = High then
+                        Write_Line ("   OK");
+                     end if;
+
+                     return Extended_Spec_Name;
+
+                  else
+                     if Current_Verbosity = High then
+                        Write_Line ("   not good");
+                     end if;
+                  end if;
+               end if;
+            end;
+         end if;
+
+      end loop;
+
+      --  We don't know this file name, return an empty string
+
+      return "";
+   end File_Name_Of_Library_Unit_Body;
+
+   -------------------------
+   -- For_All_Object_Dirs --
+   -------------------------
+
+   procedure For_All_Object_Dirs (Project : Project_Id) is
+      Seen : Project_List := Empty_Project_List;
+
+      procedure Add (Project : Project_Id);
+      --  Process a project. Remember the processes visited to avoid
+      --  processing a project twice. Recursively process an eventual
+      --  modified project, and all imported projects.
+
+      ---------
+      -- Add --
+      ---------
+
+      procedure Add (Project : Project_Id) is
+         Data : constant Project_Data := Projects.Table (Project);
+         List : Project_List := Data.Imported_Projects;
+
+      begin
+         --  If the list of visited project is empty, then
+         --  for sure we never visited this project.
+
+         if Seen = Empty_Project_List then
+            Project_Lists.Increment_Last;
+            Seen := Project_Lists.Last;
+            Project_Lists.Table (Seen) :=
+              (Project => Project, Next => Empty_Project_List);
+
+         else
+            --  Check if the project is in the list
+
+            declare
+               Current : Project_List := Seen;
+
+            begin
+               loop
+                  --  If it is, then there is nothing else to do
+
+                  if Project_Lists.Table (Current).Project = Project then
+                     return;
+                  end if;
+
+                  exit when Project_Lists.Table (Current).Next =
+                    Empty_Project_List;
+                  Current := Project_Lists.Table (Current).Next;
+               end loop;
+
+               --  This project has never been visited, add it
+               --  to the list.
+
+               Project_Lists.Increment_Last;
+               Project_Lists.Table (Current).Next := Project_Lists.Last;
+               Project_Lists.Table (Project_Lists.Last) :=
+                 (Project => Project, Next => Empty_Project_List);
+            end;
+         end if;
+
+         --  If there is an object directory, call Action
+         --  with its name
+
+         if Data.Object_Directory /= No_Name then
+            Get_Name_String (Data.Object_Directory);
+            Action (Name_Buffer (1 .. Name_Len));
+         end if;
+
+         --  If we are modifying a project, visit it
+
+         if Data.Modifies /= No_Project then
+            Add (Data.Modifies);
+         end if;
+
+         --  And visit all imported projects
+
+         while List /= Empty_Project_List loop
+            Add (Project_Lists.Table (List).Project);
+            List := Project_Lists.Table (List).Next;
+         end loop;
+      end Add;
+
+   --  Start of processing for For_All_Object_Dirs
+
+   begin
+      --  Visit this project, and its imported projects,
+      --  recursively
+
+      Add (Project);
+   end For_All_Object_Dirs;
+
+   -------------------------
+   -- For_All_Source_Dirs --
+   -------------------------
+
+   procedure For_All_Source_Dirs (Project : Project_Id) is
+      Seen : Project_List := Empty_Project_List;
+
+      procedure Add (Project : Project_Id);
+      --  Process a project. Remember the processes visited to avoid
+      --  processing a project twice. Recursively process an eventual
+      --  modified project, and all imported projects.
+
+      ---------
+      -- Add --
+      ---------
+
+      procedure Add (Project : Project_Id) is
+         Data : constant Project_Data := Projects.Table (Project);
+         List : Project_List := Data.Imported_Projects;
+
+      begin
+         --  If the list of visited project is empty, then
+         --  for sure we never visited this project.
+
+         if Seen = Empty_Project_List then
+            Project_Lists.Increment_Last;
+            Seen := Project_Lists.Last;
+            Project_Lists.Table (Seen) :=
+              (Project => Project, Next => Empty_Project_List);
+
+         else
+            --  Check if the project is in the list
+
+            declare
+               Current : Project_List := Seen;
+
+            begin
+               loop
+                  --  If it is, then there is nothing else to do
+
+                  if Project_Lists.Table (Current).Project = Project then
+                     return;
+                  end if;
+
+                  exit when Project_Lists.Table (Current).Next =
+                    Empty_Project_List;
+                  Current := Project_Lists.Table (Current).Next;
+               end loop;
+
+               --  This project has never been visited, add it
+               --  to the list.
+
+               Project_Lists.Increment_Last;
+               Project_Lists.Table (Current).Next := Project_Lists.Last;
+               Project_Lists.Table (Project_Lists.Last) :=
+                 (Project => Project, Next => Empty_Project_List);
+            end;
+         end if;
+
+         declare
+            Current    : String_List_Id := Data.Source_Dirs;
+            The_String : String_Element;
+
+         begin
+            --  Call action with the name of every source directorie
+
+            while Current /= Nil_String loop
+               The_String := String_Elements.Table (Current);
+               String_To_Name_Buffer (The_String.Value);
+               Action (Name_Buffer (1 .. Name_Len));
+               Current := The_String.Next;
+            end loop;
+         end;
+
+         --  If we are modifying a project, visit it
+
+         if Data.Modifies /= No_Project then
+            Add (Data.Modifies);
+         end if;
+
+         --  And visit all imported projects
+
+         while List /= Empty_Project_List loop
+            Add (Project_Lists.Table (List).Project);
+            List := Project_Lists.Table (List).Next;
+         end loop;
+      end Add;
+
+   --  Start of processing for For_All_Source_Dirs
+
+   begin
+      --  Visit this project, and its imported projects recursively
+
+      Add (Project);
+   end For_All_Source_Dirs;
+
+   -------------------
+   -- Get_Reference --
+   -------------------
+
+   procedure Get_Reference
+     (Source_File_Name : String;
+      Project          : out Project_Id;
+      Path             : out Name_Id)
+   is
+   begin
+      if Current_Verbosity > Default then
+         Write_Str ("Getting Reference_Of (""");
+         Write_Str (Source_File_Name);
+         Write_Str (""") ... ");
+      end if;
+
+      declare
+         Original_Name : String := Source_File_Name;
+         Unit          : Unit_Data;
+
+      begin
+         Canonical_Case_File_Name (Original_Name);
+
+         for Id in Units.First .. Units.Last loop
+            Unit := Units.Table (Id);
+
+            if (Unit.File_Names (Specification).Name /= No_Name
+                 and then
+                   Namet.Get_Name_String
+                     (Unit.File_Names (Specification).Name) = Original_Name)
+              or else (Unit.File_Names (Specification).Path /= No_Name
+                         and then
+                           Namet.Get_Name_String
+                           (Unit.File_Names (Specification).Path) =
+                                                              Original_Name)
+            then
+               Project := Unit.File_Names (Specification).Project;
+               Path := Unit.File_Names (Specification).Path;
+
+               if Current_Verbosity > Default then
+                  Write_Str ("Done: Specification.");
+                  Write_Eol;
+               end if;
+
+               return;
+
+            elsif (Unit.File_Names (Body_Part).Name /= No_Name
+                    and then
+                      Namet.Get_Name_String
+                        (Unit.File_Names (Body_Part).Name) = Original_Name)
+              or else (Unit.File_Names (Body_Part).Path /= No_Name
+                         and then Namet.Get_Name_String
+                                    (Unit.File_Names (Body_Part).Path) =
+                                                             Original_Name)
+            then
+               Project := Unit.File_Names (Body_Part).Project;
+               Path := Unit.File_Names (Body_Part).Path;
+
+               if Current_Verbosity > Default then
+                  Write_Str ("Done: Body.");
+                  Write_Eol;
+               end if;
+
+               return;
+            end if;
+
+         end loop;
+      end;
+
+      Project := No_Project;
+      Path    := No_Name;
+
+      if Current_Verbosity > Default then
+         Write_Str ("Cannot be found.");
+         Write_Eol;
+      end if;
+   end Get_Reference;
+
+   ----------------
+   -- Initialize --
+   ----------------
+
+   procedure Initialize is
+      Global : constant String := "global_configuration_pragmas";
+      Local  : constant String :=  "local_configuration_pragmas";
+   begin
+      --  Put the standard GNAT naming scheme in the Namings table
+
+      Namings.Increment_Last;
+      Namings.Table (Namings.Last) := Standard_Naming_Data;
+      Name_Len := Global'Length;
+      Name_Buffer (1 .. Name_Len) := Global;
+      Global_Configuration_Pragmas := Name_Find;
+      Name_Len := Local'Length;
+      Name_Buffer (1 .. Name_Len) := Local;
+      Local_Configuration_Pragmas := Name_Find;
+   end Initialize;
+
+   ------------------------------------
+   -- Path_Name_Of_Library_Unit_Body --
+   ------------------------------------
+
+   function Path_Name_Of_Library_Unit_Body
+     (Name    : String;
+      Project : Project_Id)
+      return String
+   is
+      Data : constant Project_Data := Projects.Table (Project);
+      Original_Name : String := Name;
+
+      Extended_Spec_Name : String :=
+                             Name & Namet.Get_Name_String
+                                     (Data.Naming.Specification_Append);
+      Extended_Body_Name : String :=
+                             Name & Namet.Get_Name_String
+                                     (Data.Naming.Body_Append);
+
+      First   : Unit_Id := Units.First;
+      Current : Unit_Id;
+      Unit    : Unit_Data;
+
+   begin
+      Canonical_Case_File_Name (Original_Name);
+      Canonical_Case_File_Name (Extended_Spec_Name);
+      Canonical_Case_File_Name (Extended_Spec_Name);
+
+      if Current_Verbosity = High then
+         Write_Str  ("Looking for path name of """);
+         Write_Str  (Name);
+         Write_Char ('"');
+         Write_Eol;
+         Write_Str  ("   Extended Spec Name = """);
+         Write_Str  (Extended_Spec_Name);
+         Write_Char ('"');
+         Write_Eol;
+         Write_Str  ("   Extended Body Name = """);
+         Write_Str  (Extended_Body_Name);
+         Write_Char ('"');
+         Write_Eol;
+      end if;
+
+      while First <= Units.Last
+        and then Units.Table (First).File_Names (Body_Part).Project /= Project
+      loop
+         First := First + 1;
+      end loop;
+
+      Current := First;
+      while Current <= Units.Last loop
+         Unit := Units.Table (Current);
+
+         if Unit.File_Names (Body_Part).Project = Project
+           and then Unit.File_Names (Body_Part).Name /= No_Name
+         then
+            declare
+               Current_Name : constant String :=
+                 Namet.Get_Name_String (Unit.File_Names (Body_Part).Name);
+            begin
+               if Current_Verbosity = High then
+                  Write_Str  ("   Comparing with """);
+                  Write_Str  (Current_Name);
+                  Write_Char ('"');
+                  Write_Eol;
+               end if;
+
+               if Current_Name = Original_Name then
+                  if Current_Verbosity = High then
+                     Write_Line ("   OK");
+                  end if;
+
+                  return Body_Path_Name_Of (Current);
+
+               elsif Current_Name = Extended_Body_Name then
+                  if Current_Verbosity = High then
+                     Write_Line ("   OK");
+                  end if;
+
+                  return Body_Path_Name_Of (Current);
+
+               else
+                  if Current_Verbosity = High then
+                     Write_Line ("   not good");
+                  end if;
+               end if;
+            end;
+
+         elsif Unit.File_Names (Specification).Name /= No_Name then
+            declare
+               Current_Name : constant String :=
+                                Namet.Get_Name_String
+                                  (Unit.File_Names (Specification).Name);
+
+            begin
+               if Current_Verbosity = High then
+                  Write_Str  ("   Comparing with """);
+                  Write_Str  (Current_Name);
+                  Write_Char ('"');
+                  Write_Eol;
+               end if;
+
+               if Current_Name = Original_Name then
+                  if Current_Verbosity = High then
+                     Write_Line ("   OK");
+                  end if;
+
+                  return Spec_Path_Name_Of (Current);
+
+               elsif Current_Name = Extended_Spec_Name then
+
+                  if Current_Verbosity = High then
+                     Write_Line ("   OK");
+                  end if;
+
+                  return Spec_Path_Name_Of (Current);
+
+               else
+                  if Current_Verbosity = High then
+                     Write_Line ("   not good");
+                  end if;
+               end if;
+            end;
+         end if;
+         Current := Current + 1;
+      end loop;
+
+      return "";
+   end Path_Name_Of_Library_Unit_Body;
+
+   -------------------
+   -- Print_Sources --
+   -------------------
+
+   procedure Print_Sources is
+      Unit : Unit_Data;
+
+   begin
+      Write_Line ("List of Sources:");
+
+      for Id in Units.First .. Units.Last loop
+         Unit := Units.Table (Id);
+         Write_Str  ("   ");
+         Write_Line (Namet.Get_Name_String (Unit.Name));
+
+         if Unit.File_Names (Specification).Name /= No_Name then
+            if Unit.File_Names (Specification).Project = No_Project then
+               Write_Line ("   No project");
+
+            else
+               Write_Str  ("   Project: ");
+               Get_Name_String
+                 (Projects.Table
+                   (Unit.File_Names (Specification).Project).Path_Name);
+               Write_Line (Name_Buffer (1 .. Name_Len));
+            end if;
+
+            Write_Str  ("      spec: ");
+            Write_Line
+              (Namet.Get_Name_String
+               (Unit.File_Names (Specification).Name));
+         end if;
+
+         if Unit.File_Names (Body_Part).Name /= No_Name then
+            if Unit.File_Names (Body_Part).Project = No_Project then
+               Write_Line ("   No project");
+
+            else
+               Write_Str  ("   Project: ");
+               Get_Name_String
+                 (Projects.Table
+                   (Unit.File_Names (Body_Part).Project).Path_Name);
+               Write_Line (Name_Buffer (1 .. Name_Len));
+            end if;
+
+            Write_Str  ("      body: ");
+            Write_Line
+              (Namet.Get_Name_String
+               (Unit.File_Names (Body_Part).Name));
+         end if;
+
+      end loop;
+
+      Write_Line ("end of List of Sources.");
+   end Print_Sources;
+
+   -----------------------
+   -- Spec_Path_Name_Of --
+   -----------------------
+
+   function Spec_Path_Name_Of (Unit : Unit_Id) return String is
+      Data : Unit_Data := Units.Table (Unit);
+
+   begin
+      if Data.File_Names (Specification).Path = No_Name then
+         declare
+            Current_Source : String_List_Id :=
+              Projects.Table (Data.File_Names (Specification).Project).Sources;
+            Path : GNAT.OS_Lib.String_Access;
+
+         begin
+            Data.File_Names (Specification).Path :=
+              Data.File_Names (Specification).Name;
+
+            while Current_Source /= Nil_String loop
+               String_To_Name_Buffer
+                 (String_Elements.Table (Current_Source).Value);
+               Path := Locate_Regular_File
+                 (Namet.Get_Name_String
+                  (Data.File_Names (Specification).Name),
+                  Name_Buffer (1 .. Name_Len));
+
+               if Path /= null then
+                  Name_Len := Path'Length;
+                  Name_Buffer (1 .. Name_Len) := Path.all;
+                  Data.File_Names (Specification).Path := Name_Enter;
+                  exit;
+               else
+                  Current_Source :=
+                    String_Elements.Table (Current_Source).Next;
+               end if;
+            end loop;
+
+            Units.Table (Unit) := Data;
+         end;
+      end if;
+
+      return Namet.Get_Name_String (Data.File_Names (Specification).Path);
+   end Spec_Path_Name_Of;
+
+end Prj.Env;
diff --git a/gcc/ada/prj-env.ads b/gcc/ada/prj-env.ads
new file mode 100644 (file)
index 0000000..272c559
--- /dev/null
@@ -0,0 +1,99 @@
+------------------------------------------------------------------------------
+--                                                                          --
+--                         GNAT COMPILER COMPONENTS                         --
+--                                                                          --
+--                              P R J . E N V                               --
+--                                                                          --
+--                                 S p e c                                  --
+--                                                                          --
+--                            $Revision: 1.10 $
+--                                                                          --
+--             Copyright (C) 2001 Free Software Foundation, Inc.            --
+--                                                                          --
+-- GNAT is free software;  you can  redistribute it  and/or modify it under --
+-- terms of the  GNU General Public License as published  by the Free Soft- --
+-- ware  Foundation;  either version 2,  or (at your option) any later ver- --
+-- sion.  GNAT is distributed in the hope that it will be useful, but WITH- --
+-- OUT 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  distributed with GNAT;  see file COPYING.  If not, write --
+-- to  the Free Software Foundation,  59 Temple Place - Suite 330,  Boston, --
+-- MA 02111-1307, USA.                                                      --
+--                                                                          --
+-- GNAT was originally developed  by the GNAT team at  New York University. --
+-- It is now maintained by Ada Core Technologies Inc (http://www.gnat.com). --
+--                                                                          --
+------------------------------------------------------------------------------
+
+--  This package implements services for Project-aware tools, related
+--  to the environment (gnat.adc, ADA_INCLUDE_PATH, ADA_OBJECTS_PATH)
+
+with GNAT.OS_Lib; use GNAT.OS_Lib;
+
+package Prj.Env is
+
+   procedure Initialize;
+   --  Put Standard_Naming_Data into Namings table (called by Prj.Initialize)
+
+   procedure Print_Sources;
+   --  Output the list of sources, after Project files have been scanned
+
+   procedure Create_Config_Pragmas_File
+     (For_Project  : Project_Id;
+      Main_Project : Project_Id);
+   --  If there needs to have SFN pragmas, either for non standard naming
+   --  schemes or for individual units, or if Global_Configuration_Pragmas
+   --  has been specified in package gnatmake of the main project, or if
+   --  Local_Configuration_Pragmas has been specified in package Compiler
+   --  of the main project, build (if needed) a temporary file that contains
+   --  all configuration pragmas, and specify the configuration pragmas file
+   --  in the project data.
+
+   function Ada_Include_Path (Project : Project_Id) return String_Access;
+   --  Get the ADA_INCLUDE_PATH of a Project file. For the first call, compute
+   --  it and cache it.
+
+   function Ada_Objects_Path
+     (Project             : Project_Id;
+      Including_Libraries : Boolean := True)
+      return                String_Access;
+   --  Get the ADA_OBJECTS_PATH of a Project file. For the first call, compute
+   --  it and cache it. When Including_Libraries is False, do not include the
+   --  object directories of the library projects, and do not cache the result.
+
+   function Path_Name_Of_Library_Unit_Body
+     (Name    : String;
+      Project : Project_Id)
+      return    String;
+   --  Returns the Path of a library unit.
+
+   function File_Name_Of_Library_Unit_Body
+     (Name    : String;
+      Project : Project_Id)
+      return    String;
+   --  Returns the file name of a library unit, in canonical case. Name may or
+   --  may not have an extension (corresponding to the naming scheme of the
+   --  project). If there is no body with this name, but there is a spec, the
+   --  name of the spec is returned. If neither a body or a spec can be found,
+   --  return an empty string.
+
+   procedure Get_Reference
+     (Source_File_Name : String;
+      Project          : out Project_Id;
+      Path             : out Name_Id);
+   --  Returns the project of a source.
+
+   generic
+      with procedure Action (Path : String);
+   procedure For_All_Source_Dirs (Project : Project_Id);
+   --  Iterate through all the source directories of a project,
+   --  including those of imported or modified projects.
+
+   generic
+      with procedure Action (Path : String);
+   procedure For_All_Object_Dirs (Project : Project_Id);
+   --  Iterate through all the object directories of a project,
+   --  including those of imported or modified projects.
+
+end Prj.Env;
diff --git a/gcc/ada/prj-ext.adb b/gcc/ada/prj-ext.adb
new file mode 100644 (file)
index 0000000..b6f6ab8
--- /dev/null
@@ -0,0 +1,130 @@
+------------------------------------------------------------------------------
+--                                                                          --
+--                         GNAT COMPILER COMPONENTS                         --
+--                                                                          --
+--                              P R J . E X T                               --
+--                                                                          --
+--                                 B o d y                                  --
+--                                                                          --
+--                            $Revision: 1.5 $
+--                                                                          --
+--             Copyright (C) 2000 Free Software Foundation, Inc.            --
+--                                                                          --
+-- GNAT is free software;  you can  redistribute it  and/or modify it under --
+-- terms of the  GNU General Public License as published  by the Free Soft- --
+-- ware  Foundation;  either version 2,  or (at your option) any later ver- --
+-- sion.  GNAT is distributed in the hope that it will be useful, but WITH- --
+-- OUT 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  distributed with GNAT;  see file COPYING.  If not, write --
+-- to  the Free Software Foundation,  59 Temple Place - Suite 330,  Boston, --
+-- MA 02111-1307, USA.                                                      --
+--                                                                          --
+-- GNAT was originally developed  by the GNAT team at  New York University. --
+-- It is now maintained by Ada Core Technologies Inc (http://www.gnat.com). --
+--                                                                          --
+------------------------------------------------------------------------------
+
+with GNAT.HTable;
+with GNAT.OS_Lib; use GNAT.OS_Lib;
+with Namet;       use Namet;
+with Prj.Com;     use Prj.Com;
+with Stringt;     use Stringt;
+with Types;       use Types;
+
+package body Prj.Ext is
+
+   package Htable is new GNAT.HTable.Simple_HTable
+     (Header_Num => Header_Num,
+      Element    => String_Id,
+      No_Element => No_String,
+      Key        => Name_Id,
+      Hash       => Hash,
+      Equal      => "=");
+
+   ---------
+   -- Add --
+   ---------
+
+   procedure Add
+     (External_Name : String;
+      Value         : String)
+   is
+      The_Key   : Name_Id;
+      The_Value : String_Id;
+
+   begin
+      Start_String;
+      Store_String_Chars (Value);
+      The_Value := End_String;
+      Name_Len := External_Name'Length;
+      Name_Buffer (1 .. Name_Len) := External_Name;
+      The_Key := Name_Find;
+      Htable.Set (The_Key, The_Value);
+   end Add;
+
+   -----------
+   -- Check --
+   -----------
+
+   function Check (Declaration : String) return Boolean is
+   begin
+      for Equal_Pos in Declaration'Range loop
+
+         if Declaration (Equal_Pos) = '=' then
+            exit when Equal_Pos = Declaration'First;
+            exit when Equal_Pos = Declaration'Last;
+            Add
+              (External_Name =>
+                 Declaration (Declaration'First .. Equal_Pos - 1),
+               Value =>
+                 Declaration (Equal_Pos + 1 .. Declaration'Last));
+            return True;
+         end if;
+
+      end loop;
+
+      return False;
+   end Check;
+
+   --------------
+   -- Value_Of --
+   --------------
+
+   function Value_Of
+     (External_Name : Name_Id;
+      With_Default  : String_Id := No_String)
+      return          String_Id
+   is
+      The_Value : String_Id;
+
+   begin
+      The_Value := Htable.Get (External_Name);
+
+      if The_Value /= No_String then
+         return The_Value;
+      end if;
+
+      --  Find if it is an environment.
+      --  If it is, put the value in the hash table.
+
+      declare
+         Env_Value : constant String_Access :=
+           Getenv (Get_Name_String (External_Name));
+
+      begin
+         if Env_Value /= null and then Env_Value'Length > 0 then
+            Start_String;
+            Store_String_Chars (Env_Value.all);
+            The_Value := End_String;
+            Htable.Set (External_Name, The_Value);
+            return The_Value;
+
+         else
+            return With_Default;
+         end if;
+      end;
+   end Value_Of;
+
+end Prj.Ext;
diff --git a/gcc/ada/prj-ext.ads b/gcc/ada/prj-ext.ads
new file mode 100644 (file)
index 0000000..4c12b78
--- /dev/null
@@ -0,0 +1,51 @@
+------------------------------------------------------------------------------
+--                                                                          --
+--                         GNAT COMPILER COMPONENTS                         --
+--                                                                          --
+--                              P R J . E X T                               --
+--                                                                          --
+--                                 S p e c                                  --
+--                                                                          --
+--                            $Revision: 1.3 $
+--                                                                          --
+--             Copyright (C) 2000 Free Software Foundation, Inc.            --
+--                                                                          --
+-- GNAT is free software;  you can  redistribute it  and/or modify it under --
+-- terms of the  GNU General Public License as published  by the Free Soft- --
+-- ware  Foundation;  either version 2,  or (at your option) any later ver- --
+-- sion.  GNAT is distributed in the hope that it will be useful, but WITH- --
+-- OUT 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  distributed with GNAT;  see file COPYING.  If not, write --
+-- to  the Free Software Foundation,  59 Temple Place - Suite 330,  Boston, --
+-- MA 02111-1307, USA.                                                      --
+--                                                                          --
+-- GNAT was originally developed  by the GNAT team at  New York University. --
+-- It is now maintained by Ada Core Technologies Inc (http://www.gnat.com). --
+--                                                                          --
+------------------------------------------------------------------------------
+
+--  Set, Get and cache External reference, to be used as External functions
+--  in project files.
+
+with Types; use Types;
+
+package Prj.Ext is
+
+   procedure Add
+     (External_Name : String;
+      Value         : String);
+   --  Add an external reference (or modify an existing one).
+
+   function Value_Of
+     (External_Name : Name_Id;
+      With_Default  : String_Id := No_String)
+      return          String_Id;
+   --  Get the value of an external reference, and cache it for future uses.
+
+   function Check (Declaration : String) return Boolean;
+   --  Check that an external declaration <external>=<value> is correct.
+   --  If it is correct, the external reference is Added.
+
+end Prj.Ext;
diff --git a/gcc/ada/prj-nmsc.adb b/gcc/ada/prj-nmsc.adb
new file mode 100644 (file)
index 0000000..6603187
--- /dev/null
@@ -0,0 +1,2236 @@
+------------------------------------------------------------------------------
+--                                                                          --
+--                         GNAT COMPILER COMPONENTS                         --
+--                                                                          --
+--                             P R J . N M S C                              --
+--                                                                          --
+--                                 B o d y                                  --
+--                                                                          --
+--                            $Revision: 1.25 $
+--                                                                          --
+--          Copyright (C) 2000-2001 Free Software Foundation, Inc.          --
+--                                                                          --
+-- GNAT is free software;  you can  redistribute it  and/or modify it under --
+-- terms of the  GNU General Public License as published  by the Free Soft- --
+-- ware  Foundation;  either version 2,  or (at your option) any later ver- --
+-- sion.  GNAT is distributed in the hope that it will be useful, but WITH- --
+-- OUT 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  distributed with GNAT;  see file COPYING.  If not, write --
+-- to  the Free Software Foundation,  59 Temple Place - Suite 330,  Boston, --
+-- MA 02111-1307, USA.                                                      --
+--                                                                          --
+-- GNAT was originally developed  by the GNAT team at  New York University. --
+-- It is now maintained by Ada Core Technologies Inc (http://www.gnat.com). --
+--                                                                          --
+------------------------------------------------------------------------------
+
+with Ada.Characters.Handling; use Ada.Characters.Handling;
+with Ada.Strings;             use Ada.Strings;
+with Ada.Strings.Fixed;       use Ada.Strings.Fixed;
+with Ada.Strings.Maps.Constants; use Ada.Strings.Maps.Constants;
+with Errout;                  use Errout;
+with GNAT.Directory_Operations; use GNAT.Directory_Operations;
+with GNAT.OS_Lib;             use GNAT.OS_Lib;
+with Namet;                   use Namet;
+with Osint;                   use Osint;
+with Output;                  use Output;
+with Prj.Com;                 use Prj.Com;
+with Prj.Util;                use Prj.Util;
+with Snames;                  use Snames;
+with Stringt;                 use Stringt;
+with Types;                   use Types;
+
+package body Prj.Nmsc is
+
+   Dir_Sep      : Character renames GNAT.OS_Lib.Directory_Separator;
+
+   Error_Report : Put_Line_Access := null;
+
+   procedure Check_Naming_Scheme (Naming : Naming_Data);
+   --  Check that the package Naming is correct.
+
+   procedure Check_Naming_Scheme
+     (Name : Name_Id;
+      Unit : out Name_Id);
+   --  Check that a name is a valid unit name.
+
+   procedure Error_Msg (Msg : String; Flag_Location : Source_Ptr);
+   --  Output an error message.
+   --  If Error_Report is null, simply call Errout.Error_Msg.
+   --  Otherwise, disregard Flag_Location and use Error_Report.
+
+   function Get_Name_String (S : String_Id) return String;
+   --  Get the string from a String_Id
+
+   procedure Get_Unit
+     (File_Name    : Name_Id;
+      Naming       : Naming_Data;
+      Unit_Name    : out Name_Id;
+      Unit_Kind    : out Spec_Or_Body;
+      Needs_Pragma : out Boolean);
+   --  Find out, from a file name, the unit name, the unit kind
+   --  and if a specific SFN pragma is needed.
+   --  If the file name corresponds to no unit, then Unit_Name
+   --  will be No_Name.
+
+   function Is_Illegal_Append (This : String) return Boolean;
+   --  Returns True if the string This cannot be used as
+   --  a Specification_Append, a Body_Append or a Separate_Append.
+
+   procedure Record_Source
+     (File_Name        : Name_Id;
+      Path_Name        : Name_Id;
+      Project          : Project_Id;
+      Data             : in out Project_Data;
+      Error_If_Invalid : Boolean;
+      Location         : Source_Ptr;
+      Current_Source   : in out String_List_Id);
+   --  Put a unit in the list of units of a project, if the file name
+   --  corresponds to a valid unit name.
+   --  If it does not correspond to a valid unit name, report an error
+   --  only if Error_If_Invalid is true.
+
+   procedure Show_Source_Dirs (Project : Project_Id);
+   --  List all the source directories of a project.
+
+   function Locate_Directory
+     (Name   : Name_Id;
+      Parent : Name_Id)
+     return   Name_Id;
+   --  Locate a directory.
+   --  Returns No_Name if directory does not exist.
+
+   function Path_Name_Of
+     (File_Name : String_Id;
+      Directory : Name_Id)
+     return      String;
+   --  Returns the path name of a (non project) file.
+   --  Returns an empty string if file cannot be found.
+
+   function Path_Name_Of
+     (File_Name : String_Id;
+      Directory : String_Id)
+     return      String;
+   --  Same as above except that Directory is a String_Id instead
+   --  of a Name_Id.
+
+   -------------------------
+   -- Check_Naming_Scheme --
+   -------------------------
+
+   procedure Check_Naming_Scheme (Naming : Naming_Data) is
+   begin
+      --  Only check if we are not using the standard naming scheme
+
+      if Naming /= Standard_Naming_Data then
+         declare
+            Dot_Replacement      : constant String :=
+                                     Get_Name_String
+                                       (Naming.Dot_Replacement);
+            Specification_Append : constant String :=
+                                     Get_Name_String
+                                       (Naming.Specification_Append);
+            Body_Append          : constant String :=
+                                     Get_Name_String
+                                       (Naming.Body_Append);
+            Separate_Append      : constant String :=
+                                     Get_Name_String
+                                       (Naming.Separate_Append);
+
+         begin
+            --  Dot_Replacement cannot
+            --   - be empty
+            --   - start or end with an alphanumeric
+            --   - be a single '_'
+            --   - start with an '_' followed by an alphanumeric
+            --   - contain a '.' except if it is "."
+
+            if Dot_Replacement'Length = 0
+              or else Is_Alphanumeric
+                        (Dot_Replacement (Dot_Replacement'First))
+              or else Is_Alphanumeric
+                        (Dot_Replacement (Dot_Replacement'Last))
+              or else (Dot_Replacement (Dot_Replacement'First) = '_'
+                        and then
+                        (Dot_Replacement'Length = 1
+                          or else
+                           Is_Alphanumeric
+                             (Dot_Replacement (Dot_Replacement'First + 1))))
+              or else (Dot_Replacement'Length > 1
+                         and then
+                           Index (Source => Dot_Replacement,
+                                  Pattern => ".") /= 0)
+            then
+               Error_Msg
+                 ('"' & Dot_Replacement &
+                  """ is illegal for Dot_Replacement.",
+                  Naming.Dot_Repl_Loc);
+            end if;
+
+            --  Appends cannot
+            --   - be empty
+            --   - start with an alphanumeric
+            --   - start with an '_' followed by an alphanumeric
+
+            if Is_Illegal_Append (Specification_Append) then
+               Error_Msg
+                 ('"' & Specification_Append &
+                  """ is illegal for Specification_Append.",
+                  Naming.Spec_Append_Loc);
+            end if;
+
+            if Is_Illegal_Append (Body_Append) then
+               Error_Msg
+                 ('"' & Body_Append &
+                  """ is illegal for Body_Append.",
+                  Naming.Body_Append_Loc);
+            end if;
+
+            if Body_Append /= Separate_Append then
+               if Is_Illegal_Append (Separate_Append) then
+                  Error_Msg
+                    ('"' & Separate_Append &
+                     """ is illegal for Separate_Append.",
+                     Naming.Sep_Append_Loc);
+               end if;
+            end if;
+
+            --  Specification_Append cannot have the same termination as
+            --  Body_Append or Separate_Append
+
+            if Specification_Append'Length >= Body_Append'Length
+              and then
+                Body_Append (Body_Append'Last -
+                             Specification_Append'Length + 1 ..
+                             Body_Append'Last) = Specification_Append
+            then
+               Error_Msg
+                 ("Body_Append (""" &
+                  Body_Append &
+                  """) cannot end with" &
+                  " Specification_Append (""" &
+                  Specification_Append & """).",
+                  Naming.Body_Append_Loc);
+            end if;
+
+            if Specification_Append'Length >= Separate_Append'Length
+              and then
+                Separate_Append
+                  (Separate_Append'Last - Specification_Append'Length + 1
+                    ..
+                   Separate_Append'Last) = Specification_Append
+            then
+               Error_Msg
+                 ("Separate_Append (""" &
+                  Separate_Append &
+                  """) cannot end with" &
+                  " Specification_Append (""" &
+                  Specification_Append & """).",
+                  Naming.Sep_Append_Loc);
+            end if;
+         end;
+      end if;
+   end Check_Naming_Scheme;
+
+   procedure Check_Naming_Scheme
+     (Name : Name_Id;
+      Unit : out Name_Id)
+   is
+      The_Name        : String := Get_Name_String (Name);
+      Need_Letter     : Boolean := True;
+      Last_Underscore : Boolean := False;
+      OK              : Boolean := The_Name'Length > 0;
+
+   begin
+      for Index in The_Name'Range loop
+         if Need_Letter then
+
+            --  We need a letter (at the beginning, and following a dot),
+            --  but we don't have one.
+
+            if Is_Letter (The_Name (Index)) then
+               Need_Letter := False;
+
+            else
+               OK := False;
+
+               if Current_Verbosity = High then
+                  Write_Int  (Types.Int (Index));
+                  Write_Str  (": '");
+                  Write_Char (The_Name (Index));
+                  Write_Line ("' is not a letter.");
+               end if;
+
+               exit;
+            end if;
+
+         elsif Last_Underscore
+           and then (The_Name (Index) = '_' or else The_Name (Index) = '.')
+         then
+            --  Two underscores are illegal, and a dot cannot follow
+            --  an underscore.
+
+            OK := False;
+
+            if Current_Verbosity = High then
+               Write_Int  (Types.Int (Index));
+               Write_Str  (": '");
+               Write_Char (The_Name (Index));
+               Write_Line ("' is illegal here.");
+            end if;
+
+            exit;
+
+         elsif The_Name (Index) = '.' then
+
+            --  We need a letter after a dot
+
+            Need_Letter := True;
+
+         elsif The_Name (Index) = '_' then
+            Last_Underscore := True;
+
+         else
+            --  We need an letter or a digit
+
+            Last_Underscore := False;
+
+            if not Is_Alphanumeric (The_Name (Index)) then
+               OK := False;
+
+               if Current_Verbosity = High then
+                  Write_Int  (Types.Int (Index));
+                  Write_Str  (": '");
+                  Write_Char (The_Name (Index));
+                  Write_Line ("' is not alphanumeric.");
+               end if;
+
+               exit;
+            end if;
+         end if;
+      end loop;
+
+      --  We cannot end with an underscore or a dot
+
+      OK := OK and then not Need_Letter and then not Last_Underscore;
+
+      if OK then
+         Unit := Name;
+      else
+         --  We signal a problem with No_Name
+
+         Unit := No_Name;
+      end if;
+   end Check_Naming_Scheme;
+
+   procedure Check_Naming_Scheme
+     (Project      : Project_Id;
+      Report_Error : Put_Line_Access)
+   is
+      Last_Source_Dir   : String_List_Id  := Nil_String;
+      Data              : Project_Data    := Projects.Table (Project);
+
+      procedure Check_Unit_Names (List : Array_Element_Id);
+      --  Check that a list of unit names contains only valid names.
+
+      procedure Find_Source_Dirs (From : String_Id; Location : Source_Ptr);
+      --  Find one or several source directories, and add them
+      --  to the list of source directories of the project.
+
+      procedure Find_Sources;
+      --  Find all the sources in all of the source directories
+      --  of a project.
+
+      procedure Get_Path_Name_And_Record_Source
+        (File_Name        : String;
+         Location         : Source_Ptr;
+         Current_Source   : in out String_List_Id);
+      --  Find the path name of a source in the source directories and
+      --  record the source, if found.
+
+      procedure Get_Sources_From_File
+        (Path     : String;
+         Location : Source_Ptr);
+      --  Get the sources of a project from a text file
+
+      ----------------------
+      -- Check_Unit_Names --
+      ----------------------
+
+      procedure Check_Unit_Names (List : Array_Element_Id) is
+         Current   : Array_Element_Id := List;
+         Element   : Array_Element;
+         Unit_Name : Name_Id;
+
+      begin
+         --  Loop through elements of the string list
+
+         while Current /= No_Array_Element loop
+            Element := Array_Elements.Table (Current);
+
+            --  Check that it contains a valid unit name
+
+            Check_Naming_Scheme (Element.Index, Unit_Name);
+
+            if Unit_Name = No_Name then
+               Error_Msg_Name_1 := Element.Index;
+               Error_Msg
+                 ("{ is not a valid unit name.",
+                  Element.Value.Location);
+
+            else
+
+               if Current_Verbosity = High then
+                  Write_Str ("   Body_Part (""");
+                  Write_Str (Get_Name_String (Unit_Name));
+                  Write_Line (""")");
+               end if;
+
+               Element.Index := Unit_Name;
+               Array_Elements.Table (Current) := Element;
+            end if;
+
+            Current := Element.Next;
+         end loop;
+      end Check_Unit_Names;
+
+      ----------------------
+      -- Find_Source_Dirs --
+      ----------------------
+
+      procedure Find_Source_Dirs (From : String_Id; Location : Source_Ptr) is
+
+         Directory    : String (1 .. Integer (String_Length (From)));
+         Directory_Id : Name_Id;
+         Element      : String_Element;
+
+         procedure Recursive_Find_Dirs (Path : String_Id);
+         --  Find all the subdirectories (recursively) of Path
+         --  and add them to the list of source directories
+         --  of the project.
+
+         -------------------------
+         -- Recursive_Find_Dirs --
+         -------------------------
+
+         procedure Recursive_Find_Dirs (Path : String_Id) is
+            Dir      : Dir_Type;
+            Name     : String (1 .. 250);
+            Last     : Natural;
+            The_Path : String := Get_Name_String (Path) & Dir_Sep;
+
+            The_Path_Last : Positive := The_Path'Last;
+
+         begin
+            if The_Path'Length > 1
+              and then
+                (The_Path (The_Path_Last - 1) = Dir_Sep
+                   or else The_Path (The_Path_Last - 1) = '/')
+            then
+               The_Path_Last := The_Path_Last - 1;
+            end if;
+
+            if Current_Verbosity = High then
+               Write_Str  ("   ");
+               Write_Line (The_Path (The_Path'First .. The_Path_Last));
+            end if;
+
+            String_Elements.Increment_Last;
+            Element :=
+              (Value    => Path,
+               Location => No_Location,
+               Next     => Nil_String);
+
+            --  Case of first source directory
+
+            if Last_Source_Dir = Nil_String then
+               Data.Source_Dirs := String_Elements.Last;
+
+            --  Here we already have source directories.
+
+            else
+               --  Link the previous last to the new one
+
+               String_Elements.Table (Last_Source_Dir).Next :=
+                 String_Elements.Last;
+            end if;
+
+            --  And register this source directory as the new last
+
+            Last_Source_Dir  := String_Elements.Last;
+            String_Elements.Table (Last_Source_Dir) := Element;
+
+            --  Now look for subdirectories
+
+            Open (Dir, The_Path (The_Path'First .. The_Path_Last));
+
+            loop
+               Read (Dir, Name, Last);
+               exit when Last = 0;
+
+               if Current_Verbosity = High then
+                  Write_Str  ("   Checking ");
+                  Write_Line (Name (1 .. Last));
+               end if;
+
+               if Name (1 .. Last) /= "."
+                 and then Name (1 .. Last) /= ".."
+               then
+                  --  Avoid . and ..
+
+                  declare
+                     Path_Name : constant String :=
+                                   The_Path (The_Path'First .. The_Path_Last) &
+                                   Name (1 .. Last);
+
+                  begin
+                     if Is_Directory (Path_Name) then
+
+                        --  We have found a new subdirectory,
+                        --  register it and find its own subdirectories.
+
+                        Start_String;
+                        Store_String_Chars (Path_Name);
+                        Recursive_Find_Dirs (End_String);
+                     end if;
+                  end;
+               end if;
+            end loop;
+
+            Close (Dir);
+
+         exception
+            when Directory_Error =>
+               null;
+         end Recursive_Find_Dirs;
+
+         --  Start of processing for Find_Source_Dirs
+
+      begin
+         if Current_Verbosity = High then
+            Write_Str ("Find_Source_Dirs (""");
+         end if;
+
+         String_To_Name_Buffer (From);
+         Directory    := Name_Buffer (1 .. Name_Len);
+         Directory_Id := Name_Find;
+
+         if Current_Verbosity = High then
+            Write_Str (Directory);
+            Write_Line (""")");
+         end if;
+
+         --  First, check if we are looking for a directory tree,
+         --  indicated by "/**" at the end.
+
+         if Directory'Length >= 3
+           and then Directory (Directory'Last - 1 .. Directory'Last) = "**"
+           and then (Directory (Directory'Last - 2) = '/'
+                       or else
+                     Directory (Directory'Last - 2) = Dir_Sep)
+         then
+            Name_Len := Directory'Length - 3;
+
+            if Name_Len = 0 then
+               --  This is the case of "/**": all directories
+               --  in the file system.
+
+               Name_Len := 1;
+               Name_Buffer (1) := Directory (Directory'First);
+
+            else
+               Name_Buffer (1 .. Name_Len) :=
+                 Directory (Directory'First .. Directory'Last - 3);
+            end if;
+
+            if Current_Verbosity = High then
+               Write_Str ("Looking for all subdirectories of """);
+               Write_Str (Name_Buffer (1 .. Name_Len));
+               Write_Line ("""");
+            end if;
+
+            declare
+               Base_Dir : constant Name_Id := Name_Find;
+               Root     : constant Name_Id :=
+                            Locate_Directory (Base_Dir, Data.Directory);
+
+            begin
+               if Root = No_Name then
+                  Error_Msg_Name_1 := Base_Dir;
+                  if Location = No_Location then
+                     Error_Msg ("{ is not a valid directory.", Data.Location);
+                  else
+                     Error_Msg ("{ is not a valid directory.", Location);
+                  end if;
+
+               else
+                  --  We have an existing directory,
+                  --  we register it and all of its subdirectories.
+
+                  if Current_Verbosity = High then
+                     Write_Line ("Looking for source directories:");
+                  end if;
+
+                  Start_String;
+                  Store_String_Chars (Get_Name_String (Root));
+                  Recursive_Find_Dirs (End_String);
+
+                  if Current_Verbosity = High then
+                     Write_Line ("End of looking for source directories.");
+                  end if;
+               end if;
+            end;
+
+         --  We have a single directory
+
+         else
+            declare
+               Path_Name : constant Name_Id :=
+                 Locate_Directory (Directory_Id, Data.Directory);
+
+            begin
+               if Path_Name = No_Name then
+                  Error_Msg_Name_1 := Directory_Id;
+                  if Location = No_Location then
+                     Error_Msg ("{ is not a valid directory", Data.Location);
+                  else
+                     Error_Msg ("{ is not a valid directory", Location);
+                  end if;
+               else
+
+                  --  As it is an existing directory, we add it to
+                  --  the list of directories.
+
+                  String_Elements.Increment_Last;
+                  Start_String;
+                  Store_String_Chars (Get_Name_String (Path_Name));
+                  Element.Value := End_String;
+
+                  if Last_Source_Dir = Nil_String then
+
+                     --  This is the first source directory
+
+                     Data.Source_Dirs := String_Elements.Last;
+
+                  else
+                     --  We already have source directories,
+                     --  link the previous last to the new one.
+
+                     String_Elements.Table (Last_Source_Dir).Next :=
+                       String_Elements.Last;
+                  end if;
+
+                  --  And register this source directory as the new last
+
+                  Last_Source_Dir := String_Elements.Last;
+                  String_Elements.Table (Last_Source_Dir) := Element;
+               end if;
+            end;
+         end if;
+      end Find_Source_Dirs;
+
+      ------------------
+      -- Find_Sources --
+      ------------------
+
+      procedure Find_Sources is
+         Source_Dir     : String_List_Id := Data.Source_Dirs;
+         Element        : String_Element;
+         Dir            : Dir_Type;
+         Current_Source : String_List_Id := Nil_String;
+
+      begin
+         if Current_Verbosity = High then
+            Write_Line ("Looking for sources:");
+         end if;
+
+         --  For each subdirectory
+
+         while Source_Dir /= Nil_String loop
+            begin
+               Element := String_Elements.Table (Source_Dir);
+               if Element.Value /= No_String then
+                  declare
+                     Source_Directory : String
+                       (1 .. Integer (String_Length (Element.Value)));
+                  begin
+                     String_To_Name_Buffer (Element.Value);
+                     Source_Directory := Name_Buffer (1 .. Name_Len);
+                     if Current_Verbosity = High then
+                        Write_Str ("Source_Dir = ");
+                        Write_Line (Source_Directory);
+                     end if;
+
+                     --  We look to every entry in the source directory
+
+                     Open (Dir, Source_Directory);
+
+                     loop
+                        Read (Dir, Name_Buffer, Name_Len);
+
+                        if Current_Verbosity = High then
+                           Write_Str  ("   Checking ");
+                           Write_Line (Name_Buffer (1 .. Name_Len));
+                        end if;
+
+                        exit when Name_Len = 0;
+
+                        declare
+                           Path_Access : constant GNAT.OS_Lib.String_Access :=
+                                           Locate_Regular_File
+                                             (Name_Buffer (1 .. Name_Len),
+                                              Source_Directory);
+
+                           File_Name : Name_Id;
+                           Path_Name : Name_Id;
+
+                        begin
+                           --  If it is a regular file
+
+                           if Path_Access /= null then
+                              File_Name := Name_Find;
+                              Name_Len := Path_Access'Length;
+                              Name_Buffer (1 .. Name_Len) := Path_Access.all;
+                              Path_Name := Name_Find;
+
+                              --  We attempt to register it as a source.
+                              --  However, there is no error if the file
+                              --  does not contain a valid source (as
+                              --  indicated by Error_If_Invalid => False).
+                              --  But there is an error if we have a
+                              --  duplicate unit name.
+
+                              Record_Source
+                                (File_Name        => File_Name,
+                                 Path_Name        => Path_Name,
+                                 Project          => Project,
+                                 Data             => Data,
+                                 Error_If_Invalid => False,
+                                 Location         => No_Location,
+                                 Current_Source   => Current_Source);
+
+                           else
+                              if Current_Verbosity = High then
+                                 Write_Line
+                                   ("      Not a regular file.");
+                              end if;
+                           end if;
+                        end;
+                     end loop;
+
+                     Close (Dir);
+                  end;
+               end if;
+
+            exception
+               when Directory_Error =>
+                  null;
+            end;
+
+            Source_Dir := Element.Next;
+         end loop;
+
+         if Current_Verbosity = High then
+            Write_Line ("end Looking for sources.");
+         end if;
+
+         --  If we have looked for sources and found none, then
+         --  it is an error. If a project is not supposed to contain
+         --  any source, then we never call Find_Sources.
+
+         if Current_Source = Nil_String then
+            Error_Msg ("there are no sources in this project",
+                       Data.Location);
+         end if;
+      end Find_Sources;
+
+      -------------------------------------
+      -- Get_Path_Name_And_Record_Source --
+      -------------------------------------
+
+      procedure Get_Path_Name_And_Record_Source
+        (File_Name        : String;
+         Location         : Source_Ptr;
+         Current_Source   : in out String_List_Id)
+      is
+         Source_Dir : String_List_Id := Data.Source_Dirs;
+         Element    : String_Element;
+         Path_Name  : GNAT.OS_Lib.String_Access;
+         Found      : Boolean := False;
+         File       : Name_Id;
+
+      begin
+         if Current_Verbosity = High then
+            Write_Str  ("   Checking """);
+            Write_Str  (File_Name);
+            Write_Line (""".");
+         end if;
+
+         --  We look in all source directories for this file name
+
+         while Source_Dir /= Nil_String loop
+            Element := String_Elements.Table (Source_Dir);
+
+            if Current_Verbosity = High then
+               Write_Str ("      """);
+               Write_Str (Get_Name_String (Element.Value));
+               Write_Str (""": ");
+            end if;
+
+            Path_Name :=
+              Locate_Regular_File
+              (File_Name,
+               Get_Name_String (Element.Value));
+
+            if Path_Name /= null then
+               if Current_Verbosity = High then
+                  Write_Line ("OK");
+               end if;
+
+               Name_Len := File_Name'Length;
+               Name_Buffer (1 .. Name_Len) := File_Name;
+               File := Name_Find;
+               Name_Len := Path_Name'Length;
+               Name_Buffer (1 .. Name_Len) := Path_Name.all;
+
+               --  We register the source.
+               --  We report an error if the file does not
+               --  correspond to a source.
+
+               Record_Source
+                 (File_Name        => File,
+                  Path_Name        => Name_Find,
+                  Project          => Project,
+                  Data             => Data,
+                  Error_If_Invalid => True,
+                  Location         => Location,
+                  Current_Source   => Current_Source);
+               Found := True;
+               exit;
+
+            else
+               if Current_Verbosity = High then
+                  Write_Line ("No");
+               end if;
+
+               Source_Dir := Element.Next;
+            end if;
+         end loop;
+
+         if not Found then
+            Name_Len := File_Name'Length;
+            Name_Buffer (1 .. Name_Len) := File_Name;
+            Error_Msg_Name_1 := Name_Find;
+            Error_Msg
+              ("cannot find source {", Location);
+         end if;
+      end Get_Path_Name_And_Record_Source;
+
+      ---------------------------
+      -- Get_Sources_From_File --
+      ---------------------------
+
+      procedure Get_Sources_From_File
+        (Path     : String;
+         Location : Source_Ptr)
+      is
+         File           : Prj.Util.Text_File;
+         Line           : String (1 .. 250);
+         Last           : Natural;
+         Current_Source : String_List_Id := Nil_String;
+
+         Nmb_Errors : constant Nat := Errors_Detected;
+
+      begin
+         if Current_Verbosity = High then
+            Write_Str  ("Opening """);
+            Write_Str  (Path);
+            Write_Line (""".");
+         end if;
+
+         --  We open the file
+
+         Prj.Util.Open (File, Path);
+
+         if not Prj.Util.Is_Valid (File) then
+            Error_Msg ("file does not exist", Location);
+         else
+            while not Prj.Util.End_Of_File (File) loop
+               Prj.Util.Get_Line (File, Line, Last);
+
+               --  If the line is not empty and does not start with "--",
+               --  then it must contains a file name.
+
+               if Last /= 0
+                 and then (Last = 1 or else Line (1 .. 2) /= "--")
+               then
+                  Get_Path_Name_And_Record_Source
+                    (File_Name => Line (1 .. Last),
+                     Location => Location,
+                     Current_Source => Current_Source);
+                  exit when Nmb_Errors /= Errors_Detected;
+               end if;
+            end loop;
+
+            Prj.Util.Close (File);
+
+         end if;
+
+         --  We should have found at least one source.
+         --  If not, report an error.
+
+         if Current_Source = Nil_String then
+            Error_Msg ("this project has no source", Location);
+         end if;
+      end Get_Sources_From_File;
+
+      --  Start of processing for Check_Naming_Scheme
+
+   begin
+
+      Error_Report := Report_Error;
+
+      if Current_Verbosity = High then
+         Write_Line ("Starting to look for directories");
+      end if;
+
+      --  Let's check the object directory
+
+      declare
+         Object_Dir : Variable_Value :=
+                        Util.Value_Of (Name_Object_Dir, Data.Decl.Attributes);
+
+      begin
+         pragma Assert (Object_Dir.Kind = Single,
+                        "Object_Dir is not a single string");
+
+         --  We set the object directory to its default
+
+         Data.Object_Directory := Data.Directory;
+
+         if not String_Equal (Object_Dir.Value, Empty_String) then
+
+            String_To_Name_Buffer (Object_Dir.Value);
+
+            if Name_Len = 0 then
+               Error_Msg ("Object_Dir cannot be empty",
+                          Object_Dir.Location);
+
+            else
+               --  We check that the specified object directory
+               --  does exist.
+
+               Canonical_Case_File_Name (Name_Buffer (1 .. Name_Len));
+
+               declare
+                  Dir_Id : constant Name_Id := Name_Find;
+
+               begin
+                  Data.Object_Directory :=
+                    Locate_Directory (Dir_Id, Data.Directory);
+
+                  if Data.Object_Directory = No_Name then
+                     Error_Msg_Name_1 := Dir_Id;
+                     Error_Msg
+                       ("the object directory { cannot be found",
+                        Data.Location);
+                  end if;
+               end;
+            end if;
+         end if;
+      end;
+
+      if Current_Verbosity = High then
+         if Data.Object_Directory = No_Name then
+            Write_Line ("No object directory");
+         else
+            Write_Str ("Object directory: """);
+            Write_Str (Get_Name_String (Data.Object_Directory));
+            Write_Line ("""");
+         end if;
+      end if;
+
+      --  Let's check the source directories
+
+      declare
+         Source_Dirs : Variable_Value :=
+           Util.Value_Of (Name_Source_Dirs, Data.Decl.Attributes);
+
+      begin
+
+         if Current_Verbosity = High then
+            Write_Line ("Starting to look for source directories");
+         end if;
+
+         pragma Assert (Source_Dirs.Kind = List,
+                          "Source_Dirs is not a list");
+
+         if Source_Dirs.Default then
+
+            --  No Source_Dirs specified: the single source directory
+            --  is the one containing the project file
+
+            String_Elements.Increment_Last;
+            Data.Source_Dirs := String_Elements.Last;
+            Start_String;
+            Store_String_Chars (Get_Name_String (Data.Directory));
+            String_Elements.Table (Data.Source_Dirs) :=
+              (Value    => End_String,
+               Location => No_Location,
+               Next     => Nil_String);
+
+            if Current_Verbosity = High then
+               Write_Line ("(Undefined) Single object directory:");
+               Write_Str ("    """);
+               Write_Str (Get_Name_String (Data.Directory));
+               Write_Line ("""");
+            end if;
+
+         elsif Source_Dirs.Values = Nil_String then
+
+            --  If Source_Dirs is an empty string list, this means
+            --  that this project contains no source.
+
+            if Data.Object_Directory = Data.Directory then
+               Data.Object_Directory := No_Name;
+            end if;
+
+            Data.Source_Dirs := Nil_String;
+
+         else
+            declare
+               Source_Dir : String_List_Id := Source_Dirs.Values;
+               Element    : String_Element;
+
+            begin
+               --  We will find the source directories for each
+               --  element of the list
+
+               while Source_Dir /= Nil_String loop
+                  Element := String_Elements.Table (Source_Dir);
+                  Find_Source_Dirs (Element.Value, Element.Location);
+                  Source_Dir := Element.Next;
+               end loop;
+            end;
+         end if;
+
+         if Current_Verbosity = High then
+            Write_Line ("Puting source directories in canonical cases");
+         end if;
+
+         declare
+            Current : String_List_Id := Data.Source_Dirs;
+            Element : String_Element;
+
+         begin
+            while Current /= Nil_String loop
+               Element := String_Elements.Table (Current);
+               if Element.Value /= No_String then
+                  String_To_Name_Buffer (Element.Value);
+                  Canonical_Case_File_Name (Name_Buffer (1 .. Name_Len));
+                  Start_String;
+                  Store_String_Chars (Name_Buffer (1 .. Name_Len));
+                  Element.Value := End_String;
+                  String_Elements.Table (Current) := Element;
+               end if;
+
+               Current := Element.Next;
+            end loop;
+         end;
+      end;
+
+      --  Library Dir, Name, Version and Kind
+
+      declare
+         Attributes : constant Prj.Variable_Id := Data.Decl.Attributes;
+
+         Lib_Dir : Prj.Variable_Value :=
+                     Prj.Util.Value_Of (Snames.Name_Library_Dir, Attributes);
+
+         Lib_Name : Prj.Variable_Value :=
+                      Prj.Util.Value_Of (Snames.Name_Library_Name, Attributes);
+
+         Lib_Version : Prj.Variable_Value :=
+                         Prj.Util.Value_Of
+                           (Snames.Name_Library_Version, Attributes);
+
+         The_Lib_Kind : Prj.Variable_Value :=
+                          Prj.Util.Value_Of
+                            (Snames.Name_Library_Kind, Attributes);
+
+      begin
+         pragma Assert (Lib_Dir.Kind = Single);
+
+         if Lib_Dir.Value = Empty_String then
+
+            if Current_Verbosity = High then
+               Write_Line ("No library directory");
+            end if;
+
+         else
+            --  Find path name, check that it is a directory
+
+            Stringt.String_To_Name_Buffer (Lib_Dir.Value);
+
+            declare
+               Dir_Id : constant Name_Id := Name_Find;
+
+            begin
+               Data.Library_Dir :=
+                 Locate_Directory (Dir_Id, Data.Directory);
+
+               if Data.Library_Dir = No_Name then
+                  Error_Msg ("not an existing directory",
+                             Lib_Dir.Location);
+
+               elsif Data.Library_Dir = Data.Object_Directory then
+                  Error_Msg
+                    ("library directory cannot be the same " &
+                     "as object directory",
+                     Lib_Dir.Location);
+                  Data.Library_Dir := No_Name;
+
+               else
+                  if Current_Verbosity = High then
+                     Write_Str ("Library directory =""");
+                     Write_Str (Get_Name_String (Data.Library_Dir));
+                     Write_Line ("""");
+                  end if;
+               end if;
+            end;
+         end if;
+
+         pragma Assert (Lib_Name.Kind = Single);
+
+         if Lib_Name.Value = Empty_String then
+            if Current_Verbosity = High then
+               Write_Line ("No library name");
+            end if;
+
+         else
+            Stringt.String_To_Name_Buffer (Lib_Name.Value);
+
+            if not Is_Letter (Name_Buffer (1)) then
+               Error_Msg ("must start with a letter",
+                          Lib_Name.Location);
+
+            else
+               Data.Library_Name := Name_Find;
+
+               for Index in 2 .. Name_Len loop
+                  if not Is_Alphanumeric (Name_Buffer (Index)) then
+                     Data.Library_Name := No_Name;
+                     Error_Msg ("only letters and digits are allowed",
+                                Lib_Name.Location);
+                     exit;
+                  end if;
+               end loop;
+
+               if Data.Library_Name /= No_Name
+                 and then Current_Verbosity = High then
+                  Write_Str ("Library name = """);
+                  Write_Str (Get_Name_String (Data.Library_Name));
+                  Write_Line ("""");
+               end if;
+            end if;
+         end if;
+
+         Data.Library :=
+           Data.Library_Dir /= No_Name
+             and then
+           Data.Library_Name /= No_Name;
+
+         if Data.Library then
+            if Current_Verbosity = High then
+               Write_Line ("This is a library project file");
+            end if;
+
+            pragma Assert (Lib_Version.Kind = Single);
+
+            if Lib_Version.Value = Empty_String then
+               if Current_Verbosity = High then
+                  Write_Line ("No library version specified");
+               end if;
+
+            else
+               Stringt.String_To_Name_Buffer (Lib_Version.Value);
+               Data.Lib_Internal_Name := Name_Find;
+            end if;
+
+            pragma Assert (The_Lib_Kind.Kind = Single);
+
+            if The_Lib_Kind.Value = Empty_String then
+               if Current_Verbosity = High then
+                  Write_Line ("No library kind specified");
+               end if;
+
+            else
+               Stringt.String_To_Name_Buffer (The_Lib_Kind.Value);
+
+               declare
+                  Kind_Name : constant String :=
+                                Ada.Characters.Handling.To_Lower
+                                  (Name_Buffer (1 .. Name_Len));
+
+                  OK : Boolean := True;
+
+               begin
+                  if Kind_Name = "static" then
+                     Data.Library_Kind := Static;
+
+                  elsif Kind_Name = "dynamic" then
+                     Data.Library_Kind := Dynamic;
+
+                  elsif Kind_Name = "relocatable" then
+                     Data.Library_Kind := Relocatable;
+
+                  else
+                     Error_Msg
+                       ("illegal value for Library_Kind",
+                        The_Lib_Kind.Location);
+                     OK := False;
+                  end if;
+
+                  if Current_Verbosity = High and then OK then
+                     Write_Str ("Library kind = ");
+                     Write_Line (Kind_Name);
+                  end if;
+               end;
+            end if;
+         end if;
+      end;
+
+      if Current_Verbosity = High then
+         Show_Source_Dirs (Project);
+      end if;
+
+      declare
+         Naming_Id : constant Package_Id :=
+                       Util.Value_Of (Name_Naming, Data.Decl.Packages);
+
+         Naming : Package_Element;
+
+      begin
+         --  If there is a package Naming, we will put in Data.Naming
+         --  what is in this package Naming.
+
+         if Naming_Id /= No_Package then
+            Naming := Packages.Table (Naming_Id);
+
+            if Current_Verbosity = High then
+               Write_Line ("Checking ""Naming"".");
+            end if;
+
+            declare
+               Bodies : constant Array_Element_Id :=
+                          Util.Value_Of (Name_Body_Part, Naming.Decl.Arrays);
+
+               Specifications : constant Array_Element_Id :=
+                                  Util.Value_Of
+                                    (Name_Specification, Naming.Decl.Arrays);
+
+            begin
+               if Bodies /= No_Array_Element then
+
+                  --  We have elements in the array Body_Part
+
+                  if Current_Verbosity = High then
+                     Write_Line ("Found Bodies.");
+                  end if;
+
+                  Data.Naming.Bodies := Bodies;
+                  Check_Unit_Names (Bodies);
+
+               else
+                  if Current_Verbosity = High then
+                     Write_Line ("No Bodies.");
+                  end if;
+               end if;
+
+               if Specifications /= No_Array_Element then
+
+                  --  We have elements in the array Specification
+
+                  if Current_Verbosity = High then
+                     Write_Line ("Found Specifications.");
+                  end if;
+
+                  Data.Naming.Specifications := Specifications;
+                  Check_Unit_Names (Specifications);
+
+               else
+                  if Current_Verbosity = High then
+                     Write_Line ("No Specifications.");
+                  end if;
+               end if;
+            end;
+
+            --  We are now checking if variables Dot_Replacement, Casing,
+            --  Specification_Append, Body_Append and/or Separate_Append
+            --  exist.
+            --  For each variable, if it does not exist, we do nothing,
+            --  because we already have the default.
+
+            --  Let's check Dot_Replacement
+
+            declare
+               Dot_Replacement : constant Variable_Value :=
+                                   Util.Value_Of
+                                     (Name_Dot_Replacement,
+                                      Naming.Decl.Attributes);
+
+            begin
+               pragma Assert (Dot_Replacement.Kind = Single,
+                              "Dot_Replacement is not a single string");
+
+               if not Dot_Replacement.Default then
+
+                  String_To_Name_Buffer (Dot_Replacement.Value);
+
+                  if Name_Len = 0 then
+                     Error_Msg ("Dot_Replacement cannot be empty",
+                                Dot_Replacement.Location);
+
+                  else
+                     Canonical_Case_File_Name (Name_Buffer (1 .. Name_Len));
+                     Data.Naming.Dot_Replacement := Name_Find;
+                     Data.Naming.Dot_Repl_Loc := Dot_Replacement.Location;
+                  end if;
+
+               end if;
+
+            end;
+
+            if Current_Verbosity = High then
+               Write_Str  ("  Dot_Replacement = """);
+               Write_Str  (Get_Name_String (Data.Naming.Dot_Replacement));
+               Write_Char ('"');
+               Write_Eol;
+            end if;
+
+            --  Check Casing
+
+            declare
+               Casing_String : constant Variable_Value :=
+                 Util.Value_Of (Name_Casing, Naming.Decl.Attributes);
+
+            begin
+               pragma Assert (Casing_String.Kind = Single,
+                              "Dot_Replacement is not a single string");
+
+               if not Casing_String.Default then
+                  declare
+                     Casing_Image : constant String :=
+                                      Get_Name_String (Casing_String.Value);
+
+                  begin
+                     declare
+                        Casing : constant Casing_Type :=
+                          Value (Casing_Image);
+
+                     begin
+                        Data.Naming.Casing := Casing;
+                     end;
+
+                  exception
+                     when Constraint_Error =>
+                        if Casing_Image'Length = 0 then
+                           Error_Msg ("Casing cannot be an empty string",
+                                      Casing_String.Location);
+
+                        else
+                           Name_Len := Casing_Image'Length;
+                           Name_Buffer (1 .. Name_Len) := Casing_Image;
+                           Error_Msg_Name_1 := Name_Find;
+                           Error_Msg
+                             ("{ is not a correct Casing",
+                              Casing_String.Location);
+                        end if;
+                  end;
+               end if;
+            end;
+
+            if Current_Verbosity = High then
+               Write_Str  ("  Casing = ");
+               Write_Str  (Image (Data.Naming.Casing));
+               Write_Char ('.');
+               Write_Eol;
+            end if;
+
+            --  Let's check Specification_Append
+
+            declare
+               Specification_Append : constant Variable_Value :=
+                                        Util.Value_Of
+                                          (Name_Specification_Append,
+                                           Naming.Decl.Attributes);
+
+            begin
+               pragma Assert (Specification_Append.Kind = Single,
+                              "Specification_Append is not a single string");
+
+               if not Specification_Append.Default then
+                  String_To_Name_Buffer (Specification_Append.Value);
+
+                  if Name_Len = 0 then
+                     Error_Msg ("Specification_Append cannot be empty",
+                                Specification_Append.Location);
+
+                  else
+                     Canonical_Case_File_Name (Name_Buffer (1 .. Name_Len));
+                     Data.Naming.Specification_Append := Name_Find;
+                     Data.Naming.Spec_Append_Loc :=
+                       Specification_Append.Location;
+                  end if;
+               end if;
+            end;
+
+            if Current_Verbosity = High then
+               Write_Str  ("  Specification_Append = """);
+               Write_Str  (Get_Name_String (Data.Naming.Specification_Append));
+               Write_Line (""".");
+            end if;
+
+            --  Check Body_Append
+
+            declare
+               Body_Append : constant Variable_Value :=
+                               Util.Value_Of
+                                 (Name_Body_Append, Naming.Decl.Attributes);
+
+            begin
+               pragma Assert (Body_Append.Kind = Single,
+                              "Body_Append is not a single string");
+
+               if not Body_Append.Default then
+
+                  String_To_Name_Buffer (Body_Append.Value);
+
+                  if Name_Len = 0 then
+                     Error_Msg ("Body_Append cannot be empty",
+                                Body_Append.Location);
+
+                  else
+                     Canonical_Case_File_Name (Name_Buffer (1 .. Name_Len));
+                     Data.Naming.Body_Append := Name_Find;
+                     Data.Naming.Body_Append_Loc := Body_Append.Location;
+
+                     --  As we have a new Body_Append, we set Separate_Append
+                     --  to the same value.
+
+                     Data.Naming.Separate_Append := Data.Naming.Body_Append;
+                     Data.Naming.Sep_Append_Loc := Data.Naming.Body_Append_Loc;
+                  end if;
+               end if;
+            end;
+
+            if Current_Verbosity = High then
+               Write_Str  ("  Body_Append = """);
+               Write_Str  (Get_Name_String (Data.Naming.Body_Append));
+               Write_Line (""".");
+            end if;
+
+            --  Check Separate_Append
+
+            declare
+               Separate_Append : constant Variable_Value :=
+                                   Util.Value_Of
+                                     (Name_Separate_Append,
+                                      Naming.Decl.Attributes);
+
+            begin
+               pragma Assert (Separate_Append.Kind = Single,
+                             "Separate_Append is not a single string");
+
+               if not Separate_Append.Default then
+                  String_To_Name_Buffer (Separate_Append.Value);
+
+                  if Name_Len = 0 then
+                     Error_Msg ("Separate_Append cannot be empty",
+                                Separate_Append.Location);
+
+                  else
+                     Canonical_Case_File_Name (Name_Buffer (1 .. Name_Len));
+                     Data.Naming.Separate_Append := Name_Find;
+                     Data.Naming.Sep_Append_Loc := Separate_Append.Location;
+                  end if;
+               end if;
+            end;
+
+            if Current_Verbosity = High then
+               Write_Str  ("  Separate_Append = """);
+               Write_Str  (Get_Name_String (Data.Naming.Separate_Append));
+               Write_Line (""".");
+               Write_Line ("end Naming.");
+            end if;
+
+            --  Now, we check if Data.Naming is valid
+
+            Check_Naming_Scheme (Data.Naming);
+         end if;
+      end;
+
+      --  If we have source directories, then let's find the sources.
+
+      if Data.Source_Dirs /= Nil_String then
+         declare
+            Sources : constant Variable_Value :=
+                        Util.Value_Of
+                          (Name_Source_Files,
+                           Data.Decl.Attributes);
+
+            Source_List_File : constant Variable_Value :=
+                                 Util.Value_Of
+                                   (Name_Source_List_File,
+                                    Data.Decl.Attributes);
+
+         begin
+            pragma Assert
+              (Sources.Kind = List,
+               "Source_Files is not a list");
+            pragma Assert
+              (Source_List_File.Kind = Single,
+               "Source_List_File is not a single string");
+
+            if not Sources.Default then
+               if not Source_List_File.Default then
+                  Error_Msg
+                    ("?both variables source_files and " &
+                     "source_list_file are present",
+                     Source_List_File.Location);
+               end if;
+
+               --  Sources is a list of file names
+
+               declare
+                  Current_Source : String_List_Id := Nil_String;
+                  Current        : String_List_Id := Sources.Values;
+                  Element        : String_Element;
+
+               begin
+                  while Current /= Nil_String loop
+                     Element := String_Elements.Table (Current);
+                     String_To_Name_Buffer (Element.Value);
+
+                     declare
+                        File_Name : constant String :=
+                          Name_Buffer (1 .. Name_Len);
+
+                     begin
+                        Get_Path_Name_And_Record_Source
+                          (File_Name        => File_Name,
+                           Location         => Element.Location,
+                           Current_Source   => Current_Source);
+                        Current := Element.Next;
+                     end;
+                  end loop;
+               end;
+
+               --  No source_files specified.
+               --  We check Source_List_File has been specified.
+
+            elsif not Source_List_File.Default then
+
+               --  Source_List_File is the name of the file
+               --  that contains the source file names
+
+               declare
+                  Source_File_Path_Name : constant String :=
+                                            Path_Name_Of
+                                              (Source_List_File.Value,
+                                               Data.Directory);
+
+               begin
+                  if Source_File_Path_Name'Length = 0 then
+                     String_To_Name_Buffer (Source_List_File.Value);
+                     Error_Msg_Name_1 := Name_Find;
+                     Error_Msg
+                       ("file with sources { does not exist",
+                        Source_List_File.Location);
+
+                  else
+                     Get_Sources_From_File
+                       (Source_File_Path_Name,
+                        Source_List_File.Location);
+                  end if;
+               end;
+
+            else
+               --  Neither Source_Files nor Source_List_File has been
+               --  specified.
+               --  Find all the files that satisfy
+               --  the naming scheme in all the source directories.
+
+               Find_Sources;
+            end if;
+         end;
+      end if;
+
+      Projects.Table (Project) := Data;
+   end Check_Naming_Scheme;
+
+   ---------------
+   -- Error_Msg --
+   ---------------
+
+   procedure Error_Msg (Msg : String; Flag_Location : Source_Ptr) is
+   begin
+      if Error_Report = null then
+         Errout.Error_Msg (Msg, Flag_Location);
+
+      else
+         declare
+            Error_Buffer : String (1 .. 5_000);
+            Error_Last   : Natural := 0;
+            Msg_Name     : Natural := 0;
+            First        : Positive := Msg'First;
+
+            procedure Add (C : Character);
+            --  Add a character to the buffer
+
+            procedure Add (S : String);
+            --  Add a string to the buffer
+
+            procedure Add (Id : Name_Id);
+            --  Add a name to the buffer
+
+            ---------
+            -- Add --
+            ---------
+
+            procedure Add (C : Character) is
+            begin
+               Error_Last := Error_Last + 1;
+               Error_Buffer (Error_Last) := C;
+            end Add;
+
+            procedure Add (S : String) is
+            begin
+               Error_Buffer (Error_Last + 1 .. Error_Last + S'Length) := S;
+               Error_Last := Error_Last + S'Length;
+            end Add;
+
+            procedure Add (Id : Name_Id) is
+            begin
+               Get_Name_String (Id);
+               Add (Name_Buffer (1 .. Name_Len));
+            end Add;
+
+         begin
+            if Msg (First) = '\' then
+               --  Continuation character, ignore.
+               First := First + 1;
+
+            elsif Msg (First) = '?' then
+               --  Warning character. It is always the first one,
+               --  in this package.
+               First := First + 1;
+               Add ("Warning: ");
+            end if;
+
+            for Index in First .. Msg'Last loop
+               if Msg (Index) = '{' or else Msg (Index) = '%' then
+                  --  Include a name between double quotes.
+                  Msg_Name := Msg_Name + 1;
+                  Add ('"');
+
+                  case Msg_Name is
+                     when 1 => Add (Error_Msg_Name_1);
+
+                     when 2 => Add (Error_Msg_Name_2);
+
+                     when 3 => Add (Error_Msg_Name_3);
+
+                     when others => null;
+                  end case;
+
+                  Add ('"');
+
+               else
+                  Add (Msg (Index));
+               end if;
+
+            end loop;
+
+            Error_Report (Error_Buffer (1 .. Error_Last));
+         end;
+      end if;
+   end Error_Msg;
+
+   ---------------------
+   -- Get_Name_String --
+   ---------------------
+
+   function Get_Name_String (S : String_Id) return String is
+   begin
+      if S = No_String then
+         return "";
+      else
+         String_To_Name_Buffer (S);
+         return Name_Buffer (1 .. Name_Len);
+      end if;
+   end Get_Name_String;
+
+   --------------
+   -- Get_Unit --
+   --------------
+
+   procedure Get_Unit
+     (File_Name    : Name_Id;
+      Naming       : Naming_Data;
+      Unit_Name    : out Name_Id;
+      Unit_Kind    : out Spec_Or_Body;
+      Needs_Pragma : out Boolean)
+   is
+      Canonical_Case_Name : Name_Id;
+
+   begin
+      Needs_Pragma := False;
+      Get_Name_String (File_Name);
+      Canonical_Case_File_Name (Name_Buffer (1 .. Name_Len));
+      Canonical_Case_Name := Name_Find;
+
+      if Naming.Bodies /= No_Array_Element then
+
+         --  There are some specified file names for some bodies
+         --  of this project. Find out if File_Name is one of these bodies.
+
+         declare
+            Current : Array_Element_Id := Naming.Bodies;
+            Element : Array_Element;
+
+         begin
+            while Current /= No_Array_Element loop
+               Element := Array_Elements.Table (Current);
+
+               if Element.Index /= No_Name then
+                  String_To_Name_Buffer (Element.Value.Value);
+                  Canonical_Case_File_Name (Name_Buffer (1 .. Name_Len));
+
+                  if Canonical_Case_Name = Name_Find then
+
+                     --  File_Name corresponds to one body.
+                     --  So, we know it is a body, and we know the unit name.
+
+                     Unit_Kind := Body_Part;
+                     Unit_Name := Element.Index;
+                     Needs_Pragma := True;
+                     return;
+                  end if;
+               end if;
+
+               Current := Element.Next;
+            end loop;
+         end;
+      end if;
+
+      if Naming.Specifications /= No_Array_Element then
+
+         --  There are some specified file names for some bodiesspecifications
+         --  of this project. Find out if File_Name is one of these
+         --  specifications.
+
+         declare
+            Current : Array_Element_Id := Naming.Specifications;
+            Element : Array_Element;
+
+         begin
+            while Current /= No_Array_Element loop
+               Element := Array_Elements.Table (Current);
+
+               if Element.Index /= No_Name then
+                  String_To_Name_Buffer (Element.Value.Value);
+                  Canonical_Case_File_Name (Name_Buffer (1 .. Name_Len));
+
+                  if Canonical_Case_Name = Name_Find then
+
+                     --  File_Name corresponds to one specification.
+                     --  So, we know it is a spec, and we know the unit name.
+
+                     Unit_Kind := Specification;
+                     Unit_Name := Element.Index;
+                     Needs_Pragma := True;
+                     return;
+                  end if;
+
+               end if;
+
+               Current := Element.Next;
+            end loop;
+         end;
+      end if;
+
+      declare
+         File  : String   := Get_Name_String (Canonical_Case_Name);
+         First : Positive := File'First;
+         Last  : Natural  := File'Last;
+
+      begin
+         --  Check if the end of the file name is Specification_Append
+
+         Get_Name_String (Naming.Specification_Append);
+
+         if File'Length > Name_Len
+           and then File (Last - Name_Len + 1 .. Last) =
+                                                Name_Buffer (1 .. Name_Len)
+         then
+            --  We have a spec
+
+            Unit_Kind := Specification;
+            Last := Last - Name_Len;
+
+            if Current_Verbosity = High then
+               Write_Str  ("   Specification: ");
+               Write_Line (File (First .. Last));
+            end if;
+
+         else
+            Get_Name_String (Naming.Body_Append);
+
+            --  Check if the end of the file name is Body_Append
+
+            if File'Length > Name_Len
+              and then File (Last - Name_Len + 1 .. Last) =
+                                                Name_Buffer (1 .. Name_Len)
+            then
+               --  We have a body
+
+               Unit_Kind := Body_Part;
+               Last := Last - Name_Len;
+
+               if Current_Verbosity = High then
+                  Write_Str  ("   Body: ");
+                  Write_Line (File (First .. Last));
+               end if;
+
+            elsif Naming.Separate_Append /= Naming.Body_Append then
+               Get_Name_String (Naming.Separate_Append);
+
+               --  Check if the end of the file name is Separate_Append
+
+               if File'Length > Name_Len
+                 and then File (Last - Name_Len + 1 .. Last) =
+                                                Name_Buffer (1 .. Name_Len)
+               then
+                  --  We have a separate (a body)
+
+                  Unit_Kind := Body_Part;
+                  Last := Last - Name_Len;
+
+                  if Current_Verbosity = High then
+                     Write_Str  ("   Separate: ");
+                     Write_Line (File (First .. Last));
+                  end if;
+
+               else
+                  Last := 0;
+               end if;
+
+            else
+               Last := 0;
+            end if;
+         end if;
+
+         if Last = 0 then
+
+            --  This is not a source file
+
+            Unit_Name := No_Name;
+            Unit_Kind := Specification;
+
+            if Current_Verbosity = High then
+               Write_Line ("   Not a valid file name.");
+            end if;
+
+            return;
+         end if;
+
+         Get_Name_String (Naming.Dot_Replacement);
+
+         if Name_Buffer (1 .. Name_Len) /= "." then
+
+            --  If Dot_Replacement is not a single dot,
+            --  then there should not be any dot in the name.
+
+            for Index in First .. Last loop
+               if File (Index) = '.' then
+                  if Current_Verbosity = High then
+                     Write_Line
+                       ("   Not a valid file name (some dot not replaced).");
+                  end if;
+
+                  Unit_Name := No_Name;
+                  return;
+
+               end if;
+            end loop;
+
+            --  Replace the substring Dot_Replacement with dots
+
+            declare
+               Index : Positive := First;
+
+            begin
+               while Index <= Last - Name_Len + 1 loop
+
+                  if File (Index .. Index + Name_Len - 1) =
+                    Name_Buffer (1 .. Name_Len)
+                  then
+                     File (Index) := '.';
+
+                     if Name_Len > 1 and then Index < Last then
+                        File (Index + 1 .. Last - Name_Len + 1) :=
+                          File (Index + Name_Len .. Last);
+                     end if;
+
+                     Last := Last - Name_Len + 1;
+                  end if;
+
+                  Index := Index + 1;
+               end loop;
+            end;
+         end if;
+
+         --  Check if the casing is right
+
+         declare
+            Src : String := File (First .. Last);
+
+         begin
+            case Naming.Casing is
+               when All_Lower_Case =>
+                  Fixed.Translate
+                    (Source  => Src,
+                     Mapping => Lower_Case_Map);
+
+               when All_Upper_Case =>
+                  Fixed.Translate
+                    (Source  => Src,
+                     Mapping => Upper_Case_Map);
+
+               when Mixed_Case | Unknown =>
+                  null;
+            end case;
+
+            if Src /= File (First .. Last) then
+               if Current_Verbosity = High then
+                  Write_Line ("   Not a valid file name (casing).");
+               end if;
+
+               Unit_Name := No_Name;
+               return;
+            end if;
+
+            --  We put the name in lower case
+
+            Fixed.Translate
+              (Source  => Src,
+               Mapping => Lower_Case_Map);
+
+            if Current_Verbosity = High then
+               Write_Str  ("      ");
+               Write_Line (Src);
+            end if;
+
+            Name_Len := Src'Length;
+            Name_Buffer (1 .. Name_Len) := Src;
+
+            --  Now, we check if this name is a valid unit name
+
+            Check_Naming_Scheme (Name => Name_Find, Unit => Unit_Name);
+         end;
+
+      end;
+
+   end Get_Unit;
+
+   -----------------------
+   -- Is_Illegal_Append --
+   -----------------------
+
+   function Is_Illegal_Append (This : String) return Boolean is
+   begin
+      return This'Length = 0
+        or else Is_Alphanumeric (This (This'First))
+        or else (This'Length >= 2
+                 and then This (This'First) = '_'
+                 and then Is_Alphanumeric (This (This'First + 1)));
+   end Is_Illegal_Append;
+
+   ----------------------
+   -- Locate_Directory --
+   ----------------------
+
+   function Locate_Directory
+     (Name   : Name_Id;
+      Parent : Name_Id)
+     return   Name_Id
+   is
+      The_Name   : constant String := Get_Name_String (Name);
+      The_Parent : constant String :=
+                     Get_Name_String (Parent) & Dir_Sep;
+
+      The_Parent_Last : Positive := The_Parent'Last;
+
+   begin
+      if The_Parent'Length > 1
+        and then (The_Parent (The_Parent_Last - 1) = Dir_Sep
+                    or else The_Parent (The_Parent_Last - 1) = '/')
+      then
+         The_Parent_Last := The_Parent_Last - 1;
+      end if;
+
+      if Current_Verbosity = High then
+         Write_Str ("Locate_Directory (""");
+         Write_Str (The_Name);
+         Write_Str (""", """);
+         Write_Str (The_Parent);
+         Write_Line (""")");
+      end if;
+
+      if Is_Absolute_Path (The_Name) then
+         if Is_Directory (The_Name) then
+            return Name;
+         end if;
+
+      else
+         declare
+            Full_Path : constant String :=
+                          The_Parent (The_Parent'First .. The_Parent_Last) &
+                                                                     The_Name;
+
+         begin
+            if Is_Directory (Full_Path) then
+               Name_Len := Full_Path'Length;
+               Name_Buffer (1 .. Name_Len) := Full_Path;
+               return Name_Find;
+            end if;
+         end;
+
+      end if;
+
+      return No_Name;
+   end Locate_Directory;
+
+   ------------------
+   -- Path_Name_Of --
+   ------------------
+
+   function Path_Name_Of
+     (File_Name : String_Id;
+      Directory : String_Id)
+      return      String
+   is
+      Result : String_Access;
+
+   begin
+      String_To_Name_Buffer (File_Name);
+
+      declare
+         The_File_Name : constant String := Name_Buffer (1 .. Name_Len);
+
+      begin
+         String_To_Name_Buffer (Directory);
+         Result := Locate_Regular_File
+           (File_Name => The_File_Name,
+            Path      => Name_Buffer (1 .. Name_Len));
+      end;
+
+      if Result = null then
+         return "";
+      else
+         Canonical_Case_File_Name (Result.all);
+         return Result.all;
+      end if;
+   end Path_Name_Of;
+
+   function Path_Name_Of
+     (File_Name : String_Id;
+      Directory : Name_Id)
+     return      String
+   is
+      Result : String_Access;
+      The_Directory : constant String := Get_Name_String (Directory);
+
+   begin
+      String_To_Name_Buffer (File_Name);
+      Result := Locate_Regular_File
+        (File_Name => Name_Buffer (1 .. Name_Len),
+         Path      => The_Directory);
+
+      if Result = null then
+         return "";
+      else
+         Canonical_Case_File_Name (Result.all);
+         return Result.all;
+      end if;
+   end Path_Name_Of;
+
+   -------------------
+   -- Record_Source --
+   -------------------
+
+   procedure Record_Source
+     (File_Name        : Name_Id;
+      Path_Name        : Name_Id;
+      Project          : Project_Id;
+      Data             : in out Project_Data;
+      Error_If_Invalid : Boolean;
+      Location         : Source_Ptr;
+      Current_Source   : in out String_List_Id)
+   is
+      Unit_Name    : Name_Id;
+      Unit_Kind    : Spec_Or_Body;
+      Needs_Pragma : Boolean;
+      The_Location : Source_Ptr := Location;
+
+   begin
+      --  Find out the unit name, the unit kind and if it needs
+      --  a specific SFN pragma.
+
+      Get_Unit
+        (File_Name    => File_Name,
+         Naming       => Data.Naming,
+         Unit_Name    => Unit_Name,
+         Unit_Kind    => Unit_Kind,
+         Needs_Pragma => Needs_Pragma);
+
+      --  If it is not a source file, report an error only if
+      --  Error_If_Invalid is true.
+
+      if Unit_Name = No_Name then
+         if Error_If_Invalid then
+            Error_Msg_Name_1 := File_Name;
+            Error_Msg
+              ("{ is not a valid source file name",
+               Location);
+
+         else
+            if Current_Verbosity = High then
+               Write_Str  ("   """);
+               Write_Str  (Get_Name_String (File_Name));
+               Write_Line (""" is not a valid source file name (ignored).");
+            end if;
+         end if;
+
+      else
+         --  Put the file name in the list of sources of the project
+
+         String_Elements.Increment_Last;
+         Get_Name_String (File_Name);
+         Start_String;
+         Store_String_Chars (Name_Buffer (1 .. Name_Len));
+         String_Elements.Table (String_Elements.Last) :=
+           (Value    => End_String,
+            Location => No_Location,
+            Next     => Nil_String);
+
+         if Current_Source = Nil_String then
+            Data.Sources := String_Elements.Last;
+
+         else
+            String_Elements.Table (Current_Source).Next :=
+              String_Elements.Last;
+         end if;
+
+         Current_Source := String_Elements.Last;
+
+         --  Put the unit in unit list
+
+         declare
+            The_Unit      : Unit_Id := Units_Htable.Get (Unit_Name);
+            The_Unit_Data : Unit_Data;
+
+         begin
+            if Current_Verbosity = High then
+               Write_Str  ("Putting ");
+               Write_Str  (Get_Name_String (Unit_Name));
+               Write_Line (" in the unit list.");
+            end if;
+
+            --  The unit is already in the list, but may be it is
+            --  only the other unit kind (spec or body), or what is
+            --  in the unit list is a unit of a project we are modifying.
+
+            if The_Unit /= Prj.Com.No_Unit then
+               The_Unit_Data := Units.Table (The_Unit);
+
+               if The_Unit_Data.File_Names (Unit_Kind).Name = No_Name
+                 or else (Data.Modifies /= No_Project
+                            and then
+                          The_Unit_Data.File_Names (Unit_Kind).Project =
+                                                            Data.Modifies)
+               then
+                  The_Unit_Data.File_Names (Unit_Kind) :=
+                    (Name         => File_Name,
+                     Path         => Path_Name,
+                     Project      => Project,
+                     Needs_Pragma => Needs_Pragma);
+                  Units.Table (The_Unit) := The_Unit_Data;
+
+               else
+                  --  It is an error to have two units with the same name
+                  --  and the same kind (spec or body).
+
+                  if The_Location = No_Location then
+                     The_Location := Projects.Table (Project).Location;
+                  end if;
+
+                  Error_Msg_Name_1 := Unit_Name;
+                  Error_Msg ("duplicate source {", The_Location);
+
+                  Error_Msg_Name_1 :=
+                    Projects.Table
+                      (The_Unit_Data.File_Names (Unit_Kind).Project).Name;
+                  Error_Msg_Name_2 :=
+                    The_Unit_Data.File_Names (Unit_Kind).Path;
+                  Error_Msg ("\   project file {, {", The_Location);
+
+                  Error_Msg_Name_1 := Projects.Table (Project).Name;
+                  Error_Msg_Name_2 := Path_Name;
+                  Error_Msg ("\   project file {, {", The_Location);
+
+               end if;
+
+            --  It is a new unit, create a new record
+
+            else
+               Units.Increment_Last;
+               The_Unit := Units.Last;
+               Units_Htable.Set (Unit_Name, The_Unit);
+               The_Unit_Data.Name := Unit_Name;
+               The_Unit_Data.File_Names (Unit_Kind) :=
+                 (Name         => File_Name,
+                  Path         => Path_Name,
+                  Project      => Project,
+                  Needs_Pragma => Needs_Pragma);
+               Units.Table (The_Unit) := The_Unit_Data;
+            end if;
+         end;
+      end if;
+   end Record_Source;
+
+   ----------------------
+   -- Show_Source_Dirs --
+   ----------------------
+
+   procedure Show_Source_Dirs (Project : Project_Id) is
+      Current : String_List_Id := Projects.Table (Project).Source_Dirs;
+      Element : String_Element;
+
+   begin
+      Write_Line ("Source_Dirs:");
+
+      while Current /= Nil_String loop
+         Element := String_Elements.Table (Current);
+         Write_Str  ("   ");
+         Write_Line (Get_Name_String (Element.Value));
+         Current := Element.Next;
+      end loop;
+
+      Write_Line ("end Source_Dirs.");
+   end Show_Source_Dirs;
+
+end Prj.Nmsc;
diff --git a/gcc/ada/prj-nmsc.ads b/gcc/ada/prj-nmsc.ads
new file mode 100644 (file)
index 0000000..5fcc005
--- /dev/null
@@ -0,0 +1,43 @@
+------------------------------------------------------------------------------
+--                                                                          --
+--                         GNAT COMPILER COMPONENTS                         --
+--                                                                          --
+--                             P R J . N M S C                             --
+--                                                                          --
+--                                 S p e c                                  --
+--                                                                          --
+--                            $Revision: 1.3 $
+--                                                                          --
+--             Copyright (C) 2000-2001 Free Software Foundation, Inc.       --
+--                                                                          --
+-- GNAT is free software;  you can  redistribute it  and/or modify it under --
+-- terms of the  GNU General Public License as published  by the Free Soft- --
+-- ware  Foundation;  either version 2,  or (at your option) any later ver- --
+-- sion.  GNAT is distributed in the hope that it will be useful, but WITH- --
+-- OUT 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  distributed with GNAT;  see file COPYING.  If not, write --
+-- to  the Free Software Foundation,  59 Temple Place - Suite 330,  Boston, --
+-- MA 02111-1307, USA.                                                      --
+--                                                                          --
+-- GNAT was originally developed  by the GNAT team at  New York University. --
+-- It is now maintained by Ada Core Technologies Inc (http://www.gnat.com). --
+--                                                                          --
+------------------------------------------------------------------------------
+--
+--  Check the Naming Scheme of a project file, find the directories
+--  and the source files.
+
+private package Prj.Nmsc is
+
+   procedure Check_Naming_Scheme
+     (Project      : Project_Id;
+      Report_Error : Put_Line_Access);
+   --  Check that the Naming Scheme of a project is legal. Find the
+   --  object directory, the source directories, and the source files.
+   --  Check the source files against the Naming Scheme.
+   --  If Report_Error is null , use the standard error reporting mechanism
+   --  (Errout). Otherwise, report errors using Report_Error.
+
+end Prj.Nmsc;
diff --git a/gcc/ada/prj-pars.adb b/gcc/ada/prj-pars.adb
new file mode 100644 (file)
index 0000000..620d2e1
--- /dev/null
@@ -0,0 +1,92 @@
+------------------------------------------------------------------------------
+--                                                                          --
+--                         GNAT COMPILER COMPONENTS                         --
+--                                                                          --
+--                             P R J . P A R S                             --
+--                                                                          --
+--                                 B o d y                                  --
+--                                                                          --
+--                            $Revision: 1.19 $
+--                                                                          --
+--             Copyright (C) 2001 Free Software Foundation, Inc.            --
+--                                                                          --
+-- GNAT is free software;  you can  redistribute it  and/or modify it under --
+-- terms of the  GNU General Public License as published  by the Free Soft- --
+-- ware  Foundation;  either version 2,  or (at your option) any later ver- --
+-- sion.  GNAT is distributed in the hope that it will be useful, but WITH- --
+-- OUT 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  distributed with GNAT;  see file COPYING.  If not, write --
+-- to  the Free Software Foundation,  59 Temple Place - Suite 330,  Boston, --
+-- MA 02111-1307, USA.                                                      --
+--                                                                          --
+-- GNAT was originally developed  by the GNAT team at  New York University. --
+-- It is now maintained by Ada Core Technologies Inc (http://www.gnat.com). --
+--                                                                          --
+------------------------------------------------------------------------------
+
+with Ada.Exceptions; use Ada.Exceptions;
+
+with Errout;   use Errout;
+with Output;   use Output;
+with Prj.Com;  use Prj.Com;
+with Prj.Part;
+with Prj.Proc;
+with Prj.Tree; use Prj.Tree;
+
+package body Prj.Pars is
+
+   -----------
+   -- Parse --
+   -----------
+
+   procedure Parse
+     (Project           : out Project_Id;
+      Project_File_Name : String)
+   is
+      Project_Tree      : Project_Node_Id := Empty_Node;
+      The_Project       : Project_Id      := No_Project;
+
+   begin
+      --  Parse the main project file into a tree
+
+      Prj.Part.Parse
+        (Project                => Project_Tree,
+         Project_File_Name      => Project_File_Name,
+         Always_Errout_Finalize => False);
+
+      --  If there were no error, process the tree
+
+      if Project_Tree /= Empty_Node then
+         Prj.Proc.Process
+           (Project           => The_Project,
+            From_Project_Node => Project_Tree,
+            Report_Error      => null);
+         Errout.Finalize;
+      end if;
+
+      Project := The_Project;
+
+   exception
+      when X : others =>
+
+         --  Internal error
+
+         Write_Line (Exception_Information (X));
+         Write_Str  ("Exception ");
+         Write_Str  (Exception_Name (X));
+         Write_Line (" raised, while processing project file");
+         Project := No_Project;
+   end Parse;
+
+   -------------------
+   -- Set_Verbosity --
+   -------------------
+
+   procedure Set_Verbosity (To : in Verbosity) is
+   begin
+      Current_Verbosity := To;
+   end Set_Verbosity;
+
+end Prj.Pars;
diff --git a/gcc/ada/prj-pars.ads b/gcc/ada/prj-pars.ads
new file mode 100644 (file)
index 0000000..0adaf72
--- /dev/null
@@ -0,0 +1,44 @@
+------------------------------------------------------------------------------
+--                                                                          --
+--                         GNAT COMPILER COMPONENTS                         --
+--                                                                          --
+--                              P R J . P A R S                             --
+--                                                                          --
+--                                 S p e c                                  --
+--                                                                          --
+--                            $Revision: 1.8 $
+--                                                                          --
+--          Copyright (C) 2000-2001 Free Software Foundation, Inc.          --
+--                                                                          --
+-- GNAT is free software;  you can  redistribute it  and/or modify it under --
+-- terms of the  GNU General Public License as published  by the Free Soft- --
+-- ware  Foundation;  either version 2,  or (at your option) any later ver- --
+-- sion.  GNAT is distributed in the hope that it will be useful, but WITH- --
+-- OUT 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  distributed with GNAT;  see file COPYING.  If not, write --
+-- to  the Free Software Foundation,  59 Temple Place - Suite 330,  Boston, --
+-- MA 02111-1307, USA.                                                      --
+--                                                                          --
+-- GNAT was originally developed  by the GNAT team at  New York University. --
+-- It is now maintained by Ada Core Technologies Inc (http://www.gnat.com). --
+--                                                                          --
+------------------------------------------------------------------------------
+--
+--  Implements the parsing of project files.
+
+package Prj.Pars is
+
+   procedure Set_Verbosity (To : Verbosity);
+   --  Set the verbosity when parsing the project files.
+
+   procedure Parse
+     (Project           : out Project_Id;
+      Project_File_Name : String);
+   --  Parse a project files and all its imported project files.
+   --  If parsing is successful, Project_Id is the project ID
+   --  of the main project file; otherwise, Project_Id is set
+   --  to No_Project.
+
+end Prj.Pars;
diff --git a/gcc/ada/prj-part.adb b/gcc/ada/prj-part.adb
new file mode 100644 (file)
index 0000000..8100ad4
--- /dev/null
@@ -0,0 +1,871 @@
+------------------------------------------------------------------------------
+--                                                                          --
+--                         GNAT COMPILER COMPONENTS                         --
+--                                                                          --
+--                             P R J . P A R T                              --
+--                                                                          --
+--                                 B o d y                                  --
+--                                                                          --
+--                            $Revision: 1.10 $
+--                                                                          --
+--             Copyright (C) 2001 Free Software Foundation, Inc.            --
+--                                                                          --
+-- GNAT is free software;  you can  redistribute it  and/or modify it under --
+-- terms of the  GNU General Public License as published  by the Free Soft- --
+-- ware  Foundation;  either version 2,  or (at your option) any later ver- --
+-- sion.  GNAT is distributed in the hope that it will be useful, but WITH- --
+-- OUT 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  distributed with GNAT;  see file COPYING.  If not, write --
+-- to  the Free Software Foundation,  59 Temple Place - Suite 330,  Boston, --
+-- MA 02111-1307, USA.                                                      --
+--                                                                          --
+-- GNAT was originally developed  by the GNAT team at  New York University. --
+-- It is now maintained by Ada Core Technologies Inc (http://www.gnat.com). --
+--                                                                          --
+------------------------------------------------------------------------------
+
+with Ada.Characters.Handling;    use Ada.Characters.Handling;
+with Ada.Exceptions;             use Ada.Exceptions;
+with Errout;                     use Errout;
+with GNAT.Directory_Operations;  use GNAT.Directory_Operations;
+with GNAT.OS_Lib;                use GNAT.OS_Lib;
+with Namet;                      use Namet;
+with Osint;                      use Osint;
+with Output;                     use Output;
+with Prj.Com;                    use Prj.Com;
+with Prj.Dect;
+with Scans;                      use Scans;
+with Scn;                        use Scn;
+with Sinfo;                      use Sinfo;
+with Sinput;                     use Sinput;
+with Sinput.P;                   use Sinput.P;
+with Stringt;                    use Stringt;
+with Table;
+with Types;                      use Types;
+
+pragma Elaborate_All (GNAT.OS_Lib);
+
+package body Prj.Part is
+
+   Dir_Sep  : Character renames GNAT.OS_Lib.Directory_Separator;
+
+   Project_File_Extension : String := ".gpr";
+
+   Project_Path : String_Access;
+   --  The project path; initialized during package elaboration.
+
+   Ada_Project_Path : constant String := "ADA_PROJECT_PATH";
+   Prj_Path : constant String_Access := Getenv (Ada_Project_Path);
+
+   ------------------------------------
+   -- Local Packages and Subprograms --
+   ------------------------------------
+
+   package Project_Stack is new Table.Table
+     (Table_Component_Type => Name_Id,
+      Table_Index_Type     => Nat,
+      Table_Low_Bound      => 1,
+      Table_Initial        => 10,
+      Table_Increment      => 10,
+      Table_Name           => "Prj.Part.Project_Stack");
+   --  This table is used to detect circular dependencies
+   --  for imported and modified projects.
+
+   procedure Parse_Context_Clause
+     (Context_Clause    : out Project_Node_Id;
+      Project_Directory : Name_Id);
+   --  Parse the context clause of a project
+   --  Does nothing if there is b\no context clause (if the current
+   --  token is not "with").
+
+   procedure Parse_Single_Project
+     (Project         : out Project_Node_Id;
+      Path_Name       : String;
+      Modified        : Boolean);
+   --  Parse a project file.
+   --  Recursive procedure: it calls itself for imported and
+   --  modified projects.
+
+   function Path_Name_Of
+     (File_Name : String;
+      Directory : String)
+      return      String;
+   --  Returns the path name of a (non project) file.
+   --  Returns an empty string if file cannot be found.
+
+   function Project_Path_Name_Of
+     (Project_File_Name : String;
+      Directory         : String)
+      return              String;
+   --  Returns the path name of a project file.
+   --  Returns an empty string if project file cannot be found.
+
+   function Immediate_Directory_Of (Path_Name : Name_Id) return Name_Id;
+   --  Get the directory of the file with the specified path name.
+   --  This includes the directory separator as the last character.
+   --  Returns "./" if Path_Name contains no directory separator.
+
+   function Simple_File_Name_Of (Path_Name : Name_Id) return Name_Id;
+   --  Returns the name of a file with the specified path name
+   --  with no directory information.
+
+   function Project_Name_From (Path_Name : String) return Name_Id;
+   --  Returns the name of the project that corresponds to its path name.
+   --  Returns No_Name if the path name is invalid, because the corresponding
+   --  project name does not have the syntax of an ada identifier.
+
+   ----------------------------
+   -- Immediate_Directory_Of --
+   ----------------------------
+
+   function Immediate_Directory_Of (Path_Name : Name_Id) return Name_Id is
+   begin
+      Get_Name_String (Path_Name);
+
+      for Index in reverse 1 .. Name_Len loop
+         if Name_Buffer (Index) = '/'
+           or else Name_Buffer (Index) = Dir_Sep
+         then
+            --  Remove from name all characters after the last
+            --  directory separator.
+
+            Name_Len := Index;
+            return Name_Find;
+         end if;
+      end loop;
+
+      --  There is no directory separator in name. Return "./" or ".\".
+      Name_Len := 2;
+      Name_Buffer (1) := '.';
+      Name_Buffer (2) := Dir_Sep;
+      return Name_Find;
+   end Immediate_Directory_Of;
+
+   -----------
+   -- Parse --
+   -----------
+
+   procedure Parse
+     (Project                : out Project_Node_Id;
+      Project_File_Name      : String;
+      Always_Errout_Finalize : Boolean)
+   is
+      Current_Directory : constant String := Get_Current_Dir;
+
+   begin
+      Project := Empty_Node;
+
+      if Current_Verbosity >= Medium then
+         Write_Str ("ADA_PROJECT_PATH=""");
+         Write_Str (Project_Path.all);
+         Write_Line ("""");
+      end if;
+
+      declare
+         Path_Name : constant String :=
+           Project_Path_Name_Of (Project_File_Name,
+                                 Directory   => Current_Directory);
+
+      begin
+         --  Initialize the tables
+
+         Tree_Private_Part.Project_Nodes.Set_Last (Empty_Node);
+         Tree_Private_Part.Projects_Htable.Reset;
+
+         Errout.Initialize;
+
+         --  And parse the main project file
+
+         if Path_Name = "" then
+            Fail ("project file """ & Project_File_Name & """ not found");
+         end if;
+
+         Parse_Single_Project
+           (Project         => Project,
+            Path_Name       => Path_Name,
+            Modified        => False);
+
+         if Errout.Errors_Detected > 0 then
+            Project := Empty_Node;
+         end if;
+
+         if Project = Empty_Node or else Always_Errout_Finalize then
+            Errout.Finalize;
+         end if;
+      end;
+
+   exception
+      when X : others =>
+
+         --  Internal error
+
+         Write_Line (Exception_Information (X));
+         Write_Str  ("Exception ");
+         Write_Str  (Exception_Name (X));
+         Write_Line (" raised, while processing project file");
+         Project := Empty_Node;
+   end Parse;
+
+   --------------------------
+   -- Parse_Context_Clause --
+   --------------------------
+
+   procedure Parse_Context_Clause
+     (Context_Clause    : out Project_Node_Id;
+      Project_Directory : Name_Id)
+   is
+      Project_Directory_Path : constant String :=
+                                 Get_Name_String (Project_Directory);
+      Current_With_Clause    : Project_Node_Id := Empty_Node;
+      Next_With_Clause       : Project_Node_Id := Empty_Node;
+
+   begin
+      --  Assume no context clause
+
+      Context_Clause := Empty_Node;
+      With_Loop :
+
+      --  If Token is not "with", there is no context clause,
+      --  or we have exhausted the with clauses.
+
+      while Token = Tok_With loop
+         Comma_Loop :
+         loop
+            --  Scan past "with" or ","
+
+            Scan;
+            Expect (Tok_String_Literal, "literal string");
+
+            if Token /= Tok_String_Literal then
+               return;
+            end if;
+
+            --  New with clause
+
+            if Current_With_Clause = Empty_Node then
+
+               --  First with clause of the context clause
+
+               Current_With_Clause := Default_Project_Node
+                 (Of_Kind => N_With_Clause);
+               Context_Clause := Current_With_Clause;
+
+            else
+               Next_With_Clause := Default_Project_Node
+                 (Of_Kind => N_With_Clause);
+               Set_Next_With_Clause_Of (Current_With_Clause, Next_With_Clause);
+               Current_With_Clause := Next_With_Clause;
+            end if;
+
+            Set_String_Value_Of (Current_With_Clause, Strval (Token_Node));
+            Set_Location_Of     (Current_With_Clause, Token_Ptr);
+            String_To_Name_Buffer (String_Value_Of (Current_With_Clause));
+
+            declare
+               Original_Path : constant String :=
+                                 Name_Buffer (1 .. Name_Len);
+
+               Imported_Path_Name : constant String :=
+                                      Project_Path_Name_Of
+                                        (Original_Path,
+                                         Project_Directory_Path);
+
+               Withed_Project : Project_Node_Id := Empty_Node;
+
+            begin
+               if Imported_Path_Name = "" then
+
+                  --  The project file cannot be found
+
+                  Name_Len := Original_Path'Length;
+                  Name_Buffer (1 .. Name_Len) := Original_Path;
+                  Error_Msg_Name_1 := Name_Find;
+
+                  Error_Msg ("unknown project file: {", Token_Ptr);
+
+               else
+                  --  Parse the imported project
+
+                  Parse_Single_Project
+                    (Project   => Withed_Project,
+                     Path_Name => Imported_Path_Name,
+                     Modified  => False);
+
+                  if Withed_Project /= Empty_Node then
+
+                     --  If parsing was successful, record project name
+                     --  and path name in with clause
+
+                     Set_Project_Node_Of (Current_With_Clause, Withed_Project);
+                     Set_Name_Of (Current_With_Clause,
+                                  Name_Of (Withed_Project));
+                     Name_Len := Imported_Path_Name'Length;
+                     Name_Buffer (1 .. Name_Len) := Imported_Path_Name;
+                     Set_Path_Name_Of (Current_With_Clause, Name_Find);
+                  end if;
+               end if;
+            end;
+
+            Scan;
+            if Token = Tok_Semicolon then
+
+               --  End of (possibly multiple) with clause;
+               --  Scan past the semicolon.
+
+               Scan;
+               exit Comma_Loop;
+
+            elsif Token /= Tok_Comma then
+               Error_Msg ("expected comma or semi colon", Token_Ptr);
+               exit Comma_Loop;
+            end if;
+         end loop Comma_Loop;
+      end loop With_Loop;
+
+   end Parse_Context_Clause;
+
+   --------------------------
+   -- Parse_Single_Project --
+   --------------------------
+
+   procedure Parse_Single_Project
+     (Project         : out Project_Node_Id;
+      Path_Name       : String;
+      Modified        : Boolean)
+   is
+      Canonical_Path_Name : Name_Id;
+      Project_Directory   : Name_Id;
+      Project_Scan_State  : Saved_Project_Scan_State;
+      Source_Index        : Source_File_Index;
+
+      Modified_Project    : Project_Node_Id := Empty_Node;
+
+      A_Project_Name_And_Node : Tree_Private_Part.Project_Name_And_Node :=
+        Tree_Private_Part.Projects_Htable.Get_First;
+
+      Name_From_Path : constant Name_Id := Project_Name_From (Path_Name);
+
+      use Tree_Private_Part;
+
+   begin
+      Name_Len := Path_Name'Length;
+      Name_Buffer (1 .. Name_Len) := Path_Name;
+      Canonical_Case_File_Name (Name_Buffer (1 .. Name_Len));
+      Canonical_Path_Name := Name_Find;
+
+      --  Check for a circular dependency
+
+      for Index in 1 .. Project_Stack.Last loop
+         if Canonical_Path_Name = Project_Stack.Table (Index) then
+            Error_Msg ("circular dependency detected", Token_Ptr);
+            Error_Msg_Name_1 := Canonical_Path_Name;
+            Error_Msg ("\  { is imported by", Token_Ptr);
+
+            for Current in reverse 1 .. Project_Stack.Last loop
+               Error_Msg_Name_1 := Project_Stack.Table (Current);
+
+               if Error_Msg_Name_1 /= Canonical_Path_Name then
+                  Error_Msg
+                    ("\  { which itself is imported by", Token_Ptr);
+
+               else
+                  Error_Msg ("\  {", Token_Ptr);
+                  exit;
+               end if;
+            end loop;
+
+            Project := Empty_Node;
+            return;
+         end if;
+      end loop;
+
+      Project_Stack.Increment_Last;
+      Project_Stack.Table (Project_Stack.Last) := Canonical_Path_Name;
+
+      --  Check if the project file has already been parsed.
+
+      while
+        A_Project_Name_And_Node /= Tree_Private_Part.No_Project_Name_And_Node
+      loop
+         if
+           Path_Name_Of (A_Project_Name_And_Node.Node) = Canonical_Path_Name
+         then
+            if Modified then
+
+               if A_Project_Name_And_Node.Modified then
+                  Error_Msg
+                    ("cannot modify several times the same project file",
+                     Token_Ptr);
+
+               else
+                  Error_Msg
+                    ("cannot modify an imported project file",
+                     Token_Ptr);
+               end if;
+
+            elsif A_Project_Name_And_Node.Modified then
+               Error_Msg
+                 ("cannot imported a modified project file",
+                  Token_Ptr);
+            end if;
+
+            Project := A_Project_Name_And_Node.Node;
+            Project_Stack.Decrement_Last;
+            return;
+         end if;
+
+         A_Project_Name_And_Node := Tree_Private_Part.Projects_Htable.Get_Next;
+      end loop;
+
+      --  We never encountered this project file
+      --  Save the scan state, load the project file and start to scan it.
+
+      Save_Project_Scan_State (Project_Scan_State);
+      Source_Index := Load_Project_File (Path_Name);
+
+      --  if we cannot find it, we stop
+
+      if Source_Index = No_Source_File then
+         Project := Empty_Node;
+         Project_Stack.Decrement_Last;
+         return;
+      end if;
+
+      Initialize_Scanner (Types.No_Unit, Source_Index);
+
+      if Name_From_Path = No_Name then
+
+         --  The project file name is not correct (no or bad extension,
+         --  or not following Ada identifier's syntax).
+
+         Error_Msg_Name_1 := Canonical_Path_Name;
+         Error_Msg ("?{ is not a valid path name for a project file",
+                    Token_Ptr);
+      end if;
+
+      if Current_Verbosity >= Medium then
+         Write_Str  ("Parsing """);
+         Write_Str  (Path_Name);
+         Write_Char ('"');
+         Write_Eol;
+      end if;
+
+      Project_Directory := Immediate_Directory_Of (Canonical_Path_Name);
+      Project := Default_Project_Node (Of_Kind => N_Project);
+      Set_Directory_Of (Project, Project_Directory);
+      Set_Name_Of (Project, Simple_File_Name_Of (Canonical_Path_Name));
+      Set_Path_Name_Of (Project, Canonical_Path_Name);
+      Set_Location_Of (Project, Token_Ptr);
+
+      --  Is there any imported project?
+
+      declare
+         First_With_Clause : Project_Node_Id := Empty_Node;
+
+      begin
+         Parse_Context_Clause (Context_Clause    => First_With_Clause,
+                               Project_Directory => Project_Directory);
+         Set_First_With_Clause_Of (Project, First_With_Clause);
+      end;
+
+      Expect (Tok_Project, "project");
+
+      --  Scan past "project"
+
+      if Token = Tok_Project then
+         Set_Location_Of (Project, Token_Ptr);
+         Scan;
+      end if;
+
+      Expect (Tok_Identifier, "identifier");
+
+      if Token = Tok_Identifier then
+         Set_Name_Of (Project, Token_Name);
+
+         Get_Name_String (Token_Name);
+         Canonical_Case_File_Name (Name_Buffer (1 .. Name_Len));
+
+         declare
+            Expected_Name : constant Name_Id := Name_Find;
+
+         begin
+            if Name_From_Path /= No_Name
+              and then Expected_Name /= Name_From_Path
+            then
+               --  The project name is not the one that was expected from
+               --  the file name. Report a warning.
+
+               Error_Msg_Name_1 := Expected_Name;
+               Error_Msg ("?file name does not match unit name, " &
+                          "should be `{" & Project_File_Extension & "`",
+                          Token_Ptr);
+            end if;
+         end;
+
+         declare
+            Project_Name : Name_Id :=
+                             Tree_Private_Part.Projects_Htable.Get_First.Name;
+
+         begin
+            --  Check if we already have a project with this name
+
+            while Project_Name /= No_Name
+              and then Project_Name /= Token_Name
+            loop
+               Project_Name := Tree_Private_Part.Projects_Htable.Get_Next.Name;
+            end loop;
+
+            if Project_Name /= No_Name then
+               Error_Msg ("duplicate project name", Token_Ptr);
+
+            else
+               Tree_Private_Part.Projects_Htable.Set
+                 (K => Token_Name,
+                  E => (Name     => Token_Name,
+                        Node     => Project,
+                        Modified => Modified));
+            end if;
+         end;
+
+         --  Scan past the project name
+
+         Scan;
+
+      end if;
+
+      if Token = Tok_Modifying then
+
+         --  We are modifying another project
+
+         --  Scan past "modifying"
+
+         Scan;
+
+         Expect (Tok_String_Literal, "literal string");
+
+         if Token = Tok_String_Literal then
+            Set_Modified_Project_Path_Of (Project, Strval (Token_Node));
+            String_To_Name_Buffer (Modified_Project_Path_Of (Project));
+
+            declare
+               Original_Path_Name : constant String :=
+                                      Name_Buffer (1 .. Name_Len);
+
+               Modified_Project_Path_Name : constant String :=
+                                              Project_Path_Name_Of
+                                                (Original_Path_Name,
+                                                   Get_Name_String
+                                                     (Project_Directory));
+
+            begin
+               if Modified_Project_Path_Name = "" then
+
+                  --  We could not find the project file to modify
+
+                  Name_Len := Original_Path_Name'Length;
+                  Name_Buffer (1 .. Name_Len) := Original_Path_Name;
+                  Error_Msg_Name_1 := Name_Find;
+
+                  Error_Msg ("unknown project file: {", Token_Ptr);
+
+               else
+                  Parse_Single_Project
+                    (Project   => Modified_Project,
+                     Path_Name => Modified_Project_Path_Name,
+                     Modified  => True);
+               end if;
+            end;
+
+            --  Scan past the modified project path
+
+            Scan;
+         end if;
+      end if;
+
+      Expect (Tok_Is, "is");
+
+      declare
+         Project_Declaration : Project_Node_Id := Empty_Node;
+
+      begin
+         --  No need to Scan past "is", Prj.Dect.Parse will do it.
+
+         Prj.Dect.Parse
+           (Declarations    => Project_Declaration,
+            Current_Project => Project,
+            Modifying       => Modified_Project);
+         Set_Project_Declaration_Of (Project, Project_Declaration);
+      end;
+
+      Expect (Tok_End, "end");
+
+      --  Scan past "end"
+
+      if Token = Tok_End then
+         Scan;
+      end if;
+
+      Expect (Tok_Identifier, "identifier");
+
+      if Token = Tok_Identifier then
+
+         --  We check if this is the project name
+
+         if To_Lower (Get_Name_String (Token_Name)) /=
+            Get_Name_String (Name_Of (Project))
+         then
+            Error_Msg ("Expected """ &
+                       Get_Name_String (Name_Of (Project)) & """",
+                       Token_Ptr);
+         end if;
+      end if;
+
+      if Token /= Tok_Semicolon then
+         Scan;
+      end if;
+
+      Expect (Tok_Semicolon, ";");
+
+      --  Restore the scan state, in case we are not the main project
+
+      Restore_Project_Scan_State (Project_Scan_State);
+
+      Project_Stack.Decrement_Last;
+   end Parse_Single_Project;
+
+   ------------------
+   -- Path_Name_Of --
+   ------------------
+
+   function Path_Name_Of
+     (File_Name : String;
+      Directory : String)
+      return      String
+   is
+      Result : String_Access;
+
+   begin
+      Result := Locate_Regular_File (File_Name => File_Name,
+                                     Path      => Directory);
+
+      if Result = null then
+         return "";
+
+      else
+         Canonical_Case_File_Name (Result.all);
+         return Result.all;
+      end if;
+   end Path_Name_Of;
+
+   -----------------------
+   -- Project_Name_From --
+   -----------------------
+
+   function Project_Name_From (Path_Name : String) return Name_Id is
+      Canonical : String (1 .. Path_Name'Length) := Path_Name;
+      First : Natural  := Canonical'Last;
+      Last  : Positive := First;
+
+   begin
+      if First = 0 then
+         return No_Name;
+      end if;
+
+      Canonical_Case_File_Name (Canonical);
+
+      while First > 0
+        and then
+        Canonical (First) /= '.'
+      loop
+         First := First - 1;
+      end loop;
+
+      if Canonical (First) = '.' then
+         if Canonical (First .. Last) = Project_File_Extension
+           and then First /= 1
+         then
+            First := First - 1;
+            Last := First;
+
+            while First > 0
+              and then Canonical (First) /= '/'
+              and then Canonical (First) /= Dir_Sep
+            loop
+               First := First - 1;
+            end loop;
+
+         else
+            return No_Name;
+         end if;
+
+      else
+         return No_Name;
+      end if;
+
+      if Canonical (First) = '/'
+        or else Canonical (First) = Dir_Sep
+      then
+         First := First + 1;
+      end if;
+
+      Name_Len := Last - First + 1;
+      Name_Buffer (1 .. Name_Len) := To_Lower (Canonical (First .. Last));
+
+      if not Is_Letter (Name_Buffer (1)) then
+         return No_Name;
+
+      else
+         for Index in 2 .. Name_Len - 1 loop
+            if Name_Buffer (Index) = '_' then
+               if Name_Buffer (Index + 1) = '_' then
+                  return No_Name;
+               end if;
+
+            elsif not Is_Alphanumeric (Name_Buffer (Index)) then
+               return No_Name;
+            end if;
+
+         end loop;
+
+         if not Is_Alphanumeric (Name_Buffer (Name_Len)) then
+            return No_Name;
+
+         else
+            return Name_Find;
+         end if;
+
+      end if;
+   end Project_Name_From;
+
+   --------------------------
+   -- Project_Path_Name_Of --
+   --------------------------
+
+   function Project_Path_Name_Of
+     (Project_File_Name : String;
+      Directory         : String)
+      return              String
+   is
+      Result : String_Access;
+
+   begin
+      --  First we try <file_name>.<extension>
+
+      if Current_Verbosity = High then
+         Write_Str  ("Project_Path_Name_Of (""");
+         Write_Str  (Project_File_Name);
+         Write_Str  (""", """);
+         Write_Str  (Directory);
+         Write_Line (""");");
+         Write_Str  ("   Trying ");
+         Write_Str (Project_File_Name);
+         Write_Line (Project_File_Extension);
+      end if;
+
+      Result :=
+        Locate_Regular_File
+          (File_Name => Project_File_Name & Project_File_Extension,
+           Path      => Project_Path.all);
+
+      --  Then we try <file_name>
+
+      if Result = null then
+         if Current_Verbosity = High then
+            Write_Str  ("   Trying ");
+            Write_Line  (Project_File_Name);
+         end if;
+
+         Result :=
+           Locate_Regular_File
+           (File_Name => Project_File_Name,
+            Path      => Project_Path.all);
+
+         --  The we try <directory>/<file_name>.<extension>
+
+         if Result = null then
+            if Current_Verbosity = High then
+               Write_Str  ("   Trying ");
+               Write_Str  (Directory);
+               Write_Str (Project_File_Name);
+               Write_Line (Project_File_Extension);
+            end if;
+
+            Result :=
+              Locate_Regular_File
+              (File_Name => Directory & Project_File_Name &
+                            Project_File_Extension,
+               Path      => Project_Path.all);
+
+            --  Then we try <directory>/<file_name>
+
+            if Result = null then
+               if Current_Verbosity = High then
+                  Write_Str  ("   Trying ");
+                  Write_Str  (Directory);
+                  Write_Line  (Project_File_Name);
+               end if;
+
+               Result :=
+                 Locate_Regular_File
+                 (File_Name => Directory & Project_File_Name,
+                  Path      => Project_Path.all);
+            end if;
+         end if;
+      end if;
+
+      --  If we cannot find the project file, we return an empty string
+
+      if Result = null then
+         return "";
+
+      else
+         declare
+            Final_Result : String
+              := GNAT.OS_Lib.Normalize_Pathname (Result.all);
+         begin
+            Free (Result);
+            Canonical_Case_File_Name (Final_Result);
+            return Final_Result;
+         end;
+
+      end if;
+
+   end Project_Path_Name_Of;
+
+   -------------------------
+   -- Simple_File_Name_Of --
+   -------------------------
+
+   function Simple_File_Name_Of (Path_Name : Name_Id) return Name_Id is
+   begin
+      Get_Name_String (Path_Name);
+
+      for Index in reverse 1 .. Name_Len loop
+         if Name_Buffer (Index) = '/'
+           or else Name_Buffer (Index) = Dir_Sep
+         then
+            exit when Index = Name_Len;
+            Name_Buffer (1 .. Name_Len - Index) :=
+              Name_Buffer (Index + 1 .. Name_Len);
+            Name_Len := Name_Len - Index;
+            return Name_Find;
+         end if;
+      end loop;
+
+      return No_Name;
+
+   end Simple_File_Name_Of;
+
+begin
+   Canonical_Case_File_Name (Project_File_Extension);
+
+   if Prj_Path.all = "" then
+      Project_Path := new String'(".");
+
+   else
+      Project_Path := new String'("." & Path_Separator & Prj_Path.all);
+   end if;
+
+end Prj.Part;
diff --git a/gcc/ada/prj-part.ads b/gcc/ada/prj-part.ads
new file mode 100644 (file)
index 0000000..d960b73
--- /dev/null
@@ -0,0 +1,46 @@
+------------------------------------------------------------------------------
+--                                                                          --
+--                         GNAT COMPILER COMPONENTS                         --
+--                                                                          --
+--                              P R J . P A R T                             --
+--                                                                          --
+--                                 S p e c                                  --
+--                                                                          --
+--                            $Revision: 1.3 $
+--                                                                          --
+--          Copyright (C) 2000-2001 Free Software Foundation, Inc.          --
+--                                                                          --
+-- GNAT is free software;  you can  redistribute it  and/or modify it under --
+-- terms of the  GNU General Public License as published  by the Free Soft- --
+-- ware  Foundation;  either version 2,  or (at your option) any later ver- --
+-- sion.  GNAT is distributed in the hope that it will be useful, but WITH- --
+-- OUT 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  distributed with GNAT;  see file COPYING.  If not, write --
+-- to  the Free Software Foundation,  59 Temple Place - Suite 330,  Boston, --
+-- MA 02111-1307, USA.                                                      --
+--                                                                          --
+-- GNAT was originally developed  by the GNAT team at  New York University. --
+-- It is now maintained by Ada Core Technologies Inc (http://www.gnat.com). --
+--                                                                          --
+------------------------------------------------------------------------------
+--
+--  Implements the parsing of project files into a tree.
+
+with Prj.Tree;  use Prj.Tree;
+
+package Prj.Part is
+
+   procedure Parse
+     (Project                : out Project_Node_Id;
+      Project_File_Name      : String;
+      Always_Errout_Finalize : Boolean);
+   --  Parse a project file and all its imported project files
+   --  and create a tree.
+   --  Return the node for the project (or Empty_Node if parsing failed).
+   --  If Always_Errout_Finalize is True, Errout.Finalize is called
+   --  in all cases; otherwise, Errout.Finalize is only called if there are
+   --  errors (but not if there are only warnings).
+
+end Prj.Part;
diff --git a/gcc/ada/prj-proc.adb b/gcc/ada/prj-proc.adb
new file mode 100644 (file)
index 0000000..4822596
--- /dev/null
@@ -0,0 +1,1371 @@
+------------------------------------------------------------------------------
+--                                                                          --
+--                         GNAT COMPILER COMPONENTS                         --
+--                                                                          --
+--                              P R J . P R O C                             --
+--                                                                          --
+--                                 B o d y                                  --
+--                                                                          --
+--                            $Revision: 1.16 $
+--                                                                          --
+--             Copyright (C) 2001 Free Software Foundation, Inc.            --
+--                                                                          --
+-- GNAT is free software;  you can  redistribute it  and/or modify it under --
+-- terms of the  GNU General Public License as published  by the Free Soft- --
+-- ware  Foundation;  either version 2,  or (at your option) any later ver- --
+-- sion.  GNAT is distributed in the hope that it will be useful, but WITH- --
+-- OUT 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  distributed with GNAT;  see file COPYING.  If not, write --
+-- to  the Free Software Foundation,  59 Temple Place - Suite 330,  Boston, --
+-- MA 02111-1307, USA.                                                      --
+--                                                                          --
+-- GNAT was originally developed  by the GNAT team at  New York University. --
+-- It is now maintained by Ada Core Technologies Inc (http://www.gnat.com). --
+--                                                                          --
+------------------------------------------------------------------------------
+
+with Errout;   use Errout;
+with Namet;    use Namet;
+with Opt;
+with Output;   use Output;
+with Prj.Attr; use Prj.Attr;
+with Prj.Com;  use Prj.Com;
+with Prj.Ext;  use Prj.Ext;
+with Prj.Nmsc; use Prj.Nmsc;
+with Stringt;  use Stringt;
+
+with GNAT.HTable;
+
+package body Prj.Proc is
+
+   Error_Report : Put_Line_Access := null;
+
+   package Processed_Projects is new GNAT.HTable.Simple_HTable
+     (Header_Num => Header_Num,
+      Element    => Project_Id,
+      No_Element => No_Project,
+      Key        => Name_Id,
+      Hash       => Hash,
+      Equal      => "=");
+   --  This hash table contains all processed projects
+
+   procedure Add (To_Exp : in out String_Id; Str : String_Id);
+   --  Concatenate two strings and returns another string if both
+   --  arguments are not null string.
+
+   procedure Add_Attributes
+     (Decl     : in out Declarations;
+      First    : Attribute_Node_Id);
+   --  Add all attributes, starting with First, with their default
+   --  values to the package or project with declarations Decl.
+
+   function Expression
+     (Project           : Project_Id;
+      From_Project_Node : Project_Node_Id;
+      Pkg               : Package_Id;
+      First_Term        : Project_Node_Id;
+      Kind              : Variable_Kind)
+      return              Variable_Value;
+   --  From N_Expression project node From_Project_Node, compute the value
+   --  of an expression and return it as a Variable_Value.
+
+   function Imported_Or_Modified_Project_From
+     (Project   : Project_Id;
+      With_Name : Name_Id)
+     return Project_Id;
+   --  Find an imported or modified project of Project whose name is With_Name.
+
+   function Package_From
+     (Project   : Project_Id;
+      With_Name : Name_Id)
+      return      Package_Id;
+   --  Find the package of Project whose name is With_Name.
+
+   procedure Process_Declarative_Items
+     (Project           : Project_Id;
+      From_Project_Node : Project_Node_Id;
+      Pkg               : Package_Id;
+      Item              : Project_Node_Id);
+   --  Process declarative items starting with From_Project_Node, and put them
+   --  in declarations Decl. This is a recursive procedure; it calls itself for
+   --  a package declaration or a case construction.
+
+   procedure Recursive_Process
+     (Project           : out Project_Id;
+      From_Project_Node : Project_Node_Id;
+      Modified_By       : Project_Id);
+   --  Process project with node From_Project_Node in the tree.
+   --  Do nothing if From_Project_Node is Empty_Node.
+   --  If project has already been processed, simply return its project id.
+   --  Otherwise create a new project id, mark it as processed, call itself
+   --  recursively for all imported projects and a modified project, if any.
+   --  Then process the declarative items of the project.
+
+   procedure Check (Project : in out Project_Id);
+   --  Set all projects to not checked, then call Recursive_Check for
+   --  the main project Project.
+   --  Project is set to No_Project if errors occurred.
+
+   procedure Recursive_Check (Project : Project_Id);
+   --  If Project is marked as not checked, mark it as checked,
+   --  call Check_Naming_Scheme for the project, then call itself
+   --  for a possible modified project and all the imported projects
+   --  of Project.
+
+   ---------
+   -- Add --
+   ---------
+
+   procedure Add (To_Exp : in out String_Id; Str : String_Id) is
+   begin
+      if To_Exp = Types.No_String or else String_Length (To_Exp) = 0 then
+
+         --  To_Exp is nil or empty. The result is Str.
+
+         To_Exp := Str;
+
+      --  If Str is nil, then do not change To_Ext
+
+      elsif Str /= No_String then
+         Start_String (To_Exp);
+         Store_String_Chars (Str);
+         To_Exp := End_String;
+      end if;
+   end Add;
+
+   --------------------
+   -- Add_Attributes --
+   --------------------
+
+   procedure Add_Attributes
+     (Decl           : in out Declarations;
+      First          : Attribute_Node_Id) is
+      The_Attribute  : Attribute_Node_Id := First;
+      Attribute_Data : Attribute_Record;
+
+   begin
+      while The_Attribute /= Empty_Attribute loop
+         Attribute_Data := Attributes.Table (The_Attribute);
+
+         if Attribute_Data.Kind_2 /= Associative_Array then
+            declare
+               New_Attribute : Variable_Value;
+
+            begin
+               case Attribute_Data.Kind_1 is
+
+                  --  Undefined should not happen
+
+                  when Undefined =>
+                     pragma Assert
+                       (False, "attribute with an undefined kind");
+                     raise Program_Error;
+
+                  --  Single attributes have a default value of empty string
+
+                  when Single =>
+                     New_Attribute :=
+                       (Kind     => Single,
+                        Location => No_Location,
+                        Default  => True,
+                        Value    => Empty_String);
+
+                  --  List attributes have a default value of nil list
+
+                  when List =>
+                     New_Attribute :=
+                       (Kind     => List,
+                        Location => No_Location,
+                        Default  => True,
+                        Values   => Nil_String);
+
+               end case;
+
+               Variable_Elements.Increment_Last;
+               Variable_Elements.Table (Variable_Elements.Last) :=
+                 (Next  => Decl.Attributes,
+                  Name  => Attribute_Data.Name,
+                  Value => New_Attribute);
+               Decl.Attributes := Variable_Elements.Last;
+            end;
+         end if;
+
+         The_Attribute := Attributes.Table (The_Attribute).Next;
+      end loop;
+
+   end Add_Attributes;
+
+   -----------
+   -- Check --
+   -----------
+
+   procedure Check (Project : in out Project_Id) is
+   begin
+      --  Make sure that all projects are marked as not checked.
+
+      for Index in 1 .. Projects.Last loop
+         Projects.Table (Index).Checked := False;
+      end loop;
+
+      Recursive_Check (Project);
+
+      if Errout.Errors_Detected > 0 then
+         Project := No_Project;
+      end if;
+
+   end Check;
+
+   ----------------
+   -- Expression --
+   ----------------
+
+   function Expression
+     (Project           : Project_Id;
+      From_Project_Node : Project_Node_Id;
+      Pkg               : Package_Id;
+      First_Term        : Project_Node_Id;
+      Kind              : Variable_Kind)
+      return              Variable_Value
+   is
+      The_Term : Project_Node_Id := First_Term;
+      --  The term in the expression list
+
+      The_Current_Term : Project_Node_Id := Empty_Node;
+      --  The current term node id
+
+      Term_Kind : Variable_Kind;
+      --  The kind of the current term
+
+      Result : Variable_Value (Kind => Kind);
+      --  The returned result
+
+      Last : String_List_Id := Nil_String;
+      --  Reference to the last string elements in Result, when Kind is List.
+
+   begin
+      Result.Location := Location_Of (From_Project_Node);
+
+      --  Process each term of the expression, starting with First_Term
+
+      while The_Term /= Empty_Node loop
+
+         --  We get the term data and kind ...
+
+         Term_Kind := Expression_Kind_Of (The_Term);
+
+         The_Current_Term := Current_Term (The_Term);
+
+         case Kind_Of (The_Current_Term) is
+
+            when N_Literal_String =>
+
+               case Kind is
+
+                  when Undefined =>
+
+                     --  Should never happen
+
+                     pragma Assert (False, "Undefined expression kind");
+                     raise Program_Error;
+
+                  when Single =>
+                     Add (Result.Value, String_Value_Of (The_Current_Term));
+
+                  when List =>
+
+                     String_Elements.Increment_Last;
+
+                     if Last = Nil_String then
+
+                        --  This can happen in an expression such as
+                        --  () & "toto"
+
+                        Result.Values := String_Elements.Last;
+
+                     else
+                        String_Elements.Table (Last).Next :=
+                          String_Elements.Last;
+                     end if;
+
+                     Last := String_Elements.Last;
+                     String_Elements.Table (Last) :=
+                       (Value    => String_Value_Of (The_Current_Term),
+                        Location => Location_Of (The_Current_Term),
+                        Next     => Nil_String);
+
+               end case;
+
+            when N_Literal_String_List =>
+
+               declare
+                  String_Node : Project_Node_Id :=
+                                  First_Expression_In_List (The_Current_Term);
+
+                  Value : Variable_Value;
+
+               begin
+                  if String_Node /= Empty_Node then
+
+                     --  If String_Node is nil, it is an empty list,
+                     --  there is nothing to do
+
+                     Value := Expression
+                       (Project           => Project,
+                        From_Project_Node => From_Project_Node,
+                        Pkg               => Pkg,
+                        First_Term        => Tree.First_Term (String_Node),
+                        Kind              => Single);
+                     String_Elements.Increment_Last;
+
+                     if Result.Values = Nil_String then
+
+                        --  This literal string list is the first term
+                        --  in a string list expression
+
+                        Result.Values := String_Elements.Last;
+
+                     else
+                        String_Elements.Table (Last).Next :=
+                          String_Elements.Last;
+                     end if;
+
+                     Last := String_Elements.Last;
+                     String_Elements.Table (Last) :=
+                       (Value    => Value.Value,
+                        Location => Value.Location,
+                        Next     => Nil_String);
+
+                     loop
+                        --  Add the other element of the literal string list
+                        --  one after the other
+
+                        String_Node :=
+                          Next_Expression_In_List (String_Node);
+
+                        exit when String_Node = Empty_Node;
+
+                        Value :=
+                          Expression
+                          (Project           => Project,
+                           From_Project_Node => From_Project_Node,
+                           Pkg               => Pkg,
+                           First_Term        => Tree.First_Term (String_Node),
+                           Kind              => Single);
+
+                        String_Elements.Increment_Last;
+                        String_Elements.Table (Last).Next :=
+                          String_Elements.Last;
+                        Last := String_Elements.Last;
+                        String_Elements.Table (Last) :=
+                          (Value    => Value.Value,
+                           Location => Value.Location,
+                           Next     => Nil_String);
+                     end loop;
+
+                  end if;
+
+               end;
+
+            when N_Variable_Reference | N_Attribute_Reference =>
+
+               declare
+                  The_Project     : Project_Id  := Project;
+                  The_Package     : Package_Id  := Pkg;
+                  The_Name        : Name_Id     := No_Name;
+                  The_Variable_Id : Variable_Id := No_Variable;
+                  The_Variable    : Variable;
+                  Term_Project    : constant Project_Node_Id :=
+                                      Project_Node_Of (The_Current_Term);
+                  Term_Package    : constant Project_Node_Id :=
+                                      Package_Node_Of (The_Current_Term);
+
+               begin
+                  if Term_Project /= Empty_Node and then
+                     Term_Project /= From_Project_Node
+                  then
+                     --  This variable or attribute comes from another project
+
+                     The_Name := Name_Of (Term_Project);
+                     The_Project := Imported_Or_Modified_Project_From
+                       (Project => Project, With_Name => The_Name);
+                  end if;
+
+                  if Term_Package /= Empty_Node then
+
+                     --  This is an attribute of a package
+
+                     The_Name := Name_Of (Term_Package);
+                     The_Package := Projects.Table (The_Project).Decl.Packages;
+
+                     while The_Package /= No_Package
+                       and then Packages.Table (The_Package).Name /= The_Name
+                     loop
+                        The_Package := Packages.Table (The_Package).Next;
+                     end loop;
+
+                     pragma Assert
+                       (The_Package /= No_Package,
+                        "package not found.");
+
+                  elsif Kind_Of (The_Current_Term) = N_Attribute_Reference then
+                     The_Package := No_Package;
+                  end if;
+
+                  The_Name := Name_Of (The_Current_Term);
+
+                  if The_Package /= No_Package then
+
+                     --  First, if there is a package, look into the package
+
+                     if Kind_Of (The_Current_Term) = N_Variable_Reference then
+                        The_Variable_Id :=
+                          Packages.Table (The_Package).Decl.Variables;
+
+                     else
+                        The_Variable_Id :=
+                          Packages.Table (The_Package).Decl.Attributes;
+                     end if;
+
+                     while The_Variable_Id /= No_Variable
+                       and then
+                         Variable_Elements.Table (The_Variable_Id).Name /=
+                                                                    The_Name
+                     loop
+                        The_Variable_Id :=
+                          Variable_Elements.Table (The_Variable_Id).Next;
+                     end loop;
+
+                  end if;
+
+                  if The_Variable_Id = No_Variable then
+
+                     --  If we have not found it, look into the project
+
+                     if Kind_Of (The_Current_Term) = N_Variable_Reference then
+                        The_Variable_Id :=
+                          Projects.Table (The_Project).Decl.Variables;
+
+                     else
+                        The_Variable_Id :=
+                          Projects.Table (The_Project).Decl.Attributes;
+                     end if;
+
+                     while The_Variable_Id /= No_Variable
+                       and then
+                         Variable_Elements.Table (The_Variable_Id).Name /=
+                                                                     The_Name
+                     loop
+                        The_Variable_Id :=
+                          Variable_Elements.Table (The_Variable_Id).Next;
+                     end loop;
+
+                  end if;
+
+                  pragma Assert (The_Variable_Id /= No_Variable,
+                                 "variable or attribute not found");
+
+                  The_Variable := Variable_Elements.Table (The_Variable_Id);
+
+                  case Kind is
+
+                     when Undefined =>
+
+                        --  Should never happen
+
+                        pragma Assert (False, "undefined expression kind");
+                        null;
+
+                     when Single =>
+
+                        case The_Variable.Value.Kind is
+
+                           when Undefined =>
+                              null;
+
+                           when Single =>
+                              Add (Result.Value, The_Variable.Value.Value);
+
+                           when List =>
+
+                              --  Should never happen
+
+                              pragma Assert
+                                (False,
+                                 "list cannot appear in single " &
+                                 "string expression");
+                              null;
+
+                        end case;
+
+                     when List =>
+                        case The_Variable.Value.Kind is
+
+                           when Undefined =>
+                              null;
+
+                           when Single =>
+                              String_Elements.Increment_Last;
+
+                              if Last = Nil_String then
+
+                                 --  This can happen in an expression such as
+                                 --  () & Var
+
+                                 Result.Values := String_Elements.Last;
+
+                              else
+                                 String_Elements.Table (Last).Next :=
+                                   String_Elements.Last;
+                              end if;
+
+                              Last := String_Elements.Last;
+                              String_Elements.Table (Last) :=
+                                (Value    => The_Variable.Value.Value,
+                                 Location => Location_Of (The_Current_Term),
+                                 Next     => Nil_String);
+
+                           when List =>
+
+                              declare
+                                 The_List : String_List_Id :=
+                                              The_Variable.Value.Values;
+
+                              begin
+                                 while The_List /= Nil_String loop
+                                    String_Elements.Increment_Last;
+
+                                    if Last = Nil_String then
+                                       Result.Values := String_Elements.Last;
+
+                                    else
+                                       String_Elements.Table (Last).Next :=
+                                         String_Elements.Last;
+
+                                    end if;
+
+                                    Last := String_Elements.Last;
+                                    String_Elements.Table (Last) :=
+                                      (Value    =>
+                                         String_Elements.Table
+                                                          (The_List).Value,
+                                       Location => Location_Of
+                                                          (The_Current_Term),
+                                       Next     => Nil_String);
+                                    The_List :=
+                                      String_Elements.Table (The_List).Next;
+
+                                 end loop;
+                              end;
+                        end case;
+                  end case;
+               end;
+
+            when N_External_Value =>
+               String_To_Name_Buffer
+                 (String_Value_Of (External_Reference_Of (The_Current_Term)));
+
+               declare
+                  Name    : constant Name_Id  := Name_Find;
+                  Default : String_Id         := No_String;
+                  Value   : String_Id         := No_String;
+
+                  Default_Node : constant Project_Node_Id :=
+                                   External_Default_Of (The_Current_Term);
+
+               begin
+                  if Default_Node /= Empty_Node then
+                     Default := String_Value_Of (Default_Node);
+                  end if;
+
+                  Value := Prj.Ext.Value_Of (Name, Default);
+
+                  if Value = No_String then
+                     if Error_Report = null then
+                        Error_Msg
+                          ("undefined external reference",
+                           Location_Of (The_Current_Term));
+
+                     else
+                        Error_Report
+                          ("""" & Get_Name_String (Name) &
+                           """ is an undefined external reference");
+                     end if;
+
+                     Value := Empty_String;
+
+                  end if;
+
+                  case Kind is
+
+                     when Undefined =>
+                        null;
+
+                     when Single =>
+                        Add (Result.Value, Value);
+
+                     when List =>
+                        String_Elements.Increment_Last;
+
+                        if Last = Nil_String then
+                           Result.Values := String_Elements.Last;
+
+                        else
+                           String_Elements.Table (Last).Next :=
+                             String_Elements.Last;
+                        end if;
+
+                        Last := String_Elements.Last;
+                        String_Elements.Table (Last) :=
+                          (Value    => Value,
+                           Location => Location_Of (The_Current_Term),
+                           Next     => Nil_String);
+
+                  end case;
+
+               end;
+
+            when others =>
+
+               --  Should never happen
+
+               pragma Assert
+                 (False,
+                  "illegal node kind in an expression");
+               raise Program_Error;
+
+         end case;
+
+         The_Term := Next_Term (The_Term);
+
+      end loop;
+      return Result;
+   end Expression;
+
+   ---------------------------------------
+   -- Imported_Or_Modified_Project_From --
+   ---------------------------------------
+
+   function Imported_Or_Modified_Project_From
+     (Project   : Project_Id;
+      With_Name : Name_Id)
+      return      Project_Id
+   is
+      Data : constant Project_Data := Projects.Table (Project);
+      List : Project_List          := Data.Imported_Projects;
+
+   begin
+      --  First check if it is the name of a modified project
+
+      if Data.Modifies /= No_Project
+        and then Projects.Table (Data.Modifies).Name = With_Name
+      then
+         return Data.Modifies;
+
+      else
+         --  Then check the name of each imported project
+
+         while List /= Empty_Project_List
+           and then
+             Projects.Table
+               (Project_Lists.Table (List).Project).Name /= With_Name
+
+         loop
+            List := Project_Lists.Table (List).Next;
+         end loop;
+
+         pragma Assert
+           (List /= Empty_Project_List,
+           "project not found");
+
+         return Project_Lists.Table (List).Project;
+      end if;
+
+   end Imported_Or_Modified_Project_From;
+
+   ------------------
+   -- Package_From --
+   ------------------
+
+   function Package_From
+     (Project   : Project_Id;
+      With_Name : Name_Id)
+      return      Package_Id
+   is
+      Data   : constant Project_Data := Projects.Table (Project);
+      Result : Package_Id := Data.Decl.Packages;
+
+   begin
+      --  Check the name of each existing package of Project
+
+      while Result /= No_Package
+        and then
+        Packages.Table (Result).Name /= With_Name
+      loop
+         Result := Packages.Table (Result).Next;
+      end loop;
+
+      if Result = No_Package then
+         --  Should never happen
+         Write_Line ("package """ & Get_Name_String (With_Name) &
+                     """ not found");
+         raise Program_Error;
+
+      else
+         return Result;
+      end if;
+   end Package_From;
+
+   -------------
+   -- Process --
+   -------------
+
+   procedure Process
+     (Project           : out Project_Id;
+      From_Project_Node : Project_Node_Id;
+      Report_Error      : Put_Line_Access)
+   is
+   begin
+      Error_Report := Report_Error;
+
+      --  Make sure there is no projects in the data structure
+
+      Projects.Set_Last (No_Project);
+      Processed_Projects.Reset;
+
+      --  And process the main project and all of the projects it depends on,
+      --  recursively
+
+      Recursive_Process
+        (Project           => Project,
+         From_Project_Node => From_Project_Node,
+         Modified_By       => No_Project);
+
+      if Errout.Errors_Detected > 0 then
+         Project := No_Project;
+      end if;
+
+      if Project /= No_Project then
+         Check (Project);
+      end if;
+
+   end Process;
+
+   -------------------------------
+   -- Process_Declarative_Items --
+   -------------------------------
+
+   procedure Process_Declarative_Items
+     (Project           : Project_Id;
+      From_Project_Node : Project_Node_Id;
+      Pkg               : Package_Id;
+      Item              : Project_Node_Id) is
+
+      Current_Declarative_Item : Project_Node_Id := Item;
+
+      Current_Item : Project_Node_Id := Empty_Node;
+
+   begin
+      --  For each declarative item
+
+      while Current_Declarative_Item /= Empty_Node loop
+
+         --  Get its data
+
+         Current_Item := Current_Item_Node (Current_Declarative_Item);
+
+         --  And set Current_Declarative_Item to the next declarative item
+         --  ready for the next iteration
+
+         Current_Declarative_Item := Next_Declarative_Item
+                                            (Current_Declarative_Item);
+
+         case Kind_Of (Current_Item) is
+
+            when N_Package_Declaration =>
+               Packages.Increment_Last;
+
+               declare
+                  New_Pkg         : constant Package_Id := Packages.Last;
+                  The_New_Package : Package_Element;
+
+                  Project_Of_Renamed_Package : constant Project_Node_Id :=
+                                                 Project_Of_Renamed_Package_Of
+                                                   (Current_Item);
+
+               begin
+                  The_New_Package.Name := Name_Of (Current_Item);
+
+                  if Pkg /= No_Package then
+                     The_New_Package.Next :=
+                       Packages.Table (Pkg).Decl.Packages;
+                     Packages.Table (Pkg).Decl.Packages := New_Pkg;
+                  else
+                     The_New_Package.Next :=
+                       Projects.Table (Project).Decl.Packages;
+                     Projects.Table (Project).Decl.Packages := New_Pkg;
+                  end if;
+
+                  Packages.Table (New_Pkg) := The_New_Package;
+
+                  if Project_Of_Renamed_Package /= Empty_Node then
+
+                     --  Renamed package
+
+                     declare
+                        Project_Name : constant Name_Id :=
+                                         Name_Of
+                                           (Project_Of_Renamed_Package);
+
+                        Renamed_Project : constant Project_Id :=
+                                            Imported_Or_Modified_Project_From
+                                              (Project, Project_Name);
+
+                        Renamed_Package : constant Package_Id :=
+                                            Package_From
+                                              (Renamed_Project,
+                                               Name_Of (Current_Item));
+
+                     begin
+                        Packages.Table (New_Pkg).Decl :=
+                          Packages.Table (Renamed_Package).Decl;
+                     end;
+
+                  else
+                     --  Set the default values of the attributes
+
+                     Add_Attributes
+                       (Packages.Table (New_Pkg).Decl,
+                        Package_Attributes.Table
+                           (Package_Id_Of (Current_Item)).First_Attribute);
+
+                     Process_Declarative_Items
+                       (Project           => Project,
+                        From_Project_Node => From_Project_Node,
+                        Pkg               => New_Pkg,
+                        Item              => First_Declarative_Item_Of
+                                                             (Current_Item));
+                  end if;
+
+               end;
+
+            when N_String_Type_Declaration =>
+
+               --  There is nothing to process
+
+               null;
+
+            when N_Attribute_Declaration      |
+                 N_Typed_Variable_Declaration |
+                 N_Variable_Declaration       =>
+
+                  pragma Assert (Expression_Of (Current_Item) /= Empty_Node,
+                                 "no expression for an object declaration");
+
+               declare
+                  New_Value : constant Variable_Value :=
+                                Expression
+                                  (Project           => Project,
+                                   From_Project_Node => From_Project_Node,
+                                   Pkg               => Pkg,
+                                   First_Term        =>
+                                     Tree.First_Term (Expression_Of
+                                                              (Current_Item)),
+                                   Kind              =>
+                                     Expression_Kind_Of (Current_Item));
+
+                  The_Variable : Variable_Id := No_Variable;
+
+                  Current_Item_Name : constant Name_Id :=
+                                        Name_Of (Current_Item);
+
+               begin
+                  if Kind_Of (Current_Item) = N_Typed_Variable_Declaration then
+
+                     if String_Equal (New_Value.Value, Empty_String) then
+                        Error_Msg_Name_1 := Name_Of (Current_Item);
+
+                        if Error_Report = null then
+                           Error_Msg
+                             ("no value defined for %",
+                              Location_Of (Current_Item));
+
+                        else
+                           Error_Report
+                             ("no value defined for " &
+                              Get_Name_String (Error_Msg_Name_1));
+                        end if;
+
+                     else
+                        declare
+                           Current_String : Project_Node_Id :=
+                                              First_Literal_String
+                                                (String_Type_Of
+                                                  (Current_Item));
+
+                        begin
+                           while Current_String /= Empty_Node
+                             and then not String_Equal
+                                            (String_Value_Of (Current_String),
+                                             New_Value.Value)
+                           loop
+                              Current_String :=
+                                Next_Literal_String (Current_String);
+                           end loop;
+
+                           if Current_String = Empty_Node then
+                              String_To_Name_Buffer (New_Value.Value);
+                              Error_Msg_Name_1 := Name_Find;
+                              Error_Msg_Name_2 := Name_Of (Current_Item);
+
+                              if Error_Report = null then
+                                 Error_Msg
+                                   ("value { is illegal for typed string %",
+                                    Location_Of (Current_Item));
+
+                              else
+                                 Error_Report
+                                   ("value """ &
+                                    Get_Name_String (Error_Msg_Name_1) &
+                                    """ is illegal for typed string """ &
+                                    Get_Name_String (Error_Msg_Name_2) &
+                                    """");
+                              end if;
+                           end if;
+                        end;
+                     end if;
+                  end if;
+
+                  if Kind_Of (Current_Item) /= N_Attribute_Declaration
+                    or else
+                      Associative_Array_Index_Of (Current_Item) = No_String
+                  then
+                     --  Usual case
+
+                     --  Code below really needs more comments ???
+
+                     if Kind_Of (Current_Item) = N_Attribute_Declaration then
+                        if Pkg /= No_Package then
+                           The_Variable :=
+                             Packages.Table (Pkg).Decl.Attributes;
+
+                        else
+                           The_Variable :=
+                             Projects.Table (Project).Decl.Attributes;
+                        end if;
+
+                     else
+                        if Pkg /= No_Package then
+                           The_Variable :=
+                             Packages.Table (Pkg).Decl.Variables;
+
+                        else
+                           The_Variable :=
+                             Projects.Table (Project).Decl.Variables;
+                        end if;
+
+                     end if;
+
+                     while
+                       The_Variable /= No_Variable
+                         and then
+                           Variable_Elements.Table (The_Variable).Name /=
+                                                          Current_Item_Name
+                     loop
+                        The_Variable :=
+                          Variable_Elements.Table (The_Variable).Next;
+                     end loop;
+
+                     if The_Variable = No_Variable then
+                        pragma Assert
+                          (Kind_Of (Current_Item) /= N_Attribute_Declaration,
+                           "illegal attribute declaration");
+
+                        Variable_Elements.Increment_Last;
+                        The_Variable := Variable_Elements.Last;
+
+                        if Pkg /= No_Package then
+                           Variable_Elements.Table (The_Variable) :=
+                             (Next    =>
+                                Packages.Table (Pkg).Decl.Variables,
+                              Name    => Current_Item_Name,
+                              Value   => New_Value);
+                           Packages.Table (Pkg).Decl.Variables := The_Variable;
+
+                        else
+                           Variable_Elements.Table (The_Variable) :=
+                             (Next    =>
+                                Projects.Table (Project).Decl.Variables,
+                              Name    => Current_Item_Name,
+                              Value   => New_Value);
+                           Projects.Table (Project).Decl.Variables :=
+                             The_Variable;
+                        end if;
+
+                     else
+                        Variable_Elements.Table (The_Variable).Value :=
+                          New_Value;
+
+                     end if;
+
+                  else
+                     --  Associative array attribute
+
+                     String_To_Name_Buffer
+                       (Associative_Array_Index_Of (Current_Item));
+
+                     declare
+                        The_Array : Array_Id;
+
+                        The_Array_Element : Array_Element_Id :=
+                                              No_Array_Element;
+
+                        Index_Name : constant Name_Id := Name_Find;
+
+                     begin
+
+                        if Pkg /= No_Package then
+                           The_Array := Packages.Table (Pkg).Decl.Arrays;
+
+                        else
+                           The_Array := Projects.Table (Project).Decl.Arrays;
+                        end if;
+
+                        while
+                          The_Array /= No_Array
+                            and then Arrays.Table (The_Array).Name /=
+                                                           Current_Item_Name
+                        loop
+                           The_Array := Arrays.Table (The_Array).Next;
+                        end loop;
+
+                        if The_Array = No_Array then
+                           Arrays.Increment_Last;
+                           The_Array := Arrays.Last;
+
+                           if Pkg /= No_Package then
+                              Arrays.Table (The_Array) :=
+                                (Name  => Current_Item_Name,
+                                 Value => No_Array_Element,
+                                 Next  => Packages.Table (Pkg).Decl.Arrays);
+                              Packages.Table (Pkg).Decl.Arrays := The_Array;
+
+                           else
+                              Arrays.Table (The_Array) :=
+                                (Name  => Current_Item_Name,
+                                 Value => No_Array_Element,
+                                 Next  =>
+                                   Projects.Table (Project).Decl.Arrays);
+                              Projects.Table (Project).Decl.Arrays :=
+                                The_Array;
+                           end if;
+
+                        else
+                           The_Array_Element := Arrays.Table (The_Array).Value;
+                        end if;
+
+                        while The_Array_Element /= No_Array_Element
+                          and then
+                            Array_Elements.Table (The_Array_Element).Index /=
+                                                                  Index_Name
+                        loop
+                           The_Array_Element :=
+                             Array_Elements.Table (The_Array_Element).Next;
+                        end loop;
+
+                        if The_Array_Element = No_Array_Element then
+                           Array_Elements.Increment_Last;
+                           The_Array_Element := Array_Elements.Last;
+                           Array_Elements.Table (The_Array_Element) :=
+                             (Index  => Index_Name,
+                              Value  => New_Value,
+                              Next   => Arrays.Table (The_Array).Value);
+                           Arrays.Table (The_Array).Value := The_Array_Element;
+
+                        else
+                           Array_Elements.Table (The_Array_Element).Value :=
+                             New_Value;
+                        end if;
+                     end;
+                  end if;
+               end;
+
+            when N_Case_Construction =>
+               declare
+                  The_Project   : Project_Id      := Project;
+                  The_Package   : Package_Id      := Pkg;
+                  The_Variable  : Variable_Value  := Nil_Variable_Value;
+                  Case_Value    : String_Id       := No_String;
+                  Case_Item     : Project_Node_Id := Empty_Node;
+                  Choice_String : Project_Node_Id := Empty_Node;
+                  Decl_Item     : Project_Node_Id := Empty_Node;
+
+               begin
+                  declare
+                     Variable_Node : constant Project_Node_Id :=
+                                       Case_Variable_Reference_Of
+                                         (Current_Item);
+
+                     Var_Id : Variable_Id := No_Variable;
+                     Name   : Name_Id     := No_Name;
+
+                  begin
+                     if Project_Node_Of (Variable_Node) /= Empty_Node then
+                        Name := Name_Of (Project_Node_Of (Variable_Node));
+                        The_Project :=
+                          Imported_Or_Modified_Project_From (Project, Name);
+                     end if;
+
+                     if Package_Node_Of (Variable_Node) /= Empty_Node then
+                        Name := Name_Of (Package_Node_Of (Variable_Node));
+                        The_Package := Package_From (The_Project, Name);
+                     end if;
+
+                     Name := Name_Of (Variable_Node);
+
+                     if The_Package /= No_Package then
+                        Var_Id := Packages.Table (The_Package).Decl.Variables;
+                        Name := Name_Of (Variable_Node);
+                        while Var_Id /= No_Variable
+                          and then
+                            Variable_Elements.Table (Var_Id).Name /= Name
+                        loop
+                           Var_Id := Variable_Elements.Table (Var_Id).Next;
+                        end loop;
+                     end if;
+
+                     if Var_Id = No_Variable
+                       and then Package_Node_Of (Variable_Node) = Empty_Node
+                     then
+                        Var_Id := Projects.Table (The_Project).Decl.Variables;
+                        while Var_Id /= No_Variable
+                          and then
+                            Variable_Elements.Table (Var_Id).Name /= Name
+                        loop
+                           Var_Id := Variable_Elements.Table (Var_Id).Next;
+                        end loop;
+                     end if;
+
+                     if Var_Id = No_Variable then
+
+                        --  Should never happen
+
+                        Write_Line ("variable """ &
+                                    Get_Name_String (Name) &
+                                    """ not found");
+                        raise Program_Error;
+                     end if;
+
+                     The_Variable := Variable_Elements.Table (Var_Id).Value;
+
+                     if The_Variable.Kind /= Single then
+
+                        --  Should never happen
+
+                        Write_Line ("variable""" &
+                                    Get_Name_String (Name) &
+                                    """ is not a single string variable");
+                        raise Program_Error;
+                     end if;
+
+                     Case_Value := The_Variable.Value;
+                  end;
+
+                  Case_Item := First_Case_Item_Of (Current_Item);
+                  Case_Item_Loop :
+                     while Case_Item /= Empty_Node loop
+                        Choice_String := First_Choice_Of (Case_Item);
+
+                        if Choice_String = Empty_Node then
+                           Decl_Item := First_Declarative_Item_Of (Case_Item);
+                           exit Case_Item_Loop;
+                        end if;
+
+                        Choice_Loop :
+                           while Choice_String /= Empty_Node loop
+                              if String_Equal (Case_Value,
+                                               String_Value_Of (Choice_String))
+                              then
+                                 Decl_Item :=
+                                   First_Declarative_Item_Of (Case_Item);
+                                 exit Case_Item_Loop;
+                              end if;
+
+                              Choice_String :=
+                                Next_Literal_String (Choice_String);
+                           end loop Choice_Loop;
+                        Case_Item := Next_Case_Item (Case_Item);
+                     end loop Case_Item_Loop;
+
+                  if Decl_Item /= Empty_Node then
+                     Process_Declarative_Items
+                       (Project           => Project,
+                        From_Project_Node => From_Project_Node,
+                        Pkg               => Pkg,
+                        Item              => Decl_Item);
+                  end if;
+               end;
+
+            when others =>
+
+               --  Should never happen
+
+               Write_Line ("Illegal declarative item: " &
+                           Project_Node_Kind'Image (Kind_Of (Current_Item)));
+               raise Program_Error;
+         end case;
+      end loop;
+   end Process_Declarative_Items;
+
+   ---------------------
+   -- Recursive_Check --
+   ---------------------
+
+   procedure Recursive_Check (Project : Project_Id) is
+      Data                  : Project_Data;
+      Imported_Project_List : Project_List := Empty_Project_List;
+
+   begin
+      --  Do nothing if Project is No_Project, or Project has already
+      --  been marked as checked.
+
+      if Project /= No_Project
+        and then not Projects.Table (Project).Checked
+      then
+         Data := Projects.Table (Project);
+
+         --  Call itself for a possible modified project.
+         --  (if there is no modified project, then nothing happens).
+
+         Recursive_Check (Data.Modifies);
+
+         --  Call itself for all imported projects
+
+         Imported_Project_List := Data.Imported_Projects;
+         while Imported_Project_List /= Empty_Project_List loop
+            Recursive_Check
+              (Project_Lists.Table (Imported_Project_List).Project);
+            Imported_Project_List :=
+              Project_Lists.Table (Imported_Project_List).Next;
+         end loop;
+
+         --  Mark project as checked
+
+         Projects.Table (Project).Checked := True;
+
+         if Opt.Verbose_Mode then
+            Write_Str ("Checking project file """);
+            Write_Str (Get_Name_String (Data.Name));
+            Write_Line ("""");
+         end if;
+
+         Prj.Nmsc.Check_Naming_Scheme (Project, Error_Report);
+      end if;
+
+   end Recursive_Check;
+
+   -----------------------
+   -- Recursive_Process --
+   -----------------------
+
+   procedure Recursive_Process
+     (Project           : out Project_Id;
+      From_Project_Node : Project_Node_Id;
+      Modified_By       : Project_Id)
+   is
+      With_Clause : Project_Node_Id;
+
+   begin
+      if From_Project_Node = Empty_Node then
+         Project := No_Project;
+
+      else
+         declare
+            Processed_Data   : Project_Data := Empty_Project;
+            Imported         : Project_List := Empty_Project_List;
+            Declaration_Node : Project_Node_Id := Empty_Node;
+            Name             : constant Name_Id :=
+                                 Name_Of (From_Project_Node);
+
+         begin
+            Project := Processed_Projects.Get (Name);
+
+            if Project /= No_Project then
+               return;
+            end if;
+
+            Projects.Increment_Last;
+            Project := Projects.Last;
+            Processed_Projects.Set (Name, Project);
+            Processed_Data.Name        := Name;
+            Processed_Data.Path_Name   := Path_Name_Of (From_Project_Node);
+            Processed_Data.Location    := Location_Of (From_Project_Node);
+            Processed_Data.Directory   := Directory_Of (From_Project_Node);
+            Processed_Data.Modified_By := Modified_By;
+            Add_Attributes (Processed_Data.Decl, Attribute_First);
+            With_Clause := First_With_Clause_Of (From_Project_Node);
+
+            while With_Clause /= Empty_Node loop
+               declare
+                  New_Project : Project_Id;
+                  New_Data    : Project_Data;
+
+               begin
+                  Recursive_Process
+                    (Project           => New_Project,
+                     From_Project_Node => Project_Node_Of (With_Clause),
+                     Modified_By       => No_Project);
+                  New_Data := Projects.Table (New_Project);
+
+                  --  If we were the first project to import it,
+                  --  set First_Referred_By to us.
+
+                  if New_Data.First_Referred_By = No_Project then
+                     New_Data.First_Referred_By := Project;
+                     Projects.Table (New_Project) := New_Data;
+                  end if;
+
+                  --  Add this project to our list of imported projects
+
+                  Project_Lists.Increment_Last;
+                  Project_Lists.Table (Project_Lists.Last) :=
+                    (Project => New_Project, Next => Empty_Project_List);
+
+                  --  Imported is the id of the last imported project.
+                  --  If it is nil, then this imported project is our first.
+
+                  if Imported = Empty_Project_List then
+                     Processed_Data.Imported_Projects := Project_Lists.Last;
+
+                  else
+                     Project_Lists.Table (Imported).Next := Project_Lists.Last;
+                  end if;
+
+                  Imported := Project_Lists.Last;
+
+                  With_Clause := Next_With_Clause_Of (With_Clause);
+               end;
+            end loop;
+
+            Declaration_Node := Project_Declaration_Of (From_Project_Node);
+
+            Recursive_Process
+              (Project           => Processed_Data.Modifies,
+               From_Project_Node => Modified_Project_Of (Declaration_Node),
+               Modified_By       => Project);
+
+            Projects.Table (Project) := Processed_Data;
+
+            Process_Declarative_Items
+              (Project           => Project,
+               From_Project_Node => From_Project_Node,
+               Pkg               => No_Package,
+               Item              => First_Declarative_Item_Of
+                                      (Declaration_Node));
+
+         end;
+      end if;
+   end Recursive_Process;
+
+end Prj.Proc;
diff --git a/gcc/ada/prj-proc.ads b/gcc/ada/prj-proc.ads
new file mode 100644 (file)
index 0000000..63259a4
--- /dev/null
@@ -0,0 +1,45 @@
+------------------------------------------------------------------------------
+--                                                                          --
+--                         GNAT COMPILER COMPONENTS                         --
+--                                                                          --
+--                              P R J . P R O C                             --
+--                                                                          --
+--                                 S p e c                                  --
+--                                                                          --
+--                            $Revision: 1.2 $
+--                                                                          --
+--             Copyright (C) 2001 Free Software Foundation, Inc.            --
+--                                                                          --
+-- GNAT is free software;  you can  redistribute it  and/or modify it under --
+-- terms of the  GNU General Public License as published  by the Free Soft- --
+-- ware  Foundation;  either version 2,  or (at your option) any later ver- --
+-- sion.  GNAT is distributed in the hope that it will be useful, but WITH- --
+-- OUT 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  distributed with GNAT;  see file COPYING.  If not, write --
+-- to  the Free Software Foundation,  59 Temple Place - Suite 330,  Boston, --
+-- MA 02111-1307, USA.                                                      --
+--                                                                          --
+-- GNAT was originally developed  by the GNAT team at  New York University. --
+-- It is now maintained by Ada Core Technologies Inc (http://www.gnat.com). --
+--                                                                          --
+------------------------------------------------------------------------------
+--
+--  This package is used to convert a project file tree (see prj-tree.ads) to
+--  project file data structures (see prj.ads), taking into account
+--  the environment (external references).
+
+with Prj.Tree;  use Prj.Tree;
+
+package Prj.Proc is
+
+   procedure Process
+     (Project           : out Project_Id;
+      From_Project_Node : Project_Node_Id;
+      Report_Error      : Put_Line_Access);
+   --  Process a project file tree into project file data structures.
+   --  If Report_Error is null, use the standard error reporting mechanism
+   --  (Errout). Otherwise, report errors using Report_Error.
+
+end Prj.Proc;
diff --git a/gcc/ada/prj-strt.adb b/gcc/ada/prj-strt.adb
new file mode 100644 (file)
index 0000000..790c632
--- /dev/null
@@ -0,0 +1,943 @@
+------------------------------------------------------------------------------
+--                                                                          --
+--                         GNAT COMPILER COMPONENTS                         --
+--                                                                          --
+--                             P R J . S T R T                              --
+--                                                                          --
+--                                 B o d y                                  --
+--                                                                          --
+--                            $Revision: 1.12 $
+--                                                                          --
+--             Copyright (C) 2001 Free Software Foundation, Inc.            --
+--                                                                          --
+-- GNAT is free software;  you can  redistribute it  and/or modify it under --
+-- terms of the  GNU General Public License as published  by the Free Soft- --
+-- ware  Foundation;  either version 2,  or (at your option) any later ver- --
+-- sion.  GNAT is distributed in the hope that it will be useful, but WITH- --
+-- OUT 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  distributed with GNAT;  see file COPYING.  If not, write --
+-- to  the Free Software Foundation,  59 Temple Place - Suite 330,  Boston, --
+-- MA 02111-1307, USA.                                                      --
+--                                                                          --
+-- GNAT was originally developed  by the GNAT team at  New York University. --
+-- It is now maintained by Ada Core Technologies Inc (http://www.gnat.com). --
+--                                                                          --
+------------------------------------------------------------------------------
+
+with Errout;    use Errout;
+with Prj.Attr;  use Prj.Attr;
+with Prj.Tree;  use Prj.Tree;
+with Scans;     use Scans;
+with Sinfo;     use Sinfo;
+with Stringt;   use Stringt;
+with Table;
+with Types;     use Types;
+
+package body Prj.Strt is
+
+   Initial_Size : constant := 8;
+
+   type Name_Location is record
+      Name     : Name_Id := No_Name;
+      Location : Source_Ptr := No_Location;
+   end record;
+   --  Store the identifier and the location of a simple name
+
+   type Name_Range is range 0 .. 3;
+   subtype Name_Index is Name_Range range 1 .. Name_Range'Last;
+   --  A Name may contain up to 3 simple names
+
+   type Names is array (Name_Index) of Name_Location;
+   --  Used to store 1 to 3 simple_names. 2 simple names are for
+   --  <project>.<package>, <project>.<variable> or <package>.<variable>.
+   --  3 simple names are for <project>.<package>.<variable>.
+
+   type Choice_String is record
+      The_String : String_Id;
+      Already_Used : Boolean := False;
+   end record;
+   --  The string of a case label, and an indication that it has already
+   --  been used (to avoid duplicate case labels).
+
+   Choices_Initial   : constant := 10;
+   Choices_Increment : constant := 10;
+
+   Choice_Node_Low_Bound  : constant := 0;
+   Choice_Node_High_Bound : constant := 099_999_999; --  In practice, infinite
+
+   type Choice_Node_Id is
+     range Choice_Node_Low_Bound .. Choice_Node_High_Bound;
+
+   First_Choice_Node_Id : constant Choice_Node_Id :=
+     Choice_Node_Low_Bound;
+
+   Empty_Choice : constant Choice_Node_Id :=
+     Choice_Node_Low_Bound;
+
+   First_Choice_Id : constant Choice_Node_Id := First_Choice_Node_Id + 1;
+
+   package Choices is
+      new Table.Table (Table_Component_Type => Choice_String,
+                       Table_Index_Type     => Choice_Node_Id,
+                       Table_Low_Bound      => First_Choice_Node_Id,
+                       Table_Initial        => Choices_Initial,
+                       Table_Increment      => Choices_Increment,
+                       Table_Name           => "Prj.Strt.Choices");
+   --  Used to store the case labels and check that there is no duplicate.
+
+   package Choice_Lasts is
+      new Table.Table (Table_Component_Type => Choice_Node_Id,
+                       Table_Index_Type     => Nat,
+                       Table_Low_Bound      => 1,
+                       Table_Initial        => 3,
+                       Table_Increment      => 3,
+                       Table_Name           => "Prj.Strt.Choice_Lasts");
+   --  Used to store the indices of the choices in table Choices,
+   --  to distinguish nested case constructions.
+
+   Choice_First : Choice_Node_Id := 0;
+   --  Index in table Choices of the first case label of the current
+   --  case construction.
+   --  0 means no current case construction.
+
+   procedure Add (This_String : String_Id);
+   --  Add a string to the case label list, indicating that it has not
+   --  yet been used.
+
+   procedure External_Reference (External_Value : out Project_Node_Id);
+   --  Parse an external reference. Current token is "external".
+
+   procedure Attribute_Reference
+     (Reference       : out Project_Node_Id;
+      First_Attribute : Attribute_Node_Id;
+      Current_Project : Project_Node_Id;
+      Current_Package : Project_Node_Id);
+   --  Parse an attribute reference. Current token is an apostrophe.
+
+   procedure Terms
+     (Term            : out Project_Node_Id;
+      Expr_Kind       : in out Variable_Kind;
+      Current_Project : Project_Node_Id;
+      Current_Package : Project_Node_Id);
+   --  Recursive procedure to parse one term or several terms concatenated
+   --  using "&".
+
+   ---------
+   -- Add --
+   ---------
+
+   procedure Add (This_String : String_Id) is
+   begin
+      Choices.Increment_Last;
+      Choices.Table (Choices.Last) :=
+        (The_String   => This_String,
+         Already_Used => False);
+   end Add;
+
+   -------------------------
+   -- Attribute_Reference --
+   -------------------------
+
+   procedure Attribute_Reference
+     (Reference       : out Project_Node_Id;
+      First_Attribute : Attribute_Node_Id;
+      Current_Project : Project_Node_Id;
+      Current_Package : Project_Node_Id)
+   is
+      Current_Attribute : Attribute_Node_Id := First_Attribute;
+
+   begin
+      Reference :=  Default_Project_Node (Of_Kind => N_Attribute_Reference);
+      Set_Location_Of (Reference, To => Token_Ptr);
+      Scan; -- past apostrophe
+      Expect (Tok_Identifier, "Identifier");
+
+      if Token = Tok_Identifier then
+         Set_Name_Of (Reference, To => Token_Name);
+
+         while Current_Attribute /= Empty_Attribute
+           and then
+             Attributes.Table (Current_Attribute).Name /= Token_Name
+         loop
+            Current_Attribute := Attributes.Table (Current_Attribute).Next;
+         end loop;
+
+         if Current_Attribute = Empty_Attribute then
+            Error_Msg ("unknown attribute", Token_Ptr);
+            Reference := Empty_Node;
+
+         elsif
+           Attributes.Table (Current_Attribute).Kind_2 = Associative_Array
+         then
+            Error_Msg
+              ("associative array attribute cannot be referenced",
+               Token_Ptr);
+            Reference := Empty_Node;
+
+         else
+            Set_Project_Node_Of (Reference, To => Current_Project);
+            Set_Package_Node_Of (Reference, To => Current_Package);
+            Set_Expression_Kind_Of
+              (Reference, To => Attributes.Table (Current_Attribute).Kind_1);
+            Scan;
+         end if;
+      end if;
+   end Attribute_Reference;
+
+   ---------------------------
+   -- End_Case_Construction --
+   ---------------------------
+
+   procedure End_Case_Construction is
+   begin
+      if Choice_Lasts.Last = 1 then
+         Choice_Lasts.Set_Last (0);
+         Choices.Set_Last (First_Choice_Node_Id);
+         Choice_First := 0;
+
+      elsif Choice_Lasts.Last = 2 then
+         Choice_Lasts.Set_Last (1);
+         Choices.Set_Last (Choice_Lasts.Table (1));
+         Choice_First := 1;
+
+      else
+         Choice_Lasts.Decrement_Last;
+         Choices.Set_Last (Choice_Lasts.Table (Choice_Lasts.Last));
+         Choice_First := Choice_Lasts.Table (Choice_Lasts.Last - 1) + 1;
+      end if;
+   end End_Case_Construction;
+
+   ------------------------
+   -- External_Reference --
+   ------------------------
+
+   procedure External_Reference (External_Value : out Project_Node_Id) is
+      Field_Id : Project_Node_Id := Empty_Node;
+
+   begin
+      External_Value :=
+        Default_Project_Node (Of_Kind       => N_External_Value,
+                              And_Expr_Kind => Single);
+      Set_Location_Of (External_Value, To => Token_Ptr);
+
+      --  The current token is External
+
+      --  Get the left parenthesis
+
+      Scan;
+      Expect (Tok_Left_Paren, "(");
+
+      --  Scan past the left parenthesis
+
+      if Token = Tok_Left_Paren then
+         Scan;
+      end if;
+
+      --  Get the name of the external reference
+
+      Expect (Tok_String_Literal, "literal string");
+
+      if Token = Tok_String_Literal then
+         Field_Id :=
+           Default_Project_Node (Of_Kind       => N_Literal_String,
+                                 And_Expr_Kind => Single);
+         Set_String_Value_Of (Field_Id, To => Strval (Token_Node));
+         Set_External_Reference_Of (External_Value, To => Field_Id);
+
+         --  Scan past the first argument
+
+         Scan;
+
+         case Token is
+
+            when Tok_Right_Paren =>
+
+               --  Scan past the right parenthesis
+               Scan;
+
+            when Tok_Comma =>
+
+               --  Scan past the comma
+
+               Scan;
+
+               Expect (Tok_String_Literal, "literal string");
+
+               --  Get the default
+
+               if Token = Tok_String_Literal then
+                  Field_Id :=
+                    Default_Project_Node (Of_Kind       => N_Literal_String,
+                                          And_Expr_Kind => Single);
+                  Set_String_Value_Of (Field_Id, To => Strval (Token_Node));
+                  Set_External_Default_Of (External_Value, To => Field_Id);
+                  Scan;
+                  Expect (Tok_Right_Paren, ")");
+               end if;
+
+               --  Scan past the right parenthesis
+               if Token = Tok_Right_Paren then
+                  Scan;
+               end if;
+
+            when others =>
+               Error_Msg ("',' or ')' expected", Token_Ptr);
+         end case;
+      end if;
+   end External_Reference;
+
+   -----------------------
+   -- Parse_Choice_List --
+   -----------------------
+
+   procedure Parse_Choice_List (First_Choice : out Project_Node_Id) is
+      Current_Choice : Project_Node_Id := Empty_Node;
+      Next_Choice    : Project_Node_Id := Empty_Node;
+      Choice_String  : String_Id       := No_String;
+      Found          : Boolean         := False;
+
+   begin
+      First_Choice :=
+        Default_Project_Node (Of_Kind       => N_Literal_String,
+                              And_Expr_Kind => Single);
+      Current_Choice := First_Choice;
+
+      loop
+         Expect (Tok_String_Literal, "literal string");
+         exit when Token /= Tok_String_Literal;
+         Set_Location_Of (Current_Choice, To => Token_Ptr);
+         Choice_String := Strval (Token_Node);
+         Set_String_Value_Of (Current_Choice, To => Choice_String);
+
+         Found := False;
+         for Choice in Choice_First .. Choices.Last loop
+            if String_Equal (Choices.Table (Choice).The_String,
+                             Choice_String)
+            then
+               Found := True;
+
+               if Choices.Table (Choice).Already_Used then
+                  Error_Msg ("duplicate case label", Token_Ptr);
+               else
+                  Choices.Table (Choice).Already_Used := True;
+               end if;
+
+               exit;
+            end if;
+         end loop;
+
+         if not Found then
+            Error_Msg ("illegal case label", Token_Ptr);
+         end if;
+
+         Scan;
+
+         if Token = Tok_Vertical_Bar then
+            Next_Choice :=
+              Default_Project_Node (Of_Kind       => N_Literal_String,
+                                    And_Expr_Kind => Single);
+            Set_Next_Literal_String (Current_Choice, To => Next_Choice);
+            Current_Choice := Next_Choice;
+            Scan;
+         else
+            exit;
+         end if;
+      end loop;
+   end Parse_Choice_List;
+
+   ----------------------
+   -- Parse_Expression --
+   ----------------------
+
+   procedure Parse_Expression
+     (Expression      : out Project_Node_Id;
+      Current_Project : Project_Node_Id;
+      Current_Package : Project_Node_Id)
+   is
+      First_Term      : Project_Node_Id := Empty_Node;
+      Expression_Kind : Variable_Kind := Undefined;
+
+   begin
+      Expression := Default_Project_Node (Of_Kind => N_Expression);
+      Set_Location_Of (Expression, To => Token_Ptr);
+      Terms (Term            => First_Term,
+             Expr_Kind       => Expression_Kind,
+             Current_Project => Current_Project,
+             Current_Package => Current_Package);
+      Set_First_Term (Expression, To => First_Term);
+      Set_Expression_Kind_Of (Expression, To => Expression_Kind);
+   end Parse_Expression;
+
+   ----------------------------
+   -- Parse_String_Type_List --
+   ----------------------------
+
+   procedure Parse_String_Type_List (First_String : out Project_Node_Id) is
+      Last_String  : Project_Node_Id := Empty_Node;
+      Next_String  : Project_Node_Id := Empty_Node;
+      String_Value : String_Id := No_String;
+
+   begin
+      First_String :=
+        Default_Project_Node (Of_Kind       => N_Literal_String,
+                              And_Expr_Kind => Single);
+      Last_String := First_String;
+
+      loop
+         Expect (Tok_String_Literal, "literal string");
+         exit when Token /= Tok_String_Literal;
+         String_Value := Strval (Token_Node);
+         Set_String_Value_Of (Last_String, To => String_Value);
+         Set_Location_Of (Last_String, To => Token_Ptr);
+
+         declare
+            Current : Project_Node_Id := First_String;
+
+         begin
+            while Current /= Last_String loop
+               if String_Equal (String_Value_Of (Current), String_Value) then
+                  Error_Msg ("duplicate value in type", Token_Ptr);
+                  exit;
+               end if;
+
+               Current := Next_Literal_String (Current);
+            end loop;
+         end;
+
+         Scan;
+
+         if Token /= Tok_Comma then
+            exit;
+
+         else
+            Next_String :=
+              Default_Project_Node (Of_Kind       => N_Literal_String,
+                                    And_Expr_Kind => Single);
+            Set_Next_Literal_String (Last_String, To => Next_String);
+            Last_String := Next_String;
+            Scan;
+         end if;
+      end loop;
+   end Parse_String_Type_List;
+
+   ------------------------------
+   -- Parse_Variable_Reference --
+   ------------------------------
+
+   procedure Parse_Variable_Reference
+     (Variable        : out Project_Node_Id;
+      Current_Project : Project_Node_Id;
+      Current_Package : Project_Node_Id)
+   is
+      The_Names        : Names;
+      Last_Name        : Name_Range := 0;
+      Current_Variable : Project_Node_Id := Empty_Node;
+
+      The_Package : Project_Node_Id := Current_Package;
+      The_Project : Project_Node_Id := Current_Project;
+
+      Specified_Project : Project_Node_Id   := Empty_Node;
+      Specified_Package : Project_Node_Id   := Empty_Node;
+      Look_For_Variable : Boolean           := True;
+      First_Attribute   : Attribute_Node_Id := Empty_Attribute;
+      Variable_Name     : Name_Id;
+
+   begin
+      for Index in The_Names'Range loop
+         Expect (Tok_Identifier, "identifier");
+
+         if Token /= Tok_Identifier then
+            Look_For_Variable := False;
+            exit;
+         end if;
+
+         Last_Name := Last_Name + 1;
+         The_Names (Last_Name) :=
+           (Name     => Token_Name,
+            Location => Token_Ptr);
+         Scan;
+         exit when Token /= Tok_Dot;
+         Scan;
+      end loop;
+
+      if Look_For_Variable then
+         if Token = Tok_Apostrophe then
+
+            --  Attribute reference
+
+            case Last_Name is
+               when 0 =>
+
+                  --  Cannot happen
+
+                  null;
+
+               when 1 =>
+                  for Index in Package_First .. Package_Attributes.Last loop
+                     if Package_Attributes.Table (Index).Name =
+                                                      The_Names (1).Name
+                     then
+                        First_Attribute :=
+                          Package_Attributes.Table (Index).First_Attribute;
+                        exit;
+                     end if;
+                  end loop;
+
+                  if First_Attribute /= Empty_Attribute then
+                     The_Package := First_Package_Of (Current_Project);
+                     while The_Package /= Empty_Node
+                       and then Name_Of (The_Package) /= The_Names (1).Name
+                     loop
+                        The_Package := Next_Package_In_Project (The_Package);
+                     end loop;
+
+                     if The_Package = Empty_Node then
+                        Error_Msg ("package not yet defined",
+                                   The_Names (1).Location);
+                     end if;
+
+                  else
+                     First_Attribute := Attribute_First;
+                     The_Package     := Empty_Node;
+
+                     declare
+                        The_Project_Name_And_Node :
+                          constant Tree_Private_Part.Project_Name_And_Node :=
+                            Tree_Private_Part.Projects_Htable.Get
+                                                          (The_Names (1).Name);
+
+                        use Tree_Private_Part;
+
+                     begin
+                        if The_Project_Name_And_Node =
+                                   Tree_Private_Part.No_Project_Name_And_Node
+                        then
+                           Error_Msg ("unknown project",
+                                      The_Names (1).Location);
+                        else
+                           The_Project := The_Project_Name_And_Node.Node;
+                        end if;
+                     end;
+                  end if;
+
+               when 2 =>
+                  declare
+                     With_Clause : Project_Node_Id :=
+                                     First_With_Clause_Of (Current_Project);
+
+                  begin
+                     while With_Clause /= Empty_Node loop
+                        The_Project := Project_Node_Of (With_Clause);
+                        exit when Name_Of (The_Project) = The_Names (1).Name;
+                        With_Clause := Next_With_Clause_Of (With_Clause);
+                     end loop;
+
+                     if With_Clause = Empty_Node then
+                        Error_Msg ("unknown project",
+                                   The_Names (1).Location);
+                        The_Project := Empty_Node;
+                        The_Package := Empty_Node;
+                        First_Attribute := Attribute_First;
+
+                     else
+                        The_Package := First_Package_Of (The_Project);
+                        while The_Package /= Empty_Node
+                          and then Name_Of (The_Package) /= The_Names (2).Name
+                        loop
+                           The_Package :=
+                             Next_Package_In_Project (The_Package);
+                        end loop;
+
+                        if The_Package = Empty_Node then
+                           Error_Msg ("package not declared in project",
+                                      The_Names (2).Location);
+                           First_Attribute := Attribute_First;
+
+                        else
+                           First_Attribute :=
+                             Package_Attributes.Table
+                             (Package_Id_Of (The_Package)).First_Attribute;
+                        end if;
+                     end if;
+                  end;
+
+               when 3 =>
+                  Error_Msg
+                    ("too many single names for an attribute reference",
+                     The_Names (1).Location);
+                  Scan;
+                  Variable := Empty_Node;
+                  return;
+            end case;
+
+            Attribute_Reference
+              (Variable,
+               Current_Project => The_Project,
+               Current_Package => The_Package,
+               First_Attribute => First_Attribute);
+            return;
+         end if;
+      end if;
+
+      Variable :=
+        Default_Project_Node (Of_Kind => N_Variable_Reference);
+
+      if Look_For_Variable then
+         case Last_Name is
+            when 0 =>
+
+               --  Cannot happen
+
+               null;
+
+            when 1 =>
+               Set_Name_Of (Variable, To => The_Names (1).Name);
+
+            --  Header comment needed ???
+
+            when 2 =>
+               Set_Name_Of (Variable, To => The_Names (2).Name);
+               The_Package := First_Package_Of (Current_Project);
+
+               while The_Package /= Empty_Node
+                 and then Name_Of (The_Package) /= The_Names (1).Name
+               loop
+                  The_Package := Next_Package_In_Project (The_Package);
+               end loop;
+
+               if The_Package /= Empty_Node then
+                  Specified_Package := The_Package;
+                  The_Project := Empty_Node;
+
+               else
+                  declare
+                     With_Clause : Project_Node_Id :=
+                                     First_With_Clause_Of (Current_Project);
+
+                  begin
+                     while With_Clause /= Empty_Node loop
+                        The_Project := Project_Node_Of (With_Clause);
+                        exit when Name_Of (The_Project) = The_Names (1).Name;
+                        With_Clause := Next_With_Clause_Of (With_Clause);
+                     end loop;
+
+                     if With_Clause = Empty_Node then
+                        The_Project :=
+                          Modified_Project_Of
+                                 (Project_Declaration_Of (Current_Project));
+
+                        if The_Project /= Empty_Node
+                          and then
+                            Name_Of (The_Project) /= The_Names (1).Name
+                        then
+                           The_Project := Empty_Node;
+                        end if;
+                     end if;
+
+                     if The_Project = Empty_Node then
+                        Error_Msg ("unknown package or project",
+                                   The_Names (1).Location);
+                        Look_For_Variable := False;
+                     else
+                        Specified_Project := The_Project;
+                     end if;
+                  end;
+               end if;
+
+            --  Header comment needed ???
+
+            when 3 =>
+               Set_Name_Of (Variable, To => The_Names (3).Name);
+
+               declare
+                  With_Clause : Project_Node_Id :=
+                                  First_With_Clause_Of (Current_Project);
+
+               begin
+                  while With_Clause /= Empty_Node loop
+                     The_Project := Project_Node_Of (With_Clause);
+                     exit when Name_Of (The_Project) = The_Names (1).Name;
+                     With_Clause := Next_With_Clause_Of (With_Clause);
+                  end loop;
+
+                  if With_Clause = Empty_Node then
+                     The_Project :=
+                       Modified_Project_Of
+                          (Project_Declaration_Of (Current_Project));
+
+                     if The_Project /= Empty_Node
+                       and then Name_Of (The_Project) /= The_Names (1).Name
+                     then
+                        The_Project := Empty_Node;
+                     end if;
+                  end if;
+
+                  if The_Project = Empty_Node then
+                     Error_Msg ("unknown package or project",
+                                The_Names (1).Location);
+                     Look_For_Variable := False;
+
+                  else
+                     Specified_Project := The_Project;
+                     The_Package := First_Package_Of (The_Project);
+
+                     while The_Package /= Empty_Node
+                       and then Name_Of (The_Package) /= The_Names (2).Name
+                     loop
+                        The_Package := Next_Package_In_Project (The_Package);
+                     end loop;
+
+                     if The_Package = Empty_Node then
+                        Error_Msg ("unknown package",
+                                   The_Names (2).Location);
+                        Look_For_Variable := False;
+
+                     else
+                        Specified_Package := The_Package;
+                        The_Project := Empty_Node;
+                     end if;
+                  end if;
+               end;
+
+         end case;
+      end if;
+
+      if Look_For_Variable then
+         Variable_Name := Name_Of (Variable);
+         Set_Project_Node_Of (Variable, To => Specified_Project);
+         Set_Package_Node_Of (Variable, To => Specified_Package);
+
+         if The_Package /= Empty_Node then
+            Current_Variable := First_Variable_Of (The_Package);
+
+            while Current_Variable /= Empty_Node
+              and then
+              Name_Of (Current_Variable) /= Variable_Name
+            loop
+               Current_Variable := Next_Variable (Current_Variable);
+            end loop;
+         end if;
+
+         if Current_Variable = Empty_Node
+           and then The_Project /= Empty_Node
+         then
+            Current_Variable := First_Variable_Of (The_Project);
+            while Current_Variable /= Empty_Node
+              and then Name_Of (Current_Variable) /= Variable_Name
+            loop
+               Current_Variable := Next_Variable (Current_Variable);
+            end loop;
+         end if;
+
+         if Current_Variable = Empty_Node then
+            Error_Msg ("unknown variable", The_Names (Last_Name).Location);
+         end if;
+      end if;
+
+      if Current_Variable /= Empty_Node then
+         Set_Expression_Kind_Of
+           (Variable, To => Expression_Kind_Of (Current_Variable));
+
+         if Kind_Of (Current_Variable) = N_Typed_Variable_Declaration then
+            Set_String_Type_Of
+              (Variable, To => String_Type_Of (Current_Variable));
+         end if;
+      end if;
+   end Parse_Variable_Reference;
+
+   ---------------------------------
+   -- Start_New_Case_Construction --
+   ---------------------------------
+
+   procedure Start_New_Case_Construction (String_Type  : Project_Node_Id) is
+      Current_String : Project_Node_Id;
+
+   begin
+      if Choice_First = 0 then
+         Choice_First := 1;
+         Choices.Set_Last (First_Choice_Node_Id);
+      else
+         Choice_First := Choices.Last + 1;
+      end if;
+
+      if String_Type /= Empty_Node then
+         Current_String := First_Literal_String (String_Type);
+
+         while Current_String /= Empty_Node loop
+            Add (This_String => String_Value_Of (Current_String));
+            Current_String := Next_Literal_String (Current_String);
+         end loop;
+      end if;
+
+      Choice_Lasts.Increment_Last;
+      Choice_Lasts.Table (Choice_Lasts.Last) := Choices.Last;
+
+   end Start_New_Case_Construction;
+
+   -----------
+   -- Terms --
+   -----------
+
+   procedure Terms (Term            : out Project_Node_Id;
+                    Expr_Kind       : in out Variable_Kind;
+                    Current_Project : Project_Node_Id;
+                    Current_Package : Project_Node_Id)
+   is
+      Next_Term          : Project_Node_Id := Empty_Node;
+      Term_Id            : Project_Node_Id := Empty_Node;
+      Current_Expression : Project_Node_Id := Empty_Node;
+      Next_Expression    : Project_Node_Id := Empty_Node;
+      Current_Location   : Source_Ptr      := No_Location;
+      Reference          : Project_Node_Id := Empty_Node;
+
+   begin
+      Term := Default_Project_Node (Of_Kind => N_Term);
+      Set_Location_Of (Term, To => Token_Ptr);
+
+      case Token is
+
+         when Tok_Left_Paren =>
+            case Expr_Kind is
+               when Undefined =>
+                  Expr_Kind := List;
+               when List =>
+                  null;
+               when Single =>
+                  Expr_Kind := List;
+                  Error_Msg
+                    ("literal string list cannot appear in a string",
+                     Token_Ptr);
+            end case;
+
+            Term_Id := Default_Project_Node
+              (Of_Kind => N_Literal_String_List,
+               And_Expr_Kind => List);
+            Set_Current_Term (Term, To => Term_Id);
+            Set_Location_Of (Term, To => Token_Ptr);
+
+            Scan;
+            if Token = Tok_Right_Paren then
+               Scan;
+
+            else
+               loop
+                  Current_Location := Token_Ptr;
+                  Parse_Expression (Expression      => Next_Expression,
+                                    Current_Project => Current_Project,
+                                    Current_Package => Current_Package);
+
+                  if Expression_Kind_Of (Next_Expression) = List then
+                     Error_Msg ("single expression expected",
+                                Current_Location);
+                  end if;
+
+                  if Current_Expression = Empty_Node then
+                     Set_First_Expression_In_List
+                       (Term_Id, To => Next_Expression);
+                  else
+                     Set_Next_Expression_In_List
+                       (Current_Expression, To => Next_Expression);
+                  end if;
+
+                  Current_Expression := Next_Expression;
+                  exit when Token /= Tok_Comma;
+                  Scan; -- past the comma
+               end loop;
+
+               Expect (Tok_Right_Paren, "(");
+
+               if Token = Tok_Right_Paren then
+                  Scan;
+               end if;
+            end if;
+
+         when Tok_String_Literal =>
+            if Expr_Kind = Undefined then
+               Expr_Kind := Single;
+            end if;
+
+            Term_Id := Default_Project_Node (Of_Kind => N_Literal_String);
+            Set_Current_Term (Term, To => Term_Id);
+            Set_String_Value_Of (Term_Id, To => Strval (Token_Node));
+
+            Scan;
+
+         when Tok_Identifier =>
+            Current_Location := Token_Ptr;
+            Parse_Variable_Reference
+              (Variable        => Reference,
+               Current_Project => Current_Project,
+               Current_Package => Current_Package);
+            Set_Current_Term (Term, To => Reference);
+
+            if Reference /= Empty_Node then
+               if Expr_Kind = Undefined then
+                  Expr_Kind := Expression_Kind_Of (Reference);
+
+               elsif Expr_Kind = Single
+                 and then Expression_Kind_Of (Reference) = List
+               then
+                  Expr_Kind := List;
+                  Error_Msg
+                    ("list variable cannot appear in single string expression",
+                     Current_Location);
+               end if;
+            end if;
+
+         when Tok_Project =>
+            Current_Location := Token_Ptr;
+            Scan;
+            Expect (Tok_Apostrophe, "'");
+
+            if Token = Tok_Apostrophe then
+               Attribute_Reference
+                 (Reference       => Reference,
+                  First_Attribute => Prj.Attr.Attribute_First,
+                  Current_Project => Current_Project,
+                  Current_Package => Empty_Node);
+               Set_Current_Term (Term, To => Reference);
+            end if;
+
+            if Reference /= Empty_Node then
+               if Expr_Kind = Undefined then
+                  Expr_Kind := Expression_Kind_Of (Reference);
+
+               elsif Expr_Kind = Single
+                 and then Expression_Kind_Of (Reference) = List
+               then
+                  Error_Msg
+                    ("lists cannot appear in single string expression",
+                     Current_Location);
+               end if;
+            end if;
+
+         when Tok_External =>
+            if Expr_Kind = Undefined then
+               Expr_Kind := Single;
+            end if;
+
+            External_Reference (External_Value => Reference);
+            Set_Current_Term (Term, To => Reference);
+
+         when others =>
+            Error_Msg ("cannot be part of an expression", Token_Ptr);
+            Term := Empty_Node;
+            return;
+      end case;
+
+      if Token = Tok_Ampersand then
+         Scan;
+
+         Terms (Term            => Next_Term,
+                Expr_Kind       => Expr_Kind,
+                Current_Project => Current_Project,
+                Current_Package => Current_Package);
+         Set_Next_Term (Term, To => Next_Term);
+
+      end if;
+
+   end Terms;
+
+end Prj.Strt;
diff --git a/gcc/ada/prj-strt.ads b/gcc/ada/prj-strt.ads
new file mode 100644 (file)
index 0000000..9bbdbeb
--- /dev/null
@@ -0,0 +1,96 @@
+------------------------------------------------------------------------------
+--                                                                          --
+--                         GNAT COMPILER COMPONENTS                         --
+--                                                                          --
+--                             P R J . S T R T                              --
+--                                                                          --
+--                                 S p e c                                  --
+--                                                                          --
+--                            $Revision: 1.4 $
+--                                                                          --
+--             Copyright (C) 2001 Free Software Foundation, Inc.            --
+--                                                                          --
+-- GNAT is free software;  you can  redistribute it  and/or modify it under --
+-- terms of the  GNU General Public License as published  by the Free Soft- --
+-- ware  Foundation;  either version 2,  or (at your option) any later ver- --
+-- sion.  GNAT is distributed in the hope that it will be useful, but WITH- --
+-- OUT 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  distributed with GNAT;  see file COPYING.  If not, write --
+-- to  the Free Software Foundation,  59 Temple Place - Suite 330,  Boston, --
+-- MA 02111-1307, USA.                                                      --
+--                                                                          --
+-- GNAT was originally developed  by the GNAT team at  New York University. --
+-- It is now maintained by Ada Core Technologies Inc (http://www.gnat.com). --
+--                                                                          --
+------------------------------------------------------------------------------
+--
+--  This package implements parsing of string expressions in project files.
+
+with Prj.Tree;  use Prj.Tree;
+
+private package Prj.Strt is
+
+   procedure Parse_String_Type_List (First_String : out Project_Node_Id);
+   --  Get the list of literal strings that are allowed for a typed string.
+   --  On entry, the current token is the first literal string following
+   --  a left parenthesis in a string type declaration such as:
+   --    type Toto is ("string_1", "string_2", "string_3");
+   --  On exit, the current token is the right parenthesis.
+   --  The parameter First_String is a node that contained the first
+   --  literal string of the string type, linked with the following
+   --  literal strings.
+   --
+   --  Report an error if
+   --    - a literal string is not found at the beginning of the list
+   --      or after a comma
+   --    - two literal strings in the list are equal
+
+   procedure Start_New_Case_Construction (String_Type : Project_Node_Id);
+   --  This procedure is called at the beginning of a case construction
+   --  The parameter String_Type is the node for the string type
+   --  of the case label variable.
+   --  The different literal strings of the string type are stored
+   --  into a table to be checked against the case labels of the
+   --  case construction.
+
+   procedure End_Case_Construction;
+   --  This procedure is called at the end of a case construction
+   --  to remove the case labels and to restore the previous state.
+   --  In particular, in the case of nested case constructions,
+   --  the case labels of the enclosing case construction are restored.
+
+   procedure Parse_Choice_List
+     (First_Choice : out Project_Node_Id);
+   --  Get the label for a choice list.
+   --  Report an error if
+   --    - a case label is not a literal string
+   --    - a case label is not in the typed string list
+   --    - the same case label is repeated in the same case construction
+
+   procedure Parse_Expression
+     (Expression      : out Project_Node_Id;
+      Current_Project : Project_Node_Id;
+      Current_Package : Project_Node_Id);
+   --  Parse a simple string expression or a string list expression.
+   --  Current_Project is the node of the project file being parsed.
+   --  Current_Package is the node of the package being parsed,
+   --  or Empty_Node when we are at the project level (not in a package).
+   --  On exit, Expression is the node of the expression that has
+   --  been parsed.
+
+   procedure Parse_Variable_Reference
+     (Variable        : out Project_Node_Id;
+      Current_Project : Project_Node_Id;
+      Current_Package : Project_Node_Id);
+   --  Parse a variable or attribute reference.
+   --  Used internally (in expressions) and for case variables (in Prj.Dect).
+   --  Current_Package is the node of the package being parsed,
+   --  or Empty_Node when we are at the project level (not in a package).
+   --  On exit, Variable is the node of the variable or attribute reference.
+   --  A variable reference is made of one to three simple names.
+   --  An attribute reference is made of one or two simple names,
+   --  followed by an apostroph, followed by the attribute simple name.
+
+end Prj.Strt;
diff --git a/gcc/ada/prj-tree.adb b/gcc/ada/prj-tree.adb
new file mode 100644 (file)
index 0000000..322e4aa
--- /dev/null
@@ -0,0 +1,1478 @@
+------------------------------------------------------------------------------
+--                                                                          --
+--                         GNAT COMPILER COMPONENTS                         --
+--                                                                          --
+--                              P R J . T R E E                             --
+--                                                                          --
+--                                 B o d y                                  --
+--                                                                          --
+--                            $Revision: 1.7 $
+--                                                                          --
+--             Copyright (C) 2001 Free Software Foundation, Inc.            --
+--                                                                          --
+-- GNAT is free software;  you can  redistribute it  and/or modify it under --
+-- terms of the  GNU General Public License as published  by the Free Soft- --
+-- ware  Foundation;  either version 2,  or (at your option) any later ver- --
+-- sion.  GNAT is distributed in the hope that it will be useful, but WITH- --
+-- OUT 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  distributed with GNAT;  see file COPYING.  If not, write --
+-- to  the Free Software Foundation,  59 Temple Place - Suite 330,  Boston, --
+-- MA 02111-1307, USA.                                                      --
+--                                                                          --
+-- GNAT was originally developed  by the GNAT team at  New York University. --
+-- It is now maintained by Ada Core Technologies Inc (http://www.gnat.com). --
+--                                                                          --
+------------------------------------------------------------------------------
+
+with Stringt; use Stringt;
+
+package body Prj.Tree is
+
+   use Tree_Private_Part;
+
+   --------------------------------
+   -- Associative_Array_Index_Of --
+   --------------------------------
+
+   function Associative_Array_Index_Of
+     (Node : Project_Node_Id)
+      return String_Id
+   is
+   begin
+      pragma Assert
+        (Node /= Empty_Node
+          and then
+            (Project_Nodes.Table (Node).Kind = N_Attribute_Declaration));
+      return Project_Nodes.Table (Node).Value;
+   end Associative_Array_Index_Of;
+
+   --------------------------------
+   -- Case_Variable_Reference_Of --
+   --------------------------------
+
+   function Case_Variable_Reference_Of
+     (Node : Project_Node_Id)
+      return Project_Node_Id
+   is
+   begin
+      pragma Assert
+        (Node /= Empty_Node
+          and then
+            Project_Nodes.Table (Node).Kind = N_Case_Construction);
+      return Project_Nodes.Table (Node).Field1;
+   end Case_Variable_Reference_Of;
+
+   -----------------------
+   -- Current_Item_Node --
+   -----------------------
+
+   function Current_Item_Node
+     (Node : Project_Node_Id)
+      return Project_Node_Id
+   is
+   begin
+      pragma Assert
+        (Node /= Empty_Node
+          and then
+            Project_Nodes.Table (Node).Kind = N_Declarative_Item);
+      return Project_Nodes.Table (Node).Field1;
+   end Current_Item_Node;
+
+   ------------------
+   -- Current_Term --
+   ------------------
+
+   function Current_Term
+     (Node : Project_Node_Id)
+      return Project_Node_Id
+   is
+   begin
+      pragma Assert
+        (Node /= Empty_Node
+          and then
+            Project_Nodes.Table (Node).Kind = N_Term);
+      return Project_Nodes.Table (Node).Field1;
+   end Current_Term;
+
+   --------------------------
+   -- Default_Project_Node --
+   --------------------------
+
+   function Default_Project_Node
+     (Of_Kind       : Project_Node_Kind;
+      And_Expr_Kind : Variable_Kind := Undefined)
+      return          Project_Node_Id
+   is
+   begin
+      Project_Nodes.Increment_Last;
+      Project_Nodes.Table (Project_Nodes.Last) :=
+           (Kind       => Of_Kind,
+            Location   => No_Location,
+            Directory  => No_Name,
+            Expr_Kind  => And_Expr_Kind,
+            Variables  => Empty_Node,
+            Packages   => Empty_Node,
+            Pkg_Id     => Empty_Package,
+            Name       => No_Name,
+            Path_Name  => No_Name,
+            Value      => No_String,
+            Field1     => Empty_Node,
+            Field2     => Empty_Node,
+            Field3     => Empty_Node);
+      return Project_Nodes.Last;
+   end Default_Project_Node;
+
+   ------------------
+   -- Directory_Of --
+   ------------------
+
+   function Directory_Of (Node : Project_Node_Id) return Name_Id is
+   begin
+      pragma Assert
+        (Node /= Empty_Node
+          and then
+            Project_Nodes.Table (Node).Kind = N_Project);
+      return Project_Nodes.Table (Node).Directory;
+   end Directory_Of;
+
+   ------------------------
+   -- Expression_Kind_Of --
+   ------------------------
+
+   function Expression_Kind_Of (Node : Project_Node_Id) return Variable_Kind is
+   begin
+      pragma Assert
+        (Node /= Empty_Node
+           and then
+             (Project_Nodes.Table (Node).Kind = N_Literal_String
+                or else
+              Project_Nodes.Table (Node).Kind = N_Attribute_Declaration
+                or else
+              Project_Nodes.Table (Node).Kind = N_Variable_Declaration
+                or else
+              Project_Nodes.Table (Node).Kind = N_Typed_Variable_Declaration
+                or else
+              Project_Nodes.Table (Node).Kind = N_Expression
+                or else
+              Project_Nodes.Table (Node).Kind = N_Term
+                or else
+              Project_Nodes.Table (Node).Kind = N_Variable_Reference
+                or else
+              Project_Nodes.Table (Node).Kind = N_Attribute_Reference));
+
+      return Project_Nodes.Table (Node).Expr_Kind;
+   end Expression_Kind_Of;
+
+   -------------------
+   -- Expression_Of --
+   -------------------
+
+   function Expression_Of
+     (Node : Project_Node_Id)
+      return Project_Node_Id
+   is
+   begin
+      pragma Assert
+        (Node /= Empty_Node
+          and then
+            (Project_Nodes.Table (Node).Kind = N_Attribute_Declaration
+               or else
+             Project_Nodes.Table (Node).Kind = N_Typed_Variable_Declaration
+               or else
+             Project_Nodes.Table (Node).Kind = N_Variable_Declaration));
+
+      return Project_Nodes.Table (Node).Field1;
+   end Expression_Of;
+
+   ---------------------------
+   -- External_Reference_Of --
+   ---------------------------
+
+   function External_Reference_Of
+     (Node : Project_Node_Id)
+      return Project_Node_Id
+   is
+   begin
+      pragma Assert
+        (Node /= Empty_Node
+          and then
+            Project_Nodes.Table (Node).Kind = N_External_Value);
+      return Project_Nodes.Table (Node).Field1;
+   end External_Reference_Of;
+
+   -------------------------
+   -- External_Default_Of --
+   -------------------------
+
+   function External_Default_Of
+     (Node : Project_Node_Id)
+      return Project_Node_Id
+   is
+   begin
+      pragma Assert
+        (Node /= Empty_Node
+          and then
+            Project_Nodes.Table (Node).Kind = N_External_Value);
+      return Project_Nodes.Table (Node).Field2;
+   end External_Default_Of;
+
+   ------------------------
+   -- First_Case_Item_Of --
+   ------------------------
+
+   function First_Case_Item_Of
+     (Node : Project_Node_Id)
+      return Project_Node_Id
+   is
+   begin
+      pragma Assert
+        (Node /= Empty_Node
+          and then
+            Project_Nodes.Table (Node).Kind = N_Case_Construction);
+      return Project_Nodes.Table (Node).Field2;
+   end First_Case_Item_Of;
+
+   ---------------------
+   -- First_Choice_Of --
+   ---------------------
+
+   function First_Choice_Of
+     (Node : Project_Node_Id)
+      return Project_Node_Id
+   is
+   begin
+      pragma Assert
+        (Node /= Empty_Node
+          and then
+            Project_Nodes.Table (Node).Kind = N_Case_Item);
+      return Project_Nodes.Table (Node).Field1;
+   end First_Choice_Of;
+
+   -------------------------------
+   -- First_Declarative_Item_Of --
+   -------------------------------
+
+   function First_Declarative_Item_Of
+     (Node : Project_Node_Id)
+      return Project_Node_Id
+   is
+   begin
+      pragma Assert
+        (Node /= Empty_Node
+          and then
+            (Project_Nodes.Table (Node).Kind = N_Project_Declaration
+               or else
+             Project_Nodes.Table (Node).Kind = N_Case_Item
+               or else
+             Project_Nodes.Table (Node).Kind = N_Package_Declaration));
+
+      if Project_Nodes.Table (Node).Kind = N_Project_Declaration then
+         return Project_Nodes.Table (Node).Field1;
+      else
+         return Project_Nodes.Table (Node).Field2;
+      end if;
+   end First_Declarative_Item_Of;
+
+   ------------------------------
+   -- First_Expression_In_List --
+   ------------------------------
+
+   function First_Expression_In_List
+     (Node : Project_Node_Id)
+      return Project_Node_Id
+   is
+   begin
+      pragma Assert
+        (Node /= Empty_Node
+          and then
+            Project_Nodes.Table (Node).Kind = N_Literal_String_List);
+      return Project_Nodes.Table (Node).Field1;
+   end First_Expression_In_List;
+
+   --------------------------
+   -- First_Literal_String --
+   --------------------------
+
+   function First_Literal_String
+     (Node : Project_Node_Id)
+      return Project_Node_Id
+   is
+   begin
+      pragma Assert
+        (Node /= Empty_Node
+          and then
+            Project_Nodes.Table (Node).Kind = N_String_Type_Declaration);
+      return Project_Nodes.Table (Node).Field1;
+   end First_Literal_String;
+
+   ----------------------
+   -- First_Package_Of --
+   ----------------------
+
+   function First_Package_Of
+     (Node : Project_Node_Id)
+      return Package_Declaration_Id
+   is
+   begin
+      pragma Assert
+        (Node /= Empty_Node
+          and then
+            Project_Nodes.Table (Node).Kind = N_Project);
+      return Project_Nodes.Table (Node).Packages;
+   end First_Package_Of;
+
+   --------------------------
+   -- First_String_Type_Of --
+   --------------------------
+
+   function First_String_Type_Of
+     (Node : Project_Node_Id)
+      return Project_Node_Id
+   is
+   begin
+      pragma Assert
+        (Node /= Empty_Node
+          and then
+            Project_Nodes.Table (Node).Kind = N_Project);
+      return Project_Nodes.Table (Node).Field3;
+   end First_String_Type_Of;
+
+   ----------------
+   -- First_Term --
+   ----------------
+
+   function First_Term
+     (Node : Project_Node_Id)
+      return Project_Node_Id
+   is
+   begin
+      pragma Assert
+        (Node /= Empty_Node
+          and then
+            Project_Nodes.Table (Node).Kind = N_Expression);
+      return Project_Nodes.Table (Node).Field1;
+   end First_Term;
+
+   -----------------------
+   -- First_Variable_Of --
+   -----------------------
+
+   function First_Variable_Of
+     (Node : Project_Node_Id)
+      return Variable_Node_Id
+   is
+   begin
+      pragma Assert
+        (Node /= Empty_Node
+          and then
+            (Project_Nodes.Table (Node).Kind = N_Project
+               or else
+             Project_Nodes.Table (Node).Kind = N_Package_Declaration));
+
+      return Project_Nodes.Table (Node).Variables;
+   end First_Variable_Of;
+
+   --------------------------
+   -- First_With_Clause_Of --
+   --------------------------
+
+   function First_With_Clause_Of
+     (Node : Project_Node_Id)
+      return Project_Node_Id
+   is
+   begin
+      pragma Assert
+        (Node /= Empty_Node
+          and then
+            Project_Nodes.Table (Node).Kind = N_Project);
+      return Project_Nodes.Table (Node).Field1;
+   end First_With_Clause_Of;
+
+   ----------------
+   -- Initialize --
+   ----------------
+
+   procedure Initialize is
+   begin
+      Project_Nodes.Set_Last (Empty_Node);
+      Projects_Htable.Reset;
+   end Initialize;
+
+   -------------
+   -- Kind_Of --
+   -------------
+
+   function Kind_Of (Node : Project_Node_Id) return Project_Node_Kind is
+   begin
+      pragma Assert (Node /= Empty_Node);
+      return Project_Nodes.Table (Node).Kind;
+   end Kind_Of;
+
+   -----------------
+   -- Location_Of --
+   -----------------
+
+   function Location_Of (Node : Project_Node_Id) return Source_Ptr is
+   begin
+      pragma Assert (Node /= Empty_Node);
+      return Project_Nodes.Table (Node).Location;
+   end Location_Of;
+
+   -------------------------
+   -- Modified_Project_Of --
+   -------------------------
+
+   function Modified_Project_Of
+     (Node : Project_Node_Id)
+      return Project_Node_Id
+   is
+   begin
+      pragma Assert
+        (Node /= Empty_Node
+          and then
+            Project_Nodes.Table (Node).Kind = N_Project_Declaration);
+      return Project_Nodes.Table (Node).Field2;
+   end Modified_Project_Of;
+
+   ------------------------------
+   -- Modified_Project_Path_Of --
+   ------------------------------
+
+   function Modified_Project_Path_Of
+     (Node : Project_Node_Id)
+      return String_Id
+   is
+   begin
+      pragma Assert
+        (Node /= Empty_Node
+          and then
+            Project_Nodes.Table (Node).Kind = N_Project);
+      return Project_Nodes.Table (Node).Value;
+   end Modified_Project_Path_Of;
+
+   -------------
+   -- Name_Of --
+   -------------
+
+   function Name_Of (Node : Project_Node_Id) return Name_Id is
+   begin
+      pragma Assert (Node /= Empty_Node);
+      return Project_Nodes.Table (Node).Name;
+   end Name_Of;
+
+   --------------------
+   -- Next_Case_Item --
+   --------------------
+
+   function Next_Case_Item
+     (Node : Project_Node_Id)
+      return Project_Node_Id
+   is
+   begin
+      pragma Assert
+        (Node /= Empty_Node
+          and then
+            Project_Nodes.Table (Node).Kind = N_Case_Item);
+      return Project_Nodes.Table (Node).Field3;
+   end Next_Case_Item;
+
+   ---------------------------
+   -- Next_Declarative_Item --
+   ---------------------------
+
+   function Next_Declarative_Item
+     (Node : Project_Node_Id)
+      return Project_Node_Id
+   is
+   begin
+      pragma Assert
+        (Node /= Empty_Node
+          and then
+            Project_Nodes.Table (Node).Kind = N_Declarative_Item);
+      return Project_Nodes.Table (Node).Field2;
+   end Next_Declarative_Item;
+
+   -----------------------------
+   -- Next_Expression_In_List --
+   -----------------------------
+
+   function Next_Expression_In_List
+     (Node : Project_Node_Id)
+      return Project_Node_Id
+   is
+   begin
+      pragma Assert
+        (Node /= Empty_Node
+          and then
+            Project_Nodes.Table (Node).Kind = N_Expression);
+      return Project_Nodes.Table (Node).Field2;
+   end Next_Expression_In_List;
+
+   -------------------------
+   -- Next_Literal_String --
+   -------------------------
+
+   function Next_Literal_String
+     (Node : Project_Node_Id)
+      return Project_Node_Id
+   is
+   begin
+      pragma Assert
+        (Node /= Empty_Node
+          and then
+            Project_Nodes.Table (Node).Kind = N_Literal_String);
+      return Project_Nodes.Table (Node).Field1;
+   end Next_Literal_String;
+
+   -----------------------------
+   -- Next_Package_In_Project --
+   -----------------------------
+
+   function Next_Package_In_Project
+     (Node : Project_Node_Id)
+      return Project_Node_Id
+   is
+   begin
+      pragma Assert
+        (Node /= Empty_Node
+          and then
+            Project_Nodes.Table (Node).Kind = N_Package_Declaration);
+      return Project_Nodes.Table (Node).Field3;
+   end Next_Package_In_Project;
+
+   ----------------------
+   -- Next_String_Type --
+   ----------------------
+
+   function Next_String_Type
+     (Node : Project_Node_Id)
+      return Project_Node_Id
+   is
+   begin
+      pragma Assert
+        (Node /= Empty_Node
+          and then
+            Project_Nodes.Table (Node).Kind = N_String_Type_Declaration);
+      return Project_Nodes.Table (Node).Field2;
+   end Next_String_Type;
+
+   ---------------
+   -- Next_Term --
+   ---------------
+
+   function Next_Term
+     (Node : Project_Node_Id)
+      return Project_Node_Id
+   is
+   begin
+      pragma Assert
+        (Node /= Empty_Node
+          and then
+            Project_Nodes.Table (Node).Kind = N_Term);
+      return Project_Nodes.Table (Node).Field2;
+   end Next_Term;
+
+   -------------------
+   -- Next_Variable --
+   -------------------
+
+   function Next_Variable
+     (Node : Project_Node_Id)
+      return Project_Node_Id
+   is
+   begin
+      pragma Assert
+        (Node /= Empty_Node
+          and then
+            (Project_Nodes.Table (Node).Kind = N_Typed_Variable_Declaration
+               or else
+             Project_Nodes.Table (Node).Kind = N_Variable_Declaration));
+
+      return Project_Nodes.Table (Node).Field3;
+   end Next_Variable;
+
+   -------------------------
+   -- Next_With_Clause_Of --
+   -------------------------
+
+   function Next_With_Clause_Of
+     (Node : Project_Node_Id)
+      return Project_Node_Id
+   is
+   begin
+      pragma Assert
+        (Node /= Empty_Node
+          and then
+            Project_Nodes.Table (Node).Kind = N_With_Clause);
+      return Project_Nodes.Table (Node).Field2;
+   end Next_With_Clause_Of;
+
+   -------------------
+   -- Package_Id_Of --
+   -------------------
+
+   function Package_Id_Of (Node : Project_Node_Id) return Package_Node_Id is
+   begin
+      pragma Assert
+        (Node /= Empty_Node
+          and then
+            Project_Nodes.Table (Node).Kind = N_Package_Declaration);
+      return Project_Nodes.Table (Node).Pkg_Id;
+   end Package_Id_Of;
+
+   ---------------------
+   -- Package_Node_Of --
+   ---------------------
+
+   function Package_Node_Of
+     (Node : Project_Node_Id)
+      return Project_Node_Id
+   is
+   begin
+      pragma Assert
+        (Node /= Empty_Node
+          and then
+            (Project_Nodes.Table (Node).Kind = N_Variable_Reference
+               or else
+             Project_Nodes.Table (Node).Kind = N_Attribute_Reference));
+      return Project_Nodes.Table (Node).Field2;
+   end Package_Node_Of;
+
+   ------------------
+   -- Path_Name_Of --
+   ------------------
+
+   function Path_Name_Of (Node : Project_Node_Id) return Name_Id is
+   begin
+      pragma Assert
+        (Node /= Empty_Node
+          and then
+            (Project_Nodes.Table (Node).Kind = N_Project
+               or else
+             Project_Nodes.Table (Node).Kind = N_With_Clause));
+      return Project_Nodes.Table (Node).Path_Name;
+   end Path_Name_Of;
+
+   ----------------------------
+   -- Project_Declaration_Of --
+   ----------------------------
+
+   function Project_Declaration_Of
+     (Node : Project_Node_Id)
+      return Project_Node_Id
+   is
+   begin
+      pragma Assert
+        (Node /= Empty_Node
+          and then
+            Project_Nodes.Table (Node).Kind = N_Project);
+      return Project_Nodes.Table (Node).Field2;
+   end Project_Declaration_Of;
+
+   ---------------------
+   -- Project_Node_Of --
+   ---------------------
+
+   function Project_Node_Of
+     (Node : Project_Node_Id)
+      return Project_Node_Id
+   is
+   begin
+      pragma Assert
+        (Node /= Empty_Node
+          and then
+           (Project_Nodes.Table (Node).Kind = N_With_Clause
+              or else
+            Project_Nodes.Table (Node).Kind = N_Variable_Reference
+              or else
+            Project_Nodes.Table (Node).Kind = N_Attribute_Reference));
+      return Project_Nodes.Table (Node).Field1;
+   end Project_Node_Of;
+
+   -----------------------------------
+   -- Project_Of_Renamed_Package_Of --
+   -----------------------------------
+
+   function Project_Of_Renamed_Package_Of
+     (Node : Project_Node_Id)
+      return Project_Node_Id
+   is
+   begin
+      pragma Assert
+        (Node /= Empty_Node
+          and then
+            Project_Nodes.Table (Node).Kind = N_Package_Declaration);
+      return Project_Nodes.Table (Node).Field1;
+   end Project_Of_Renamed_Package_Of;
+
+   ------------------------------------
+   -- Set_Associative_Array_Index_Of --
+   ------------------------------------
+
+   procedure Set_Associative_Array_Index_Of
+     (Node : Project_Node_Id;
+      To   : String_Id)
+   is
+   begin
+      pragma Assert
+        (Node /= Empty_Node
+          and then
+            Project_Nodes.Table (Node).Kind = N_Attribute_Declaration);
+      Project_Nodes.Table (Node).Value := To;
+   end Set_Associative_Array_Index_Of;
+
+   ------------------------------------
+   -- Set_Case_Variable_Reference_Of --
+   ------------------------------------
+
+   procedure Set_Case_Variable_Reference_Of
+     (Node : Project_Node_Id;
+      To   : Project_Node_Id)
+   is
+   begin
+      pragma Assert
+        (Node /= Empty_Node
+          and then
+            Project_Nodes.Table (Node).Kind = N_Case_Construction);
+      Project_Nodes.Table (Node).Field1 := To;
+   end Set_Case_Variable_Reference_Of;
+
+   ---------------------------
+   -- Set_Current_Item_Node --
+   ---------------------------
+
+   procedure Set_Current_Item_Node
+     (Node : Project_Node_Id;
+      To   : Project_Node_Id)
+   is
+   begin
+      pragma Assert
+        (Node /= Empty_Node
+          and then
+            Project_Nodes.Table (Node).Kind = N_Declarative_Item);
+      Project_Nodes.Table (Node).Field1 := To;
+   end Set_Current_Item_Node;
+
+   ----------------------
+   -- Set_Current_Term --
+   ----------------------
+
+   procedure Set_Current_Term
+     (Node : Project_Node_Id;
+      To   : Project_Node_Id)
+   is
+   begin
+      pragma Assert
+        (Node /= Empty_Node
+          and then
+            Project_Nodes.Table (Node).Kind = N_Term);
+      Project_Nodes.Table (Node).Field1 := To;
+   end Set_Current_Term;
+
+   ----------------------
+   -- Set_Directory_Of --
+   ----------------------
+
+   procedure Set_Directory_Of
+     (Node : Project_Node_Id;
+      To   : Name_Id)
+   is
+   begin
+      pragma Assert
+        (Node /= Empty_Node
+          and then
+            Project_Nodes.Table (Node).Kind = N_Project);
+      Project_Nodes.Table (Node).Directory := To;
+   end Set_Directory_Of;
+
+   ----------------------------
+   -- Set_Expression_Kind_Of --
+   ----------------------------
+
+   procedure Set_Expression_Kind_Of
+     (Node : Project_Node_Id;
+      To   : Variable_Kind)
+   is
+   begin
+      pragma Assert
+        (Node /= Empty_Node
+           and then
+             (Project_Nodes.Table (Node).Kind = N_Literal_String
+                or else
+              Project_Nodes.Table (Node).Kind = N_Attribute_Declaration
+                or else
+              Project_Nodes.Table (Node).Kind = N_Variable_Declaration
+                or else
+              Project_Nodes.Table (Node).Kind = N_Typed_Variable_Declaration
+                or else
+              Project_Nodes.Table (Node).Kind = N_Expression
+                or else
+              Project_Nodes.Table (Node).Kind = N_Term
+                or else
+              Project_Nodes.Table (Node).Kind = N_Variable_Reference
+                or else
+              Project_Nodes.Table (Node).Kind = N_Attribute_Reference));
+      Project_Nodes.Table (Node).Expr_Kind := To;
+   end Set_Expression_Kind_Of;
+
+   -----------------------
+   -- Set_Expression_Of --
+   -----------------------
+
+   procedure Set_Expression_Of
+     (Node : Project_Node_Id;
+      To   : Project_Node_Id)
+   is
+   begin
+      pragma Assert
+        (Node /= Empty_Node
+          and then
+            (Project_Nodes.Table (Node).Kind = N_Attribute_Declaration
+               or else
+             Project_Nodes.Table (Node).Kind = N_Typed_Variable_Declaration
+               or else
+             Project_Nodes.Table (Node).Kind = N_Variable_Declaration));
+      Project_Nodes.Table (Node).Field1 := To;
+   end Set_Expression_Of;
+
+   -------------------------------
+   -- Set_External_Reference_Of --
+   -------------------------------
+
+   procedure Set_External_Reference_Of
+     (Node : Project_Node_Id;
+      To   : Project_Node_Id)
+   is
+   begin
+      pragma Assert
+        (Node /= Empty_Node
+          and then
+            Project_Nodes.Table (Node).Kind = N_External_Value);
+      Project_Nodes.Table (Node).Field1 := To;
+   end Set_External_Reference_Of;
+
+   -----------------------------
+   -- Set_External_Default_Of --
+   -----------------------------
+
+   procedure Set_External_Default_Of
+     (Node : Project_Node_Id;
+      To   : Project_Node_Id)
+   is
+   begin
+      pragma Assert
+        (Node /= Empty_Node
+          and then
+            Project_Nodes.Table (Node).Kind = N_External_Value);
+      Project_Nodes.Table (Node).Field2 := To;
+   end Set_External_Default_Of;
+
+   ----------------------------
+   -- Set_First_Case_Item_Of --
+   ----------------------------
+
+   procedure Set_First_Case_Item_Of
+     (Node : Project_Node_Id;
+      To   : Project_Node_Id)
+   is
+   begin
+      pragma Assert
+        (Node /= Empty_Node
+          and then
+            Project_Nodes.Table (Node).Kind = N_Case_Construction);
+      Project_Nodes.Table (Node).Field2 := To;
+   end Set_First_Case_Item_Of;
+
+   -------------------------
+   -- Set_First_Choice_Of --
+   -------------------------
+
+   procedure Set_First_Choice_Of
+     (Node : Project_Node_Id;
+      To   : Project_Node_Id)
+   is
+   begin
+      pragma Assert
+        (Node /= Empty_Node
+          and then
+            Project_Nodes.Table (Node).Kind = N_Case_Item);
+      Project_Nodes.Table (Node).Field1 := To;
+   end Set_First_Choice_Of;
+
+   ------------------------
+   -- Set_Next_Case_Item --
+   ------------------------
+
+   procedure Set_Next_Case_Item
+     (Node : Project_Node_Id;
+      To   : Project_Node_Id)
+   is
+   begin
+      pragma Assert
+        (Node /= Empty_Node
+          and then
+            Project_Nodes.Table (Node).Kind = N_Case_Item);
+      Project_Nodes.Table (Node).Field3 := To;
+   end Set_Next_Case_Item;
+
+   -----------------------------------
+   -- Set_First_Declarative_Item_Of --
+   -----------------------------------
+
+   procedure Set_First_Declarative_Item_Of
+     (Node : Project_Node_Id;
+      To   : Project_Node_Id)
+   is
+   begin
+      pragma Assert
+        (Node /= Empty_Node
+          and then
+            (Project_Nodes.Table (Node).Kind = N_Project_Declaration
+               or else
+             Project_Nodes.Table (Node).Kind = N_Case_Item
+               or else
+             Project_Nodes.Table (Node).Kind = N_Package_Declaration));
+
+      if Project_Nodes.Table (Node).Kind = N_Project_Declaration then
+         Project_Nodes.Table (Node).Field1 := To;
+      else
+         Project_Nodes.Table (Node).Field2 := To;
+      end if;
+   end Set_First_Declarative_Item_Of;
+
+   ----------------------------------
+   -- Set_First_Expression_In_List --
+   ----------------------------------
+
+   procedure Set_First_Expression_In_List
+     (Node : Project_Node_Id;
+      To   : Project_Node_Id)
+   is
+   begin
+      pragma Assert
+        (Node /= Empty_Node
+          and then
+            Project_Nodes.Table (Node).Kind = N_Literal_String_List);
+      Project_Nodes.Table (Node).Field1 := To;
+   end Set_First_Expression_In_List;
+
+   ------------------------------
+   -- Set_First_Literal_String --
+   ------------------------------
+
+   procedure Set_First_Literal_String
+     (Node : Project_Node_Id;
+      To   : Project_Node_Id)
+   is
+   begin
+      pragma Assert
+        (Node /= Empty_Node
+          and then
+            Project_Nodes.Table (Node).Kind = N_String_Type_Declaration);
+      Project_Nodes.Table (Node).Field1 := To;
+   end Set_First_Literal_String;
+
+   --------------------------
+   -- Set_First_Package_Of --
+   --------------------------
+
+   procedure Set_First_Package_Of
+     (Node : Project_Node_Id;
+      To   : Package_Declaration_Id)
+   is
+   begin
+      pragma Assert
+        (Node /= Empty_Node
+          and then
+            Project_Nodes.Table (Node).Kind = N_Project);
+      Project_Nodes.Table (Node).Packages := To;
+   end Set_First_Package_Of;
+
+   ------------------------------
+   -- Set_First_String_Type_Of --
+   ------------------------------
+
+   procedure Set_First_String_Type_Of
+     (Node : Project_Node_Id;
+      To   : Project_Node_Id)
+   is
+   begin
+      pragma Assert
+        (Node /= Empty_Node
+          and then
+            Project_Nodes.Table (Node).Kind = N_Project);
+      Project_Nodes.Table (Node).Field3 := To;
+   end Set_First_String_Type_Of;
+
+   --------------------
+   -- Set_First_Term --
+   --------------------
+
+   procedure Set_First_Term
+     (Node : Project_Node_Id;
+      To   : Project_Node_Id)
+   is
+   begin
+      pragma Assert
+        (Node /= Empty_Node
+          and then
+            Project_Nodes.Table (Node).Kind = N_Expression);
+      Project_Nodes.Table (Node).Field1 := To;
+   end Set_First_Term;
+
+   ---------------------------
+   -- Set_First_Variable_Of --
+   ---------------------------
+
+   procedure Set_First_Variable_Of
+     (Node : Project_Node_Id;
+      To   : Variable_Node_Id)
+   is
+   begin
+      pragma Assert
+        (Node /= Empty_Node
+          and then
+            (Project_Nodes.Table (Node).Kind = N_Project
+               or else
+             Project_Nodes.Table (Node).Kind = N_Package_Declaration));
+      Project_Nodes.Table (Node).Variables := To;
+   end Set_First_Variable_Of;
+
+   ------------------------------
+   -- Set_First_With_Clause_Of --
+   ------------------------------
+
+   procedure Set_First_With_Clause_Of
+     (Node : Project_Node_Id;
+      To   : Project_Node_Id)
+   is
+   begin
+      pragma Assert
+        (Node /= Empty_Node
+          and then
+            Project_Nodes.Table (Node).Kind = N_Project);
+      Project_Nodes.Table (Node).Field1 := To;
+   end Set_First_With_Clause_Of;
+
+   -----------------
+   -- Set_Kind_Of --
+   -----------------
+
+   procedure Set_Kind_Of
+     (Node : Project_Node_Id;
+      To   : Project_Node_Kind)
+   is
+   begin
+      pragma Assert (Node /= Empty_Node);
+      Project_Nodes.Table (Node).Kind := To;
+   end Set_Kind_Of;
+
+   ---------------------
+   -- Set_Location_Of --
+   ---------------------
+
+   procedure Set_Location_Of
+     (Node : Project_Node_Id;
+      To   : Source_Ptr)
+   is
+   begin
+      pragma Assert (Node /= Empty_Node);
+      Project_Nodes.Table (Node).Location := To;
+   end Set_Location_Of;
+
+   -----------------------------
+   -- Set_Modified_Project_Of --
+   -----------------------------
+
+   procedure Set_Modified_Project_Of
+     (Node : Project_Node_Id;
+      To   : Project_Node_Id)
+   is
+   begin
+      pragma Assert
+        (Node /= Empty_Node
+          and then
+            Project_Nodes.Table (Node).Kind = N_Project_Declaration);
+      Project_Nodes.Table (Node).Field2 := To;
+   end Set_Modified_Project_Of;
+
+   ----------------------------------
+   -- Set_Modified_Project_Path_Of --
+   ----------------------------------
+
+   procedure Set_Modified_Project_Path_Of
+     (Node : Project_Node_Id;
+      To   : String_Id)
+   is
+   begin
+      pragma Assert
+        (Node /= Empty_Node
+          and then
+            Project_Nodes.Table (Node).Kind = N_Project);
+      Project_Nodes.Table (Node).Value := To;
+   end Set_Modified_Project_Path_Of;
+
+   -----------------
+   -- Set_Name_Of --
+   -----------------
+
+   procedure Set_Name_Of
+     (Node : Project_Node_Id;
+      To   : Name_Id)
+   is
+   begin
+      pragma Assert (Node /= Empty_Node);
+      Project_Nodes.Table (Node).Name := To;
+   end Set_Name_Of;
+
+   -------------------------------
+   -- Set_Next_Declarative_Item --
+   -------------------------------
+
+   procedure Set_Next_Declarative_Item
+     (Node : Project_Node_Id;
+      To   : Project_Node_Id)
+   is
+   begin
+      pragma Assert
+        (Node /= Empty_Node
+          and then
+            Project_Nodes.Table (Node).Kind = N_Declarative_Item);
+      Project_Nodes.Table (Node).Field2 := To;
+   end Set_Next_Declarative_Item;
+
+   ---------------------------------
+   -- Set_Next_Expression_In_List --
+   ---------------------------------
+
+   procedure Set_Next_Expression_In_List
+     (Node : Project_Node_Id;
+      To   : Project_Node_Id)
+   is
+   begin
+      pragma Assert
+        (Node /= Empty_Node
+          and then
+            Project_Nodes.Table (Node).Kind = N_Expression);
+      Project_Nodes.Table (Node).Field2 := To;
+   end Set_Next_Expression_In_List;
+
+   -----------------------------
+   -- Set_Next_Literal_String --
+   -----------------------------
+
+   procedure Set_Next_Literal_String
+     (Node : Project_Node_Id;
+      To   : Project_Node_Id)
+   is
+   begin
+      pragma Assert
+        (Node /= Empty_Node
+          and then
+            Project_Nodes.Table (Node).Kind = N_Literal_String);
+      Project_Nodes.Table (Node).Field1 := To;
+   end Set_Next_Literal_String;
+
+   ---------------------------------
+   -- Set_Next_Package_In_Project --
+   ---------------------------------
+
+   procedure Set_Next_Package_In_Project
+     (Node : Project_Node_Id;
+      To   : Project_Node_Id)
+   is
+   begin
+      pragma Assert
+        (Node /= Empty_Node
+          and then
+            Project_Nodes.Table (Node).Kind = N_Package_Declaration);
+      Project_Nodes.Table (Node).Field3 := To;
+   end Set_Next_Package_In_Project;
+
+   --------------------------
+   -- Set_Next_String_Type --
+   --------------------------
+
+   procedure Set_Next_String_Type
+     (Node : Project_Node_Id;
+      To   : Project_Node_Id)
+   is
+   begin
+      pragma Assert
+        (Node /= Empty_Node
+          and then
+            Project_Nodes.Table (Node).Kind = N_String_Type_Declaration);
+      Project_Nodes.Table (Node).Field2 := To;
+   end Set_Next_String_Type;
+
+   -------------------
+   -- Set_Next_Term --
+   -------------------
+
+   procedure Set_Next_Term
+     (Node : Project_Node_Id;
+      To   : Project_Node_Id)
+   is
+   begin
+      pragma Assert
+        (Node /= Empty_Node
+          and then
+            Project_Nodes.Table (Node).Kind = N_Term);
+      Project_Nodes.Table (Node).Field2 := To;
+   end Set_Next_Term;
+
+   -----------------------
+   -- Set_Next_Variable --
+   -----------------------
+
+   procedure Set_Next_Variable
+     (Node : Project_Node_Id;
+      To   : Project_Node_Id)
+   is
+   begin
+      pragma Assert
+        (Node /= Empty_Node
+          and then
+            (Project_Nodes.Table (Node).Kind = N_Typed_Variable_Declaration
+               or else
+             Project_Nodes.Table (Node).Kind = N_Variable_Declaration));
+      Project_Nodes.Table (Node).Field3 := To;
+   end Set_Next_Variable;
+
+   -----------------------------
+   -- Set_Next_With_Clause_Of --
+   -----------------------------
+
+   procedure Set_Next_With_Clause_Of
+     (Node : Project_Node_Id;
+      To   : Project_Node_Id)
+   is
+   begin
+      pragma Assert
+        (Node /= Empty_Node
+          and then
+            Project_Nodes.Table (Node).Kind = N_With_Clause);
+      Project_Nodes.Table (Node).Field2 := To;
+   end Set_Next_With_Clause_Of;
+
+   -----------------------
+   -- Set_Package_Id_Of --
+   -----------------------
+
+   procedure Set_Package_Id_Of
+     (Node : Project_Node_Id;
+      To   : Package_Node_Id)
+   is
+   begin
+      pragma Assert
+        (Node /= Empty_Node
+          and then
+            Project_Nodes.Table (Node).Kind = N_Package_Declaration);
+      Project_Nodes.Table (Node).Pkg_Id := To;
+   end Set_Package_Id_Of;
+
+   -------------------------
+   -- Set_Package_Node_Of --
+   -------------------------
+
+   procedure Set_Package_Node_Of
+     (Node : Project_Node_Id;
+      To   : Project_Node_Id)
+   is
+   begin
+      pragma Assert
+        (Node /= Empty_Node
+          and then
+            (Project_Nodes.Table (Node).Kind = N_Variable_Reference
+               or else
+             Project_Nodes.Table (Node).Kind = N_Attribute_Reference));
+      Project_Nodes.Table (Node).Field2 := To;
+   end Set_Package_Node_Of;
+
+   ----------------------
+   -- Set_Path_Name_Of --
+   ----------------------
+
+   procedure Set_Path_Name_Of
+     (Node : Project_Node_Id;
+      To   : Name_Id)
+   is
+   begin
+      pragma Assert
+        (Node /= Empty_Node
+          and then
+            (Project_Nodes.Table (Node).Kind = N_Project
+               or else
+             Project_Nodes.Table (Node).Kind = N_With_Clause));
+      Project_Nodes.Table (Node).Path_Name := To;
+   end Set_Path_Name_Of;
+
+   --------------------------------
+   -- Set_Project_Declaration_Of --
+   --------------------------------
+
+   procedure Set_Project_Declaration_Of
+     (Node : Project_Node_Id;
+      To   : Project_Node_Id)
+   is
+   begin
+      pragma Assert
+        (Node /= Empty_Node
+         and then
+           Project_Nodes.Table (Node).Kind = N_Project);
+      Project_Nodes.Table (Node).Field2 := To;
+   end Set_Project_Declaration_Of;
+
+   -------------------------
+   -- Set_Project_Node_Of --
+   -------------------------
+
+   procedure Set_Project_Node_Of
+     (Node : Project_Node_Id;
+      To   : Project_Node_Id)
+   is
+   begin
+      pragma Assert
+        (Node /= Empty_Node
+          and then
+            (Project_Nodes.Table (Node).Kind = N_With_Clause
+               or else
+             Project_Nodes.Table (Node).Kind = N_Variable_Reference
+               or else
+             Project_Nodes.Table (Node).Kind = N_Attribute_Reference));
+      Project_Nodes.Table (Node).Field1 := To;
+   end Set_Project_Node_Of;
+
+   ---------------------------------------
+   -- Set_Project_Of_Renamed_Package_Of --
+   ---------------------------------------
+
+   procedure Set_Project_Of_Renamed_Package_Of
+     (Node : Project_Node_Id;
+      To   : Project_Node_Id)
+   is
+   begin
+      pragma Assert
+        (Node /= Empty_Node
+          and then
+            Project_Nodes.Table (Node).Kind = N_Package_Declaration);
+      Project_Nodes.Table (Node).Field1 := To;
+   end Set_Project_Of_Renamed_Package_Of;
+
+   ------------------------
+   -- Set_String_Type_Of --
+   ------------------------
+
+   procedure Set_String_Type_Of
+     (Node : Project_Node_Id;
+      To   : Project_Node_Id)
+   is
+   begin
+      pragma Assert
+        (Node /= Empty_Node
+          and then
+            (Project_Nodes.Table (Node).Kind = N_Variable_Reference
+               or else
+             Project_Nodes.Table (Node).Kind = N_Typed_Variable_Declaration)
+           and then
+            Project_Nodes.Table (To).Kind    = N_String_Type_Declaration);
+
+      if Project_Nodes.Table (Node).Kind = N_Variable_Reference then
+         Project_Nodes.Table (Node).Field3 := To;
+      else
+         Project_Nodes.Table (Node).Field2 := To;
+      end if;
+   end Set_String_Type_Of;
+
+   -------------------------
+   -- Set_String_Value_Of --
+   -------------------------
+
+   procedure Set_String_Value_Of
+     (Node : Project_Node_Id;
+      To   : String_Id)
+   is
+   begin
+      pragma Assert
+        (Node /= Empty_Node
+          and then
+            (Project_Nodes.Table (Node).Kind = N_With_Clause
+               or else
+             Project_Nodes.Table (Node).Kind = N_Literal_String));
+      Project_Nodes.Table (Node).Value := To;
+   end Set_String_Value_Of;
+
+   --------------------
+   -- String_Type_Of --
+   --------------------
+
+   function String_Type_Of  (Node : Project_Node_Id)
+                            return Project_Node_Id is
+   begin
+      pragma Assert
+        (Node /= Empty_Node
+          and then
+            (Project_Nodes.Table (Node).Kind = N_Variable_Reference
+               or else
+             Project_Nodes.Table (Node).Kind = N_Typed_Variable_Declaration));
+
+      if Project_Nodes.Table (Node).Kind = N_Variable_Reference then
+         return Project_Nodes.Table (Node).Field3;
+      else
+         return Project_Nodes.Table (Node).Field2;
+      end if;
+   end String_Type_Of;
+
+   ---------------------
+   -- String_Value_Of --
+   ---------------------
+
+   function String_Value_Of (Node : Project_Node_Id) return String_Id is
+   begin
+      pragma Assert
+        (Node /= Empty_Node
+          and then
+           (Project_Nodes.Table (Node).Kind = N_With_Clause
+              or else
+            Project_Nodes.Table (Node).Kind = N_Literal_String));
+      return Project_Nodes.Table (Node).Value;
+   end String_Value_Of;
+
+   --------------------
+   -- Value_Is_Valid --
+   --------------------
+
+   function Value_Is_Valid
+     (For_Typed_Variable : Project_Node_Id;
+      Value              : String_Id)
+      return               Boolean
+   is
+   begin
+      pragma Assert
+        (For_Typed_Variable /= Empty_Node
+          and then
+           (Project_Nodes.Table (For_Typed_Variable).Kind =
+                                     N_Typed_Variable_Declaration));
+
+      declare
+         Current_String : Project_Node_Id :=
+                            First_Literal_String
+                              (String_Type_Of (For_Typed_Variable));
+
+      begin
+         while Current_String /= Empty_Node
+           and then
+             not String_Equal (String_Value_Of (Current_String), Value)
+         loop
+            Current_String :=
+              Next_Literal_String (Current_String);
+         end loop;
+
+         return Current_String /= Empty_Node;
+      end;
+
+   end Value_Is_Valid;
+
+end Prj.Tree;
diff --git a/gcc/ada/prj-tree.ads b/gcc/ada/prj-tree.ads
new file mode 100644 (file)
index 0000000..d32fcb1
--- /dev/null
@@ -0,0 +1,742 @@
+------------------------------------------------------------------------------
+--                                                                          --
+--                         GNAT COMPILER COMPONENTS                         --
+--                                                                          --
+--                              P R J . T R E E                             --
+--                                                                          --
+--                                 S p e c                                  --
+--                                                                          --
+--                            $Revision: 1.9 $
+--                                                                          --
+--             Copyright (C) 2001 Free Software Foundation, Inc.            --
+--                                                                          --
+-- GNAT is free software;  you can  redistribute it  and/or modify it under --
+-- terms of the  GNU General Public License as published  by the Free Soft- --
+-- ware  Foundation;  either version 2,  or (at your option) any later ver- --
+-- sion.  GNAT is distributed in the hope that it will be useful, but WITH- --
+-- OUT 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  distributed with GNAT;  see file COPYING.  If not, write --
+-- to  the Free Software Foundation,  59 Temple Place - Suite 330,  Boston, --
+-- MA 02111-1307, USA.                                                      --
+--                                                                          --
+-- GNAT was originally developed  by the GNAT team at  New York University. --
+-- It is now maintained by Ada Core Technologies Inc (http://www.gnat.com). --
+--                                                                          --
+------------------------------------------------------------------------------
+
+--  This package defines the structure of the Project File tree.
+
+with GNAT.HTable;
+
+with Prj.Attr; use Prj.Attr;
+with Prj.Com;  use Prj.Com;
+with Types;    use Types;
+with Table;
+
+package Prj.Tree is
+
+   Project_Nodes_Initial   : constant := 1_000;
+   --  Initial number of nodes in table Tree_Private_Part.Project_Nodes
+   Project_Nodes_Increment : constant := 100;
+
+   Project_Node_Low_Bound  : constant := 0;
+   Project_Node_High_Bound : constant := 099_999_999; -- In practice, infinite
+
+   type Project_Node_Id is range
+     Project_Node_Low_Bound .. Project_Node_High_Bound;
+   --  The index of table Tree_Private_Part.Project_Nodes
+
+   Empty_Node    : constant Project_Node_Id := Project_Node_Low_Bound;
+   --  Designates no node in table Project_Nodes
+   First_Node_Id : constant Project_Node_Id := Project_Node_Low_Bound;
+
+   subtype Variable_Node_Id       is Project_Node_Id;
+   --  Used to designate a node whose expected kind is
+   --  N_Typed_Variable_Declaration, N_Variable_Declaration or
+   --  N_Variable_Reference.
+   subtype Package_Declaration_Id is Project_Node_Id;
+   --  Used to designate a node whose expected kind is
+   --  N_Project_Declaration.
+
+   type Project_Node_Kind is
+     (N_Project,
+      N_With_Clause,
+      N_Project_Declaration,
+      N_Declarative_Item,
+      N_Package_Declaration,
+      N_String_Type_Declaration,
+      N_Literal_String,
+      N_Attribute_Declaration,
+      N_Typed_Variable_Declaration,
+      N_Variable_Declaration,
+      N_Expression,
+      N_Term,
+      N_Literal_String_List,
+      N_Variable_Reference,
+      N_External_Value,
+      N_Attribute_Reference,
+      N_Case_Construction,
+      N_Case_Item);
+   --  Each node in the tree is of a Project_Node_Kind
+   --  For the signification of the fields in each node of a
+   --  Project_Node_Kind, look at package Tree_Private_Part.
+
+   procedure Initialize;
+   --  Initialize the Project File tree: empty the Project_Nodes table
+   --  and reset the Projects_Htable.
+
+   function Default_Project_Node
+     (Of_Kind       : Project_Node_Kind;
+      And_Expr_Kind : Variable_Kind := Undefined)
+     return Project_Node_Id;
+   --  Returns a Project_Node_Record with the specified Kind and
+   --  Expr_Kind; all the other components have default nil values.
+
+   ----------------------
+   -- Access Functions --
+   ----------------------
+
+   --  The following query functions are part of the abstract interface
+   --  of the Project File tree
+
+   function Name_Of (Node : Project_Node_Id) return Name_Id;
+   --  Valid for all non empty nodes. May return No_Name for nodes that have
+   --  no names.
+
+   function Kind_Of (Node : Project_Node_Id) return Project_Node_Kind;
+   --  Valid for all non empty nodes
+
+   function Location_Of (Node : Project_Node_Id) return Source_Ptr;
+   --  Valid for all non empty nodes
+
+   function Directory_Of (Node : Project_Node_Id) return Name_Id;
+   --  Only valid for N_Project nodes.
+
+   function Expression_Kind_Of (Node : Project_Node_Id) return Variable_Kind;
+   --  Only valid for N_Literal_String, N_Attribute_Declaration,
+   --  N_Variable_Declaration, N_Typed_Variable_Declaration, N_Expression,
+   --  N_Term, N_Variable_Reference or N_Attribute_Reference nodes.
+
+   function First_Variable_Of
+     (Node  : Project_Node_Id)
+      return Variable_Node_Id;
+   --  Only valid for N_Project or N_Package_Declaration nodes
+
+   function First_Package_Of
+     (Node  : Project_Node_Id)
+      return  Package_Declaration_Id;
+   --  Only valid for N_Project nodes
+
+   function Package_Id_Of (Node  : Project_Node_Id) return Package_Node_Id;
+   --  Only valid for N_Package_Declaration nodes
+
+   function Path_Name_Of (Node  : Project_Node_Id) return Name_Id;
+   --  Only valid for N_Project and N_With_Clause nodes.
+
+   function String_Value_Of (Node  : Project_Node_Id) return String_Id;
+   --  Only valid for N_With_Clause or N_Literal_String nodes.
+
+   function First_With_Clause_Of
+     (Node  : Project_Node_Id)
+      return  Project_Node_Id;
+   --  Only valid for N_Project nodes
+
+   function Project_Declaration_Of
+     (Node  : Project_Node_Id)
+      return  Project_Node_Id;
+   --  Only valid for N_Project nodes
+
+   function First_String_Type_Of
+     (Node  : Project_Node_Id)
+      return  Project_Node_Id;
+   --  Only valid for N_Project nodes
+
+   function Modified_Project_Path_Of
+     (Node  : Project_Node_Id)
+      return  String_Id;
+   --  Only valid for N_With_Clause nodes
+
+   function Project_Node_Of
+     (Node  : Project_Node_Id)
+      return  Project_Node_Id;
+   --  Only valid for N_Project nodes
+
+   function Next_With_Clause_Of
+     (Node  : Project_Node_Id)
+      return  Project_Node_Id;
+   --  Only valid for N_With_Clause nodes
+
+   function First_Declarative_Item_Of
+     (Node  : Project_Node_Id)
+      return  Project_Node_Id;
+   --  Only valid for N_With_Clause nodes
+
+   function Modified_Project_Of
+     (Node  : Project_Node_Id)
+      return Project_Node_Id;
+   --  Only valid for N_With_Clause nodes
+
+   function Current_Item_Node
+     (Node  : Project_Node_Id)
+      return  Project_Node_Id;
+   --  Only valid for N_Declarative_Item nodes
+
+   function Next_Declarative_Item
+     (Node  : Project_Node_Id)
+      return  Project_Node_Id;
+   --  Only valid for N_Declarative_Item node
+
+   function Project_Of_Renamed_Package_Of
+     (Node  : Project_Node_Id)
+      return  Project_Node_Id;
+   --  Only valid for N_Package_Declaration nodes.
+   --  May return Empty_Node.
+
+   function Next_Package_In_Project
+     (Node  : Project_Node_Id)
+      return  Project_Node_Id;
+   --  Only valid for N_Package_Declaration nodes
+
+   function First_Literal_String
+     (Node  : Project_Node_Id)
+      return  Project_Node_Id;
+   --  Only valid for N_String_Type_Declaration nodes
+
+   function Next_String_Type
+     (Node  : Project_Node_Id)
+      return  Project_Node_Id;
+   --  Only valid for N_String_Type_Declaration nodes
+
+   function Next_Literal_String
+     (Node  : Project_Node_Id)
+      return  Project_Node_Id;
+   --  Only valid for N_Literal_String nodes
+
+   function Expression_Of
+     (Node  : Project_Node_Id)
+      return  Project_Node_Id;
+   --  Only valid for N_Attribute_Declaration, N_Typed_Variable_Declaration
+   --  or N_Variable_Declaration nodes
+
+   function Value_Is_Valid
+     (For_Typed_Variable : Project_Node_Id;
+      Value              : String_Id)
+      return               Boolean;
+   --  Only valid for N_Typed_Variable_Declaration. Returns True if Value is
+   --  in the list of allowed strings for For_Typed_Variable. False otherwise.
+
+   function Associative_Array_Index_Of
+     (Node  : Project_Node_Id)
+      return  String_Id;
+   --  Only valid for N_Attribute_Declaration.
+   --  Returns No_String for non associative array attributes.
+
+   function Next_Variable
+     (Node  : Project_Node_Id)
+      return  Project_Node_Id;
+   --  Only valid for N_Typed_Variable_Declaration or N_Variable_Declaration
+   --  nodes.
+
+   function First_Term
+     (Node  : Project_Node_Id)
+      return  Project_Node_Id;
+   --  Only valid for N_Expression nodes
+
+   function Next_Expression_In_List
+     (Node  : Project_Node_Id)
+      return  Project_Node_Id;
+   --  Only valid for N_Expression nodes
+
+   function Current_Term
+     (Node  : Project_Node_Id)
+      return  Project_Node_Id;
+   --  Only valid for N_Term nodes
+
+   function Next_Term
+     (Node  : Project_Node_Id)
+      return  Project_Node_Id;
+   --  Only valid for N_Term nodes
+
+   function First_Expression_In_List
+     (Node  : Project_Node_Id)
+      return  Project_Node_Id;
+   --  Only valid for N_Literal_String_List nodes
+
+   function Package_Node_Of
+     (Node  : Project_Node_Id)
+      return  Project_Node_Id;
+   --  Only valid for N_Variable_Reference or N_Attribute_Reference nodes.
+   --  May return Empty_Node.
+
+   function String_Type_Of
+     (Node  : Project_Node_Id)
+      return  Project_Node_Id;
+   --  Only valid for N_Variable_Reference or N_Typed_Variable_Declaration
+   --  nodes.
+
+   function External_Reference_Of
+     (Node  : Project_Node_Id)
+      return  Project_Node_Id;
+   --  Only valid for N_External_Value nodes
+
+   function External_Default_Of
+     (Node  : Project_Node_Id)
+      return  Project_Node_Id;
+   --  Only valid for N_External_Value nodes
+
+   function Case_Variable_Reference_Of
+     (Node  : Project_Node_Id)
+      return  Project_Node_Id;
+   --  Only valid for N_Case_Construction nodes
+
+   function First_Case_Item_Of
+     (Node  : Project_Node_Id)
+      return  Project_Node_Id;
+   --  Only valid for N_Case_Construction nodes
+
+   function First_Choice_Of
+     (Node  : Project_Node_Id)
+      return  Project_Node_Id;
+   --  Only valid for N_Case_Item nodes
+
+   function Next_Case_Item
+     (Node  : Project_Node_Id)
+      return  Project_Node_Id;
+   --  Only valid for N_Case_Item nodes
+
+   --------------------
+   -- Set Procedures --
+   --------------------
+
+   --  The following procedures are part of the abstract interface of
+   --  the Project File tree.
+
+   --  Each Set_* procedure is valid only for the same Project_Node_Kind
+   --  nodes as the corresponding query function above.
+
+   procedure Set_Name_Of
+     (Node : Project_Node_Id;
+      To   : Name_Id);
+
+   procedure Set_Kind_Of
+     (Node : Project_Node_Id;
+      To   : Project_Node_Kind);
+
+   procedure Set_Location_Of
+     (Node : Project_Node_Id;
+      To   : Source_Ptr);
+
+   procedure Set_Directory_Of
+     (Node : Project_Node_Id;
+      To   : Name_Id);
+
+   procedure Set_Expression_Kind_Of
+     (Node : Project_Node_Id;
+      To   : Variable_Kind);
+
+   procedure Set_First_Variable_Of
+     (Node : Project_Node_Id;
+      To   : Variable_Node_Id);
+
+   procedure Set_First_Package_Of
+     (Node : Project_Node_Id;
+      To   : Package_Declaration_Id);
+
+   procedure Set_Package_Id_Of
+     (Node : Project_Node_Id;
+      To   : Package_Node_Id);
+
+   procedure Set_Path_Name_Of
+     (Node : Project_Node_Id;
+      To   : Name_Id);
+
+   procedure Set_String_Value_Of
+     (Node : Project_Node_Id;
+      To   : String_Id);
+
+   procedure Set_First_With_Clause_Of
+     (Node : Project_Node_Id;
+      To   : Project_Node_Id);
+
+   procedure Set_Project_Declaration_Of
+     (Node : Project_Node_Id;
+      To   : Project_Node_Id);
+
+   procedure Set_First_String_Type_Of
+     (Node : Project_Node_Id;
+      To   : Project_Node_Id);
+
+   procedure Set_Modified_Project_Path_Of
+     (Node : Project_Node_Id;
+      To   : String_Id);
+
+   procedure Set_Project_Node_Of
+     (Node : Project_Node_Id;
+      To   : Project_Node_Id);
+
+   procedure Set_Next_With_Clause_Of
+     (Node : Project_Node_Id;
+      To   : Project_Node_Id);
+
+   procedure Set_First_Declarative_Item_Of
+     (Node : Project_Node_Id;
+      To   : Project_Node_Id);
+
+   procedure Set_Modified_Project_Of
+     (Node : Project_Node_Id;
+      To   : Project_Node_Id);
+
+   procedure Set_Current_Item_Node
+     (Node : Project_Node_Id;
+      To   : Project_Node_Id);
+
+   procedure Set_Next_Declarative_Item
+     (Node : Project_Node_Id;
+      To   : Project_Node_Id);
+
+   procedure Set_Project_Of_Renamed_Package_Of
+     (Node : Project_Node_Id;
+      To   : Project_Node_Id);
+
+   procedure Set_Next_Package_In_Project
+     (Node : Project_Node_Id;
+      To   : Project_Node_Id);
+
+   procedure Set_First_Literal_String
+     (Node : Project_Node_Id;
+      To   : Project_Node_Id);
+
+   procedure Set_Next_String_Type
+     (Node : Project_Node_Id;
+      To   : Project_Node_Id);
+
+   procedure Set_Next_Literal_String
+     (Node : Project_Node_Id;
+      To   : Project_Node_Id);
+
+   procedure Set_Expression_Of
+     (Node : Project_Node_Id;
+      To   : Project_Node_Id);
+
+   procedure Set_Associative_Array_Index_Of
+     (Node : Project_Node_Id;
+      To   : String_Id);
+
+   procedure Set_Next_Variable
+     (Node : Project_Node_Id;
+      To   : Project_Node_Id);
+
+   procedure Set_First_Term
+     (Node : Project_Node_Id;
+      To   : Project_Node_Id);
+
+   procedure Set_Next_Expression_In_List
+     (Node : Project_Node_Id;
+      To   : Project_Node_Id);
+
+   procedure Set_Current_Term
+     (Node : Project_Node_Id;
+      To   : Project_Node_Id);
+
+   procedure Set_Next_Term
+     (Node : Project_Node_Id;
+      To   : Project_Node_Id);
+
+   procedure Set_First_Expression_In_List
+     (Node : Project_Node_Id;
+      To   : Project_Node_Id);
+
+   procedure Set_Package_Node_Of
+     (Node : Project_Node_Id;
+      To   : Project_Node_Id);
+
+   procedure Set_String_Type_Of
+     (Node : Project_Node_Id;
+      To   : Project_Node_Id);
+
+   procedure Set_External_Reference_Of
+     (Node : Project_Node_Id;
+      To   : Project_Node_Id);
+
+   procedure Set_External_Default_Of
+     (Node : Project_Node_Id;
+      To   : Project_Node_Id);
+
+   procedure Set_Case_Variable_Reference_Of
+     (Node : Project_Node_Id;
+      To   : Project_Node_Id);
+
+   procedure Set_First_Case_Item_Of
+     (Node : Project_Node_Id;
+      To   : Project_Node_Id);
+
+   procedure Set_First_Choice_Of
+     (Node : Project_Node_Id;
+      To   : Project_Node_Id);
+
+   procedure Set_Next_Case_Item
+     (Node : Project_Node_Id;
+      To   : Project_Node_Id);
+
+   -------------------------------
+   -- Restricted Access Section --
+   -------------------------------
+
+   package Tree_Private_Part is
+
+      --  This is conceptually in the private part.
+      --  However, for efficiency, some packages are accessing it directly.
+
+      type Project_Node_Record is record
+
+         Kind        : Project_Node_Kind;
+
+         Location    : Source_Ptr    := No_Location;
+
+         Directory   : Name_Id       := No_Name;
+         --  Only for N_Project
+
+         Expr_Kind   : Variable_Kind := Undefined;
+         --  See below for what Project_Node_Kind it is used
+
+         Variables   : Variable_Node_Id := Empty_Node;
+         --  First variable in a project or a package
+
+         Packages    : Package_Declaration_Id := Empty_Node;
+         --  First package declaration in a project
+
+         Pkg_Id      : Package_Node_Id := Empty_Package;
+         --  Only use in Package_Declaration
+
+         Name        : Name_Id         := No_Name;
+         --  See below for what Project_Node_Kind it is used
+
+         Path_Name   : Name_Id         := No_Name;
+         --  See below for what Project_Node_Kind it is used
+
+         Value       : String_Id       := No_String;
+         --  See below for what Project_Node_Kind it is used
+
+         Field1      : Project_Node_Id := Empty_Node;
+         --  See below the meaning for each Project_Node_Kind
+
+         Field2      : Project_Node_Id := Empty_Node;
+         --  See below the meaning for each Project_Node_Kind
+
+         Field3      : Project_Node_Id := Empty_Node;
+         --  See below the meaning for each Project_Node_Kind
+
+      end record;
+
+      --  type Project_Node_Kind is
+
+      --   (N_Project,
+      --    --  Name:      project name
+      --    --  Path_Name: project path name
+      --    --  Expr_Kind: Undefined
+      --    --  Field1:    first with clause
+      --    --  Field2:    project declaration
+      --    --  Field3:    first string type
+      --    --  Value:     modified project path name (if any)
+
+      --    N_With_Clause,
+      --    --  Name:      imported project name
+      --    --  Path_Name: imported project path name
+      --    --  Expr_Kind: Undefined
+      --    --  Field1:    project node
+      --    --  Field2:    next with clause
+      --    --  Field3:    not used
+      --    --  Value:     literal string withed
+
+      --    N_Project_Declaration,
+      --    --  Name:      not used
+      --    --  Path_Name: not used
+      --    --  Expr_Kind: Undefined
+      --    --  Field1:    first declarative item
+      --    --  Field2:    modified project
+      --    --  Field3:    not used
+      --    --  Value:     not used
+
+      --    N_Declarative_Item,
+      --    --  Name:      not used
+      --    --  Path_Name: not used
+      --    --  Expr_Kind: Undefined
+      --    --  Field1:    current item node
+      --    --  Field2:    next declarative item
+      --    --  Field3:    not used
+      --    --  Value:     not used
+
+      --    N_Package_Declaration,
+      --    --  Name:      package name
+      --    --  Path_Name: not used
+      --    --  Expr_Kind: Undefined
+      --    --  Field1:    project of renamed package (if any)
+      --    --  Field2:    first declarative item
+      --    --  Field3:    next package in project
+      --    --  Value:     not used
+
+      --    N_String_Type_Declaration,
+      --    --  Name:      type name
+      --    --  Path_Name: not used
+      --    --  Expr_Kind: Undefined
+      --    --  Field1:    first literal string
+      --    --  Field2:    next string type
+      --    --  Field3:    not used
+      --    --  Value:     not used
+
+      --    N_Literal_String,
+      --    --  Name:      not used
+      --    --  Path_Name: not used
+      --    --  Expr_Kind: Single
+      --    --  Field1:    next literal string
+      --    --  Field2:    not used
+      --    --  Field3:    not used
+      --    --  Value:     string value
+
+      --    N_Attribute_Declaration,
+      --    --  Name:      attribute name
+      --    --  Path_Name: not used
+      --    --  Expr_Kind: attribute kind
+      --    --  Field1:    expression
+      --    --  Field2:    not used
+      --    --  Field3:    not used
+      --    --  Value:     associative array index
+      --    --             (if an associative array element)
+
+      --    N_Typed_Variable_Declaration,
+      --    --  Name:      variable name
+      --    --  Path_Name: not used
+      --    --  Expr_Kind: Single
+      --    --  Field1:    expression
+      --    --  Field2:    type of variable (N_String_Type_Declaration)
+      --    --  Field3:    next variable
+      --    --  Value:     not used
+
+      --    N_Variable_Declaration,
+      --    --  Name:      variable name
+      --    --  Path_Name: not used
+      --    --  Expr_Kind: variable kind
+      --    --  Field1:    expression
+      --    --  Field2:    not used
+      --    --             Field3 is used for next variable, instead of Field2,
+      --    --             so that it is the same field for
+      --    --             N_Variable_Declaration and
+      --    --             N_Typed_Variable_Declaration
+      --    --  Field3:    next variable
+      --    --  Value:     not used
+
+      --    N_Expression,
+      --    --  Name:      not used
+      --    --  Path_Name: not used
+      --    --  Expr_Kind: expression kind
+      --    --  Field1:    first term
+      --    --  Field2:    next expression in list
+      --    --  Field3:    not used
+      --    --  Value:     not used
+
+      --    N_Term,
+      --    --  Name:      not used
+      --    --  Path_Name: not used
+      --    --  Expr_Kind: term kind
+      --    --  Field1:    current term
+      --    --  Field2:    next term in the expression
+      --    --  Field3:    not used
+      --    --  Value:     not used
+
+      --    N_Literal_String_List,
+      --    --  Designates a list of string expressions between brackets
+      --    --  separated by commas. The string expressions are not necessarily
+      --    --  literal strings.
+      --    --  Name:      not used
+      --    --  Path_Name: not used
+      --    --  Expr_Kind: List
+      --    --  Field1:    first expression
+      --    --  Field2:    not used
+      --    --  Field3:    not used
+      --    --  Value:     not used
+
+      --    N_Variable_Reference,
+      --    --  Name:      variable name
+      --    --  Path_Name: not used
+      --    --  Expr_Kind: variable kind
+      --    --  Field1:    project (if specified)
+      --    --  Field2:    package (if specified)
+      --    --  Field3:    type of variable (N_String_Type_Declaration), if any
+      --    --  Value:     not used
+
+      --    N_External_Value,
+      --    --  Name:      not used
+      --    --  Path_Name: not used
+      --    --  Expr_Kind: Single
+      --    --  Field1:    Name of the external reference (literal string)
+      --    --  Field2:    Default (literal string)
+      --    --  Field3:    not used
+      --    --  Value:     not used
+
+      --    N_Attribute_Reference,
+      --    --  Name:      attribute name
+      --    --  Path_Name: not used
+      --    --  Expr_Kind: attribute kind
+      --    --  Field1:    project
+      --    --  Field2:    package (if attribute of a package)
+      --    --  Field3:    not used
+      --    --  Value:     not used
+
+      --    N_Case_Construction,
+      --    --  Name:      not used
+      --    --  Path_Name: not used
+      --    --  Expr_Kind: Undefined
+      --    --  Field1:    case variable reference
+      --    --  Field2:    first case item
+      --    --  Field3:    not used
+      --    --  Value:     not used
+
+      --    N_Case_Item);
+      --    --  Name:      not used
+      --    --  Path_Name: not used
+      --    --  Expr_Kind: not used
+      --    --  Field1:    first choice (literal string)
+      --    --  Field2:    first declarative item
+      --    --  Field3:    next case item
+      --    --  Value:     not used
+
+      package Project_Nodes is
+         new Table.Table (Table_Component_Type => Project_Node_Record,
+                          Table_Index_Type     => Project_Node_Id,
+                          Table_Low_Bound      => First_Node_Id,
+                          Table_Initial        => Project_Nodes_Initial,
+                          Table_Increment      => Project_Nodes_Increment,
+                          Table_Name           => "Project_Nodes");
+      --  This table contains the syntactic tree of project data
+      --  from project files.
+
+      type Project_Name_And_Node is record
+         Name     : Name_Id;
+         --  Name of the project
+         Node     : Project_Node_Id;
+         --  Node of the project in table Project_Nodes
+         Modified : Boolean;
+         --  True when the project is being modified by another project
+      end record;
+
+      No_Project_Name_And_Node : constant Project_Name_And_Node :=
+        (Name => No_Name, Node => Empty_Node, Modified => True);
+
+      package Projects_Htable is new GNAT.HTable.Simple_HTable
+        (Header_Num => Header_Num,
+         Element    => Project_Name_And_Node,
+         No_Element => No_Project_Name_And_Node,
+         Key        => Name_Id,
+         Hash       => Hash,
+         Equal      => "=");
+      --  This hash table contains a mapping of project names to project nodes.
+      --  Note that this hash table contains only the nodes whose Kind is
+      --  N_Project. It is used to find the node of a project from its
+      --  name, and to verify if a project has already been parsed, knowing
+      --  its name.
+
+   end Tree_Private_Part;
+
+end Prj.Tree;
diff --git a/gcc/ada/prj-util.adb b/gcc/ada/prj-util.adb
new file mode 100644 (file)
index 0000000..6a94a0c
--- /dev/null
@@ -0,0 +1,415 @@
+------------------------------------------------------------------------------
+--                                                                          --
+--                         GNAT COMPILER COMPONENTS                         --
+--                                                                          --
+--                              P R J . U T I L                             --
+--                                                                          --
+--                                 B o d y                                  --
+--                                                                          --
+--                            $Revision: 1.8 $                              --
+--                                                                          --
+--             Copyright (C) 2001 Free Software Foundation, Inc.            --
+--                                                                          --
+-- GNAT is free software;  you can  redistribute it  and/or modify it under --
+-- terms of the  GNU General Public License as published  by the Free Soft- --
+-- ware  Foundation;  either version 2,  or (at your option) any later ver- --
+-- sion.  GNAT is distributed in the hope that it will be useful, but WITH- --
+-- OUT 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  distributed with GNAT;  see file COPYING.  If not, write --
+-- to  the Free Software Foundation,  59 Temple Place - Suite 330,  Boston, --
+-- MA 02111-1307, USA.                                                      --
+--                                                                          --
+-- GNAT was originally developed  by the GNAT team at  New York University. --
+-- It is now maintained by Ada Core Technologies Inc (http://www.gnat.com). --
+--                                                                          --
+------------------------------------------------------------------------------
+
+with Ada.Unchecked_Deallocation;
+
+with Namet;    use Namet;
+with Osint;
+with Output;   use Output;
+with Stringt;  use Stringt;
+
+package body Prj.Util is
+
+   procedure Free is new Ada.Unchecked_Deallocation
+     (Text_File_Data, Text_File);
+
+   -----------
+   -- Close --
+   -----------
+
+   procedure Close (File : in out Text_File) is
+   begin
+      if File = null then
+         Osint.Fail ("Close attempted on an invalid Text_File");
+      end if;
+
+      Close (File.FD);
+      Free (File);
+   end Close;
+
+   -----------------
+   -- End_Of_File --
+   -----------------
+
+   function End_Of_File (File : Text_File) return Boolean is
+   begin
+      if File = null then
+         Osint.Fail ("End_Of_File attempted on an invalid Text_File");
+      end if;
+
+      return File.End_Of_File_Reached;
+   end End_Of_File;
+
+   --------------
+   -- Get_Line --
+   --------------
+
+   procedure Get_Line
+     (File : Text_File;
+      Line : out String;
+      Last : out Natural)
+   is
+      C : Character;
+
+      procedure Advance;
+
+      -------------
+      -- Advance --
+      -------------
+
+      procedure Advance is
+      begin
+         if File.Cursor = File.Buffer_Len then
+            File.Buffer_Len :=
+              Read
+               (FD => File.FD,
+                A  => File.Buffer'Address,
+                N  => File.Buffer'Length);
+
+            if File.Buffer_Len = 0 then
+               File.End_Of_File_Reached := True;
+               return;
+            else
+               File.Cursor := 1;
+            end if;
+
+         else
+            File.Cursor := File.Cursor + 1;
+         end if;
+      end Advance;
+
+   --  Start of processing for Get_Line
+
+   begin
+      if File = null then
+         Osint.Fail ("Get_Line attempted on an invalid Text_File");
+      end if;
+
+      Last := Line'First - 1;
+
+      if not File.End_Of_File_Reached then
+         loop
+            C := File.Buffer (File.Cursor);
+            exit when C = ASCII.CR or else C = ASCII.LF;
+            Last := Last + 1;
+            Line (Last) := C;
+            Advance;
+
+            if File.End_Of_File_Reached then
+               return;
+            end if;
+
+            exit when Last = Line'Last;
+         end loop;
+
+         if C = ASCII.CR or else C = ASCII.LF then
+            Advance;
+
+            if File.End_Of_File_Reached then
+               return;
+            end if;
+         end if;
+
+         if C = ASCII.CR
+           and then File.Buffer (File.Cursor) = ASCII.LF
+         then
+            Advance;
+         end if;
+      end if;
+   end Get_Line;
+
+   --------------
+   -- Is_Valid --
+   --------------
+
+   function Is_Valid (File : Text_File) return Boolean is
+   begin
+      return File /= null;
+   end Is_Valid;
+
+   ----------
+   -- Open --
+   ----------
+
+   procedure Open (File : out Text_File; Name : in String) is
+      FD        : File_Descriptor;
+      File_Name : String (1 .. Name'Length + 1);
+
+   begin
+      File_Name (1 .. Name'Length) := Name;
+      File_Name (File_Name'Last) := ASCII.NUL;
+      FD := Open_Read (Name => File_Name'Address,
+                            Fmode => GNAT.OS_Lib.Text);
+      if FD = Invalid_FD then
+         File := null;
+      else
+         File := new Text_File_Data;
+         File.FD := FD;
+         File.Buffer_Len :=
+           Read (FD => FD,
+                 A  => File.Buffer'Address,
+                 N  => File.Buffer'Length);
+
+         if File.Buffer_Len = 0 then
+            File.End_Of_File_Reached := True;
+         else
+            File.Cursor := 1;
+         end if;
+      end if;
+   end Open;
+
+   --------------
+   -- Value_Of --
+   --------------
+
+   function Value_Of
+     (Index    : Name_Id;
+      In_Array : Array_Element_Id)
+      return     Name_Id
+   is
+      Current : Array_Element_Id := In_Array;
+      Element : Array_Element;
+
+   begin
+      while Current /= No_Array_Element loop
+         Element := Array_Elements.Table (Current);
+
+         if Index = Element.Index then
+            exit when Element.Value.Kind /= Single;
+            exit when String_Length (Element.Value.Value) = 0;
+            String_To_Name_Buffer (Element.Value.Value);
+            return Name_Find;
+         else
+            Current := Element.Next;
+         end if;
+      end loop;
+
+      return No_Name;
+   end Value_Of;
+
+   function Value_Of
+     (Index    : Name_Id;
+      In_Array : Array_Element_Id)
+      return     Variable_Value
+   is
+      Current : Array_Element_Id := In_Array;
+      Element : Array_Element;
+
+   begin
+      while Current /= No_Array_Element loop
+         Element := Array_Elements.Table (Current);
+
+         if Index = Element.Index then
+            return Element.Value;
+         else
+            Current := Element.Next;
+         end if;
+      end loop;
+
+      return Nil_Variable_Value;
+   end Value_Of;
+
+   function Value_Of
+     (Name                    : Name_Id;
+      Attribute_Or_Array_Name : Name_Id;
+      In_Package              : Package_Id)
+      return                   Variable_Value
+   is
+      The_Array     : Array_Element_Id;
+      The_Attribute : Variable_Value := Nil_Variable_Value;
+
+   begin
+      if In_Package /= No_Package then
+
+         --  First, look if there is an array element that fits
+
+         The_Array :=
+           Value_Of
+             (Name      => Attribute_Or_Array_Name,
+              In_Arrays => Packages.Table (In_Package).Decl.Arrays);
+         The_Attribute :=
+           Value_Of
+             (Index    => Name,
+              In_Array => The_Array);
+
+         --  If there is no array element, look for a variable
+
+         if The_Attribute = Nil_Variable_Value then
+            The_Attribute :=
+              Value_Of
+                (Variable_Name => Attribute_Or_Array_Name,
+                 In_Variables  => Packages.Table (In_Package).Decl.Attributes);
+         end if;
+      end if;
+
+      return The_Attribute;
+   end Value_Of;
+
+   function Value_Of
+     (Index     : Name_Id;
+      In_Array  : Name_Id;
+      In_Arrays : Array_Id)
+      return      Name_Id
+   is
+      Current : Array_Id := In_Arrays;
+      The_Array : Array_Data;
+
+   begin
+      while Current /= No_Array loop
+         The_Array := Arrays.Table (Current);
+         if The_Array.Name = In_Array then
+            return Value_Of (Index, In_Array => The_Array.Value);
+         else
+            Current := The_Array.Next;
+         end if;
+      end loop;
+
+      return No_Name;
+   end Value_Of;
+
+   function Value_Of
+     (Name      : Name_Id;
+      In_Arrays : Array_Id)
+      return      Array_Element_Id
+   is
+      Current : Array_Id := In_Arrays;
+      The_Array : Array_Data;
+
+   begin
+      while Current /= No_Array loop
+         The_Array := Arrays.Table (Current);
+         if The_Array.Name = Name then
+            return The_Array.Value;
+         else
+            Current := The_Array.Next;
+         end if;
+      end loop;
+
+      return No_Array_Element;
+   end Value_Of;
+
+   function Value_Of
+     (Name        : Name_Id;
+      In_Packages : Package_Id)
+      return        Package_Id
+   is
+      Current : Package_Id := In_Packages;
+      The_Package : Package_Element;
+
+   begin
+      while Current /= No_Package loop
+         The_Package := Packages.Table (Current);
+         exit when The_Package.Name /= No_Name and then
+           The_Package.Name = Name;
+         Current := The_Package.Next;
+      end loop;
+
+      return Current;
+   end Value_Of;
+
+   function Value_Of
+     (Variable_Name : Name_Id;
+      In_Variables  : Variable_Id)
+      return          Variable_Value
+   is
+      Current : Variable_Id := In_Variables;
+      The_Variable : Variable;
+
+   begin
+      while Current /= No_Variable loop
+         The_Variable := Variable_Elements.Table (Current);
+
+         if Variable_Name = The_Variable.Name then
+            return The_Variable.Value;
+         else
+            Current := The_Variable.Next;
+         end if;
+      end loop;
+
+      return Nil_Variable_Value;
+   end Value_Of;
+
+   ---------------
+   -- Write_Str --
+   ---------------
+
+   procedure Write_Str
+     (S          : String;
+      Max_Length : Positive;
+      Separator  : Character)
+   is
+      First : Positive := S'First;
+      Last  : Natural  := S'Last;
+
+   begin
+      --  Nothing to do for empty strings
+
+      if S'Length > 0 then
+         --  Start on a new line if current line is already longer than
+         --  Max_Length.
+
+         if Positive (Column) >= Max_Length then
+            Write_Eol;
+         end if;
+
+         --  If length of remainder is longer than Max_Length, we need to
+         --  cut the remainder in several lines.
+
+         while Positive (Column) + S'Last - First > Max_Length loop
+            --  Try the maximum length possible
+
+            Last := First + Max_Length - Positive (Column);
+
+            --  Look for last Separator in the line
+
+            while Last >= First and then S (Last) /= Separator loop
+               Last := Last - 1;
+            end loop;
+
+            --  If we do not find a separator, we output the maximum length
+            --  possible.
+            if Last < First then
+               Last := First + Max_Length - Positive (Column);
+            end if;
+
+            Write_Line (S (First .. Last));
+
+            --  Set the beginning of the new remainder
+
+            First := Last + 1;
+
+         end loop;
+
+         --  What is left goes to the buffer, without EOL
+
+         Write_Str (S (First .. S'Last));
+
+      end if;
+   end Write_Str;
+
+end Prj.Util;
diff --git a/gcc/ada/prj-util.ads b/gcc/ada/prj-util.ads
new file mode 100644 (file)
index 0000000..baef040
--- /dev/null
@@ -0,0 +1,148 @@
+------------------------------------------------------------------------------
+--                                                                          --
+--                         GNAT COMPILER COMPONENTS                         --
+--                                                                          --
+--                              P R J . U T I L                             --
+--                                                                          --
+--                                 S p e c                                  --
+--                                                                          --
+--                            $Revision: 1.6 $
+--                                                                          --
+--             Copyright (C) 2001 Free Software Foundation, Inc.            --
+--                                                                          --
+-- GNAT is free software;  you can  redistribute it  and/or modify it under --
+-- terms of the  GNU General Public License as published  by the Free Soft- --
+-- ware  Foundation;  either version 2,  or (at your option) any later ver- --
+-- sion.  GNAT is distributed in the hope that it will be useful, but WITH- --
+-- OUT 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  distributed with GNAT;  see file COPYING.  If not, write --
+-- to  the Free Software Foundation,  59 Temple Place - Suite 330,  Boston, --
+-- MA 02111-1307, USA.                                                      --
+--                                                                          --
+-- GNAT was originally developed  by the GNAT team at  New York University. --
+-- It is now maintained by Ada Core Technologies Inc (http://www.gnat.com). --
+--                                                                          --
+------------------------------------------------------------------------------
+--
+--  Utilities when using project files.
+
+with GNAT.OS_Lib; use GNAT.OS_Lib;
+with Types;       use Types;
+
+package Prj.Util is
+
+   function Value_Of
+     (Index    : Name_Id;
+      In_Array : Array_Element_Id)
+      return     Name_Id;
+   --  Get a single string array component.
+   --  Returns No_Name if there is no component Index (case sensitive),
+   --  if In_Array is null, or if the component is a String list.
+
+   function Value_Of
+     (Index    : Name_Id;
+      In_Array : Array_Element_Id)
+      return     Variable_Value;
+   --  Get a string array component (single String or String list).
+   --  Returns Nil_Variable_Value if there is no component Index
+   --  (case sensitive), or if In_Array is null.
+
+   function Value_Of
+     (Name                    : Name_Id;
+      Attribute_Or_Array_Name : Name_Id;
+      In_Package              : Package_Id)
+      return                   Variable_Value;
+   --  In a specific package,
+   --   - if there exists an array Variable_Or_Array_Name with an index
+   --     Name, returns the corresponding component,
+   --   - otherwise if there is a attribute Attribute_Or_Array_Name,
+   --     returns this attribute,
+   --   - otherwise, returns Nil_Variable_Value.
+   --  If In_Package is null, returns Nil_Variable_Value.
+
+   function Value_Of
+     (Index     : Name_Id;
+      In_Array  : Name_Id;
+      In_Arrays : Array_Id)
+      return      Name_Id;
+   --  Get a string array component in an array of an array list.
+   --  Returns No_Name if there is no component Index (case sensitive),
+   --  if In_Arrays is null, if In_Array is not found in In_Arrays,
+   --  or if the component is a String list.
+
+   function Value_Of
+     (Name      : Name_Id;
+      In_Arrays : Array_Id)
+      return      Array_Element_Id;
+   --  Returns a specified array in an array list.
+   --  Returns No_Array_Element if In_Arrays is null or if Name is not the
+   --  name of an array in In_Arrays.
+   --  Assumption: Name is in lower case.
+
+   function Value_Of
+     (Name        : Name_Id;
+      In_Packages : Package_Id)
+      return        Package_Id;
+   --  Returns a specified package in a package list.
+   --  Returns No_Package if In_Packages is null or if Name is not the
+   --  name of a package in Package_List.
+   --  Assumption: Name is in lower case.
+
+   function Value_Of
+     (Variable_Name : Name_Id;
+      In_Variables  : Variable_Id)
+      return          Variable_Value;
+   --  Returns a specified variable in a variable list.
+   --  Returns null if In_Variables is null or if Variable_Name
+   --  is not the name of a variable in In_Variables.
+   --  Assumption: Variable_Name is in lower case.
+
+   procedure Write_Str
+     (S          : String;
+      Max_Length : Positive;
+      Separator  : Character);
+   --  Output string S using Output.Write_Str.
+   --  If S is too long to fit in one line of Max_Length, cut it in
+   --  several lines, using Separator as the last character of each line,
+   --  if possible.
+
+   type Text_File is limited private;
+   --  Represents a text file.
+   --  Default is invalid text file.
+
+   function Is_Valid (File : Text_File) return Boolean;
+   --  Returns True if File designates an open text file that
+   --  has not yet been closed.
+
+   procedure Open (File : out Text_File; Name : String);
+   --  Open a text file. If this procedure fails, File is invalid.
+
+   function End_Of_File (File : Text_File) return Boolean;
+   --  Returns True if the end of the text file File has been
+   --  reached. Fails if File is invalid.
+
+   procedure Get_Line
+     (File : Text_File;
+      Line : out String;
+      Last : out Natural);
+   --  Reads a line from an open text file. Fails if File is invalid.
+
+   procedure Close (File : in out Text_File);
+   --  Close an open text file. File becomes invalid.
+   --  Fails if File is already invalid.
+
+private
+
+   type Text_File_Data is record
+      FD                  : File_Descriptor := Invalid_FD;
+      Buffer              : String (1 .. 1_000);
+      Buffer_Len          : Natural;
+      Cursor              : Natural := 0;
+      End_Of_File_Reached : Boolean := False;
+   end record;
+
+   type Text_File is access Text_File_Data;
+
+end Prj.Util;
diff --git a/gcc/ada/prj.adb b/gcc/ada/prj.adb
new file mode 100644 (file)
index 0000000..8e30211
--- /dev/null
@@ -0,0 +1,286 @@
+------------------------------------------------------------------------------
+--                                                                          --
+--                         GNAT COMPILER COMPONENTS                         --
+--                                                                          --
+--                                  P R J                                   --
+--                                                                          --
+--                                 B o d y                                  --
+--                                                                          --
+--                            $Revision: 1.16 $
+--                                                                          --
+--             Copyright (C) 2001 Free Software Foundation, Inc.            --
+--                                                                          --
+-- GNAT is free software;  you can  redistribute it  and/or modify it under --
+-- terms of the  GNU General Public License as published  by the Free Soft- --
+-- ware  Foundation;  either version 2,  or (at your option) any later ver- --
+-- sion.  GNAT is distributed in the hope that it will be useful, but WITH- --
+-- OUT 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  distributed with GNAT;  see file COPYING.  If not, write --
+-- to  the Free Software Foundation,  59 Temple Place - Suite 330,  Boston, --
+-- MA 02111-1307, USA.                                                      --
+--                                                                          --
+-- GNAT was originally developed  by the GNAT team at  New York University. --
+-- It is now maintained by Ada Core Technologies Inc (http://www.gnat.com). --
+--                                                                          --
+------------------------------------------------------------------------------
+
+with Ada.Characters.Handling; use Ada.Characters.Handling;
+with Errout;      use Errout;
+with GNAT.OS_Lib; use GNAT.OS_Lib;
+with Namet;       use Namet;
+with Osint;       use Osint;
+with Prj.Attr;
+with Prj.Com;
+with Prj.Env;
+with Scans;       use Scans;
+with Scn;
+with Stringt;     use Stringt;
+with Sinfo.CN;
+with Snames;      use Snames;
+
+package body Prj is
+
+   The_Empty_String : String_Id;
+
+   subtype Known_Casing is Casing_Type range All_Upper_Case .. Mixed_Case;
+
+   The_Casing_Images : array (Known_Casing) of String_Access :=
+     (All_Lower_Case => new String'("lowercase"),
+      All_Upper_Case => new String'("UPPERCASE"),
+      Mixed_Case     => new String'("MixedCase"));
+
+   Initialized : Boolean := False;
+
+   Standard_Dot_Replacement      : constant Name_Id :=
+     First_Name_Id + Character'Pos ('-');
+   Standard_Specification_Append : Name_Id;
+   Standard_Body_Append          : Name_Id;
+
+   Std_Naming_Data : Naming_Data :=
+     (Dot_Replacement      => Standard_Dot_Replacement,
+      Dot_Repl_Loc         => No_Location,
+      Casing               => All_Lower_Case,
+      Specification_Append => No_Name,
+      Spec_Append_Loc      => No_Location,
+      Body_Append          => No_Name,
+      Body_Append_Loc      => No_Location,
+      Separate_Append      => No_Name,
+      Sep_Append_Loc       => No_Location,
+      Specifications       => No_Array_Element,
+      Bodies               => No_Array_Element);
+
+   Project_Empty : Project_Data :=
+     (First_Referred_By  => No_Project,
+      Name               => No_Name,
+      Path_Name          => No_Name,
+      Location           => No_Location,
+      Directory          => No_Name,
+      File_Name          => No_Name,
+      Library            => False,
+      Library_Dir        => No_Name,
+      Library_Name       => No_Name,
+      Library_Kind       => Static,
+      Lib_Internal_Name  => No_Name,
+      Lib_Elaboration    => False,
+      Sources            => Nil_String,
+      Source_Dirs        => Nil_String,
+      Object_Directory   => No_Name,
+      Modifies           => No_Project,
+      Modified_By        => No_Project,
+      Naming             => Std_Naming_Data,
+      Decl               => No_Declarations,
+      Imported_Projects  => Empty_Project_List,
+      Include_Path       => null,
+      Objects_Path       => null,
+      Config_File_Name   => No_Name,
+      Config_File_Temp   => False,
+      Config_Checked     => False,
+      Checked            => False,
+      Seen               => False,
+      Flag1              => False,
+      Flag2              => False);
+
+   -------------------
+   -- Empty_Project --
+   -------------------
+
+   function Empty_Project return Project_Data is
+   begin
+      Initialize;
+      return Project_Empty;
+   end Empty_Project;
+
+   ------------------
+   -- Empty_String --
+   ------------------
+
+   function Empty_String return String_Id is
+   begin
+      return The_Empty_String;
+   end Empty_String;
+
+   ------------
+   -- Expect --
+   ------------
+
+   procedure Expect (The_Token : Token_Type; Token_Image : String) is
+   begin
+      if Token /= The_Token then
+         Error_Msg ("""" & Token_Image & """ expected", Token_Ptr);
+      end if;
+   end Expect;
+
+   --------------------------------
+   -- For_Every_Project_Imported --
+   --------------------------------
+
+   procedure For_Every_Project_Imported
+     (By         : Project_Id;
+      With_State : in out State)
+   is
+
+      procedure Check (Project : Project_Id);
+      --  Check if a project has already been seen.
+      --  If not seen, mark it as seen, call Action,
+      --  and check all its imported projects.
+
+      procedure Check (Project : Project_Id) is
+         List : Project_List;
+
+      begin
+         if not Projects.Table (Project).Seen then
+            Projects.Table (Project).Seen := False;
+            Action (Project, With_State);
+
+            List := Projects.Table (Project).Imported_Projects;
+            while List /= Empty_Project_List loop
+               Check (Project_Lists.Table (List).Project);
+               List := Project_Lists.Table (List).Next;
+            end loop;
+         end if;
+      end Check;
+
+   begin
+      for Project in Projects.First .. Projects.Last loop
+         Projects.Table (Project).Seen := False;
+      end loop;
+
+      Check (Project => By);
+   end For_Every_Project_Imported;
+
+   -----------
+   -- Image --
+   -----------
+
+   function Image (Casing : Casing_Type) return String is
+   begin
+      return The_Casing_Images (Casing).all;
+   end Image;
+
+   ----------------
+   -- Initialize --
+   ----------------
+
+   procedure Initialize is
+   begin
+      if not Initialized then
+         Initialized := True;
+         Stringt.Initialize;
+         Start_String;
+         The_Empty_String := End_String;
+         Name_Len := 4;
+         Name_Buffer (1 .. 4) := ".ads";
+         Canonical_Case_File_Name (Name_Buffer (1 .. 4));
+         Standard_Specification_Append := Name_Find;
+         Name_Buffer (4) := 'b';
+         Canonical_Case_File_Name (Name_Buffer (1 .. 4));
+         Standard_Body_Append := Name_Find;
+         Std_Naming_Data.Specification_Append := Standard_Specification_Append;
+         Std_Naming_Data.Body_Append          := Standard_Body_Append;
+         Std_Naming_Data.Separate_Append      := Standard_Body_Append;
+         Project_Empty.Naming                 := Std_Naming_Data;
+         Prj.Env.Initialize;
+         Prj.Attr.Initialize;
+         Set_Name_Table_Byte (Name_Project,   Token_Type'Pos (Tok_Project));
+         Set_Name_Table_Byte (Name_Modifying, Token_Type'Pos (Tok_Modifying));
+         Set_Name_Table_Byte (Name_External,  Token_Type'Pos (Tok_External));
+      end if;
+   end Initialize;
+
+   ------------
+   --  Reset --
+   ------------
+
+   procedure Reset is
+   begin
+      Projects.Init;
+      Project_Lists.Init;
+      Packages.Init;
+      Arrays.Init;
+      Variable_Elements.Init;
+      String_Elements.Init;
+      Prj.Com.Units.Init;
+      Prj.Com.Units_Htable.Reset;
+   end Reset;
+
+   ------------------------
+   -- Same_Naming_Scheme --
+   ------------------------
+
+   function Same_Naming_Scheme
+     (Left, Right : Naming_Data)
+      return        Boolean
+   is
+   begin
+      return Left.Dot_Replacement = Right.Dot_Replacement
+        and then Left.Casing = Right.Casing
+        and then Left.Specification_Append = Right.Specification_Append
+        and then Left.Body_Append = Right.Body_Append
+        and then Left.Separate_Append = Right.Separate_Append;
+   end Same_Naming_Scheme;
+
+   ----------
+   -- Scan --
+   ----------
+
+   procedure Scan is
+   begin
+      Scn.Scan;
+
+      --  Change operator symbol to literal strings, since that's the way
+      --  we treat all strings in a project file.
+
+      if Token = Tok_Operator_Symbol then
+         Sinfo.CN.Change_Operator_Symbol_To_String_Literal (Token_Node);
+         Token := Tok_String_Literal;
+      end if;
+   end Scan;
+
+   --------------------------
+   -- Standard_Naming_Data --
+   --------------------------
+
+   function Standard_Naming_Data return Naming_Data is
+   begin
+      Initialize;
+      return Std_Naming_Data;
+   end Standard_Naming_Data;
+
+   -----------
+   -- Value --
+   -----------
+
+   function Value (Image : String) return Casing_Type is
+   begin
+      for Casing in The_Casing_Images'Range loop
+         if To_Lower (Image) = To_Lower (The_Casing_Images (Casing).all) then
+            return Casing;
+         end if;
+      end loop;
+
+      raise Constraint_Error;
+   end Value;
+
+end Prj;
diff --git a/gcc/ada/prj.ads b/gcc/ada/prj.ads
new file mode 100644 (file)
index 0000000..409a071
--- /dev/null
@@ -0,0 +1,416 @@
+------------------------------------------------------------------------------
+--                                                                          --
+--                         GNAT COMPILER COMPONENTS                         --
+--                                                                          --
+--                                  P R J                                   --
+--                                                                          --
+--                                 S p e c                                  --
+--                                                                          --
+--                            $Revision: 1.18 $
+--                                                                          --
+--             Copyright (C) 2001 Free Software Foundation, Inc.            --
+--                                                                          --
+-- GNAT is free software;  you can  redistribute it  and/or modify it under --
+-- terms of the  GNU General Public License as published  by the Free Soft- --
+-- ware  Foundation;  either version 2,  or (at your option) any later ver- --
+-- sion.  GNAT is distributed in the hope that it will be useful, but WITH- --
+-- OUT 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  distributed with GNAT;  see file COPYING.  If not, write --
+-- to  the Free Software Foundation,  59 Temple Place - Suite 330,  Boston, --
+-- MA 02111-1307, USA.                                                      --
+--                                                                          --
+-- GNAT was originally developed  by the GNAT team at  New York University. --
+-- It is now maintained by Ada Core Technologies Inc (http://www.gnat.com). --
+--                                                                          --
+------------------------------------------------------------------------------
+
+--  The following package declares the data types for GNAT project.
+--  These data types may be used by GNAT Project-aware tools.
+
+--  Children of these package implements various services on these data types.
+--  See in particular Prj.Pars and Prj.Env.
+
+with Casing;      use Casing;
+with GNAT.OS_Lib; use GNAT.OS_Lib;
+with Scans;       use Scans;
+with Table;
+with Types;       use Types;
+
+package Prj is
+
+   type Put_Line_Access is access procedure (Line : String);
+   --  Use to customize error reporting in Prj.Proc and Prj.Nmsc.
+
+   type Verbosity is (Default, Medium, High);
+   --  Verbosity when parsing GNAT Project Files.
+   --  Default is default (very quiet, if no errors).
+   --  Medium is more verbose.
+   --  High is extremely verbose.
+
+   type Lib_Kind is (Static, Dynamic, Relocatable);
+
+   function Empty_String return String_Id;
+
+   type String_List_Id is new Nat;
+   Nil_String : constant String_List_Id := 0;
+   type String_Element is record
+      Value    : String_Id      := No_String;
+      Location : Source_Ptr     := No_Location;
+      Next     : String_List_Id := Nil_String;
+   end record;
+   --  To hold values for string list variables and array elements.
+
+   package String_Elements is new Table.Table
+     (Table_Component_Type => String_Element,
+      Table_Index_Type     => String_List_Id,
+      Table_Low_Bound      => 1,
+      Table_Initial        => 200,
+      Table_Increment      => 100,
+      Table_Name           => "Prj.String_Elements");
+   --  The table for string elements in string lists.
+
+   type Variable_Kind is (Undefined, List, Single);
+   --  Different kinds of variables
+
+   type Variable_Value (Kind : Variable_Kind := Undefined) is record
+      Location : Source_Ptr := No_Location;
+      Default  : Boolean    := False;
+      case Kind is
+         when Undefined =>
+            null;
+         when List =>
+            Values : String_List_Id := Nil_String;
+         when Single =>
+            Value : String_Id := No_String;
+      end case;
+   end record;
+   --  Values for variables and array elements
+
+   Nil_Variable_Value : constant Variable_Value :=
+     (Kind     => Undefined,
+      Location => No_Location,
+      Default  => False);
+   --  Value of a non existing variable or array element.
+
+   type Variable_Id is new Nat;
+   No_Variable : constant Variable_Id := 0;
+   type Variable is record
+      Next     : Variable_Id := No_Variable;
+      Name     : Name_Id;
+      Value    : Variable_Value;
+   end record;
+   --  To hold the list of variables in a project file and in packages.
+
+   package Variable_Elements is new Table.Table
+     (Table_Component_Type => Variable,
+      Table_Index_Type     => Variable_Id,
+      Table_Low_Bound      => 1,
+      Table_Initial        => 200,
+      Table_Increment      => 100,
+      Table_Name           => "Prj.Variable_Elements");
+   --  The table of variable in list of variables.
+
+   type Array_Element_Id is new Nat;
+   No_Array_Element : constant Array_Element_Id := 0;
+   type Array_Element is record
+      Index    : Name_Id;
+      Value    : Variable_Value;
+      Next     : Array_Element_Id := No_Array_Element;
+   end record;
+   --  Each Array_Element represents an array element.
+   --  Each Array_Element is linked (Next) to the next array element,
+   --  if any, in the array.
+
+   package Array_Elements is new Table.Table
+     (Table_Component_Type => Array_Element,
+      Table_Index_Type     => Array_Element_Id,
+      Table_Low_Bound      => 1,
+      Table_Initial        => 200,
+      Table_Increment      => 100,
+      Table_Name           => "Prj.Array_Elements");
+   --  The table that contains all array elements
+
+   type Array_Id is new Nat;
+   No_Array : constant Array_Id := 0;
+   type Array_Data is record
+      Name  : Name_Id          := No_Name;
+      Value : Array_Element_Id := No_Array_Element;
+      Next  : Array_Id         := No_Array;
+   end record;
+   --  Each Array_Data represents an array.
+   --  Value is the id of the first element.
+   --  Next is the id of the next array in the project file or package.
+
+   package Arrays is new Table.Table
+     (Table_Component_Type => Array_Data,
+      Table_Index_Type     => Array_Id,
+      Table_Low_Bound      => 1,
+      Table_Initial        => 200,
+      Table_Increment      => 100,
+      Table_Name           => "Prj.Arrays");
+   --  The table that contains all arrays
+
+   type Package_Id is new Nat;
+   No_Package : constant Package_Id := 0;
+   type Declarations is record
+      Variables  : Variable_Id := No_Variable;
+      Attributes : Variable_Id := No_Variable;
+      Arrays     : Array_Id    := No_Array;
+      Packages   : Package_Id  := No_Package;
+   end record;
+
+   No_Declarations : constant Declarations :=
+     (Variables  => No_Variable,
+      Attributes => No_Variable,
+      Arrays     => No_Array,
+      Packages   => No_Package);
+   --  Declarations. Used in project structures and packages.
+
+   type Package_Element is record
+      Name   : Name_Id      := No_Name;
+      Decl   : Declarations := No_Declarations;
+      Parent : Package_Id   := No_Package;
+      Next   : Package_Id   := No_Package;
+   end record;
+   --  A package. Includes declarations that may include
+   --  other packages.
+
+   package Packages is new Table.Table
+     (Table_Component_Type => Package_Element,
+      Table_Index_Type     => Package_Id,
+      Table_Low_Bound      => 1,
+      Table_Initial        => 100,
+      Table_Increment      => 100,
+      Table_Name           => "Prj.Packages");
+   --  The table that contains all packages.
+
+   function Image (Casing : Casing_Type) return String;
+   --  Similar to 'Image
+
+   function Value (Image : String) return Casing_Type;
+   --  Similar to 'Value
+   --  This is to avoid s-valenu in the closure of the tools
+   --  Raises Constraint_Error if not a Casing_Type image.
+
+   type Naming_Data is record
+      Dot_Replacement      : Name_Id          := No_Name;
+      --  The string to replace '.' in the source file name.
+
+      Dot_Repl_Loc         : Source_Ptr       := No_Location;
+      --  The position in the project file source where
+      --  Dot_Replacement is defined.
+
+      Casing               : Casing_Type      := All_Lower_Case;
+      --  The casing of the source file name.
+
+      Specification_Append : Name_Id          := No_Name;
+      --  The string to append to the unit name for the
+      --  source file name of a specification.
+
+      Spec_Append_Loc      : Source_Ptr       := No_Location;
+      --  The position in the project file source where
+      --  Specification_Append is defined.
+
+      Body_Append          : Name_Id          := No_Name;
+      --  The string to append to the unit name for the
+      --  source file name of a body.
+
+      Body_Append_Loc      : Source_Ptr       := No_Location;
+      --  The position in the project file source where
+      --  Body_Append is defined.
+
+      Separate_Append      : Name_Id          := No_Name;
+      --  The string to append to the unit name for the
+      --  source file name of a subunit.
+
+      Sep_Append_Loc       : Source_Ptr       := No_Location;
+      --  The position in the project file source where
+      --  Separate_Append is defined.
+
+      Specifications       : Array_Element_Id := No_Array_Element;
+      --  An associative array mapping individual specifications
+      --  to source file names.
+
+      Bodies               : Array_Element_Id := No_Array_Element;
+      --  An associative array mapping individual bodies
+      --  to source file names.
+
+   end record;
+   --  A naming scheme.
+
+   function Standard_Naming_Data return Naming_Data;
+   pragma Inline (Standard_Naming_Data);
+   --  The standard GNAT naming scheme.
+
+   function Same_Naming_Scheme
+     (Left, Right : Naming_Data)
+      return        Boolean;
+   --  Returns True if Left and Right are the same naming scheme
+   --  not considering Specifications and Bodies.
+
+   type Project_Id is new Nat;
+   No_Project : constant Project_Id := 0;
+   --  Id of a Project File
+
+   type Project_List is new Nat;
+   Empty_Project_List : constant Project_List := 0;
+   --  A list of project files.
+
+   type Project_Element is record
+      Project : Project_Id   := No_Project;
+      Next    : Project_List := Empty_Project_List;
+   end record;
+   --  Element in a list of project file.
+   --  Next is the id of the next project file in the list.
+
+   package Project_Lists is new Table.Table
+     (Table_Component_Type => Project_Element,
+      Table_Index_Type     => Project_List,
+      Table_Low_Bound      => 1,
+      Table_Initial        => 100,
+      Table_Increment      => 100,
+      Table_Name           => "Prj.Project_Lists");
+   --  The table that contains the lists of project files.
+
+   type Project_Data is record
+      First_Referred_By  : Project_Id     := No_Project;
+      --  The project, if any, that was the first to be known
+      --  as importing or modifying this project.
+
+      Name               : Name_Id        := No_Name;
+      --  The name of the project.
+
+      Path_Name          : Name_Id        := No_Name;
+      --  The path name of the project file.
+
+      Location           : Source_Ptr     := No_Location;
+      --  The location in the project file source of the
+      --  reserved word project.
+
+      Directory          : Name_Id        := No_Name;
+      --  The directory where the project file resides.
+
+      File_Name          : Name_Id        := No_Name;
+      --  The file name of the project file.
+
+      Library            : Boolean        := False;
+      --  True if this is a library project
+
+      Library_Dir        : Name_Id        := No_Name;
+      --  If a library project, directory where resides the library
+
+      Library_Name       : Name_Id        := No_Name;
+      --  If a library project, name of the library
+
+      Library_Kind       : Lib_Kind       := Static;
+      --  If a library project, kind of library
+
+      Lib_Internal_Name  : Name_Id        := No_Name;
+      --  If a library project, internal name store inside the library
+
+      Lib_Elaboration    : Boolean        := False;
+      --  If a library project, indicate if <lib>init and <lib>final
+      --  procedures need to be defined.
+
+      Sources            : String_List_Id := Nil_String;
+      --  The list of all the source file names.
+
+      Source_Dirs        : String_List_Id := Nil_String;
+      --  The list of all the source directories.
+
+      Object_Directory   : Name_Id        := No_Name;
+      --  The object directory of this project file.
+
+      Modifies           : Project_Id     := No_Project;
+      --  The reference of the project file, if any, that this
+      --  project file modifies.
+
+      Modified_By        : Project_Id     := No_Project;
+      --  The reference of the project file, if any, that
+      --  modifies this project file.
+
+      Naming             : Naming_Data    := Standard_Naming_Data;
+      --  The naming scheme of this project file.
+
+      Decl               : Declarations   := No_Declarations;
+      --  The declarations (variables, attributes and packages)
+      --  of this project file.
+
+      Imported_Projects  : Project_List   := Empty_Project_List;
+      --  The list of all directly imported projects, if any.
+
+      Include_Path       : String_Access  := null;
+      --  The cached value of ADA_INCLUDE_PATH for this project file.
+
+      Objects_Path       : String_Access  := null;
+      --  The cached value of ADA_OBJECTS_PATH for this project file.
+
+      Config_File_Name   : Name_Id        := No_Name;
+      --  The name of the configuration pragmas file, if any.
+
+      Config_File_Temp   : Boolean        := False;
+      --  An indication that the configuration pragmas file is
+      --  a temporary file that must be deleted at the end.
+
+      Config_Checked     : Boolean        := False;
+      --  A flag to avoid checking repetively the configuration pragmas file.
+
+      Checked            : Boolean        := False;
+      --  A flag to avoid checking repetively the naming scheme of
+      --  this project file.
+
+      --  Various flags that are used in an ad hoc manner
+
+      Seen               : Boolean        := False;
+      Flag1              : Boolean        := False;
+      Flag2              : Boolean        := False;
+
+   end record;
+   --  Project File representation.
+
+   function Empty_Project return Project_Data;
+   --  Return the representation of an empty project.
+
+   package Projects is new Table.Table (
+     Table_Component_Type => Project_Data,
+     Table_Index_Type     => Project_Id,
+     Table_Low_Bound      => 1,
+     Table_Initial        => 100,
+     Table_Increment      => 100,
+     Table_Name           => "Prj.Projects");
+   --  The set of all project files.
+
+   procedure Expect (The_Token : Token_Type; Token_Image : String);
+   --  Check that the current token is The_Token. If it is not, then
+   --  output an error message.
+
+   procedure Initialize;
+   --  This procedure must be called before using any services from the Prj
+   --  hierarchy. Namet.Initialize must be called before Prj.Initialize.
+
+   procedure Reset;
+   --  This procedure resets all the tables that are used when processing a
+   --  project file tree. Initialize must be called before the call to Reset.
+
+   generic
+      type State is limited private;
+      with procedure Action
+        (Project    : Project_Id;
+         With_State : in out State);
+   procedure For_Every_Project_Imported
+     (By         : Project_Id;
+      With_State : in out State);
+   --  Call Action for each project imported directly or indirectly by project
+   --  By.--  Action is called according to the order of importation: if A
+   --  imports B, directly or indirectly, Action will be called for A before
+   --  it is called for B. With_State may be used by Action to choose a
+   --  behavior or to report some global result.
+
+private
+
+   procedure Scan;
+   --  Calls Scn.Scan and change any Operator_Symbol to String_Literal
+
+end Prj;
diff --git a/gcc/ada/raise.c b/gcc/ada/raise.c
new file mode 100644 (file)
index 0000000..43d6307
--- /dev/null
@@ -0,0 +1,86 @@
+/****************************************************************************
+ *                                                                          *
+ *                         GNAT COMPILER COMPONENTS                         *
+ *                                                                          *
+ *                                R A I S E                                 *
+ *                                                                          *
+ *                          C Implementation File                           *
+ *                                                                          *
+ *                            $Revision: 1.1 $
+ *                                                                          *
+ *             Copyright (C) 1992-2001, Free Software Foundation, Inc.      *
+ *                                                                          *
+ * GNAT is free software;  you can  redistribute it  and/or modify it under *
+ * terms of the  GNU General Public License as published  by the Free Soft- *
+ * ware  Foundation;  either version 2,  or (at your option) any later ver- *
+ * sion.  GNAT is distributed in the hope that it will be useful, but WITH- *
+ * OUT 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  distributed with GNAT;  see file COPYING.  If not, write *
+ * to  the Free Software Foundation,  59 Temple Place - Suite 330,  Boston, *
+ * MA 02111-1307, USA.                                                      *
+ *                                                                          *
+ * As a  special  exception,  if you  link  this file  with other  files to *
+ * produce an executable,  this file does not by itself cause the resulting *
+ * executable to be covered by the GNU General Public License. This except- *
+ * ion does not  however invalidate  any other reasons  why the  executable *
+ * file might be covered by the  GNU Public License.                        *
+ *                                                                          *
+ * GNAT was originally developed  by the GNAT team at  New York University. *
+ * It is now maintained by Ada Core Technologies Inc (http://www.gnat.com). *
+ *                                                                          *
+ ****************************************************************************/
+
+/* Routines to support runtime exception handling */
+
+#ifdef IN_RTS
+#include "tconfig.h"
+#include "tsystem.h"
+#include <sys/stat.h>
+#else
+#include "config.h"
+#include "system.h"
+#endif
+
+#include "adaint.h"
+#include "raise.h"
+
+/*  We have not yet figured out how to import this directly */
+
+void
+_gnat_builtin_longjmp (ptr, flag)
+     void *ptr;
+     int flag ATTRIBUTE_UNUSED;
+{
+   __builtin_longjmp (ptr, 1);
+}
+
+/* When an exception is raised for which no handler exists, the procedure
+   Ada.Exceptions.Unhandled_Exception is called, which performs the call to
+   adafinal to complete finalization, and then prints out the error messages
+   for the unhandled exception. The final step is to call this routine, which
+   performs any system dependent cleanup required.  */
+
+void
+__gnat_unhandled_terminate ()
+{
+  /* Special termination handling for VMS */
+
+#ifdef VMS
+    {
+      long prvhnd;
+
+      /* Remove the exception vector so it won't intercept any errors
+        in the call to exit, and go into and endless loop */
+
+      SYS$SETEXV (1, 0, 3, &prvhnd);
+      __gnat_os_exit (1);
+    }
+
+/* Termination handling for all other systems. */
+
+#elif !defined (__RT__)
+    __gnat_os_exit (1);
+#endif
+}
diff --git a/gcc/ada/raise.h b/gcc/ada/raise.h
new file mode 100644 (file)
index 0000000..8db83f4
--- /dev/null
@@ -0,0 +1,71 @@
+/****************************************************************************
+ *                                                                          *
+ *                         GNAT COMPILER COMPONENTS                         *
+ *                                                                          *
+ *                                R A I S E                                 *
+ *                                                                          *
+ *                              C Header File                               *
+ *                                                                          *
+ *                            $Revision: 1.1 $
+ *                                                                          *
+ *          Copyright (C) 1992-2001, Free Software Foundation, Inc.         *
+ *                                                                          *
+ * GNAT is free software;  you can  redistribute it  and/or modify it under *
+ * terms of the  GNU General Public License as published  by the Free Soft- *
+ * ware  Foundation;  either version 2,  or (at your option) any later ver- *
+ * sion.  GNAT is distributed in the hope that it will be useful, but WITH- *
+ * OUT 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  distributed with GNAT;  see file COPYING.  If not, write *
+ * to  the Free Software Foundation,  59 Temple Place - Suite 330,  Boston, *
+ * MA 02111-1307, USA.                                                      *
+ *                                                                          *
+ * As a  special  exception,  if you  link  this file  with other  files to *
+ * produce an executable,  this file does not by itself cause the resulting *
+ * executable to be covered by the GNU General Public License. This except- *
+ * ion does not  however invalidate  any other reasons  why the  executable *
+ * file might be covered by the  GNU Public License.                        *
+ *                                                                          *
+ * GNAT was originally developed  by the GNAT team at  New York University. *
+ * It is now maintained by Ada Core Technologies Inc (http://www.gnat.com). *
+ *                                                                          *
+ ****************************************************************************/
+
+struct Exception_Data
+{ 
+  char  Handled_By_Others;
+  char Lang;
+  int Name_Length;
+  char *Full_Name, Htable_Ptr;
+  int Import_Code;
+};
+
+typedef struct Exception_Data *Exception_Id;
+
+struct Exception_Occurrence
+{
+  int Max_Length;
+  Exception_Id Id;
+  int Msg_Length;
+  char Msg [0];
+};
+
+typedef struct Exception_Occurrence *Exception_Occurrence_Access;
+
+extern void _gnat_builtin_longjmp      PARAMS ((void *, int));
+extern void __gnat_unhandled_terminate PARAMS ((void));
+extern void *__gnat_malloc             PARAMS ((__SIZE_TYPE__));
+extern void __gnat_free                        PARAMS ((void *));
+extern void *__gnat_realloc            PARAMS ((void *, __SIZE_TYPE__));
+extern void __gnat_finalize            PARAMS ((void));
+extern void set_gnat_exit_status       PARAMS ((int));
+extern void __gnat_set_globals         PARAMS ((int, int, int, int, int, int,
+                                                void (*) PARAMS ((void)),
+                                                int, int));
+extern void __gnat_initialize          PARAMS ((void));
+extern void __gnat_init_float          PARAMS ((void));
+extern void __gnat_install_handler     PARAMS ((void));
+
+extern int gnat_exit_status;
+
diff --git a/gcc/ada/repinfo.adb b/gcc/ada/repinfo.adb
new file mode 100644 (file)
index 0000000..9e71152
--- /dev/null
@@ -0,0 +1,1024 @@
+------------------------------------------------------------------------------
+--                                                                          --
+--                         GNAT COMPILER COMPONENTS                         --
+--                                                                          --
+--                              R E P I N F O                               --
+--                                                                          --
+--                                 B o d y                                  --
+--                                                                          --
+--                            $Revision: 1.36 $
+--                                                                          --
+--          Copyright (C) 1999-2001 Free Software Foundation, Inc.          --
+--                                                                          --
+-- GNAT is free software;  you can  redistribute it  and/or modify it under --
+-- terms of the  GNU General Public License as published  by the Free Soft- --
+-- ware  Foundation;  either version 2,  or (at your option) any later ver- --
+-- sion.  GNAT is distributed in the hope that it will be useful, but WITH- --
+-- OUT 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  distributed with GNAT;  see file COPYING.  If not, write --
+-- to  the Free Software Foundation,  59 Temple Place - Suite 330,  Boston, --
+-- MA 02111-1307, USA.                                                      --
+--                                                                          --
+-- As a special exception,  if other files  instantiate  generics from this --
+-- unit, or you link  this unit with other files  to produce an executable, --
+-- this  unit  does not  by itself cause  the resulting  executable  to  be --
+-- covered  by the  GNU  General  Public  License.  This exception does not --
+-- however invalidate  any other reasons why  the executable file  might be --
+-- covered by the  GNU Public License.                                      --
+--                                                                          --
+-- GNAT was originally developed  by the GNAT team at  New York University. --
+-- It is now maintained by Ada Core Technologies Inc (http://www.gnat.com). --
+--                                                                          --
+------------------------------------------------------------------------------
+
+with Alloc;    use Alloc;
+with Atree;    use Atree;
+with Casing;   use Casing;
+with Debug;    use Debug;
+with Einfo;    use Einfo;
+with Lib;      use Lib;
+with Namet;    use Namet;
+with Opt;      use Opt;
+with Output;   use Output;
+with Sinfo;    use Sinfo;
+with Sinput;   use Sinput;
+with Table;    use Table;
+with Uname;    use Uname;
+with Urealp;   use Urealp;
+
+package body Repinfo is
+
+   SSU : constant := 8;
+   --  Value for Storage_Unit, we do not want to get this from TTypes, since
+   --  this introduces problematic dependencies in ASIS, and in any case this
+   --  value is assumed to be 8 for the implementation of the DDA.
+   --  This is wrong for AAMP???
+
+   ---------------------------------------
+   -- Representation of gcc Expressions --
+   ---------------------------------------
+
+   --    This table is used only if Frontend_Layout_On_Target is False,
+   --    so that gigi lays out dynamic size/offset fields using encoded
+   --    gcc expressions.
+
+   --    A table internal to this unit is used to hold the values of
+   --    back annotated expressions. This table is written out by -gnatt
+   --    and read back in for ASIS processing.
+
+   --    Node values are stored as Uint values which are the negative of
+   --    the node index in this table. Constants appear as non-negative
+   --    Uint values.
+
+   type Exp_Node is record
+      Expr : TCode;
+      Op1  : Node_Ref_Or_Val;
+      Op2  : Node_Ref_Or_Val;
+      Op3  : Node_Ref_Or_Val;
+   end record;
+
+   package Rep_Table is new Table.Table (
+      Table_Component_Type => Exp_Node,
+      Table_Index_Type     => Nat,
+      Table_Low_Bound      => 1,
+      Table_Initial        => Alloc.Rep_Table_Initial,
+      Table_Increment      => Alloc.Rep_Table_Increment,
+      Table_Name           => "BE_Rep_Table");
+
+   --------------------------------------------------------------
+   -- Representation of Front-End Dynamic Size/Offset Entities --
+   --------------------------------------------------------------
+
+   package Dynamic_SO_Entity_Table is new Table.Table (
+      Table_Component_Type => Entity_Id,
+      Table_Index_Type     => Nat,
+      Table_Low_Bound      => 1,
+      Table_Initial        => Alloc.Rep_Table_Initial,
+      Table_Increment      => Alloc.Rep_Table_Increment,
+      Table_Name           => "FE_Rep_Table");
+
+   -----------------------
+   -- Local Subprograms --
+   -----------------------
+
+   Unit_Casing : Casing_Type;
+   --  Indentifier casing for current unit
+
+   procedure Spaces (N : Natural);
+   --  Output given number of spaces
+
+   function Back_End_Layout return Boolean;
+   --  Test for layout mode, True = back end, False = front end. This
+   --  function is used rather than checking the configuration parameter
+   --  because we do not want Repinfo to depend on Targparm (for ASIS)
+
+   procedure List_Entities (Ent : Entity_Id);
+   --  This procedure lists the entities associated with the entity E,
+   --  starting with the First_Entity and using the Next_Entity link.
+   --  If a nested package is found, entities within the package are
+   --  recursively processed.
+
+   procedure List_Name (Ent : Entity_Id);
+   --  List name of entity Ent in appropriate case. The name is listed with
+   --  full qualification up to but not including the compilation unit name.
+
+   procedure List_Array_Info (Ent : Entity_Id);
+   --  List representation info for array type Ent
+
+   procedure List_Object_Info (Ent : Entity_Id);
+   --  List representation info for object Ent
+
+   procedure List_Record_Info (Ent : Entity_Id);
+   --  List representation info for record type Ent
+
+   procedure List_Type_Info (Ent : Entity_Id);
+   --  List type info for type Ent
+
+   function Rep_Not_Constant (Val : Node_Ref_Or_Val) return Boolean;
+   --  Returns True if Val represents a variable value, and False if it
+   --  represents a value that is fixed at compile time.
+
+   procedure Write_Val (Val : Node_Ref_Or_Val; Paren : Boolean := False);
+   --  Given a representation value, write it out. No_Uint values or values
+   --  dependent on discriminants are written as two question marks. If the
+   --  flag Paren is set, then the output is surrounded in parentheses if
+   --  it is other than a simple value.
+
+   ---------------------
+   -- Back_End_Layout --
+   ---------------------
+
+   function Back_End_Layout return Boolean is
+   begin
+      --  We have back end layout if the back end has made any entries in
+      --  the table of GCC expressions, otherwise we have front end layout.
+
+      return Rep_Table.Last > 0;
+   end Back_End_Layout;
+
+   ------------------------
+   -- Create_Discrim_Ref --
+   ------------------------
+
+   function Create_Discrim_Ref
+     (Discr : Entity_Id)
+      return  Node_Ref
+   is
+      N : constant Uint := Discriminant_Number (Discr);
+      T : Nat;
+
+   begin
+      Rep_Table.Increment_Last;
+      T := Rep_Table.Last;
+      Rep_Table.Table (T).Expr := Discrim_Val;
+      Rep_Table.Table (T).Op1  := N;
+      Rep_Table.Table (T).Op2  := No_Uint;
+      Rep_Table.Table (T).Op3  := No_Uint;
+      return UI_From_Int (-T);
+   end Create_Discrim_Ref;
+
+   ---------------------------
+   -- Create_Dynamic_SO_Ref --
+   ---------------------------
+
+   function Create_Dynamic_SO_Ref
+     (E    : Entity_Id)
+      return Dynamic_SO_Ref
+   is
+      T : Nat;
+
+   begin
+      Dynamic_SO_Entity_Table.Increment_Last;
+      T := Dynamic_SO_Entity_Table.Last;
+      Dynamic_SO_Entity_Table.Table (T) := E;
+      return UI_From_Int (-T);
+   end Create_Dynamic_SO_Ref;
+
+   -----------------
+   -- Create_Node --
+   -----------------
+
+   function Create_Node
+     (Expr : TCode;
+      Op1  : Node_Ref_Or_Val;
+      Op2  : Node_Ref_Or_Val := No_Uint;
+      Op3  : Node_Ref_Or_Val := No_Uint)
+      return  Node_Ref
+   is
+      T : Nat;
+
+   begin
+      Rep_Table.Increment_Last;
+      T := Rep_Table.Last;
+      Rep_Table.Table (T).Expr := Expr;
+      Rep_Table.Table (T).Op1  := Op1;
+      Rep_Table.Table (T).Op2  := Op2;
+      Rep_Table.Table (T).Op3  := Op3;
+
+      return UI_From_Int (-T);
+   end Create_Node;
+
+   ---------------------------
+   -- Get_Dynamic_SO_Entity --
+   ---------------------------
+
+   function Get_Dynamic_SO_Entity
+     (U    : Dynamic_SO_Ref)
+      return Entity_Id
+   is
+   begin
+      return Dynamic_SO_Entity_Table.Table (-UI_To_Int (U));
+   end Get_Dynamic_SO_Entity;
+
+   -----------------------
+   -- Is_Dynamic_SO_Ref --
+   -----------------------
+
+   function Is_Dynamic_SO_Ref (U : SO_Ref) return Boolean is
+   begin
+      return U < Uint_0;
+   end Is_Dynamic_SO_Ref;
+
+   ----------------------
+   -- Is_Static_SO_Ref --
+   ----------------------
+
+   function Is_Static_SO_Ref (U : SO_Ref) return Boolean is
+   begin
+      return U >= Uint_0;
+   end Is_Static_SO_Ref;
+
+   ---------
+   -- lgx --
+   ---------
+
+   procedure lgx (U : Node_Ref_Or_Val) is
+   begin
+      List_GCC_Expression (U);
+      Write_Eol;
+   end lgx;
+
+   ----------------------
+   -- List_Array_Info --
+   ----------------------
+
+   procedure List_Array_Info (Ent : Entity_Id) is
+   begin
+      List_Type_Info (Ent);
+
+      Write_Str ("for ");
+      List_Name (Ent);
+      Write_Str ("'Component_Size use ");
+      Write_Val (Component_Size (Ent));
+      Write_Line (";");
+   end List_Array_Info;
+
+   -------------------
+   -- List_Entities --
+   -------------------
+
+   procedure List_Entities (Ent : Entity_Id) is
+      E : Entity_Id;
+
+   begin
+      if Present (Ent) then
+         E := First_Entity (Ent);
+         while Present (E) loop
+            if Comes_From_Source (E) or else Debug_Flag_AA then
+
+               if Is_Record_Type (E) then
+                  List_Record_Info (E);
+
+               elsif Is_Array_Type (E) then
+                  List_Array_Info (E);
+
+               elsif List_Representation_Info >= 2 then
+
+                  if Is_Type (E) then
+                     List_Type_Info (E);
+
+                  elsif Ekind (E) = E_Variable
+                          or else
+                        Ekind (E) = E_Constant
+                          or else
+                        Ekind (E) = E_Loop_Parameter
+                          or else
+                        Is_Formal (E)
+                  then
+                     List_Object_Info (E);
+                  end if;
+               end if;
+
+               --  Recurse over nested package, but not if they are
+               --  package renamings (in particular renamings of the
+               --  enclosing package, as for some Java bindings and
+               --  for generic instances).
+
+               if (Ekind (E) = E_Package
+                         and then No (Renamed_Object (E)))
+                       or else
+                     Ekind (E) = E_Protected_Type
+                       or else
+                     Ekind (E) = E_Task_Type
+                       or else
+                     Ekind (E) = E_Subprogram_Body
+                       or else
+                     Ekind (E) = E_Package_Body
+                       or else
+                     Ekind (E) = E_Task_Body
+                       or else
+                     Ekind (E) = E_Protected_Body
+               then
+                  List_Entities (E);
+               end if;
+            end if;
+
+            E := Next_Entity (E);
+         end loop;
+      end if;
+   end List_Entities;
+
+   -------------------------
+   -- List_GCC_Expression --
+   -------------------------
+
+   procedure List_GCC_Expression (U : Node_Ref_Or_Val) is
+
+      procedure P (Val : Node_Ref_Or_Val);
+      --  Internal recursive procedure to print expression
+
+      procedure P (Val : Node_Ref_Or_Val) is
+      begin
+         if Val >= 0 then
+            UI_Write (Val, Decimal);
+
+         else
+            declare
+               Node : Exp_Node renames Rep_Table.Table (-UI_To_Int (Val));
+
+               procedure Binop (S : String);
+               --  Output text for binary operator with S being operator name
+
+               procedure Binop (S : String) is
+               begin
+                  Write_Char ('(');
+                  P (Node.Op1);
+                  Write_Str (S);
+                  P (Node.Op2);
+                  Write_Char (')');
+               end Binop;
+
+            --  Start of processing for P
+
+            begin
+               case Node.Expr is
+                  when Cond_Expr =>
+                     Write_Str ("(if ");
+                     P (Node.Op1);
+                     Write_Str (" then ");
+                     P (Node.Op2);
+                     Write_Str (" else ");
+                     P (Node.Op3);
+                     Write_Str (" end)");
+
+                  when Plus_Expr =>
+                     Binop (" + ");
+
+                  when Minus_Expr =>
+                     Binop (" - ");
+
+                  when Mult_Expr =>
+                     Binop (" * ");
+
+                  when Trunc_Div_Expr =>
+                     Binop (" /t ");
+
+                  when Ceil_Div_Expr =>
+                     Binop (" /c ");
+
+                  when Floor_Div_Expr =>
+                     Binop (" /f ");
+
+                  when Trunc_Mod_Expr =>
+                     Binop (" modt ");
+
+                  when Floor_Mod_Expr =>
+                     Binop (" modf ");
+
+                  when Ceil_Mod_Expr =>
+                     Binop (" modc ");
+
+                  when Exact_Div_Expr =>
+                     Binop (" /e ");
+
+                  when Negate_Expr =>
+                     Write_Char ('-');
+                     P (Node.Op1);
+
+                  when Min_Expr =>
+                     Binop (" min ");
+
+                  when Max_Expr =>
+                     Binop (" max ");
+
+                  when Abs_Expr =>
+                     Write_Str ("abs ");
+                     P (Node.Op1);
+
+                  when Truth_Andif_Expr =>
+                     Binop (" and if ");
+
+                  when Truth_Orif_Expr =>
+                     Binop (" or if ");
+
+                  when Truth_And_Expr =>
+                     Binop (" and ");
+
+                  when Truth_Or_Expr =>
+                     Binop (" or ");
+
+                  when Truth_Xor_Expr =>
+                     Binop (" xor ");
+
+                  when Truth_Not_Expr =>
+                     Write_Str ("not ");
+                     P (Node.Op1);
+
+                  when Lt_Expr =>
+                     Binop (" < ");
+
+                  when Le_Expr =>
+                     Binop (" <= ");
+
+                  when Gt_Expr =>
+                     Binop (" > ");
+
+                  when Ge_Expr =>
+                     Binop (" >= ");
+
+                  when Eq_Expr =>
+                     Binop (" == ");
+
+                  when Ne_Expr =>
+                     Binop (" != ");
+
+                  when Discrim_Val =>
+                     Write_Char ('#');
+                     UI_Write (Node.Op1);
+
+               end case;
+            end;
+         end if;
+      end P;
+
+   --  Start of processing for List_GCC_Expression
+
+   begin
+      if U = No_Uint then
+         Write_Line ("??");
+      else
+         P (U);
+      end if;
+   end List_GCC_Expression;
+
+   ---------------
+   -- List_Name --
+   ---------------
+
+   procedure List_Name (Ent : Entity_Id) is
+   begin
+      if not Is_Compilation_Unit (Scope (Ent)) then
+         List_Name (Scope (Ent));
+         Write_Char ('.');
+      end if;
+
+      Get_Unqualified_Decoded_Name_String (Chars (Ent));
+      Set_Casing (Unit_Casing);
+      Write_Str (Name_Buffer (1 .. Name_Len));
+   end List_Name;
+
+   ---------------------
+   -- List_Object_Info --
+   ---------------------
+
+   procedure List_Object_Info (Ent : Entity_Id) is
+   begin
+      Write_Eol;
+
+      if Known_Esize (Ent) then
+         Write_Str ("for ");
+         List_Name (Ent);
+         Write_Str ("'Size use ");
+         Write_Val (Esize (Ent));
+         Write_Line (";");
+      end if;
+
+      if Known_Alignment (Ent) then
+         Write_Str ("for ");
+         List_Name (Ent);
+         Write_Str ("'Alignment use ");
+         Write_Val (Alignment (Ent));
+         Write_Line (";");
+      end if;
+   end List_Object_Info;
+
+   ----------------------
+   -- List_Record_Info --
+   ----------------------
+
+   procedure List_Record_Info (Ent : Entity_Id) is
+      Comp  : Entity_Id;
+      Esiz  : Uint;
+      Cfbit : Uint;
+      Sunit : Uint;
+
+      Max_Name_Length : Natural;
+      Max_Suni_Length : Natural;
+
+   begin
+      List_Type_Info (Ent);
+
+      Write_Str ("for ");
+      List_Name (Ent);
+      Write_Line (" use record");
+
+      --  First loop finds out max line length and max starting position
+      --  length, for the purpose of lining things up nicely.
+
+      Max_Name_Length := 0;
+      Max_Suni_Length   := 0;
+
+      Comp := First_Entity (Ent);
+      while Present (Comp) loop
+         if Ekind (Comp) = E_Component
+           or else Ekind (Comp) = E_Discriminant
+         then
+            Get_Decoded_Name_String (Chars (Comp));
+            Max_Name_Length := Natural'Max (Max_Name_Length, Name_Len);
+
+            Cfbit := Component_Bit_Offset (Comp);
+
+            if Rep_Not_Constant (Cfbit) then
+               UI_Image_Length := 2;
+
+            else
+               --  Complete annotation in case not done
+
+               Set_Normalized_Position (Comp, Cfbit / SSU);
+               Set_Normalized_First_Bit (Comp, Cfbit mod SSU);
+
+               Esiz  := Esize (Comp);
+               Sunit := Cfbit / SSU;
+               UI_Image (Sunit);
+            end if;
+
+            if Unknown_Normalized_First_Bit (Comp) then
+               Set_Normalized_First_Bit (Comp, Uint_0);
+            end if;
+
+            Max_Suni_Length :=
+              Natural'Max (Max_Suni_Length, UI_Image_Length);
+         end if;
+
+         Comp := Next_Entity (Comp);
+      end loop;
+
+      --  Second loop does actual output based on those values
+
+      Comp := First_Entity (Ent);
+      while Present (Comp) loop
+         if Ekind (Comp) = E_Component
+           or else Ekind (Comp) = E_Discriminant
+         then
+            declare
+               Esiz : constant Uint := Esize (Comp);
+               Bofs : constant Uint := Component_Bit_Offset (Comp);
+               Npos : constant Uint := Normalized_Position (Comp);
+               Fbit : constant Uint := Normalized_First_Bit (Comp);
+               Lbit : Uint;
+
+            begin
+               Write_Str ("   ");
+               Get_Decoded_Name_String (Chars (Comp));
+               Set_Casing (Unit_Casing);
+               Write_Str (Name_Buffer (1 .. Name_Len));
+
+               for J in 1 .. Max_Name_Length - Name_Len loop
+                  Write_Char (' ');
+               end loop;
+
+               Write_Str (" at ");
+
+               if Known_Static_Normalized_Position (Comp) then
+                  UI_Image (Npos);
+                  Spaces (Max_Suni_Length - UI_Image_Length);
+                  Write_Str (UI_Image_Buffer (1 .. UI_Image_Length));
+
+               elsif Known_Component_Bit_Offset (Comp)
+                 and then List_Representation_Info = 3
+               then
+                  Spaces (Max_Suni_Length - 2);
+                  Write_Val (Bofs, Paren => True);
+                  Write_Str (" / 8");
+
+               elsif Known_Normalized_Position (Comp)
+                 and then List_Representation_Info = 3
+               then
+                  Spaces (Max_Suni_Length - 2);
+                  Write_Val (Npos);
+
+               else
+                  Write_Str ("??");
+               end if;
+
+               Write_Str (" range  ");
+               UI_Write (Fbit);
+               Write_Str (" .. ");
+
+               if not Is_Dynamic_SO_Ref (Esize (Comp)) then
+                  Lbit := Fbit + Esiz - 1;
+
+                  if Lbit < 10 then
+                     Write_Char (' ');
+                  end if;
+
+                  UI_Write (Lbit);
+
+               elsif List_Representation_Info < 3 then
+                  Write_Str ("??");
+
+               else -- List_Representation >= 3
+
+                  Write_Val (Esiz, Paren => True);
+
+                  --  If in front end layout mode, then dynamic size is
+                  --  stored in storage units, so renormalize for output
+
+                  if not Back_End_Layout then
+                     Write_Str (" * ");
+                     Write_Int (SSU);
+                  end if;
+
+                  --  Add appropriate first bit offset
+
+                  if Fbit = 0 then
+                     Write_Str (" - 1");
+
+                  elsif Fbit = 1 then
+                     null;
+
+                  else
+                     Write_Str (" + ");
+                     Write_Int (UI_To_Int (Fbit) - 1);
+                  end if;
+               end if;
+
+               Write_Line (";");
+            end;
+         end if;
+
+         Comp := Next_Entity (Comp);
+      end loop;
+
+      Write_Line ("end record;");
+   end List_Record_Info;
+
+   -------------------
+   -- List_Rep_Info --
+   -------------------
+
+   procedure List_Rep_Info is
+      Col : Nat;
+
+   begin
+      for U in Main_Unit .. Last_Unit loop
+         if In_Extended_Main_Source_Unit (Cunit_Entity (U)) then
+            Unit_Casing := Identifier_Casing (Source_Index (U));
+            Write_Eol;
+            Write_Str ("Representation information for unit ");
+            Write_Unit_Name (Unit_Name (U));
+            Col := Column;
+            Write_Eol;
+
+            for J in 1 .. Col - 1 loop
+               Write_Char ('-');
+            end loop;
+
+            Write_Eol;
+            List_Entities (Cunit_Entity (U));
+         end if;
+      end loop;
+   end List_Rep_Info;
+
+   --------------------
+   -- List_Type_Info --
+   --------------------
+
+   procedure List_Type_Info (Ent : Entity_Id) is
+   begin
+      Write_Eol;
+
+      --  If Esize and RM_Size are the same and known, list as Size. This
+      --  is a common case, which we may as well list in simple form.
+
+      if Esize (Ent) = RM_Size (Ent) then
+         if Known_Esize (Ent) then
+            Write_Str ("for ");
+            List_Name (Ent);
+            Write_Str ("'Size use ");
+            Write_Val (Esize (Ent));
+            Write_Line (";");
+         end if;
+
+      --  For now, temporary case, to be removed when gigi properly back
+      --  annotates RM_Size, if RM_Size is not set, then list Esize as
+      --  Size. This avoids odd Object_Size output till we fix things???
+
+      elsif Unknown_RM_Size (Ent) then
+         if Known_Esize (Ent) then
+            Write_Str ("for ");
+            List_Name (Ent);
+            Write_Str ("'Size use ");
+            Write_Val (Esize (Ent));
+            Write_Line (";");
+         end if;
+
+      --  Otherwise list size values separately if they are set
+
+      else
+         if Known_Esize (Ent) then
+            Write_Str ("for ");
+            List_Name (Ent);
+            Write_Str ("'Object_Size use ");
+            Write_Val (Esize (Ent));
+            Write_Line (";");
+         end if;
+
+         --  Note on following check: The RM_Size of a discrete type can
+         --  legitimately be set to zero, so a special check is needed.
+
+         if Known_RM_Size (Ent) or else Is_Discrete_Type (Ent) then
+            Write_Str ("for ");
+            List_Name (Ent);
+            Write_Str ("'Value_Size use ");
+            Write_Val (RM_Size (Ent));
+            Write_Line (";");
+         end if;
+      end if;
+
+      if Known_Alignment (Ent) then
+         Write_Str ("for ");
+         List_Name (Ent);
+         Write_Str ("'Alignment use ");
+         Write_Val (Alignment (Ent));
+         Write_Line (";");
+      end if;
+   end List_Type_Info;
+
+   ----------------------
+   -- Rep_Not_Constant --
+   ----------------------
+
+   function Rep_Not_Constant (Val : Node_Ref_Or_Val) return Boolean is
+   begin
+      if Val = No_Uint or else Val < 0 then
+         return True;
+      else
+         return False;
+      end if;
+   end Rep_Not_Constant;
+
+   ---------------
+   -- Rep_Value --
+   ---------------
+
+   function Rep_Value
+     (Val  : Node_Ref_Or_Val;
+      D    : Discrim_List)
+      return Uint
+   is
+      function B (Val : Boolean) return Uint;
+      --  Returns Uint_0 for False, Uint_1 for True
+
+      function T (Val : Node_Ref_Or_Val) return Boolean;
+      --  Returns True for 0, False for any non-zero (i.e. True)
+
+      function V (Val : Node_Ref_Or_Val) return Uint;
+      --  Internal recursive routine to evaluate tree
+
+      -------
+      -- B --
+      -------
+
+      function B (Val : Boolean) return Uint is
+      begin
+         if Val then
+            return Uint_1;
+         else
+            return Uint_0;
+         end if;
+      end B;
+
+      -------
+      -- T --
+      -------
+
+      function T (Val : Node_Ref_Or_Val) return Boolean is
+      begin
+         if V (Val) = 0 then
+            return False;
+         else
+            return True;
+         end if;
+      end T;
+
+      -------
+      -- V --
+      -------
+
+      function V (Val : Node_Ref_Or_Val) return Uint is
+         L, R, Q : Uint;
+
+      begin
+         if Val >= 0 then
+            return Val;
+
+         else
+            declare
+               Node : Exp_Node renames Rep_Table.Table (-UI_To_Int (Val));
+
+            begin
+               case Node.Expr is
+                  when Cond_Expr =>
+                     if T (Node.Op1) then
+                        return V (Node.Op2);
+                     else
+                        return V (Node.Op3);
+                     end if;
+
+                  when Plus_Expr =>
+                     return V (Node.Op1) + V (Node.Op2);
+
+                  when Minus_Expr =>
+                     return V (Node.Op1) - V (Node.Op2);
+
+                  when Mult_Expr =>
+                     return V (Node.Op1) * V (Node.Op2);
+
+                  when Trunc_Div_Expr =>
+                     return V (Node.Op1) / V (Node.Op2);
+
+                  when Ceil_Div_Expr =>
+                     return
+                       UR_Ceiling
+                         (V (Node.Op1) / UR_From_Uint (V (Node.Op2)));
+
+                  when Floor_Div_Expr =>
+                     return
+                       UR_Floor
+                         (V (Node.Op1) / UR_From_Uint (V (Node.Op2)));
+
+                  when Trunc_Mod_Expr =>
+                     return V (Node.Op1) rem V (Node.Op2);
+
+                  when Floor_Mod_Expr =>
+                     return V (Node.Op1) mod V (Node.Op2);
+
+                  when Ceil_Mod_Expr =>
+                     L := V (Node.Op1);
+                     R := V (Node.Op2);
+                     Q := UR_Ceiling (L / UR_From_Uint (R));
+                     return L - R * Q;
+
+                  when Exact_Div_Expr =>
+                     return V (Node.Op1) / V (Node.Op2);
+
+                  when Negate_Expr =>
+                     return -V (Node.Op1);
+
+                  when Min_Expr =>
+                     return UI_Min (V (Node.Op1), V (Node.Op2));
+
+                  when Max_Expr =>
+                     return UI_Max (V (Node.Op1), V (Node.Op2));
+
+                  when Abs_Expr =>
+                     return UI_Abs (V (Node.Op1));
+
+                  when Truth_Andif_Expr =>
+                     return B (T (Node.Op1) and then T (Node.Op2));
+
+                  when Truth_Orif_Expr =>
+                     return B (T (Node.Op1) or else T (Node.Op2));
+
+                  when Truth_And_Expr =>
+                     return B (T (Node.Op1) and T (Node.Op2));
+
+                  when Truth_Or_Expr =>
+                     return B (T (Node.Op1) or T (Node.Op2));
+
+                  when Truth_Xor_Expr =>
+                     return B (T (Node.Op1) xor T (Node.Op2));
+
+                  when Truth_Not_Expr =>
+                     return B (not T (Node.Op1));
+
+                  when Lt_Expr =>
+                     return B (V (Node.Op1) < V (Node.Op2));
+
+                  when Le_Expr =>
+                     return B (V (Node.Op1) <= V (Node.Op2));
+
+                  when Gt_Expr =>
+                     return B (V (Node.Op1) > V (Node.Op2));
+
+                  when Ge_Expr =>
+                     return B (V (Node.Op1) >= V (Node.Op2));
+
+                  when Eq_Expr =>
+                     return B (V (Node.Op1) = V (Node.Op2));
+
+                  when Ne_Expr =>
+                     return B (V (Node.Op1) /= V (Node.Op2));
+
+                  when Discrim_Val =>
+                     declare
+                        Sub : constant Int := UI_To_Int (Node.Op1);
+
+                     begin
+                        pragma Assert (Sub in D'Range);
+                        return D (Sub);
+                     end;
+
+               end case;
+            end;
+         end if;
+      end V;
+
+   --  Start of processing for Rep_Value
+
+   begin
+      if Val = No_Uint then
+         return No_Uint;
+
+      else
+         return V (Val);
+      end if;
+   end Rep_Value;
+
+   ------------
+   -- Spaces --
+   ------------
+
+   procedure Spaces (N : Natural) is
+   begin
+      for J in 1 .. N loop
+         Write_Char (' ');
+      end loop;
+   end Spaces;
+
+   ---------------
+   -- Tree_Read --
+   ---------------
+
+   procedure Tree_Read is
+   begin
+      Rep_Table.Tree_Read;
+   end Tree_Read;
+
+   ----------------
+   -- Tree_Write --
+   ----------------
+
+   procedure Tree_Write is
+   begin
+      Rep_Table.Tree_Write;
+   end Tree_Write;
+
+   ---------------
+   -- Write_Val --
+   ---------------
+
+   procedure Write_Val (Val : Node_Ref_Or_Val; Paren : Boolean := False) is
+   begin
+      if Rep_Not_Constant (Val) then
+         if List_Representation_Info < 3 then
+            Write_Str ("??");
+         else
+            if Back_End_Layout then
+               Write_Char (' ');
+               List_GCC_Expression (Val);
+               Write_Char (' ');
+            else
+               Write_Name_Decoded (Chars (Get_Dynamic_SO_Entity (Val)));
+            end if;
+         end if;
+
+      else
+         UI_Write (Val);
+      end if;
+   end Write_Val;
+
+end Repinfo;
diff --git a/gcc/ada/repinfo.ads b/gcc/ada/repinfo.ads
new file mode 100644 (file)
index 0000000..0b41ba0
--- /dev/null
@@ -0,0 +1,320 @@
+------------------------------------------------------------------------------
+--                                                                          --
+--                         GNAT COMPILER COMPONENTS                         --
+--                                                                          --
+--                              R E P I N F O                               --
+--                                                                          --
+--                                 S p e c                                  --
+--                                                                          --
+--                            $Revision: 1.20 $
+--                                                                          --
+--          Copyright (C) 1999-2001 Free Software Foundation, Inc.          --
+--                                                                          --
+-- GNAT is free software;  you can  redistribute it  and/or modify it under --
+-- terms of the  GNU General Public License as published  by the Free Soft- --
+-- ware  Foundation;  either version 2,  or (at your option) any later ver- --
+-- sion.  GNAT is distributed in the hope that it will be useful, but WITH- --
+-- OUT 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  distributed with GNAT;  see file COPYING.  If not, write --
+-- to  the Free Software Foundation,  59 Temple Place - Suite 330,  Boston, --
+-- MA 02111-1307, USA.                                                      --
+--                                                                          --
+-- As a special exception,  if other files  instantiate  generics from this --
+-- unit, or you link  this unit with other files  to produce an executable, --
+-- this  unit  does not  by itself cause  the resulting  executable  to  be --
+-- covered  by the  GNU  General  Public  License.  This exception does not --
+-- however invalidate  any other reasons why  the executable file  might be --
+-- covered by the  GNU Public License.                                      --
+--                                                                          --
+-- GNAT was originally developed  by the GNAT team at  New York University. --
+-- It is now maintained by Ada Core Technologies Inc (http://www.gnat.com). --
+--                                                                          --
+------------------------------------------------------------------------------
+
+--  This package contains the routines to handle back annotation of the
+--  tree to fill in representation information, and also the routine used
+--  by -gnatR to print this information. This unit is used both in the
+--  compiler and in ASIS (it is used in ASIS as part of the implementation
+--  of the data decomposition annex.
+
+with Types; use Types;
+with Uintp; use Uintp;
+
+package Repinfo is
+
+   --------------------------------
+   -- Representation Information --
+   --------------------------------
+
+   --  The representation information of interest here is size and
+   --  component information for arrays and records. For primitive
+   --  types, the front end computes the Esize and RM_Size fields of
+   --  the corresponding entities as constant non-negative integers,
+   --  and the Uint values are stored directly in these fields.
+
+   --  For composite types, there are three cases:
+
+   --    1. In some cases the front end knows the values statically,
+   --       for example in the ase where representation clauses or
+   --       pragmas specify the values.
+
+   --    2. If Backend_Layout is True, then the backend is responsible
+   --       for layout of all types and objects not laid out by the
+   --       front end. This includes all dynamic values, and also
+   --       static values (e.g. record sizes) when not set by the
+   --       front end.
+
+   --    3. If Backend_Layout is False, then the front end lays out
+   --       all data, according to target dependent size and alignment
+   --       information, creating dynamic inlinable functions where
+   --       needed in the case of sizes not known till runtime.
+
+   -----------------------------
+   -- Back-Annotation by Gigi --
+   -----------------------------
+
+   --  The following interface is used by gigi if Backend_Layout is True.
+
+   --  As part of the processing in gigi, the types are laid out and
+   --  appropriate values computed for the sizes and component positions
+   --  and sizes of records and arrays.
+
+   --  The back-annotation circuit in gigi is responsible for updating the
+   --  relevant fields in the tree to reflect these computations, as follows:
+
+   --    For E_Array_Type entities, the Component_Size field
+
+   --    For all record and array types and subtypes, the Esize field,
+   --    which contains the Size (more accurately the Object_SIze) value
+   --    for the type or subtype.
+
+   --    For E_Component and E_Distriminant entities, the Esize (size
+   --    of component) and Component_Bit_Offset fields. Note that gigi
+   --    does not (yet ???) back annotate Normalized_Position/First_Bit.
+
+   --  There are three cases to consider:
+
+   --    1. The value is constant. In this case, the back annotation works
+   --       by simply storing the non-negative universal integer value in
+   --       the appropriate field corresponding to this constant size.
+
+   --    2. The value depends on variables other than discriminants of the
+   --       current record. In this case, the value is not known, even if
+   --       the complete data of the record is available, and gigi marks
+   --       this situation by storing the special value No_Uint.
+
+   --    3. The value depends on the discriminant values for the current
+   --       record. In this case, gigi back annotates the field with a
+   --       representation of the expression for computing the value in
+   --       terms of the discriminants. A negative Uint value is used to
+   --       represent the value of such an expression, as explained in
+   --       the following section.
+
+   --  GCC expressions are represented with a Uint value that is negative.
+   --  See the body of this package for details on the representation used.
+
+   --  One other case in which gigi back annotates GCC expressions is in
+   --  the Present_Expr field of an N_Variant node. This expression which
+   --  will always depend on discriminants, and hence always be represented
+   --  as a negative Uint value, provides an expression which, when evaluated
+   --  with a given set of discriminant values, indicates whether the variant
+   --  is present for that set of values (result is True, i.e. non-zero) or
+   --  not present (result is False, i.e. zero).
+
+   subtype Node_Ref is Uint;
+   --  Subtype used for negative Uint values used to represent nodes
+
+   subtype Node_Ref_Or_Val is Uint;
+   --  Subtype used for values that can either be a Node_Ref (negative)
+   --  or a value (non-negative)
+
+   type TCode is range 0 .. 27;
+   --  Type used on Ada side to represent DEFTREECODE values defined in
+   --  tree.def. Only a subset of these tree codes can actually appear.
+   --  The names are the names from tree.def in Ada casing.
+
+   --  name                             code   description           operands
+
+   Cond_Expr        : constant TCode :=  1; -- conditional              3
+   Plus_Expr        : constant TCode :=  2; -- addition                 2
+   Minus_Expr       : constant TCode :=  3; -- subtraction              2
+   Mult_Expr        : constant TCode :=  4; -- multiplication           2
+   Trunc_Div_Expr   : constant TCode :=  5; -- truncating division      2
+   Ceil_Div_Expr    : constant TCode :=  6; -- division rounding up     2
+   Floor_Div_Expr   : constant TCode :=  7; -- division rounding down   2
+   Trunc_Mod_Expr   : constant TCode :=  8; -- mod for trunc_div        2
+   Ceil_Mod_Expr    : constant TCode :=  9; -- mod for ceil_div         2
+   Floor_Mod_Expr   : constant TCode := 10; -- mod for floor_div        2
+   Exact_Div_Expr   : constant TCode := 11; -- exact div                2
+   Negate_Expr      : constant TCode := 12; -- negation                 1
+   Min_Expr         : constant TCode := 13; -- minimum                  2
+   Max_Expr         : constant TCode := 14; -- maximum                  2
+   Abs_Expr         : constant TCode := 15; -- absolute value           1
+   Truth_Andif_Expr : constant TCode := 16; -- Boolean and then         2
+   Truth_Orif_Expr  : constant TCode := 17; -- Boolean or else          2
+   Truth_And_Expr   : constant TCode := 18; -- Boolean and              2
+   Truth_Or_Expr    : constant TCode := 19; -- Boolean or               2
+   Truth_Xor_Expr   : constant TCode := 20; -- Boolean xor              2
+   Truth_Not_Expr   : constant TCode := 21; -- Boolean not              1
+   Lt_Expr          : constant TCode := 22; -- comparision <            2
+   Le_Expr          : constant TCode := 23; -- comparision <=           2
+   Gt_Expr          : constant TCode := 24; -- comparision >            2
+   Ge_Expr          : constant TCode := 25; -- comparision >=           2
+   Eq_Expr          : constant TCode := 26; -- comparision =            2
+   Ne_Expr          : constant TCode := 27; -- comparision /=           2
+
+   --  The following entry is used to represent a discriminant value in
+   --  the tree. It has a special tree code that does not correspond
+   --  directly to a gcc node. The single operand is the number of the
+   --  discriminant in the record (1 = first discriminant).
+
+   Discrim_Val : constant TCode := 0;  -- discriminant value       1
+
+   ------------------------
+   -- The gigi Interface --
+   ------------------------
+
+   --  The following declarations are for use by gigi for back annotation
+
+   function Create_Node
+     (Expr  : TCode;
+      Op1   : Node_Ref_Or_Val;
+      Op2   : Node_Ref_Or_Val := No_Uint;
+      Op3   : Node_Ref_Or_Val := No_Uint)
+      return  Node_Ref;
+   --  Creates a node with using the tree code defined by Expr and from
+   --  1-3 operands as required (unused operands set as shown to No_Uint)
+   --  Note that this call can be used to create a discriminant reference
+   --  by using (Expr => Discrim_Val, Op1 => discriminant_number).
+
+   function Create_Discrim_Ref
+     (Discr : Entity_Id)
+      return  Node_Ref;
+   --  Creates a refrerence to the discriminant whose entity is Discr.
+
+   --------------------------------------------------------
+   -- Front-End Interface for Dynamic Size/Offset Values --
+   --------------------------------------------------------
+
+   --  If Backend_Layout is False, then the front-end deals with all
+   --  dynamic size and offset fields. There are two cases:
+
+   --    1. The value can be computed at the time of type freezing, and
+   --       is stored in a run-time constant. In this case, the field
+   --       contains a reference to this entity. In the case of sizes
+   --       the value stored is the size in storage units, since dynamic
+   --       sizes are always a multiple of storage units.
+
+   --    2. The size/offset depends on the value of discriminants at
+   --       run-time. In this case, the front end builds a function to
+   --       compute the value. This function has a single parameter
+   --       which is the discriminated record object in question. Any
+   --       references to discriminant values are simply references to
+   --       the appropriate discriminant in this single argument, and
+   --       to compute the required size/offset value at run time, the
+   --       code generator simply constructs a call to the function
+   --       with the appropriate argument. The size/offset field in
+   --       this case contains a reference to the function entity.
+   --       Note that as for case 1, if such a function is used to
+   --       return a size, then the size in storage units is returned,
+   --       not the size in bits.
+
+   --  The interface here allows these created entities to be referenced
+   --  using negative Unit values, so that they can be stored in the
+   --  appropriate size and offset fields in the tree.
+
+   --  In the case of components, if the location of the component is static,
+   --  then all four fields (Component_Bit_Offset, Normalized_Position, Esize,
+   --  and Normalized_First_Bit) are set to appropraite values. In the case of
+   --  a non-static component location, Component_Bit_Offset is not used and
+   --  is left set to Unknown. Normalized_Position and Normalized_First_Bit
+   --  are set appropriately.
+
+   subtype SO_Ref is Uint;
+   --  Type used to represent a Uint value that represents a static or
+   --  dynamic size/offset value (non-negative if static, negative if
+   --  the size value is dynamic).
+
+   subtype Dynamic_SO_Ref is Uint;
+   --  Type used to represent a negative Uint value used to store
+   --  a dynamic size/offset value.
+
+   function Is_Dynamic_SO_Ref (U : SO_Ref) return Boolean;
+   pragma Inline (Is_Dynamic_SO_Ref);
+   --  Given a SO_Ref (Uint) value, returns True iff the SO_Ref value
+   --  represents a dynamic Size/Offset value (i.e. it is negative).
+
+   function Is_Static_SO_Ref (U : SO_Ref) return Boolean;
+   pragma Inline (Is_Static_SO_Ref);
+   --  Given a SO_Ref (Uint) value, returns True iff the SO_Ref value
+   --  represents a static Size/Offset value (i.e. it is non-negative).
+
+   function Create_Dynamic_SO_Ref
+     (E    : Entity_Id)
+      return Dynamic_SO_Ref;
+   --  Given the Entity_Id for a constant (case 1), the Node_Id for an
+   --  expression (case 2), or the Entity_Id for a function (case 3),
+   --  this function returns a (negative) Uint value that can be used
+   --  to retrieve the entity or expression for later use.
+
+   function Get_Dynamic_SO_Entity
+     (U    : Dynamic_SO_Ref)
+      return Entity_Id;
+   --  Retrieve the Node_Id or Entity_Id stored by a previous call to
+   --  Create_Dynamic_SO_Ref. The approach is that the front end makes
+   --  the necessary Create_Dynamic_SO_Ref calls to associate the node
+   --  and entity id values and the back end makes Get_Dynamic_SO_Ref
+   --  calls to retrive them.
+
+   --------------------
+   -- ASIS_Interface --
+   --------------------
+
+   type Discrim_List is array (Pos range <>) of Uint;
+   --  Type used to represent list of discriminant values
+
+   function Rep_Value
+     (Val  : Node_Ref_Or_Val;
+      D    : Discrim_List)
+      return Uint;
+   --  Given the contents of a First_Bit_Position or Esize field containing
+   --  a node reference (i.e. a negative Uint value) and D, the list of
+   --  discriminant values, returns the interpreted value of this field.
+   --  For convenience, Rep_Value will take a non-negative Uint value
+   --  as an argument value, and return it unmodified. A No_Uint value is
+   --  also returned unmodified.
+
+   procedure Tree_Read;
+   --  Read in the value of the Rep_Table
+
+   ------------------------
+   -- Compiler Interface --
+   ------------------------
+
+   procedure List_Rep_Info;
+   --  Procedure to list representation information
+
+   procedure Tree_Write;
+   --  Write out the value of the Rep_Table
+
+   --------------------------
+   -- Debugging Procedures --
+   --------------------------
+
+   procedure List_GCC_Expression (U : Node_Ref_Or_Val);
+   --  Prints out given expression in symbolic form. Constants are listed
+   --  in decimal numeric form, Discriminants are listed with a # followed
+   --  by the discriminant number, and operators are output in appropriate
+   --  symbolic form No_Uint displays as two question marks. The output is
+   --  on a single line but has no line return after it. This procedure is
+   --  useful only if operating in backend layout mode.
+
+   procedure lgx (U : Node_Ref_Or_Val);
+   --  In backend layout mode, this is like List_GCC_Expression, but
+   --  includes a line return at the end. If operating in front end
+   --  layout mode, then the name of the entity for the size (either
+   --  a function of a variable) is listed followed by a line return.
+
+end Repinfo;
diff --git a/gcc/ada/repinfo.h b/gcc/ada/repinfo.h
new file mode 100644 (file)
index 0000000..305c818
--- /dev/null
@@ -0,0 +1,79 @@
+/****************************************************************************
+ *                                                                          *
+ *                         GNAT COMPILER COMPONENTS                         *
+ *                                                                          *
+ *                              R E P I N F O                               *
+ *                                                                          *
+ *                              C Header File                               *
+ *                                                                          *
+ *                             $Revision: 1.1 $
+ *                                                                          *
+ *          Copyright (C) 1999-2001 Free Software Foundation, Inc.          *
+ *                                                                          *
+ * GNAT is free software;  you can  redistribute it  and/or modify it under *
+ * terms of the  GNU General Public License as published  by the Free Soft- *
+ * ware  Foundation;  either version 2,  or (at your option) any later ver- *
+ * sion.  GNAT is distributed in the hope that it will be useful, but WITH- *
+ * OUT 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  distributed with GNAT;  see file COPYING.  If not, write *
+ * to  the Free Software Foundation,  59 Temple Place - Suite 330,  Boston, *
+ * MA 02111-1307, USA.                                                      *
+ *                                                                          *
+ * As a  special  exception,  if you  link  this file  with other  files to *
+ * produce an executable,  this file does not by itself cause the resulting *
+ * executable to be covered by the GNU General Public License. This except- *
+ * ion does not  however invalidate  any other reasons  why the  executable *
+ * file might be covered by the  GNU Public License.                        *
+ *                                                                          *
+ * GNAT was originally developed  by the GNAT team at  New York University. *
+ * It is now maintained by Ada Core Technologies Inc (http://www.gnat.com). *
+ *                                                                          *
+ ****************************************************************************/
+
+/* This file corresponds to the Ada file repinfo.ads.  */
+
+typedef Uint Node_Ref;
+typedef Uint Node_Ref_Or_Val;
+typedef char TCode;
+
+/* These are the values of TCcode that correspond to tree codes in tree.def,
+   except for the first, which is how we encode discriminants.  */
+
+#define Discrim_Val       0
+#define Cond_Expr         1
+#define Plus_Expr         2
+#define Minus_Expr        3
+#define Mult_Expr         4
+#define Trunc_Div_Expr    5
+#define Ceil_Div_Expr     6
+#define Floor_Div_Expr    7
+#define Trunc_Mod_Expr    8
+#define Ceil_Mod_Expr     9
+#define Floor_Mod_Expr   10
+#define Exact_Div_Expr   11
+#define Negate_Expr      12
+#define Min_Expr         13
+#define Max_Expr         14
+#define Abs_Expr         15
+#define Truth_Andif_Expr 16
+#define Truth_Orif_Expr  17
+#define Truth_And_Expr   18
+#define Truth_Or_Expr    19
+#define Truth_Xor_Expr   20
+#define Truth_Not_Expr   21
+#define Lt_Expr          22
+#define Le_Expr          23
+#define Gt_Expr          24
+#define Ge_Expr          25
+#define Eq_Expr          26
+#define Ne_Expr          27
+
+/* Creates a node using the tree code defined by Expr and from 1-3
+   operands as required (unused operands set as shown to No_Uint) Note
+   that this call can be used to create a discriminant reference by
+   using (Expr => Discrim_Val, Op1 => discriminant_number).  */
+#define Create_Node repinfo__create_node
+extern Node_Ref Create_Node    PARAMS((TCode, Node_Ref_Or_Val,
+                                       Node_Ref_Or_Val, Node_Ref_Or_Val));
diff --git a/gcc/ada/restrict.adb b/gcc/ada/restrict.adb
new file mode 100644 (file)
index 0000000..a284cd4
--- /dev/null
@@ -0,0 +1,458 @@
+------------------------------------------------------------------------------
+--                                                                          --
+--                         GNAT COMPILER COMPONENTS                         --
+--                                                                          --
+--                             R E S T R I C T                              --
+--                                                                          --
+--                                 B o d y                                  --
+--                                                                          --
+--                            $Revision: 1.37 $
+--                                                                          --
+--          Copyright (C) 1992-2001 Free Software Foundation, Inc.          --
+--                                                                          --
+-- GNAT is free software;  you can  redistribute it  and/or modify it under --
+-- terms of the  GNU General Public License as published  by the Free Soft- --
+-- ware  Foundation;  either version 2,  or (at your option) any later ver- --
+-- sion.  GNAT is distributed in the hope that it will be useful, but WITH- --
+-- OUT 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  distributed with GNAT;  see file COPYING.  If not, write --
+-- to  the Free Software Foundation,  59 Temple Place - Suite 330,  Boston, --
+-- MA 02111-1307, USA.                                                      --
+--                                                                          --
+-- GNAT was originally developed  by the GNAT team at  New York University. --
+-- It is now maintained by Ada Core Technologies Inc (http://www.gnat.com). --
+--                                                                          --
+------------------------------------------------------------------------------
+
+with Atree;    use Atree;
+with Casing;   use Casing;
+with Errout;   use Errout;
+with Exp_Util; use Exp_Util;
+with Fname;    use Fname;
+with Fname.UF; use Fname.UF;
+with Lib;      use Lib;
+with Namet;    use Namet;
+with Nmake;    use Nmake;
+with Opt;      use Opt;
+with Stand;    use Stand;
+with Uname;    use Uname;
+
+package body Restrict is
+
+   function Suppress_Restriction_Message (N : Node_Id) return Boolean;
+   --  N is the node for a possible restriction violation message, but
+   --  the message is to be suppressed if this is an internal file and
+   --  this file is not the main unit.
+
+   -------------------
+   -- Abort_Allowed --
+   -------------------
+
+   function Abort_Allowed return Boolean is
+   begin
+      return
+        Restrictions (No_Abort_Statements) = False
+          or else
+        Restriction_Parameters (Max_Asynchronous_Select_Nesting) /= 0;
+   end Abort_Allowed;
+
+   ------------------------------------
+   -- Check_Elaboration_Code_Allowed --
+   ------------------------------------
+
+   procedure Check_Elaboration_Code_Allowed (N : Node_Id) is
+   begin
+      --  Avoid calling Namet.Unlock/Lock except when there is an error.
+      --  Even in the error case it is a bit dubious, either gigi needs
+      --  the table locked or it does not! ???
+
+      if Restrictions (No_Elaboration_Code)
+        and then not Suppress_Restriction_Message (N)
+      then
+         Namet.Unlock;
+         Check_Restriction (No_Elaboration_Code, N);
+         Namet.Lock;
+      end if;
+   end Check_Elaboration_Code_Allowed;
+
+   ---------------------------
+   -- Check_Restricted_Unit --
+   ---------------------------
+
+   procedure Check_Restricted_Unit (U : Unit_Name_Type; N : Node_Id) is
+   begin
+      if Suppress_Restriction_Message (N) then
+         return;
+
+      elsif Is_Spec_Name (U) then
+         declare
+            Fnam : constant File_Name_Type :=
+                     Get_File_Name (U, Subunit => False);
+            R_Id : Restriction_Id;
+
+         begin
+            if not Is_Predefined_File_Name (Fnam) then
+               return;
+
+            --  Ada child unit spec, needs checking against list
+
+            else
+               --  Pad name to 8 characters with blanks
+
+               Get_Name_String (Fnam);
+               Name_Len := Name_Len - 4;
+
+               while Name_Len < 8 loop
+                  Name_Len := Name_Len + 1;
+                  Name_Buffer (Name_Len) := ' ';
+               end loop;
+
+               for J in Unit_Array'Range loop
+                  if Name_Len = 8
+                    and then Name_Buffer (1 .. 8) = Unit_Array (J).Filenm
+                  then
+                     R_Id := Unit_Array (J).Res_Id;
+                     Violations (R_Id) := True;
+
+                     if Restrictions (R_Id) then
+                        declare
+                           S : constant String := Restriction_Id'Image (R_Id);
+
+                        begin
+                           Error_Msg_Unit_1 := U;
+
+                           Error_Msg_N
+                             ("dependence on $ not allowed,", N);
+
+                           Name_Buffer (1 .. S'Last) := S;
+                           Name_Len := S'Length;
+                           Set_Casing (All_Lower_Case);
+                           Error_Msg_Name_1 := Name_Enter;
+                           Error_Msg_Sloc := Restrictions_Loc (R_Id);
+
+                           Error_Msg_N
+                             ("\violates pragma Restriction (%) #", N);
+                           return;
+                        end;
+                     end if;
+                  end if;
+               end loop;
+            end if;
+         end;
+      end if;
+   end Check_Restricted_Unit;
+
+   -----------------------
+   -- Check_Restriction --
+   -----------------------
+
+   --  Case of simple identifier (no parameter)
+
+   procedure Check_Restriction (R : Restriction_Id; N : Node_Id) is
+   begin
+      Violations (R) := True;
+
+      if Restrictions (R)
+        and then not Suppress_Restriction_Message (N)
+      then
+         declare
+            S : constant String := Restriction_Id'Image (R);
+
+         begin
+            Name_Buffer (1 .. S'Last) := S;
+            Name_Len := S'Length;
+            Set_Casing (All_Lower_Case);
+            Error_Msg_Name_1 := Name_Enter;
+            Error_Msg_Sloc := Restrictions_Loc (R);
+            Error_Msg_N ("violation of restriction %#", N);
+         end;
+      end if;
+   end Check_Restriction;
+
+   --  Case where a parameter is present (but no count)
+
+   procedure Check_Restriction
+     (R : Restriction_Parameter_Id;
+      N : Node_Id)
+   is
+   begin
+      if Restriction_Parameters (R) = Uint_0
+        and then not Suppress_Restriction_Message (N)
+      then
+         declare
+            Loc : constant Source_Ptr := Sloc (N);
+            S   : constant String :=
+                    Restriction_Parameter_Id'Image (R);
+
+         begin
+            Error_Msg_NE
+              ("& will be raised at run time?!", N, Standard_Storage_Error);
+            Name_Buffer (1 .. S'Last) := S;
+            Name_Len := S'Length;
+            Set_Casing (All_Lower_Case);
+            Error_Msg_Name_1 := Name_Enter;
+            Error_Msg_Sloc := Restriction_Parameters_Loc (R);
+            Error_Msg_N ("violation of restriction %?#!", N);
+
+            Insert_Action (N,
+              Make_Raise_Storage_Error (Loc));
+         end;
+      end if;
+   end Check_Restriction;
+
+   --  Case where a parameter is present, with a count
+
+   procedure Check_Restriction
+     (R : Restriction_Parameter_Id;
+      V : Uint;
+      N : Node_Id)
+   is
+   begin
+      if Restriction_Parameters (R) /= No_Uint
+        and then V > Restriction_Parameters (R)
+        and then not Suppress_Restriction_Message (N)
+      then
+         declare
+            S : constant String := Restriction_Parameter_Id'Image (R);
+
+         begin
+            Name_Buffer (1 .. S'Last) := S;
+            Name_Len := S'Length;
+            Set_Casing (All_Lower_Case);
+            Error_Msg_Name_1 := Name_Enter;
+            Error_Msg_Sloc := Restriction_Parameters_Loc (R);
+            Error_Msg_N ("maximum value exceeded for restriction %#", N);
+         end;
+      end if;
+   end Check_Restriction;
+
+   -------------------------------------------
+   -- Compilation_Unit_Restrictions_Restore --
+   -------------------------------------------
+
+   procedure Compilation_Unit_Restrictions_Restore
+     (R : Save_Compilation_Unit_Restrictions)
+   is
+   begin
+      for J in Compilation_Unit_Restrictions loop
+         Restrictions (J) := R (J);
+      end loop;
+   end Compilation_Unit_Restrictions_Restore;
+
+   ----------------------------------------
+   -- Compilation_Unit_Restrictions_Save --
+   ----------------------------------------
+
+   function Compilation_Unit_Restrictions_Save
+     return Save_Compilation_Unit_Restrictions
+   is
+      R : Save_Compilation_Unit_Restrictions;
+
+   begin
+      for J in Compilation_Unit_Restrictions loop
+         R (J) := Restrictions (J);
+         Restrictions (J) := False;
+      end loop;
+
+      return R;
+   end Compilation_Unit_Restrictions_Save;
+
+   ----------------------------------
+   -- Disallow_In_No_Run_Time_Mode --
+   ----------------------------------
+
+   procedure Disallow_In_No_Run_Time_Mode (Enode : Node_Id) is
+   begin
+      if No_Run_Time then
+         Error_Msg_N
+           ("this construct not allowed in No_Run_Time mode", Enode);
+      end if;
+   end Disallow_In_No_Run_Time_Mode;
+
+   ------------------------
+   -- Get_Restriction_Id --
+   ------------------------
+
+   function Get_Restriction_Id
+     (N    : Name_Id)
+      return Restriction_Id
+   is
+      J : Restriction_Id;
+
+   begin
+      Get_Name_String (N);
+      Set_Casing (All_Upper_Case);
+
+      J := Restriction_Id'First;
+      while J /= Not_A_Restriction_Id loop
+         declare
+            S : constant String := Restriction_Id'Image (J);
+
+         begin
+            exit when S = Name_Buffer (1 .. Name_Len);
+         end;
+
+         J := Restriction_Id'Succ (J);
+      end loop;
+
+      return J;
+   end Get_Restriction_Id;
+
+   ----------------------------------
+   -- Get_Restriction_Parameter_Id --
+   ----------------------------------
+
+   function Get_Restriction_Parameter_Id
+     (N    : Name_Id)
+      return Restriction_Parameter_Id
+   is
+      J : Restriction_Parameter_Id;
+
+   begin
+      Get_Name_String (N);
+      Set_Casing (All_Upper_Case);
+
+      J := Restriction_Parameter_Id'First;
+      while J /= Not_A_Restriction_Parameter_Id loop
+         declare
+            S : constant String := Restriction_Parameter_Id'Image (J);
+
+         begin
+            exit when S = Name_Buffer (1 .. Name_Len);
+         end;
+
+         J := Restriction_Parameter_Id'Succ (J);
+      end loop;
+
+      return J;
+   end Get_Restriction_Parameter_Id;
+
+   -------------------------------
+   -- No_Exception_Handlers_Set --
+   -------------------------------
+
+   function No_Exception_Handlers_Set return Boolean is
+   begin
+      return Restrictions (No_Exception_Handlers);
+   end No_Exception_Handlers_Set;
+
+   ------------------------
+   -- Restricted_Profile --
+   ------------------------
+
+   --  This implementation must be coordinated with Set_Restricted_Profile
+
+   function Restricted_Profile return Boolean is
+   begin
+      return     Restrictions (No_Abort_Statements)
+        and then Restrictions (No_Asynchronous_Control)
+        and then Restrictions (No_Entry_Queue)
+        and then Restrictions (No_Task_Hierarchy)
+        and then Restrictions (No_Task_Allocators)
+        and then Restrictions (No_Dynamic_Priorities)
+        and then Restrictions (No_Terminate_Alternatives)
+        and then Restrictions (No_Dynamic_Interrupts)
+        and then Restrictions (No_Protected_Type_Allocators)
+        and then Restrictions (No_Local_Protected_Objects)
+        and then Restrictions (No_Requeue)
+        and then Restrictions (No_Task_Attributes)
+        and then Restriction_Parameters (Max_Asynchronous_Select_Nesting) =  0
+        and then Restriction_Parameters (Max_Task_Entries)                =  0
+        and then Restriction_Parameters (Max_Protected_Entries)           <= 1
+        and then Restriction_Parameters (Max_Select_Alternatives)         =  0;
+   end Restricted_Profile;
+
+   --------------------------
+   -- Set_No_Run_Time_Mode --
+   --------------------------
+
+   procedure Set_No_Run_Time_Mode is
+   begin
+      No_Run_Time := True;
+      Restrictions (No_Exception_Handlers) := True;
+   end Set_No_Run_Time_Mode;
+
+   -------------------
+   -- Set_Ravenscar --
+   -------------------
+
+   procedure Set_Ravenscar is
+   begin
+      Set_Restricted_Profile;
+      Restrictions (Boolean_Entry_Barriers)       := True;
+      Restrictions (No_Select_Statements)         := True;
+      Restrictions (No_Calendar)                  := True;
+      Restrictions (Static_Storage_Size)          := True;
+      Restrictions (No_Entry_Queue)               := True;
+      Restrictions (No_Relative_Delay)            := True;
+      Restrictions (No_Task_Termination)          := True;
+      Restrictions (No_Implicit_Heap_Allocations) := True;
+   end Set_Ravenscar;
+
+   ----------------------------
+   -- Set_Restricted_Profile --
+   ----------------------------
+
+   --  This must be coordinated with Restricted_Profile
+
+   procedure Set_Restricted_Profile is
+   begin
+      Restrictions (No_Abort_Statements)          := True;
+      Restrictions (No_Asynchronous_Control)      := True;
+      Restrictions (No_Entry_Queue)               := True;
+      Restrictions (No_Task_Hierarchy)            := True;
+      Restrictions (No_Task_Allocators)           := True;
+      Restrictions (No_Dynamic_Priorities)        := True;
+      Restrictions (No_Terminate_Alternatives)    := True;
+      Restrictions (No_Dynamic_Interrupts)        := True;
+      Restrictions (No_Protected_Type_Allocators) := True;
+      Restrictions (No_Local_Protected_Objects)   := True;
+      Restrictions (No_Requeue)                   := True;
+      Restrictions (No_Task_Attributes)           := True;
+
+      Restriction_Parameters (Max_Asynchronous_Select_Nesting) :=  Uint_0;
+      Restriction_Parameters (Max_Task_Entries)                :=  Uint_0;
+      Restriction_Parameters (Max_Select_Alternatives)         :=  Uint_0;
+
+      if Restriction_Parameters (Max_Protected_Entries) /= Uint_0 then
+         Restriction_Parameters (Max_Protected_Entries) := Uint_1;
+      end if;
+   end Set_Restricted_Profile;
+
+   ----------------------------------
+   -- Suppress_Restriction_Message --
+   ----------------------------------
+
+   function Suppress_Restriction_Message (N : Node_Id) return Boolean is
+   begin
+      --  If main unit is library unit, then we will output message
+
+      if In_Extended_Main_Source_Unit (N) then
+         return False;
+
+      --  If loaded by rtsfind, then suppress message
+
+      elsif Sloc (N) <= No_Location then
+         return True;
+
+      --  Otherwise suppress message if internal file
+
+      else
+         return
+           Is_Internal_File_Name (Unit_File_Name (Get_Source_Unit (N)));
+      end if;
+   end Suppress_Restriction_Message;
+
+   ---------------------
+   -- Tasking_Allowed --
+   ---------------------
+
+   function Tasking_Allowed return Boolean is
+   begin
+      return
+        Restriction_Parameters (Max_Tasks) /= 0;
+   end Tasking_Allowed;
+
+end Restrict;
diff --git a/gcc/ada/restrict.ads b/gcc/ada/restrict.ads
new file mode 100644 (file)
index 0000000..426149e
--- /dev/null
@@ -0,0 +1,253 @@
+------------------------------------------------------------------------------
+--                                                                          --
+--                         GNAT COMPILER COMPONENTS                         --
+--                                                                          --
+--                             R E S T R I C T                              --
+--                                                                          --
+--                                 S p e c                                  --
+--                                                                          --
+--                            $Revision: 1.27 $
+--                                                                          --
+--          Copyright (C) 1992-2001 Free Software Foundation, Inc.          --
+--                                                                          --
+-- GNAT is free software;  you can  redistribute it  and/or modify it under --
+-- terms of the  GNU General Public License as published  by the Free Soft- --
+-- ware  Foundation;  either version 2,  or (at your option) any later ver- --
+-- sion.  GNAT is distributed in the hope that it will be useful, but WITH- --
+-- OUT 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  distributed with GNAT;  see file COPYING.  If not, write --
+-- to  the Free Software Foundation,  59 Temple Place - Suite 330,  Boston, --
+-- MA 02111-1307, USA.                                                      --
+--                                                                          --
+-- GNAT was originally developed  by the GNAT team at  New York University. --
+-- It is now maintained by Ada Core Technologies Inc (http://www.gnat.com). --
+--                                                                          --
+------------------------------------------------------------------------------
+
+--  This package deals with the implementation of the Restrictions pragma
+
+with Rident;
+with Types;  use Types;
+with Uintp;  use Uintp;
+
+package Restrict is
+
+   type Restriction_Id is new Rident.Restriction_Id;
+   --  The type Restriction_Id defines the set of restriction identifiers,
+   --  which take no parameter (i.e. they are either present or not present).
+   --  The actual definition is in the separate package Rident, so that it
+   --  can easily be accessed by the binder without dragging in lots of stuff.
+
+   subtype Partition_Restrictions is
+     Restriction_Id range
+       Restriction_Id (Rident.Partition_Restrictions'First) ..
+       Restriction_Id (Rident.Partition_Restrictions'Last);
+   --  Range of restriction identifiers that are checked by the binder
+
+   subtype Compilation_Unit_Restrictions is
+     Restriction_Id range
+       Restriction_Id (Rident.Compilation_Unit_Restrictions'First) ..
+       Restriction_Id (Rident.Compilation_Unit_Restrictions'Last);
+   --  Range of restriction identifiers not checked by binder
+
+   type Restriction_Parameter_Id is new Rident.Restriction_Parameter_Id;
+   --  The type Restriction_Parameter_Id records cases where a parameter is
+   --  present in the corresponding pragma. These cases are not checked for
+   --  consistency by the binder. The actual definition is in the separate
+   --  package Rident for consistency.
+
+   type Restrictions_Flags is array (Restriction_Id) of Boolean;
+   --  Type used for arrays indexed by Restriction_Id.
+
+   Restrictions : Restrictions_Flags := (others => False);
+   --  Corresponding entry is False if restriction is not active, and
+   --  True if the restriction is active, i.e. if a pragma Restrictions
+   --  has been seen anywhere. Note that we are happy to pick up any
+   --  restrictions pragmas in with'ed units, since we are required to
+   --  be consistent at link time, and we might as well find the error
+   --  at compile time. Clients must NOT use this array for checking to
+   --  see if a restriction is violated, instead it is required that the
+   --  Check_Restrictions subprograms be used for this purpose. The only
+   --  legitimate direct use of this array is when the code is modified
+   --  as a result of the restriction in some way.
+
+   Restrictions_Loc : array (Restriction_Id) of Source_Ptr;
+   --  Locations of Restrictions pragmas for error message purposes.
+   --  Valid only if corresponding entry in Restrictions is set.
+
+   Main_Restrictions : Restrictions_Flags := (others => False);
+   --  This variable saves the cumulative restrictions in effect compiling
+   --  any unit that is part of the extended main unit (i.e. the compiled
+   --  unit, its spec if any, and its subunits if any). The reason we keep
+   --  track of this is for the information that goes to the binder about
+   --  restrictions that are set. The binder will identify a unit that has
+   --  a restrictions pragma for error message purposes, and we do not want
+   --  to pick up a restrictions pragma in a with'ed unit for this purpose.
+
+   Violations : Restrictions_Flags := (others => False);
+   --  Corresponding entry is False if the restriction has not been
+   --  violated in the current main unit, and True if it has been violated.
+
+   Restriction_Parameters :
+     array (Restriction_Parameter_Id) of Uint := (others => No_Uint);
+   --  This array indicates the setting of restriction parameter identifier
+   --  values. All values are initially set to No_Uint indicating that the
+   --  parameter is not set, and are set to the appropriate non-negative
+   --  value if a Restrictions pragma specifies the corresponding
+   --  restriction parameter identifier with an appropriate value.
+
+   Restriction_Parameters_Loc :
+     array (Restriction_Parameter_Id) of Source_Ptr;
+   --  Locations of Restrictions pragmas for error message purposes.
+   --  Valid only if corresponding entry in Restriction_Parameters is
+   --  set to a value other than No_Uint.
+
+   type Unit_Entry is record
+      Res_Id : Restriction_Id;
+      Filenm : String (1 .. 8);
+   end record;
+
+   type Unit_Array_Type is array (Positive range <>) of Unit_Entry;
+
+   Unit_Array : constant Unit_Array_Type := (
+     (No_Asynchronous_Control,    "a-astaco"),
+     (No_Calendar,                "a-calend"),
+     (No_Calendar,                "calendar"),
+     (No_Delay,                   "a-calend"),
+     (No_Delay,                   "calendar"),
+     (No_Dynamic_Priorities,      "a-dynpri"),
+     (No_IO,                      "a-direio"),
+     (No_IO,                      "directio"),
+     (No_IO,                      "a-sequio"),
+     (No_IO,                      "sequenio"),
+     (No_IO,                      "a-ststio"),
+     (No_IO,                      "a-textio"),
+     (No_IO,                      "text_io "),
+     (No_IO,                      "a-witeio"),
+     (No_Task_Attributes,         "a-tasatt"),
+     (No_Streams,                 "a-stream"),
+     (No_Unchecked_Conversion,    "a-unccon"),
+     (No_Unchecked_Conversion,    "unchconv"),
+     (No_Unchecked_Deallocation,  "a-uncdea"),
+     (No_Unchecked_Deallocation,  "unchdeal"));
+   --  This array defines the mapping between restriction identifiers and
+   --  predefined language files containing units for which the identifier
+   --  forbids semantic dependence.
+
+   type Save_Compilation_Unit_Restrictions is private;
+   --  Type used for saving and restoring compilation unit restrictions.
+   --  See Compilation_Unit_Restrictions_[Save|Restore] subprograms.
+
+   -----------------
+   -- Subprograms --
+   -----------------
+
+   procedure Check_Restricted_Unit (U : Unit_Name_Type; N : Node_Id);
+   --  Checks if loading of unit U is prohibited by the setting of some
+   --  restriction (e.g. No_IO restricts the loading of unit Ada.Text_IO).
+   --  If a restriction exists post error message at the given node.
+
+   procedure Check_Restriction (R : Restriction_Id; N : Node_Id);
+   --  Checks that the given restriction is not set, and if it is set, an
+   --  appropriate message is posted on the given node. Also records the
+   --  violation in the violations array. Note that it is mandatory to
+   --  always use this routine to check if a restriction is violated. Such
+   --  checks must never be done directly by the caller, since otherwise
+   --  they are not properly recorded in the violations array.
+
+   procedure Check_Restriction
+     (R : Restriction_Parameter_Id;
+      N : Node_Id);
+   --  Checks that the given restriction parameter identifier is not set to
+   --  zero. If it is set to zero, then the node N is replaced by a node
+   --  that raises Storage_Error, and a warning is issued.
+
+   procedure Check_Restriction
+     (R : Restriction_Parameter_Id;
+      V : Uint;
+      N : Node_Id);
+   --  Checks that the count in V does not exceed the maximum value of the
+   --  restriction parameter value corresponding to the given restriction
+   --  parameter identifier (if it has been set). If the count in V exceeds
+   --  the maximum, then post an error message on node N.
+
+   procedure Check_Elaboration_Code_Allowed (N : Node_Id);
+   --  Tests to see if elaboration code is allowed by the current restrictions
+   --  settings. This function is called by Gigi when it needs to define
+   --  an elaboration routine. If elaboration code is not allowed, an error
+   --  message is posted on the node given as argument.
+
+   function No_Exception_Handlers_Set return Boolean;
+   --  Test to see if current restrictions settings specify that no exception
+   --  handlers are present. This function is called by Gigi when it needs to
+   --  expand an AT END clean up identifier with no exception handler.
+
+   function Compilation_Unit_Restrictions_Save
+     return Save_Compilation_Unit_Restrictions;
+   --  This function saves the compilation unit restriction settings, and
+   --  resets them to False. This is used e.g. when compiling a with'ed
+   --  unit to avoid incorrectly propagating restrictions. Note that it
+   --  would not be wrong to also save and reset the partition restrictions,
+   --  since the binder would catch inconsistencies, but actually it is a
+   --  good thing to acquire restrictions from with'ed units if they are
+   --  required to be partition wide, because it allows the restriction
+   --  violation message to be given at compile time instead of link time.
+
+   procedure Compilation_Unit_Restrictions_Restore
+     (R : Save_Compilation_Unit_Restrictions);
+   --  This is the corresponding restore procedure to restore restrictions
+   --  previously saved by Compilation_Unit_Restrictions_Save.
+
+   procedure Disallow_In_No_Run_Time_Mode (Enode : Node_Id);
+   --  If in No_Run_Time mode, then the construct represented by Enode is
+   --  not permitted, and will be appropriately flagged.
+
+   procedure Set_No_Run_Time_Mode;
+   --  Set the no run time mode, and associated restriction pragmas.
+
+   function Get_Restriction_Id
+     (N    : Name_Id)
+      return Restriction_Id;
+   --  Given an identifier name, determines if it is a valid restriction
+   --  identifier, and if so returns the corresponding Restriction_Id
+   --  value, otherwise returns Not_A_Restriction_Id.
+
+   function Get_Restriction_Parameter_Id
+     (N    : Name_Id)
+      return Restriction_Parameter_Id;
+   --  Given an identifier name, determines if it is a valid restriction
+   --  parameter identifier, and if so returns the corresponding
+   --  Restriction_Parameter_Id value, otherwise returns
+   --  Not_A_Restriction_Parameter_Id.
+
+   function Abort_Allowed return Boolean;
+   pragma Inline (Abort_Allowed);
+   --  Tests to see if abort is allowed by the current restrictions settings.
+   --  For abort to be allowed, either No_Abort_Statements must be False,
+   --  or Max_Asynchronous_Select_Nesting must be non-zero.
+
+   function Restricted_Profile return Boolean;
+   --  Tests to see if tasking operations follow the GNAT restricted run time
+   --  profile.
+
+   procedure Set_Ravenscar;
+   --  Sets the set of rerstrictions fro Ravenscar
+
+   procedure Set_Restricted_Profile;
+   --  Sets the set of restrictions for pragma Restricted_Run_Time
+
+   function Tasking_Allowed return Boolean;
+   pragma Inline (Tasking_Allowed);
+   --  Tests to see if tasking operations are allowed by the current
+   --  restrictions settings. For tasking to be allowed Max_Tasks must
+   --  be non-zero.
+
+private
+   type Save_Compilation_Unit_Restrictions is
+     array (Compilation_Unit_Restrictions) of Boolean;
+   --  Type used for saving and restoring compilation unit restrictions.
+   --  See Compilation_Unit_Restrictions_[Save|Restore] subprograms.
+
+end Restrict;
diff --git a/gcc/ada/rident.ads b/gcc/ada/rident.ads
new file mode 100644 (file)
index 0000000..3eb6540
--- /dev/null
@@ -0,0 +1,139 @@
+------------------------------------------------------------------------------
+--                                                                          --
+--                         GNAT COMPILER COMPONENTS                         --
+--                                                                          --
+--                               R I D E N T                                --
+--                                                                          --
+--                                 S p e c                                  --
+--                                                                          --
+--                            $Revision: 1.12 $
+--                                                                          --
+--          Copyright (C) 1992-2001 Free Software Foundation, Inc.          --
+--                                                                          --
+-- GNAT is free software;  you can  redistribute it  and/or modify it under --
+-- terms of the  GNU General Public License as published  by the Free Soft- --
+-- ware  Foundation;  either version 2,  or (at your option) any later ver- --
+-- sion.  GNAT is distributed in the hope that it will be useful, but WITH- --
+-- OUT 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  distributed with GNAT;  see file COPYING.  If not, write --
+-- to  the Free Software Foundation,  59 Temple Place - Suite 330,  Boston, --
+-- MA 02111-1307, USA.                                                      --
+--                                                                          --
+-- GNAT was originally developed  by the GNAT team at  New York University. --
+-- It is now maintained by Ada Core Technologies Inc (http://www.gnat.com). --
+--                                                                          --
+------------------------------------------------------------------------------
+
+--  This package defines the set of restriction identifiers. It is in a
+--  separate package from Restrict so that it can be easily used by the
+--  binder without dragging in a lot of stuff.
+
+package Rident is
+
+   --  The following enumeration type defines the set of restriction
+   --  identifiers not taking a parameter that are implemented in GNAT.
+   --  To add a new restriction identifier, add an entry with the name
+   --  to be used in the pragma, and add appropriate calls to the
+   --  Check_Restriction routine.
+
+   type Restriction_Id is (
+
+      --  The following cases are checked for consistency in the binder
+
+      Boolean_Entry_Barriers,                  -- GNAT (Ravenscar)
+      No_Abort_Statements,                     -- (RM D.7(5), H.4(3))
+      No_Access_Subprograms,                   -- (RM H.4(17))
+      No_Allocators,                           -- (RM H.4(7))
+      No_Asynchronous_Control,                 -- (RM D.9(10))
+      No_Calendar,                             -- GNAT
+      No_Delay,                                -- (RM H.4(21))
+      No_Dispatch,                             -- (RM H.4(19))
+      No_Dynamic_Interrupts,                   -- GNAT
+      No_Dynamic_Priorities,                   -- (RM D.9(9))
+      No_Enumeration_Maps,                     -- GNAT
+      No_Entry_Calls_In_Elaboration_Code,      -- GNAT
+      No_Entry_Queue,                          -- GNAT
+      No_Exception_Handlers,                   -- GNAT
+      No_Exceptions,                           -- (RM H.4(12))
+      No_Fixed_Point,                          -- (RM H.4(15))
+      No_Floating_Point,                       -- (RM H.4(14))
+      No_IO,                                   -- (RM H.4(20))
+      No_Implicit_Conditionals,                -- GNAT
+      No_Implicit_Dynamic_Code,                -- GNAT
+      No_Implicit_Heap_Allocations,            -- (RM D.8(8), H.4(3))
+      No_Implicit_Loops,                       -- GNAT
+      No_Local_Allocators,                     -- (RM H.4(8))
+      No_Local_Protected_Objects,              -- GNAT
+      No_Nested_Finalization,                  -- (RM D.7(4))
+      No_Protected_Type_Allocators,            -- GNAT
+      No_Protected_Types,                      -- (RM H.4(5))
+      No_Recursion,                            -- (RM H.4(22))
+      No_Reentrancy,                           -- (RM H.4(23))
+      No_Relative_Delay,                       -- GNAT
+      No_Requeue,                              -- GNAT
+      No_Select_Statements,                    -- GNAT (Ravenscar)
+      No_Standard_Storage_Pools,               -- GNAT
+      No_Streams,                              -- GNAT
+      No_Task_Allocators,                      -- (RM D.7(7))
+      No_Task_Attributes,                      -- GNAT
+      No_Task_Hierarchy,                       -- (RM D.7(3), H.4(3))
+      No_Task_Termination,                     -- GNAT
+      No_Terminate_Alternatives,               -- (RM D.7(6))
+      No_Unchecked_Access,                     -- (RM H.4(18))
+      No_Unchecked_Conversion,                 -- (RM H.4(16))
+      No_Unchecked_Deallocation,               -- (RM H.4(9))
+      No_Wide_Characters,                      -- GNAT
+      Static_Priorities,                       -- GNAT
+      Static_Storage_Size,                     -- GNAT
+
+      --  The following cases do not require partition-wide checks
+
+      Immediate_Reclamation,                   -- (RM H.4(10))
+      No_Implementation_Attributes,            -- GNAT
+      No_Implementation_Pragmas,               -- GNAT
+      No_Implementation_Restrictions,          -- GNAT
+      No_Elaboration_Code,                     -- GNAT
+
+      Not_A_Restriction_Id);
+
+   --  The following range of Restriction identifiers is checked for
+   --  consistency across a partition. The generated ali file is marked
+   --  for each entry to show one of three possibilities:
+   --
+   --    Corresponding restriction is set (so unit does not violate it)
+   --    Corresponding restriction is not violated
+   --    Corresponding restriction is violated
+
+   subtype Partition_Restrictions is
+     Restriction_Id range Boolean_Entry_Barriers .. Static_Storage_Size;
+
+   --  The following set of Restriction identifiers is not checked for
+   --  consistency across a partition, and the generated ali files does
+   --  not carry any indications with respect to such restrictions.
+
+   subtype Compilation_Unit_Restrictions is
+     Restriction_Id range Immediate_Reclamation .. No_Elaboration_Code;
+
+   --  The following enumeration type defines the set of restriction
+   --  parameter identifiers taking a parameter that are implemented in
+   --  GNAT. To add a new restriction parameter identifier, add an entry
+   --  with the name to be used in the pragma, and add appropriate
+   --  calls to Check_Restriction.
+
+   --  Note: the GNAT implementation currently only accomodates restriction
+   --  parameter identifiers whose expression value is a non-negative
+   --  integer. This is true for all language defined parameters.
+
+   type Restriction_Parameter_Id is (
+     Max_Asynchronous_Select_Nesting,         -- (RM D.7(18), H.4(3))
+     Max_Entry_Queue_Depth,                   -- GNAT
+     Max_Protected_Entries,                   -- (RM D.7(14))
+     Max_Select_Alternatives,                 -- (RM D.7(12))
+     Max_Storage_At_Blocking,                 -- (RM D.7(17))
+     Max_Task_Entries,                        -- (RM D.7(13), H.4(3))
+     Max_Tasks,                               -- (RM D.7(19), H.4(3))
+     Not_A_Restriction_Parameter_Id);
+
+end Rident;
diff --git a/gcc/ada/rtsfind.adb b/gcc/ada/rtsfind.adb
new file mode 100644 (file)
index 0000000..1299e1e
--- /dev/null
@@ -0,0 +1,913 @@
+------------------------------------------------------------------------------
+--                                                                          --
+--                         GNAT COMPILER COMPONENTS                         --
+--                                                                          --
+--                              R T S F I N D                               --
+--                                                                          --
+--                                 B o d y                                  --
+--                                                                          --
+--                            $Revision: 1.96 $
+--                                                                          --
+--          Copyright (C) 1992-2001, Free Software Foundation, Inc.         --
+--                                                                          --
+-- GNAT is free software;  you can  redistribute it  and/or modify it under --
+-- terms of the  GNU General Public License as published  by the Free Soft- --
+-- ware  Foundation;  either version 2,  or (at your option) any later ver- --
+-- sion.  GNAT is distributed in the hope that it will be useful, but WITH- --
+-- OUT 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  distributed with GNAT;  see file COPYING.  If not, write --
+-- to  the Free Software Foundation,  59 Temple Place - Suite 330,  Boston, --
+-- MA 02111-1307, USA.                                                      --
+--                                                                          --
+-- GNAT was originally developed  by the GNAT team at  New York University. --
+-- It is now maintained by Ada Core Technologies Inc (http://www.gnat.com). --
+--                                                                          --
+------------------------------------------------------------------------------
+
+with Atree;    use Atree;
+with Casing;   use Casing;
+with Csets;    use Csets;
+with Debug;    use Debug;
+with Einfo;    use Einfo;
+with Elists;   use Elists;
+with Fname;    use Fname;
+with Fname.UF; use Fname.UF;
+with Lib;      use Lib;
+with Lib.Load; use Lib.Load;
+with Namet;    use Namet;
+with Nlists;   use Nlists;
+with Nmake;    use Nmake;
+with Output;   use Output;
+with Opt;      use Opt;
+with Restrict; use Restrict;
+with Sem;      use Sem;
+with Sem_Ch7;  use Sem_Ch7;
+with Sem_Util; use Sem_Util;
+with Sinfo;    use Sinfo;
+with Stand;    use Stand;
+with Snames;   use Snames;
+with Tbuild;   use Tbuild;
+with Uname;    use Uname;
+
+package body Rtsfind is
+
+   ----------------
+   -- Unit table --
+   ----------------
+
+   --  The unit table has one entry for each unit included in the definition
+   --  of the type RTU_Id in the spec. The table entries are initialized in
+   --  Initialize to set the Entity field to Empty, indicating that the
+   --  corresponding unit has not yet been loaded. The fields are set when
+   --  a unit is loaded to contain the defining entity for the unit, the
+   --  unit name, and the unit number.
+
+   type RT_Unit_Table_Record is record
+      Entity : Entity_Id;
+      Uname  : Unit_Name_Type;
+      Unum   : Unit_Number_Type;
+      Withed : Boolean;
+   end record;
+
+   RT_Unit_Table : array (RTU_Id) of RT_Unit_Table_Record;
+
+   --------------------------
+   -- Runtime Entity Table --
+   --------------------------
+
+   --  There is one entry in the runtime entity table for each entity that is
+   --  included in the definition of the RE_Id type in the spec. The entries
+   --  are set by Initialize_Rtsfind to contain Empty, indicating that the
+   --  entity has not yet been located. Once the entity is located for the
+   --  first time, its ID is stored in this array, so that subsequent calls
+   --  for the same entity can be satisfied immediately.
+
+   RE_Table : array (RE_Id) of Entity_Id;
+
+   --------------------------
+   -- Generation of WITH's --
+   --------------------------
+
+   --  When a unit is implicitly loaded as a result of a call to RTE, it
+   --  is necessary to create an implicit with to ensure that the object
+   --  is correctly loaded by the binder. Such with statements are only
+   --  required when the request is from the extended main unit (if a
+   --  client needs a with, that will be taken care of when the client
+   --  is compiled.
+
+   --  We always attach the with to the main unit. This is not perfectly
+   --  accurate in terms of elaboration requirements, but it is close
+   --  enough, since the units that are accessed using rtsfind do not
+   --  have delicate elaboration requirements.
+
+   --  The flag Withed in the unit table record is initially set to False.
+   --  It is set True if a with has been generated for the main unit for
+   --  the corresponding unit.
+
+   -----------------------
+   -- Local Subprograms --
+   -----------------------
+
+   procedure Load_Fail (S : String; U_Id : RTU_Id; Ent_Name : String := "");
+   --  Internal procedure called if we can't find the entity or unit.
+   --  The parameter is a detailed error message that is to be given.
+   --  S is a reason for failing to compile the file. U_Id is the unit
+   --  id, and Ent_Name, if non-null, is the associated entity name.
+
+   function Get_Unit_Name (U_Id : RTU_Id) return Unit_Name_Type;
+   --  Retrieves the Unit Name given a unit id represented by its
+   --  enumaration value in RTU_Id.
+
+   procedure Load_RTU (U_Id : RTU_Id; Use_Setting : Boolean := False);
+   --  Load the unit whose Id is given if not already loaded. The unit is
+   --  loaded, analyzed, and added to the with list, and the entry in
+   --  RT_Unit_Table is updated to reflect the load. The second parameter
+   --  indicates the initial setting for the Is_Potentially_Use_Visible
+   --  flag of the entity for the loaded unit (if it is indeed loaded).
+   --  A value of False means nothing special need be done. A value of
+   --  True indicates that this flag must be set to True. It is needed
+   --  only in the Text_IO_Kludge procedure, which may materialize an
+   --  entity of Text_IO (or Wide_Text_IO) that was previously unknown.
+
+   function RE_Chars (E : RE_Id) return Name_Id;
+   --  Given a RE_Id value returns the Chars of the corresponding entity.
+
+   -------------------
+   -- Get_Unit_Name --
+   -------------------
+
+   function Get_Unit_Name (U_Id : RTU_Id) return Unit_Name_Type is
+      Uname_Chars : constant String := RTU_Id'Image (U_Id);
+
+   begin
+      Name_Len := Uname_Chars'Length;
+      Name_Buffer (1 .. Name_Len) := Uname_Chars;
+      Set_Casing (All_Lower_Case);
+
+      if U_Id in Ada_Child then
+         Name_Buffer (4) := '.';
+
+         if U_Id in Ada_Calendar_Child then
+            Name_Buffer (13) := '.';
+
+         elsif U_Id in Ada_Finalization_Child then
+            Name_Buffer (17) := '.';
+
+         elsif U_Id in Ada_Real_Time_Child then
+            Name_Buffer (14) := '.';
+
+         elsif U_Id in Ada_Streams_Child then
+            Name_Buffer (12) := '.';
+
+         elsif U_Id in Ada_Text_IO_Child then
+            Name_Buffer (12) := '.';
+
+         elsif U_Id in Ada_Wide_Text_IO_Child then
+            Name_Buffer (17) := '.';
+         end if;
+
+      elsif U_Id in Interfaces_Child then
+         Name_Buffer (11) := '.';
+
+      elsif U_Id in System_Child then
+         Name_Buffer (7) := '.';
+
+         if U_Id in System_Tasking_Child then
+            Name_Buffer (15) := '.';
+         end if;
+
+         if U_Id in System_Tasking_Restricted_Child then
+            Name_Buffer (26) := '.';
+         end if;
+
+         if U_Id in System_Tasking_Protected_Objects_Child then
+            Name_Buffer (33) := '.';
+         end if;
+
+         if U_Id in System_Tasking_Async_Delays_Child then
+            Name_Buffer (28) := '.';
+         end if;
+      end if;
+
+      --  Add %s at end for spec
+
+      Name_Buffer (Name_Len + 1) := '%';
+      Name_Buffer (Name_Len + 2) := 's';
+      Name_Len := Name_Len + 2;
+
+      return Name_Find;
+   end Get_Unit_Name;
+
+   ----------------
+   -- Initialize --
+   ----------------
+
+   procedure Initialize is
+   begin
+      --  Initialize the unit table
+
+      for J in RTU_Id loop
+         RT_Unit_Table (J).Entity := Empty;
+      end loop;
+
+      for J in RE_Id loop
+         RE_Table (J) := Empty;
+      end loop;
+   end Initialize;
+
+   ------------
+   -- Is_RTE --
+   ------------
+
+   function Is_RTE (Ent : Entity_Id; E : RE_Id) return Boolean is
+      E_Unit_Name   : Unit_Name_Type;
+      Ent_Unit_Name : Unit_Name_Type;
+
+      S  : Entity_Id;
+      E1 : Entity_Id;
+      E2 : Entity_Id;
+
+   begin
+      if No (Ent) then
+         return False;
+
+      --  If E has already a corresponding entity, check it directly,
+      --  going to full views if they exist to deal with the incomplete
+      --  and private type cases properly.
+
+      elsif Present (RE_Table (E)) then
+         E1 := Ent;
+
+         if Is_Type (E1) and then Present (Full_View (E1)) then
+            E1 := Full_View (E1);
+         end if;
+
+         E2 := RE_Table (E);
+
+         if Is_Type (E2) and then Present (Full_View (E2)) then
+            E2 := Full_View (E2);
+         end if;
+
+         return E1 = E2;
+      end if;
+
+      --  If the unit containing E is not loaded, we already know that
+      --  the entity we have cannot have come from this unit.
+
+      E_Unit_Name := Get_Unit_Name (RE_Unit_Table (E));
+
+      if not Is_Loaded (E_Unit_Name) then
+         return False;
+      end if;
+
+      --  Here the unit containing the entity is loaded. We have not made
+      --  an explicit call to RTE to get the entity in question, but we may
+      --  have obtained a reference to it indirectly from some other entity
+      --  in the same unit, or some other unit that references it.
+
+      --  Get the defining unit of the entity
+
+      S := Scope (Ent);
+
+      if Ekind (S) /= E_Package then
+         return False;
+      end if;
+
+      Ent_Unit_Name := Get_Unit_Name (Unit_Declaration_Node (S));
+
+      --  If the defining unit of the entity we are testing is not the
+      --  unit containing E, then they cannot possibly match.
+
+      if Ent_Unit_Name /= E_Unit_Name then
+         return False;
+      end if;
+
+      --  If the units match, then compare the names (remember that no
+      --  overloading is permitted in entities fetched using Rtsfind).
+
+      if RE_Chars (E) = Chars (Ent) then
+         RE_Table (E) := Ent;
+
+         --  If front-end inlining is enabled, we may be within a body that
+         --  contains inlined functions, which has not been retrieved through
+         --  rtsfind, and therefore is not yet recorded in the RT_Unit_Table.
+         --  Add the unit information now, it must be fully available.
+
+         declare
+            U : RT_Unit_Table_Record
+                  renames  RT_Unit_Table (RE_Unit_Table (E));
+         begin
+            if No (U.Entity) then
+               U.Entity := S;
+               U.Uname  := E_Unit_Name;
+               U.Unum   := Get_Source_Unit (S);
+            end if;
+         end;
+
+         return True;
+      else
+         return False;
+      end if;
+   end Is_RTE;
+
+   ----------------------------
+   -- Is_Text_IO_Kludge_Unit --
+   ----------------------------
+
+   function Is_Text_IO_Kludge_Unit (Nam : Node_Id) return Boolean is
+      Prf : Node_Id;
+      Sel : Node_Id;
+
+   begin
+      if Nkind (Nam) /= N_Expanded_Name then
+         return False;
+      end if;
+
+      Prf := Prefix (Nam);
+      Sel := Selector_Name (Nam);
+
+      if Nkind (Sel) /= N_Expanded_Name
+        or else Nkind (Prf) /= N_Identifier
+        or else Chars (Prf) /= Name_Ada
+      then
+         return False;
+      end if;
+
+      Prf := Prefix (Sel);
+      Sel := Selector_Name (Sel);
+
+      return
+        Nkind (Prf) = N_Identifier
+          and then
+        (Chars (Prf) = Name_Text_IO or else Chars (Prf) = Name_Wide_Text_IO)
+          and then
+        Nkind (Sel) = N_Identifier
+          and then
+        Chars (Sel) in Text_IO_Package_Name;
+
+   end Is_Text_IO_Kludge_Unit;
+
+   ---------------
+   -- Load_Fail --
+   ---------------
+
+   procedure Load_Fail (S : String; U_Id : RTU_Id; Ent_Name : String := "") is
+   begin
+      Set_Standard_Error;
+
+      Write_Str ("fatal error: run-time library configuration error");
+      Write_Eol;
+
+      if Ent_Name /= "" then
+         Write_Str ("cannot locate """);
+
+         --  Copy name skipping initial RE_ or RO_XX characters
+
+         if Ent_Name (1 .. 2) = "RE" then
+            for J in 4 .. Ent_Name'Length loop
+               Name_Buffer (J - 3) := Ent_Name (J);
+            end loop;
+         else
+            for J in 7 .. Ent_Name'Length loop
+               Name_Buffer (J - 6) := Ent_Name (J);
+            end loop;
+         end if;
+
+         Name_Len := Ent_Name'Length - 3;
+         Set_Casing (Mixed_Case);
+         Write_Str (Name_Buffer (1 .. Name_Len));
+         Write_Str (""" in file """);
+
+      else
+         Write_Str ("cannot load file """);
+      end if;
+
+      Write_Name
+        (Get_File_Name (RT_Unit_Table (U_Id).Uname, Subunit => False));
+      Write_Str (""" (");
+      Write_Str (S);
+      Write_Char (')');
+      Write_Eol;
+      Set_Standard_Output;
+      raise Unrecoverable_Error;
+   end Load_Fail;
+
+   --------------
+   -- Load_RTU --
+   --------------
+
+   procedure Load_RTU (U_Id : RTU_Id; Use_Setting : Boolean := False) is
+      Loaded   : Boolean;
+      U        : RT_Unit_Table_Record renames RT_Unit_Table (U_Id);
+      Priv_Par : Elist_Id := New_Elmt_List;
+      Lib_Unit : Node_Id;
+
+      procedure Save_Private_Visibility;
+      --  If the current unit is the body of child unit or the spec of a
+      --  private child unit, the private declarations of the parent (s)
+      --  are visible. If the unit to be loaded is another public sibling,
+      --  its compilation will affect the visibility of the common ancestors.
+      --  Indicate those that must be restored.
+
+      procedure Restore_Private_Visibility;
+      --  Restore the visibility of ancestors after compiling RTU.
+
+      --------------------------------
+      -- Restore_Private_Visibility --
+      --------------------------------
+
+      procedure Restore_Private_Visibility is
+         E_Par : Elmt_Id;
+
+      begin
+         E_Par := First_Elmt (Priv_Par);
+
+         while Present (E_Par) loop
+            if not In_Private_Part (Node (E_Par)) then
+               Install_Private_Declarations (Node (E_Par));
+            end if;
+
+            Next_Elmt (E_Par);
+         end loop;
+      end Restore_Private_Visibility;
+
+      -----------------------------
+      -- Save_Private_Visibility --
+      -----------------------------
+
+      procedure Save_Private_Visibility is
+         Par : Entity_Id;
+
+      begin
+         Par := Scope (Current_Scope);
+
+         while Present (Par)
+           and then Par /= Standard_Standard
+         loop
+            if Ekind (Par) = E_Package
+              and then Is_Compilation_Unit (Par)
+              and then In_Private_Part (Par)
+            then
+               Append_Elmt (Par, Priv_Par);
+            end if;
+
+            Par := Scope (Par);
+         end loop;
+      end Save_Private_Visibility;
+
+   --  Start of processing for Load_RTU
+
+   begin
+      --  Nothing to do if unit is already loaded
+
+      if Present (U.Entity) then
+         return;
+      end if;
+
+      --  Otherwise we need to load the unit, First build unit name
+      --  from the enumeration literal name in type RTU_Id.
+
+      U.Uname  := Get_Unit_Name (U_Id);
+      U.Withed := False;
+      Loaded   := Is_Loaded (U.Uname);
+
+      --  Now do the load call, note that setting Error_Node to Empty is
+      --  a signal to Load_Unit that we will regard a failure to find the
+      --  file as a fatal error, and that it should not output any kind
+      --  of diagnostics, since we will take care of it here.
+
+      U.Unum :=
+        Load_Unit
+          (Load_Name  => U.Uname,
+           Required   => False,
+           Subunit    => False,
+           Error_Node => Empty);
+
+      if U.Unum = No_Unit then
+         Load_Fail ("unit not found", U_Id);
+
+      elsif Fatal_Error (U.Unum) then
+         Load_Fail ("parser errors", U_Id);
+      end if;
+
+      --  Make sure that the unit is analyzed
+
+      declare
+         Was_Analyzed : Boolean := Analyzed (Cunit (Current_Sem_Unit));
+
+      begin
+         --  Pretend that the current unit is analysed, in case it is
+         --  System or some such. This allows us to put some declarations,
+         --  such as exceptions and packed arrays of Boolean, into System
+         --  even though expanding them requires System...
+
+         --  This is a bit odd but works fine. If the RTS unit does not depend
+         --  in any way on the current unit, then it never gets back into the
+         --  current unit's tree, and the change we make to the current unit
+         --  tree is never noticed by anyone (it is undone in a moment). That
+         --  is the normal situation.
+
+         --  If the RTS Unit *does* depend on the current unit, for instance,
+         --  when you are compiling System, then you had better have finished
+         --  Analyzing the part of System that is depended on before you try
+         --  to load the RTS Unit. This means having the System ordered in an
+         --  appropriate manner.
+
+         Set_Analyzed (Cunit (Current_Sem_Unit), True);
+
+         if not Analyzed (Cunit (U.Unum)) then
+
+            Save_Private_Visibility;
+            Semantics (Cunit (U.Unum));
+            Restore_Private_Visibility;
+
+            if Fatal_Error (U.Unum) then
+               Load_Fail ("semantic errors", U_Id);
+            end if;
+         end if;
+
+         --  Undo the pretence
+
+         Set_Analyzed (Cunit (Current_Sem_Unit), Was_Analyzed);
+      end;
+
+      Lib_Unit := Unit (Cunit (U.Unum));
+      U.Entity := Defining_Entity (Lib_Unit);
+
+      if Use_Setting then
+         Set_Is_Potentially_Use_Visible (U.Entity, True);
+      end if;
+   end Load_RTU;
+
+   --------------
+   -- RE_Chars --
+   --------------
+
+   function RE_Chars (E : RE_Id) return Name_Id is
+      RE_Name_Chars : constant String := RE_Id'Image (E);
+
+   begin
+      --  Copy name skipping initial RE_ or RO_XX characters
+
+      if RE_Name_Chars (1 .. 2) = "RE" then
+         for J in 4 .. RE_Name_Chars'Last loop
+            Name_Buffer (J - 3) := Fold_Lower (RE_Name_Chars (J));
+         end loop;
+
+         Name_Len := RE_Name_Chars'Length - 3;
+
+      else
+         for J in 7 .. RE_Name_Chars'Last loop
+            Name_Buffer (J - 6) := Fold_Lower (RE_Name_Chars (J));
+         end loop;
+
+         Name_Len := RE_Name_Chars'Length - 6;
+      end if;
+
+      return Name_Find;
+   end RE_Chars;
+
+   ---------
+   -- RTE --
+   ---------
+
+   function RTE (E : RE_Id) return Entity_Id is
+      U_Id : constant RTU_Id := RE_Unit_Table (E);
+      U    : RT_Unit_Table_Record renames RT_Unit_Table (U_Id);
+
+      Ent      : Entity_Id;
+      Lib_Unit : Node_Id;
+      Pkg_Ent  : Entity_Id;
+      Ename    : Name_Id;
+      Enode    : Node_Id;
+
+      procedure Check_RPC;
+      --  Reject programs that make use of distribution features not supported
+      --  on the current target. On such targets (VMS, Vxworks, others?) we
+      --  only provide a minimal body for System.Rpc that only supplies an
+      --  implementation of partition_id.
+
+      function Find_Local_Entity (E : RE_Id) return Entity_Id;
+      --  This function is used when entity E is in this compilation's main
+      --  unit. It gets the value from the already compiled declaration.
+
+      function Make_Unit_Name (N : Node_Id) return Node_Id;
+      --  If the unit is a child unit, build fully qualified name for use
+      --  in with_clause.
+
+      ---------------
+      -- Check_RPC --
+      ---------------
+
+      procedure Check_RPC is
+         Body_Name    : Unit_Name_Type;
+         Unum         : Unit_Number_Type;
+
+      begin
+         --  Bypass this check if debug flag -gnatdR set
+
+         if Debug_Flag_RR then
+            return;
+         end if;
+
+         --  Otherwise we need the check if we are going after one of
+         --  the critical entities in System.RPC in stubs mode.
+
+         if (Distribution_Stub_Mode = Generate_Receiver_Stub_Body
+                      or else
+                        Distribution_Stub_Mode = Generate_Caller_Stub_Body)
+           and then (E = RE_Do_Rpc
+                       or else E = RE_Do_Apc
+                       or else E = RE_Params_Stream_Type
+                       or else E = RE_RPC_Receiver)
+         then
+            --  Load body of System.Rpc, and abort if this is the body that is
+            --  provided by GNAT, for which these features are not supported
+            --  on current target. We identify the gnat body by the presence
+            --  of a local entity called Gnat in the first declaration.
+
+            Lib_Unit := Unit (Cunit (U.Unum));
+            Body_Name := Get_Body_Name (Get_Unit_Name (Lib_Unit));
+            Unum :=
+              Load_Unit
+                (Load_Name  => Body_Name,
+                 Required   => False,
+                 Subunit    => False,
+                 Error_Node => Empty,
+                 Renamings  => True);
+
+            if Unum /= No_Unit then
+               declare
+                  Decls : List_Id := Declarations (Unit (Cunit (Unum)));
+
+               begin
+                  if Present (Decls)
+                    and then Nkind (First (Decls)) = N_Object_Declaration
+                    and then
+                      Chars (Defining_Identifier (First (Decls))) = Name_Gnat
+                  then
+                     Set_Standard_Error;
+                     Write_Str ("distribution feature not supported");
+                     Write_Eol;
+                     raise Unrecoverable_Error;
+                  end if;
+               end;
+            end if;
+         end if;
+      end Check_RPC;
+
+      ------------------------
+      -- Find_System_Entity --
+      ------------------------
+
+      function Find_Local_Entity (E : RE_Id) return Entity_Id is
+         RE_Str : String renames RE_Id'Image (E);
+         Ent    : Entity_Id;
+
+         Save_Nam : constant String := Name_Buffer (1 .. Name_Len);
+         --  Save name buffer and length over call
+
+      begin
+         Name_Len := Natural'Max (0, RE_Str'Length - 3);
+         Name_Buffer (1 .. Name_Len) :=
+           RE_Str (RE_Str'First + 3 .. RE_Str'Last);
+
+         Ent := Entity_Id (Get_Name_Table_Info (Name_Find));
+
+         Name_Len := Save_Nam'Length;
+         Name_Buffer (1 .. Name_Len) := Save_Nam;
+
+         return Ent;
+      end Find_Local_Entity;
+
+      --------------------
+      -- Make_Unit_Name --
+      --------------------
+
+      function Make_Unit_Name (N : Node_Id) return Node_Id is
+         Nam  : Node_Id;
+         Scop : Entity_Id;
+
+      begin
+         Nam  := New_Reference_To (U.Entity, Standard_Location);
+         Scop := Scope (U.Entity);
+
+         if Nkind (N) = N_Defining_Program_Unit_Name then
+            while Scop /= Standard_Standard loop
+               Nam :=
+                 Make_Expanded_Name (Standard_Location,
+                   Chars  => Chars (U.Entity),
+                   Prefix => New_Reference_To (Scop, Standard_Location),
+                   Selector_Name => Nam);
+               Set_Entity (Nam, U.Entity);
+
+               Scop := Scope (Scop);
+            end loop;
+         end if;
+
+         return Nam;
+      end Make_Unit_Name;
+
+   --  Start of processing for RTE
+
+   begin
+      --  Doing a rtsfind in system.ads is special, as we cannot do this
+      --  when compiling System itself. So if we are compiling system then
+      --  we should already have acquired and processed the declaration
+      --  of the entity. The test is to see if this compilation's main unit
+      --  is System. If so, return the value from the already compiled
+      --  declaration and otherwise do a regular find.
+
+      --  Not pleasant, but these kinds of annoying recursion when
+      --  writing an Ada compiler in Ada have to be broken somewhere!
+
+      if Present (Main_Unit_Entity)
+        and then Chars (Main_Unit_Entity) = Name_System
+        and then Analyzed (Main_Unit_Entity)
+        and then not Is_Child_Unit (Main_Unit_Entity)
+      then
+         return Find_Local_Entity (E);
+      end if;
+
+      Enode := Current_Error_Node;
+
+      --  Load unit if unit not previously loaded
+
+      if No (RE_Table (E)) then
+         Load_RTU (U_Id);
+         Lib_Unit := Unit (Cunit (U.Unum));
+
+         --  In the subprogram case, we are all done, the entity we want
+         --  is the entity for the subprogram itself. Note that we do not
+         --  bother to check that it is the entity that was requested.
+         --  the only way that could fail to be the case is if runtime is
+         --  hopelessly misconfigured, and it isn't worth testing for this.
+
+         if Nkind (Lib_Unit) = N_Subprogram_Declaration then
+            RE_Table (E) := U.Entity;
+
+         --  Otherwise we must have the package case, and here we have to
+         --  search the package entity chain for the entity we want. The
+         --  entity we want must be present in this chain, or we have a
+         --  misconfigured runtime.
+
+         else
+            pragma Assert (Nkind (Lib_Unit) = N_Package_Declaration);
+            Ename := RE_Chars (E);
+
+            Pkg_Ent := First_Entity (U.Entity);
+
+            while Present (Pkg_Ent) loop
+               if Ename = Chars (Pkg_Ent) then
+                  RE_Table (E) := Pkg_Ent;
+                  Check_RPC;
+                  goto Found;
+               end if;
+
+               Next_Entity (Pkg_Ent);
+            end loop;
+
+            --  If we didn't find the unit we want, something is wrong!
+
+            Load_Fail ("entity not in package", U_Id,  RE_Id'Image (E));
+            raise Program_Error;
+         end if;
+      end if;
+
+      --  See if we have to generate a with for this entity. We generate
+      --  a with if the current unit is part of the extended main code
+      --  unit, and if we have not already added the with. The with is
+      --  added to the appropriate unit (the current one).
+
+   <<Found>>
+      if (not U.Withed)
+        and then
+          In_Extended_Main_Code_Unit (Cunit_Entity (Current_Sem_Unit))
+      then
+         U.Withed := True;
+
+         declare
+            Withn    : Node_Id;
+            Lib_Unit : Node_Id;
+
+         begin
+            Lib_Unit := Unit (Cunit (U.Unum));
+            Withn :=
+              Make_With_Clause (Standard_Location,
+                Name =>
+                  Make_Unit_Name
+                    (Defining_Unit_Name (Specification (Lib_Unit))));
+            Set_Library_Unit          (Withn, Cunit (U.Unum));
+            Set_Corresponding_Spec    (Withn, U.Entity);
+            Set_First_Name            (Withn, True);
+            Set_Implicit_With         (Withn, True);
+
+            Mark_Rewrite_Insertion (Withn);
+            Append (Withn, Context_Items (Cunit (Current_Sem_Unit)));
+         end;
+      end if;
+
+      --  We can now obtain the entity. Check that the No_Run_Time condition
+      --  is not violated. Note that we do not signal the error if we detect
+      --  it in a runtime unit. This can only arise if the user explicitly
+      --  with'ed the runtime unit (or another runtime unit that uses it
+      --  transitively), or if some acceptable (e.g. inlined) entity is
+      --  fetched from a unit, some of whose other routines or entities
+      --  violate the conditions. In the latter case, it does not matter,
+      --  since we won't be using those entities.
+
+      Ent := RE_Table (E);
+
+      if Is_Subprogram (Ent)
+        and then not Is_Inlined (Ent)
+        and then Sloc (Enode) /= Standard_Location
+        and then not
+          Is_Predefined_File_Name (Unit_File_Name (Get_Source_Unit (Enode)))
+      then
+         Disallow_In_No_Run_Time_Mode (Enode);
+      end if;
+
+      return Ent;
+   end RTE;
+
+   --------------------
+   -- Text_IO_Kludge --
+   --------------------
+
+   procedure Text_IO_Kludge (Nam : Node_Id) is
+      Chrs : Name_Id;
+
+      type Name_Map_Type is array (Text_IO_Package_Name) of RTU_Id;
+
+      Name_Map : Name_Map_Type := Name_Map_Type'(
+        Name_Decimal_IO     => Ada_Text_IO_Decimal_IO,
+        Name_Enumeration_IO => Ada_Text_IO_Enumeration_IO,
+        Name_Fixed_IO       => Ada_Text_IO_Fixed_IO,
+        Name_Float_IO       => Ada_Text_IO_Float_IO,
+        Name_Integer_IO     => Ada_Text_IO_Integer_IO,
+        Name_Modular_IO     => Ada_Text_IO_Modular_IO);
+
+      Wide_Name_Map : Name_Map_Type := Name_Map_Type'(
+        Name_Decimal_IO     => Ada_Wide_Text_IO_Decimal_IO,
+        Name_Enumeration_IO => Ada_Wide_Text_IO_Enumeration_IO,
+        Name_Fixed_IO       => Ada_Wide_Text_IO_Fixed_IO,
+        Name_Float_IO       => Ada_Wide_Text_IO_Float_IO,
+        Name_Integer_IO     => Ada_Wide_Text_IO_Integer_IO,
+        Name_Modular_IO     => Ada_Wide_Text_IO_Modular_IO);
+
+   begin
+      --  Nothing to do if name is not identifier or a selected component
+      --  whose selector_name is not an identifier.
+
+      if Nkind (Nam) = N_Identifier then
+         Chrs := Chars (Nam);
+
+      elsif Nkind (Nam) = N_Selected_Component
+        and then Nkind (Selector_Name (Nam)) = N_Identifier
+      then
+         Chrs := Chars (Selector_Name (Nam));
+
+      else
+         return;
+      end if;
+
+      --  Nothing to do if name is not one of the Text_IO subpackages
+      --  Otherwise look through loaded units, and if we find Text_IO
+      --  or Wide_Text_IO already loaded, then load the proper child.
+
+      if Chrs in Text_IO_Package_Name then
+         for U in Main_Unit .. Last_Unit loop
+            Get_Name_String (Unit_File_Name (U));
+
+            if Name_Len = 12 then
+
+               --  Here is where we do the loads if we find one of the
+               --  units Ada.Text_IO or Ada.Wide_Text_IO. An interesting
+               --  detail is that these units may already be used (i.e.
+               --  their In_Use flags may be set). Normally when the In_Use
+               --  flag is set, the Is_Potentially_Use_Visible flag of all
+               --  entities in the package is set, but the new entity we
+               --  are mysteriously adding was not there to have its flag
+               --  set at the time. So that's why we pass the extra parameter
+               --  to RTU_Find, to make sure the flag does get set now.
+               --  Given that those generic packages are in fact child units,
+               --  we must indicate that they are visible.
+
+               if Name_Buffer (1 .. 12) = "a-textio.ads" then
+                  Load_RTU (Name_Map (Chrs), In_Use (Cunit_Entity (U)));
+                  Set_Is_Visible_Child_Unit
+                    (RT_Unit_Table (Name_Map (Chrs)).Entity);
+
+               elsif Name_Buffer (1 .. 12) = "a-witeio.ads" then
+                  Load_RTU (Wide_Name_Map (Chrs), In_Use (Cunit_Entity (U)));
+                  Set_Is_Visible_Child_Unit
+                    (RT_Unit_Table (Wide_Name_Map (Chrs)).Entity);
+               end if;
+            end if;
+         end loop;
+      end if;
+   end Text_IO_Kludge;
+
+end Rtsfind;
diff --git a/gcc/ada/rtsfind.ads b/gcc/ada/rtsfind.ads
new file mode 100644 (file)
index 0000000..11304f6
--- /dev/null
@@ -0,0 +1,2324 @@
+------------------------------------------------------------------------------
+--                                                                          --
+--                         GNAT COMPILER COMPONENTS                         --
+--                                                                          --
+--                              R T S F I N D                               --
+--                                                                          --
+--                                 S p e c                                  --
+--                                                                          --
+--                            $Revision: 1.216 $
+--                                                                          --
+--          Copyright (C) 1992-2001, Free Software Foundation, Inc.         --
+--                                                                          --
+-- GNAT is free software;  you can  redistribute it  and/or modify it under --
+-- terms of the  GNU General Public License as published  by the Free Soft- --
+-- ware  Foundation;  either version 2,  or (at your option) any later ver- --
+-- sion.  GNAT is distributed in the hope that it will be useful, but WITH- --
+-- OUT 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  distributed with GNAT;  see file COPYING.  If not, write --
+-- to  the Free Software Foundation,  59 Temple Place - Suite 330,  Boston, --
+-- MA 02111-1307, USA.                                                      --
+--                                                                          --
+-- GNAT was originally developed  by the GNAT team at  New York University. --
+-- It is now maintained by Ada Core Technologies Inc (http://www.gnat.com). --
+--                                                                          --
+------------------------------------------------------------------------------
+
+with Types; use Types;
+
+package Rtsfind is
+
+--  This package contains the routine that is used to obtain runtime library
+--  entities, loading in the required runtime library packages on demand. It
+--  is also used for such purposes as finding System.Address when System has
+--  not been explicitly With'ed.
+
+   ------------------------
+   -- Runtime Unit Table --
+   ------------------------
+
+   --  The following type includes an enumeration entry for each runtime
+   --  unit. The enumeration literal represents the fully qualified
+   --  name of the unit, as follows:
+
+   --    Names of the form Ada_xxx are first level children of Ada, whose
+   --    name is Ada.xxx. For example, the name Ada_Tags refers to package
+   --    Ada.Tags.
+
+   --    Names of the form Ada_Calendar_xxx are second level children
+   --    of Ada.Calendar. This is part of a temporary implementation of
+   --    delays; eventually, packages implementing delays will be found
+   --    relative to the package that declares the time type.
+
+   --    Names of the form Interfaces_xxx are first level children of
+   --    Interfaces_CPP refers to package Interfaces.CPP
+
+   --    Names of the form System_xxx are first level children of System, whose
+   --    name is System.xxx. For example, the name System_Str_Concat refers to
+   --    package System.Str_Concat.
+
+   --    Names of the form System_Tasking_xxx are second level children of the
+   --    package System.Tasking. For example, System_Tasking_Stages refers to
+   --    refers to the package System.Tasking.Stages.
+
+   --    Other names stand for themselves (e.g. System for package System)
+
+   --  This list can contain both subprogram and package unit names. For
+   --  packages, the accessible entities in the package are separately
+   --  listed in the package entity table. The units must be either library
+   --  level package declarations, or library level subprogram declarations.
+   --  Generic units, library level instantiations and subprogram bodies
+   --  acting as specs may not be referenced (all these cases could be added
+   --  at the expense of additional complexity in the body of Rtsfind, but
+   --  it doesn't seem worth while, since the implementation controls the
+   --  set of units that are referenced, and this restrictions is easily met.
+
+   --  IMPORTANT NOTE: the specs of packages and procedures with'ed using
+   --  this mechanism may not contain use clauses. This is because these
+   --  subprograms are compiled in the current visibility environment, and
+   --  it would be too much trouble to establish a clean environment for the
+   --  compilation. The presence of extraneous visible stuff has no effect
+   --  on the compilation except in the presence of use clauses (which might
+   --  result in unexpected ambiguities).
+
+   type RTU_Id is (
+      --  Runtime packages, for list of accessible entities in each
+      --  package see declarations in the runtime entity table below.
+
+      RTU_Null,
+      --  Used as a null entry. Will cause an error if referenced.
+
+      --  Children of Ada
+
+      Ada_Calendar,
+      Ada_Exceptions,
+      Ada_Finalization,
+      Ada_Interrupts,
+      Ada_Real_Time,
+      Ada_Streams,
+      Ada_Tags,
+      Ada_Task_Identification,
+
+      --  Children of Ada.Calendar
+
+      Ada_Calendar_Delays,
+
+      --  Children of Ada.Finalization
+
+      Ada_Finalization_List_Controller,
+
+      --  Children of Ada.Real_Time
+
+      Ada_Real_Time_Delays,
+
+      --  Children of Ada.Streams
+
+      Ada_Streams_Stream_IO,
+
+      --  Children of Ada.Text_IO (for Text_IO_Kludge)
+
+      Ada_Text_IO_Decimal_IO,
+      Ada_Text_IO_Enumeration_IO,
+      Ada_Text_IO_Fixed_IO,
+      Ada_Text_IO_Float_IO,
+      Ada_Text_IO_Integer_IO,
+      Ada_Text_IO_Modular_IO,
+
+      --  Children of Ada.Wide_Text_IO (for Text_IO_Kludge)
+
+      Ada_Wide_Text_IO_Decimal_IO,
+      Ada_Wide_Text_IO_Enumeration_IO,
+      Ada_Wide_Text_IO_Fixed_IO,
+      Ada_Wide_Text_IO_Float_IO,
+      Ada_Wide_Text_IO_Integer_IO,
+      Ada_Wide_Text_IO_Modular_IO,
+
+      --  Interfaces
+
+      Interfaces,
+
+      --  Children of Interfaces
+
+      Interfaces_CPP,
+      Interfaces_Packed_Decimal,
+
+      --  Package System
+
+      System,
+
+      --  Children of System
+
+      System_Arith_64,
+      System_AST_Handling,
+      System_Assertions,
+      System_Aux_DEC,
+      System_Bit_Ops,
+      System_Checked_Pools,
+      System_Exception_Table,
+      System_Exceptions,
+      System_Delay_Operations,
+      System_Exn_Flt,
+      System_Exn_Int,
+      System_Exn_LFlt,
+      System_Exn_LInt,
+      System_Exn_LLF,
+      System_Exn_LLI,
+      System_Exn_SFlt,
+      System_Exn_SInt,
+      System_Exn_SSI,
+      System_Exp_Flt,
+      System_Exp_Int,
+      System_Exp_LFlt,
+      System_Exp_LInt,
+      System_Exp_LLF,
+      System_Exp_LLI,
+      System_Exp_LLU,
+      System_Exp_Mod,
+      System_Exp_SFlt,
+      System_Exp_SInt,
+      System_Exp_SSI,
+      System_Exp_Uns,
+      System_Fat_Flt,
+      System_Fat_LFlt,
+      System_Fat_LLF,
+      System_Fat_SFlt,
+      System_Finalization_Implementation,
+      System_Finalization_Root,
+      System_Fore,
+      System_Img_Bool,
+      System_Img_Char,
+      System_Img_Dec,
+      System_Img_Enum,
+      System_Img_Int,
+      System_Img_LLD,
+      System_Img_LLI,
+      System_Img_LLU,
+      System_Img_Name,
+      System_Img_Real,
+      System_Img_Uns,
+      System_Img_WChar,
+      System_Interrupts,
+      System_Machine_Code,
+      System_Mantissa,
+      System_Pack_03,
+      System_Pack_05,
+      System_Pack_06,
+      System_Pack_07,
+      System_Pack_09,
+      System_Pack_10,
+      System_Pack_11,
+      System_Pack_12,
+      System_Pack_13,
+      System_Pack_14,
+      System_Pack_15,
+      System_Pack_17,
+      System_Pack_18,
+      System_Pack_19,
+      System_Pack_20,
+      System_Pack_21,
+      System_Pack_22,
+      System_Pack_23,
+      System_Pack_24,
+      System_Pack_25,
+      System_Pack_26,
+      System_Pack_27,
+      System_Pack_28,
+      System_Pack_29,
+      System_Pack_30,
+      System_Pack_31,
+      System_Pack_33,
+      System_Pack_34,
+      System_Pack_35,
+      System_Pack_36,
+      System_Pack_37,
+      System_Pack_38,
+      System_Pack_39,
+      System_Pack_40,
+      System_Pack_41,
+      System_Pack_42,
+      System_Pack_43,
+      System_Pack_44,
+      System_Pack_45,
+      System_Pack_46,
+      System_Pack_47,
+      System_Pack_48,
+      System_Pack_49,
+      System_Pack_50,
+      System_Pack_51,
+      System_Pack_52,
+      System_Pack_53,
+      System_Pack_54,
+      System_Pack_55,
+      System_Pack_56,
+      System_Pack_57,
+      System_Pack_58,
+      System_Pack_59,
+      System_Pack_60,
+      System_Pack_61,
+      System_Pack_62,
+      System_Pack_63,
+      System_Parameters,
+      System_Partition_Interface,
+      System_Pool_Global,
+      System_Pool_Empty,
+      System_Pool_Local,
+      System_Pool_Size,
+      System_RPC,
+      System_Scalar_Values,
+      System_Secondary_Stack,
+      System_Shared_Storage,
+      System_Soft_Links,
+      System_Standard_Library,
+      System_Storage_Elements,
+      System_Storage_Pools,
+      System_Stream_Attributes,
+      System_String_Ops,
+      System_String_Ops_Concat_3,
+      System_String_Ops_Concat_4,
+      System_String_Ops_Concat_5,
+      System_Task_Info,
+      System_Tasking,
+      System_Unsigned_Types,
+      System_Val_Bool,
+      System_Val_Char,
+      System_Val_Dec,
+      System_Val_Enum,
+      System_Val_Int,
+      System_Val_LLD,
+      System_Val_LLI,
+      System_Val_LLU,
+      System_Val_Name,
+      System_Val_Real,
+      System_Val_Uns,
+      System_Val_WChar,
+      System_Vax_Float_Operations,
+      System_Version_Control,
+      System_VMS_Exception_Table,
+      System_WCh_StW,
+      System_WCh_WtS,
+      System_Wid_Bool,
+      System_Wid_Char,
+      System_Wid_Enum,
+      System_Wid_LLI,
+      System_Wid_LLU,
+      System_Wid_Name,
+      System_Wid_WChar,
+      System_WWd_Char,
+      System_WWd_Enum,
+      System_WWd_Wchar,
+
+      --  Children of System.Tasking
+
+      System_Tasking_Async_Delays,
+      System_Tasking_Async_Delays_Enqueue_Calendar,
+      System_Tasking_Async_Delays_Enqueue_RT,
+      System_Tasking_Protected_Objects,
+      System_Tasking_Protected_Objects_Entries,
+      System_Tasking_Protected_Objects_Operations,
+      System_Tasking_Protected_Objects_Single_Entry,
+      System_Tasking_Restricted_Stages,
+      System_Tasking_Rendezvous,
+      System_Tasking_Stages);
+
+   subtype Ada_Child is RTU_Id
+     range Ada_Calendar .. Ada_Wide_Text_IO_Modular_IO;
+   --  Range of values for children or grand-children of Ada
+
+   subtype Ada_Calendar_Child is Ada_Child
+     range Ada_Calendar_Delays .. Ada_Calendar_Delays;
+   --  Range of values for children of Ada.Calendar
+
+   subtype Ada_Finalization_Child is Ada_Child range
+     Ada_Finalization_List_Controller .. Ada_Finalization_List_Controller;
+   --  Range of values for children of Ada.Finalization
+
+   subtype Ada_Real_Time_Child is Ada_Child
+     range Ada_Real_Time_Delays .. Ada_Real_Time_Delays;
+   --  Range of values for children of Ada.Real_Time
+
+   subtype Ada_Streams_Child is Ada_Child
+     range Ada_Streams_Stream_IO .. Ada_Streams_Stream_IO;
+
+   subtype Ada_Text_IO_Child is Ada_Child
+     range Ada_Text_IO_Decimal_IO .. Ada_Text_IO_Modular_IO;
+   --  Range of values for children of Ada.Text_IO
+
+   subtype Ada_Wide_Text_IO_Child is Ada_Child
+     range Ada_Wide_Text_IO_Decimal_IO .. Ada_Wide_Text_IO_Modular_IO;
+   --  Range of values for children of Ada.Text_IO
+
+   subtype Interfaces_Child is RTU_Id
+     range Interfaces_CPP .. Interfaces_Packed_Decimal;
+   --  Range of values for children of Interfaces
+
+   subtype System_Child is RTU_Id
+     range System_Arith_64 .. System_Tasking_Stages;
+   --  Range of values for children or grandchildren of System
+
+   subtype System_Tasking_Child is System_Child
+     range System_Tasking_Async_Delays .. System_Tasking_Stages;
+   --  Range of values for children of System.Tasking
+
+   subtype System_Tasking_Protected_Objects_Child is System_Tasking_Child
+     range System_Tasking_Protected_Objects_Entries ..
+       System_Tasking_Protected_Objects_Single_Entry;
+   --  Range of values for children of System.Tasking.Protected_Objects
+
+   subtype System_Tasking_Restricted_Child is System_Tasking_Child
+     range System_Tasking_Restricted_Stages ..
+       System_Tasking_Restricted_Stages;
+   --  Range of values for children of System.Tasking.Restricted
+
+   subtype System_Tasking_Async_Delays_Child is System_Tasking_Child
+     range System_Tasking_Async_Delays_Enqueue_Calendar ..
+       System_Tasking_Async_Delays_Enqueue_RT;
+   --  Range of values for children of System.Tasking.Async_Delays
+
+   --------------------------
+   -- Runtime Entity Table --
+   --------------------------
+
+   --  This is the enumeration type used to define the argument passed to
+   --  the RTE function. The name must exactly match the name of the entity
+   --  involved, and in the case of a package entity, this name must uniquely
+   --  imply the package containing the entity.
+
+   --  As far as possible, we avoid duplicate names in runtime packages, so
+   --  that the name RE_nnn uniquely identifies the entity nnn. In some cases,
+   --  it is impossible to avoid such duplication because the names come from
+   --  RM defined packages. In such cases, the name is of the form RO_XX_nnn
+   --  where XX is two letters used to differentiate the multiple occurrences
+   --  of the name xx, and nnn is the entity name.
+
+   --  Note that not all entities in the units contained in the run-time unit
+   --  table are included in the following table, only those that actually
+   --  have to be referenced from generated code.
+
+   --  Note on RE_Null. This value is used as a null entry where an RE_Id
+   --  value is required syntactically, but no real entry is required or
+   --  needed. Use of this value will cause a fatal error in an RTE call.
+
+   type RE_Id is (
+
+     RE_Null,
+
+     RE_Code_Loc,                        -- Ada.Exceptions
+     RE_Current_Target_Exception,        -- Ada.Exceptions (JGNAT use only)
+     RE_Exception_Id,                    -- Ada.Exceptions
+     RE_Exception_Information,           -- Ada.Exceptions
+     RE_Exception_Message,               -- Ada.Exceptions
+     RE_Exception_Name_Simple,           -- Ada.Exceptions
+     RE_Exception_Occurrence,            -- Ada.Exceptions
+     RE_Null_Id,                         -- Ada.Exceptions
+     RE_Null_Occurrence,                 -- Ada.Exceptions
+     RE_Poll,                            -- Ada.Exceptions
+     RE_Raise_Exception,                 -- Ada.Exceptions
+     RE_Raise_Exception_Always,          -- Ada.Exceptions
+     RE_Reraise_Occurrence,              -- Ada.Exceptions
+     RE_Reraise_Occurrence_Always,       -- Ada.Exceptions
+     RE_Reraise_Occurrence_No_Defer,     -- Ada.Exceptions
+     RE_Save_Occurrence,                 -- Ada.Exceptions
+
+     RE_Simple_List_Controller,          -- Ada.Finalization.List_Controller
+     RE_List_Controller,                 -- Ada.Finalization.List_Controller
+
+     RE_Interrupt_Id,                    -- Ada.Interrupts
+
+     RE_Root_Stream_Type,                -- Ada.Streams
+     RE_Stream_Element,                  -- Ada.Streams
+     RE_Stream_Element_Offset,           -- Ada.Streams
+     RE_Stream_Element_Array,            -- Ada.Streams
+
+     RE_Stream_Access,                   -- Ada.Streams.Stream_IO
+
+     RE_CW_Membership,                   -- Ada.Tags
+     RE_DT_Entry_Size,                   -- Ada.Tags
+     RE_DT_Prologue_Size,                -- Ada.Tags
+     RE_External_Tag,                    -- Ada.Tags
+     RE_Get_Expanded_Name,               -- Ada.Tags
+     RE_Get_External_Tag,                -- Ada.Tags
+     RE_Get_Prim_Op_Address,             -- Ada.Tags
+     RE_Get_RC_Offset,                   -- Ada.Tags
+     RE_Get_Remotely_Callable,           -- Ada.Tags
+     RE_Get_TSD,                         -- Ada.Tags
+     RE_Inherit_DT,                      -- Ada.Tags
+     RE_Inherit_TSD,                     -- Ada.Tags
+     RE_Internal_Tag,                    -- Ada.Tags
+     RE_Register_Tag,                    -- Ada.Tags
+     RE_Set_Expanded_Name,               -- Ada.Tags
+     RE_Set_External_Tag,                -- Ada.Tags
+     RE_Set_Prim_Op_Address,             -- Ada.Tags
+     RE_Set_RC_Offset,                   -- Ada.Tags
+     RE_Set_Remotely_Callable,           -- Ada.Tags
+     RE_Set_TSD,                         -- Ada.Tags
+     RE_Tag_Error,                       -- Ada.Tags
+     RE_TSD_Entry_Size,                  -- Ada.Tags
+     RE_TSD_Prologue_Size,               -- Ada.Tags
+     RE_Tag,                             -- Ada.Tags
+     RE_Address_Array,                   -- Ada.Tags
+
+     RE_Current_Task,                    -- Ada.Task_Identification
+     RO_AT_Task_ID,                      -- Ada.Task_Identification
+
+     RO_CA_Time,                         -- Ada.Calendar
+
+     RO_CA_Delay_For,                    -- Ada.Calendar.Delays
+     RO_CA_Delay_Until,                  -- Ada.Calendar.Delays
+     RO_CA_To_Duration,                  -- Ada.Calendar.Delays
+
+     RO_RT_Time,                         -- Ada.Real_Time
+
+     RO_RT_Delay_Until,                  -- Ada.Real_Time.Delays
+     RO_RT_To_Duration,                  -- Ada.Real_Time.Delays
+
+     RE_Integer_64,                      -- Interfaces
+     RE_Unsigned_8,                      -- Interfaces
+     RE_Unsigned_16,                     -- Interfaces
+     RE_Unsigned_32,                     -- Interfaces
+     RE_Unsigned_64,                     -- Interfaces
+
+     RE_Vtable_Ptr,                      -- Interfaces.CPP
+     RE_Displaced_This,                  -- Interfaces.CPP
+     RE_CPP_CW_Membership,               -- Interfaces.CPP
+     RE_CPP_DT_Entry_Size,               -- Interfaces.CPP
+     RE_CPP_DT_Prologue_Size,            -- Interfaces.CPP
+     RE_CPP_Get_Expanded_Name,           -- Interfaces.CPP
+     RE_CPP_Get_External_Tag,            -- Interfaces.CPP
+     RE_CPP_Get_Prim_Op_Address,         -- Interfaces.CPP
+     RE_CPP_Get_RC_Offset,               -- Interfaces.CPP
+     RE_CPP_Get_Remotely_Callable,       -- Interfaces.CPP
+     RE_CPP_Get_TSD,                     -- Interfaces.CPP
+     RE_CPP_Inherit_DT,                  -- Interfaces.CPP
+     RE_CPP_Inherit_TSD,                 -- Interfaces.CPP
+     RE_CPP_Register_Tag,                -- Interfaces.CPP
+     RE_CPP_Set_Expanded_Name,           -- Interfaces.CPP
+     RE_CPP_Set_External_Tag,            -- Interfaces.CPP
+     RE_CPP_Set_Prim_Op_Address,         -- Interfaces.CPP
+     RE_CPP_Set_RC_Offset,               -- Interfaces.CPP
+     RE_CPP_Set_Remotely_Callable,       -- Interfaces.CPP
+     RE_CPP_Set_TSD,                     -- Interfaces.CPP
+     RE_CPP_TSD_Entry_Size,              -- Interfaces.CPP
+     RE_CPP_TSD_Prologue_Size,           -- Interfaces.CPP
+
+     RE_Packed_Size,                     -- Interfaces.Packed_Decimal
+     RE_Packed_To_Int32,                 -- Interfaces.Packed_Decimal
+     RE_Packed_To_Int64,                 -- Interfaces.Packed_Decimal
+     RE_Int32_To_Packed,                 -- Interfaces.Packed_Decimal
+     RE_Int64_To_Packed,                 -- Interfaces.Packed_Decimal
+
+     RE_Address,                         -- System
+     RE_Any_Priority,                    -- System
+     RE_Bit_Order,                       -- System
+     RE_Default_Priority,                -- System
+     RE_High_Order_First,                -- System
+     RE_Interrupt_Priority,              -- System
+     RE_Lib_Stop,                        -- System
+     RE_Low_Order_First,                 -- System
+     RE_Max_Interrupt_Priority,          -- System
+     RE_Max_Priority,                    -- System
+     RE_Null_Address,                    -- System
+     RE_Priority,                        -- System
+
+     RE_Add_With_Ovflo_Check,            -- System.Arith_64
+     RE_Double_Divide,                   -- System.Arith_64
+     RE_Multiply_With_Ovflo_Check,       -- System.Arith_64
+     RE_Scaled_Divide,                   -- System.Arith_64
+     RE_Subtract_With_Ovflo_Check,       -- System.Arith_64
+
+     RE_Create_AST_Handler,              -- System.AST_Handling
+
+     RE_Raise_Assert_Failure,            -- System.Assertions
+
+     RE_AST_Handler,                     -- System.Aux_DEC
+     RE_Import_Value,                    -- System.Aux_DEC
+     RE_No_AST_Handler,                  -- System.Aux_DEC
+     RE_Type_Class,                      -- System.Aux_DEC
+     RE_Type_Class_Enumeration,          -- System.Aux_DEC
+     RE_Type_Class_Integer,              -- System.Aux_DEC
+     RE_Type_Class_Fixed_Point,          -- System.Aux_DEC
+     RE_Type_Class_Floating_Point,       -- System.Aux_DEC
+     RE_Type_Class_Array,                -- System.Aux_DEC
+     RE_Type_Class_Record,               -- System.Aux_DEC
+     RE_Type_Class_Access,               -- System.Aux_DEC
+     RE_Type_Class_Task,                 -- System.Aux_DEC
+     RE_Type_Class_Address,              -- System.Aux_DEC
+
+     RE_Bit_And,                         -- System.Bit_Ops
+     RE_Bit_Eq,                          -- System.Bit_Ops
+     RE_Bit_Not,                         -- System.Bit_Ops
+     RE_Bit_Or,                          -- System.Bit_Ops
+     RE_Bit_Xor,                         -- System.Bit_Ops
+
+     RE_Checked_Pool,                    -- System.Checked_Pools
+
+     RE_Register_Exception,              -- System.Exception_Table
+
+     RE_All_Others_Id,                   -- System.Exceptions
+     RE_Handler_Record,                  -- System.Exceptions
+     RE_Handler_Record_Ptr,              -- System.Exceptions
+     RE_Others_Id,                       -- System.Exceptions
+     RE_Subprogram_Descriptor,           -- System.Exceptions
+     RE_Subprogram_Descriptor_0,         -- System.Exceptions
+     RE_Subprogram_Descriptor_1,         -- System.Exceptions
+     RE_Subprogram_Descriptor_2,         -- System.Exceptions
+     RE_Subprogram_Descriptor_3,         -- System.Exceptions
+     RE_Subprogram_Descriptor_List,      -- System.Exceptions
+     RE_Subprogram_Descriptor_Ptr,       -- System.Exceptions
+     RE_Subprogram_Descriptors_Record,   -- System.Exceptions
+     RE_Subprogram_Descriptors_Ptr,      -- System.Exceptions
+
+     RE_Exn_Float,                       -- System.Exn_Flt
+
+     RE_Exn_Integer,                     -- System.Exn_Int
+
+     RE_Exn_Long_Float,                  -- System.Exn_LFlt
+
+     RE_Exn_Long_Integer,                -- System.Exn_LInt
+
+     RE_Exn_Long_Long_Float,             -- System.Exn_LLF
+
+     RE_Exn_Long_Long_Integer,           -- System.Exn_LLI
+
+     RE_Exn_Short_Float,                 -- System.Exn_SFlt
+
+     RE_Exn_Short_Integer,               -- System.Exn_SInt
+
+     RE_Exn_Short_Short_Integer,         -- System.Exn_SSI
+
+     RE_Exp_Float,                       -- System.Exp_Flt
+
+     RE_Exp_Integer,                     -- System.Exp_Int
+
+     RE_Exp_Long_Float,                  -- System.Exp_LFlt
+
+     RE_Exp_Long_Integer,                -- System.Exp_LInt
+
+     RE_Exp_Long_Long_Float,             -- System.Exp_LLF
+
+     RE_Exp_Long_Long_Integer,           -- System.Exp_LLI
+
+     RE_Exp_Long_Long_Unsigned,          -- System.Exp_LLU
+
+     RE_Exp_Modular,                     -- System.Exp_Mod
+
+     RE_Exp_Short_Float,                 -- System.Exp_SFlt
+
+     RE_Exp_Short_Integer,               -- System.Exp_SInt
+
+     RE_Exp_Short_Short_Integer,         -- System.Exp_SSI
+
+     RE_Exp_Unsigned,                    -- System.Exp_Uns
+
+     RE_Fat_Float,                       -- System.Fat_Flt
+
+     RE_Fat_Long_Float,                  -- System.Fat_LFlt
+
+     RE_Fat_Long_Long_Float,             -- System.Fat_LLF
+
+     RE_Fat_Short_Float,                 -- System.Fat_SFlt
+
+     RE_Attach_To_Final_List,            -- System.Finalization_Implementation
+     RE_Finalize_List,                   -- System.Finalization_Implementation
+     RE_Finalize_One,                    -- System.Finalization_Implementation
+     RE_Global_Final_List,               -- System.Finalization_Implementation
+     RE_Record_Controller,               -- System.Finalization_Implementation
+     RE_Limited_Record_Controller,       -- System.Finalization_Implementation
+     RE_Deep_Tag_Initialize,             -- System.Finalization_Implementation
+     RE_Deep_Tag_Adjust,                 -- System.Finalization_Implementation
+     RE_Deep_Tag_Finalize,               -- System.Finalization_Implementation
+     RE_Deep_Tag_Attach,                 -- System.Finalization_Implementation
+     RE_Deep_Rec_Initialize,             -- System.Finalization_Implementation
+     RE_Deep_Rec_Adjust,                 -- System.Finalization_Implementation
+     RE_Deep_Rec_Finalize,               -- System.Finalization_Implementation
+
+     RE_Root_Controlled,                 -- System.Finalization_Root
+     RE_Finalizable,                     -- System.Finalization_Root
+     RE_Finalizable_Ptr,                 -- System.Finalization_Root
+
+     RE_Fore,                            -- System.Fore
+
+     RE_Image_Boolean,                   -- System.Img_Bool
+
+     RE_Image_Character,                 -- System.Img_Char
+
+     RE_Image_Decimal,                   -- System.Img_Dec
+
+     RE_Image_Enumeration_8,             -- System.Img_Enum
+     RE_Image_Enumeration_16,            -- System.Img_Enum
+     RE_Image_Enumeration_32,            -- System.Img_Enum
+
+     RE_Image_Integer,                   -- System.Img_Int
+
+     RE_Image_Long_Long_Decimal,         -- System.Img_LLD
+
+     RE_Image_Long_Long_Integer,         -- System.Img_LLI
+
+     RE_Image_Long_Long_Unsigned,        -- System.Img_LLU
+
+     RE_Image_Ordinary_Fixed_Point,      -- System.Img_Real
+     RE_Image_Floating_Point,            -- System.Img_Real
+
+     RE_Image_Unsigned,                  -- System.Img_Uns
+
+     RE_Image_Wide_Character,            -- System.Img_WChar
+
+     RE_Bind_Interrupt_To_Entry,         -- System.Interrupts
+     RE_Default_Interrupt_Priority,      -- System.Interrupts
+     RE_Dynamic_Interrupt_Protection,    -- System.Interrupts
+     RE_Install_Handlers,                -- System.Interrupts
+     RE_Register_Interrupt_Handler,      -- System.Interrupts
+     RE_Static_Interrupt_Protection,     -- System.Interrupts
+
+     RE_Asm_Insn,                        -- System.Machine_Code
+     RE_Asm_Input_Operand,               -- System.Machine_Code
+     RE_Asm_Output_Operand,              -- System.Machine_Code
+
+     RE_Mantissa_Value,                  -- System_Mantissa
+
+     RE_Bits_03,                         -- System.Pack_03
+     RE_Get_03,                          -- System.Pack_03
+     RE_Set_03,                          -- System.Pack_03
+
+     RE_Bits_05,                         -- System.Pack_05
+     RE_Get_05,                          -- System.Pack_05
+     RE_Set_05,                          -- System.Pack_05
+
+     RE_Bits_06,                         -- System.Pack_06
+     RE_Get_06,                          -- System.Pack_06
+     RE_GetU_06,                         -- System.Pack_06
+     RE_Set_06,                          -- System.Pack_06
+     RE_SetU_06,                         -- System.Pack_06
+
+     RE_Bits_07,                         -- System.Pack_07
+     RE_Get_07,                          -- System.Pack_07
+     RE_Set_07,                          -- System.Pack_07
+
+     RE_Bits_09,                         -- System.Pack_09
+     RE_Get_09,                          -- System.Pack_09
+     RE_Set_09,                          -- System.Pack_09
+
+     RE_Bits_10,                         -- System.Pack_10
+     RE_Get_10,                          -- System.Pack_10
+     RE_GetU_10,                         -- System.Pack_10
+     RE_Set_10,                          -- System.Pack_10
+     RE_SetU_10,                         -- System.Pack_10
+
+     RE_Bits_11,                         -- System.Pack_11
+     RE_Get_11,                          -- System.Pack_11
+     RE_Set_11,                          -- System.Pack_11
+
+     RE_Bits_12,                         -- System.Pack_12
+     RE_Get_12,                          -- System.Pack_12
+     RE_GetU_12,                         -- System.Pack_12
+     RE_Set_12,                          -- System.Pack_12
+     RE_SetU_12,                         -- System.Pack_12
+
+     RE_Bits_13,                         -- System.Pack_13
+     RE_Get_13,                          -- System.Pack_13
+     RE_Set_13,                          -- System.Pack_13
+
+     RE_Bits_14,                         -- System.Pack_14
+     RE_Get_14,                          -- System.Pack_14
+     RE_GetU_14,                         -- System.Pack_14
+     RE_Set_14,                          -- System.Pack_14
+     RE_SetU_14,                         -- System.Pack_14
+
+     RE_Bits_15,                         -- System.Pack_15
+     RE_Get_15,                          -- System.Pack_15
+     RE_Set_15,                          -- System.Pack_15
+
+     RE_Bits_17,                         -- System.Pack_17
+     RE_Get_17,                          -- System.Pack_17
+     RE_Set_17,                          -- System.Pack_17
+
+     RE_Bits_18,                         -- System.Pack_18
+     RE_Get_18,                          -- System.Pack_18
+     RE_GetU_18,                         -- System.Pack_18
+     RE_Set_18,                          -- System.Pack_18
+     RE_SetU_18,                         -- System.Pack_18
+
+     RE_Bits_19,                         -- System.Pack_19
+     RE_Get_19,                          -- System.Pack_19
+     RE_Set_19,                          -- System.Pack_19
+
+     RE_Bits_20,                         -- System.Pack_20
+     RE_Get_20,                          -- System.Pack_20
+     RE_GetU_20,                         -- System.Pack_20
+     RE_Set_20,                          -- System.Pack_20
+     RE_SetU_20,                         -- System.Pack_20
+
+     RE_Bits_21,                         -- System.Pack_21
+     RE_Get_21,                          -- System.Pack_21
+     RE_Set_21,                          -- System.Pack_21
+
+     RE_Bits_22,                         -- System.Pack_22
+     RE_Get_22,                          -- System.Pack_22
+     RE_GetU_22,                         -- System.Pack_22
+     RE_Set_22,                          -- System.Pack_22
+     RE_SetU_22,                         -- System.Pack_22
+
+     RE_Bits_23,                         -- System.Pack_23
+     RE_Get_23,                          -- System.Pack_23
+     RE_Set_23,                          -- System.Pack_23
+
+     RE_Bits_24,                         -- System.Pack_24
+     RE_Get_24,                          -- System.Pack_24
+     RE_GetU_24,                         -- System.Pack_24
+     RE_Set_24,                          -- System.Pack_24
+     RE_SetU_24,                         -- System.Pack_24
+
+     RE_Bits_25,                         -- System.Pack_25
+     RE_Get_25,                          -- System.Pack_25
+     RE_Set_25,                          -- System.Pack_25
+
+     RE_Bits_26,                         -- System.Pack_26
+     RE_Get_26,                          -- System.Pack_26
+     RE_GetU_26,                         -- System.Pack_26
+     RE_Set_26,                          -- System.Pack_26
+     RE_SetU_26,                         -- System.Pack_26
+
+     RE_Bits_27,                         -- System.Pack_27
+     RE_Get_27,                          -- System.Pack_27
+     RE_Set_27,                          -- System.Pack_27
+
+     RE_Bits_28,                         -- System.Pack_28
+     RE_Get_28,                          -- System.Pack_28
+     RE_GetU_28,                         -- System.Pack_28
+     RE_Set_28,                          -- System.Pack_28
+     RE_SetU_28,                         -- System.Pack_28
+
+     RE_Bits_29,                         -- System.Pack_29
+     RE_Get_29,                          -- System.Pack_29
+     RE_Set_29,                          -- System.Pack_29
+
+     RE_Bits_30,                         -- System.Pack_30
+     RE_Get_30,                          -- System.Pack_30
+     RE_GetU_30,                         -- System.Pack_30
+     RE_Set_30,                          -- System.Pack_30
+     RE_SetU_30,                         -- System.Pack_30
+
+     RE_Bits_31,                         -- System.Pack_31
+     RE_Get_31,                          -- System.Pack_31
+     RE_Set_31,                          -- System.Pack_31
+
+     RE_Bits_33,                         -- System.Pack_33
+     RE_Get_33,                          -- System.Pack_33
+     RE_Set_33,                          -- System.Pack_33
+
+     RE_Bits_34,                         -- System.Pack_34
+     RE_Get_34,                          -- System.Pack_34
+     RE_GetU_34,                         -- System.Pack_34
+     RE_Set_34,                          -- System.Pack_34
+     RE_SetU_34,                         -- System.Pack_34
+
+     RE_Bits_35,                         -- System.Pack_35
+     RE_Get_35,                          -- System.Pack_35
+     RE_Set_35,                          -- System.Pack_35
+
+     RE_Bits_36,                         -- System.Pack_36
+     RE_Get_36,                          -- System.Pack_36
+     RE_GetU_36,                         -- System.Pack_36
+     RE_Set_36,                          -- System.Pack_36
+     RE_SetU_36,                         -- System.Pack_36
+
+     RE_Bits_37,                         -- System.Pack_37
+     RE_Get_37,                          -- System.Pack_37
+     RE_Set_37,                          -- System.Pack_37
+
+     RE_Bits_38,                         -- System.Pack_38
+     RE_Get_38,                          -- System.Pack_38
+     RE_GetU_38,                         -- System.Pack_38
+     RE_Set_38,                          -- System.Pack_38
+     RE_SetU_38,                         -- System.Pack_38
+
+     RE_Bits_39,                         -- System.Pack_39
+     RE_Get_39,                          -- System.Pack_39
+     RE_Set_39,                          -- System.Pack_39
+
+     RE_Bits_40,                         -- System.Pack_40
+     RE_Get_40,                          -- System.Pack_40
+     RE_GetU_40,                         -- System.Pack_40
+     RE_Set_40,                          -- System.Pack_40
+     RE_SetU_40,                         -- System.Pack_40
+
+     RE_Bits_41,                         -- System.Pack_41
+     RE_Get_41,                          -- System.Pack_41
+     RE_Set_41,                          -- System.Pack_41
+
+     RE_Bits_42,                         -- System.Pack_42
+     RE_Get_42,                          -- System.Pack_42
+     RE_GetU_42,                         -- System.Pack_42
+     RE_Set_42,                          -- System.Pack_42
+     RE_SetU_42,                         -- System.Pack_42
+
+     RE_Bits_43,                         -- System.Pack_43
+     RE_Get_43,                          -- System.Pack_43
+     RE_Set_43,                          -- System.Pack_43
+
+     RE_Bits_44,                         -- System.Pack_44
+     RE_Get_44,                          -- System.Pack_44
+     RE_GetU_44,                         -- System.Pack_44
+     RE_Set_44,                          -- System.Pack_44
+     RE_SetU_44,                         -- System.Pack_44
+
+     RE_Bits_45,                         -- System.Pack_45
+     RE_Get_45,                          -- System.Pack_45
+     RE_Set_45,                          -- System.Pack_45
+
+     RE_Bits_46,                         -- System.Pack_46
+     RE_Get_46,                          -- System.Pack_46
+     RE_GetU_46,                         -- System.Pack_46
+     RE_Set_46,                          -- System.Pack_46
+     RE_SetU_46,                         -- System.Pack_46
+
+     RE_Bits_47,                         -- System.Pack_47
+     RE_Get_47,                          -- System.Pack_47
+     RE_Set_47,                          -- System.Pack_47
+
+     RE_Bits_48,                         -- System.Pack_48
+     RE_Get_48,                          -- System.Pack_48
+     RE_GetU_48,                         -- System.Pack_48
+     RE_Set_48,                          -- System.Pack_48
+     RE_SetU_48,                         -- System.Pack_48
+
+     RE_Bits_49,                         -- System.Pack_49
+     RE_Get_49,                          -- System.Pack_49
+     RE_Set_49,                          -- System.Pack_49
+
+     RE_Bits_50,                         -- System.Pack_50
+     RE_Get_50,                          -- System.Pack_50
+     RE_GetU_50,                         -- System.Pack_50
+     RE_Set_50,                          -- System.Pack_50
+     RE_SetU_50,                         -- System.Pack_50
+
+     RE_Bits_51,                         -- System.Pack_51
+     RE_Get_51,                          -- System.Pack_51
+     RE_Set_51,                          -- System.Pack_51
+
+     RE_Bits_52,                         -- System.Pack_52
+     RE_Get_52,                          -- System.Pack_52
+     RE_GetU_52,                         -- System.Pack_52
+     RE_Set_52,                          -- System.Pack_52
+     RE_SetU_52,                         -- System.Pack_52
+
+     RE_Bits_53,                         -- System.Pack_53
+     RE_Get_53,                          -- System.Pack_53
+     RE_Set_53,                          -- System.Pack_53
+
+     RE_Bits_54,                         -- System.Pack_54
+     RE_Get_54,                          -- System.Pack_54
+     RE_GetU_54,                         -- System.Pack_54
+     RE_Set_54,                          -- System.Pack_54
+     RE_SetU_54,                         -- System.Pack_54
+
+     RE_Bits_55,                         -- System.Pack_55
+     RE_Get_55,                          -- System.Pack_55
+     RE_Set_55,                          -- System.Pack_55
+
+     RE_Bits_56,                         -- System.Pack_56
+     RE_Get_56,                          -- System.Pack_56
+     RE_GetU_56,                         -- System.Pack_56
+     RE_Set_56,                          -- System.Pack_56
+     RE_SetU_56,                         -- System.Pack_56
+
+     RE_Bits_57,                         -- System.Pack_57
+     RE_Get_57,                          -- System.Pack_57
+     RE_Set_57,                          -- System.Pack_57
+
+     RE_Bits_58,                         -- System.Pack_58
+     RE_Get_58,                          -- System.Pack_58
+     RE_GetU_58,                         -- System.Pack_58
+     RE_Set_58,                          -- System.Pack_58
+     RE_SetU_58,                         -- System.Pack_58
+
+     RE_Bits_59,                         -- System.Pack_59
+     RE_Get_59,                          -- System.Pack_59
+     RE_Set_59,                          -- System.Pack_59
+
+     RE_Bits_60,                         -- System.Pack_60
+     RE_Get_60,                          -- System.Pack_60
+     RE_GetU_60,                         -- System.Pack_60
+     RE_Set_60,                          -- System.Pack_60
+     RE_SetU_60,                         -- System.Pack_60
+
+     RE_Bits_61,                         -- System.Pack_61
+     RE_Get_61,                          -- System.Pack_61
+     RE_Set_61,                          -- System.Pack_61
+
+     RE_Bits_62,                         -- System.Pack_62
+     RE_Get_62,                          -- System.Pack_62
+     RE_GetU_62,                         -- System.Pack_62
+     RE_Set_62,                          -- System.Pack_62
+     RE_SetU_62,                         -- System.Pack_62
+
+     RE_Bits_63,                         -- System.Pack_63
+     RE_Get_63,                          -- System.Pack_63
+     RE_Set_63,                          -- System.Pack_63
+
+     RE_Adjust_Storage_Size,             -- System_Parameters
+     RE_Default_Stack_Size,              -- System.Parameters
+     RE_Garbage_Collected,               -- System.Parameters
+     RE_Size_Type,                       -- System.Parameters
+     RE_Unspecified_Size,                -- System.Parameters
+
+     RE_Get_Active_Partition_Id,         -- System.Partition_Interface
+     RE_Get_Passive_Partition_Id,        -- System.Partition_Interface
+     RE_Get_Local_Partition_Id,          -- System.Partition_Interface
+     RE_Get_RCI_Package_Receiver,        -- System.Partition_Interface
+     RE_Get_Unique_Remote_Pointer,       -- System.Partition_Interface
+     RE_RACW_Stub_Type,                  -- System.Partition_Interface
+     RE_RACW_Stub_Type_Access,           -- System.Partition_Interface
+     RE_Raise_Program_Error_For_E_4_18,  -- System.Partition_Interface
+     RE_Raise_Program_Error_Unknown_Tag, -- System.Partition_Interface
+     RE_Register_Passive_Package,        -- System.Partition_Interface
+     RE_Register_Receiving_Stub,         -- System.Partition_Interface
+     RE_RCI_Info,                        -- System.Partition_Interface
+     RE_Subprogram_Id,                   -- System.Partition_Interface
+
+     RE_Global_Pool_Object,              -- System.Pool_Global
+
+     RE_Unbounded_Reclaim_Pool,          -- System.Pool_Local
+
+     RE_Stack_Bounded_Pool,              -- System.Pool_Size
+
+     RE_Do_Apc,                          -- System.RPC
+     RE_Do_Rpc,                          -- System.RPC
+     RE_Params_Stream_Type,              -- System.RPC
+     RE_Partition_ID,                    -- System.RPC
+     RE_RPC_Receiver,                    -- System.RPC
+
+     RE_IS_Is1,                          -- System.Scalar_Values
+     RE_IS_Is2,                          -- System.Scalar_Values
+     RE_IS_Is4,                          -- System.Scalar_Values
+     RE_IS_Is8,                          -- System.Scalar_Values
+     RE_IS_Iu1,                          -- System.Scalar_Values
+     RE_IS_Iu2,                          -- System.Scalar_Values
+     RE_IS_Iu4,                          -- System.Scalar_Values
+     RE_IS_Iu8,                          -- System.Scalar_Values
+     RE_IS_Isf,                          -- System.Scalar_Values
+     RE_IS_Ifl,                          -- System.Scalar_Values
+     RE_IS_Ilf,                          -- System.Scalar_Values
+     RE_IS_Ill,                          -- System.Scalar_Values
+
+     RE_Mark_Id,                         -- System.Secondary_Stack
+     RE_SS_Allocate,                     -- System.Secondary_Stack
+     RE_SS_Pool,                         -- System.Secondary_Stack
+     RE_SS_Mark,                         -- System.Secondary_Stack
+     RE_SS_Release,                      -- System.Secondary_Stack
+
+     RE_Shared_Var_Close,                -- System.Shared_Storage
+     RE_Shared_Var_Lock,                 -- System.Shared_Storage
+     RE_Shared_Var_ROpen,                -- System.Shared_Storage
+     RE_Shared_Var_Unlock,               -- System.Shared_Storage
+     RE_Shared_Var_WOpen,                -- System.Shared_Storage
+
+     RE_Abort_Undefer_Direct,            -- System.Standard_Library
+     RE_Exception_Data,                  -- System.Standard_Library
+     RE_Exception_Data_Ptr,              -- System.Standard_Library
+
+     RE_Integer_Address,                 -- System.Storage_Elements
+     RE_Storage_Offset,                  -- System.Storage_Elements
+     RE_Storage_Array,                   -- System.Storage_Elements
+     RE_To_Address,                      -- System.Storage_Elements
+
+     RE_Root_Storage_Pool,               -- System.Storage_Pools
+
+     RE_Thin_Pointer,                    -- System.Stream_Attributes
+     RE_Fat_Pointer,                     -- System.Stream_Attributes
+
+     RE_I_AD,                            -- System.Stream_Attributes
+     RE_I_AS,                            -- System.Stream_Attributes
+     RE_I_B,                             -- System.Stream_Attributes
+     RE_I_C,                             -- System.Stream_Attributes
+     RE_I_F,                             -- System.Stream_Attributes
+     RE_I_I,                             -- System.Stream_Attributes
+     RE_I_LF,                            -- System.Stream_Attributes
+     RE_I_LI,                            -- System.Stream_Attributes
+     RE_I_LLF,                           -- System.Stream_Attributes
+     RE_I_LLI,                           -- System.Stream_Attributes
+     RE_I_LLU,                           -- System.Stream_Attributes
+     RE_I_LU,                            -- System.Stream_Attributes
+     RE_I_SF,                            -- System.Stream_Attributes
+     RE_I_SI,                            -- System.Stream_Attributes
+     RE_I_SSI,                           -- System.Stream_Attributes
+     RE_I_SSU,                           -- System.Stream_Attributes
+     RE_I_SU,                            -- System.Stream_Attributes
+     RE_I_U,                             -- System.Stream_Attributes
+     RE_I_WC,                            -- System.Stream_Attributes
+
+     RE_W_AD,                            -- System.Stream_Attributes
+     RE_W_AS,                            -- System.Stream_Attributes
+     RE_W_B,                             -- System.Stream_Attributes
+     RE_W_C,                             -- System.Stream_Attributes
+     RE_W_F,                             -- System.Stream_Attributes
+     RE_W_I,                             -- System.Stream_Attributes
+     RE_W_LF,                            -- System.Stream_Attributes
+     RE_W_LI,                            -- System.Stream_Attributes
+     RE_W_LLF,                           -- System.Stream_Attributes
+     RE_W_LLI,                           -- System.Stream_Attributes
+     RE_W_LLU,                           -- System.Stream_Attributes
+     RE_W_LU,                            -- System.Stream_Attributes
+     RE_W_SF,                            -- System.Stream_Attributes
+     RE_W_SI,                            -- System.Stream_Attributes
+     RE_W_SSI,                           -- System.Stream_Attributes
+     RE_W_SSU,                           -- System.Stream_Attributes
+     RE_W_SU,                            -- System.Stream_Attributes
+     RE_W_U,                             -- System.Stream_Attributes
+     RE_W_WC,                            -- System.Stream_Attributes
+
+     RE_Str_Concat,                      -- System.String_Ops
+     RE_Str_Concat_CC,                   -- System.String_Ops
+     RE_Str_Concat_CS,                   -- System.String_Ops
+     RE_Str_Concat_SC,                   -- System.String_Ops
+     RE_Str_Equal,                       -- System.String_Ops
+     RE_Str_Normalize,                   -- System.String_Ops
+     RE_Wide_Str_Normalize,              -- System.String_Ops
+
+     RE_Str_Concat_3,                    -- System.String_Ops_Concat_3
+
+     RE_Str_Concat_4,                    -- System.String_Ops_Concat_4
+
+     RE_Str_Concat_5,                    -- System.String_Ops_Concat_5
+
+     RE_Free_Task_Image,                 -- System.Task_Info
+     RE_Task_Info_Type,                  -- System.Task_Info
+     RE_Task_Image_Type,                 -- System_Task_Info
+     RE_Unspecified_Task_Info,           -- System.Task_Info
+
+     RE_Library_Task_Level,              -- System.Tasking
+
+     RE_Task_Procedure_Access,           -- System.Tasking
+
+     RO_ST_Task_ID,                      -- System.Tasking
+
+     RE_Call_Modes,                      -- System.Tasking
+     RE_Simple_Call,                     -- System.Tasking
+     RE_Conditional_Call,                -- System.Tasking
+     RE_Asynchronous_Call,               -- System.Tasking
+     RE_Timed_Call,                      -- System.Tasking
+
+     RE_Task_List,                       -- System.Tasking
+
+     RE_Accept_Alternative,              -- System.Tasking
+     RE_Accept_List,                     -- System.Tasking
+     RE_Accept_List_Access,              -- System.Tasking
+     RE_Max_Select,                      -- System.Tasking
+     RE_Max_Task_Entry,                  -- System.Tasking
+     RE_No_Rendezvous,                   -- System.Tasking
+     RE_Null_Task_Entry,                 -- System.Tasking
+     RE_Positive_Select_Index,           -- System.Tasking
+     RE_Select_Index,                    -- System.Tasking
+     RE_Select_Modes,                    -- System.Tasking
+     RE_Else_Mode,                       -- System.Tasking
+     RE_Simple_Mode,                     -- System.Tasking
+     RE_Terminate_Mode,                  -- System.Tasking
+     RE_Delay_Mode,                      -- System.Tasking
+     RE_Task_Entry_Index,                -- System.Tasking
+     RE_Self,                            -- System.Tasking
+
+     RE_Master_Id,                       -- System.Tasking
+     RE_Unspecified_Priority,            -- System.Tasking
+
+     RE_Activation_Chain,                -- System.Tasking
+
+     RE_Abort_Defer,                     -- System.Soft_Links
+     RE_Abort_Undefer,                   -- System.Soft_Links
+     RE_Complete_Master,                 -- System.Soft_Links
+     RE_Current_Master,                  -- System.Soft_Links
+     RE_Enter_Master,                    -- System.Soft_Links
+     RE_Get_Current_Excep,               -- System.Soft_Links
+     RE_Get_GNAT_Exception,              -- System.Soft_Links
+     RE_Update_Exception,                -- System.Soft_Links
+
+     RE_Bits_1,                          -- System.Unsigned_Types
+     RE_Bits_2,                          -- System.Unsigned_Types
+     RE_Bits_4,                          -- System.Unsigned_Types
+     RE_Float_Unsigned,                  -- System.Unsigned_Types
+     RE_Long_Long_Unsigned,              -- System.Unsigned_Types
+     RE_Packed_Byte,                     -- System.Unsigned_Types
+     RE_Packed_Bytes1,                   -- System.Unsigned_Types
+     RE_Packed_Bytes2,                   -- System.Unsigned_Types
+     RE_Packed_Bytes4,                   -- System.Unsigned_Types
+     RE_Unsigned,                        -- System.Unsigned_Types
+
+     RE_Value_Boolean,                   -- System.Val_Bool
+
+     RE_Value_Character,                 -- System.Val_Char
+
+     RE_Value_Decimal,                   -- System.Val_Dec
+
+     RE_Value_Enumeration_8,             -- System.Val_Enum
+     RE_Value_Enumeration_16,            -- System.Val_Enum
+     RE_Value_Enumeration_32,            -- System.Val_Enum
+
+     RE_Value_Integer,                   -- System.Val_Int
+
+     RE_Value_Long_Long_Decimal,         -- System.Val_LLD
+
+     RE_Value_Long_Long_Integer,         -- System.Val_LLI
+
+     RE_Value_Long_Long_Unsigned,        -- System.Val_LLU
+
+     RE_Value_Real,                      -- System.Val_Real
+
+     RE_Value_Unsigned,                  -- System.Val_Uns
+
+     RE_Value_Wide_Character,            -- System.Val_WChar
+
+     RE_D,                               -- System.Vax_Float_Operations
+     RE_F,                               -- System.Vax_Float_Operations
+     RE_G,                               -- System.Vax_Float_Operations
+     RE_Q,                               -- System.Vax_Float_Operations
+     RE_S,                               -- System.Vax_Float_Operations
+     RE_T,                               -- System.Vax_Float_Operations
+
+     RE_D_To_G,                          -- System.Vax_Float_Operations
+     RE_F_To_G,                          -- System.Vax_Float_Operations
+     RE_F_To_Q,                          -- System.Vax_Float_Operations
+     RE_F_To_S,                          -- System.Vax_Float_Operations
+     RE_G_To_D,                          -- System.Vax_Float_Operations
+     RE_G_To_F,                          -- System.Vax_Float_Operations
+     RE_G_To_Q,                          -- System.Vax_Float_Operations
+     RE_G_To_T,                          -- System.Vax_Float_Operations
+     RE_Q_To_F,                          -- System.Vax_Float_Operations
+     RE_Q_To_G,                          -- System.Vax_Float_Operations
+     RE_S_To_F,                          -- System.Vax_Float_Operations
+     RE_T_To_D,                          -- System.Vax_Float_Operations
+     RE_T_To_G,                          -- System.Vax_Float_Operations
+
+     RE_Abs_F,                           -- System.Vax_Float_Operations
+     RE_Abs_G,                           -- System.Vax_Float_Operations
+     RE_Add_F,                           -- System.Vax_Float_Operations
+     RE_Add_G,                           -- System.Vax_Float_Operations
+     RE_Div_F,                           -- System.Vax_Float_Operations
+     RE_Div_G,                           -- System.Vax_Float_Operations
+     RE_Mul_F,                           -- System.Vax_Float_Operations
+     RE_Mul_G,                           -- System.Vax_Float_Operations
+     RE_Neg_F,                           -- System.Vax_Float_Operations
+     RE_Neg_G,                           -- System.Vax_Float_Operations
+     RE_Sub_F,                           -- System.Vax_Float_Operations
+     RE_Sub_G,                           -- System.Vax_Float_Operations
+
+     RE_Eq_F,                            -- System.Vax_Float_Operations
+     RE_Eq_G,                            -- System.Vax_Float_Operations
+     RE_Le_F,                            -- System.Vax_Float_Operations
+     RE_Le_G,                            -- System.Vax_Float_Operations
+     RE_Lt_F,                            -- System.Vax_Float_Operations
+     RE_Lt_G,                            -- System.Vax_Float_Operations
+
+     RE_Version_String,                  -- System.Version_Control
+     RE_Get_Version_String,              -- System.Version_Control
+
+     RE_Register_VMS_Exception,          -- System.VMS_Exception_Table
+
+     RE_String_To_Wide_String,           -- System.WCh_StW
+
+     RE_Wide_String_To_String,           -- System.WCh_WtS
+
+     RE_Wide_Width_Character,            -- System.WWd_Char
+
+     RE_Wide_Width_Enumeration_8,        -- System.WWd_Enum
+     RE_Wide_Width_Enumeration_16,       -- System.WWd_Enum
+     RE_Wide_Width_Enumeration_32,       -- System.WWd_Enum
+
+     RE_Wide_Width_Wide_Character,       -- System.WWd_Wchar
+
+     RE_Width_Boolean,                   -- System.Wid_Bool
+
+     RE_Width_Character,                 -- System.Wid_Char
+
+     RE_Width_Enumeration_8,             -- System.Wid_Enum
+     RE_Width_Enumeration_16,            -- System.Wid_Enum
+     RE_Width_Enumeration_32,            -- System.Wid_Enum
+
+     RE_Width_Long_Long_Integer,         -- System.Wid_LLI
+
+     RE_Width_Long_Long_Unsigned,        -- System.Wid_LLU
+
+     RE_Width_Wide_Character,            -- System.Wid_WChar
+
+     RE_Protected_Entry_Body_Array,      -- Tasking.Protected_Objects.Entries
+     RE_Protection_Entries,              -- Tasking.Protected_Objects.Entries
+     RE_Initialize_Protection_Entries,   -- Tasking.Protected_Objects.Entries
+     RE_Lock_Entries,                    -- Tasking.Protected_Objects.Entries
+     RE_Lock_Read_Only_Entries,          -- Tasking.Protected_Objects.Entries
+     RE_Unlock_Entries,                  -- Tasking.Protected_Objects.Entries
+     RE_Communication_Block,             -- Protected_Objects.Operations
+     RE_Protected_Entry_Call,            -- Protected_Objects.Operations
+     RE_Service_Entries,                 -- Protected_Objects.Operations
+     RE_Cancel_Protected_Entry_Call,     -- Protected_Objects.Operations
+     RE_Enqueued,                        -- Protected_Objects.Operations
+     RE_Cancelled,                       -- Protected_Objects.Operations
+     RE_Complete_Entry_Body,             -- Protected_Objects.Operations
+     RE_Exceptional_Complete_Entry_Body, -- Protected_Objects.Operations
+     RE_Requeue_Protected_Entry,         -- Protected_Objects.Operations
+     RE_Requeue_Task_To_Protected_Entry, -- Protected_Objects.Operations
+     RE_Protected_Count,                 -- Protected_Objects.Operations
+     RE_Protected_Entry_Caller,          -- Protected_Objects.Operations
+     RE_Timed_Protected_Entry_Call,      -- Protected_Objects.Operations
+
+     RE_Protection_Entry,                -- Protected_Objects.Single_Entry
+     RE_Initialize_Protection_Entry,     -- Protected_Objects.Single_Entry
+     RE_Lock_Entry,                      -- Protected_Objects.Single_Entry
+     RE_Lock_Read_Only_Entry,            -- Protected_Objects.Single_Entry
+     RE_Unlock_Entry,                    -- Protected_Objects.Single_Entry
+     RE_Protected_Single_Entry_Call,     -- Protected_Objects.Single_Entry
+     RE_Service_Entry,                   -- Protected_Objects.Single_Entry
+     RE_Complete_Single_Entry_Body,      -- Protected_Objects.Single_Entry
+     RE_Exceptional_Complete_Single_Entry_Body,
+     RE_Protected_Count_Entry,           -- Protected_Objects.Single_Entry
+     RE_Protected_Single_Entry_Caller,   -- Protected_Objects.Single_Entry
+     RE_Timed_Protected_Single_Entry_Call,
+
+     RE_Protected_Entry_Index,           -- System.Tasking.Protected_Objects
+     RE_Entry_Body,                      -- System.Tasking.Protected_Objects
+     RE_Protection,                      -- System.Tasking.Protected_Objects
+     RE_Initialize_Protection,           -- System.Tasking.Protected_Objects
+     RE_Finalize_Protection,             -- System.Tasking.Protected_Objects
+     RE_Lock,                            -- System.Tasking.Protected_Objects
+     RE_Lock_Read_Only,                  -- System.Tasking.Protected_Objects
+     RE_Unlock,                          -- System.Tasking.Protected_Objects
+
+     RE_Delay_Block,                     -- System.Tasking.Async_Delays
+     RE_Timed_Out,                       -- System.Tasking.Async_Delays
+     RE_Cancel_Async_Delay,              -- System.Tasking.Async_Delays
+     RE_Enqueue_Duration,                -- System.Tasking.Async_Delays
+     RE_Enqueue_Calendar,                -- System.Tasking.Async_Delays
+     RE_Enqueue_RT,                      -- System.Tasking.Async_Delays
+
+     RE_Accept_Call,                     -- System.Tasking.Rendezvous
+     RE_Accept_Trivial,                  -- System.Tasking.Rendezvous
+     RE_Callable,                        -- System.Tasking.Rendezvous
+     RE_Call_Simple,                     -- System.Tasking.Rendezvous
+     RE_Requeue_Task_Entry,              -- System.Tasking.Rendezvous
+     RE_Requeue_Protected_To_Task_Entry, -- System.Tasking.Rendezvous
+     RE_Cancel_Task_Entry_Call,          -- System.Tasking.Rendezvous
+     RE_Complete_Rendezvous,             -- System.Tasking.Rendezvous
+     RE_Task_Count,                      -- System.Tasking.Rendezvous
+     RE_Exceptional_Complete_Rendezvous, -- System.Tasking.Rendezvous
+     RE_Selective_Wait,                  -- System.Tasking.Rendezvous
+     RE_Task_Entry_Call,                 -- System.Tasking.Rendezvous
+     RE_Task_Entry_Caller,               -- System.Tasking.Rendezvous
+     RE_Timed_Task_Entry_Call,           -- System.Tasking.Rendezvous
+     RE_Timed_Selective_Wait,            -- System.Tasking.Rendezvous
+
+     RE_Activate_Restricted_Tasks,       -- System.Tasking.Restricted.Stages
+     RE_Complete_Restricted_Activation,  -- System.Tasking.Restricted.Stages
+     RE_Create_Restricted_Task,          -- System.Tasking.Restricted.Stages
+     RE_Complete_Restricted_Task,        -- System.Tasking.Restricted.Stages
+     RE_Restricted_Terminated,           -- System.Tasking.Restricted.Stages
+
+     RE_Abort_Tasks,                     -- System.Tasking.Stages
+     RE_Activate_Tasks,                  -- System.Tasking.Stages
+     RE_Complete_Activation,             -- System.Tasking.Stages
+     RE_Create_Task,                     -- System.Tasking.Stages
+     RE_Complete_Task,                   -- System.Tasking.Stages
+     RE_Free_Task,                       -- System.Tasking.Stages
+     RE_Expunge_Unactivated_Tasks,       -- System.Tasking.Stages
+     RE_Terminated);                     -- System.Tasking.Stages
+
+   --  The following declarations build a table that is indexed by the
+   --  RTE function to determine the unit containing the given entity.
+   --  This table is sorted in order of package names.
+
+   RE_Unit_Table : array (RE_Id) of RTU_Id := (
+
+     RE_Null                             => RTU_Null,
+
+     RE_Code_Loc                         => Ada_Exceptions,
+     RE_Current_Target_Exception         => Ada_Exceptions, -- of JGNAT
+     RE_Exception_Id                     => Ada_Exceptions,
+     RE_Exception_Information            => Ada_Exceptions,
+     RE_Exception_Message                => Ada_Exceptions,
+     RE_Exception_Name_Simple            => Ada_Exceptions,
+     RE_Exception_Occurrence             => Ada_Exceptions,
+     RE_Null_Id                          => Ada_Exceptions,
+     RE_Null_Occurrence                  => Ada_Exceptions,
+     RE_Poll                             => Ada_Exceptions,
+     RE_Raise_Exception                  => Ada_Exceptions,
+     RE_Raise_Exception_Always           => Ada_Exceptions,
+     RE_Reraise_Occurrence               => Ada_Exceptions,
+     RE_Reraise_Occurrence_Always        => Ada_Exceptions,
+     RE_Reraise_Occurrence_No_Defer      => Ada_Exceptions,
+     RE_Save_Occurrence                  => Ada_Exceptions,
+
+     RE_Simple_List_Controller           => Ada_Finalization_List_Controller,
+     RE_List_Controller                  => Ada_Finalization_List_Controller,
+
+     RE_Interrupt_Id                     => Ada_Interrupts,
+
+     RE_Root_Stream_Type                 => Ada_Streams,
+     RE_Stream_Element                   => Ada_Streams,
+     RE_Stream_Element_Offset            => Ada_Streams,
+     RE_Stream_Element_Array             => Ada_Streams,
+
+     RE_Stream_Access                    => Ada_Streams_Stream_IO,
+
+     RE_CW_Membership                    => Ada_Tags,
+     RE_DT_Entry_Size                    => Ada_Tags,
+     RE_DT_Prologue_Size                 => Ada_Tags,
+     RE_External_Tag                     => Ada_Tags,
+     RE_Get_Expanded_Name                => Ada_Tags,
+     RE_Get_External_Tag                 => Ada_Tags,
+     RE_Get_Prim_Op_Address              => Ada_Tags,
+     RE_Get_RC_Offset                    => Ada_Tags,
+     RE_Get_Remotely_Callable            => Ada_Tags,
+     RE_Get_TSD                          => Ada_Tags,
+     RE_Inherit_DT                       => Ada_Tags,
+     RE_Inherit_TSD                      => Ada_Tags,
+     RE_Internal_Tag                     => Ada_Tags,
+     RE_Register_Tag                     => Ada_Tags,
+     RE_Set_Expanded_Name                => Ada_Tags,
+     RE_Set_External_Tag                 => Ada_Tags,
+     RE_Set_Prim_Op_Address              => Ada_Tags,
+     RE_Set_RC_Offset                    => Ada_Tags,
+     RE_Set_Remotely_Callable            => Ada_Tags,
+     RE_Set_TSD                          => Ada_Tags,
+     RE_Tag_Error                        => Ada_Tags,
+     RE_TSD_Entry_Size                   => Ada_Tags,
+     RE_TSD_Prologue_Size                => Ada_Tags,
+     RE_Tag                              => Ada_Tags,
+     RE_Address_Array                    => Ada_Tags,
+
+     RE_Current_Task                     => Ada_Task_Identification,
+     RO_AT_Task_ID                       => Ada_Task_Identification,
+
+     RO_CA_Time                          => Ada_Calendar,
+     RO_CA_Delay_For                     => Ada_Calendar_Delays,
+     RO_CA_Delay_Until                   => Ada_Calendar_Delays,
+     RO_CA_To_Duration                   => Ada_Calendar_Delays,
+
+     RO_RT_Time                          => Ada_Real_Time,
+     RO_RT_Delay_Until                   => Ada_Real_Time_Delays,
+     RO_RT_To_Duration                   => Ada_Real_Time_Delays,
+
+     RE_Integer_64                       => Interfaces,
+     RE_Unsigned_8                       => Interfaces,
+     RE_Unsigned_16                      => Interfaces,
+     RE_Unsigned_32                      => Interfaces,
+     RE_Unsigned_64                      => Interfaces,
+
+     RE_Vtable_Ptr                       => Interfaces_CPP,
+     RE_Displaced_This                   => Interfaces_CPP,
+     RE_CPP_CW_Membership                => Interfaces_CPP,
+     RE_CPP_DT_Entry_Size                => Interfaces_CPP,
+     RE_CPP_DT_Prologue_Size             => Interfaces_CPP,
+     RE_CPP_Get_Expanded_Name            => Interfaces_CPP,
+     RE_CPP_Get_External_Tag             => Interfaces_CPP,
+     RE_CPP_Get_Prim_Op_Address          => Interfaces_CPP,
+     RE_CPP_Get_RC_Offset                => Interfaces_CPP,
+     RE_CPP_Get_Remotely_Callable        => Interfaces_CPP,
+     RE_CPP_Get_TSD                      => Interfaces_CPP,
+     RE_CPP_Inherit_DT                   => Interfaces_CPP,
+     RE_CPP_Inherit_TSD                  => Interfaces_CPP,
+     RE_CPP_Register_Tag                 => Interfaces_CPP,
+     RE_CPP_Set_Expanded_Name            => Interfaces_CPP,
+     RE_CPP_Set_External_Tag             => Interfaces_CPP,
+     RE_CPP_Set_Prim_Op_Address          => Interfaces_CPP,
+     RE_CPP_Set_RC_Offset                => Interfaces_CPP,
+     RE_CPP_Set_Remotely_Callable        => Interfaces_CPP,
+     RE_CPP_Set_TSD                      => Interfaces_CPP,
+     RE_CPP_TSD_Entry_Size               => Interfaces_CPP,
+     RE_CPP_TSD_Prologue_Size            => Interfaces_CPP,
+
+     RE_Packed_Size                      => Interfaces_Packed_Decimal,
+     RE_Packed_To_Int32                  => Interfaces_Packed_Decimal,
+     RE_Packed_To_Int64                  => Interfaces_Packed_Decimal,
+     RE_Int32_To_Packed                  => Interfaces_Packed_Decimal,
+     RE_Int64_To_Packed                  => Interfaces_Packed_Decimal,
+
+     RE_Address                          => System,
+     RE_Any_Priority                     => System,
+     RE_Bit_Order                        => System,
+     RE_Default_Priority                 => System,
+     RE_High_Order_First                 => System,
+     RE_Interrupt_Priority               => System,
+     RE_Lib_Stop                         => System,
+     RE_Low_Order_First                  => System,
+     RE_Max_Interrupt_Priority           => System,
+     RE_Max_Priority                     => System,
+     RE_Null_Address                     => System,
+     RE_Priority                         => System,
+
+     RE_Add_With_Ovflo_Check             => System_Arith_64,
+     RE_Double_Divide                    => System_Arith_64,
+     RE_Multiply_With_Ovflo_Check        => System_Arith_64,
+     RE_Scaled_Divide                    => System_Arith_64,
+     RE_Subtract_With_Ovflo_Check        => System_Arith_64,
+
+     RE_Create_AST_Handler               => System_AST_Handling,
+
+     RE_Raise_Assert_Failure             => System_Assertions,
+
+     RE_AST_Handler                      => System_Aux_DEC,
+     RE_Import_Value                     => System_Aux_DEC,
+     RE_No_AST_Handler                   => System_Aux_DEC,
+     RE_Type_Class                       => System_Aux_DEC,
+     RE_Type_Class_Enumeration           => System_Aux_DEC,
+     RE_Type_Class_Integer               => System_Aux_DEC,
+     RE_Type_Class_Fixed_Point           => System_Aux_DEC,
+     RE_Type_Class_Floating_Point        => System_Aux_DEC,
+     RE_Type_Class_Array                 => System_Aux_DEC,
+     RE_Type_Class_Record                => System_Aux_DEC,
+     RE_Type_Class_Access                => System_Aux_DEC,
+     RE_Type_Class_Task                  => System_Aux_DEC,
+     RE_Type_Class_Address               => System_Aux_DEC,
+
+     RE_Bit_And                          => System_Bit_Ops,
+     RE_Bit_Eq                           => System_Bit_Ops,
+     RE_Bit_Not                          => System_Bit_Ops,
+     RE_Bit_Or                           => System_Bit_Ops,
+     RE_Bit_Xor                          => System_Bit_Ops,
+
+     RE_Checked_Pool                     => System_Checked_Pools,
+
+     RE_Register_Exception               => System_Exception_Table,
+
+     RE_All_Others_Id                    => System_Exceptions,
+     RE_Handler_Record                   => System_Exceptions,
+     RE_Handler_Record_Ptr               => System_Exceptions,
+     RE_Others_Id                        => System_Exceptions,
+     RE_Subprogram_Descriptor            => System_Exceptions,
+     RE_Subprogram_Descriptor_0          => System_Exceptions,
+     RE_Subprogram_Descriptor_1          => System_Exceptions,
+     RE_Subprogram_Descriptor_2          => System_Exceptions,
+     RE_Subprogram_Descriptor_3          => System_Exceptions,
+     RE_Subprogram_Descriptor_List       => System_Exceptions,
+     RE_Subprogram_Descriptor_Ptr        => System_Exceptions,
+     RE_Subprogram_Descriptors_Record    => System_Exceptions,
+     RE_Subprogram_Descriptors_Ptr       => System_Exceptions,
+
+     RE_Exn_Float                        => System_Exn_Flt,
+
+     RE_Exn_Integer                      => System_Exn_Int,
+
+     RE_Exn_Long_Float                   => System_Exn_LFlt,
+
+     RE_Exn_Long_Integer                 => System_Exn_LInt,
+
+     RE_Exn_Long_Long_Float              => System_Exn_LLF,
+
+     RE_Exn_Long_Long_Integer            => System_Exn_LLI,
+
+     RE_Exn_Short_Float                  => System_Exn_SFlt,
+
+     RE_Exn_Short_Integer                => System_Exn_SInt,
+
+     RE_Exn_Short_Short_Integer          => System_Exn_SSI,
+
+     RE_Exp_Float                        => System_Exp_Flt,
+
+     RE_Exp_Integer                      => System_Exp_Int,
+
+     RE_Exp_Long_Float                   => System_Exp_LFlt,
+
+     RE_Exp_Long_Integer                 => System_Exp_LInt,
+
+     RE_Exp_Long_Long_Float              => System_Exp_LLF,
+
+     RE_Exp_Long_Long_Integer            => System_Exp_LLI,
+
+     RE_Exp_Long_Long_Unsigned           => System_Exp_LLU,
+
+     RE_Exp_Modular                      => System_Exp_Mod,
+
+     RE_Exp_Short_Float                  => System_Exp_SFlt,
+
+     RE_Exp_Short_Integer                => System_Exp_SInt,
+
+     RE_Exp_Short_Short_Integer          => System_Exp_SSI,
+
+     RE_Exp_Unsigned                     => System_Exp_Uns,
+
+     RE_Fat_Float                        => System_Fat_Flt,
+
+     RE_Fat_Long_Float                   => System_Fat_LFlt,
+
+     RE_Fat_Long_Long_Float              => System_Fat_LLF,
+
+     RE_Fat_Short_Float                  => System_Fat_SFlt,
+
+     RE_Attach_To_Final_List             => System_Finalization_Implementation,
+     RE_Finalize_List                    => System_Finalization_Implementation,
+     RE_Finalize_One                     => System_Finalization_Implementation,
+     RE_Global_Final_List                => System_Finalization_Implementation,
+     RE_Record_Controller                => System_Finalization_Implementation,
+     RE_Limited_Record_Controller        => System_Finalization_Implementation,
+     RE_Deep_Tag_Initialize              => System_Finalization_Implementation,
+     RE_Deep_Tag_Adjust                  => System_Finalization_Implementation,
+     RE_Deep_Tag_Finalize                => System_Finalization_Implementation,
+     RE_Deep_Tag_Attach                  => System_Finalization_Implementation,
+     RE_Deep_Rec_Initialize              => System_Finalization_Implementation,
+     RE_Deep_Rec_Adjust                  => System_Finalization_Implementation,
+     RE_Deep_Rec_Finalize                => System_Finalization_Implementation,
+
+     RE_Root_Controlled                  => System_Finalization_Root,
+     RE_Finalizable                      => System_Finalization_Root,
+     RE_Finalizable_Ptr                  => System_Finalization_Root,
+
+     RE_Fore                             => System_Fore,
+
+     RE_Image_Boolean                    => System_Img_Bool,
+
+     RE_Image_Character                  => System_Img_Char,
+
+     RE_Image_Decimal                    => System_Img_Dec,
+
+     RE_Image_Enumeration_8              => System_Img_Enum,
+     RE_Image_Enumeration_16             => System_Img_Enum,
+     RE_Image_Enumeration_32             => System_Img_Enum,
+
+     RE_Image_Integer                    => System_Img_Int,
+
+     RE_Image_Long_Long_Decimal          => System_Img_LLD,
+
+     RE_Image_Long_Long_Integer          => System_Img_LLI,
+
+     RE_Image_Long_Long_Unsigned         => System_Img_LLU,
+
+     RE_Image_Ordinary_Fixed_Point       => System_Img_Real,
+     RE_Image_Floating_Point             => System_Img_Real,
+
+     RE_Image_Unsigned                   => System_Img_Uns,
+
+     RE_Image_Wide_Character             => System_Img_WChar,
+
+     RE_Bind_Interrupt_To_Entry          => System_Interrupts,
+     RE_Default_Interrupt_Priority       => System_Interrupts,
+     RE_Dynamic_Interrupt_Protection     => System_Interrupts,
+     RE_Install_Handlers                 => System_Interrupts,
+     RE_Register_Interrupt_Handler       => System_Interrupts,
+     RE_Static_Interrupt_Protection      => System_Interrupts,
+
+     RE_Asm_Insn                         => System_Machine_Code,
+     RE_Asm_Input_Operand                => System_Machine_Code,
+     RE_Asm_Output_Operand               => System_Machine_Code,
+
+     RE_Mantissa_Value                   => System_Mantissa,
+
+     RE_Bits_03                          => System_Pack_03,
+     RE_Get_03                           => System_Pack_03,
+     RE_Set_03                           => System_Pack_03,
+
+     RE_Bits_05                          => System_Pack_05,
+     RE_Get_05                           => System_Pack_05,
+     RE_Set_05                           => System_Pack_05,
+
+     RE_Bits_06                          => System_Pack_06,
+     RE_Get_06                           => System_Pack_06,
+     RE_GetU_06                          => System_Pack_06,
+     RE_Set_06                           => System_Pack_06,
+     RE_SetU_06                          => System_Pack_06,
+
+     RE_Bits_07                          => System_Pack_07,
+     RE_Get_07                           => System_Pack_07,
+     RE_Set_07                           => System_Pack_07,
+
+     RE_Bits_09                          => System_Pack_09,
+     RE_Get_09                           => System_Pack_09,
+     RE_Set_09                           => System_Pack_09,
+
+     RE_Bits_10                          => System_Pack_10,
+     RE_Get_10                           => System_Pack_10,
+     RE_GetU_10                          => System_Pack_10,
+     RE_Set_10                           => System_Pack_10,
+     RE_SetU_10                          => System_Pack_10,
+
+     RE_Bits_11                          => System_Pack_11,
+     RE_Get_11                           => System_Pack_11,
+     RE_Set_11                           => System_Pack_11,
+
+     RE_Bits_12                          => System_Pack_12,
+     RE_Get_12                           => System_Pack_12,
+     RE_GetU_12                          => System_Pack_12,
+     RE_Set_12                           => System_Pack_12,
+     RE_SetU_12                          => System_Pack_12,
+
+     RE_Bits_13                          => System_Pack_13,
+     RE_Get_13                           => System_Pack_13,
+     RE_Set_13                           => System_Pack_13,
+
+     RE_Bits_14                          => System_Pack_14,
+     RE_Get_14                           => System_Pack_14,
+     RE_GetU_14                          => System_Pack_14,
+     RE_Set_14                           => System_Pack_14,
+     RE_SetU_14                          => System_Pack_14,
+
+     RE_Bits_15                          => System_Pack_15,
+     RE_Get_15                           => System_Pack_15,
+     RE_Set_15                           => System_Pack_15,
+
+     RE_Bits_17                          => System_Pack_17,
+     RE_Get_17                           => System_Pack_17,
+     RE_Set_17                           => System_Pack_17,
+
+     RE_Bits_18                          => System_Pack_18,
+     RE_Get_18                           => System_Pack_18,
+     RE_GetU_18                          => System_Pack_18,
+     RE_Set_18                           => System_Pack_18,
+     RE_SetU_18                          => System_Pack_18,
+
+     RE_Bits_19                          => System_Pack_19,
+     RE_Get_19                           => System_Pack_19,
+     RE_Set_19                           => System_Pack_19,
+
+     RE_Bits_20                          => System_Pack_20,
+     RE_Get_20                           => System_Pack_20,
+     RE_GetU_20                          => System_Pack_20,
+     RE_Set_20                           => System_Pack_20,
+     RE_SetU_20                          => System_Pack_20,
+
+     RE_Bits_21                          => System_Pack_21,
+     RE_Get_21                           => System_Pack_21,
+     RE_Set_21                           => System_Pack_21,
+
+     RE_Bits_22                          => System_Pack_22,
+     RE_Get_22                           => System_Pack_22,
+     RE_GetU_22                          => System_Pack_22,
+     RE_Set_22                           => System_Pack_22,
+     RE_SetU_22                          => System_Pack_22,
+
+     RE_Bits_23                          => System_Pack_23,
+     RE_Get_23                           => System_Pack_23,
+     RE_Set_23                           => System_Pack_23,
+
+     RE_Bits_24                          => System_Pack_24,
+     RE_Get_24                           => System_Pack_24,
+     RE_GetU_24                          => System_Pack_24,
+     RE_Set_24                           => System_Pack_24,
+     RE_SetU_24                          => System_Pack_24,
+
+     RE_Bits_25                          => System_Pack_25,
+     RE_Get_25                           => System_Pack_25,
+     RE_Set_25                           => System_Pack_25,
+
+     RE_Bits_26                          => System_Pack_26,
+     RE_Get_26                           => System_Pack_26,
+     RE_GetU_26                          => System_Pack_26,
+     RE_Set_26                           => System_Pack_26,
+     RE_SetU_26                          => System_Pack_26,
+
+     RE_Bits_27                          => System_Pack_27,
+     RE_Get_27                           => System_Pack_27,
+     RE_Set_27                           => System_Pack_27,
+
+     RE_Bits_28                          => System_Pack_28,
+     RE_Get_28                           => System_Pack_28,
+     RE_GetU_28                          => System_Pack_28,
+     RE_Set_28                           => System_Pack_28,
+     RE_SetU_28                          => System_Pack_28,
+
+     RE_Bits_29                          => System_Pack_29,
+     RE_Get_29                           => System_Pack_29,
+     RE_Set_29                           => System_Pack_29,
+
+     RE_Bits_30                          => System_Pack_30,
+     RE_Get_30                           => System_Pack_30,
+     RE_GetU_30                          => System_Pack_30,
+     RE_Set_30                           => System_Pack_30,
+     RE_SetU_30                          => System_Pack_30,
+
+     RE_Bits_31                          => System_Pack_31,
+     RE_Get_31                           => System_Pack_31,
+     RE_Set_31                           => System_Pack_31,
+
+     RE_Bits_33                          => System_Pack_33,
+     RE_Get_33                           => System_Pack_33,
+     RE_Set_33                           => System_Pack_33,
+
+     RE_Bits_34                          => System_Pack_34,
+     RE_Get_34                           => System_Pack_34,
+     RE_GetU_34                          => System_Pack_34,
+     RE_Set_34                           => System_Pack_34,
+     RE_SetU_34                          => System_Pack_34,
+
+     RE_Bits_35                          => System_Pack_35,
+     RE_Get_35                           => System_Pack_35,
+     RE_Set_35                           => System_Pack_35,
+
+     RE_Bits_36                          => System_Pack_36,
+     RE_Get_36                           => System_Pack_36,
+     RE_GetU_36                          => System_Pack_36,
+     RE_Set_36                           => System_Pack_36,
+     RE_SetU_36                          => System_Pack_36,
+
+     RE_Bits_37                          => System_Pack_37,
+     RE_Get_37                           => System_Pack_37,
+     RE_Set_37                           => System_Pack_37,
+
+     RE_Bits_38                          => System_Pack_38,
+     RE_Get_38                           => System_Pack_38,
+     RE_GetU_38                          => System_Pack_38,
+     RE_Set_38                           => System_Pack_38,
+     RE_SetU_38                          => System_Pack_38,
+
+     RE_Bits_39                          => System_Pack_39,
+     RE_Get_39                           => System_Pack_39,
+     RE_Set_39                           => System_Pack_39,
+
+     RE_Bits_40                          => System_Pack_40,
+     RE_Get_40                           => System_Pack_40,
+     RE_GetU_40                          => System_Pack_40,
+     RE_Set_40                           => System_Pack_40,
+     RE_SetU_40                          => System_Pack_40,
+
+     RE_Bits_41                          => System_Pack_41,
+     RE_Get_41                           => System_Pack_41,
+     RE_Set_41                           => System_Pack_41,
+
+     RE_Bits_42                          => System_Pack_42,
+     RE_Get_42                           => System_Pack_42,
+     RE_GetU_42                          => System_Pack_42,
+     RE_Set_42                           => System_Pack_42,
+     RE_SetU_42                          => System_Pack_42,
+
+     RE_Bits_43                          => System_Pack_43,
+     RE_Get_43                           => System_Pack_43,
+     RE_Set_43                           => System_Pack_43,
+
+     RE_Bits_44                          => System_Pack_44,
+     RE_Get_44                           => System_Pack_44,
+     RE_GetU_44                          => System_Pack_44,
+     RE_Set_44                           => System_Pack_44,
+     RE_SetU_44                          => System_Pack_44,
+
+     RE_Bits_45                          => System_Pack_45,
+     RE_Get_45                           => System_Pack_45,
+     RE_Set_45                           => System_Pack_45,
+
+     RE_Bits_46                          => System_Pack_46,
+     RE_Get_46                           => System_Pack_46,
+     RE_GetU_46                          => System_Pack_46,
+     RE_Set_46                           => System_Pack_46,
+     RE_SetU_46                          => System_Pack_46,
+
+     RE_Bits_47                          => System_Pack_47,
+     RE_Get_47                           => System_Pack_47,
+     RE_Set_47                           => System_Pack_47,
+
+     RE_Bits_48                          => System_Pack_48,
+     RE_Get_48                           => System_Pack_48,
+     RE_GetU_48                          => System_Pack_48,
+     RE_Set_48                           => System_Pack_48,
+     RE_SetU_48                          => System_Pack_48,
+
+     RE_Bits_49                          => System_Pack_49,
+     RE_Get_49                           => System_Pack_49,
+     RE_Set_49                           => System_Pack_49,
+
+     RE_Bits_50                          => System_Pack_50,
+     RE_Get_50                           => System_Pack_50,
+     RE_GetU_50                          => System_Pack_50,
+     RE_Set_50                           => System_Pack_50,
+     RE_SetU_50                          => System_Pack_50,
+
+     RE_Bits_51                          => System_Pack_51,
+     RE_Get_51                           => System_Pack_51,
+     RE_Set_51                           => System_Pack_51,
+
+     RE_Bits_52                          => System_Pack_52,
+     RE_Get_52                           => System_Pack_52,
+     RE_GetU_52                          => System_Pack_52,
+     RE_Set_52                           => System_Pack_52,
+     RE_SetU_52                          => System_Pack_52,
+
+     RE_Bits_53                          => System_Pack_53,
+     RE_Get_53                           => System_Pack_53,
+     RE_Set_53                           => System_Pack_53,
+
+     RE_Bits_54                          => System_Pack_54,
+     RE_Get_54                           => System_Pack_54,
+     RE_GetU_54                          => System_Pack_54,
+     RE_Set_54                           => System_Pack_54,
+     RE_SetU_54                          => System_Pack_54,
+
+     RE_Bits_55                          => System_Pack_55,
+     RE_Get_55                           => System_Pack_55,
+     RE_Set_55                           => System_Pack_55,
+
+     RE_Bits_56                          => System_Pack_56,
+     RE_Get_56                           => System_Pack_56,
+     RE_GetU_56                          => System_Pack_56,
+     RE_Set_56                           => System_Pack_56,
+     RE_SetU_56                          => System_Pack_56,
+
+     RE_Bits_57                          => System_Pack_57,
+     RE_Get_57                           => System_Pack_57,
+     RE_Set_57                           => System_Pack_57,
+
+     RE_Bits_58                          => System_Pack_58,
+     RE_Get_58                           => System_Pack_58,
+     RE_GetU_58                          => System_Pack_58,
+     RE_Set_58                           => System_Pack_58,
+     RE_SetU_58                          => System_Pack_58,
+
+     RE_Bits_59                          => System_Pack_59,
+     RE_Get_59                           => System_Pack_59,
+     RE_Set_59                           => System_Pack_59,
+
+     RE_Bits_60                          => System_Pack_60,
+     RE_Get_60                           => System_Pack_60,
+     RE_GetU_60                          => System_Pack_60,
+     RE_Set_60                           => System_Pack_60,
+     RE_SetU_60                          => System_Pack_60,
+
+     RE_Bits_61                          => System_Pack_61,
+     RE_Get_61                           => System_Pack_61,
+     RE_Set_61                           => System_Pack_61,
+
+     RE_Bits_62                          => System_Pack_62,
+     RE_Get_62                           => System_Pack_62,
+     RE_GetU_62                          => System_Pack_62,
+     RE_Set_62                           => System_Pack_62,
+     RE_SetU_62                          => System_Pack_62,
+
+     RE_Bits_63                          => System_Pack_63,
+     RE_Get_63                           => System_Pack_63,
+     RE_Set_63                           => System_Pack_63,
+
+     RE_Adjust_Storage_Size              => System_Parameters,
+     RE_Default_Stack_Size               => System_Parameters,
+     RE_Garbage_Collected                => System_Parameters,
+     RE_Size_Type                        => System_Parameters,
+     RE_Unspecified_Size                 => System_Parameters,
+
+     RE_Get_Active_Partition_Id          => System_Partition_Interface,
+     RE_Get_Passive_Partition_Id         => System_Partition_Interface,
+     RE_Get_Local_Partition_Id           => System_Partition_Interface,
+     RE_Get_RCI_Package_Receiver         => System_Partition_Interface,
+     RE_Get_Unique_Remote_Pointer        => System_Partition_Interface,
+     RE_RACW_Stub_Type                   => System_Partition_Interface,
+     RE_RACW_Stub_Type_Access            => System_Partition_Interface,
+     RE_Raise_Program_Error_For_E_4_18   => System_Partition_Interface,
+     RE_Raise_Program_Error_Unknown_Tag  => System_Partition_Interface,
+     RE_Register_Passive_Package         => System_Partition_Interface,
+     RE_Register_Receiving_Stub          => System_Partition_Interface,
+     RE_RCI_Info                         => System_Partition_Interface,
+     RE_Subprogram_Id                    => System_Partition_Interface,
+
+     RE_Global_Pool_Object               => System_Pool_Global,
+
+     RE_Unbounded_Reclaim_Pool           => System_Pool_Local,
+
+     RE_Stack_Bounded_Pool               => System_Pool_Size,
+
+     RE_Do_Apc                           => System_RPC,
+     RE_Do_Rpc                           => System_RPC,
+     RE_Params_Stream_Type               => System_RPC,
+     RE_Partition_ID                     => System_RPC,
+     RE_RPC_Receiver                     => System_RPC,
+
+     RE_IS_Is1                           => System_Scalar_Values,
+     RE_IS_Is2                           => System_Scalar_Values,
+     RE_IS_Is4                           => System_Scalar_Values,
+     RE_IS_Is8                           => System_Scalar_Values,
+     RE_IS_Iu1                           => System_Scalar_Values,
+     RE_IS_Iu2                           => System_Scalar_Values,
+     RE_IS_Iu4                           => System_Scalar_Values,
+     RE_IS_Iu8                           => System_Scalar_Values,
+     RE_IS_Isf                           => System_Scalar_Values,
+     RE_IS_Ifl                           => System_Scalar_Values,
+     RE_IS_Ilf                           => System_Scalar_Values,
+     RE_IS_Ill                           => System_Scalar_Values,
+
+     RE_Mark_Id                          => System_Secondary_Stack,
+     RE_SS_Allocate                      => System_Secondary_Stack,
+     RE_SS_Mark                          => System_Secondary_Stack,
+     RE_SS_Pool                          => System_Secondary_Stack,
+     RE_SS_Release                       => System_Secondary_Stack,
+
+     RE_Shared_Var_Close                 => System_Shared_Storage,
+     RE_Shared_Var_Lock                  => System_Shared_Storage,
+     RE_Shared_Var_ROpen                 => System_Shared_Storage,
+     RE_Shared_Var_Unlock                => System_Shared_Storage,
+     RE_Shared_Var_WOpen                 => System_Shared_Storage,
+
+     RE_Abort_Undefer_Direct             => System_Standard_Library,
+     RE_Exception_Data                   => System_Standard_Library,
+     RE_Exception_Data_Ptr               => System_Standard_Library,
+
+     RE_Integer_Address                  => System_Storage_Elements,
+     RE_Storage_Offset                   => System_Storage_Elements,
+     RE_Storage_Array                    => System_Storage_Elements,
+     RE_To_Address                       => System_Storage_Elements,
+
+     RE_Root_Storage_Pool                => System_Storage_Pools,
+
+     RE_Thin_Pointer                     => System_Stream_Attributes,
+     RE_Fat_Pointer                      => System_Stream_Attributes,
+
+     RE_I_AD                             => System_Stream_Attributes,
+     RE_I_AS                             => System_Stream_Attributes,
+     RE_I_B                              => System_Stream_Attributes,
+     RE_I_C                              => System_Stream_Attributes,
+     RE_I_F                              => System_Stream_Attributes,
+     RE_I_I                              => System_Stream_Attributes,
+     RE_I_LF                             => System_Stream_Attributes,
+     RE_I_LI                             => System_Stream_Attributes,
+     RE_I_LLF                            => System_Stream_Attributes,
+     RE_I_LLI                            => System_Stream_Attributes,
+     RE_I_LLU                            => System_Stream_Attributes,
+     RE_I_LU                             => System_Stream_Attributes,
+     RE_I_SF                             => System_Stream_Attributes,
+     RE_I_SI                             => System_Stream_Attributes,
+     RE_I_SSI                            => System_Stream_Attributes,
+     RE_I_SSU                            => System_Stream_Attributes,
+     RE_I_SU                             => System_Stream_Attributes,
+     RE_I_U                              => System_Stream_Attributes,
+     RE_I_WC                             => System_Stream_Attributes,
+
+     RE_W_AD                             => System_Stream_Attributes,
+     RE_W_AS                             => System_Stream_Attributes,
+     RE_W_B                              => System_Stream_Attributes,
+     RE_W_C                              => System_Stream_Attributes,
+     RE_W_F                              => System_Stream_Attributes,
+     RE_W_I                              => System_Stream_Attributes,
+     RE_W_LF                             => System_Stream_Attributes,
+     RE_W_LI                             => System_Stream_Attributes,
+     RE_W_LLF                            => System_Stream_Attributes,
+     RE_W_LLI                            => System_Stream_Attributes,
+     RE_W_LLU                            => System_Stream_Attributes,
+     RE_W_LU                             => System_Stream_Attributes,
+     RE_W_SF                             => System_Stream_Attributes,
+     RE_W_SI                             => System_Stream_Attributes,
+     RE_W_SSI                            => System_Stream_Attributes,
+     RE_W_SSU                            => System_Stream_Attributes,
+     RE_W_SU                             => System_Stream_Attributes,
+     RE_W_U                              => System_Stream_Attributes,
+     RE_W_WC                             => System_Stream_Attributes,
+
+     RE_Str_Concat                       => System_String_Ops,
+     RE_Str_Equal                        => System_String_Ops,
+     RE_Str_Normalize                    => System_String_Ops,
+     RE_Wide_Str_Normalize               => System_String_Ops,
+     RE_Str_Concat_CC                    => System_String_Ops,
+     RE_Str_Concat_CS                    => System_String_Ops,
+     RE_Str_Concat_SC                    => System_String_Ops,
+
+     RE_Str_Concat_3                     => System_String_Ops_Concat_3,
+
+     RE_Str_Concat_4                     => System_String_Ops_Concat_4,
+
+     RE_Str_Concat_5                     => System_String_Ops_Concat_5,
+
+     RE_Free_Task_Image                  => System_Task_Info,
+     RE_Task_Info_Type                   => System_Task_Info,
+     RE_Task_Image_Type                  => System_Task_Info,
+     RE_Unspecified_Task_Info            => System_Task_Info,
+
+     RE_Library_Task_Level               => System_Tasking,
+
+     RE_Task_Procedure_Access            => System_Tasking,
+
+     RO_ST_Task_ID                       => System_Tasking,
+
+     RE_Call_Modes                       => System_Tasking,
+     RE_Simple_Call                      => System_Tasking,
+     RE_Conditional_Call                 => System_Tasking,
+     RE_Asynchronous_Call                => System_Tasking,
+     RE_Timed_Call                       => System_Tasking,
+
+     RE_Task_List                        => System_Tasking,
+
+     RE_Accept_Alternative               => System_Tasking,
+     RE_Accept_List                      => System_Tasking,
+     RE_Accept_List_Access               => System_Tasking,
+     RE_Max_Select                       => System_Tasking,
+     RE_Max_Task_Entry                   => System_Tasking,
+     RE_No_Rendezvous                    => System_Tasking,
+     RE_Null_Task_Entry                  => System_Tasking,
+     RE_Positive_Select_Index            => System_Tasking,
+     RE_Select_Index                     => System_Tasking,
+     RE_Select_Modes                     => System_Tasking,
+     RE_Else_Mode                        => System_Tasking,
+     RE_Simple_Mode                      => System_Tasking,
+     RE_Terminate_Mode                   => System_Tasking,
+     RE_Delay_Mode                       => System_Tasking,
+     RE_Task_Entry_Index                 => System_Tasking,
+     RE_Self                             => System_Tasking,
+
+     RE_Master_Id                        => System_Tasking,
+     RE_Unspecified_Priority             => System_Tasking,
+
+     RE_Activation_Chain                 => System_Tasking,
+
+     RE_Abort_Defer                      => System_Soft_Links,
+     RE_Abort_Undefer                    => System_Soft_Links,
+     RE_Complete_Master                  => System_Soft_Links,
+     RE_Current_Master                   => System_Soft_Links,
+     RE_Enter_Master                     => System_Soft_Links,
+     RE_Get_Current_Excep                => System_Soft_Links,
+     RE_Get_GNAT_Exception               => System_Soft_Links,
+     RE_Update_Exception                 => System_Soft_Links,
+
+     RE_Bits_1                           => System_Unsigned_Types,
+     RE_Bits_2                           => System_Unsigned_Types,
+     RE_Bits_4                           => System_Unsigned_Types,
+     RE_Float_Unsigned                   => System_Unsigned_Types,
+     RE_Long_Long_Unsigned               => System_Unsigned_Types,
+     RE_Packed_Byte                      => System_Unsigned_Types,
+     RE_Packed_Bytes1                    => System_Unsigned_Types,
+     RE_Packed_Bytes2                    => System_Unsigned_Types,
+     RE_Packed_Bytes4                    => System_Unsigned_Types,
+     RE_Unsigned                         => System_Unsigned_Types,
+
+     RE_Value_Boolean                    => System_Val_Bool,
+
+     RE_Value_Character                  => System_Val_Char,
+
+     RE_Value_Decimal                    => System_Val_Dec,
+
+     RE_Value_Enumeration_8              => System_Val_Enum,
+     RE_Value_Enumeration_16             => System_Val_Enum,
+     RE_Value_Enumeration_32             => System_Val_Enum,
+
+     RE_Value_Integer                    => System_Val_Int,
+
+     RE_Value_Long_Long_Decimal          => System_Val_LLD,
+
+     RE_Value_Long_Long_Integer          => System_Val_LLI,
+
+     RE_Value_Long_Long_Unsigned         => System_Val_LLU,
+
+     RE_Value_Real                       => System_Val_Real,
+
+     RE_Value_Unsigned                   => System_Val_Uns,
+
+     RE_Value_Wide_Character             => System_Val_WChar,
+
+     RE_D                                => System_Vax_Float_Operations,
+     RE_F                                => System_Vax_Float_Operations,
+     RE_G                                => System_Vax_Float_Operations,
+     RE_Q                                => System_Vax_Float_Operations,
+     RE_S                                => System_Vax_Float_Operations,
+     RE_T                                => System_Vax_Float_Operations,
+
+     RE_D_To_G                           => System_Vax_Float_Operations,
+     RE_F_To_G                           => System_Vax_Float_Operations,
+     RE_F_To_Q                           => System_Vax_Float_Operations,
+     RE_F_To_S                           => System_Vax_Float_Operations,
+     RE_G_To_D                           => System_Vax_Float_Operations,
+     RE_G_To_F                           => System_Vax_Float_Operations,
+     RE_G_To_Q                           => System_Vax_Float_Operations,
+     RE_G_To_T                           => System_Vax_Float_Operations,
+     RE_Q_To_F                           => System_Vax_Float_Operations,
+     RE_Q_To_G                           => System_Vax_Float_Operations,
+     RE_S_To_F                           => System_Vax_Float_Operations,
+     RE_T_To_D                           => System_Vax_Float_Operations,
+     RE_T_To_G                           => System_Vax_Float_Operations,
+
+     RE_Abs_F                            => System_Vax_Float_Operations,
+     RE_Abs_G                            => System_Vax_Float_Operations,
+     RE_Add_F                            => System_Vax_Float_Operations,
+     RE_Add_G                            => System_Vax_Float_Operations,
+     RE_Div_F                            => System_Vax_Float_Operations,
+     RE_Div_G                            => System_Vax_Float_Operations,
+     RE_Mul_F                            => System_Vax_Float_Operations,
+     RE_Mul_G                            => System_Vax_Float_Operations,
+     RE_Neg_F                            => System_Vax_Float_Operations,
+     RE_Neg_G                            => System_Vax_Float_Operations,
+     RE_Sub_F                            => System_Vax_Float_Operations,
+     RE_Sub_G                            => System_Vax_Float_Operations,
+
+     RE_Eq_F                             => System_Vax_Float_Operations,
+     RE_Eq_G                             => System_Vax_Float_Operations,
+     RE_Le_F                             => System_Vax_Float_Operations,
+     RE_Le_G                             => System_Vax_Float_Operations,
+     RE_Lt_F                             => System_Vax_Float_Operations,
+     RE_Lt_G                             => System_Vax_Float_Operations,
+
+     RE_Version_String                   => System_Version_Control,
+     RE_Get_Version_String               => System_Version_Control,
+
+     RE_Register_VMS_Exception           => System_VMS_Exception_Table,
+
+     RE_String_To_Wide_String            => System_WCh_StW,
+
+     RE_Wide_String_To_String            => System_WCh_WtS,
+
+     RE_Wide_Width_Character             => System_WWd_Char,
+
+     RE_Wide_Width_Enumeration_8         => System_WWd_Enum,
+     RE_Wide_Width_Enumeration_16        => System_WWd_Enum,
+     RE_Wide_Width_Enumeration_32        => System_WWd_Enum,
+
+     RE_Wide_Width_Wide_Character        => System_WWd_Wchar,
+
+     RE_Width_Boolean                    => System_Wid_Bool,
+
+     RE_Width_Character                  => System_Wid_Char,
+
+     RE_Width_Enumeration_8              => System_Wid_Enum,
+     RE_Width_Enumeration_16             => System_Wid_Enum,
+     RE_Width_Enumeration_32             => System_Wid_Enum,
+
+     RE_Width_Long_Long_Integer          => System_Wid_LLI,
+
+     RE_Width_Long_Long_Unsigned         => System_Wid_LLU,
+
+     RE_Width_Wide_Character             => System_Wid_WChar,
+
+     RE_Protected_Entry_Body_Array       =>
+       System_Tasking_Protected_Objects_Entries,
+     RE_Protection_Entries               =>
+       System_Tasking_Protected_Objects_Entries,
+     RE_Initialize_Protection_Entries    =>
+       System_Tasking_Protected_Objects_Entries,
+     RE_Lock_Entries                     =>
+       System_Tasking_Protected_Objects_Entries,
+     RE_Lock_Read_Only_Entries           =>
+       System_Tasking_Protected_Objects_Entries,
+     RE_Unlock_Entries                   =>
+       System_Tasking_Protected_Objects_Entries,
+     RE_Communication_Block              =>
+       System_Tasking_Protected_Objects_Operations,
+     RE_Protected_Entry_Call             =>
+       System_Tasking_Protected_Objects_Operations,
+     RE_Service_Entries                  =>
+       System_Tasking_Protected_Objects_Operations,
+     RE_Cancel_Protected_Entry_Call      =>
+       System_Tasking_Protected_Objects_Operations,
+     RE_Enqueued                         =>
+       System_Tasking_Protected_Objects_Operations,
+     RE_Cancelled                        =>
+       System_Tasking_Protected_Objects_Operations,
+     RE_Complete_Entry_Body              =>
+       System_Tasking_Protected_Objects_Operations,
+     RE_Exceptional_Complete_Entry_Body  =>
+       System_Tasking_Protected_Objects_Operations,
+     RE_Requeue_Protected_Entry          =>
+       System_Tasking_Protected_Objects_Operations,
+     RE_Requeue_Task_To_Protected_Entry  =>
+       System_Tasking_Protected_Objects_Operations,
+     RE_Protected_Count                  =>
+       System_Tasking_Protected_Objects_Operations,
+     RE_Protected_Entry_Caller           =>
+       System_Tasking_Protected_Objects_Operations,
+     RE_Timed_Protected_Entry_Call       =>
+       System_Tasking_Protected_Objects_Operations,
+
+     RE_Protection_Entry                 =>
+       System_Tasking_Protected_Objects_Single_Entry,
+     RE_Initialize_Protection_Entry      =>
+       System_Tasking_Protected_Objects_Single_Entry,
+     RE_Lock_Entry                       =>
+       System_Tasking_Protected_Objects_Single_Entry,
+     RE_Lock_Read_Only_Entry             =>
+       System_Tasking_Protected_Objects_Single_Entry,
+     RE_Unlock_Entry                     =>
+       System_Tasking_Protected_Objects_Single_Entry,
+     RE_Protected_Single_Entry_Call      =>
+       System_Tasking_Protected_Objects_Single_Entry,
+     RE_Service_Entry                    =>
+       System_Tasking_Protected_Objects_Single_Entry,
+     RE_Complete_Single_Entry_Body       =>
+       System_Tasking_Protected_Objects_Single_Entry,
+     RE_Exceptional_Complete_Single_Entry_Body =>
+       System_Tasking_Protected_Objects_Single_Entry,
+     RE_Protected_Count_Entry            =>
+       System_Tasking_Protected_Objects_Single_Entry,
+     RE_Protected_Single_Entry_Caller    =>
+       System_Tasking_Protected_Objects_Single_Entry,
+     RE_Timed_Protected_Single_Entry_Call =>
+       System_Tasking_Protected_Objects_Single_Entry,
+
+     RE_Protected_Entry_Index            => System_Tasking_Protected_Objects,
+     RE_Entry_Body                       => System_Tasking_Protected_Objects,
+     RE_Protection                       => System_Tasking_Protected_Objects,
+     RE_Initialize_Protection            => System_Tasking_Protected_Objects,
+     RE_Finalize_Protection              => System_Tasking_Protected_Objects,
+     RE_Lock                             => System_Tasking_Protected_Objects,
+     RE_Lock_Read_Only                   => System_Tasking_Protected_Objects,
+     RE_Unlock                           => System_Tasking_Protected_Objects,
+
+     RE_Delay_Block                      => System_Tasking_Async_Delays,
+     RE_Timed_Out                        => System_Tasking_Async_Delays,
+     RE_Cancel_Async_Delay               => System_Tasking_Async_Delays,
+     RE_Enqueue_Duration                 => System_Tasking_Async_Delays,
+
+     RE_Enqueue_Calendar                 =>
+       System_Tasking_Async_Delays_Enqueue_Calendar,
+     RE_Enqueue_RT                       =>
+       System_Tasking_Async_Delays_Enqueue_RT,
+
+     RE_Accept_Call                      => System_Tasking_Rendezvous,
+     RE_Accept_Trivial                   => System_Tasking_Rendezvous,
+     RE_Callable                         => System_Tasking_Rendezvous,
+     RE_Call_Simple                      => System_Tasking_Rendezvous,
+     RE_Cancel_Task_Entry_Call           => System_Tasking_Rendezvous,
+     RE_Requeue_Task_Entry               => System_Tasking_Rendezvous,
+     RE_Requeue_Protected_To_Task_Entry  => System_Tasking_Rendezvous,
+     RE_Complete_Rendezvous              => System_Tasking_Rendezvous,
+     RE_Task_Count                       => System_Tasking_Rendezvous,
+     RE_Exceptional_Complete_Rendezvous  => System_Tasking_Rendezvous,
+     RE_Selective_Wait                   => System_Tasking_Rendezvous,
+     RE_Task_Entry_Call                  => System_Tasking_Rendezvous,
+     RE_Task_Entry_Caller                => System_Tasking_Rendezvous,
+     RE_Timed_Task_Entry_Call            => System_Tasking_Rendezvous,
+     RE_Timed_Selective_Wait             => System_Tasking_Rendezvous,
+
+     RE_Activate_Restricted_Tasks        => System_Tasking_Restricted_Stages,
+     RE_Complete_Restricted_Activation   => System_Tasking_Restricted_Stages,
+     RE_Create_Restricted_Task           => System_Tasking_Restricted_Stages,
+     RE_Complete_Restricted_Task         => System_Tasking_Restricted_Stages,
+     RE_Restricted_Terminated            => System_Tasking_Restricted_Stages,
+
+     RE_Abort_Tasks                      => System_Tasking_Stages,
+     RE_Activate_Tasks                   => System_Tasking_Stages,
+     RE_Complete_Activation              => System_Tasking_Stages,
+     RE_Create_Task                      => System_Tasking_Stages,
+     RE_Complete_Task                    => System_Tasking_Stages,
+     RE_Free_Task                        => System_Tasking_Stages,
+     RE_Expunge_Unactivated_Tasks        => System_Tasking_Stages,
+     RE_Terminated                       => System_Tasking_Stages);
+
+   -----------------
+   -- Subprograms --
+   -----------------
+
+   procedure Initialize;
+   --  Procedure to initialize data structures used by RTE. Called at the
+   --  start of processing a new main source file. Must be called after
+   --  Initialize_Snames (since names it enters into name table must come
+   --  after names entered by Snames).
+
+   function RTE (E : RE_Id) return Entity_Id;
+   --  Given the entity defined in the above tables, as identified by the
+   --  corresponding value in the RE_Id enumeration type, returns the Id
+   --  of the corresponding entity, first loading in (parsing, analyzing and
+   --  expanding) its spec if the unit has not already been loaded. If the
+   --  unit cannot be found, or if it does not contain the specified entity,
+   --  then an appropriate error message is output ("run-time configuration
+   --  error") and an Unrecoverable_Error exception is raised.
+
+   function Is_RTE (Ent : Entity_Id; E : RE_Id) return Boolean;
+   --  This function determines if the given entity corresponds to the entity
+   --  referenced by RE_Id. It is similar in effect to (Ent = RTE (E)) except
+   --  that the latter would unconditionally load the unit containing E. For
+   --  this call, if the unit is not loaded, then a result of False is returned
+   --  immediately, since obviously Ent cannot be the entity in question if the
+   --  corresponding unit has not been loaded.
+
+   procedure Text_IO_Kludge (Nam : Node_Id);
+   --  In Ada 83, and hence for compatibility in Ada 9X, package Text_IO has
+   --  generic subpackages (e.g. Integer_IO). They really should be child
+   --  packages, and in GNAT, they *are* child packages. To maintain the
+   --  required compatibility, this routine is called for package renamings
+   --  and generic instantiations, with the simple name of the referenced
+   --  package. If Text_IO has been with'ed and if the simple name of Nam
+   --  matches one of the subpackages of Text_IO, then this subpackage is
+   --  with'ed automatically. The important result of this approach is that
+   --  Text_IO does not drag in all the code for the subpackages unless they
+   --  are used. Our test is a little crude, and could drag in stuff when it
+   --  is not necessary, but that doesn't matter. Wide_Text_IO is handled in
+   --  a similar manner.
+
+   function Is_Text_IO_Kludge_Unit (Nam : Node_Id) return Boolean;
+   --  Returns True if the given Nam is an Expanded Name, whose Prefix is
+   --  Ada, and whose selector is either Text_IO.xxx or Wide_Text_IO.xxx
+   --  where xxx is one of the subpackages of Text_IO that is specially
+   --  handled as described above for Text_IO_Kludge.
+
+end Rtsfind;