--  Configure AdaBrowse with or without project file support

with Ada.Calendar;
with Ada.Command_Line;
with Ada.Strings.Unbounded;
with Ada.Text_IO;

with Util.Execution;
with Util.Files;
with Util.Pathes;
with Util.Strings;
with Util.Calendar.IO;

procedure ADConf is

   package ASU renames Ada.Strings.Unbounded;

   Gcc      : ASU.Unbounded_String;
   Asis_Dir : ASU.Unbounded_String;
   Gnat_Src : ASU.Unbounded_String;
   Gnat_Lib : ASU.Unbounded_String;

   function Handle_Command_Line
     return Boolean
   is
      use Ada.Command_Line;
   begin
      if Argument_Count /= 4 then return False; end if;
      Gcc      := ASU.To_Unbounded_String (Argument (1));
      Asis_Dir := ASU.To_Unbounded_String (Argument (2));
      Gnat_Src := ASU.To_Unbounded_String (Argument (3));
      Gnat_Lib := ASU.To_Unbounded_String (Argument (4));
      return True;
   end Handle_Command_Line;

   function Configure
     return Boolean
   is

      procedure Open is
         new Util.Files.Open_G (Ada.Text_IO.File_Type,
                                Ada.Text_IO.File_Mode,
                                Ada.Text_IO.Open,
                                Ada.Text_IO.Create);
      use Ada.Text_IO;

      procedure Generate_Header
        (File : in out File_Type)
      is
         Now : Ada.Calendar.Time := Ada.Calendar.Clock;
      begin
         Put_Line (File,
                   "--  This file has been generated automatically by the");
         Put_Line (File,
                   "--  AdaBrowse configuration tool adconf.");
         Put_Line (File,
                   "--");
         Put_Line (File,
                   "--  Generated on " & Util.Calendar.IO.Image (Now) & ' ' &
                   Util.Calendar.IO.Image (Ada.Calendar.Seconds (Now)));
         Put_Line (File,
                   "--");
         Put_Line (File,
                   "--  DO NOT MODIFY THIS FILE!");
         New_Line (File);
         Put_Line (File,
                   "pragma License (GPL);");
         New_Line (File);
      end Generate_Header;

      procedure Generate_Stub
        (Component : in String)
      is
         File : File_Type;
      begin
         Open (File, Out_File, "ad-projects-impl_yes-get_parent.adb");
         Generate_Header (File);
         Put_Line (File, "with Prj;");
         Put_Line (File, "separate (AD.Projects.Impl_Yes)");
         Put_Line (File, "function Get_Parent");
         Put_Line (File, "  (Project : in Prj.Project_Id)");
         Put_Line (File, "  return Prj.Project_Id");
         Put_Line (File, "is");
         Put_Line (File, "begin");
         Put_Line (File, "   return Prj.Projects.Table (Project)." &
                         Component & ';');
         Put_Line (File, "end Get_Parent;");
         Close (File);
      end Generate_Stub;

      procedure Generate_Renaming
        (Package_Suffix : in String)
      is
         Package_Name : constant String :=
           "AD.Projects.Impl_" & Package_Suffix;

         File : File_Type;
      begin
         Open (File, Out_File, "ad-projects-impl.ads");
         Generate_Header (File);
         Put_Line (File, "with " & Package_Name & ';');
         Put_Line (File,
                   "private package AD.Projects.Impl");
         Put_Line (File,
                   "  renames " & Package_Name & ';');
         Close (File);
      end Generate_Renaming;

      function Try_To_Build
        return Boolean
      is
         File                : File_Type;
         Three_Fifteen_Tried : Boolean;

         GnatMake : constant String :=
           "gnatmake -q -gnatwIL -I. -I.." &
           " -I" & ASU.To_String (Asis_Dir) &
           " -I" & ASU.To_String (GNAT_Lib) &
           " -I" & ASU.To_String (Gnat_Src) &
           " adtest -largs -lasis";

      begin
         --  Generate the renaming.
         Generate_Renaming ("Yes");
         --  Generate the stub. Try to get it right the first time:
         if
            Util.Strings.First_Index (ASU.To_String (Gnat_Src), "3.15") /= 0
         then
            Three_Fifteen_Tried := True;
            Generate_Stub ("Modifies");
         else
            Three_Fifteen_Tried := False;
            Generate_Stub ("Extends");
         end if;
         --  Try to compile the file:
         declare
            Result : Integer;
         begin
            Util.Execution.Execute
              (ASU.To_String (Gcc) & " -c ../util-nl.c");
            Result := Util.Execution.Execute (GnatMake);
            if Result /= 0 then
               --  Maybe the stub was wrong?
               if Three_Fifteen_Tried then
                  Generate_Stub ("Extends");
               else
                  Generate_Stub ("Modifies");
               end if;
               Result := Util.Execution.Execute (GnatMake);
            end if;
            return Result = 0;
         end;
      end Try_To_Build;

      procedure Remove
        (Name : in String)
      is
         File : File_Type;
      begin
         Ada.Text_IO.Open (File, In_File, Name);
         Delete (File);
      exception
         when others =>
            null;
      end Remove;

      File : File_Type;

   begin
      if Handle_Command_Line then
         Put_Line (Current_Error, "===============================");
         Put_Line (Current_Error, "AdaBrowse configuration STARTS.");
         Put_Line (Current_Error,
                   "Compiler          => " & ASU.To_String (Gcc));
         Put_Line (Current_Error,
                   "ASIS installation => " & ASU.To_String (Asis_Dir));
         Put_Line (Current_Error,
                   "GNAT sources      => " & ASU.To_String (Gnat_Src));
         Put_Line (Current_Error,
                   "GNAT library      => " & ASU.To_String (Gnat_Lib));
         --  Generate the test main program. We want to try linking, too!
         Open (File, Out_File, "adtest.adb");
         Put_Line
           (File,  "-- This file is just temporary, it will be deleted");
         Put_Line
           (File,  "-- once AdaBrowse is configured.");
         Put_Line (File, "with AD.Projects;");
         Put_Line (File, "procedure ADTest is");
         Put_Line (File, "begin");
         Put_Line (File, "   AD.Projects.Handle_Project_File (""blah"");");
         Put_Line (File, "end ADTest;");
         Close (File);
         declare
            Result : Boolean := Try_To_Build;
         begin
            --  Delete the test driver
            Remove ("adtest.adb");
            Remove ("adtest.o");
            Remove ("adtest.ali");
            Remove ("adtest.exe");
            if Result then
               return True;
            else
               Put_Line
                 (Current_Error,
                  "Cannot configure AdaBrowse with GNAT project manager " &
                  "support.");
            end if;
         end;
      end if;
      --  Didn't work: generate a renaming that points to a null
      --  implementation.
      Generate_Renaming ("No");
      return False;
   end Configure;

begin
   if Configure then
      Ada.Text_IO.Put_Line
        (Ada.Text_IO.Current_Error,
         "==================================================");
      Ada.Text_IO.Put_Line
        (Ada.Text_IO.Current_Error,
         "AdaBrowse configured WITH project manager support.");
   else
      Ada.Text_IO.Put_Line
        (Ada.Text_IO.Current_Error,
         "=====================================================");
      Ada.Text_IO.Put_Line
        (Ada.Text_IO.Current_Error,
         "AdaBrowse configured WITHOUT project manager support.");
   end if;
   Ada.Command_Line.Set_Exit_Status (Ada.Command_Line.Success);
exception
   when others =>
      Ada.Text_IO.Put_Line
        (Ada.Text_IO.Current_Error,
         "================================");
      Ada.Text_IO.Put_Line
        (Ada.Text_IO.Current_Error,
         "AdaBrowse configuration FAILED!!");
      Ada.Command_Line.Set_Exit_Status (Ada.Command_Line.Failure);
      raise;
end ADConf;


