(*$l-,d-,v-*)

{  this program needs a timer function

for linux,
use a program header file parameter and call this program with
/proc/uptime as program parameter:
          ./dhry /proc/uptime

Other systems will need suitable modifications

user configuration: search for "autoRun" }

{ [saf] This program was obtained from
  http://www.netlib.org/benchmark/dhry-pascal. It only has the credits listed. }
(*
 ****************************************************************************
 *
 *                   "DHRYSTONE" Benchmark Program
 *                   -----------------------------
 *
 *  Version:    Pascal, Version 2.1
 *
 *  File:       dhry.p
 *
 *  Date:       May 25, 1988
 *
 *  Author:     Reinhold P. Weicker
 *                      Siemens AG, AUT E 51
 *                      Postfach 3220
 *                      8520 Erlangen
 *                      Germany (West)
 *                              Phone:  [+49]-9131-7-20330
 *                                      (8-17 Central European Time)
 *                              Usenet: ..!mcsun!unido!estevax!weicker
 *
 *              Original Version (in Ada) published in
 *              "Communications of the ACM" vol. 27., no. 10 (Oct. 1984),
 *              pp. 1013 - 1030, together with the statistics
 *              on which the distribution of statements etc. is based,
 *
 *              This version uses calls to the Pascal runtime library of the
 *              Berkeley UNIX system (4.3 bsd) for time measurement.
 *              For measurements on other systems, these calls need to be
 *              modified.
 *
 *  Collection of Results:
 *              Reinhold Weicker (address see above) and
 *
 *              Rick Richardson
 *              PC Research. Inc.
 *              94 Apple Orchard Drive
 *              Tinton Falls, NJ 07724
 *                      Phone:  (201) 389-8963 (9-17 EST)
 *                      Usenet: ...!uunet!pcrat!rick
 *
 *      Please send results to Rick Richardson and/or Reinhold Weicker.
 *      Complete information should be given on hardware and software used.
 *      Hardware information includes: Machine type, CPU, type and size
 *      of caches; for microprocessors: clock frequency, memory speed
 *      (number of wait states).
 *      Software information includes: Compiler (and runtime library)
 *      manufacturer and version, compilation switches, OS version.
 *      The Operating System version may give an indication about the
 *      compiler; Dhrystone itself performs no OS calls in the measurement loop.
 *
 *      The complete output generated by the program should be mailed
 *      such that at least some checks for correctness can be made.
 *
 ****************************************************************************
 *
 *  History:    This version Pascal/2.1 has been made for two reasons:
 *
 *              1) There is a need for a common Pascal version of
 *              Dhrystone. Although translation from the published (Ada)
 *              version to Pascal is straightforward in most aspects,
 *              there are cases where it may not be obvious to everyone.
 *              There should be, as far as possible, only one Pascal version
 *              of Dhrystone such that results can be compared without
 *              restrictions. Also, a Pascal version of Dhrystone has not yet
 *              found a network distribution comparable to the C version
 *              (version 1.1) distributed by Rick Richardson.
 *
 *              2) As far as it is possible without changes to the Dhrystone
 *              statistics, optimizing compilers should be prevented from
 *              removing significant statements.
 *
 *              This Pascal version 2.1 has been made consistent with the
 *              C version 2.1; therefore the acknowledgments for the C version
 *              are due for the Pascal version as well: I thank
 *              Rick Richardson (Tinton Falls, NJ), Chaim Benedelac (Nat.
 *              Semi.), David Ditzel (SUN), Earl Killian and John Mashey (MIPS),
 *              Alan Smith and Rafael Saavedra-Barrera (UC at Berkeley)
 *              for their help with comments on earlier versions of the
 *              benchmark.
 *
 *  Changes:    In the initialization part, this version differs
 *              from the Pascal version previously distributed by Reinhold
 *              Weicker, the number of runs through Dhrystone is obtained
 *              interactively from the terminal. Output of the result
 *              has been changed to conform to the C version (2.1).
 *              The changes in the initialization part and in the printing
 *              of the result have no impact on performance measurement
 *              since they are outside the measaurement loop.
 *
 *              Inside the measurement loop, this version follows the
 *              version previously distributed by Reinhold Weicker.
 *              As a correction to the published version, a statement
 *              initializing Array2Glob [8,7] (outside the measurement
 *              loop) has been added. Otherwise, this array element would
 *              have an undefined value.
 *
 *              At several places in the benchmark, code has been added,
 *              but within the measurement loop only in branches that
 *              are not executed. The intention is that optimizing compilers
 *              should be prevented from moving code out of the measurement
 *              loop, or from removing code altogether. Since the statements
 *              that are executed within the measurement loop have NOT been
 *              changed, all numbers defining the "Dhrystone distribution"
 *              (distribution of statements, operand types and locality)
 *              still hold. Except for sophisticated optimizing compilers,
 *              execution times for this version should be the same as
 *              for previous versions.
 *
 *              Since it has proven difficult to subtract the time for the
 *              measurement loop overhead in a correct way, the loop check
 *              has been made a part of the benchmark. This does have
 *              an impact - though a very minor one - on the distribution
 *              statistics which have been updated for this version.
 *
 *              All changes within the measurement loop are described
 *              and discussed in the companion paper "Rationale for
 *              Dhrystone version 2".
 *
 *              Because of the self-imposed limitation that the order and
 *              distribution of the executed statements should not be
 *              changed, there are still cases where optimizing compilers
 *              may not generate code for some statements. To a certain
 *              degree, this is unavoidable for small synthetic benchmarks.
 *              Users of the benchmark are advised to check code listings
 *              whether code is generated for all statements of Dhrystone.
 *
 *              Version 2.1 is identical to version 2.0 distributed via
 *              the UNIX network Usenet in March 1988 except that it corrects
 *              some minor deficiencies that were found by users of version 2.0.
 *              The only change within the measurement loop is that a
 *              non-executed "else" part was added to the "if" statement in
 *              Func3, and a non-executed "else" part removed from Proc3.
 *
 ***************************************************************************
 *
 *  Compilation model and measurement (IMPORTANT):
 *
 *  This program contains the Dhrystone program, including measurement setup,
 *  in one file. The original (Ada) program contained three packages,
 *  - a package with global type definitions,
 *  - Pack_1, containing the main program (Proc_0 in Ada) and procedures
 *            Proc_1, ... , Proc_5,
 *  - Pack_2, containing Proc_6, ... , Proc_8, Func_1, ..., Func_3.
 *  Since ISO/ANSI Standard Pascal provides no means to express separate
 *  compilation (although many Pascal implementations provide such a feature),
 *  it is not possible to formulate a portable Pascal version with the program
 *  in several modules, corresponding more closely to the Ada and C versions.
 *  Therefore, no attempt has been made to construct a Pascal version with
 *  the program consisting of several modules.
 *
 *  This difference may impact execution time because the compiler can
 *  perform more data flow analysis for a single-module program;
 *  sophisticated compilers may be able to suppress code generation for
 *  some parts of the program.
 *  Users should check machine code listings generated by the compiler
 *  to ensure that code is generated for all parts of the program.
 *
 *  The following "ground rules" apply for measurements:
 *  - No procedure merging
 *  - Otherwise, compiler optimizations are allowed but should be indicated
 *  See the companion paper "Rationale for Dhrystone Version 2" for a more
 *  detailed discussion of these ground rules.
 *
 *  For 16-Bit processors (e.g. 80x86), times for all compilation models
 *  ("small", "medium", "large") should be given if possible, together
 *  with a definition of these models for the compiler system used.
 *
 **************************************************************************
 *
 *  Dhrystone (Pascal version) statistics:
 *
 *  [Comment from the first distribution by Reinhold Weicker,
 *   the distribution statistics have been updated for Version 2.1.
 *   Note that because of language differences, the numbers are different
 *   from the Ada version. The main difference is that the variables that
 *   are local variables of "Proc_0" (Ada) or "main" (C) are global
 *   variables in the Pascal version.]
 *
 *  The following program contains statements of a high level programming
 *  language (here: Pascal) in a distribution considered representative:
 *
 *    assignments                  58
 *    control statements           28
 *    procedure, function calls    15
 *
 *  100 statements are dynamically executed. The program is balanced with
 *  respect to the three aspects:
 *
 *    - statement type
 *    - operand type (for simple data types)
 *    - operand access
 *         operand global, local, parameter, or constant.
 *           There is no static nesting of blocks or procedures,
 *           therefore all variables are either global or local.
 *
 *  The combination of these three aspects is balanced only approximately.
 *
 *  1. Statement Type:
 *  -----------------             number
 *
 *     V1 := V2                   15
 *     V := Constant              12
 *       (incl. V1 := F(..)
 *     Assignment,                 7
 *       with array element
 *     Assignment,                 6
 *       with record component
 *                                --
 *                                40       40
 *
 *     X := Y +|-|and|or Z         5
 *     X := Y +|-|"=" Constant     6
 *     X := X +|- 1                3
 *     X := Y *|/ Z                2
 *     X := Expression,            1
 *          two operators
 *     X := Expression,            1
 *          three operators
 *                                --
 *                                18       18
 *
 *     if .... then ....          14
 *       with "else"      7
 *       without "else"   7
 *           executed        3
 *           not executed    4
 *     for I in 1..N do ...        7  |  counted every time
 *     while ... do ...            4  |  the loop condition
 *     repeat ... until            1  |  is evaluated
 *     case ... end                1
 *     with                        1
 *                                --
 *                                28       28
 *
 *     P (...)  procedure call    10
 *     X := F (...)
 *             function  call      5
 *                                --
 *                                15       15
 *                                        ---
 *                                        101
 *
 *    22 of the 58 assignments have a variable of a constrained
 *    (sub-)type as their destination. In general, discriminant checks
 *    will be necessary in these cases; however, the compiler may
 *    optimize out some of these checks.
 *
 *    The average number of parameters in procedure or function calls
 *    is 1.80 (not counting the function values as implicit parameters).
 *
 *
 *  2. Operators
 *  ------------
 *                          number    approximate
 *                                    percentage
 *
 *    Arithmetic             27          52.9
 *
 *       +                     16          31.4
 *       -                      7          13.7
 *       *                      3           5.9
 *       div                    1           2.0
 *
 *    Comparison             20           39.2
 *
 *       =                      9           17.6
 *       <>                     4            7.8
 *       >                      1            2.0
 *       <                      3            5.9
 *       >=                     1            2.0
 *       <=                     2            3.9
 *
 *    Logic                   4            7.8
 *
 *       AND                    1            2.0
 *       OR                     1            2.0
 *       NOT                    2            3.9
 *
 *                           --          -----
 *                           51           99.9
 *
 *
 *  3. Operand Type (counted once per operand reference):
 *  ---------------
 *                          number    approximate
 *                                    percentage
 *
 *     Integer               135        54.7 %
 *     Character              47        19.0 %
 *     Enumeration            31        12.6 %
 *     Boolean                13         5.3 %
 *     Pointer                11         4.5 %
 *     String30                6         2.4 %
 *     Array                   2         0.8 %
 *     Record                  2         0.8 %
 *                           ---       -------
 *                           247        100.1 %
 *
 *  When there is an access path leading to the final operand (e.g. a record
 *  component), only the final data type on the access path is counted.
 *
 *  There are 16 accesses to components of a record, 9 of them go to
 *  a component in a variant part. For some of these accesses, the
 *  compiler may suppress generation of code checking the tag field
 *  during optimization.
 *
 *
 *  3. Operand Locality:
 *  -------------------
 *
 *     local variable               84        34.0 %
 *     global variable              58        23.5 %
 *     parameter                    45        18.2 %
 *        value                        23         9.3 %
 *        reference                    22         8.9 %
 *     function result               5         2.0 %
 *     constant                     55        22.3 %
 *                                 ---       -------
 *                                 247       100.0 %
 *
 *
 *  The program does not compute anything meaningful, but it is syntactically
 *  and semantically correct. All variables have a value assigned to them
 *  before they are used as a source operand.
 *
 *  There may be cases where a highly optimizing compiler may recognize
 *  unnecessary statements and may not generate code for them.
 *
 *  There has been no explicit effort to account for the effects of a
 *  cache, or to balance the use of long or short displacements for code or
 *  data.
 *
 ****************************************************************************
 *)

