with Global_Def, Pack_2;
use Global_Def;
with Cpu_Time_Clock;
with Text_Io;
with Duration_Io;

package body Pack_1 is
-----------

    Bool_Glob : Boolean;
    Char_Glob_1, Char_Glob_2 : Character;
    Array_Glob_1 : Array_1_Dim_Integer;
    Array_Glob_2 : Array_2_Dim_Integer;
    Pointer_Glob, Pointer_Glob_Next : Record_Pointer;

    Start_Time : Duration;
    Stop_Time : Duration;
    Iteration_Count : constant := 10_000;

    procedure Proc_4;
    procedure Proc_5;

    procedure Proc_0 is
        Int_Loc_1, Int_Loc_2, Int_Loc_3 : One_To_Fifty;
        Char_Loc : Character;
        Enum_Loc : Enumeration;
        String_Loc_1, String_Loc_2 : String_30;

    begin
        -- initializations
        Pack_1.Pointer_Glob_Next := new Record_Type;

        Pack_1.Pointer_Glob :=
           new Record_Type'(Pointer_Comp => Pack_1.Pointer_Glob_Next,
                            Discr => Ident_1,
                            Enum_Comp => Ident_3,
                            Int_Comp => 40,
                            String_Comp => "DHRYSTONE PROGRAM, SOME STRING");

        String_Loc_1 := "DHRYSTONE PROGRAM, 1'ST STRING";

---------------
-- start timer here
---------------
        Start_Time := Cpu_Time_Clock;
        for I in 1 .. Iteration_Count loop

            Proc_5;
            Proc_4;
            -- char_glob_1 = 'A', char_glob_2 = 'B', bool_glob = false

            Int_Loc_1 := 2;
            Int_Loc_2 := 3;
            String_Loc_2 := "DHRYSTONE PROGRAM, 2'ND STRING";
            Enum_Loc := Ident_2;
            Bool_Glob := not Pack_2.Func_2 (String_Loc_1, String_Loc_2);
            -- bool_glob = true
            while Int_Loc_1 < Int_Loc_2 loop --loop body executed once
                Int_Loc_3 := 5 * Int_Loc_1 - Int_Loc_2;
                -- int_loc_3 = 7
                Pack_2.Proc_7 (Int_Loc_1, Int_Loc_2, Int_Loc_3);
                -- int_loc_3 = 7
                Int_Loc_1 := Int_Loc_1 + 1;
            end loop;
            -- int_loc_1 = 3
            Pack_2.Proc_8 (Array_Glob_1, Array_Glob_2, Int_Loc_1, Int_Loc_3);
            -- int_glob = 5
            Proc_1 (Pointer_Glob);
            for Char_Index in 'A' .. Char_Glob_2 loop --loop body executed twice
                if Enum_Loc = Pack_2.Func_1
                                 (Char_Index, 'C') then   -- not executed
                    Pack_2.Proc_6 (Ident_1, Enum_Loc);
                end if;
            end loop;
            -- enum_loc = ident_1
            -- int_loc = 3, int_loc_2 = 3, int_loc_3 = 7
            Int_Loc_3 := Int_Loc_2 * Int_Loc_1;
            Int_Loc_2 := Int_Loc_3 / Int_Loc_1;
            Int_Loc_2 := 7 * (Int_Loc_3 - Int_Loc_2) - Int_Loc_1;
            Proc_2 (Int_Loc_1);

        end loop;
        Stop_Time := Cpu_Time_Clock;
        Text_Io.New_Line;
        Text_Io.New_Line;
        Text_Io.Put_Line
           ("Test Name:   A000091            Class Name:  Composite");
        Text_Io.Put ("      ");
        Duration_Io.Put ((Stop_Time - Start_Time) * 1000 / Iteration_Count);
        Text_Io.Put_Line (" is time in milliseconds for one Dhrystone");
        Text_Io.Put_Line ("Test Description:");
        Text_Io.Put_Line
           (" Reinhold P. Weicker's DHRYSTONE composite benchmark");
        Text_Io.New_Line;
------------------
-- stop timer here
------------------

    end Proc_0;

    procedure Proc_1 (Pointer_Par_In : in Record_Pointer) is -- executed once

        Next_Record : Record_Type renames Pointer_Par_In.Pointer_Comp.
                                          all; -- pointer_glob_next.all
    begin
        Next_Record := Pointer_Glob.all;
        Pointer_Par_In.Int_Comp := 5;
        Next_Record.Int_Comp := Pointer_Par_In.Int_Comp;
        Next_Record.Pointer_Comp := Pointer_Par_In.Pointer_Comp;
        Proc_3 (Next_Record.Pointer_Comp);
        -- next_record.pointer_glob.pointer_comp = pointer_comp.next
        if Next_Record.Discr = Ident_1 then  -- executed
            Next_Record.Int_Comp := 6;
            Pack_2.Proc_6 (Pointer_Par_In.Enum_Comp, Next_Record.Enum_Comp);
            Next_Record.Pointer_Comp := Pointer_Glob.Pointer_Comp;
            Pack_2.Proc_7 (Next_Record.Int_Comp, 10, Next_Record.Int_Comp);
        else
            Pointer_Par_In.all := Next_Record;
        end if;
    end Proc_1;

    procedure Proc_2 (Int_Par_In_Out : in out
                         One_To_Fifty) is -- executed once
                                          -- in_par_in_out = 3 becomes 7
        Int_Loc : One_To_Fifty;
        Enum_Loc : Enumeration;
    begin
        Int_Loc := Int_Par_In_Out + 10;
        loop
            if Char_Glob_1 = 'A' then
                Int_Loc := Int_Loc - 1;
                Int_Par_In_Out := Int_Loc - Int_Glob;
                Enum_Loc := Ident_1;  -- true
            end if;
            exit when Enum_Loc = Ident_1; -- true
        end loop;
    end Proc_2;

    procedure Proc_3
                 (Pointer_Par_Out : out
                     Record_Pointer) is -- executed once
                                        -- pointer_par_out becomes pointer_glob
    begin
        if Pointer_Glob /= null then   -- executed
            Pointer_Par_Out := Pointer_Glob.Pointer_Comp;
        else
            Int_Glob := 100;
        end if;
        Pack_2.Proc_7 (10, Int_Glob, Pointer_Glob.Int_Comp);
    end Proc_3;

    procedure Proc_4 is
        Bool_Loc : Boolean;
    begin
        Bool_Loc := Char_Glob_1 = 'A';
        Bool_Loc := Bool_Loc or Bool_Glob;
        Char_Glob_2 := 'B';
    end Proc_4;

    procedure Proc_5 is
    begin
        Char_Glob_1 := 'A';
        Bool_Glob := False;
    end Proc_5;

end Pack_1;