------------------------------------------------------------------------------
--                                                                          --
--                           POLYORB COMPONENTS                             --
--                                                                          --
--                             X E _ U N I T S                              --
--                                                                          --
--                                 S p e c                                  --
--                                                                          --
--         Copyright (C) 1995-2008, Free Software Foundation, Inc.          --
--                                                                          --
-- PolyORB is free software; you  can  redistribute  it and/or modify it    --
-- under terms of the  GNU General Public License as published by the  Free --
-- Software Foundation;  either version 2,  or (at your option)  any  later --
-- version. PolyORB is distributed  in the hope that it will be  useful,    --
-- but WITHOUT ANY WARRANTY;  without even the implied warranty of MERCHAN- --
-- TABILITY 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 PolyORB; see file COPYING. If    --
-- not, write to the Free Software Foundation, 51 Franklin Street, Fifth    --
-- Floor, Boston, MA 02111-1301, USA.                                       --
--                                                                          --
--                                                                          --
--                  PolyORB is maintained by AdaCore                        --
--                     (email: sales@adacore.com)                           --
--                                                                          --
------------------------------------------------------------------------------

--  This package provides all the types and tables required to
--  represent the configuration of the distributed system like
--  Ada units, configured units, partitions, channels, locations, ...

with GNAT.Table;

with XE;       use XE;
with XE_Types; use XE_Types;

