with Ada.Command_Line; use Ada.Command_Line;
with Ada.Directories;use Ada.Directories;
with Ada.Exceptions;
with Ada.Io_Exceptions;
with Ada.Sequential_IO;
with Ada.Text_IO; use Ada.Text_IO;
with Bits; use Bits;
with Interfaces; use Interfaces;
with SMG_Keccak; use SMG_Keccak;
with Character_IO; use Character_IO;
procedure Ksum is
   Buffer_Size: constant Natural := 2048;
   Hash_Size: constant Natural := 64;
   Byte_Size: constant Natural := 8;
   
   package CIO renames Character_IO.Character_IO;
   Fs: File_Size;
   File: CIO.File_Type;
   Ctx: Keccak_Context(Block_Len=>Default_Bitrate);
   Buf: String(1..Buffer_Size);
   B: Bitstream(1..Buf'Length*Byte_Size);
   
   function Read_Buffer return Integer is
      C: Character;
   begin
      for I in 1..Buf'Length loop
         CIO.Read(File, C);
         Buf(I):=C;
         if End_Of_File(File) then
            return I;
         end if;
      end loop;
      return Buf'Length;
   end Read_Buffer;
   
begin
   for Arg in 1..Argument_Count loop
      declare
         Filename: String:=Argument(Arg);
      begin
         Fs:=Size(Filename);
         Character_IO.Open(File, CIO.In_File, Filename);
         declare
            O: Bitstream(1..Hash_Size*Byte_Size);
            N: Integer;
         begin
            KeccakBegin(Ctx);
        Read_Loop:
            loop
               exit Read_Loop when End_Of_File(File);
               N := Read_Buffer;
               ToBitstream(Buf(1..N), B(1..N*Byte_Size));
               KeccakHash(Ctx, B(1..N*Byte_Size));
            end loop Read_Loop;
            KeccakEnd(Ctx, O);
            declare
               Hex: String := ToHex(O);
            begin
               Put(Hex); Put("  "); Put_Line(Filename);
            end;
         end;
         Character_IO.Close(File);
      exception
         when The_Error : others =>
            Put(Standard_Error, Filename); Put(": "); 
            Put_Line(Ada.Exceptions.Exception_Message(The_Error));
      end;
   end loop;
end;
