-------------------------------------------------------------------------------
-- (C) Altran Praxis Limited
-------------------------------------------------------------------------------
--
-- The SPARK toolset 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 3, or (at your option) any later
-- version. The SPARK toolset is distributed in the hope that it will be
-- useful, but WITHOUT 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 the SPARK toolset; see file
-- COPYING3. If not, go to http://www.gnu.org/licenses for a complete copy of
-- the license.
--
--=============================================================================

----------------------------------------------------------------------------
-- WARNING: if you add or modify a command line switch be sure to update  --
--          Print_Help in examiner.adb                                    --
----------------------------------------------------------------------------

with FileSystem;
with SPARK_IO;
with Version;
with XMLReport;

use type Version.Distribution_Sort;

package body CommandLineData is

   Ada_Extension          : constant String := "ada";
   Lst_Extension          : constant String := "lst";
   Default_Report_File    : constant String := "spark.rep";
   Default_Dict_File      : constant String := "spark.dic";
   Default_HTML_Directory : constant String := "HTML";

   procedure Initialize is
   begin
      Content :=
        Command_Line_Contents'
        (Valid                 => True,
         Index                 => False,
         Warning               => False,
         Target_Data           => False,
         Target_Config         => False,
         Source_Extension      => E_Strings.Copy_String (Str => Ada_Extension),
         Listing_Extension     => E_Strings.Copy_String (Str => Lst_Extension),
         Number_Source         => 0,
         Echo                  => True,
         Makefile_Mode         => False,
         Report                => True,
         Write_Dict            => False,
         Report_File_Name      => E_Strings.Copy_String (Str => Default_Report_File),
         Dict_File_Name        => E_Strings.Copy_String (Str => Default_Dict_File),
         VCG                   => False,
         DPC                   => False,
         Write_Statistics      => False,
         Flow_Option           => Auto_Flow,
         Default_Switch_File   => False,
         HTML                  => False,
         HTML_Directory        => E_Strings.Copy_String (Str => Default_HTML_Directory),
         Output_Directory      => False,
         Output_Directory_Name => E_Strings.Empty_String,
         Index_File_Name       => E_Strings.Empty_String,
         Warning_File_Name     => E_Strings.Empty_String,
         Target_Data_File      => E_Strings.Empty_String,
         Target_Config_File    => E_Strings.Empty_String,
         Source_File_List      => Source_File_Lists'(others => Source_File_Entry'(Source_File_Name  => E_Strings.Empty_String,
                                                                                  Listing           => False,
                                                                                  Listing_File_Name => E_Strings.Empty_String)),
         Anno_Char             => '#',
         Syntax_Only           => False,
         FDL_Reserved          => True,
         FDL_Mangle            => E_Strings.Empty_String,
         Plain_Output          => False,
         Version_Requested     => False,
         Help_Requested        => False,
         VC_Finger_Prints      => False,
         Concurrency_Profile   => Sequential,
         Language_Profile      => SPARK95,
         No_Duration           => False,
         Brief                 => False,
         Brief_Option          => No_Path,
         XML                   => False,
         Info_Flow_Policy      => None,
         Constant_Rules        => Lazy,
         Legacy_Errors         => False,
         Error_Explanation     => Off,
         Justification_Option  => Full,
         No_Listings           => False,
         Generate_SLI          => True,
         Casing_Standard       => False,
         Casing_Identifier     => False,
         SPARK_Lib             => False,
         Debug                 => Debug_State'(Enabled      => False,
                                               Expressions  => False,
                                               HTML         => False,
                                               Lookup_Trace => False,
                                               File_Names   => False,
                                               Units        => False,
                                               Invariants   => False,
                                               Components   => False,
                                               Rho          => False,
                                               Parser       => False,
                                               FDL_Ranking  => False,
                                               VCG          => False,
                                               SLI          => False,
                                               VCG_All      => False,
                                               DAG          => False,
                                               Extra_Stats  => False),
         Distribution_Is_Pro   => Version.Toolset_Distribution_Sort = Version.Pro,
         GPL_Switch            => False);
   end Initialize;

   procedure Normalize_File_Name_To_Output_Directory (F : in out E_Strings.T) is
      Original : E_Strings.T;

      procedure Debug
      --# derives ;
      is
         --# hide Debug;
      begin
         if Content.Debug.File_Names then
            SPARK_IO.Put_String (SPARK_IO.Standard_Output, "Normalizing ", 0);
            E_Strings.Put_String (File  => SPARK_IO.Standard_Output,
                                  E_Str => Original);
            SPARK_IO.Put_String (SPARK_IO.Standard_Output, " with respect to ", 0);
            E_Strings.Put_String (File  => SPARK_IO.Standard_Output,
                                  E_Str => Content.Output_Directory_Name);
            SPARK_IO.Put_String (SPARK_IO.Standard_Output, " results in ", 0);
            E_Strings.Put_Line (File  => SPARK_IO.Standard_Output,
                                E_Str => F);
         end if;
      end Debug;

   begin
      Original := F;
      if Content.Output_Directory then
         F := FileSystem.Interpret_Relative (File_Name             => Original,
                                             Relative_To_Directory => Content.Output_Directory_Name);
         Debug;
      end if;
   end Normalize_File_Name_To_Output_Directory;

   procedure Dump_File_Names is
      --# hide Dump_File_Names;
   begin
      if Content.Debug.File_Names then
         SPARK_IO.New_Line (SPARK_IO.Standard_Output, 1);
         SPARK_IO.Put_Line (SPARK_IO.Standard_Output, "------------Dump of CommandLineData.Content File Names------------", 0);
         if Content.Index then
            SPARK_IO.Put_String (SPARK_IO.Standard_Output, "Index file is:", 0);
            E_Strings.Put_Line (File  => SPARK_IO.Standard_Output,
                                E_Str => Content.Index_File_Name);
         else
            SPARK_IO.Put_Line (SPARK_IO.Standard_Output, "No Index File", 0);
         end if;

         if Content.Warning then
            SPARK_IO.Put_String (SPARK_IO.Standard_Output, "Warning file is:", 0);
            E_Strings.Put_Line (File  => SPARK_IO.Standard_Output,
                                E_Str => Content.Warning_File_Name);
         else
            SPARK_IO.Put_Line (SPARK_IO.Standard_Output, "No Warning File", 0);
         end if;

         if Content.Target_Data then
            SPARK_IO.Put_String (SPARK_IO.Standard_Output, "Target Data File is:", 0);
            E_Strings.Put_Line (File  => SPARK_IO.Standard_Output,
                                E_Str => Content.Target_Data_File);
         else
            SPARK_IO.Put_Line (SPARK_IO.Standard_Output, "No Target Data File", 0);
         end if;

         if Content.Target_Config then
            SPARK_IO.Put_String (SPARK_IO.Standard_Output, "Target Config File is:", 0);
            E_Strings.Put_Line (File  => SPARK_IO.Standard_Output,
                                E_Str => Content.Target_Config_File);
         else
            SPARK_IO.Put_Line (SPARK_IO.Standard_Output, "No Target Config File", 0);
         end if;

         SPARK_IO.Put_String (SPARK_IO.Standard_Output, "Source extension is:", 0);
         E_Strings.Put_Line (File  => SPARK_IO.Standard_Output,
                             E_Str => Content.Source_Extension);

         SPARK_IO.Put_String (SPARK_IO.Standard_Output, "Listing extension is:", 0);
         E_Strings.Put_Line (File  => SPARK_IO.Standard_Output,
                             E_Str => Content.Listing_Extension);

         SPARK_IO.Put_String (SPARK_IO.Standard_Output, "Report File Name is:", 0);
         E_Strings.Put_Line (File  => SPARK_IO.Standard_Output,
                             E_Str => Content.Report_File_Name);

         SPARK_IO.Put_String (SPARK_IO.Standard_Output, "Dictionary File Name is:", 0);
         E_Strings.Put_Line (File  => SPARK_IO.Standard_Output,
                             E_Str => Content.Dict_File_Name);

         if Content.Output_Directory then
            SPARK_IO.Put_String (SPARK_IO.Standard_Output, "Output Directory is:", 0);
            E_Strings.Put_Line (File  => SPARK_IO.Standard_Output,
                                E_Str => Content.Output_Directory_Name);
         else
            SPARK_IO.Put_Line (SPARK_IO.Standard_Output, "Output directory is CWD", 0);
         end if;

         SPARK_IO.Put_String (SPARK_IO.Standard_Output, "Number of Source Files is:", 0);
         SPARK_IO.Put_Line (SPARK_IO.Standard_Output, Integer'Image (Content.Number_Source), 0);

         for I in Source_File_Positions range 1 .. Content.Number_Source loop
            E_Strings.Put_String (File  => SPARK_IO.Standard_Output,
                                  E_Str => Content.Source_File_List (I).Source_File_Name);

            if Content.No_Listings then
               SPARK_IO.Put_Line (SPARK_IO.Standard_Output, ", All listing files suppressed", 0);
            elsif Content.Source_File_List (I).Listing then
               SPARK_IO.Put_String (SPARK_IO.Standard_Output, ", ", 0);
               E_Strings.Put_Line (File  => SPARK_IO.Standard_Output,
                                   E_Str => Content.Source_File_List (I).Listing_File_Name);
            else
               SPARK_IO.Put_Line (SPARK_IO.Standard_Output, ", No listing file", 0);
            end if;
         end loop;

         SPARK_IO.Put_String (SPARK_IO.Standard_Output, "Examiner Lib Directory is: ", 0);

         if FileSystem.Use_Windows_Command_Line and then Content.Plain_Output then
            E_Strings.Put_Line
              (File  => SPARK_IO.Standard_Output,
               E_Str => E_Strings.Lower_Case (E_Str => FileSystem.Examiner_Lib_Directory));
         else
            E_Strings.Put_Line (File  => SPARK_IO.Standard_Output,
                                E_Str => FileSystem.Examiner_Lib_Directory);
         end if;

         SPARK_IO.Put_Line (SPARK_IO.Standard_Output, "------------End of CommandLineData.Content File Names-------------", 0);
         SPARK_IO.New_Line (SPARK_IO.Standard_Output, 1);
      end if;

   end Dump_File_Names;

   procedure Output_Command_Line (Prefix     : in     String;
                                  XML        : in     Boolean;
                                  Option_Str :    out E_Strings.T) is
      Dir_Actual_C : constant String := "output_directory (actual)=";

      Tmp_String : E_Strings.T;
      Out_Dir    : E_Strings.T;
      CWD        : E_Strings.T;
      Is_First   : Boolean;

      procedure Output_Option
        (Prefix  : in     String;
         Option  : in     E_Strings.T;
         Acc     : in out E_Strings.T;
         XML     : in     Boolean;
         For_XML : in     Boolean)
      --# global in out XMLReport.State;
      --# derives Acc             from *,
      --#                              For_XML,
      --#                              Option,
      --#                              Prefix,
      --#                              XML,
      --#                              XMLReport.State &
      --#         XMLReport.State from *,
      --#                              For_XML,
      --#                              XML;
      is
         Acc_Option : E_Strings.T;
      begin
         if XML then
            if For_XML then
               Acc_Option := Option;
               XMLReport.Option (Opt => Acc_Option);
            else
               Acc_Option := E_Strings.Empty_String;
            end if;
         else
            Acc_Option := E_Strings.Copy_String (Str => Prefix);
            E_Strings.Append_Examiner_String (E_Str1 => Acc_Option,
                                              E_Str2 => Option);
            E_Strings.Append_Examiner_String (E_Str1 => Acc_Option,
                                              E_Str2 => FileSystem.End_Of_Line);
         end if;
         E_Strings.Append_Examiner_String (E_Str1 => Acc,
                                           E_Str2 => Acc_Option);
      end Output_Option;

      function Plain_Output (E_Str : E_Strings.T;
                             XML   : Boolean) return E_Strings.T
      --# global in Content;
      is
         Result : E_Strings.T;
      begin
         if Content.Plain_Output and then not XML then
            Result := FileSystem.Just_File (Fn  => E_Str,
                                            Ext => True);
         else
            Result := E_Str;
         end if;
         return Result;
      end Plain_Output;

   begin
      Option_Str := E_Strings.Empty_String;
      if not Content.Default_Switch_File then
         Tmp_String := E_Strings.Copy_String (Str => Option_No_Switch);
         Output_Option (Prefix  => Prefix,
                        Option  => Tmp_String,
                        Acc     => Option_Str,
                        XML     => XML,
                        For_XML => True);
      end if;

      --# assert True;

      if Content.Index then
         Tmp_String := E_Strings.Copy_String (Str => Option_Index_File & "=");
         E_Strings.Append_Examiner_String
           (E_Str1 => Tmp_String,
            E_Str2 => Plain_Output (E_Str => Content.Index_File_Name,
                                    XML   => XML));
         Output_Option (Prefix  => Prefix,
                        Option  => Tmp_String,
                        Acc     => Option_Str,
                        XML     => XML,
                        For_XML => True);
      else
         Tmp_String := E_Strings.Copy_String (Str => "no" & Option_Index_File);
         Output_Option (Prefix  => Prefix,
                        Option  => Tmp_String,
                        Acc     => Option_Str,
                        XML     => XML,
                        For_XML => False);
      end if;

      if Content.Warning then
         Tmp_String := E_Strings.Copy_String (Str => Option_Warning_File & "=");
         E_Strings.Append_Examiner_String
           (E_Str1 => Tmp_String,
            E_Str2 => Plain_Output (E_Str => Content.Warning_File_Name,
                                    XML   => XML));
         Output_Option (Prefix  => Prefix,
                        Option  => Tmp_String,
                        Acc     => Option_Str,
                        XML     => XML,
                        For_XML => True);
      else
         Tmp_String := E_Strings.Copy_String (Str => "no" & Option_Warning_File);
         Output_Option (Prefix  => Prefix,
                        Option  => Tmp_String,
                        Acc     => Option_Str,
                        XML     => XML,
                        For_XML => False);
      end if;

      --# assert True;

      if Content.Target_Data then
         Tmp_String := E_Strings.Copy_String (Str => Option_Target_Compiler_Data & "=");
         E_Strings.Append_Examiner_String
           (E_Str1 => Tmp_String,
            E_Str2 => Plain_Output (E_Str => Content.Target_Data_File,
                                    XML   => XML));
         Output_Option (Prefix  => Prefix,
                        Option  => Tmp_String,
                        Acc     => Option_Str,
                        XML     => XML,
                        For_XML => True);
      else
         Tmp_String := E_Strings.Copy_String (Str => "no" & Option_Target_Compiler_Data);
         Output_Option (Prefix  => Prefix,
                        Option  => Tmp_String,
                        Acc     => Option_Str,
                        XML     => XML,
                        For_XML => False);
      end if;

      if Content.Target_Config then
         Tmp_String := E_Strings.Copy_String (Str => Option_Config_File & "=");
         E_Strings.Append_Examiner_String
           (E_Str1 => Tmp_String,
            E_Str2 => Plain_Output (E_Str => Content.Target_Config_File,
                                    XML   => XML));
         Output_Option (Prefix  => Prefix,
                        Option  => Tmp_String,
                        Acc     => Option_Str,
                        XML     => XML,
                        For_XML => True);
      else
         Tmp_String := E_Strings.Copy_String (Str => "no" & Option_Config_File);
         Output_Option (Prefix  => Prefix,
                        Option  => Tmp_String,
                        Acc     => Option_Str,
                        XML     => XML,
                        For_XML => False);
      end if;

      --# assert True;

      Tmp_String := E_Strings.Copy_String (Str => Option_Source_Extension & "=");
      E_Strings.Append_Examiner_String
        (E_Str1 => Tmp_String,
         E_Str2 => Plain_Output (E_Str => Content.Source_Extension,
                                 XML   => XML));
      Output_Option (Prefix  => Prefix,
                     Option  => Tmp_String,
                     Acc     => Option_Str,
                     XML     => XML,
                     For_XML => True);

      Tmp_String := E_Strings.Copy_String (Str => Option_Listing_Extension & "=");
      E_Strings.Append_Examiner_String
        (E_Str1 => Tmp_String,
         E_Str2 => Plain_Output (E_Str => Content.Listing_Extension,
                                 XML   => XML));
      Output_Option (Prefix  => Prefix,
                     Option  => Tmp_String,
                     Acc     => Option_Str,
                     XML     => XML,
                     For_XML => True);
      if Content.No_Listings then
         Tmp_String := E_Strings.Copy_String (Str => Option_No_Listings);
         Output_Option (Prefix  => Prefix,
                        Option  => Tmp_String,
                        Acc     => Option_Str,
                        XML     => XML,
                        For_XML => False);
      end if;

      if not Content.Echo then
         Tmp_String := E_Strings.Copy_String (Str => Option_No_Echo);
         Output_Option (Prefix  => Prefix,
                        Option  => Tmp_String,
                        Acc     => Option_Str,
                        XML     => XML,
                        For_XML => True);
      end if;

      if Content.Makefile_Mode then
         Tmp_String := E_Strings.Copy_String (Str => Option_Makefile_Mode);
         Output_Option (Prefix  => Prefix,
                        Option  => Tmp_String,
                        Acc     => Option_Str,
                        XML     => XML,
                        For_XML => True);
      end if;

      if Content.Write_Dict then
         Tmp_String := E_Strings.Copy_String (Str => Option_Dictionary_File & "=");
         E_Strings.Append_Examiner_String
           (E_Str1 => Tmp_String,
            E_Str2 => Plain_Output (E_Str => Content.Dict_File_Name,
                                    XML   => XML));
         Output_Option (Prefix  => Prefix,
                        Option  => Tmp_String,
                        Acc     => Option_Str,
                        XML     => XML,
                        For_XML => True);
      else
         Tmp_String := E_Strings.Copy_String (Str => "no" & Option_Dictionary_File);
         Output_Option (Prefix  => Prefix,
                        Option  => Tmp_String,
                        Acc     => Option_Str,
                        XML     => XML,
                        For_XML => False);
      end if;

      --# assert True;

      if Content.Report then
         Tmp_String := E_Strings.Copy_String (Str => Option_Report_File & "=");
         E_Strings.Append_Examiner_String
           (E_Str1 => Tmp_String,
            E_Str2 => Plain_Output (E_Str => Content.Report_File_Name,
                                    XML   => XML));
         Output_Option (Prefix  => Prefix,
                        Option  => Tmp_String,
                        Acc     => Option_Str,
                        XML     => XML,
                        For_XML => True);
      else
         Tmp_String := E_Strings.Copy_String (Str => "no" & Option_Report_File);
         Output_Option (Prefix  => Prefix,
                        Option  => Tmp_String,
                        Acc     => Option_Str,
                        XML     => XML,
                        For_XML => False);
      end if;

      if Content.HTML then
         Tmp_String := E_Strings.Copy_String (Str => Option_Html & "=");
         E_Strings.Append_Examiner_String
           (E_Str1 => Tmp_String,
            E_Str2 => Plain_Output (E_Str => Content.HTML_Directory,
                                    XML   => XML));
         Output_Option (Prefix  => Prefix,
                        Option  => Tmp_String,
                        Acc     => Option_Str,
                        XML     => XML,
                        For_XML => True);
      else
         Tmp_String := E_Strings.Copy_String (Str => "no" & Option_Html);
         Output_Option (Prefix  => Prefix,
                        Option  => Tmp_String,
                        Acc     => Option_Str,
                        XML     => XML,
                        For_XML => False);
      end if;

      --# assert True;

      if Content.VCG then
         Tmp_String := E_Strings.Copy_String (Str => Option_Vcg);
         Output_Option (Prefix  => Prefix,
                        Option  => Tmp_String,
                        Acc     => Option_Str,
                        XML     => XML,
                        For_XML => True);
      end if;

      if Content.DPC then
         Tmp_String := E_Strings.Copy_String (Str => Option_Dpc);
         Output_Option (Prefix  => Prefix,
                        Option  => Tmp_String,
                        Acc     => Option_Str,
                        XML     => XML,
                        For_XML => True);
      end if;

      --# assert True;

      if Content.Syntax_Only then
         Tmp_String := E_Strings.Copy_String (Str => Option_Syntax_Check);
         Output_Option (Prefix  => Prefix,
                        Option  => Tmp_String,
                        Acc     => Option_Str,
                        XML     => XML,
                        For_XML => True);
      end if;

      if Content.GPL_Switch then
         Tmp_String := E_Strings.Copy_String (Str => Option_GPL);
         Output_Option (Prefix  => Prefix,
                        Option  => Tmp_String,
                        Acc     => Option_Str,
                        XML     => XML,
                        For_XML => True);
      end if;

      --# assert True;

      if Content.Plain_Output then
         Tmp_String := E_Strings.Copy_String (Str => Option_Plain_Output);
         Output_Option (Prefix  => Prefix,
                        Option  => Tmp_String,
                        Acc     => Option_Str,
                        XML     => XML,
                        For_XML => True);
      end if;

      if Content.No_Duration then
         Tmp_String := E_Strings.Copy_String (Str => Option_No_Duration);
         Output_Option (Prefix  => Prefix,
                        Option  => Tmp_String,
                        Acc     => Option_Str,
                        XML     => XML,
                        For_XML => True);
      end if;

      if Content.Brief then
         Tmp_String := E_Strings.Copy_String (Str => Option_Brief & "=");
         case Content.Brief_Option is
            when No_Path =>
               E_Strings.Append_String (E_Str => Tmp_String,
                                        Str   => Option_Brief_No_Path);
            when Full_Path =>
               E_Strings.Append_String (E_Str => Tmp_String,
                                        Str   => Option_Brief_Full_Path);
         end case;
         Output_Option (Prefix  => Prefix,
                        Option  => Tmp_String,
                        Acc     => Option_Str,
                        XML     => XML,
                        For_XML => True);
      end if;

      if Content.SPARK_Lib then
         Tmp_String := E_Strings.Copy_String (Str => Option_SPARK_Lib);
         Output_Option (Prefix  => Prefix,
                        Option  => Tmp_String,
                        Acc     => Option_Str,
                        XML     => XML,
                        For_XML => True);
      end if;

      if Content.Write_Statistics then
         Tmp_String := E_Strings.Copy_String (Str => Option_Statistics);
      else
         Tmp_String := E_Strings.Copy_String (Str => "no" & Option_Statistics);
      end if;
      Output_Option (Prefix  => Prefix,
                     Option  => Tmp_String,
                     Acc     => Option_Str,
                     XML     => XML,
                     For_XML => True);

      --# assert True;

      Tmp_String := E_Strings.Copy_String (Str => Option_Fdl_Identifiers & "=");
      if Content.FDL_Reserved then
         E_Strings.Append_String (E_Str => Tmp_String,
                                  Str   => Option_Fdl_Identifiers_Accept);
      else
         if E_Strings.Is_Empty (E_Str => Content.FDL_Mangle) then
            E_Strings.Append_String (E_Str => Tmp_String,
                                     Str   => Option_Fdl_Identifiers_Reject);
         else
            E_Strings.Append_Examiner_String (E_Str1 => Tmp_String,
                                              E_Str2 => Content.FDL_Mangle);
         end if;
      end if;
      Output_Option (Prefix  => Prefix,
                     Option  => Tmp_String,
                     Acc     => Option_Str,
                     XML     => XML,
                     For_XML => True);

      Tmp_String := E_Strings.Copy_String (Str => Option_Flow_Analysis & "=");
      case Content.Flow_Option is
         when Data_Flow =>
            E_Strings.Append_String (E_Str => Tmp_String,
                                     Str   => Option_Flow_Analysis_Data);
         when Info_Flow =>
            E_Strings.Append_String (E_Str => Tmp_String,
                                     Str   => Option_Flow_Analysis_Information);
         when Auto_Flow =>
            E_Strings.Append_String (E_Str => Tmp_String,
                                     Str   => Option_Flow_Analysis_Auto);
      end case;
      Output_Option (Prefix  => Prefix,
                     Option  => Tmp_String,
                     Acc     => Option_Str,
                     XML     => XML,
                     For_XML => True);

      --# assert True;

      Tmp_String := E_Strings.Copy_String (Str => Option_Policy & "=");
      case Content.Info_Flow_Policy is
         when None =>
            null;
         when Safety =>
            E_Strings.Append_String (E_Str => Tmp_String,
                                     Str   => Option_Policy_Safety);
            Output_Option (Prefix  => Prefix,
                           Option  => Tmp_String,
                           Acc     => Option_Str,
                           XML     => XML,
                           For_XML => True);
         when Security =>
            E_Strings.Append_String (E_Str => Tmp_String,
                                     Str   => Option_Policy_Security);
            Output_Option (Prefix  => Prefix,
                           Option  => Tmp_String,
                           Acc     => Option_Str,
                           XML     => XML,
                           For_XML => True);
      end case;

      --# assert True;

      Tmp_String := E_Strings.Copy_String (Str => Option_Language & "=");
      case Content.Language_Profile is
         when SPARK83 =>
            E_Strings.Append_String (E_Str => Tmp_String,
                                     Str   => Option_Language_83);
         when SPARK95 =>
            E_Strings.Append_String (E_Str => Tmp_String,
                                     Str   => Option_Language_95);
         when SPARK2005 =>
            E_Strings.Append_String (E_Str => Tmp_String,
                                     Str   => Option_Language_2005);
         when KCG =>
            E_Strings.Append_String (E_Str => Tmp_String,
                                     Str   => Option_Language_KCG);
      end case;
      Output_Option (Prefix  => Prefix,
                     Option  => Tmp_String,
                     Acc     => Option_Str,
                     XML     => XML,
                     For_XML => True);

      Tmp_String := E_Strings.Copy_String (Str => Option_Profile & "=");
      case Content.Concurrency_Profile is
         when Ravenscar =>
            E_Strings.Append_String (E_Str => Tmp_String,
                                     Str   => Option_Profile_Ravenscar);
         when Sequential =>
            E_Strings.Append_String (E_Str => Tmp_String,
                                     Str   => Option_Profile_Sequential);
      end case;
      Output_Option (Prefix  => Prefix,
                     Option  => Tmp_String,
                     Acc     => Option_Str,
                     XML     => XML,
                     For_XML => True);

      Tmp_String := E_Strings.Copy_String (Str => Option_Annotation_Character & "=");
      E_Strings.Append_Char (E_Str => Tmp_String,
                             Ch    => Content.Anno_Char);
      Output_Option (Prefix  => Prefix,
                     Option  => Tmp_String,
                     Acc     => Option_Str,
                     XML     => XML,
                     For_XML => True);

      --# assert True;

      Tmp_String := E_Strings.Copy_String (Str => Option_Rules & "=");
      case Content.Constant_Rules is
         when No_Rules =>
            E_Strings.Append_String (E_Str => Tmp_String,
                                     Str   => Option_Rules_None);
         when Lazy =>
            E_Strings.Append_String (E_Str => Tmp_String,
                                     Str   => Option_Rules_Lazy);
         when Keen =>
            E_Strings.Append_String (E_Str => Tmp_String,
                                     Str   => Option_Rules_Keen);
         when All_Rules =>
            E_Strings.Append_String (E_Str => Tmp_String,
                                     Str   => Option_Rules_All);
      end case;
      Output_Option (Prefix  => Prefix,
                     Option  => Tmp_String,
                     Acc     => Option_Str,
                     XML     => XML,
                     For_XML => True);

      --# assert True;

      if Content.Legacy_Errors then
         Tmp_String := E_Strings.Copy_String (Str => Option_Original_Flow_Errors);
         Output_Option (Prefix  => Prefix,
                        Option  => Tmp_String,
                        Acc     => Option_Str,
                        XML     => XML,
                        For_XML => True);
      end if;

      if not Content.Generate_SLI then
         Tmp_String := E_Strings.Copy_String (Str => Option_No_Sli);
         Output_Option (Prefix  => Prefix,
                        Option  => Tmp_String,
                        Acc     => Option_Str,
                        XML     => XML,
                        For_XML => True);
      end if;

      --# assert True;

      Tmp_String := E_Strings.Copy_String (Str => Option_Error_Explanations & "=");
      case Content.Error_Explanation is
         when Off =>
            E_Strings.Append_String (E_Str => Tmp_String,
                                     Str   => Option_Error_Explanations_Off);
         when First_Occurrence =>
            E_Strings.Append_String (E_Str => Tmp_String,
                                     Str   => Option_Error_Explanations_First_Occurrence);
         when Every_Occurrence =>
            E_Strings.Append_String (E_Str => Tmp_String,
                                     Str   => Option_Error_Explanations_Every_Occurrence);
      end case;
      Output_Option (Prefix  => Prefix,
                     Option  => Tmp_String,
                     Acc     => Option_Str,
                     XML     => XML,
                     For_XML => True);

      Tmp_String := E_Strings.Copy_String (Str => Option_Justification_Option & "=");
      case Content.Justification_Option is
         when Ignore =>
            E_Strings.Append_String (E_Str => Tmp_String,
                                     Str   => Option_Justification_Option_Ignore);
         when Full =>
            E_Strings.Append_String (E_Str => Tmp_String,
                                     Str   => Option_Justification_Option_Full);
         when Brief =>
            E_Strings.Append_String (E_Str => Tmp_String,
                                     Str   => Option_Justification_Option_Brief);
      end case;
      Output_Option (Prefix  => Prefix,
                     Option  => Tmp_String,
                     Acc     => Option_Str,
                     XML     => XML,
                     For_XML => True);

      --# assert True;

      if Content.Casing_Standard or else Content.Casing_Identifier then
         Tmp_String := E_Strings.Copy_String (Str => Option_Casing & "=");
         if Content.Casing_Standard then
            E_Strings.Append_Char (E_Str => Tmp_String,
                                   Ch    => Option_Casing_Standard);
         end if;
         if Content.Casing_Identifier then
            E_Strings.Append_Char (E_Str => Tmp_String,
                                   Ch    => Option_Casing_Identifier);
         end if;
         Output_Option (Prefix  => Prefix,
                        Option  => Tmp_String,
                        Acc     => Option_Str,
                        XML     => XML,
                        For_XML => True);
      end if;

      if Content.Debug.Enabled then
         Tmp_String := E_Strings.Copy_String (Str => Option_Debug);
         Is_First   := True;

         if Content.Debug.Expressions then
            E_Strings.Append_Char (E_Str => Tmp_String,
                                   Ch    => '=');
            Is_First := False;
            E_Strings.Append_Char (E_Str => Tmp_String,
                                   Ch    => Option_Debug_E);
         end if;

         --# assert True;

         if Content.Debug.HTML then
            if Is_First then
               E_Strings.Append_Char (E_Str => Tmp_String,
                                      Ch    => '=');
               Is_First := False;
            end if;
            E_Strings.Append_Char (E_Str => Tmp_String,
                                   Ch    => Option_Debug_H);
         end if;

         --# assert True;

         if Content.Debug.Lookup_Trace then
            if Is_First then
               E_Strings.Append_Char (E_Str => Tmp_String,
                                      Ch    => '=');
               Is_First := False;
            end if;
            E_Strings.Append_Char (E_Str => Tmp_String,
                                   Ch    => Option_Debug_L);
         end if;

         --# assert True;

         if Content.Debug.File_Names then
            if Is_First then
               E_Strings.Append_Char (E_Str => Tmp_String,
                                      Ch    => '=');
               Is_First := False;
            end if;
            E_Strings.Append_Char (E_Str => Tmp_String,
                                   Ch    => Option_Debug_F);
         end if;

         --# assert True;

         if Content.Debug.Units then
            if Is_First then
               E_Strings.Append_Char (E_Str => Tmp_String,
                                      Ch    => '=');
               Is_First := False;
            end if;
            E_Strings.Append_Char (E_Str => Tmp_String,
                                   Ch    => Option_Debug_U);
         end if;

         --# assert True;

         if Content.Debug.Invariants then
            if Is_First then
               E_Strings.Append_Char (E_Str => Tmp_String,
                                      Ch    => '=');
               Is_First := False;
            end if;
            E_Strings.Append_Char (E_Str => Tmp_String,
                                   Ch    => Option_Debug_I);
         end if;

         --# assert True;

         if Content.Debug.Components then
            if Is_First then
               E_Strings.Append_Char (E_Str => Tmp_String,
                                      Ch    => '=');
               Is_First := False;
            end if;
            E_Strings.Append_Char (E_Str => Tmp_String,
                                   Ch    => Option_Debug_C);
         end if;

         --# assert True;

         if Content.Debug.Rho then
            if Is_First then
               E_Strings.Append_Char (E_Str => Tmp_String,
                                      Ch    => '=');
               Is_First := False;
            end if;
            E_Strings.Append_Char (E_Str => Tmp_String,
                                   Ch    => Option_Debug_R);
         end if;

         --# assert True;

         if Content.Debug.Parser then
            if Is_First then
               E_Strings.Append_Char (E_Str => Tmp_String,
                                      Ch    => '=');
               Is_First := False;
            end if;
            E_Strings.Append_Char (E_Str => Tmp_String,
                                   Ch    => Option_Debug_P);
         end if;

         if Content.Debug.FDL_Ranking then
            if Is_First then
               E_Strings.Append_Char (E_Str => Tmp_String,
                                      Ch    => '=');
               Is_First := False;
            end if;
            E_Strings.Append_Char (E_Str => Tmp_String,
                                   Ch    => Option_Debug_K);
         end if;

         --# assert True;

         if Content.Debug.VCG then
            if Is_First then
               E_Strings.Append_Char (E_Str => Tmp_String,
                                      Ch    => '=');
               Is_First := False;
            end if;
            E_Strings.Append_Char (E_Str => Tmp_String,
                                   Ch    => Option_Debug_V);
         end if;

         --# assert True;

         if Content.Debug.VCG_All then
            if Is_First then
               E_Strings.Append_Char (E_Str => Tmp_String,
                                      Ch    => '=');
               Is_First := False;
            end if;
            E_Strings.Append_Char (E_Str => Tmp_String,
                                   Ch    => Option_Debug_V_Upper);
         end if;

         --# assert True;

         if Content.Debug.DAG then
            if Is_First then
               E_Strings.Append_Char (E_Str => Tmp_String,
                                      Ch    => '=');
               Is_First := False;
            end if;
            E_Strings.Append_Char (E_Str => Tmp_String,
                                   Ch    => Option_Debug_D);
         end if;

         --# assert True;

         if Content.Debug.SLI then
            if Is_First then
               E_Strings.Append_Char (E_Str => Tmp_String,
                                      Ch    => '=');
            end if;
            E_Strings.Append_Char (E_Str => Tmp_String,
                                   Ch    => Option_Debug_X);
         end if;

         Output_Option (Prefix  => Prefix,
                        Option  => Tmp_String,
                        Acc     => Option_Str,
                        XML     => XML,
                        For_XML => False);
      end if;

      --# assert True;

      if Content.Output_Directory then

         -- output_directory _has_ been specified, so firstly
         -- report exactly what the user gave on the command-line
         -- as the requested output directory
         Tmp_String := E_Strings.Copy_String (Str => Option_Output_Directory & "=");

         Out_Dir := Content.Output_Directory_Name;

         -- Out_Dir might have an EndOfPath (normally '/' or '\') on
         -- the end, so remove it here.
         FileSystem.Remove_End_Of_Path_If_Present (D => Out_Dir);
         E_Strings.Append_Examiner_String (E_Str1 => Tmp_String,
                                           E_Str2 => Out_Dir);
         Output_Option (Prefix  => Prefix,
                        Option  => Tmp_String,
                        Acc     => Option_Str,
                        XML     => XML,
                        For_XML => True);

         -- Now report the actual output directory.
         if Content.Plain_Output then
            -- Plain output mode, so just repeat the requested dir.
            Tmp_String := E_Strings.Copy_String (Str => Dir_Actual_C);
            E_Strings.Append_Examiner_String (E_Str1 => Tmp_String,
                                              E_Str2 => Out_Dir);
            Output_Option (Prefix  => Prefix,
                           Option  => Tmp_String,
                           Acc     => Option_Str,
                           XML     => XML,
                           For_XML => True);
         else
            -- Verbose output mode...imagine we're creating a dummy
            -- file called "a" in the requested output directory.
            -- Normalize this filename for the output dir, then
            -- find its full pathname relative to CWD, then report
            -- that, minus the "a" on the end...
            Tmp_String := E_Strings.Copy_String (Str => Dir_Actual_C);
            Out_Dir    := E_Strings.Copy_String (Str => "a");
            Normalize_File_Name_To_Output_Directory (Out_Dir);

            CWD := FileSystem.Working_Directory;
            FileSystem.Append_End_Of_Path_If_Needed (D => CWD);

            Out_Dir := FileSystem.Interpret_Relative (File_Name             => Out_Dir,
                                                      Relative_To_Directory => CWD);

            -- Drop the "a" off the end...
            Out_Dir :=
              E_Strings.Section (E_Str     => Out_Dir,
                                 Start_Pos => 1,
                                 Length    => E_Strings.Get_Length (E_Str => Out_Dir) - 1);

            E_Strings.Append_Examiner_String (E_Str1 => Tmp_String,
                                              E_Str2 => Out_Dir);
            Output_Option (Prefix  => Prefix,
                           Option  => Tmp_String,
                           Acc     => Option_Str,
                           XML     => XML,
                           For_XML => True);
         end if;
      else
         -- output_directory NOT specified, so report "."
         Tmp_String := E_Strings.Copy_String (Str => Option_Output_Directory & "=");
         E_Strings.Append_String (E_Str => Tmp_String,
                                  Str   => ".");
         Output_Option (Prefix  => Prefix,
                        Option  => Tmp_String,
                        Acc     => Option_Str,
                        XML     => XML,
                        For_XML => True);
         if Content.Plain_Output then
            -- Plain output, so report "." as actual output directory
            -- to avoid diff between runs and platforms
            Tmp_String := E_Strings.Copy_String (Str => Dir_Actual_C);
            E_Strings.Append_String (E_Str => Tmp_String,
                                     Str   => ".");
            Output_Option (Prefix  => Prefix,
                           Option  => Tmp_String,
                           Acc     => Option_Str,
                           XML     => XML,
                           For_XML => True);
         else
            -- Verbose output, so report full pathname of
            -- current working directory
            Tmp_String := E_Strings.Copy_String (Str => Dir_Actual_C);
            CWD        := FileSystem.Working_Directory;
            FileSystem.Append_End_Of_Path_If_Needed (D => CWD);
            E_Strings.Append_Examiner_String (E_Str1 => Tmp_String,
                                              E_Str2 => CWD);
            Output_Option (Prefix  => Prefix,
                           Option  => Tmp_String,
                           Acc     => Option_Str,
                           XML     => XML,
                           For_XML => True);
         end if;

      end if;
   end Output_Command_Line;

   function Ravenscar_Selected return Boolean is
   begin
      return Content.Concurrency_Profile = Ravenscar;
   end Ravenscar_Selected;

end CommandLineData;
