-- main is main file of main project written with Ada.
-- Main is Copyright (C) 2025 Manuel De Girardi ; 
--
--   This program is free software; you can redistribute it and/or modify
--   it under the terms of the GNU General Public License as published by
--   the Free Software Foundation; either version 2 of the License, or
--   (at your option) any later version.
--
--   This program 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
--   along with this program; if not, write to the Free Software
--   Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
--
-- Date := 2026-10-11 17:08:47 ; 
-- Version := 0.48.0a ; 
with GNAT.Directory_Operations.Iteration;
with Gnat.Regexp;
with Gnat.Directory_Operations;
with Ada.Strings.Fixed;
use Ada.Strings;
use Gnat.Directory_Operations;
with Gnat.Command_Line;
with Text_Io;
use Text_Io;
with System.Os_Constants;
use System.Os_Constants;
with Ada.Characters.Handling;
use Ada.Characters;
with Gnat.Os_Lib;
use Gnat;
with Ada.Wide_Text_Io;
use Ada;
with System.Os_Constants;
use System.Os_Constants;
with Gnat.Command_Line;
use Gnat.Command_Line;
with Ada.Characters.Handling;
use Ada.Characters.Handling;
package body M.Tools is
   function Integer_Image (Value : in Integer) return String is
   begin
      if Value < 0 then
	 return 
	   '-' & Integer'Image(Value)(Fixed.Index_Non_Blank(Integer'Image(Value)(2..Integer'Image(Value)'Last))..Integer'Image(Value)'Last);
      else
	 return 
	   Integer'Image(Value)(Fixed.Index_Non_Blank(Integer'Image(Value))..Integer'Image(Value)'Last);
      end if;
   end Integer_Image;

   
   function Spawn(Line : in String; Filename : in String) return M.Results.Result_Record is
      Command : Gnat.Command_Line.Command_Line;
            
      Spawn_Result : M.Results.Result_Record(M.Results.Spawn);
	        
      Buffer_args, Arguments_List : Os_Lib.Argument_List_Access;                  
      
      File : Wide_Text_Io.File_Type;      
      Deleted : Boolean := False;
      
      Exec_Path : Os_Lib.String_Access;
      Initialized : Boolean := False;
      
      
      Home : Os_Lib.String_Access;
      
      Out_Filename : String_Access;
      PID : Process_Id;
   begin
      case Target_Os is
	 when Windows =>	    
	    Home := Getenv("HOMEPATH");
	 when others =>
	    Home := Getenv("HOME");
      end case;
