-----
-- Macro Pre-Processor package
--
-- Handles all of our Macro Pre-Processor functionality.
--
-- @access Public
-----
Package Body Macro is
-- Holds the pointer to the head of the Macro Table.
Head : Pointer_Macro_Table := Null;
-- Holds current number value for the next system label.
System_Label_Number : Integer := 0;
-----
-- Is Macro
--
-- Returns true if the macro name is a defined macro table.
--
-- @access Public
-----
Function Is_Macro (Macro_Name : String) Return Boolean is
Scan : Pointer_Macro_Table := Head;
Begin
Loop
If Scan.Name = Macro_Name Then
Return True;
End If;
Exit When Scan.Next = null;
Scan := Scan.Next;
End Loop;
Return False;
End Is_Macro;
-----
-- Get Macro Table
--
-- This will search the macro table list and pull the macro table out for our macro name.
--
-- @access Private
-----
Function Get_Macro_Table (Macro_Name : String) Return Macro_Table is
Scan : Pointer_Macro_Table := Head;
Result : Macro_Table;
Begin
Result.Name := nus;
Result.Formal := nus;
Result.Lines(0) := nus;
Result.Next := null;
Loop
If Scan.Name = Macro_Name Then
Result.Name := Scan.Name;
Result.Formal := Scan.Formal;
Result.Lines := Scan.Lines;
Result.Next := null;
End If;
Exit When Scan.Next = null;
Scan := Scan.Next;
End Loop;
Return Result;
End Get_Macro_Table;
-----
-- Get Next Parameter
--
-- This is used to parse out the next parameter in the parameter list.
--
-- @access Private
-----
Function Get_Next_Parameter (Parameter_List : String) Return String is
Head, Index : Integer := Parameter_List'First;
Tail : Integer := Parameter_List'Last;
Begin
Loop
Exit When Parameter_List(Index) = ',' or Index = Tail;
Index := Index + 1;
End Loop;
Return Parameter_List(Head..Index);
End Get_Next_Parameter;
Pragma Inline (Get_Next_Parameter);
-----
-- Tokenize Macro
--
-- This procedure will take the given macro name and tokenize it for future parameter replacement.
--
-- @access Private
-----
Function Tokenize (Line : String; Parameter_List : String) Return String is
Function Get_Next_Word (Line : String; Index : Integer) Return String is
Current : Integer := Index;
Result : Ada.Strings.Unbounded.Unbounded_String := Ada.Strings.Unbounded.Null_Unbounded_String;
Begin
Skip_White_Space(Line, Current);
While Line(Current) /= ' ' or Line(Current) /= Character'Val(9) Loop
Ada.Strings.Unbounded.Append(Result, Line(Current));
End Loop;
Return Ada.Strings.Unbounded.To_String(Result);
End Get_Next_Word;
Prev, Index : Integer := Line'First;
Tail : Integer := Line'Last;
Quit : Boolean := False;
Result : Ada.Strings.Unbounded.Unbounded_String := Ada.Strings.Unbounded.Null_Unbounded_String;
Begin
While Index /= Tail Loop
Declare
Word : String := Get_Next_Word(Line(Index..Tail), Index);
Current : Integer := Parameter_List'First;
Begin
While Not Quit Loop
Declare
Parameter : String := Get_Next_Parameter(Parameter_List(Current..Parameter_List'Last));
Begin
If Parameter /= "" Then
If Parameter(Parameter'First) = '%' And Then Word = Parameter(Parameter'First + 1 .. Parameter'Last) Then
Declare
System_Number : String := Integer'Image(System_Label_Number);
Begin
Ada.Strings.Unbounded.Append(Result, "SystemLabel" & System_Number(System_Number'First + 1 .. System_Number'Last) & ":");
End;
System_Label_Number := System_Label_Number + 1;
Elsif Word(Word'First .. Word'Last - 1) = Parameter Then
Ada.Strings.Unbounded.Append(Result, Token & Word);
Else
Ada.Strings.Unbounded.Append(Result, Word);
End If;
Else
Quit := True;
End If;
Current := Current + Parameter'Length + 1;
End;
End Loop;
End;
For Space in Prev .. Index Loop
Ada.Strings.Unbounded.Append(Result, " ");
End Loop;
Prev := Index;
End Loop;
Return Ada.Strings.Unbounded.To_String(Result);
End Tokenize;
-----
-- Append
--
-- Append a new macro to the macro table.
--
-- @access Private
-----
Procedure Append (Macro_Start : Integer; Macro_End : Integer; File_Handle : Ada.Text_IO.File_Type) is
Type Line_Array is Array (Macro_Start .. Macro_End) of Line;
Line_Data : Line_Array;
Index : Integer := Macro_Start + 1;
Temp_Table : Macro_Table;
Line_Number : Integer := 1;
Begin
-- Skip to the beginning of the line we are wanting.
Ada.Text_IO.Flush(File_Handle);
For LN in 1 .. (Macro_Start - 1) Loop
Ada.Text_IO.Skip_Line(File_Handle);
End Loop;
Line_Data(Macro_Start) := Parse(Ada.Text_IO.Get_Line(File_Handle));
For Line_Number in (Macro_Start + 1) .. (Macro_End + 1) Loop
Line_Data(Index) := Parse(Ada.Text_IO.Get_Line(File_Handle));
Temp_Table.Lines(Line_Number) := Ada.Strings.Unbounded.To_Unbounded_String(Tokenize(
Ada.Strings.Unbounded.To_String(Line_Data(Line_Number).Label) & " " &
Ada.Strings.Unbounded.To_String(Line_Data(Line_Number).Opcode) & " " &
Ada.Strings.Unbounded.To_String(Line_Data(Line_Number).Operand),
Ada.Strings.Unbounded.To_String(Line_Data(Line_Number).Operand)));
-- Debug Line
Ada.Text_IO.Put_Line(Ada.Strings.Unbounded.To_String(Temp_Table.Lines(Line_Number)));
End Loop;
Temp_Table.Formal := Line_Data(Macro_Start).Operand;
Temp_Table.Name := Line_Data(Macro_Start).Label;
-- Create new table and append to the macro table.
End Append;
-----
-- Macro Expander
--
-- Expand our Macros
--
-- @access Public
-----
Procedure Expand (Macro_Name : String; Actual : String; File_Handle : Ada.Text_IO.File_Type) is
Index : Integer := Macro_Name'First;
Tail : Integer := Macro_Name'Last;
Begin
Loop
Exit When Index >= Tail;
Declare
Temp : String := Get_Next_Parameter(Macro_Name(Index..Tail));
Begin
Index := Index + Temp'Length;
If Index < Tail Then
Ada.Text_IO.Put_Line(Temp(Temp'First..(Temp'Last - 1)));
Else
Ada.Text_IO.Put_Line(Temp);
End If;
End;
End Loop;
End Expand;
End Macro;