program Dhrystone (input, output, uptime);
(***************)

const
  autoRun = true;

  (* for measurement *)

  MicrosecondsPerClock  = 1000;
  ClocksPerSecond       = 1000;
        (* In Berkeley UNIX Pascal, the function "clock"        *)
        (* returns milliseconds                                 *)
  TooSmallTime          = 2000;
        (* Measurements should last at least 2 seconds          *)

type

  (* Global type definitions *)

  Enumeration           = (Ident1, Ident2, Ident3, Ident4, Ident5);

  OneToThirty           = 1..30;
  OneToFifty            = 1..50;
  CapitalLetter         = 'A'..'Z';

  String30              = packed array [OneToThirty] of char;

  Array1DimInteger      = array [OneToFifty] of integer;
  Array2DimInteger      = array [OneToFifty, OneToFifty] of integer;

  RecordPointer         = ^RecordType;

  RecordType            =
      record
        PointerComp:   RecordPointer;
        case Discr:    Enumeration of
          Ident1:         (* only this variant is used,           *)
                          (* but in some cases discriminant       *)
                          (* checks are necessary                 *)
            (EnumComp:      Enumeration;
             IntComp:       OneToFifty;
             StringComp:    String30);
          Ident2:
            (Enum2Comp:    Enumeration;
             String2Comp:  String30);
          Ident3, Ident4, Ident5:
            (Char1Comp,
             Char2Comp:    char);
      end; (* record *)