--      Out_Filename := new String ' (Home.all & Directory_Separator & Filename); 
      Out_Filename := new String ' (Filename); 
      Set_Command_Line(Command, Line);
      
      Gnat.Command_Line.Build(Command, Arguments_List, False);
      
      if Arguments_List(1) /= null and then Arguments_List(1).all /= "" then
         
         
         if Arguments_List'length > 1 then
            
            Buffer_Args := new Argument_List(1..Arguments_List'length - 1);
            
            for I in 1..Arguments_List'length - 1 loop
	       
               Buffer_Args(I) := new String ' (Normalize_Quoted_argument(Arguments_List(I+1).all));
	       
            end loop;            
            
            Spawn_Result := (Name         => M.Results.Spawn,
			     Wlines       => null,
			     Count        => 0,
			     Initialized  => False,
                             Process_Id   => Invalid_Pid,			  
                             Program_Name => M.Results."+"(To_Wide_String(Arguments_List(1).all)),
                             Args          => Buffer_Args,
                             Output_File  => M.Results."+"(To_Wide_String(Out_Filename.all)),
                             Success      => False,
                             Return_Code  => 0,
                             Err_To_Out   => True
                             
                            );
            
            
            
            
         else
            
            
            Spawn_Result := (Name         => M.Results.Spawn,
			     Wlines       => null,
			     Count        => 0,
			     Initialized  => False,
                             Process_Id   => Invalid_Pid,                             
                             Program_Name => M.Results."+"(To_Wide_String(Arguments_List(1).all)),
                             Args          => new Argument_List  ' (1..0 => new String ' ("" & Character'Val(0))),
                             Output_File  => M.Results."+"(To_Wide_String(Out_Filename.all)),
                             Success      => False,
                             Return_Code  => 0,
                             Err_To_Out   => True
                               
                            );
         end if;
         
         
         
         if Locate_Exec_On_Path(Arguments_List(1).all) /= null then
            Exec_Path := new String ' (Locate_Exec_On_Path(Arguments_List(1).all).all);         
                              
	    
            if Is_Executable_File(Exec_Path.all) then                                             
               
	       --  Os_Lib.Spawn(Program_Name => Exec_Path.all,
	       --  		    Args         => Spawn_Result.Args.all,                           
	       --  		    Output_File  => To_String(-Spawn_Result.Output_File),
	       --  		    Success      => Spawn_Result.Success,
	       --  		    Return_Code  => Spawn_Result.Return_Code,
	       --  		    Err_To_Out   => Spawn_Result.Err_To_out
	       --  		   );

	       Spawn_Result.Process_id := Os_Lib.Non_Blocking_Spawn(Program_Name => Exec_Path.all,
								    Args         => Spawn_Result.Args.all,                           
								    Output_File  => To_String(M.Results."-"(Spawn_Result.Output_File)),
								    --Success      => Spawn_Result.Success,
								    --Return_Code  => Spawn_Result.Return_Code,
								    Err_To_Out   => Spawn_Result.Err_To_out
								   );
               
               if Spawn_Result.Process_Id /= Gnat.Os_Lib.Invalid_Pid then
                  
                  Gnat.Os_Lib.Wait_Process(Spawn_Result.Process_Id, Spawn_Result.Success);
                  
               end if;               

               Spawn_Result.Wlines := new M.Results.U_Array(1..1);
               
               Wide_Text_Io.Open(File, Wide_Text_Io.In_File, To_String(M.Results."-"(Spawn_Result.Output_File)), Form => "WCEM=8");

               while not Wide_Text_Io.End_Of_File(File) loop

                  declare
                     
                     Line : constant Wide_String := Wide_Text_Io.Get_Line(File);
                     Buffer : M.Results.U_Array_Access;
                  begin
		     if M.Results."/="(Spawn_Result.Wlines, null) then
			
			if Initialized then
			   Buffer := new M.Results.U_Array(1..(Spawn_Result.Wlines'Length)+1);
			   Buffer(Buffer'First..Buffer'Last-1) := Spawn_Result.Wlines.all;
			   Buffer(Buffer'Last) := (M.Results."+"(Line));
			else
			   Buffer := new M.Results.U_array(1..1);
			   Buffer(Buffer'Last) := (M.Results."+"(Line));
			   Initialized := True;
			end if;

                        

                     end if;
                     M.Results.U_Array_Free(Spawn_Result.Wlines);
                     Spawn_Result.Wlines := new M.Results.U_Array ' (Buffer.all);
                     M.Results.U_Array_Free(Buffer);
                     
                  end;
                  
               end loop;

               Wide_Text_Io.Close(File);

	       Spawn_Result.Success := True;
	       
               --Delete_File (Name => To_String((-Spawn_Result.Output_File)), Success => deleted);
               Spawn_Result.Return_Code := Gnat.Os_Lib.Errno;
               --  if Spawn_Result.Success then      
               --     Spawn_Result.Return_Code := Gnat.Os_Lib.Errno;
               --  end if;
            else
               Spawn_Result.Wlines := new M.Results.U_Array ' (1 => (M.Results."+"(To_Wide_String(Arguments_List(1).all) & " : command not found.")));               
               Spawn_Result.Return_Code := 127;
            end if;
         else            
            Spawn_Result.Wlines := new M.Results.U_Array ' (1 => (M.Results."+"(To_Wide_String(Arguments_List(1).all) & " : command not found.")));               
            Spawn_Result.Return_Code := 127;
         end if;         
      else         
         Spawn_Result.Wlines := new M.Results.U_Array ' (1 => (M.Results."+"(To_Wide_String(Arguments_List(1).all) & " : command not found.")));                        
         Spawn_Result.Return_Code := 127;
      end if;
      
      return Spawn_Result;
   end Spawn;    

   
   function Delete_Local_Prefix(Filename : in String) return String is
   begin
      if Filename'Length > 2 then
         if Filename(Filename'First..Filename'First+1) = Local_Prefix then
            return Filename(Filename'First+2..Filename'Last);
         else
            return Filename;
         end if;
      else
         return Filename;
      end if;
   end Delete_Local_Prefix;
   
   
   function Normalize_Quoted_Argument(Arg : in String) return String is
      Local : String(1..Arg'Length) := Arg;
      Local_Index : Natural := 0;
   begin

      for I in Arg'First .. Arg'Last loop 
         if Arg(i) /= '"' then

            Local(Local_Index + 1) := Arg(I);
            Local_Index := Local_Index + 1;

         end if;
      end loop;

      if Local_Index /= 0 then

         return Local(Local'First..Local_index);
      else

         return Arg;
      end if;
      
   end Normalize_Quoted_Argument;

   
   function Search_Regexp (Path : in String;
                           Pattern : in String) return String is
      
      Full_Line : String_Access := new String ' ("");
      
      
      procedure Action (Filename : in String;
                        Index    : in Positive;
                        Verax    : in out Boolean) is
         
         Buffer : String_Access := new String ' ("");
         Tmp    : String_Access := new String ' ("");
         
         Is_Out : Boolean := True;
         Regular_Exp : Gnat.Regexp.Regexp;
      begin
         
         --Text_Io.Put_line("File : "& Filename & "; Pattern : " & Pattern); 
         Regular_Exp := Gnat.Regexp.Compile("*" & Pattern, True, True);
         
         
         if Gnat.Regexp.Match(Filename, Regular_Exp) then
            if Fixed.Index(Filename, " ") /= 0 then
               
               for I in Filename'First..Filename'Last-1 loop
                  if Filename(I) = Character'Val(32) then                    
                     Buffer := new String ' (Tmp.all & " ");
                     Free(Tmp);
                     Tmp := new String ' (Buffer.all);
                     Free(Buffer);
                  elsif Filename(I) = '/' then
                     if Fixed.Index(Filename, " ", I) > I and Fixed.Index(Filename, "/", I+1) > Fixed.Index(Filename, " ", I) then
                        if Is_Out then
                           Buffer := new String ' (Tmp.all & Filename(I) & """");
                           Free(Tmp);
                           Tmp := new String ' (Buffer.all);
                           Free(Buffer);
                           Is_Out := False;
                        else
                           Buffer := new String ' (Tmp.all & Filename(I));
                           Free(Tmp);
                           Tmp := new String ' (Buffer.all);
                           Free(Buffer);
                        end if;
                        
                     elsif Fixed.Index(Filename, " ", I) > I and Fixed.Index(Filename, "/", I+1) = 0 then
                        
                        if Is_Out then
                           Buffer := new String ' (Tmp.all & Filename(I) & """");
                           Free(Tmp);
                           Tmp := new String ' (Buffer.all);
                           Free(Buffer);
                           Is_Out := False;
                        else
                           Buffer := new String ' (Tmp.all & Filename(I));
                           Free(Tmp);
                           Tmp := new String ' (Buffer.all);
                           Free(Buffer);
                        end if;
                     else
                        Buffer := new String ' (Tmp.all & Filename(I));
                        Free(Tmp);
                        Tmp := new String ' (Buffer.all);
                        Free(Buffer);
                     end if;
                     
                  else
                     Buffer := new String ' (Tmp.all & Filename(I));
                     Free(Tmp);
                     Tmp := new String ' (Buffer.all);
                     Free(Buffer);
                  end if;
                  
               end loop;
               Buffer := new String ' (Tmp.all & Filename(Filename'Last));
               if not Is_Out then                 
                  Buffer := new String ' (Tmp.all & """");
                  Free(Tmp);
                  Tmp := new String ' (Buffer.all);
                  Free(Buffer);
               end if;
               --Text_Io.Put_Line("Matched :" & Full_Line.all);
               if Full_Line'Length > 0 then
                  Buffer := new String ' (Full_Line.all & ' ' & "" & Delete_Local_Prefix(Tmp.all) & "");
                  Free(Full_Line);
                  Full_Line := new String ' (Buffer.all);
                  Free(Buffer);
                  
               else
                  Buffer := new String ' (Full_Line.all & "" & Delete_Local_Prefix(Tmp.all) & "");
                  Free(Full_Line);
                  Full_Line := new String ' (Buffer.all);
                  Free(Buffer);            
               end if;
               --Text_Io.Put_Line("Matche :" & Tmp.all);
            else
               --Text_Io.Put_Line("Matched :" & filename);
               if Full_Line'Length > 0 then
                  Buffer := new String ' (Full_Line.all & ' ' &  Delete_Local_Prefix(filename));
                  Free(Full_Line);
                  Full_Line := new String ' (Buffer.all);
                  Free(Buffer);            
               else
                  Buffer := new String ' (Full_Line.all & "" & Delete_Local_Prefix(filename) & "");
                  Free(Full_Line);
                  Full_Line := new String ' (Buffer.all);
                  Free(Buffer);
                  
               end if;
               --Text_Io.Put_Line("Matche :" & filename);
            end if;
         end if;
         Verax := False;
      end Action;
      
      
      
      
      procedure File_Search is
         new Iteration.Wildcard_iterator(Action);
      
      
   begin
      
      
      --Text_Io.Put_Line("pattern for : " & Expand_Path(Pattern));
      
      
      if Expand_Path(Pattern) /= "" then
         
         File_Search(Path);
      end if;
      if Full_Line'Length > 0 then
         declare
            Result : constant String := Full_Line.all;
         begin
            Free(Full_Line);
            return Result;
         end;
      else
         return Expand_Path(Pattern);
      end if;
   exception 
      when others =>
         if Full_Line'Length > 0 then
            declare
               Result : constant String := Full_Line.all;
            begin
               Free(Full_Line);
               return Result;
            end;
         else
            return Expand_Path(Pattern);
         end if;
   end Search_Regexp;

   function Expand_filename (Line : in String) return String is
      
      

      Absolute_Path : constant Character := '/';

      
      procedure Recursive_Expand (Line : in String; Result : in out String_Access) is
         
         Start, Stop : Natural := 0;
      begin
         if Line'Length > 1 then            
            if Start = 0 then
               Start := Line'First;
            end if;
            
            Stop := Fixed.Index(Line, " ", Start+1);
            if Stop /= 0 then
               if Line(Start) /= Absolute_Path then
                  
                  Result := new String ' (Result.all & ' ' & Search_Regexp(Expand_Path(Line(Start..Stop-1)), Line(Start..Stop-1)));
               else               
                  
                  Result := new String ' (Result.all & ' ' & Search_Regexp(Expand_Path(Line(Start..Stop-1)), Line(Start..Stop-1)));
               end if;          
               Recursive_Expand(Line(Stop+1..Line'last), Result);
               
               
            else
               
               
               if Line(Start) /= Absolute_Path then
                  
                  Result := new String ' (Result.all & ' ' & Search_Regexp(Expand_Path(Line(Start..Line'last)), Line(Start..Line'Last)));
               else               
                  
                  Result := new String ' (Result.all & ' ' & Search_Regexp(Expand_Path(Line(Start..Line'last)), Line(Start..Line'Last)));
               end if;          
               
               
            end if;
            
         else
            if Start = 0 then
               Start := Line'First;
            end if;
            if Line(Start) /= Absolute_Path then
               
               Result := new String ' (Result.all & ' ' & Search_Regexp(Expand_Path(Line(Start..Line'Last)), Line(Start..Line'Last)));
            else                  
               
               Result := new String ' (Result.all & ' ' & Search_Regexp(Expand_Path(Line(Start..Line'last)), Line(Start..Line'Last)));
            end if;                       
            
         end if;
      end Recursive_Expand;
      Full_Set : String_Access := new String ' ("");
   begin
      
      Recursive_Expand(Line(Fixed.Index_Non_Blank(Line)..Fixed.Index_Non_Blank(Line, Backward)), Full_Set);
      
      if Full_Set'Length > 0 then
         declare
            Result : constant String := Full_Set.all(Fixed.Index_Non_Blank(Full_Set.all)..Fixed.Index_Non_Blank(Full_Set.all, Backward));
         begin
            Free(Full_Set);
            return Result;
         end;            
      else
         return "";
      end if;
      
   end Expand_Filename;
   
   
   procedure Change_directory (Line : in String;Old_Pwd : in out String_Access) is
      Command : Gnat.Command_Line.Command_Line;
      
      Args_List : Argument_List_Access;                  
      Buffer : String_Access;
   begin      
      Gnat.Command_Line.Set_Command_Line(Command, Line);
      Gnat.Command_Line.Build(Command, Args_List, False);
      if Args_List'Last > 2 then
	 
	 return;
      elsif Args_List'Last = 2 then
	 if Args_List(2) /= null and then Args_List(2).all /= "" then
	    if Args_List(2).all = "-" then
	       if Old_Pwd'Length /= 0 then		  
		  
		  buffer := new String ' (Get_Current_Dir);
		  Change_Dir(Old_Pwd.all);
		  Free(Old_Pwd);
		  Old_Pwd := new String ' (Buffer.all);
		  Free(Buffer);
		  
	       else
		  
		  Put_Line("no old_pwd.");
	       end if;
	    else
	       Free(Old_Pwd);
	       Old_Pwd := new String ' (Get_Current_Dir);	       
	       Change_Dir(Args_List(2).all);
	       
	    end if;

	 end if;
      else	 
	 case Target_Os is
	    when Windows =>
	       Free(Old_Pwd);
	       Old_Pwd := new String ' (Get_Current_Dir);
	       Change_Dir(Getenv("HOMEPATH").all);	       
	       
	    when Other_OS =>
	       Free(Old_Pwd);
	       Old_Pwd := new String ' (Get_Current_Dir);
	       Change_Dir(Getenv("HOME").all);
	       
	 end case;
      end if;   

   end Change_Directory;
   
   

   
   use Gnat.Regexp;   
   
   
   
   
   procedure Find_At_Path (Path : in String;
			   Pattern : in String;
			   Result : in M.Results.Wide_Result_Access) is
      
      Reg_Exp : constant Gnat.Regexp.Regexp := Gnat.Regexp.Compile(Pattern, True, True);
      
      procedure Find_Action (Item  :        String;
			     Index :        Positive;
			     Quit  : in out Boolean) is	 
	 Buffer : M.Results.U_array_Access;
	 
	 
	 
      begin
	 if Match(Item, Reg_Exp) then
	    Buffer := new M.Results.u_Array(1..(Result.Wlines'Length)+1);
	    Buffer(Buffer'First..Buffer'Last-1) := Result.Wlines.all;
	    Buffer(Buffer'Last) := (M.Results."+"(Handling.To_Wide_String(Item)));
	    M.Results.U_Array_free(Result.Wlines);
	    Result.Wlines := new M.Results.U_Array ' (Buffer.all);
	    Quit := False;
	 end if;
      end Find_Action;
      
      procedure Wildcard_Iterator is
	 new GNAT.Directory_Operations.Iteration.Wildcard_Iterator(Find_Action);
      
   begin      
      Wildcard_Iterator(Path);
   end Find_At_Path;
   
   procedure Completion (Line : in String;
			 Full_Command : out Wide_String_Access;
			 Result : out M.Results.Wide_Result_Access) is
      
      Top : constant Natural := Fixed.Index_Non_Blank(Line);
      Bot : constant Natural := Fixed.Index_Non_Blank(Line, Backward);
      
      Blank_Index : constant Natural := Fixed.Index(Line(Top..Bot), " ", Backward);
      
      
      
   begin
      Result := new M.Results.spawn_Result_Record;
      Result.Wlines := new M.Results.U_Array (1..1);
      
      if Blank_Index < Bot then
	 declare
	    Path : constant String := Line(Blank_Index+1..Bot);
	    Directory_Index : constant Natural := 
	      Fixed.Index(Path, "/", Backward);
	 begin
	    if Directory_Index > 0 and 
	      Directory_Index < Path'Last then
	       declare
		  Directory : constant String := 
		    Path(Path'First..Directory_Index);
	       begin
		  Find_At_Path(Directory,
			       "*" & Path(Directory_Index+1..Path'Last) & "*",
			       Result);
	       end;
	    elsif Directory_Index > 0 then
	       declare
		  Directory : constant String := 
		    Path(Path'First..Directory_Index);
	       begin

		  Find_At_Path(Directory, 
			       "*",
			       Result);
	       end;
	    else
	       begin

		  Find_At_Path(Get_Current_Dir,
			       "*" & Path & "*",
			       Result);
	       end;
	    end if;
	 end;
      else

	 
	 begin
	    
	    Find_At_Path(Get_Current_Dir,
			 "*",
			 Result);
	 end;
      end if;
      
      if Result.Wlines'Length = 2 then
	 Full_Command := new Wide_String ' (Handling.To_Wide_String(Line(Line'First..Blank_Index)) & Handling.To_Wide_String(Delete_Local_Prefix(Handling.To_String((M.Results."-"(Result.Wlines(2)))))));
      end if;
      

      
   end Completion;
   
   use Adam.Results;
   
   function Shell_Spawn(Line : in String) return Adam.Results.Spawn_Result_Type is
      
      Command : Gnat.Command_Line.Command_Line;
            
      Spawn_Result : Adam.Results.Spawn_Result_Type;
	        
      Buffer_args, Arguments_List : Os_Lib.Argument_List_Access;                  
      
      File : Wide_Text_Io.File_Type;      
      
      Home : constant Os_Lib.String_Access := Getenv("HOME");
      
      Out_Filename : constant String := Home.all & "/.out_file.txt";
      
      Deleted : Boolean := False;
      
      Exec_Path : Os_Lib.String_Access;
      Initialized : Boolean := False;
      
      
      
      GnuShell_Filename : constant String := Home.all & "/.buffer.txt";
      
      GnuShell_File : Wide_Text_Io.File_Type;      
      
   begin
      
      Set_Command_Line(Command, Line);
      
      Gnat.Command_Line.Build(Command, Arguments_List, False);
      
      if Arguments_List(1) /= null and then Arguments_List(1).all /= "" then         
         
         if Arguments_List'length > 1 then
            
            Buffer_Args := new Argument_List(1..Arguments_List'length - 1);
            
            for I in 1..Arguments_List'length - 1 loop
	       
               Buffer_Args(I) := new String ' (Normalize_Quoted_argument(Arguments_List(I+1).all));
	       
            end loop;            
            
            Spawn_Result := (
                             Process_Id   => Invalid_Pid,			  
                             Program_Name => +To_Wide_String(Arguments_List(3).all),
                             Args          => Buffer_Args,
                             Output_File  => +To_Wide_String(Out_Filename),
                             Success      => False,
                             Return_Code  => 0,
                             Err_To_Out   => True,
                             File_content => null			    
                            );
            
            
            
            
         else
            
            
            Spawn_Result := (
                             Process_Id   => Invalid_Pid,                             
                             Program_Name => +To_Wide_String(Arguments_List(3).all),
                             Args          => new Argument_List  ' (1..0 => new String ' ("" & Character'Val(0))),
                             Output_File  => +To_Wide_String(Out_Filename),
                             Success      => False,
                             Return_Code  => 0,
                             Err_To_Out   => True,
                             File_content => null
                               
                            );
         end if;
         
         
         
         if Locate_Exec_On_Path(Arguments_List(1).all) /= null then
            Exec_Path := new String ' (Locate_Exec_On_Path(Arguments_List(1).all).all);         
                              
            
            if Is_Executable_File(Exec_Path.all) then
                              
               
               
               Spawn_Result.Process_Id := 
                 Non_Blocking_Spawn(Program_Name => Exec_Path.all,
                                    Args         => Spawn_Result.Args.all,                           
                                    Output_File  => To_String((-Spawn_Result.Output_File)),
                                    Err_To_Out   => Spawn_Result.Err_To_out
                                   );
               
               if Spawn_Result.Process_Id /= Gnat.Os_Lib.Invalid_Pid then
                  
                  Gnat.Os_Lib.Wait_Process(Spawn_Result.Process_Id, Spawn_Result.Success);
                  
               end if;               
               
               Spawn_Result.File_Content := new Variadic_Array(1..1);
               
	       
               Wide_Text_Io.Open(File, Wide_Text_Io.In_File, To_String(-Spawn_Result.Output_File), Form => "WCEM=8");
	       
   	       begin
   	       	  Wide_Text_Io.Open(Gnushell_File, Wide_Text_Io.Append_File, Gnushell_Filename, Form => "WCEM=8");
   	       exception
   	       	  when others =>
   	       	     Wide_Text_Io.Create(Gnushell_File, Wide_Text_Io.Out_File, Gnushell_Filename, Form => "WCEM=8");
   	       end;
   	       while not Wide_Text_Io.End_Of_File(File) loop

                  declare
                     
                     Line : constant Wide_String := Wide_Text_Io.Get_Line(File);
                     
                  begin
                     Wide_Text_Io.Put_Line(Gnushell_File, Line);
                     
                  end;
                  
               end loop;
   	       Wide_Text_Io.Close(File);
   	       Wide_Text_Io.Close(Gnushell_File);
   	       Wide_Text_Io.Open(Gnushell_File, Wide_Text_Io.In_File, Gnushell_Filename, Form => "WCEM=8");
               while not Wide_Text_Io.End_Of_File(Gnushell_File) loop

                  declare
                     
                     Line : constant Wide_String := Wide_Text_Io.Get_Line(GnuShell_File);
                     Buffer : Variadic_Access;
                  begin
   		     if Spawn_Result.File_Content /= null then
			
   			if Initialized then
   			   Buffer := new Variadic_Array(1..(Spawn_Result.File_Content'Length)+1);
   			   Buffer(Buffer'First..Buffer'Last-1) := Spawn_Result.File_Content.all;
   			   Buffer(Buffer'Last) := (+(Line));
   			else
   			   Buffer := new Variadic_Array(1..1);
   			   Buffer(Buffer'Last) := (+(Line));
   			   Initialized := True;
   			end if;
                        

                     end if;
                     
                     Spawn_Result.File_Content := new Variadic_Array ' (Buffer.all);
                     
                     
                  end;
                  
               end loop;
               Wide_Text_Io.Close(Gnushell_File);	 
               
               Delete_File (Name => To_String((-Spawn_Result.Output_File)), Success => deleted);
               --Wide_Text_Io.Put_Line("Deleted file : "& (-Spawn_Result.Output_File));
               if not Spawn_Result.Success then      
                  Spawn_Result.Return_Code := Gnat.Os_Lib.Errno;
               end if;
            else
               Spawn_Result.File_Content := new Variadic_Array ' (1 => (+(To_Wide_String(Arguments_List(1).all) & " : command not found.")));               
               Spawn_Result.Return_Code := 127;
            end if;
         else            
            Spawn_Result.File_Content := new Variadic_Array ' (1 => (+(To_Wide_String(Arguments_List(1).all) & " : command not found.")));               
            Spawn_Result.Return_Code := 127;
         end if;         
      else         
         Spawn_Result.File_Content := new Variadic_Array ' (1 => (+(To_Wide_String(Arguments_List(1).all) & " : command not found.")));                        
         Spawn_Result.Return_Code := 127;
      end if;
      
      return Spawn_Result;
   end Shell_Spawn;    

end M.Tools ;