summaryrefslogtreecommitdiff
path: root/tool/template.adb
diff options
context:
space:
mode:
Diffstat (limited to 'tool/template.adb')
-rw-r--r--tool/template.adb156
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;
+
+