var

  uptime :text;

  (* Ada version: Variables local in Proc_0 *)

  Int1Glob,
  Int2Glob,
  Int3Glob:       OneToFifty;
  CharIndex:      char;
  EnumGlob:       Enumeration;
  String1Glob,
  String2Glob:    String30;

  (* Ada version: Variables global in Pack_1 *)

  PointerGlob,
  NextPointerGlob: RecordPointer;
  IntGlob:         integer;

  BoolGlob:        boolean;
  Char1Glob,
  Char2Glob:       char;
  Array1Glob:      Array1DimInteger;
  Array2Glob:      Array2DimInteger;

  (* Variables for measurement *)

  BeginTime,  EndTime: real;
  RunIndex,
  NumberOfRuns,
  SumClocks:            integer;
  Microseconds,
  DhrystonesPerSecond:  real;
  I:                    integer;

{ return seconds counter }
function timer: real;
{ for linux:
      call this program with /proc/uptime as program parameter
            dhry /proc/uptime
      read on file uptime gives uptime and idletime in seconds as real nr
            980.44 1531.67
}
var
   t : real;
begin
   reset( uptime );
   readln( uptime, t );
   timer := t;
end;

  (* end of variables for measurement *)

procedure Proc1 (    PointerParVal: RecordPointer);     forward;

