diff options
Diffstat (limited to 'tool/template.adb')
-rw-r--r-- | tool/template.adb | 156 |
1 files changed, 156 insertions, 0 deletions
diff --git a/tool/template.adb b/tool/template.adb new file mode 100644 index 0000000..a28fff8 --- /dev/null +++ b/tool/template.adb @@ -0,0 +1,156 @@ + + +-- Programmed by Jedidiah Barber +-- Released into the public domain + + +-- This is a tool that reads in a file with an exact template +-- and a file with sets of substitution rules with each rule +-- of the form X=Y and with each set of rules separated by +-- one or more blank lines. + +-- It then applies each set of rules to a copy of the template +-- and puts the result to standard output. + +-- The specific use this tool was written for was to deal with +-- very repetitive codegen such as binding static char get/set. +-- But of course, it can be useful for other things too. + + +with + + Ada.Characters.Latin_1, + Ada.Command_Line, + Ada.Containers.Indefinite_Ordered_Maps, + Ada.Direct_IO, + Ada.Directories, + Ada.Strings.Maps, + Ada.Strings.Unbounded, + Ada.Text_IO; + + +procedure Template is + + + package Latin renames Ada.Characters.Latin_1; + package ACom renames Ada.Command_Line; + package ADir renames Ada.Directories; + package SMap renames Ada.Strings.Maps; + package SU renames Ada.Strings.Unbounded; + package TIO renames Ada.Text_IO; + + + package Char_IO is new Ada.Direct_IO (Character); + + + My_Template : Char_IO.File_Type; + My_Rule_List : TIO.File_Type; + + + Element_In : Character; + Template_Input, Copy_Input : SU.Unbounded_String; + + + Sub_Line : SU.Unbounded_String; + Cut_At : Natural; + + + package String_Maps is new Ada.Containers.Indefinite_Ordered_Maps + (Key_Type => String, + Element_Type => String); + + Rule_Map : String_Maps.Map; + + + procedure Process + (Text : in out SU.Unbounded_String; + Rules : in String_Maps.Map) + is + Token_At : Natural; + begin + for C in Rules.Iterate loop + Token_At := 1; + while Token_At <= SU.Length (Text) loop + Token_At := SU.Index (Text, String_Maps.Key (C), Token_At); + exit when Token_At = 0; + SU.Replace_Slice + (Text, + Token_At, + Token_At + String_Maps.Key (C)'Length - 1, + String_Maps.Element (C)); + Token_At := Token_At + String_Maps.Element (C)'Length; + end loop; + end loop; + end Process; + + +begin + + + if ACom.Argument_Count /= 2 then + TIO.Put_Line + (TIO.Standard_Error, + "ERROR: Need an input template file and a substitution list file"); + ACom.Set_Exit_Status (ACom.Failure); + return; + end if; + + if not ADir.Exists (ACom.Argument (1)) then + TIO.Put_Line + (TIO.Standard_Error, + "ERROR: Input template file does not exist"); + ACom.Set_Exit_Status (ACom.Failure); + return; + end if; + + if not ADir.Exists (ACom.Argument (2)) then + TIO.Put_Line + (TIO.Standard_Error, + "ERROR: Substitution list file does not exist"); + ACom.Set_Exit_Status (ACom.Failure); + return; + end if; + + + Char_IO.Open (My_Template, Char_IO.In_File, ACom.Argument (1)); + while not Char_IO.End_Of_File (My_Template) loop + Char_IO.Read (My_Template, Element_In); + SU.Append (Template_Input, Element_In); + end loop; + Char_IO.Close (My_Template); + + + TIO.Open (My_Rule_List, TIO.In_File, ACom.Argument (2)); + while not TIO.End_Of_File (My_Rule_List) loop + SU.Set_Unbounded_String (Sub_Line, TIO.Get_Line (My_Rule_List)); + Cut_At := SU.Index (Sub_Line, SMap.To_Set ('=')); + if Cut_At = 0 and SU.Length (Sub_Line) > 0 then + TIO.Put_Line + (TIO.Standard_Error, + "WARNING: Malformed rule """ & SU.To_String (Sub_Line) & """ with no production"); + end if; + if Cut_At = 0 and not Rule_Map.Is_Empty then + Copy_Input := Template_Input; + Process (Copy_Input, Rule_Map); + TIO.Put (SU.To_String (Copy_Input)); + Rule_Map.Clear; + elsif Cut_At = 1 then + TIO.Put_Line + (TIO.Standard_Error, + "WARNING: Malformed rule """ & SU.To_String (Sub_Line) & """ with null pattern"); + elsif Cut_At > 1 then + Rule_Map.Include + (SU.Slice (Sub_Line, 1, Cut_At - 1), + SU.Slice (Sub_Line, Cut_At + 1, SU.Length (Sub_Line))); + end if; + end loop; + if not Rule_Map.Is_Empty then + Process (Template_Input, Rule_Map); + TIO.Put (SU.To_String (Template_Input)); + end if; + TIO.Close (My_Rule_List); + + +end Template; + + |