package XE_Units is

   ----------------
   -- Name Types --
   ----------------

   No_Unit_Name : constant Unit_Name_Type := Unit_Name_Type (No_Name);

   subtype Partition_Name_Type is Unit_Name_Type;
   No_Partition_Name : constant Partition_Name_Type := No_Unit_Name;

   subtype Channel_Name_Type is Name_Id;
   No_Channel_Name : constant Channel_Name_Type := Channel_Name_Type (No_Name);

   subtype Filter_Name_Type is Name_Id;
   No_Filter_Name : constant Filter_Name_Type := Filter_Name_Type (No_Name);

   subtype Host_Name_Type is Name_Id;
   No_Host_Name : constant Host_Name_Type := Host_Name_Type (No_Name);

   subtype Main_Subprogram_Type is Unit_Name_Type;
   No_Main_Subprogram : constant Main_Subprogram_Type := No_Unit_Name;

   subtype Command_Line_Type is Name_Id;
   No_Command_Line : constant Command_Line_Type := Command_Line_Type (No_Name);

   subtype Directory_Name_Type is File_Name_Type;
   No_Directory_Name  : constant Directory_Name_Type := No_File_Name;

   -------------------
   -- Tasking Types --
   -------------------

   type Task_Pool_Type is array (1 .. 3) of Int;
   No_Task_Pool : constant Task_Pool_Type := (-1, -1, -1);

   type Priority_Type is new Int;
   No_Priority : constant Priority_Type := -1;

   --------------
   -- Id Types --
   --------------

   --  The various entries are stored in tables with distinct subscript
   --  ranges. The following type definitions indicate the ranges used
   --  for the subscripts (Id values) for the various tables.

   type ALI_Id is range 0 .. 999_999;
   --  Id values used for ALIs table entries

   No_ALI_Id    : constant ALI_Id := ALI_Id'First;
   First_ALI_Id : constant ALI_Id := No_ALI_Id + 1;

   type Unit_Id is range 1_000_000 .. 1_999_999;
   --  Id values used for Unit table entries

   No_Unit_Id    : constant Unit_Id := Unit_Id'First;
   First_Unit_Id : constant Unit_Id := No_Unit_Id + 1;

   type With_Id is range 2_000_000 .. 2_999_999;
   --  Id values used for Withs table entries

   No_With_Id    : constant With_Id := With_Id'First;
   First_With_Id : constant With_Id := No_With_Id + 1;

   type Sdep_Id is range 4_000_000 .. 4_999_999;
   --  Id values used for Sdep table entries

   No_Sdep_Id    : constant Sdep_Id := Sdep_Id'First;
   First_Sdep_Id : constant Sdep_Id := No_Sdep_Id + 1;

   type Partition_Id is range 7_000_000 .. 7_000_255;

   No_Partition_Id    : constant Partition_Id := Partition_Id'First;
   First_Partition_Id : constant Partition_Id := No_Partition_Id + 1;

   type Conf_Unit_Id is range 7_100_000 .. 7_199_999;

   No_Conf_Unit_Id    : constant Conf_Unit_Id := Conf_Unit_Id'First;
   First_Conf_Unit_Id : constant Conf_Unit_Id := No_Conf_Unit_Id + 1;

   type Channel_Id is range 7_200_000 .. 7_299_999;

   No_Channel_Id    : constant Channel_Id := Channel_Id'First;
   First_Channel_Id : constant Channel_Id := No_Channel_Id + 1;

   type Host_Id is range 7_300_000 .. 7_399_999;

   No_Host_Id    : constant Host_Id := Host_Id'First;
   First_Host_Id : constant Host_Id := No_Host_Id + 1;

   type Location_Id is range 7_400_000 .. 7_499_999;

   No_Location_Id    : constant Location_Id := Location_Id'First;
   First_Location_Id : constant Location_Id := No_Location_Id + 1;

   type Stub_Id is range 7_500_000 .. 7_599_999;

   No_Stub_Id    : constant Stub_Id := Stub_Id'First;
   First_Stub_Id : constant Stub_Id := No_Stub_Id + 1;

   type Env_Var_Id is range 7_500_000 .. 7_599_999;

   No_Env_Var_Id    : constant Env_Var_Id := Env_Var_Id'First;
   First_Env_Var_Id : constant Env_Var_Id := No_Env_Var_Id + 1;

   type Required_Storage_Id is range 7_600_000 .. 7_699_999;

   No_Required_Storage_Id    : constant Required_Storage_Id :=
                                 Required_Storage_Id'First;
   First_Required_Storage_Id : constant Required_Storage_Id :=
                                 No_Required_Storage_Id + 1;

   --------------------
   -- ALI File Table --
   --------------------

   --  Each ALI file read generates an entry in the ALIs table

   type Main_Program_Type is (None, Proc, Func);
   --  Indicator of whether unit can be used as main program

   type ALIs_Record is record

      Ofile : File_Name_Type;
      --  Name of object file

      Afile : File_Name_Type;
      --  Name of ALI file

      Sfile : File_Name_Type;
      --  Name of source file that generates this ALI file (which is equal
      --  to the name of the source file in the first unit table entry for
      --  this ALI file, since the body if present is always first).

      Uname : Unit_Name_Type;
      --  Name of Unit

      First_Unit : Unit_Id;
      --  Id of first Unit table entry for this file

      Last_Unit : Unit_Id;
      --  Id of last Unit table entry for this file

      First_Sdep : Sdep_Id;
      --  Id of first Sdep table entry for this file

      Last_Sdep : Sdep_Id;
      --  Id of last Sdep table entry for this file

      Main_Program : Main_Program_Type;
      --  Indicator of whether first unit can be used as main program.

      Tasking : Tasking_Type;
      --  Indicator of whether the unit (or the collocated units it
      --  depends on) drags tasking.
      --  Notation:
      --     Unknown_Tasking : tasking has not been established
      --     PCS_Tasking     : tasking is required because of PCS code
      --     User_Tasking    : tasking is required because of user code
      --     No_Tasking      : tasking is not required for this unit
      --  Note that PCS_Tasking is a stronger property than User_Tasking
      --  as this has also an impact on the termination policy.

   end record;

   Default_ALI : constant ALIs_Record := (
      Ofile        => No_File_Name,
      Afile        => No_File_Name,
      Sfile        => No_File_Name,
      Uname        => No_Unit_Name,
      First_Unit   => No_Unit_Id,
      Last_Unit    => No_Unit_Id,
      First_Sdep   => First_Sdep_Id,
      Last_Sdep    => No_Sdep_Id,
      Main_Program => None,
      Tasking      => Unknown_Tasking);

   package ALIs is new GNAT.Table (
     Table_Component_Type => ALIs_Record,
     Table_Index_Type     => ALI_Id,
     Table_Low_Bound      => First_ALI_Id,
     Table_Initial        => 500,
     Table_Increment      => 200);

   ----------------
   -- Unit Table --
   ----------------

   --  Each unit within an ALI file generates an entry in the unit table

   type Unit_Type is (Is_Spec, Is_Body, Is_Spec_Only, Is_Body_Only);
   --  Indicates type of entry, if both body and spec appear in the ALI file,
   --  then the first unit is marked Is_Body, and the second is marked Is_Spec.
   --  If only a spec appears, then it is marked as Is_Spec_Only, and if only
   --  a body appears, then it is marked Is_Body_Only).

   type Unit_Record is record

      My_ALI : ALI_Id;
      --  Corresponding ALI entry

      Uname : Unit_Name_Type;
      --  Name of Unit

      Sfile : File_Name_Type;
      --  Name of source file

      First_With : With_Id;
      --  Id of first withs table entry for this file

      Last_With : With_Id;
      --  Id of last withs table entry for this file

      Has_RACW : Boolean;
      --  Indicates presence of RA parameter for a package that declares
      --  at least one Remote Access to Class_Wide (RACW) object.
      Remote_Types : Boolean;
      --  Indicates a Remote_Types package.

      Shared_Passive : Boolean;
      --  Indicates a Shared_Passive package.

      RCI : Boolean;
      --  Indicates a Remote_Call_Interface package.

      Preelaborated : Boolean;
      --  Indicates a preelaborated package.

      Pure : Boolean;
      --  Indicates a pure package.

      Predefined : Boolean;
      --  Indicates if unit is language predefined (or a child of such a unit)

      Internal : Boolean;
      --  Indicates if unit is an internal unit (or a child of such a unit)

      Utype : Unit_Type;
      --  Type of entry

      Is_Generic : Boolean;
      --  True for generic unit (i.e. a generic declaration, or a generic
      --  body). False for a non-generic unit.

      Unit_Kind : Character;
      --  Indicates the nature of the unit. 'p' for Packages and 's' for
      --  subprograms.

   end record;

   package Units is new GNAT.Table (
     Table_Component_Type => Unit_Record,
     Table_Index_Type     => Unit_Id,
     Table_Low_Bound      => First_Unit_Id,
     Table_Initial        => 100,
     Table_Increment      => 200);

   Default_Unit : constant Unit_Record := (
      My_ALI         => No_ALI_Id,
      Uname          => No_Unit_Name,
      Sfile          => No_File_Name,
      First_With     => First_With_Id,
      Last_With      => No_With_Id,
      Has_RACW       => False,
      Remote_Types   => False,
      Shared_Passive => False,
      RCI            => False,
      Preelaborated  => False,
      Pure           => False,
      Predefined     => False,
      Internal       => False,
      Utype          => Is_Spec_Only,
      Is_Generic     => False,
      Unit_Kind      => 'p');

   ----------------
   -- With Table --
   ----------------

   --  Each with within an ALI file generates an entry in the Withs table

   type With_Record is record

      Uname : Unit_Name_Type;
      --  Name of Unit

      Sfile : File_Name_Type;
      --  Name of source file, set to No_File in generic case

      Afile : File_Name_Type;
      --  Name of ALI file, set to No_File in generic case
   end record;

   package Withs is new GNAT.Table (
     Table_Component_Type => With_Record,
     Table_Index_Type     => With_Id,
     Table_Low_Bound      => First_With_Id,
     Table_Initial        => 100,
     Table_Increment      => 200);

   Default_With : constant With_Record := (
      Uname          => No_Unit_Name,
      Afile          => No_File_Name,
      Sfile          => No_File_Name);

   ------------------------------------
   -- Sdep (Source Dependency) Table --
   ------------------------------------

   --  Each source dependency (D line) in an ALI file generates an
   --  entry in the Sdep table.

   type Sdep_Record is record

      Sfile : File_Name_Type;
      --  Name of source file

   end record;

   package Sdep is new GNAT.Table (
     Table_Component_Type => Sdep_Record,
     Table_Index_Type     => Sdep_Id,
     Table_Low_Bound      => First_Sdep_Id,
     Table_Initial        => 5000,
     Table_Increment      => 200);

   ---------------------
   -- Partition Table --
   ---------------------

   type Partition_Type is record

      Name : Partition_Name_Type;
      --  Name of partition

      First_Unit : Conf_Unit_Id;
      --  Id of first unit table entry for this partition

      Last_Unit : Conf_Unit_Id;
      --  Id of last unit table entry for this partition

      Main_Subprogram : Unit_Name_Type;
      --  Main subprogram for this partition

      First_Stub : Stub_Id;
      --  Id of first stub unit table entry for this partition

      Last_Stub : Stub_Id;
      --  Id of last stub unit table entry for this partition

      First_Channel : Channel_Id;
      --  Id of first channel table entry for this partition

      Last_Channel : Channel_Id;
      --  Id of last channel table entry for this partition

      First_Env_Var : Env_Var_Id;
      --  Id of first environment variables entry for this partition

      Last_Env_Var : Env_Var_Id;
      --  Id of last environment variables entry for this partition

      Passive : Boolean_Type;
      --  Indicate whether this partition is passive

      Tasking : Tasking_Type;
      --  Indicate why this partition requires tasking.
      --  Notation:
      --     Unknown_Tasking : tasking has not been established
      --     PCS_Tasking     : tasking is required because of PCS code
      --     User_Tasking    : tasking is required because of user code
      --     No_Tasking      : tasking is not required for this unit

      ORB_Tasking_Policy : ORB_Tasking_Policy_Type;
      --  ORB tasking policy to activate on this partition.
      --  Has no effect in Garlic PCS.

      Task_Pool : Task_Pool_Type;
      --  Configuration of the task pool

      Priority : Priority_Type;
      --  Priority to which remote calls are executed when priority
      --  policy is server declared.

      Light_PCS : Boolean_Type;
      --  True when the partition may be configured with a light PCS

      Termination : Termination_Type;
      --  Termination policy to activate on this partition

      Reconnection : Reconnection_Type;
      --  Reconnection policy to execute on this partition when
      --  another partition crashes.

      Host : Host_Id;
      --  Host on which this partition has to be launched

      Command_Line : Command_Line_Type;
      --  Command line to pass when we launch the partition

      First_Network_Loc : Location_Id;
      --  Id of first network location table entry for this partition

      Last_Network_Loc : Location_Id;
      --  Id of last network location table entry for this partition

      Storage_Loc : Location_Id;
      --  Id of storage location table entry for this partition

      First_Required_Storage : Required_Storage_Id;
      --  Id of first location needed by this partition for shared storage

      Last_Required_Storage : Required_Storage_Id;
      --  Id of last location needed by this partition for shared storage

      Filter : Filter_Name_Type;
      --  Name of filter to apply during filter registration

      Partition_Dir : File_Name_Type;
      --  Internal directory in which we build the partition

      Executable_Dir : Directory_Name_Type;
      --  Directory to store the executable file

      Executable_File : File_Name_Type;
      --  Fully qualified executable file name

      To_Build : Boolean;
      --  True when we want to build this partition

      Node : Node_Id;
      --  Frontend node

      Most_Recent : File_Name_Type;
      --  Most recent source file of this partition

   end record;

   package Partitions is new GNAT.Table
     (Table_Component_Type => Partition_Type,
      Table_Index_Type     => Partition_Id,
      Table_Low_Bound      => First_Partition_Id,
      Table_Initial        => 20,
      Table_Increment      => 10);

   Null_Partition : constant Partition_Type :=
     (Name                   => No_Partition_Name,
      First_Unit             => No_Conf_Unit_Id,
      Last_Unit              => No_Conf_Unit_Id,
      Main_Subprogram        => No_Unit_Name,
      First_Stub             => First_Stub_Id,
      Last_Stub              => No_Stub_Id,
      First_Channel          => No_Channel_Id,
      Last_Channel           => No_Channel_Id,
      First_Env_Var          => No_Env_Var_Id,
      Last_Env_Var           => No_Env_Var_Id,
      Passive                => BMaybe,
      Tasking                => Unknown_Tasking,
      ORB_Tasking_Policy     => No_ORB_Tasking_Policy,
      Task_Pool              => No_Task_Pool,
      Priority               => No_Priority,
      Light_PCS              => BMaybe,
      Termination            => No_Termination,
      Reconnection           => No_Reconnection,
      Command_Line           => No_Command_Line,
      Host                   => No_Host_Id,
      First_Network_Loc      => No_Location_Id,
      Last_Network_Loc       => No_Location_Id,
      Storage_Loc            => No_Location_Id,
      First_Required_Storage => No_Required_Storage_Id,
      Last_Required_Storage  => No_Required_Storage_Id,
      Filter                 => No_Filter_Name,
      Partition_Dir          => No_Directory_Name,
      Executable_Dir         => No_Directory_Name,
      Executable_File        => No_File_Name,
      To_Build               => True,
      Node                   => Null_Node,
      Most_Recent            => No_File_Name);

   ---------------------------
   -- Configured Unit Table --
   ---------------------------

   --  Configured units are different from units. Such units come from the
   --  configuration language and mau not correspond to Ada units in case
   --  of an illegal configuration file.

   type Conf_Unit_Type is record

      Name : Unit_Name_Type;
      --  Name of unit

      Node : Node_Id;
      --  Frontend node

      My_ALI : ALI_Id;
      --  Corresponding ALI id

      My_Unit : Unit_Id;
      --  Corresponding unit id

      Partition : Partition_Id;
      --  Partition on which this unit is assigned

      Next_Unit : Conf_Unit_Id;
      --  Next unit assigned on the unit partition

      Most_Recent : File_Name_Type;
      --  Most recent file for this unit

   end record;

   package Conf_Units is new GNAT.Table
     (Table_Component_Type => Conf_Unit_Type,
      Table_Index_Type     => Conf_Unit_Id,
      Table_Low_Bound      => First_Conf_Unit_Id,
      Table_Initial        => 200,
      Table_Increment      => 100);

   Null_Conf_Unit : constant Conf_Unit_Type :=
     (Name        => No_Unit_Name,
      Node        => Null_Node,
      My_ALI      => No_ALI_Id,
      My_Unit     => No_Unit_Id,
      Partition   => No_Partition_Id,
      Next_Unit   => No_Conf_Unit_Id,
      Most_Recent => No_File_Name);

   -------------------
   -- Channel Types --
   -------------------

   type Channel_Partition_Type is record
      My_Partition : Partition_Id;
      Next_Channel : Channel_Id;
   end record;

   Null_Channel_Partition : Channel_Partition_Type :=
     (No_Partition_Id, No_Channel_Id);

   type Channel_Type is record
      Name   : Channel_Name_Type;
      Node   : Node_Id;
      Lower  : Channel_Partition_Type;
      Upper  : Channel_Partition_Type;
      Filter : Filter_Name_Type;
   end record;

   package Channels  is new GNAT.Table
     (Table_Component_Type => Channel_Type,
      Table_Index_Type     => Channel_Id,
      Table_Low_Bound      => First_Channel_Id,
      Table_Initial        => 20,
      Table_Increment      => 10);

   ----------------
   -- Host Table --
   ----------------

   type Host_Type is record
      Name        : Host_Name_Type;
      Node        : Node_Id;
      Static      : Boolean            := True;
      Import      : Import_Method_Type := None_Import;
      External    : Host_Name_Type     := No_Host_Name;
      Most_Recent : File_Name_Type     := No_File_Name;
   end record;

   package Hosts is new GNAT.Table
     (Table_Component_Type => Host_Type,
      Table_Index_Type     => Host_Id,
      Table_Low_Bound      => First_Host_Id,
      Table_Initial        => 20,
      Table_Increment      => 10);

   --------------------
   -- Location Table --
   --------------------

   type Location_Type is record
      Major         : Name_Id;
      Minor         : Name_Id;
      Next_Location : Location_Id;
   end record;

   package Locations is new GNAT.Table
     (Table_Component_Type => Location_Type,
      Table_Index_Type     => Location_Id,
      Table_Low_Bound      => First_Location_Id,
      Table_Initial        => 20,
      Table_Increment      => 10);

   ----------------
   -- Stub Table --
   ----------------

   package Stubs is new GNAT.Table
     (Table_Component_Type => Unit_Name_Type,
      Table_Index_Type     => Stub_Id,
      Table_Low_Bound      => First_Stub_Id,
      Table_Initial        => 20,
      Table_Increment      => 10);

   -------------------
   -- Env var Table --
   -------------------

   type Env_Var_Type is record
      Name         : Name_Id;
      Next_Env_Var : Env_Var_Id;
   end record;

   package Env_Vars is new GNAT.Table
     (Table_Component_Type => Env_Var_Type,
      Table_Index_Type     => Env_Var_Id,
      Table_Low_Bound      => First_Env_Var_Id,
      Table_Initial        => 20,
      Table_Increment      => 10);

   ----------------------------
   -- Required Storage Table --
   ----------------------------

   type Required_Storage_Type is record
      Location     : Location_Id;
      Is_Owner     : Boolean;
      Unit         : Unit_Id;
      Next_Storage : Required_Storage_Id;
   end record;

   package Required_Storages is new GNAT.Table
     (Table_Component_Type => Required_Storage_Type,
      Table_Index_Type     => Required_Storage_Id,
      Table_Low_Bound      => First_Required_Storage_Id,
      Table_Initial        => 20,
      Table_Increment      => 10);

end XE_Units;