procedure Proc2 (var IntParRef:     OneToFifty);        forward;

procedure Proc3 (var PointerParRef: RecordPointer);     forward;

procedure Proc4;                                        forward;
  (* without parameters *)

procedure Proc5;                                        forward;
  (* without parameters *)

procedure Proc6 (    EnumParVal:    Enumeration;
                 var EnumParRef:    Enumeration);       forward;

procedure Proc7 (    Int1ParVal,
                     Int2ParVal:    OneToFifty;
                 var IntParRef:     OneToFifty);        forward;

procedure Proc8 (var Array1ParRef:  Array1DimInteger;
                 var Array2ParRef:  Array2DimInteger;
                     Int1ParVal,
                     Int2ParVal:    integer);            forward;

function Func1  (    Char1ParVal,
                     Char2ParVal:   CapitalLetter):
                                            Enumeration; forward;

function Func2  (var String1ParRef,
                     String2ParRef: String30):
                                            boolean;      forward;

function Func3  (    EnumParVal:    Enumeration):
                                            boolean;      forward;


procedure Proc1; (* (PointerParVal: RecordPointer) *)
    (* executed once *)
begin
  with PointerParVal^.PointerComp^ (* = PointerGlobNext *) do
  begin
    PointerParVal^.PointerComp^ := PointerGlob^;
    PointerParVal^.IntComp := 5;
    IntComp := PointerParVal^.IntComp;
    PointerComp := PointerParVal^.PointerComp;
    Proc3 (PointerComp);
      (* PointerParVal^.PointerComp^.PointerComp = PointerGlob^.PointerComp *)
    if Discr = Ident1
    then (* executed *)
    begin
      IntComp := 6;
      Proc6 (PointerParVal^.EnumComp, EnumComp);
      PointerComp := PointerGlob^.PointerComp;
      Proc7 (IntComp, 10, IntComp);
    end (* then *)
    else (* not executed *)
      PointerParVal^ := PointerParVal^.PointerComp^;
  end; (* with *)
