with Calendar;   --| Predefined library package for dates and times
with Read_Log, Text_Io;
with Varhand, Average;
with Type_Definitions, Implementation_Dependencies, Simple_Paginated_Output;
with String_Pkg, Report_Library;
with Dynarray_Pkg;
use Type_Definitions;

----------------------
package body Smart_Pkg is
    ----------------------

    procedure Smart (  --| Self Metric Analysis and Reporting Tool

                     Log_File_Name : in
                     Filename;       --| The name of the log file

                     Report_File_Name : in
                        Filename   --| The name of Output report file

                     ) is


        --| Overview
        --| Smart produces a report from the logfile created by the runtime monitor.

        --| The report has 4 parts;
        --|    1) Test Configuration Report: lists the name of program being analyzed,
        --|       the name of log file and the date and time of both log file and
        --|       report are generated.
        --|    2) Variable Trace Report: records the trace of change of values of all
        --|       user specified variables.
        --|    3) Loop Summary Report: prints the number of times loop executes, name
        --|       of the compilation unit and the unit number.
        --|    4) Variable Statistic Report: outputs the minimum, maximum and average
        --|       values of each user specified numerical variable.

        --| Requires
        --| Each Ada program unit about which information is to be recorded
        --| by the Runtime Monitor (RTM), and
        --| to be reported by SMART must have been instrumented by the Ada
        --| Source Instrumenter prior to compilation, linking, and execution.
        --| An Ada program unit is a procedure, function, task, or generic.

        --| N/A:  Errors, Raises, Modifies

        --  Version         : 0.00

        --  Last Modified   : 07/02/85
        --  Author          : Alexis P. Wei
        --  Initial Release : 03/15/85


        use Type_Definitions;         --| Global type declarations for ATETS tools
        use Report_Library;           --| Ada Testing and Analysis Tools
        use Simple_Paginated_Output;  --| Output writer uses Text_IO
        use String_Pkg;               --| String handling package for String_Type's
        use Implementation_Dependencies;
        use Text_Io;
        use Average;
        use Varhand;
        use Read_Log; --| Performs all input from the Execution Log File
        --| for all Ada Testing and Analysis Tools
        use Ivdarray_Pkg, Livdarray_Pkg, Fvdarray_Pkg;  -- Lfvdarray_Pkg;
        use Calendar; --| Predefined library package for dates and times
        use Varhand.Ivdarray_Pkg, Varhand.Livdarray_Pkg;
        use Varhand.Fvdarray_Pkg;   -- Varhand.Lfvdarray_Pkg;

        package Lopdarray_Pkg is new Dynarray_Pkg (Loop_Record);
        use Lopdarray_Pkg;

        Tool_Version : constant String (1 .. 20) := "Smart 1.0           ";

        Format_Options : Options  --| Formatting options for reports
            := (132,               --|   Characters Per Line
               60,                --|   Lines Per Page
               Smart_Tool,        --|   The tool name
               Tool_Version);  --|   The tool version number

        Report_File : Paginated_File_Handle;
        --| A "handle" for the output report file

        Program_Name : Ada_Name;        --| The name of the program under test
        Test_Date : Time;            --| The time of the test
        Test_Ident : Test_Identifier;

        Variable_Trace_Title : constant String := "VARIABLE TRACE REPORT";
        Loop_Summary_Title : constant String := "LOOP SUMMARY REPORT";
        Variable_Statistic : constant String := "VARIABLE STATISTIC REPORT";
        --
        Initial_Variable_Range : constant Integer := 20;
        Increment_Factor : constant Integer := 20;
        Iarray : Ivdarray_Pkg.Darray;
        Liarray : Livdarray_Pkg.Darray;
        Farray : Fvdarray_Pkg.Darray;
        --        Lfarray                : Lfvdarray_Pkg.Darray;
        Loparray : Lopdarray_Pkg.Darray;
        Found, Loop_Found : Boolean := False;
        Key : Logfile_Keys;
        Idx : Natural;
        Pid, Loop_Pid : Program_Unit_Unique_Identifier;
        Strvalue : String_Variables;
        Loop_Brkpt, Brkpt : Breakpoint_Number_Range := 0;
        Unitname, Vname : Ada_Name;
        Loop_In_Unitname : Ada_Name;
        Ivalue, Iaverage : Integer;
        Livalue, Liaverage : Long_Integer;
        Fvalue, Faverage : Float;
        --        Lfvalue, Lfaverage     : Long_Float;
        --FPVALUE,FPAVERAGE       : FIXED_POINT;

        Loop_Count, Iv_Count : Natural := 0;
        Liv_Count, Fv_Count : Natural := 0;
        --        Lfv_Count, Fp_Count    : Natural := 0;

        Integer_Array : Ivrecord;
        Long_Integer_Array : Livrecord;
        Float_Array : Fvrecord;
        --        Long_Float_Array       : Lfvrecord;
        --FIXED_POINT_ARRAY       : FPRECORD;
        Loop_Array : Loop_Record;

        Blank_String, Outline : String_Type;

        Blanks : constant String (1 .. 50) := (1 .. 50 => ' ');
        Blank_Line : constant String (1 .. 132) := (1 .. 132 => ' ');


        procedure New_Variable_Trace_Line is

            --| Effects
            --| Starts a new report line for the variable trace report

        begin

            Outline := Blank_String;

            if Length (Pid.Enclosing_Unit_Identifier) > 20 then
                Outline :=
                   Replace (Outline,
                            Substr (Pid.Enclosing_Unit_Identifier, 1, 20), 1);
            else
                Outline := Replace (Outline, Pid.Enclosing_Unit_Identifier, 1);
            end if;

            Outline := Replace (Outline, String_Of (Brkpt, 5), 23);

            --| If the length of the variable name is greater that the width
            --| of the variable name field then output it a piece at a time.
            while Length (Vname) > 50 loop
                Outline := Replace (Outline, Substr (Vname, 1, 50), 30);
                Put_Line (Report_File, Outline);
                Outline := Blank_String;
                --| An "*" in the breakpoint field indicates a continuation
                Outline := Replace (Outline, "*", 27);
                --| Indent the next line two spaces
                Vname := "  " & Substr (Vname, 51, Length (Vname) - 50);
            end loop;

            Outline := Replace (Outline, Vname, 30);

        end New_Variable_Trace_Line;


        procedure Print_Variable_Trace_Report (Ivalue : in Integer) is

            --| overview:
            --| For every user specified variable whenever the value changes for a
            --| particular variable this procedure will be called to output a line
            --| consisting of the compilation unit name, the procedure unit no, the
            --| procedure unit name, the breakpoint no., the value of the variable
            --| and the variable name.

            --| effects:
            --| a line with the above data will be printed to the variable_trace_
            --| report by calling paginated_output package to enable the appropriate
            --| title, page count and other options to be printed.

        begin
            String_Pkg.Mark;
            New_Variable_Trace_Line;
            Outline := Replace (Outline, String_Of (Ivalue), 82);
            Put_Line (Report_File, Outline);
            String_Pkg.Release;
        end Print_Variable_Trace_Report;


        procedure Print_Variable_Trace_Report (Ivalue : in Long_Integer) is

            --| overview:
            --| For every user specified variable whenever the value changes for a
            --| particular variable this procedure will be called to output a line
            --| consisting of the compilation unit name, the procedure unit no, the
            --| procedure unit name, the breakpoint no., the value of the variable
            --| and the variable name.

            --| effects:
            --| a line with the above data will be printed to the variable_trace_
            --| report by calling paginated_output package to enable the appropriate
            --| title, page count and other options to be printed.

        begin
            String_Pkg.Mark;
            New_Variable_Trace_Line;
            Outline := Replace (Outline, Long_Integer_To_Str (Ivalue), 82);
            Put_Line (Report_File, Outline);
            String_Pkg.Release;
        end Print_Variable_Trace_Report;



        procedure Print_Variable_Trace_Report (Fvalue : in Float) is

            --| overview:
            --| For every user specified variable whenever the value changes for a
            --| particular variable this procedure will be called to output a line
            --| consisting of the compilation unit name, the procedure unit no, the
            --| procedure unit name, the breakpoint no., the value of the variable
            --| and the variable name.

            --| effects:
            --| a line with the above data will be printed to the variable_trace_
            --| report by calling paginated_output package to enable the appropriate
            --| title, page count and other options to be printed.

        begin
            String_Pkg.Mark;
            New_Variable_Trace_Line;
            Outline := Replace (Outline, Float_To_Str (Fvalue), 82);
            Put_Line (Report_File, Outline);
            String_Pkg.Release;
        end Print_Variable_Trace_Report;


        --        procedure Print_Variable_Trace_Report (Lfvalue : in Long_Float) is

        --| overview:
        --| For every user specified variable whenever the value changes for a
        --| particular variable this procedure will be called to output a line
        --| consisting of the compilation unit name, the procedure unit no, the
        --| procedure unit name, the breakpoint no., the value of the variable
        --| and the variable name.

        --| effects:
        --| a line with the above data will be printed to the variable_trace_
        --| report by calling paginated_output package to enable the appropriate
        --| title, page count and other options to be printed.

        --        begin
        --            String_Pkg.Mark;
        --            New_Variable_Trace_Line;
        --            Outline := Replace (Outline, Long_Float_To_Str (Lfvalue), 82);
        --            Put_Line (Report_File, Outline);
        --            String_Pkg.Release;
        --        end Print_Variable_Trace_Report;


        procedure Print_Variable_Trace_Report
                     (Strvalue : in out String_Variables) is

            --| overview:
            --| For every user specified variable whenever the value changes for a
            --| particular variable this procedure will be called to output a line
            --| consisting of the compilation unit name, the procedure unit no, the
            --| procedure unit name, the breakpoint no., the value of the variable
            --| and the variable name.

            --| effects:
            --| a line with the above data will be printed to the variable_trace_
            --| report by calling paginated_output package to enable the appropriate
            --| title, page count and other options to be printed.

        begin
            String_Pkg.Mark;
            New_Variable_Trace_Line;
            --| If the length of the string variable is greater that the width
            --| of the string variable field then output it a piece at a time.
            while Length (Strvalue) > 50 loop
                Outline := Replace (Outline, Substr (Strvalue, 1, 50), 82);
                Put_Line (Report_File, Outline);
                Outline := Blank_String;
                --| An "*" in the breakpoint field indicates a continuation
                Outline := Replace (Outline, "*", 27);
                --| Indent the next line two spaces
                Strvalue := "  " & Substr
                                      (Strvalue, 51, Length (Strvalue) - 50);
            end loop;
            Outline := Replace (Outline, Strvalue, 82);
            Put_Line (Report_File, Outline);
            String_Pkg.Release;
        end Print_Variable_Trace_Report;


        procedure Print_Variable_Statistic_Report is

            --| Overview
            --| For each user specified numerical variable it calculates the minimum,
            --| maximum and average values and formats them into a report.

            --| effects
            --| Variable_Statistic_Report parses the log file extracts the variable
            --| values and calculates the maximum, minimum and average values for
            --| every user specified numerical variable.

            procedure New_Variable_Statistic_Line
                         (
                          --| Start a new Variable Statistic Report Line

                          Pid : in Program_Unit_Unique_Identifier;

                          Vname : in out Ada_Name;

                          Outline : in out String_Type

                          ) is

                --| Effects
                --| Starts a new Variable Statistic Report Line. Inserts the Program
                --| Unit Number and the variable name into the line buffer. If the
                --| length of the variable name is greater than the width of the
                --| variable name field then it is inserted a section at a time and
                --| the line is printed.

            begin

                Outline := Blank_String;
                Outline := Replace (Outline,
                                    String_Of (Pid.Program_Unit_Number, 5), 1);

                --| If the length of the variable name is greater that the width
                --| of the variable name field then output it a piece at a time.
                while Length (Vname) > 57 loop
                    Outline := Replace (Outline, Substr (Vname, 1, 57), 8);
                    Put_Line (Report_File, Outline);
                    Outline := Blank_String;
                    --| Indent the next line two spaces
                    Vname := "  " & Substr (Vname, 58, Length (Vname) - 57);
                end loop;

                Outline := Replace (Outline, Vname, 8);

            end New_Variable_Statistic_Line;

        begin

            String_Pkg.Mark;

            --  Print the Variable Statistic report title
            Put_Page (Report_File);
            Set_Header (Report_File, 4,
                        Center (Variable_Statistic, Format_Options.Cpl));
            Set_Header (Report_File, 6,
                        "UNIT#                  VARIABLE NAME        " &
                           "                             MAX VALUE      " &
                           "      MIN VALUE            AVERAGE VALUE");
            Set_Header (Report_File, 7,
                        "-----  -------------------------------------" &
                           "---------------------  -------------------- " &
                           " --------------------  ---------------------");
            for I in 1 .. Iv_Count loop
                Integer_Array := Fetch (Iarray, I);
                New_Variable_Statistic_Line
                   (Integer_Array.Programid,
                    Integer_Array.Variablename, Outline);
                Outline := Replace (Outline,
                                    String_Of (Integer_Array.Max_V, 20), 68);
                Outline := Replace (Outline,
                                    String_Of (Integer_Array.Min_V, 20), 90);
                Outline :=
                   Replace (Outline,
                            String_Of (Integer_Array.Average_V, 20), 112);
                Put_Line (Report_File, Outline);
            end loop;

            for I in 1 .. Liv_Count loop
                Long_Integer_Array := Fetch (Liarray, I);
                New_Variable_Statistic_Line
                   (Long_Integer_Array.Programid,
                    Long_Integer_Array.Variablename, Outline);
                Outline :=
                   Replace
                      (Outline,
                       Long_Integer_To_Str (Long_Integer_Array.Max_Liv, 20),
                       68);
                Outline :=
                   Replace
                      (Outline,
                       Long_Integer_To_Str (Long_Integer_Array.Min_Liv, 20),
                       90);
                Outline :=
                   Replace
                      (Outline,
                       Long_Integer_To_Str (Long_Integer_Array.Average_Liv, 20),
                       112);
                Put_Line (Report_File, Outline);
            end loop;

            for I in 1 .. Fv_Count loop
                Float_Array := Fetch (Farray, I);
                New_Variable_Statistic_Line (Float_Array.Programid,
                                             Float_Array.Variablename, Outline);
                Outline := Replace (Outline,
                                    Float_To_Str (Float_Array.Max_Fv, 20), 68);
                Outline := Replace (Outline,
                                    Float_To_Str (Float_Array.Min_Fv, 20), 90);
                Outline := Replace
                              (Outline, Float_To_Str
                                           (Float_Array.Average_Fv, 20), 112);
                Put_Line (Report_File, Outline);
            end loop;

            --            for I in 1..Lfv_Count loop
            --                Long_Float_Array := Fetch (Lfarray, I);
            --                New_Variable_Statistic_Line (Long_Float_Array.Programid,
            --                                             Long_Float_Array.Variablename,
            --                                             Outline);
            --                Outline := Replace (Outline,
            --                                    Long_Float_To_Str
            --                                     (Long_Float_Array.Max_Lfv, 20), 68);
            --                Outline := Replace (Outline,
            --                                    Long_Float_To_Str
            --                                     (Long_Float_Array.Min_Lfv, 20), 90);
            --                Outline := Replace (Outline,
            --                                    Long_Float_To_Str
            --                                     (Long_Float_Array.Average_Lfv, 20),
            --                                    112);
            --                Put_Line (Report_File, Outline);

            --            end loop;

            String_Pkg.Release;
        end Print_Variable_Statistic_Report;


        -----------------------------------------------------------------------
        --|                                                                     |--
        --|                        BODY OF PROGRAM                              |--
        --|---------------------------------------------------------------------|




    begin
        Blank_String := Make_Persistent (Blank_Line);

        --| Identify the tool name and version number
        Text_Io.New_Line;
        Text_Io.Put_Line (Tool_Version &
                          "Self Metric Analysis and Reporting Tool");

        --| Open the log file and get the test configuration data
        Open_Log (Log_File_Name, Program_Name, Test_Ident, Test_Date);

        --| Display the logfile test configuration data at the user's
        --| console and ask him whether or not he wishes to continue.
        Put_Test_Configuration_Data (Program_Name, Test_Date, Test_Ident);

        if Query ("Do you wish to continue (Y/N)? ") then

            --| Open the report file and set up the report formatting options
            Open_Report_File (Report_File, Report_File_Name, Format_Options);

            --| Print the Test Configuration Report
            Print_Test_Configuration_Report
               (Report_File, Program_Name,
                Log_File_Name, Test_Date, Test_Ident);

            --| Start the Variable Trace Report on a new page
            Put_Page (Report_File);

            --| Print the Variable Trace Report title
            Set_Header (Report_File, 4,
                        Center (Variable_Trace_Title, Format_Options.Cpl));
            Set_Header (Report_File, 6,
                        "   COMP UNIT NAME     BKPT#                 " &
                           "   VARIABLE NAME                            " &
                           "               VALUE");
            Set_Header (Report_File, 7,
                        "--------------------  -----  ---------------" &
                           "-----------------------------------  -------" &
                           "--------------------------------------------");

            -- initialize dynamic arrays to hold variables

            Create (1, Initial_Variable_Range, 100, Increment_Factor, Iarray);
            Create (1, Initial_Variable_Range, 100, Increment_Factor, Liarray);
            Create (1, Initial_Variable_Range, 100, Increment_Factor, Farray);
            --            Create (1, Initial_Variable_Range, 100, Increment_Factor, Lfarray);
            Create (1, Initial_Variable_Range, 100, Increment_Factor, Loparray);


            String_Pkg.Mark;

            --| Read and process each record in the log file
            while not End_Of_Log loop
                Get_Next_Key (Key);

                case Key is

                    when Integer_Variable =>

                        Get_Value (Pid, Vname, Ivalue);
                        if Iv_Count = 0 then
                            Iv_Count := Iv_Count + 1;
                            Find_Unit_Name (Pid, Unitname);
                            -- assign average, max, min values
                            Initarray (Integer_Array, Iarray, Pid, Vname,
                                       Unitname, Ivalue, Iv_Count);
                            --------------------------------------------------
                            --  output to variable trace report
                            Print_Variable_Trace_Report (Ivalue);
                            --------------------------------------------------
                        else
                            Find_Variable (Pid, Iarray, Integer_Array,
                                           Vname, Iv_Count, Idx, Found);
                            if Found then
                                Averager (Iaverage, Integer_Array.Variablecount,
                                          Ivalue, Integer_Array.Average_V);
                                Integer_Array.Average_V := Iaverage;
                                if Integer_Array.Current_V /= Ivalue then
                                    Integer_Array.Current_V := Ivalue;

                                    ----------------------------------
                                    -- output to variable trace report
                                    Print_Variable_Trace_Report (Ivalue);
                                    ----------------------------------
                                    Find_Maxmin (Integer_Array,
                                                 Iarray, Idx, Ivalue);
                                end if;
                            else
                                Iv_Count := Iv_Count + 1;
                                Find_Unit_Name (Pid, Unitname);
                                Initarray (Integer_Array, Iarray, Pid, Vname,
                                           Unitname, Ivalue, Iv_Count);
                                --------------------------------------------------
                                --  output to variable trace report
                                Print_Variable_Trace_Report (Ivalue);
                                --------------------------------------------------
                            end if;
                        end if;

                    when Long_Integer_Variable =>
                        Get_Value (Pid, Vname, Livalue);
                        if Liv_Count = 0 then
                            Liv_Count := Liv_Count + 1;
                            Find_Unit_Name (Pid, Unitname);
                            -- assign average, max, min values
                            Initarray (Long_Integer_Array, Liarray, Pid,
                                       Vname, Unitname, Livalue, Liv_Count);
                            --------------------------------------------------
                            --  output to variable trace report
                            Print_Variable_Trace_Report (Livalue);
                            --------------------------------------------------
                        else
                            Find_Variable (Pid, Liarray, Long_Integer_Array,
                                           Vname, Liv_Count, Idx, Found);
                            if Found then
                                Averager
                                   (Liaverage, Long_Integer_Array.Variablecount,
                                    Livalue, Long_Integer_Array.Average_Liv);
                                Long_Integer_Array.Average_Liv := Liaverage;
                                if Long_Integer_Array.Current_Liv /=
                                   Livalue then
                                    Long_Integer_Array.Current_Liv := Livalue;

                                    ----------------------------------
                                    -- output to variable trace report
                                    Print_Variable_Trace_Report (Livalue);
                                    ----------------------------------
                                    Find_Maxmin (Long_Integer_Array,
                                                 Liarray, Idx, Livalue);
                                end if;

                            else
                                Liv_Count := Liv_Count + 1;
                                Find_Unit_Name (Pid, Unitname);
                                Initarray (Long_Integer_Array, Liarray, Pid,
                                           Vname, Unitname, Livalue, Liv_Count);
                                --------------------------------------------------
                                --  output to variable trace report
                                --------------------------------------------------
                            end if;
                        end if;

                    when Float_Variable =>

                        Get_Value (Pid, Vname, Fvalue);
                        if Fv_Count = 0 then
                            Fv_Count := Fv_Count + 1;
                            Find_Unit_Name (Pid, Unitname);
                            -- assign average, max, min values
                            Initarray (Float_Array, Farray, Pid, Vname,
                                       Unitname, Fvalue, Fv_Count);
                            --------------------------------------------------
                            --  output to variable trace report
                            Print_Variable_Trace_Report (Fvalue);
                            --------------------------------------------------
                        else
                            Find_Variable (Pid, Farray, Float_Array,
                                           Vname, Fv_Count, Idx, Found);
                            if Found then
                                Averager (Faverage, Float_Array.Variablecount,
                                          Fvalue, Float_Array.Average_Fv);
                                Float_Array.Average_Fv := Faverage;
                                if Float_Array.Current_Fv /= Fvalue then
                                    Float_Array.Current_Fv := Fvalue;

                                    ----------------------------------
                                    -- output to variable trace report
                                    Print_Variable_Trace_Report (Fvalue);
                                    ----------------------------------
                                    Find_Maxmin (Float_Array, Farray,
                                                 Idx, Fvalue);
                                end if;
                            else
                                Fv_Count := Fv_Count + 1;
                                Find_Unit_Name (Pid, Unitname);
                                Initarray (Float_Array, Farray, Pid, Vname,
                                           Unitname, Fvalue, Fv_Count);
                                --------------------------------------------------
                                --  output to variable trace report
                                Print_Variable_Trace_Report (Fvalue);
                                --------------------------------------------------
                            end if;
                        end if;

                        --                    when Long_Float_Variable =>
                        -- note that a "Flush_Logfile_Record (Key)" is done by the "others" choice -jwb
                        --                        Get_Value (Pid, Vname, Lfvalue);

                        --                        if Lfv_Count = 0 then
                        --                            Lfv_Count := Lfv_Count + 1;
                        --                            Find_Unit_Name (Pid, Unitname);
                        -- assign average, max, min values
                        --                            Initarray (Long_Float_Array, Lfarray, Pid, Vname,
                        --                                       Unitname, Lfvalue,
                        --                                       Lfv_Count);
                        --------------------------------------------------
                        --  output to variable trace report
                        --                            Print_Variable_Trace_Report (Lfvalue);
                        --------------------------------------------------
                        --                        else
                        --                            Find_Variable
                        --                                 (Pid, Lfarray, Long_Float_Array, Vname,
                        --                                  Lfv_Count, Idx,
                        --                                  Found);

                        --                            if Found then
                        --                                Averager (Lfaverage,
                        --                                          Long_Float_Array.Variablecount,
                        --                                          Lfvalue,
                        --                                          Long_Float_Array.Average_Lfv);
                        --                                Long_Float_Array.Average_Lfv := Lfaverage;

                        --                                if Long_Float_Array.Current_Lfv /= Lfvalue then
                        --                                    Long_Float_Array.Current_Lfv := Lfvalue;

                        ----------------------------------
                        -- output to variable trace report
                        --                                    Print_Variable_Trace_Report (Lfvalue);
                        ----------------------------------
                        --                                    Find_Maxmin (Long_Float_Array, Lfarray, Idx,
                        --                                                 Lfvalue);
                        --                                end if;
                        --                            else
                        --                                Lfv_Count := Lfv_Count + 1;
                        --                                Find_Unit_Name (Pid, Unitname);
                        --                                Initarray (Long_Float_Array, Lfarray, Pid,
                        --                                           Vname,
                        --                                           Unitname, Lfvalue, Lfv_Count);
                        --------------------------------------------------
                        --  output to variable trace report
                        --                                Print_Variable_Trace_Report (Lfvalue);
                        --------------------------------------------------
                        --                            end if;
                        --                        end if;



                    when Fixed_Point_Variable =>
                        Flush_Logfile_Record (Key);
                        --       get_value(pid, vname, fpvalue);
                        --       if  fp_count = 0 then
                        --         fp_count := fp_count + 1;
                        --         find_unit_name(pid, unitname);
                        --         -- assign average, max, min values
                        --         initarray(fixed_point_array, fparray, pid, vname,
                        --                   unitname, fpvalue, fp_count);
                        --         --------------------------------------------------
                        --         --  output to variable trace report
                        --         print_variable_trace_report(fpvalue);
                        --         --------------------------------------------------
                        --       else
                        --         find_variable(pid, fparray, fixed_point_array, vname,
                        --                       fp_count, idx, found);
                        --         if found then
                        --           averager(fpaverage, fixed_point_array.variablecount,fpvalue,
                        --                    fixed_point_array.average_fpv);
                        --           fixed_point_array.average_fpv :=fpaverage;
                        --           if fixed_point_array.current_fpv /= fpvalue then
                        --             fixed_point_array.current_fpv := fpvalue;

                        ----------------------------------
                        -- output to variable trace report
                        --             print_variable_trace_report(fpvalue);
                        ----------------------------------
                        --             find_maxmin(fixed_point_array, fparray, idx, fpvalue);
                        --           end if;
                        --         else
                        --           fp_count := fp_count + 1;
                        --           find_unit_name(pid, unitname);
                        --           initarray(fixed_point_array, fparray, pid, vname,
                        --                     unitname, fpvalue, fp_count);
                        --           --------------------------------------------------
                        --           --  output to variable trace report
                        --           --------------------------------------------------
                        --         end if;
                        --       end if;

                    when String_Variable =>
                        Get_Value (Pid, Vname, Strvalue);
                        if Value (Strvalue) /= Last_Value
                                                  (Pid, Vname, Strvalue) then
                            Find_Unit_Name (Pid, Unitname);
                            --------------------------------------------------
                            --  output to variable trace report
                            Print_Variable_Trace_Report (Strvalue);
                            --------------------------------------------------
                        end if;

                    when Other_Breakpoint =>
                        Get_Breakpoint (Pid, Brkpt);

                    when Loop_Breakpoint =>
                        Get_Breakpoint (Loop_Pid, Loop_Brkpt);
                        if Loop_Count = 0 then
                            Loop_Count := Loop_Count + 1;
                            Find_Unit_Name (Loop_Pid, Loop_In_Unitname);
                            Loop_Array.Programid := Loop_Pid;
                            Loop_Array.Brkpt_No := Loop_Brkpt;
                            Loop_Array.Brkptcount := 1;
                            Loop_Array.Unitname := Loop_In_Unitname;
                            Add_High (Loparray, Loop_Array);
                        else
                            Loop_Found := False;
                            Search_Loop:
                                for I in 1 .. Loop_Count loop
                                    -- check to see if this is an existing loop
                                    Loop_Array := Fetch (Loparray, I);
                                    if (Loop_Array.Brkpt_No = Loop_Brkpt) and
                                       (Loop_Array.Programid.
                                        Program_Unit_Number =
                                        Loop_Pid.Program_Unit_Number) and
                                       Equal (Loop_Array.Programid.
                                              Enclosing_Unit_Identifier,
                                              Loop_Pid.
                                                 Enclosing_Unit_Identifier) then
                                        Loop_Found := True;
                                        Loop_Array.Brkptcount :=
                                           Loop_Array.Brkptcount + 1;
                                        Store (Loparray, I, Loop_Array);
                                        exit Search_Loop when Loop_Found;
                                    end if;
                                end loop Search_Loop;

                            if not Loop_Found then
                                Loop_Count := Loop_Count + 1;
                                Find_Unit_Name (Loop_Pid, Loop_In_Unitname);
                                Loop_Array.Programid := Loop_Pid;
                                Loop_Array.Brkpt_No := Loop_Brkpt;
                                Loop_Array.Brkptcount := 1;
                                Loop_Array.Unitname := Loop_In_Unitname;
                                Add_High (Loparray, Loop_Array);
                            end if;
                        end if;

                    when others =>

                        Flush_Logfile_Record (Key);

                end case;

            end loop;

            String_Pkg.Release;


            --| If any loops were instrumented and executed then
            --| print the loop summary report
            if Loop_Count > 0 then

                Put_Page (Report_File);

                --|  Set up the loop summary report title and column headers
                Set_Header (Report_File, 4,
                            Center (Loop_Summary_Title, Format_Options.Cpl));
                Set_Header (Report_File, 6,
                            "LOOP COUNT  BKPT#  UNIT#                    " &
                               "                               UNIT NAME");
                Set_Header (Report_File, 7,
                            "----------  -----  -----  ------------------" &
                               "--------------------------------------------" &
                               "--------------------------------------------");

                --| Print out the loop array elements
                for I in 1 .. Loop_Count loop
                    String_Pkg.Mark;
                    Loop_Array := Fetch (Loparray, I);
                    Outline := Blank_String;
                    Outline := Replace
                                  (Outline, String_Of
                                               (Loop_Array.Brkptcount, 10), 1);
                    Outline := Replace (Outline,
                                        String_Of (Loop_Array.Brkpt_No, 5), 13);
                    Outline :=
                       Replace
                          (Outline,
                           String_Of
                              (Loop_Array.Programid.Program_Unit_Number, 5),
                           20);

                    --| If the length of the unit name is greater that the width
                    --| of the unit name field then output it a piece at a time.
                    while Length (Loop_Array.Unitname) > 105 loop
                        Outline :=
                           Replace (Outline,
                                    Substr (Loop_Array.Unitname, 1, 105), 27);
                        Put_Line (Report_File, Outline);
                        Outline := Blank_String;
                        --| An "*" in the breakpoint field indicates a continuation
                        Outline := Replace (Outline, "*", 17);
                        --| Indent the next line two spaces
                        Loop_Array.Unitname :=
                           "  " & Substr (Loop_Array.Unitname, 106,
                                          Length (Loop_Array.Unitname) - 105);
                    end loop;

                    Outline := Replace (Outline, Loop_Array.Unitname, 27);
                    Put_Line (Report_File, Outline);
                    String_Pkg.Release;
                end loop;

            end if;

            Print_Variable_Statistic_Report;

            --| Close the report file
            Close_Paginated_File (Report_File);

        end if;

        --| Close the log file
        Close_Log;

    end Smart;

end Smart_Pkg;