-- Counting_Coffee - An example of tabular programming with the goal of unstructured data summation. -- Copyright (C) 2023 Prince Trippy . -- This program is free software: you can redistribute it and/or modify it under the terms of the -- GNU Affero General Public License version 3 as published by the Free Software Foundation. -- 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 Affero General Public License for more details. -- You should have received a copy of the GNU Affero General Public License along with this program. -- If not, see . -- This program requires Ada 2005 support due entirely to the function form of Ada.Text_IO.Get_Line. with Trivial_Trie, Ada.Text_IO, Ada.Command_Line; procedure Counting_Coffee is package Trie is new Trivial_Trie(Index_Type => Positive, Domain_Type => Character, Input_Type => String, Stored_Type => Natural); Tray : Trie.Trie; File, Sink : Ada.Text_IO.File_Type; Count : Natural := 0; begin Ada.Command_Line.Set_Exit_Status(Ada.Command_Line.Failure); Ada.Text_IO.Set_Output(Ada.Text_IO.Standard_Error); case Ada.Command_Line.Argument_Count is when 1 | 2 | 3 => null; when others => Ada.Text_IO.Put_Line("Supply one, two, or three files: " & "input, any previous output, and a new output."); return; end case; if Ada.Command_Line.Argument_Count = 3 then Ada.Text_IO.Create(Sink, Mode => Ada.Text_IO.Append_File, Name => Ada.Command_Line.Argument(3)); end if; if Ada.Command_Line.Argument_Count > 1 then -- Build a trie from any previous run of the program. Ada.Text_IO.Open(File, Mode => Ada.Text_IO.In_File, Name => Ada.Command_Line.Argument(2)); Ada.Text_IO.Set_Input(File); while not Ada.Text_IO.End_Of_File loop declare Line : String := Ada.Text_IO.Get_Line; Here : Boolean; Size : Natural; begin Trie.Find(Path => Line, Tree => Tray, Seen => Here, Unto => Size); if Here then Ada.Text_IO.Put_Line("Duplicated lines aren't allowed in the previous output file."); return; else Size := Natural'Value(Ada.Text_IO.Get_Line); Trie.Give(Path => Line, Tree => Tray, What => Size); -- It's possible to provide the same file, for both a previous input and then output. -- I recall not any access to the underlying nonsense for detecting such through Ada. -- Though, the trie duplication detection alone will eventually end such a situation. -- Records must be sent piecewise as collected, due to the nature of exploring tries. if Ada.Text_IO.Is_Open(Sink) then Ada.Text_IO.Put_Line(Sink, Line); Ada.Text_IO.Put_Line(Sink, Natural'Image(Size)); end if; end if; end; end loop; Ada.Text_IO.Set_Input(Ada.Text_IO.Standard_Input); Ada.Text_IO.Close(File); end if; -- The remainder of the code is mostly the same as the simpler of these Counting_Coffee programs. Ada.Text_IO.Open(File, Mode => Ada.Text_IO.In_File, Name => Ada.Command_Line.Argument(1)); while not Ada.Text_IO.End_Of_File(File) loop declare Line : String := Ada.Text_IO.Get_Line(File); Here : Boolean; Size : Natural; begin Trie.Find(Path => Line, Tree => Tray, Seen => Here, Unto => Size); if not Here then loop begin Ada.Text_IO.Put_Line(Line); Size := Natural'Value(Ada.Text_IO.Get_Line); exit; exception when Constraint_Error => Ada.Text_IO.Put_Line("Supply a natural number."); end; end loop; Trie.Give(Path => Line, Tree => Tray, What => Size); if Ada.Text_IO.Is_Open(Sink) then Ada.Text_IO.Put_Line(Sink, Line); Ada.Text_IO.Put_Line(Sink, Natural'Image(Size)); end if; end if; Count := Count + Size; end; end loop; Ada.Text_IO.Put_Line(Ada.Text_IO.Standard_Output, Natural'Image(Count)); if Ada.Text_IO.Is_Open(Sink) then Ada.Text_IO.Flush(Sink); Ada.Text_IO.Close(Sink); end if; Ada.Text_IO.Flush(Ada.Text_IO.Standard_Error); Ada.Text_IO.Flush(Ada.Text_IO.Standard_Output); Ada.Text_IO.Close(File); Ada.Command_Line.Set_Exit_Status(Ada.Command_Line.Success); exception when Storage_Error => Ada.Text_IO.Put_Line("Working storage has been exhausted."); when others => Ada.Text_IO.Put_Line("Either integer overflow or a file error has occurred."); end Counting_Coffee; .