end; (* Proc1 *)


procedure Proc2; (* (var IntParRef: OneToFifty) *)
    (* executed once *)
    (* InParRef = 3, becomes 7 *)
var
  IntLoc:  OneToFifty;
  EnumLoc: Enumeration;
begin
  IntLoc := IntParRef + 10;
  repeat (* executed once *)
    if Char1Glob = 'A'
    then (* executed *)
    begin
      IntLoc := IntLoc - 1;
      IntParRef := IntLoc - IntGlob;
      EnumLoc := Ident1;
    end (* if *)
  until EnumLoc = Ident1; (* true *)
end; (* Proc2 *)


procedure Proc3; (* (var PointerParRef: RecordPointer) *)
    (* executed once *)
    (* PointerParRef becomes PointerGlob *)
begin
  if PointerGlob <> nil
  then (* executed *)
    PointerParRef := PointerGlob^.PointerComp;
  Proc7 (10, IntGlob, PointerGlob^.IntComp);
end; (* Proc3 *)


procedure Proc4; (* without parameters *)
    (* executed once *)
var
  BoolLoc: boolean;
begin
  BoolLoc := Char1Glob = 'A';
  BoolGlob := BoolLoc or BoolGlob;
  Char2Glob := 'B';
end; (* Proc4 *)


procedure Proc5; (* without parameters *)
    (* executed once *)
begin
  Char1Glob := 'A';
  BoolGlob := false;
end; (* Proc5 *)


procedure Proc6; (* (    EnumParVal:     Enumeration;
                     var EnumParRef:     Enumeration) *)
    (* executed once *)
    (* EnumParVal = Ident3, EnumParRef becomes Ident2 *)
begin
  EnumParRef := EnumParVal;
  if not Func3 (EnumParVal)
  then (* not executed *)
    EnumParRef := Ident4;
  case EnumParVal of
    Ident1: EnumParRef := Ident1;
    Ident2: if IntGlob > 100
              then EnumParRef := Ident1
              else EnumParRef := Ident4;
    Ident3: EnumParRef := Ident2;    (* executed *)
    Ident4: ;
    Ident5: EnumParRef := Ident3;
  end; (* case *)
