------------------------------------------------------------------------------
--                                                                          --
--                        GNAT RUN-TIME COMPONENTS                          --
--                                                                          --
--                             T A R G P A R M                              --
--                                                                          --
--                                 B o d y                                  --
--                                                                          --
--          Copyright (C) 1999-2019, 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 3,  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 COPYING3.  If not, go to --
-- http://www.gnu.org/licenses for a complete copy of the license.          --
--                                                                          --
-- GNAT was originally developed  by the GNAT team at  New York University. --
-- Extensive contributions were provided by Ada Core Technologies Inc.      --
--                                                                          --
------------------------------------------------------------------------------

with Csets;         use Csets;
with Opt;
with Osint;         use Osint;
with Output;        use Output;
with System.OS_Lib; use System.OS_Lib;

package body Targparm is
   use ASCII;

   Parameters_Obtained : Boolean := False;
   --  Set True after first call to Get_Target_Parameters. Used to avoid
   --  reading system.ads more than once, since it cannot change.

   --  The following array defines a tag name for each entry

   type Targparm_Tags is
     (AAM,  --   AAMP
      ACR,  --   Always_Compatible_Rep
      ASD,  --   Atomic_Sync_Default
      BDC,  --   Backend_Divide_Checks
      BOC,  --   Backend_Overflow_Checks
      CLA,  --   Command_Line_Args
      CRT,  --   Configurable_Run_Times
      D32,  --   Duration_32_Bits
      DEN,  --   Denorm
      EXS,  --   Exit_Status_Supported
      FEL,  --   Frontend_Layout
      FEX,  --   Frontend_Exceptions
      FFO,  --   Fractional_Fixed_Ops
      MOV,  --   Machine_Overflows
      MRN,  --   Machine_Rounds
      PAS,  --   Preallocated_Stacks
      SAG,  --   Support_Aggregates
      SAP,  --   Support_Atomic_Primitives
      SCA,  --   Support_Composite_Assign
      SCC,  --   Support_Composite_Compare
      SCD,  --   Stack_Check_Default
      SCL,  --   Stack_Check_Limits
      SCP,  --   Stack_Check_Probes
      SLS,  --   Support_Long_Shifts
      SNZ,  --   Signed_Zeros
      SSL,  --   Suppress_Standard_Library
      UAM,  --   Use_Ada_Main_Program_Name
      ZCX); --   ZCX_By_Default

   Targparm_Flags : array (Targparm_Tags) of Boolean := (others => False);
   --  Flag is set True if corresponding parameter is scanned

   --  The following list of string constants gives the parameter names

   AAM_Str : aliased constant Source_Buffer := "AAMP";
   ACR_Str : aliased constant Source_Buffer := "Always_Compatible_Rep";
   ASD_Str : aliased constant Source_Buffer := "Atomic_Sync_Default";
   BDC_Str : aliased constant Source_Buffer := "Backend_Divide_Checks";
   BOC_Str : aliased constant Source_Buffer := "Backend_Overflow_Checks";
   CLA_Str : aliased constant Source_Buffer := "Command_Line_Args";
   CRT_Str : aliased constant Source_Buffer := "Configurable_Run_Time";
   D32_Str : aliased constant Source_Buffer := "Duration_32_Bits";
   DEN_Str : aliased constant Source_Buffer := "Denorm";
   EXS_Str : aliased constant Source_Buffer := "Exit_Status_Supported";
   FEL_Str : aliased constant Source_Buffer := "Frontend_Layout";
   FEX_Str : aliased constant Source_Buffer := "Frontend_Exceptions";
   FFO_Str : aliased constant Source_Buffer := "Fractional_Fixed_Ops";
   MOV_Str : aliased constant Source_Buffer := "Machine_Overflows";
   MRN_Str : aliased constant Source_Buffer := "Machine_Rounds";
   PAS_Str : aliased constant Source_Buffer := "Preallocated_Stacks";
   SAG_Str : aliased constant Source_Buffer := "Support_Aggregates";
   SAP_Str : aliased constant Source_Buffer := "Support_Atomic_Primitives";
   SCA_Str : aliased constant Source_Buffer := "Support_Composite_Assign";
   SCC_Str : aliased constant Source_Buffer := "Support_Composite_Compare";
   SCD_Str : aliased constant Source_Buffer := "Stack_Check_Default";
   SCL_Str : aliased constant Source_Buffer := "Stack_Check_Limits";
   SCP_Str : aliased constant Source_Buffer := "Stack_Check_Probes";
   SLS_Str : aliased constant Source_Buffer := "Support_Long_Shifts";
   SNZ_Str : aliased constant Source_Buffer := "Signed_Zeros";
   SSL_Str : aliased constant Source_Buffer := "Suppress_Standard_Library";
   UAM_Str : aliased constant Source_Buffer := "Use_Ada_Main_Program_Name";
   ZCX_Str : aliased constant Source_Buffer := "ZCX_By_Default";

   --  The following defines a set of pointers to the above strings,
   --  indexed by the tag values.

   type Buffer_Ptr is access constant Source_Buffer;
   Targparm_Str : constant array (Targparm_Tags) of Buffer_Ptr :=
     (AAM => AAM_Str'Access,
      ACR => ACR_Str'Access,
      ASD => ASD_Str'Access,
      BDC => BDC_Str'Access,
      BOC => BOC_Str'Access,
      CLA => CLA_Str'Access,
      CRT => CRT_Str'Access,
      D32 => D32_Str'Access,
      DEN => DEN_Str'Access,
      EXS => EXS_Str'Access,
      FEL => FEL_Str'Access,
      FEX => FEX_Str'Access,
      FFO => FFO_Str'Access,
      MOV => MOV_Str'Access,
      MRN => MRN_Str'Access,
      PAS => PAS_Str'Access,
      SAG => SAG_Str'Access,
      SAP => SAP_Str'Access,
      SCA => SCA_Str'Access,
      SCC => SCC_Str'Access,
      SCD => SCD_Str'Access,
      SCL => SCL_Str'Access,
      SCP => SCP_Str'Access,
      SLS => SLS_Str'Access,
      SNZ => SNZ_Str'Access,
      SSL => SSL_Str'Access,
      UAM => UAM_Str'Access,
      ZCX => ZCX_Str'Access);

   -----------------------
   -- Local Subprograms --
   -----------------------

   procedure Set_Profile_Restrictions (P : Profile_Name);
   --  Set Restrictions_On_Target for the given profile

   ---------------------------
   -- Get_Target_Parameters --
   ---------------------------

   --  Version that reads in system.ads

   procedure Get_Target_Parameters
     (Make_Id : Make_Id_Type := null;
      Make_SC : Make_SC_Type := null;
      Set_NOD : Set_NOD_Type := null;
      Set_NSA : Set_NSA_Type := null;
      Set_NUA : Set_NUA_Type := null;
      Set_NUP : Set_NUP_Type := null)
   is
      FD   : File_Descriptor;
      Hi   : Source_Ptr;
      Text : Source_Buffer_Ptr;

   begin
      if Parameters_Obtained then
         return;
      end if;

      Name_Buffer (1 .. 10) := "system.ads";
      Name_Len := 10;

      Read_Source_File (Name_Find, 0, Hi, Text, FD);

      if Null_Source_Buffer_Ptr (Text) then
         Write_Line ("fatal error, run-time library not installed correctly");

         if FD = Null_FD then
            Write_Line ("cannot locate file system.ads");
         else
            Write_Line ("no read access for file system.ads");
         end if;

         raise Unrecoverable_Error;
      end if;

      Get_Target_Parameters
        (System_Text  => Text,
         Source_First => 0,
         Source_Last  => Hi,
         Make_Id      => Make_Id,
         Make_SC      => Make_SC,
         Set_NOD      => Set_NOD,
         Set_NSA      => Set_NSA,
         Set_NUA      => Set_NUA,
         Set_NUP      => Set_NUP);
   end Get_Target_Parameters;

   --  Version where caller supplies system.ads text

   procedure Get_Target_Parameters
     (System_Text  : Source_Buffer_Ptr;
      Source_First : Source_Ptr;
      Source_Last  : Source_Ptr;
      Make_Id      : Make_Id_Type := null;
      Make_SC      : Make_SC_Type := null;
      Set_NOD      : Set_NOD_Type := null;
      Set_NSA      : Set_NSA_Type := null;
      Set_NUA      : Set_NUA_Type := null;
      Set_NUP      : Set_NUP_Type := null)
   is
      pragma Assert (System_Text'First = Source_First);
      pragma Assert (System_Text'Last = Source_Last);

      P : Source_Ptr;
      --  Scans source buffer containing source of system.ads

      Fatal : Boolean := False;
      --  Set True if a fatal error is detected

      Result : Boolean;
      --  Records boolean from system line

      OK : Boolean;
      --  Status result from Set_NUP/NSA/NUA call

      PR_Start : Source_Ptr;
      --  Pointer to ( following pragma Restrictions

      procedure Collect_Name;
      --  Scan a name starting at System_Text (P), and put Name in Name_Buffer,
      --  with Name_Len being length, folded to lower case. On return, P points
      --  just past the last character (which should be a right paren).

      function Looking_At (S : Source_Buffer) return Boolean;
      --  True if P points to the same text as S in System_Text

      function Looking_At_Skip (S : Source_Buffer) return Boolean;
      --  True if P points to the same text as S in System_Text,
      --  and if True, moves P forward to skip S as a side effect.

      ------------------
      -- Collect_Name --
      ------------------

      procedure Collect_Name is
      begin
         Name_Len := 0;
         loop
            if System_Text (P) in 'a' .. 'z'
              or else
                System_Text (P) = '_'
              or else
                System_Text (P) in '0' .. '9'
            then
               Name_Buffer (Name_Len + 1) := System_Text (P);

            elsif System_Text (P) in 'A' .. 'Z' then
               Name_Buffer (Name_Len + 1) :=
                 Character'Val (Character'Pos (System_Text (P)) + 32);

            else
               exit;
            end if;

            P := P + 1;
            Name_Len := Name_Len + 1;
         end loop;
      end Collect_Name;

      ----------------
      -- Looking_At --
      ----------------

      function Looking_At (S : Source_Buffer) return Boolean is
         Last : constant Source_Ptr := P + S'Length - 1;
      begin
         return Last <= System_Text'Last
           and then System_Text (P .. Last) = S;
      end Looking_At;

      ---------------------
      -- Looking_At_Skip --
      ---------------------

      function Looking_At_Skip (S : Source_Buffer) return Boolean is
         Result : constant Boolean := Looking_At (S);
      begin
         if Result then
            P := P + S'Length;
         end if;

         return Result;
      end Looking_At_Skip;

   --  Start of processing for Get_Target_Parameters

   begin
      if Parameters_Obtained then
         return;
      end if;

      Parameters_Obtained := True;
      Opt.Address_Is_Private := False;

      --  Loop through source lines

      --  Note: in the case or pragmas, we are only interested in pragmas that
      --  appear as configuration pragmas. These are left justified, so they
      --  do not have three spaces at the start. Pragmas appearing within the
      --  package (like Pure and No_Elaboration_Code_All) will have the three
      --  spaces at the start and so will be ignored.

      --  For a special exception, see processing for pragma Pure below

      P := Source_First;

      while not Looking_At ("end System;") loop
         --  Skip comments

         if Looking_At ("-") then
            goto Line_Loop_Continue;

         --  Test for type Address is private

         elsif Looking_At_Skip ("   type Address is private;") then
            Opt.Address_Is_Private := True;
            goto Line_Loop_Continue;

         --  Test for pragma Profile (Ravenscar);

         elsif Looking_At_Skip ("pragma Profile (Ravenscar);") then
            Set_Profile_Restrictions (Ravenscar);
            Opt.Task_Dispatching_Policy := 'F';
            Opt.Locking_Policy          := 'C';
            goto Line_Loop_Continue;

         --  Test for pragma Profile (GNAT_Extended_Ravenscar);

         elsif Looking_At_Skip
           ("pragma Profile (GNAT_Extended_Ravenscar);")
         then
            Set_Profile_Restrictions (GNAT_Extended_Ravenscar);
            Opt.Task_Dispatching_Policy := 'F';
            Opt.Locking_Policy          := 'C';
            goto Line_Loop_Continue;

         --  Test for pragma Profile (GNAT_Ravenscar_EDF);

         elsif Looking_At_Skip ("pragma Profile (GNAT_Ravenscar_EDF);") then
            Set_Profile_Restrictions (GNAT_Ravenscar_EDF);
            Opt.Task_Dispatching_Policy := 'E';
            Opt.Locking_Policy          := 'C';
            goto Line_Loop_Continue;

         --  Test for pragma Profile (Restricted);

         elsif Looking_At_Skip ("pragma Profile (Restricted);") then
            Set_Profile_Restrictions (Restricted);
            goto Line_Loop_Continue;

         --  Test for pragma Restrictions

         elsif Looking_At_Skip ("pragma Restrictions (") then
            PR_Start := P - 1;

            --  Boolean restrictions

            for K in All_Boolean_Restrictions loop
               declare
                  Rname : constant String := Restriction_Id'Image (K);

               begin
                  for J in Rname'Range loop
                     if Fold_Upper (System_Text (P + Source_Ptr (J - 1)))
                                                        /= Rname (J)
                     then
                        goto Rloop_Continue;
                     end if;
                  end loop;

                  if System_Text (P + Rname'Length) = ')' then
                     Restrictions_On_Target.Set (K) := True;
                     goto Line_Loop_Continue;
                  end if;
               end;

               <<Rloop_Continue>> null;
            end loop;

            --  Restrictions taking integer parameter

            Ploop : for K in Integer_Parameter_Restrictions loop
               declare
                  Rname : constant String :=
                            All_Parameter_Restrictions'Image (K);

                  V : Natural;
                  --  Accumulates value

               begin
                  for J in Rname'Range loop
                     if Fold_Upper (System_Text (P + Source_Ptr (J - 1)))
                                                        /= Rname (J)
                     then
                        goto Ploop_Continue;
                     end if;
                  end loop;

                  if System_Text (P + Rname'Length .. P + Rname'Length + 3) =
                                                      " => "
                  then
                     P := P + Rname'Length + 4;

                     V := 0;
                     loop
                        if System_Text (P) in '0' .. '9' then
                           declare
                              pragma Unsuppress (Overflow_Check);

                           begin
                              --  Accumulate next digit

                              V := 10 * V +
                                   Character'Pos (System_Text (P)) -
                                   Character'Pos ('0');

                           exception
                              --  On overflow, we just ignore the pragma since
                              --  that is the standard handling in this case.

                              when Constraint_Error =>
                                 goto Line_Loop_Continue;
                           end;

                        elsif System_Text (P) = '_' then
                           null;

                        elsif System_Text (P) = ')' then
                           Restrictions_On_Target.Value (K) := V;
                           Restrictions_On_Target.Set (K) := True;
                           goto Line_Loop_Continue;

                        else
                           exit Ploop;
                        end if;

                        P := P + 1;
                     end loop;

                  else
                     exit Ploop;
                  end if;
               end;

               <<Ploop_Continue>> null;
            end loop Ploop;

            --  No_Dependence case

            if Looking_At_Skip ("No_Dependence => ") then
               --  Skip this processing (and simply ignore No_Dependence lines)
               --  if caller did not supply the three subprograms we need to
               --  process these lines.

               if Make_Id = null then
                  goto Line_Loop_Continue;
               end if;

               --  We have scanned out "pragma Restrictions (No_Dependence =>"

               declare
                  Unit  : Node_Id;
                  Id    : Node_Id;
                  Start : Source_Ptr;

               begin
                  Unit := Empty;

                  --  Loop through components of name, building up Unit

                  loop
                     Start := P;
                     while System_Text (P) /= '.'
                             and then
                           System_Text (P) /= ')'
                     loop
                        P := P + 1;
                     end loop;

                     Id := Make_Id (System_Text (Start .. P - 1));

                     --  If first name, just capture the identifier

                     if Unit = Empty then
                        Unit := Id;
                     else
                        Unit := Make_SC (Unit, Id);
                     end if;

                     exit when System_Text (P) = ')';
                     P := P + 1;
                  end loop;

                  Set_NOD (Unit);
                  goto Line_Loop_Continue;
               end;

            --  No_Specification_Of_Aspect case

            elsif Looking_At_Skip ("No_Specification_Of_Aspect => ") then
               --  Skip this processing (and simply ignore the pragma), if
               --  caller did not supply the subprogram we need to process
               --  such lines.

               if Set_NSA = null then
                  goto Line_Loop_Continue;
               end if;

               --  We have scanned
               --    "pragma Restrictions (No_Specification_Of_Aspect =>"

               Collect_Name;

               if System_Text (P) /= ')' then
                  goto Bad_Restrictions_Pragma;

               else
                  Set_NSA (Name_Find, OK);

                  if OK then
                     goto Line_Loop_Continue;
                  else
                     goto Bad_Restrictions_Pragma;
                  end if;
               end if;

            --  No_Use_Of_Attribute case

            elsif Looking_At_Skip ("No_Use_Of_Attribute => ") then
               --  Skip this processing (and simply ignore No_Use_Of_Attribute
               --  lines) if caller did not supply the subprogram we need to
               --  process such lines.

               if Set_NUA = null then
                  goto Line_Loop_Continue;
               end if;

               --  We have scanned
               --    "pragma Restrictions (No_Use_Of_Attribute =>"

               Collect_Name;

               if System_Text (P) /= ')' then
                  goto Bad_Restrictions_Pragma;

               else
                  Set_NUA (Name_Find, OK);

                  if OK then
                     goto Line_Loop_Continue;
                  else
                     goto Bad_Restrictions_Pragma;
                  end if;
               end if;

            --  No_Use_Of_Pragma case

            elsif Looking_At_Skip ("No_Use_Of_Pragma => ") then
               --  Skip this processing (and simply ignore No_Use_Of_Pragma
               --  lines) if caller did not supply the subprogram we need to
               --  process such lines.

               if Set_NUP = null then
                  goto Line_Loop_Continue;
               end if;

               --  We have scanned
               --    "pragma Restrictions (No_Use_Of_Pragma =>"

               Collect_Name;

               if System_Text (P) /= ')' then
                  goto Bad_Restrictions_Pragma;

               else
                  Set_NUP (Name_Find, OK);

                  if OK then
                     goto Line_Loop_Continue;
                  else
                     goto Bad_Restrictions_Pragma;
                  end if;
               end if;
            end if;

            --  Here if unrecognizable restrictions pragma form

            <<Bad_Restrictions_Pragma>>

            Set_Standard_Error;
            Write_Line
               ("fatal error: system.ads is incorrectly formatted");
            Write_Str ("unrecognized or incorrect restrictions pragma: ");

            P := PR_Start;
            loop
               exit when System_Text (P) = ASCII.LF;
               Write_Char (System_Text (P));
               exit when System_Text (P) = ')';
               P := P + 1;
            end loop;

            Write_Eol;
            Fatal := True;
            Set_Standard_Output;

         --  Test for pragma Detect_Blocking;

         elsif Looking_At_Skip ("pragma Detect_Blocking;") then
            Opt.Detect_Blocking := True;
            goto Line_Loop_Continue;

         --  Discard_Names

         elsif Looking_At_Skip ("pragma Discard_Names;") then
            Opt.Global_Discard_Names := True;
            goto Line_Loop_Continue;

         --  Locking Policy

         elsif Looking_At_Skip ("pragma Locking_Policy (") then
            Opt.Locking_Policy := System_Text (P);
            Opt.Locking_Policy_Sloc := System_Location;
            goto Line_Loop_Continue;

         --  Normalize_Scalars

         elsif Looking_At_Skip ("pragma Normalize_Scalars;") then
            Opt.Normalize_Scalars := True;
            Opt.Init_Or_Norm_Scalars := True;
            goto Line_Loop_Continue;

         --  Partition_Elaboration_Policy

         elsif Looking_At_Skip ("pragma Partition_Elaboration_Policy (") then
            Opt.Partition_Elaboration_Policy := System_Text (P);
            Opt.Partition_Elaboration_Policy_Sloc := System_Location;
            goto Line_Loop_Continue;

         --  Polling (On)

         elsif Looking_At_Skip ("pragma Polling (On);") then
            Opt.Polling_Required := True;
            goto Line_Loop_Continue;

         --  Queuing Policy

         elsif Looking_At_Skip ("pragma Queuing_Policy (") then
            Opt.Queuing_Policy := System_Text (P);
            Opt.Queuing_Policy_Sloc := System_Location;
            goto Line_Loop_Continue;

         --  Suppress_Exception_Locations

         elsif Looking_At_Skip ("pragma Suppress_Exception_Locations;") then
            Opt.Exception_Locations_Suppressed := True;
            goto Line_Loop_Continue;

         --  Task_Dispatching Policy

         elsif Looking_At_Skip ("pragma Task_Dispatching_Policy (") then
            Opt.Task_Dispatching_Policy := System_Text (P);
            Opt.Task_Dispatching_Policy_Sloc := System_Location;
            goto Line_Loop_Continue;

         --  No other configuration pragmas are permitted

         elsif Looking_At ("pragma ") then
            --  Special exception, we allow pragma Pure (System) appearing in
            --  column one. This is an obsolete usage which may show up in old
            --  tests with an obsolete version of system.ads, so we recognize
            --  and ignore it to make life easier in handling such tests.

            if Looking_At_Skip ("pragma Pure (System);") then
               goto Line_Loop_Continue;
            end if;

            Set_Standard_Error;
            Write_Line ("unrecognized line in system.ads: ");

            while System_Text (P) /= ')'
              and then System_Text (P) /= ASCII.LF
            loop
               Write_Char (System_Text (P));
               P := P + 1;
            end loop;

            Write_Eol;
            Set_Standard_Output;
            Fatal := True;

         --  See if we have a Run_Time_Name

         elsif Looking_At_Skip
           ("   Run_Time_Name : constant String := """)
         then
            Name_Len := 0;
            while System_Text (P) in 'A' .. 'Z'
                    or else
                  System_Text (P) in 'a' .. 'z'
                    or else
                  System_Text (P) in '0' .. '9'
                    or else
                  System_Text (P) = ' '
                    or else
                  System_Text (P) = '_'
            loop
               Add_Char_To_Name_Buffer (System_Text (P));
               P := P + 1;
            end loop;

            if System_Text (P) /= '"'
              or else System_Text (P + 1) /= ';'
              or else (System_Text (P + 2) /= ASCII.LF
                         and then
                       System_Text (P + 2) /= ASCII.CR)
            then
               Set_Standard_Error;
               Write_Line
                 ("incorrectly formatted Run_Time_Name in system.ads");
               Set_Standard_Output;
               Fatal := True;

            else
               Run_Time_Name_On_Target := Name_Enter;
            end if;

            goto Line_Loop_Continue;

         --  See if we have an Executable_Extension

         elsif Looking_At_Skip
           ("   Executable_Extension : constant String := """)
         then
            Name_Len := 0;
            while System_Text (P) /= '"'
              and then System_Text (P) /= ASCII.LF
            loop
               Add_Char_To_Name_Buffer (System_Text (P));
               P := P + 1;
            end loop;

            if System_Text (P) /= '"' or else System_Text (P + 1) /= ';' then
               Set_Standard_Error;
               Write_Line
                 ("incorrectly formatted Executable_Extension in system.ads");
               Set_Standard_Output;
               Fatal := True;

            else
               Executable_Extension_On_Target := Name_Enter;
            end if;

            goto Line_Loop_Continue;

         --  Next see if we have a configuration parameter

         else
            Config_Param_Loop : for K in Targparm_Tags loop
               if Looking_At_Skip ("   " & Targparm_Str (K).all) then
                  if Targparm_Flags (K) then
                     Set_Standard_Error;
                     Write_Line
                       ("fatal error: system.ads is incorrectly formatted");
                     Write_Str ("duplicate line for parameter: ");

                     for J in Targparm_Str (K)'Range loop
                        Write_Char (Targparm_Str (K).all (J));
                     end loop;

                     Write_Eol;
                     Set_Standard_Output;
                     Fatal := True;

                  else
                     Targparm_Flags (K) := True;
                  end if;

                  while System_Text (P) /= ':'
                     or else System_Text (P + 1) /= '='
                  loop
                     P := P + 1;
                  end loop;

                  P := P + 2;

                  while System_Text (P) = ' ' loop
                     P := P + 1;
                  end loop;

                  Result := (System_Text (P) = 'T');

                  case K is
                     when AAM => null;
                     when ACR => Always_Compatible_Rep_On_Target     := Result;
                     when ASD => Atomic_Sync_Default_On_Target       := Result;
                     when BDC => Backend_Divide_Checks_On_Target     := Result;
                     when BOC => Backend_Overflow_Checks_On_Target   := Result;
                     when CLA => Command_Line_Args_On_Target         := Result;
                     when CRT => Configurable_Run_Time_On_Target     := Result;
                     when D32 => Duration_32_Bits_On_Target          := Result;
                     when DEN => Denorm_On_Target                    := Result;
                     when EXS => Exit_Status_Supported_On_Target     := Result;
                     when FEL => null;
                     when FEX => Frontend_Exceptions_On_Target       := Result;
                     when FFO => Fractional_Fixed_Ops_On_Target      := Result;
                     when MOV => Machine_Overflows_On_Target         := Result;
                     when MRN => Machine_Rounds_On_Target            := Result;
                     when PAS => Preallocated_Stacks_On_Target       := Result;
                     when SAG => Support_Aggregates_On_Target        := Result;
                     when SAP => Support_Atomic_Primitives_On_Target := Result;
                     when SCA => Support_Composite_Assign_On_Target  := Result;
                     when SCC => Support_Composite_Compare_On_Target := Result;
                     when SCD => Stack_Check_Default_On_Target       := Result;
                     when SCL => Stack_Check_Limits_On_Target        := Result;
                     when SCP => Stack_Check_Probes_On_Target        := Result;
                     when SLS => Support_Long_Shifts_On_Target       := Result;
                     when SSL => Suppress_Standard_Library_On_Target := Result;
                     when SNZ => Signed_Zeros_On_Target              := Result;
                     when UAM => Use_Ada_Main_Program_Name_On_Target := Result;
                     when ZCX => ZCX_By_Default_On_Target            := Result;

                     goto Line_Loop_Continue;
                  end case;

                  --  Here we are seeing a parameter we do not understand. We
                  --  simply ignore this (will happen when an old compiler is
                  --  used to compile a newer version of GNAT which does not
                  --  support the parameter).
               end if;
            end loop Config_Param_Loop;
         end if;

         --  Here after processing one line of System spec

         <<Line_Loop_Continue>>

         while P < Source_Last
           and then System_Text (P) /= CR
           and then System_Text (P) /= LF
         loop
            P := P + 1;
         end loop;

         while P < Source_Last
           and then (System_Text (P) = CR
                       or else System_Text (P) = LF)
         loop
            P := P + 1;
         end loop;

         if P >= Source_Last then
            Set_Standard_Error;
            Write_Line ("fatal error, system.ads not formatted correctly");
            Write_Line ("unexpected end of file");
            Set_Standard_Output;
            raise Unrecoverable_Error;
         end if;
      end loop;

      if Fatal then
         raise Unrecoverable_Error;
      end if;
   end Get_Target_Parameters;

   ------------------------------
   -- Set_Profile_Restrictions --
   ------------------------------

   procedure Set_Profile_Restrictions (P : Profile_Name) is
      R : Restriction_Flags  renames Profile_Info (P).Set;
      V : Restriction_Values renames Profile_Info (P).Value;
   begin
      for J in R'Range loop
         if R (J) then
            Restrictions_On_Target.Set (J) := True;

            if J in All_Parameter_Restrictions then
               Restrictions_On_Target.Value (J) := V (J);
            end if;
         end if;
      end loop;
   end Set_Profile_Restrictions;

end Targparm;
