New Language: Ada
From-SVN: r45956
This commit is contained in:
parent
38cbfe40a0
commit
19235870ad
57 changed files with 38371 additions and 0 deletions
1080
gcc/ada/par-ch10.adb
Normal file
1080
gcc/ada/par-ch10.adb
Normal file
File diff suppressed because it is too large
Load diff
246
gcc/ada/par-ch11.adb
Normal file
246
gcc/ada/par-ch11.adb
Normal file
|
@ -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;
|
882
gcc/ada/par-ch12.adb
Normal file
882
gcc/ada/par-ch12.adb
Normal file
|
@ -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;
|
441
gcc/ada/par-ch13.adb
Normal file
441
gcc/ada/par-ch13.adb
Normal file
|
@ -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;
|
405
gcc/ada/par-ch2.adb
Normal file
405
gcc/ada/par-ch2.adb
Normal file
|
@ -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;
|
3724
gcc/ada/par-ch3.adb
Normal file
3724
gcc/ada/par-ch3.adb
Normal file
File diff suppressed because it is too large
Load diff
2298
gcc/ada/par-ch4.adb
Normal file
2298
gcc/ada/par-ch4.adb
Normal file
File diff suppressed because it is too large
Load diff
2184
gcc/ada/par-ch5.adb
Normal file
2184
gcc/ada/par-ch5.adb
Normal file
File diff suppressed because it is too large
Load diff
1165
gcc/ada/par-ch6.adb
Normal file
1165
gcc/ada/par-ch6.adb
Normal file
File diff suppressed because it is too large
Load diff
282
gcc/ada/par-ch7.adb
Normal file
282
gcc/ada/par-ch7.adb
Normal file
|
@ -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;
|
175
gcc/ada/par-ch8.adb
Normal file
175
gcc/ada/par-ch8.adb
Normal file
|
@ -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;
|
1616
gcc/ada/par-ch9.adb
Normal file
1616
gcc/ada/par-ch9.adb
Normal file
File diff suppressed because it is too large
Load diff
1191
gcc/ada/par-endh.adb
Normal file
1191
gcc/ada/par-endh.adb
Normal file
File diff suppressed because it is too large
Load diff
202
gcc/ada/par-labl.adb
Normal file
202
gcc/ada/par-labl.adb
Normal file
|
@ -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;
|
410
gcc/ada/par-load.adb
Normal file
410
gcc/ada/par-load.adb
Normal file
|
@ -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;
|
950
gcc/ada/par-prag.adb
Normal file
950
gcc/ada/par-prag.adb
Normal file
|
@ -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;
|
312
gcc/ada/par-sync.adb
Normal file
312
gcc/ada/par-sync.adb
Normal file
|
@ -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;
|
812
gcc/ada/par-tchk.adb
Normal file
812
gcc/ada/par-tchk.adb
Normal file
|
@ -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;
|
638
gcc/ada/par-util.adb
Normal file
638
gcc/ada/par-util.adb
Normal file
|
@ -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;
|
1181
gcc/ada/par.adb
Normal file
1181
gcc/ada/par.adb
Normal file
File diff suppressed because it is too large
Load diff
44
gcc/ada/par.ads
Normal file
44
gcc/ada/par.ads
Normal file
|
@ -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.
|
211
gcc/ada/prj-attr.adb
Normal file
211
gcc/ada/prj-attr.adb
Normal file
|
@ -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;
|
108
gcc/ada/prj-attr.ads
Normal file
108
gcc/ada/prj-attr.ads
Normal file
|
@ -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;
|
49
gcc/ada/prj-com.adb
Normal file
49
gcc/ada/prj-com.adb
Normal file
|
@ -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;
|
92
gcc/ada/prj-com.ads
Normal file
92
gcc/ada/prj-com.ads
Normal file
|
@ -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;
|
942
gcc/ada/prj-dect.adb
Normal file
942
gcc/ada/prj-dect.adb
Normal file
|
@ -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;
|
41
gcc/ada/prj-dect.ads
Normal file
41
gcc/ada/prj-dect.ads
Normal file
|
@ -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;
|
1471
gcc/ada/prj-env.adb
Normal file
1471
gcc/ada/prj-env.adb
Normal file
File diff suppressed because it is too large
Load diff
99
gcc/ada/prj-env.ads
Normal file
99
gcc/ada/prj-env.ads
Normal file
|
@ -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;
|
130
gcc/ada/prj-ext.adb
Normal file
130
gcc/ada/prj-ext.adb
Normal file
|
@ -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;
|
51
gcc/ada/prj-ext.ads
Normal file
51
gcc/ada/prj-ext.ads
Normal file
|
@ -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;
|
2236
gcc/ada/prj-nmsc.adb
Normal file
2236
gcc/ada/prj-nmsc.adb
Normal file
File diff suppressed because it is too large
Load diff
43
gcc/ada/prj-nmsc.ads
Normal file
43
gcc/ada/prj-nmsc.ads
Normal file
|
@ -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;
|
92
gcc/ada/prj-pars.adb
Normal file
92
gcc/ada/prj-pars.adb
Normal file
|
@ -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;
|
44
gcc/ada/prj-pars.ads
Normal file
44
gcc/ada/prj-pars.ads
Normal file
|
@ -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;
|
871
gcc/ada/prj-part.adb
Normal file
871
gcc/ada/prj-part.adb
Normal file
|
@ -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;
|
46
gcc/ada/prj-part.ads
Normal file
46
gcc/ada/prj-part.ads
Normal file
|
@ -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;
|
1371
gcc/ada/prj-proc.adb
Normal file
1371
gcc/ada/prj-proc.adb
Normal file
File diff suppressed because it is too large
Load diff
45
gcc/ada/prj-proc.ads
Normal file
45
gcc/ada/prj-proc.ads
Normal file
|
@ -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;
|
943
gcc/ada/prj-strt.adb
Normal file
943
gcc/ada/prj-strt.adb
Normal file
|
@ -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;
|
96
gcc/ada/prj-strt.ads
Normal file
96
gcc/ada/prj-strt.ads
Normal file
|
@ -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;
|
1478
gcc/ada/prj-tree.adb
Normal file
1478
gcc/ada/prj-tree.adb
Normal file
File diff suppressed because it is too large
Load diff
742
gcc/ada/prj-tree.ads
Normal file
742
gcc/ada/prj-tree.ads
Normal file
|
@ -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;
|
415
gcc/ada/prj-util.adb
Normal file
415
gcc/ada/prj-util.adb
Normal file
|
@ -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;
|
148
gcc/ada/prj-util.ads
Normal file
148
gcc/ada/prj-util.ads
Normal file
|
@ -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;
|
286
gcc/ada/prj.adb
Normal file
286
gcc/ada/prj.adb
Normal file
|
@ -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;
|
416
gcc/ada/prj.ads
Normal file
416
gcc/ada/prj.ads
Normal file
|
@ -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;
|
86
gcc/ada/raise.c
Normal file
86
gcc/ada/raise.c
Normal file
|
@ -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
|
||||
}
|
71
gcc/ada/raise.h
Normal file
71
gcc/ada/raise.h
Normal file
|
@ -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;
|
||||
|
1024
gcc/ada/repinfo.adb
Normal file
1024
gcc/ada/repinfo.adb
Normal file
File diff suppressed because it is too large
Load diff
320
gcc/ada/repinfo.ads
Normal file
320
gcc/ada/repinfo.ads
Normal file
|
@ -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;
|
79
gcc/ada/repinfo.h
Normal file
79
gcc/ada/repinfo.h
Normal file
|
@ -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));
|
458
gcc/ada/restrict.adb
Normal file
458
gcc/ada/restrict.adb
Normal file
|
@ -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;
|
253
gcc/ada/restrict.ads
Normal file
253
gcc/ada/restrict.ads
Normal file
|
@ -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;
|
139
gcc/ada/rident.ads
Normal file
139
gcc/ada/rident.ads
Normal file
|
@ -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;
|
913
gcc/ada/rtsfind.adb
Normal file
913
gcc/ada/rtsfind.adb
Normal file
|
@ -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;
|
2324
gcc/ada/rtsfind.ads
Normal file
2324
gcc/ada/rtsfind.ads
Normal file
File diff suppressed because it is too large
Load diff
Loading…
Add table
Reference in a new issue