end; (* Proc6 *)


procedure Proc7; (* (    Int1ParVal,
                         Int2ParVal:    OneToFifty;
                var IntParRef:     OneToFifty);
    (* executed three times                               *)
    (* first call:      Int1ParVal = 2, Int2ParVal = 3,   *)
    (*                  IntParRef becomes 7               *)
    (* second call:     Int1ParVal = 10, Int2ParVal = 5,  *)
    (*                  IntParRef becomes 17              *)
    (* third call:      Int1ParVal = 6, Int2ParVal = 10,  *)
    (*                  IntParRef becomes 18              *)
var
  IntLoc: OneToFifty;
begin
  IntLoc := Int1ParVal + 2;
  IntParRef := Int2ParVal + IntLoc;
end; (* Proc7 *)


procedure Proc8; (* (var Array1ParRef: Array1DimInteger;
                     var Array2ParRef: Array2DimInteger;
                         Int1ParVal,
                         Int2ParVal:    integer)          *)
    (* executed once  *)
    (* Int1ParVal = 3 *)
    (* Int2ParVal = 7 *)
var
  IntIndex,
  IntLoc:   OneToFifty;
begin
  IntLoc := Int1ParVal + 5;
  Array1ParRef [IntLoc] := Int2ParVal;
  Array1ParRef [IntLoc+1] := Array1ParRef [IntLoc];
  Array1ParRef [IntLoc+30] := IntLoc;
  for IntIndex := IntLoc to IntLoc+1 do
    Array2ParRef [IntLoc, IntIndex] := IntLoc;
  Array2ParRef [IntLoc, IntLoc-1] := Array2ParRef [IntLoc, IntLoc-1] + 1;
  Array2ParRef [IntLoc+20, IntLoc] := Array1ParRef [IntLoc];
  IntGlob := 5;
end; (* Proc8 *)


function Func1; (* (Char1ParVal,
                    Char2ParVal: CapitalLetter): Enumeration *)
    (* executed three times, returns always Ident1              *)
    (* first call:      Char1ParVal = 'H', Char2ParVal = 'R'    *)
    (* second call:     Char1ParVal = 'A', Char2ParVal = 'C'    *)
    (* third call:      Char1ParVal = 'B', Char2ParVal = 'C'    *)
var
  Char1Loc, Char2Loc: CapitalLetter;
begin
  Char1Loc := Char1ParVal;
  Char2Loc := Char1Loc;
  if Char2Loc <> Char2ParVal
  then  (* executed *)
    Func1 := Ident1
  else  (* not executed *)
  begin
    Char1Glob := Char1Loc;
    Func1 := Ident2;
  end;
end; (* Func1 *)


function Func2; (* (var String1ParRef,
                        String2ParRef: String30): boolean *)
    (* executed once, returns false              *)
    (* String1ParRef = 'DHRYSTONE PROGRAM, 1''ST STRING' *)
    (* String2ParRef = 'DHRYSTONE PROGRAM, 2''ND STRING' *)
var
  IntLoc:  OneToThirty;
  CharLoc: CapitalLetter;
begin
  IntLoc := 2;
  while IntLoc <= 2 do (* loop body executed once *)
    if Func1 (String1ParRef[IntLoc],
              String2ParRef[IntLoc+1]) = Ident1
    then (* executed *)
    begin
      CharLoc := 'A';
      IntLoc := IntLoc + 1;
    end; (* if, while *)
  if (CharLoc >= 'W') and (CharLoc < 'Z')
  then (* not executed *)
    IntLoc := 7;
  if CharLoc = 'R'
  then (* not executed *)
    Func2 := true
  else (* executed *)
  begin
    if String1ParRef > String2ParRef
    then (* not executed *)
    begin
      IntLoc := IntLoc + 7;
      IntGlob := IntLoc;
      Func2 := true
    end
    else (* executed *)
      Func2 := false;
  end; (* if CharLoc *)
end; (* Func2 *)


function Func3; (* (EnumParVal: Enumeration): boolean *)
    (* executed once, returns true      *)
    (* EnumParVal = Ident3              *)
var
  EnumLoc:  Enumeration;
begin
  EnumLoc := EnumParVal;
  if EnumLoc = Ident3
  then (* executed *)
    Func3 := true
  else (* not executed *)
    Func3 := false;
end; (* Func3 *)


begin (* main program, corresponds to procedures        *)
      (* Main and Proc_0 in the Ada version             *)

  (* Initializations *)

  new (NextPointerGlob);

  new (PointerGlob);

  PointerGlob^.PointerComp := NextPointerGlob;
  PointerGlob^.Discr       := Ident1;
  PointerGlob^.EnumComp    := Ident3;
  PointerGlob^.IntComp     := 40;
  PointerGlob^.StringComp  := 'DHRYSTONE PROGRAM, SOME STRING';

  String1Glob := 'DHRYSTONE PROGRAM, 1''ST STRING';

  Array2Glob [8,7] := 10;

  writeln;
  writeln ('Dhrystone Benchmark, Version 2.1 (Language: Pascal)');
  writeln;
   NumberOfRuns := 100000000;
  if not autoRun then begin
     write('Please give the number of runs through the benchmark (default ',
               NumberOfRuns: 1, '): ');
     if not eoln then
        readln (NumberOfRuns); { too bad if a non-integer is entered!! }
  end;
  writeln;
  writeln ('Execution starts, ', NumberOfRuns : 7, ' runs through Dhrystone');

  BeginTime := timer;

  (***************)
  (* Start timer *)
  (***************)
  
  for RunIndex := 1 to NumberOfRuns do
  begin

    Proc5;
    Proc4;
      (* Char1Glob = 'A', Char2Glob = 'B', BoolGlob = false *)
    Int1Glob := 2;
    Int2Glob := 3;
    String2Glob := 'DHRYSTONE PROGRAM, 2''ND STRING';
    EnumGlob := Ident2;
    BoolGlob := not Func2 (String1Glob, String2Glob);
      (* BoolGlob = true *)
    while Int1Glob < Int2Glob do  (* loop body executed once *)
    begin
      Int3Glob := 5 * Int1Glob - Int2Glob;
        (* Int3Glob = 7 *)
      Proc7 (Int1Glob, Int2Glob, Int3Glob);
        (* Int3Glob = 7 *)
      Int1Glob := Int1Glob + 1;
    end; (* while *)
      (* Int1Glob = 3 *)
    Proc8 (Array1Glob, Array2Glob, Int1Glob, Int3Glob);
      (* IntGlob = 5 *)
    Proc1 (PointerGlob);
    for CharIndex := 'A' to Char2Glob do   (* loop body executed twice *)
      if EnumGlob = Func1 (CharIndex, 'C')
        then (* not executed *)
        begin
          Proc6 (Ident1, EnumGlob);
          String2Glob := 'DHRYSTONE PROGRAM, 3''RD STRING';
          Int2Glob := RunIndex;
          IntGlob := RunIndex;
        end;
    (* Int1Glob = 3, Int2Glob = 3, Int3Glob = 7 *)
    Int2Glob := Int2Glob * Int1Glob;
    Int1Glob := Int2Glob div Int3Glob;
    Int2Glob := 7 * (Int2Glob - Int3Glob) - Int1Glob;
      (* Int1Glob = 1, Int2Glob = 13, Int3Glob = 7 *)
    Proc2 (Int1Glob);
      (* Int1Glob = 5 *)

  end; (* for RunIndex *)

  EndTime := timer;

  (**************)
  (* Stop timer *)
  (**************)

  writeln ('Execution ends');
  writeln;
  writeln ('Final values of the variables used in the benchmark:');
  writeln;

  writeln ('IntGlob:                      ', IntGlob : 5);
  writeln ('        should be:                5');
  write ('BoolGlob:                      ');
  if BoolGlob = true
  then
    writeln ('TRUE')
  else
    writeln ('FALSE');
  writeln ('        should be:             TRUE');
  writeln ('Char1Glob:                        ', Char1Glob);
  writeln ('        should be:                A');
  writeln ('Char2Glob:                        ', Char2Glob);
  writeln ('        should be:                B');
  writeln ('Array1Glob [8]:               ', Array1Glob [8] : 5);
  writeln ('        should be:                7');
  writeln ('Array2Glob [8,7]:             ', Array2Glob [8,7] : 5);
  writeln ('        should be:            ', NumberOfRuns + 10);
  writeln ('PointerGlob^.Discr:           ', ord (PointerGlob^.Discr) : 5);
  writeln ('        should be:                0');
  writeln ('PointerGlob^.EnumComp:        ', ord (PointerGlob^.EnumComp) : 5);
  writeln ('        should be:                2');
  writeln ('PointerGlob^.IntComp  :       ', PointerGlob^.IntComp : 5);
  writeln ('        should be:               17');
  write   ('PointerGlob^.StringComp:     ');
  for I := 1 to 30 do
    write (PointerGlob^.StringComp [I]);
  writeln;
  writeln ('        should be:           DHRYSTONE PROGRAM, SOME STRING');
  writeln ('NextPointerGlob^.Discr:       ', ord (NextPointerGlob^.Discr) : 5);
  writeln ('        should be:                0');
  writeln ('NextPointerGlob^.EnumComp:    ',
                    ord (NextPointerGlob^.EnumComp) : 5);
  writeln ('        should be:                1');
  writeln ('NextPointerGlob^.IntComp:     ', NextPointerGlob^.IntComp : 5);
  writeln ('        should be:               18');
  write   ('NextPointerGlob^.StringComp: ');
  for I := 1 to 30 do
    write (NextPointerGlob^.StringComp [I]);
  writeln;
  writeln ('        should be:           DHRYSTONE PROGRAM, SOME STRING');
  writeln ('Int1Glob:                     ', Int1Glob : 5);
  writeln ('        should be:                5');
  writeln ('Int2Glob:                     ', Int2Glob : 5);
  writeln ('        should be:               13');
  writeln ('Int3Glob:                     ', Int3Glob : 5);
  writeln ('        should be:                7');
  writeln ('EnumGlob:                     ', ord (EnumGlob) : 5);
  writeln ('        should be:                1');
  write   ('String1Glob:                 ');
  for I := 1 to 30 do
    write (String1Glob [I]);
  writeln;
  writeln ('        should be:           DHRYSTONE PROGRAM, 1''ST STRING');
  write   ('String2Glob:                 ');
  for I := 1 to 30 do
    write (String2Glob [I]);
  writeln;
  writeln ('        should be:           DHRYSTONE PROGRAM, 2''ND STRING');
  writeln;
  writeln;

  SumClocks := trunc(1000*(EndTime - BeginTime)); { converting to milliseconds }

  if SumClocks < TooSmallTime
    then
    begin
      writeln ('Measured time too small to obtain meaningful results');
      writeln ('Please increase number of runs');
      writeln;
    end
    else
    begin
      Microseconds := SumClocks * (MicrosecondsPerClock / NumberOfRuns);
                                (* Brackets to prevent integer overflow *)
      DhrystonesPerSecond := NumberOfRuns * (ClocksPerSecond / SumClocks);
      write ('Microseconds for one run through Dhrystone: ');
      writeln (Microseconds : 1 : 3);
      write ('Dhrystones per Second:                      ');
      writeln (DhrystonesPerSecond : 1 : 1);
      writeln;
    end;
  
  dispose(NextPointerGlob);
  dispose(PointerGlob);

end.
