#!/usr/bin/perl
#   Copyright (C) 2021-2023 Free Software Foundation, Inc.
#   Contributed by Oracle.
#
#   This file is part of GNU Binutils.
#
#   This program is free software; you can redistribute it and/or modify
#   it under the terms of the GNU General Public License as published by
#   the Free Software Foundation; either version 3, or (at your option)
#   any later version.
#
#   This program is distributed in the hope that it will be useful,
#   but WITHOUT ANY WARRANTY; without even the implied warranty of
#   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
#   GNU General Public License for more details.
#
#   You should have received a copy of the GNU General Public License
#   along with this program; if not, write to the Free Software
#   Foundation, 51 Franklin Street - Fifth Floor, Boston,
#   MA 02110-1301, USA.
 
use strict;
use warnings;
use feature qw (state);
use File::stat;

#------------------------------------------------------------------------------
# Check as early as possible if the version of Perl used is supported.
#------------------------------------------------------------------------------
INIT
{
  my $perl_minimal_version_supported = version->parse ("5.10.0")->normal;
  my $perl_current_version           = version->parse ("$]")->normal;

  if ($perl_current_version lt $perl_minimal_version_supported)
    {
      my $msg;

      $msg  = "Error: minimum Perl release required: ";
      $msg .= $perl_minimal_version_supported;
      $msg .= " current: ";
      $msg .= $perl_current_version;
      $msg .= "\n";

      print $msg;

      exit (1);
     }
} #-- End of INIT

#------------------------------------------------------------------------------
# Poor man's version of a boolean.
#------------------------------------------------------------------------------
my $TRUE    = 1;
my $FALSE   = 0;

#------------------------------------------------------------------------------
# Used to ensure correct alignment of columns.
#------------------------------------------------------------------------------
my $g_max_length_first_metric;

#------------------------------------------------------------------------------
# This variable contains the path used to execute $GP_DISPAY_TEXT.
#------------------------------------------------------------------------------
my $g_path_to_tools;

#-------------------------------------------------------------------------------
# Code debugging flag
#-------------------------------------------------------------------------------
my $g_test_code = $FALSE;

#-------------------------------------------------------------------------------
# GPROFNG commands and files used.
#-------------------------------------------------------------------------------
my $GP_DISPLAY_TEXT = "gp-display-text";

my $g_gp_output_file   = $GP_DISPLAY_TEXT.".stdout.log";
my $g_gp_error_logfile = $GP_DISPLAY_TEXT.".stderr.log";

#------------------------------------------------------------------------------
# Global variables.
#------------------------------------------------------------------------------
my $g_addressing_mode = "64 bit";

#------------------------------------------------------------------------------
# The global regex section.
#
# First step towards consolidating all regexes.
#------------------------------------------------------------------------------
  my $g_less_than_regex      = '<';
  my $g_html_less_than_regex = '&lt;';
  my $g_endbr_inst_regex     = 'endbr[32|64]';

#------------------------------------------------------------------------------
# These are the regex's used.
#------------------------------------------------------------------------------
#------------------------------------------------------------------------------
# Disassembly analysis
#------------------------------------------------------------------------------
  my $g_branch_regex = '\.*([0-9a-fA-F]*):\s+(j).*\s*0x([0-9a-fA-F]+)';
  my $g_endbr_regex  = '\.*([0-9a-fA-F]*):\s+(endbr[32|64])';
  my $g_function_call_v2_regex = '(.*)\s+([0-9a-fA-F]*):\s+(call)\s*0x([0-9a-fA-F]+)\s*';

#------------------------------------------------------------------------------
# Convenience.  These map the on/off value to $TRUE/$FALSE to make the code
# easier to read.  For example: "if ($g_verbose)" as opposed to the following:
# "if ($verbose_setting eq "on").
#------------------------------------------------------------------------------
my $g_verbose;
my $g_warnings;
my $g_quiet;

my $g_first_metric; 

my $binutils_version;
my $driver_cmd;
my $tool_name;
my $version_info;

my %g_mapped_cmds = ();

#------------------------------------------------------------------------------
# TBD All warning messages are collected and are accessible through the main
# page.
#------------------------------------------------------------------------------
my @g_warning_messages = ();

#------------------------------------------------------------------------------
# Contains the names that have already been tagged.  This is a global
# structure because otherwise the code would get much more complicated.
#------------------------------------------------------------------------------
my %g_tagged_names = ();

#------------------------------------------------------------------------------
# TBD Remove the use of these structures. No longer used.
#------------------------------------------------------------------------------
my %g_function_tag_id = ();
my $g_context = 5; # Defines the range of scan

my $g_default_setting_lang = "en-US.UTF-8";
my %g_exp_dir_meta_data;

my @g_user_input_errors = ();

my $g_html_credits_line;

my $g_warn_keyword  = "Input warning: ";
my $g_error_keyword = "Input error:   ";

my %g_function_occurrences = ();
my %g_map_function_to_index = ();
my %g_multi_count_function = ();
my %g_function_view_all = ();
my @g_full_function_view_table = ();

my @g_html_experiment_stats = ();

#-------------------------------------------------------------------------------
# These structures contain the information printed in the function views.
#-------------------------------------------------------------------------------
my $g_header_lines;

my @g_html_function_name = ();

#-------------------------------------------------------------------------------
# TBD: This variable may not be needed and replaced by tp_value
my $thresh = 0;
#-------------------------------------------------------------------------------

#-------------------------------------------------------------------------------
# Define the driver command, tool name and version number.
#-------------------------------------------------------------------------------
$driver_cmd       = "gprofng display html";
$tool_name        = "gp-display-html";
#$binutils_version = "2.38.50";
$binutils_version = "2.40.00";
$version_info     = $tool_name . " GNU binutils version " . $binutils_version;

#-------------------------------------------------------------------------------

#-------------------------------------------------------------------------------
# Define several key data structures.
#-------------------------------------------------------------------------------
my %g_user_settings = 
  (
    output           => { option => "-o" , no_of_arguments => 1, data_type => "path"    , current_value => undef, defined => $FALSE},
    overwrite        => { option => "-O" , no_of_arguments => 1, data_type => "path"    , current_value => undef, defined => $FALSE},
    calltree         => { option => "-ct", no_of_arguments => 1, data_type => "onoff"   , current_value => "off"      , defined => $FALSE},
    func_limit       => { option => "-fl", no_of_arguments => 1, data_type => "pinteger", current_value => 500        , defined => $FALSE},
    highlight_percentage => { option => "-hp", no_of_arguments => 1, data_type => "pfloat"  , current_value => 90.0       , defined => $FALSE},
    threshold_percentage => { option => "-tp", no_of_arguments => 1, data_type => "pfloat"  , current_value => 100.0      , defined => $FALSE},
    default_metrics  => { option => "-dm", no_of_arguments => 1, data_type => "onoff"   , current_value => "off"      , defined => $FALSE},
    ignore_metrics   => { option => "-im", no_of_arguments => 1, data_type => "metric_names", current_value => undef, defined => $FALSE},
    verbose          => { option => "--verbose" , no_of_arguments => 1, data_type => "onoff"  , current_value => "off" , defined => $FALSE},
    warnings         => { option => "--warnings" , no_of_arguments => 1, data_type => "onoff"  , current_value => "on" , defined => $FALSE},
    debug            => { option => "--debug" , no_of_arguments => 1, data_type => "size"  , current_value => "off" , defined => $FALSE},
    quiet            => { option => "--quiet" , no_of_arguments => 1, data_type => "onoff"   , current_value => "off"      , defined => $FALSE},
  );

my %g_debug_size = 
  (
    "on"  => $FALSE,
    "s"   => $FALSE,
    "m"   => $FALSE,
    "l"   => $FALSE,
    "xl"  => $FALSE,
  );

my %local_system_config =
  (
    kernel_name       => "undefined",
    nodename          => "undefined",
    kernel_release    => "undefined",
    kernel_version    => "undefined",
    machine           => "undefined",
    processor         => "undefined",
    hardware_platform => "undefined",
    operating_system  => "undefined",
    hostname_current  => "undefined",
  );

# Note that we use single quotes here, because regular expressions wreak havoc otherwise.

my %g_arch_specific_settings =
  (
    arch_supported  => $FALSE,
    arch            => 'undefined',
    regex           => 'undefined',
    subexp          => 'undefined',
    linksubexp      => 'undefined',
  );

my %g_locale_settings = (
  LANG              => "en_US.UTF-8",
  decimal_separator => "\\.",
  covert_to_dot     => $FALSE
);

#------------------------------------------------------------------------------
# See this page for a nice overview with the colors:
# https://www.w3schools.com/colors/colors_groups.asp
#------------------------------------------------------------------------------

my %g_html_color_scheme = (
  "control_flow"  => "Brown",
  "target_function_name" => "Red",
  "non_target_function_name" => "BlueViolet",
  "background_color_hot" => "PeachPuff",
  "background_color_lukewarm" => "LemonChiffon",
  "link_outside_range" => "Crimson",
  "error_message" => "LightPink",
  "background_color_page" => "White",
#  "background_color_page" => "LightGray",
  "background_selected_sort" => "LightSlateGray",
  "index" => "Lavender",
);

#------------------------------------------------------------------------------
# These are the base names for the HTML files that are generated.
#------------------------------------------------------------------------------
my %g_html_base_file_name = (
  "caller_callee"  => "caller-callee",
  "disassembly" => "dis",
  "experiment_info"  => "experiment-info",
  "function_view"  => "function-view-sorted",
  "index" => "index",
  "source" => "src",
  "warnings" => "warnings",
);

#------------------------------------------------------------------------------
# This is cosmetic, but helps with the scoping of variables.
#------------------------------------------------------------------------------
  main ();

  exit (0);

#------------------------------------------------------------------------------
# This is the driver part of the program.
#------------------------------------------------------------------------------
sub main
{
  my $subr_name = get_my_name ();

#------------------------------------------------------------------------------
# The name of the configuration file.
#------------------------------------------------------------------------------
  my $rc_file_name = ".gp-display-html.rc";

#------------------------------------------------------------------------------
# OS commands executed and search paths.
#------------------------------------------------------------------------------
  my @selected_os_cmds = qw (rm mv cat hostname locale which printenv ls
                             uname readelf mkdir);
  my @search_paths_os_cmds = qw (
    /usr/bin
    /bin
    /usr/local/bin
    /usr/local/sbin
    /usr/sbin
    /sbin
  );

#------------------------------------------------------------------------------
# TBD: Eliminate these.
#------------------------------------------------------------------------------
  my $ARCHIVES_MAP_NAME;
  my $ARCHIVES_MAP_VADDR;

#------------------------------------------------------------------------------
# Local structures (hashes and arrays).
#------------------------------------------------------------------------------
  my @exp_dir_list; # List with experiment directories
  my @metrics_data;

  my %function_address_info = ();
  my $function_address_info_ref; 

  my @function_info = ();
  my $function_info_ref;

  my %function_address_and_index = ();
  my $function_address_and_index_ref;

  my %addressobjtextm = ();
  my $addressobjtextm_ref;

  my %addressobj_index = ();
  my $addressobj_index_ref;

  my %LINUX_vDSO = ();
  my $LINUX_vDSO_ref;

  my %function_view_structure = ();
  my $function_view_structure_ref;

  my %elf_rats = ();
  my $elf_rats_ref;

#------------------------------------------------------------------------------
# Local variables.
#------------------------------------------------------------------------------
  my $abs_path_outputdir; 
  my $archive_dir_not_empty;
  my $base_va_executable; 
  my $executable_name;
  my $exp_dir_list_ref;
  my $found_exp_dir;
  my $ignore_value;
  my $message;
  my $number_of_metrics;
  my $va_executable_in_hex;

  my $failed_command_mappings; 
  my $option_errors;
  my $total_user_errors;

  my $script_pc_metrics; 
  my $dir_check_errors;
  my $consistency_errors;
  my $outputdir;
  my $return_code;

  my $decimal_separator;
  my $convert_to_dot;
  my $architecture_supported;
  my $elf_arch;
  my $elf_support;
  my $home_dir;
  my $elf_loadobjects_found; 

  my $rc_file_paths_ref;
  my @rc_file_paths = ();
  my $rc_file_errors = 0;

  my @sort_fields = ();
  my $summary_metrics;
  my $call_metrics;
  my $user_metrics;
  my $system_metrics;
  my $wall_metrics;
  my $detail_metrics;
  my $detail_metrics_system; 

  my $pretty_dir_list; 

  my %metric_value       = ();
  my %metric_description = ();
  my %metric_description_reversed = ();
  my %metric_found = ();
  my %ignored_metrics = ();

  my $metric_value_ref;
  my $metric_description_ref;
  my $metric_found_ref;
  my $ignored_metrics_ref;

  my @table_execution_stats = ();
  my $table_execution_stats_ref;

  my $html_first_metric_file_ref;
  my $html_first_metric_file;

  my $arch;
  my $subexp;
  my $linksubexp;

  my $setting_for_LANG;
  my $time_percentage_multiplier;
  my $process_all_functions;

  my $selected_archive;

#------------------------------------------------------------------------------
# If no options are given, print the help info and exit.
#------------------------------------------------------------------------------
  if ($#ARGV == -1)
    {
      $ignore_value = print_help_info (); 
      return (0);
    }

#------------------------------------------------------------------------------
# This part is like a preamble.  Before we continue we need to figure out some 
# things that are needed later on.
#------------------------------------------------------------------------------

#------------------------------------------------------------------------------
# Store the absolute path of the command executed.
#------------------------------------------------------------------------------
  my $location_gp_command = $0;

#------------------------------------------------------------------------------
# The very first thing to do is to quickly determine if the user has enabled 
# one of the following options and take action accordingly:
# --version, --verbose, --debug, --quiet
#
# This avoids that there is a gap between the start of the execution and the
# moment the options are parsed, checked, and interpreted.
#
# When parsing the full command line, these options will be more extensively
# checked and also updated in %g_user_settings

# Note that a confirmation message, if any, is printed here and not when the 
# options are parsed and processed.
#------------------------------------------------------------------------------

  $g_verbose  = $g_user_settings{"verbose"}{"current_value"} eq "on" ? $TRUE : $FALSE;
  $g_warnings = $g_user_settings{"warnings"}{"current_value"} eq "on" ? $TRUE : $FALSE;
  $g_quiet    = $g_user_settings{"quiet"}{"current_value"} eq "on" ? $TRUE : $FALSE;

  $ignore_value = early_scan_specific_options ();

#------------------------------------------------------------------------------
# The next subroutine is executed early to ensure the OS commands we need are 
# available.
#
# This subroutine stores the commands and the full path names as an associative
# array called "g_mapped_cmds".  The command is the key and the value is the full 
# path.  For example: ("uname", /usr/bin/uname).
#------------------------------------------------------------------------------
  $failed_command_mappings = check_and_define_cmds (\@selected_os_cmds, \@search_paths_os_cmds);

  if ($failed_command_mappings == 0)
    {
      gp_message ("debug", $subr_name, "verified the OS commands");
    }
  else
    {
      my $msg = "failure in the verification of the OS commands";
      gp_message ("assertion", $subr_name, $msg);
    }

#------------------------------------------------------------------------------
# Get the home directory and the locations for the configuration file on the 
# current system.
#------------------------------------------------------------------------------
  ($home_dir, $rc_file_paths_ref) = get_home_dir_and_rc_path ($rc_file_name);

  @rc_file_paths = @{ $rc_file_paths_ref };
  gp_message ("debug", $subr_name, "the home directory is $home_dir");
  gp_message ("debugXL", $subr_name, "the search path for the rc file is @rc_file_paths");

  $pretty_dir_list = build_pretty_dir_list (\@rc_file_paths);

#------------------------------------------------------------------------------
# Get the ball rolling.  Parse and interpret the configuration file (if any)
# and the command line options.
#
# If either $rc_file_errors or $total_user_errors, or both, are non-zero it
# means a fatal error has occured. In this case, all error messages are 
# printed and execution is terminated.
#
# Note that the verbose, debug, and quiet options can be set in this file.
# It is a deliberate choice to ignore these for now.  The assumption is that
# the user will not be happy if we ignore the command line settings for a
# while.
#------------------------------------------------------------------------------

  gp_message ("debugXL", $subr_name, "processing of the rc file disabled for now");

# Temporarily disabled  print_table_user_settings ("debugXL", "before function process_rc_file");
# Temporarily disabled
# Temporarily disabled  $rc_file_errors = process_rc_file ($rc_file_name, $rc_file_paths_ref);
# Temporarily disabled  
# Temporarily disabled  if ($rc_file_errors != 0)
# Temporarily disabled    {
# Temporarily disabled      $message = "fatal errors in file $rc_file_name encountered";
# Temporarily disabled      gp_message ("debugXL", $subr_name, $message);
# Temporarily disabled    }
# Temporarily disabled
# Temporarily disabled  print_table_user_settings ("debugXL", "after function process_rc_file");

#------------------------------------------------------------------------------
# Get the ball rolling. Parse and interpret the options.  Some first checks
# are performed.
#
# Instead of bailing out on the first user error, we capture all errors, print
# messages and then bail out. This is more user friendly.
#------------------------------------------------------------------------------
  gp_message ("verbose", $subr_name, "Parse the user options");

  $total_user_errors = 0;

  ($option_errors, $found_exp_dir, $exp_dir_list_ref) = parse_and_check_user_options (
                                                          \$#ARGV, 
                                                          \@ARGV);
  $total_user_errors += $option_errors;

#------------------------------------------------------------------------------
# Dynamically load the modules needed.  If a module is not available, print 
# an error message and bail out.
#
# This call replaces the following:
#
# use feature qw (state);
# use List::Util qw (min max);
# use Cwd;
# use File::Basename;
# use File::stat;
# use POSIX;
# use bignum;
#
# Note that this check cannot be done earlier, because in case of a missing 
# module, the man page would not be generated if the code ends prematurely
# in case the --help and --version options are used..
#------------------------------------------------------------------------------
  my ($module_errors_ref, $missing_modules_ref) = handle_module_availability ();
 
  my $module_errors = ${ $module_errors_ref };

  if ($module_errors > 0)
    {
      my $msg;

      my $plural_or_single = ($module_errors > 1) ? "modules are" : "module is";
      my @missing_modules = @{ $missing_modules_ref };

      for my $i (0 .. $#missing_modules)
        {
          $msg = "module $missing_modules[$i] is missing";
          gp_message ("error", $subr_name, $msg);
        }
      
      $msg = $module_errors . " " . $plural_or_single  .
             "missing - execution is terminated";
      gp_message ("abort", $subr_name, $msg);
    }

#------------------------------------------------------------------------------
# The user options have been taken in.  Check for validity and consistency.
#------------------------------------------------------------------------------
  gp_message ("verbose", $subr_name, "Process user options");

  ($option_errors, $ignored_metrics_ref, $outputdir, 
   $time_percentage_multiplier, $process_all_functions,
   $exp_dir_list_ref) = process_user_options ($exp_dir_list_ref);

  @exp_dir_list = @{ $exp_dir_list_ref };
  %ignored_metrics = %{$ignored_metrics_ref};

  $total_user_errors += $option_errors;

#------------------------------------------------------------------------------
# If no option is given for the output directory, pick a default.  Otherwise,
# if the output directory exists, wipe it clean in case the -O option is used.
# If not, flag an error because the -o option does not overwrite an existing
# directory.
#------------------------------------------------------------------------------
  if ($total_user_errors == 0)
    {
      ($option_errors, $outputdir) = set_up_output_directory ();
      $abs_path_outputdir = cwd () . "/" . $outputdir;
      $total_user_errors += $option_errors;
    }

  if ($total_user_errors == 0)
    {
      gp_message ("debug", $subr_name, "the output directory is $outputdir");
    }
  else
    {
#------------------------------------------------------------------------------
# All command line errors and warnings are printed here.
#------------------------------------------------------------------------------
      my $plural_or_single = ($total_user_errors > 1) ? "errors have" : "error has";
      $message  =  $g_error_keyword;
      $message .=  $total_user_errors;
      if ($rc_file_errors > 0)
        {
          $message .=  " additional";
        }
      $message .=  " fatal input $plural_or_single been detected:";
      gp_message ("error", $subr_name, $message);
      for my $key (keys @g_user_input_errors)
        {
          gp_message ("error", $subr_name, "$g_error_keyword  $g_user_input_errors[$key]");
        }
    }

#------------------------------------------------------------------------------
# Bail out in case fatal errors have occurred.
#------------------------------------------------------------------------------
  if ( ($rc_file_errors + $total_user_errors) > 0)
    {
      my $msg = "the current values for the user controllable settings";
      print_user_settings ("debug", $msg);

      gp_message ("abort", $subr_name, "execution terminated");
    }
  else
    {
      my $msg = "after parsing the user options, the final values are";
      print_user_settings ("debug", $msg);

#------------------------------------------------------------------------------
# TBD: Enable once all planned features have been implemented and tested.
#------------------------------------------------------------------------------
# Temporarily disabled      $msg = "the final values for the user controllable settings";
# Temporarily disabled      print_table_user_settings ("verbose", $msg);
    }

#------------------------------------------------------------------------------
# Print a list with the experiment directory names
#------------------------------------------------------------------------------
  $pretty_dir_list = build_pretty_dir_list (\@exp_dir_list);

  my $plural = ($#exp_dir_list > 0) ? "directories are" : "directory is";

  gp_message ("verbose", $subr_name, "The experiment " . $plural . ":");
  gp_message ("verbose", $subr_name, $pretty_dir_list);

#------------------------------------------------------------------------------
# Set up the first entry with the meta data for the experiments.  This field
# contains the absolute paths to the experiment directories.
#------------------------------------------------------------------------------
  for my $exp_dir (@exp_dir_list)
    {
     my ($filename, $directory_path, $ignore_suffix) = fileparse ($exp_dir);
     gp_message ("debug", $subr_name, "exp_dir = $exp_dir"); 
     gp_message ("debug", $subr_name, "filename = $filename"); 
     gp_message ("debug", $subr_name, "directory_path = $directory_path"); 
     $g_exp_dir_meta_data{$filename}{"directory_path"} = $directory_path; 
    }

#------------------------------------------------------------------------------
# Check whether the experiment directories are valid.  If not, it is a fatal
# error.
# Upon successful return, one directory has been selected to be used in the
# remainder.  This is not always the correct thing to do, but is the same as
# the original code.  In due time this should be addressed though.
#------------------------------------------------------------------------------
  ($dir_check_errors, $archive_dir_not_empty, $selected_archive, 
   $elf_rats_ref) = check_validity_exp_dirs ($exp_dir_list_ref);

  if ($dir_check_errors)
    {
      gp_message ("abort", $subr_name, "execution terminated");
    }
  else
    {
      gp_message ("verbose", $subr_name, "The experiment directories have been verified and are valid");
    }

  %elf_rats = %{$elf_rats_ref};

#-------------------------------------------------------------------------------
# Now that we know the map.xml file(s) are present, we can scan these and get
# the required information.  This includes setting the base virtual address.
#-------------------------------------------------------------------------------
  $ignore_value = determine_base_virtual_address ($exp_dir_list_ref);

#------------------------------------------------------------------------------
# Check whether the experiment directories are consistent.
#------------------------------------------------------------------------------
  ($consistency_errors, $executable_name) = verify_consistency_experiments ($exp_dir_list_ref);

  if ($consistency_errors == 0)
    {
      gp_message ("verbose", $subr_name, "The experiment directories are consistent");
    }
  else
    {
      gp_message ("abort", $subr_name, "number of consistency errors detected: $consistency_errors"); 
    }

#------------------------------------------------------------------------------
# The directories are consistent.  We can now set the base virtual address of
# the executable.
#------------------------------------------------------------------------------
  $base_va_executable = $g_exp_dir_meta_data{$selected_archive}{"va_base_in_hex"}; 

  gp_message ("debug", $subr_name, "executable_name    = $executable_name");
  gp_message ("debug", $subr_name, "selected_archive = $selected_archive");
  gp_message ("debug", $subr_name, "base_va_executable = $base_va_executable");

#------------------------------------------------------------------------------
# The $GP_DISPLAY_TEXT tool is critical and has to be available in order 
# to proceed.
# This subroutine only returns a value if the tool can be found."
#------------------------------------------------------------------------------
  $g_path_to_tools = ${ check_availability_tool (\$location_gp_command)};

  $GP_DISPLAY_TEXT = $g_path_to_tools . $GP_DISPLAY_TEXT;

  gp_message ("debug", $subr_name, "updated GP_DISPLAY_TEXT = $GP_DISPLAY_TEXT");

#------------------------------------------------------------------------------
# Check if $GP_DISPLAY_TEXT is executable for user, group, and other.
# If not, print a warning only, since this may not be fatal but could
# potentially lead to issues later on.
#------------------------------------------------------------------------------
  if (not is_file_executable ($GP_DISPLAY_TEXT))
    {
      my $msg = "file $GP_DISPLAY_TEXT is not executable for user, group, and other";
      gp_message ("warning", $subr_name, $msg);
    }

#------------------------------------------------------------------------------
# Find out what the decimal separator is, as set by the user.
#------------------------------------------------------------------------------
  ($return_code, $decimal_separator, $convert_to_dot) = 
                                                determine_decimal_separator ();

  if ($return_code == 0)
    {
      my $txt  = "decimal separator is $decimal_separator " . 
                 "(conversion to dot is " .
                 ($convert_to_dot == $TRUE ? "enabled" : "disabled").")";
      gp_message ("debugXL", $subr_name, $txt);
    }
  else
    {
      my $msg = "the decimal separator cannot be determined - set to $decimal_separator";
      gp_message ("warning", $subr_name, $msg);
    }

#------------------------------------------------------------------------------
# Collect and store the system information.
#------------------------------------------------------------------------------
  gp_message ("verbose", $subr_name, "Collect system information and adapt settings");

  $return_code = get_system_config_info (); 

#------------------------------------------------------------------------------
# The 3 variables below are used in the remainder.
#
# The output from "uname -p" is recommended to be used for the ISA.
#------------------------------------------------------------------------------
  my $hostname_current = $local_system_config{hostname_current};
  my $arch_uname_s     = $local_system_config{kernel_name};
  my $arch_uname       = $local_system_config{processor};

  gp_message ("debug", $subr_name, "set hostname_current = $hostname_current");
  gp_message ("debug", $subr_name, "set arch_uname_s     = $arch_uname_s");
  gp_message ("debug", $subr_name, "set arch_uname       = $arch_uname");

#-------------------------------------------------------------------------------
# This function also sets the values in "g_arch_specific_settings".  This 
# includes several definitions of regular expressions.
#-------------------------------------------------------------------------------
  ($architecture_supported, $elf_arch, $elf_support) = 
                     set_system_specific_variables ($arch_uname, $arch_uname_s);

  gp_message ("debug", $subr_name, "architecture_supported = $architecture_supported");
  gp_message ("debug", $subr_name, "elf_arch               = $elf_arch");
  gp_message ("debug", $subr_name, "elf_support            = ".($elf_arch ? "TRUE" : "FALSE"));

  for my $feature (sort keys %g_arch_specific_settings)
    {
      gp_message ("debug", $subr_name, "g_arch_specific_settings{$feature} = $g_arch_specific_settings{$feature}");
    }

  $arch       = $g_arch_specific_settings{"arch"};
  $subexp     = $g_arch_specific_settings{"subexp"};
  $linksubexp = $g_arch_specific_settings{"linksubexp"};

  $g_locale_settings{"LANG"} =  get_LANG_setting ();

  gp_message ("debugXL", $subr_name, "after get_LANG_setting: LANG = $g_locale_settings{'LANG'}");

#------------------------------------------------------------------------------
# Temporarily reset selected settings since these are not yet implemented.
#------------------------------------------------------------------------------
  $ignore_value = reset_selected_settings ();

#------------------------------------------------------------------------------
# TBD: Revisit. Is this really necessary?
#------------------------------------------------------------------------------

  ($executable_name, $va_executable_in_hex) = check_loadobjects_are_elf ($selected_archive);
  $elf_loadobjects_found = $TRUE;

# TBD: Hack and those ARCHIVES_ names can be eliminated
  $ARCHIVES_MAP_NAME  = $executable_name;
  $ARCHIVES_MAP_VADDR = $va_executable_in_hex;
  gp_message ("debugXL", $subr_name, "hack ARCHIVES_MAP_NAME  = $ARCHIVES_MAP_NAME");
  gp_message ("debugXL", $subr_name, "hack ARCHIVES_MAP_VADDR = $ARCHIVES_MAP_VADDR");

  gp_message ("debugXL", $subr_name, "after call to check_loadobjects_are_elf forced elf_loadobjects_found = $elf_loadobjects_found");
  
  $g_html_credits_line = ${ create_html_credits () };
  gp_message ("debugXL", $subr_name, "g_html_credits_line = $g_html_credits_line");
#------------------------------------------------------------------------------
# Add a "/" to simplify the construction of path names in the remainder.
#
# TBD: Push this into a subroutine(s).
#------------------------------------------------------------------------------
  $outputdir = append_forward_slash ($outputdir);

  gp_message ("debug", $subr_name, "prepared outputdir = $outputdir");

#------------------------------------------------------------------------------
#------------------------------------------------------------------------------
# ******* TBD: e.system not available on Linux!!
#------------------------------------------------------------------------------
#------------------------------------------------------------------------------

##  my $summary_metrics       = 'e.totalcpu';
  $detail_metrics        = 'e.totalcpu';
  $detail_metrics_system = 'e.totalcpu:e.system';
  $call_metrics          = 'a.totalcpu';

  my $cmd_options; 
  my $metrics_cmd;

  my $outfile1      = $outputdir   ."metrics";
  my $outfile2      = $outputdir . "metrictotals";
  my $gp_error_file = $outputdir . $g_gp_error_logfile;

#------------------------------------------------------------------------------
# Execute the $GP_DISPLAY_TEXT tool with the appropriate options.  The goal is
# to get all the output in files $outfile1 and $outfile2.  These are then
# parsed.
#------------------------------------------------------------------------------
  gp_message ("verbose", $subr_name, "Gather the metrics data from the experiments");

  $return_code = get_metrics_data (\@exp_dir_list, $outputdir, $outfile1, $outfile2, $gp_error_file);

  if ($return_code != 0)
    {
      gp_message ("abort", $subr_name, "execution terminated");
    }

#------------------------------------------------------------------------------
# TBD: Test this code
#------------------------------------------------------------------------------
  open (METRICS, "<", $outfile1) 
    or die ("$subr_name - unable to open metric value data file $outfile1 for reading: '$!'");
  gp_message ("debug", $subr_name, "opened file $outfile1 for reading");

  chomp (@metrics_data = <METRICS>);
  close (METRICS);

  for my $i (keys @metrics_data)
    {
      gp_message ("debugXL", $subr_name, "metrics_data[$i] = $metrics_data[$i]");
    }

#------------------------------------------------------------------------------
# Process the generated metrics data.
#------------------------------------------------------------------------------
  if ($g_user_settings{"default_metrics"}{"current_value"} eq "off")

#------------------------------------------------------------------------------
# The metrics will be derived from the experiments.
#------------------------------------------------------------------------------
    {
      gp_message ("verbose", $subr_name, "Process the metrics data");

      ($metric_value_ref, $metric_description_ref, $metric_found_ref, 
       $user_metrics, $system_metrics, $wall_metrics,
       $summary_metrics, $detail_metrics, $detail_metrics_system, $call_metrics
       ) = process_metrics_data ($outfile1, $outfile2, \%ignored_metrics);

      %metric_value                = %{ $metric_value_ref };
      %metric_description          = %{ $metric_description_ref };
      %metric_found                = %{ $metric_found_ref };
      %metric_description_reversed = reverse %metric_description;

      gp_message ("debugXL", $subr_name, "after the call to process_metrics_data");
      for my $metric (sort keys %metric_value)
        {
          gp_message ("debugXL", $subr_name, "metric_value{$metric} = $metric_value{$metric}");
        }
      for my $metric (sort keys %metric_description)
        {
          gp_message ("debugXL", $subr_name, "metric_description{$metric} = $metric_description{$metric}");
        }
      gp_message ("debugXL", $subr_name, "user_metrics   = $user_metrics");
      gp_message ("debugXL", $subr_name, "system_metrics = $system_metrics");
      gp_message ("debugXL", $subr_name, "wall_metrics   = $wall_metrics");
    }
  else
    {
#------------------------------------------------------------------------------
# A default set of metrics will be used.
#
# TBD: These should be OS dependent.
#------------------------------------------------------------------------------
      gp_message ("verbose", $subr_name, "Select the set of default metrics"); 

      ($metric_description_ref, $metric_found_ref, $summary_metrics, 
       $detail_metrics, $detail_metrics_system, $call_metrics
       ) = set_default_metrics ($outfile1, \%ignored_metrics);


      %metric_description          = %{ $metric_description_ref };
      %metric_found                = %{ $metric_found_ref };
      %metric_description_reversed = reverse %metric_description;

      gp_message ("debug", $subr_name, "after the call to set_default_metrics");

    }

  $number_of_metrics = split (":", $summary_metrics);

  gp_message ("debugXL", $subr_name, "summary_metrics       = $summary_metrics");
  gp_message ("debugXL", $subr_name, "detail_metrics        = $detail_metrics");
  gp_message ("debugXL", $subr_name, "detail_metrics_system = $detail_metrics_system");
  gp_message ("debugXL", $subr_name, "call_metrics          = $call_metrics");
  gp_message ("debugXL", $subr_name, "number_of_metrics = $number_of_metrics");

#------------------------------------------------------------------------------
# TBD Find a way to better handle this situation:
#------------------------------------------------------------------------------
  for my $im (keys %metric_found)
    {
      gp_message ("debugXL", $subr_name, "metric_found{$im} = $metric_found{$im}");
    }
  for my $im (keys %ignored_metrics)
    {
      if (not exists ($metric_found{$im}))
        {
          gp_message ("debugXL", $subr_name, "user requested ignored metric (-im) $im does not exist in collected metrics");
        }
    }

#------------------------------------------------------------------------------
# Get the information on the experiments.
#------------------------------------------------------------------------------
  gp_message ("verbose", $subr_name, "Generate the experiment information");
  
  my $exp_info_file_ref;
  my $exp_info_file;
  my $exp_info_ref;
  my @exp_info;

  my $experiment_data_ref;

  $experiment_data_ref = get_experiment_info (\$outputdir, \@exp_dir_list);
  my @experiment_data = @{ $experiment_data_ref };

  for my $i (sort keys @experiment_data)
    {
      my $msg = "i = $i " . $experiment_data[$i]{"exp_id"} . " => " . 
                $experiment_data[$i]{"exp_name_full"};
      gp_message ("debugM", $subr_name, $msg);
    }

  $experiment_data_ref = process_experiment_info ($experiment_data_ref);
  @experiment_data = @{ $experiment_data_ref };

  for my $i (sort keys @experiment_data)
    {
      for my $fields (sort keys %{ $experiment_data[$i] })
        {
          my $msg = "i = $i experiment_data[$i]{$fields} = " .
                    $experiment_data[$i]{$fields};
          gp_message ("debugXL", $subr_name, $msg);
        }
    }

  @g_html_experiment_stats = @{ create_exp_info (
                                  \@exp_dir_list,
                                  \@experiment_data) };

  $table_execution_stats_ref = html_generate_exp_summary (
                                 \$outputdir, 
                                 \@experiment_data);
  @table_execution_stats = @{ $table_execution_stats_ref };

#------------------------------------------------------------------------------
# Get the function overview.
#------------------------------------------------------------------------------
  gp_message ("verbose", $subr_name, "Generate the list with functions executed");

  my ($outfile, $sort_fields_ref) = get_hot_functions (\@exp_dir_list, $summary_metrics, $outputdir);

  @sort_fields = @{$sort_fields_ref};

#------------------------------------------------------------------------------
# Parse the output from the fsummary command and store the relevant data for
# all the functions listed there.
#------------------------------------------------------------------------------

  gp_message ("verbose", $subr_name, "Analyze and store the relevant function information");

  ($function_info_ref, $function_address_and_index_ref, $addressobjtextm_ref, 
   $LINUX_vDSO_ref, $function_view_structure_ref) = get_function_info ($outfile);

  @function_info              = @{ $function_info_ref };
  %function_address_and_index = %{ $function_address_and_index_ref };
  %addressobjtextm            = %{ $addressobjtextm_ref };
  %LINUX_vDSO                 = %{ $LINUX_vDSO_ref };
  %function_view_structure    = %{ $function_view_structure_ref };

  for my $keys (0 .. $#function_info)
    {
      for my $fields (keys %{$function_info[$keys]})
        {
          gp_message ("debugXL", $subr_name,"$keys $fields $function_info[$keys]{$fields}");
        }
    }

  for my $i (keys %addressobjtextm)
    {
      gp_message ("debugXL", $subr_name,"addressobjtextm{$i} = $addressobjtextm{$i}");
    }

  gp_message ("verbose", $subr_name, "Generate the files with function overviews and the callers-callees information"); 

  $script_pc_metrics = generate_function_level_info (\@exp_dir_list, 
                                                     $call_metrics, 
                                                     $summary_metrics, 
                                                     $outputdir, 
                                                     $sort_fields_ref);

  gp_message ("verbose", $subr_name, "Preprocess the files with the function level information");

  $ignore_value = preprocess_function_files (
                    $metric_description_ref, 
                    $script_pc_metrics, 
                    $outputdir, 
                    \@sort_fields);

  gp_message ("verbose", $subr_name, "For each function, generate a set of files");

  ($function_info_ref, $function_address_info_ref, $addressobj_index_ref) = process_function_files (
                                                                            \@exp_dir_list,
                                                                            $executable_name,
                                                                            $time_percentage_multiplier,
                                                                            $summary_metrics,
                                                                            $process_all_functions,
                                                                            $elf_loadobjects_found, 
                                                                            $outputdir, 
                                                                            \@sort_fields, 
                                                                            \@function_info, 
                                                                            \%function_address_and_index,
                                                                            \%LINUX_vDSO,
                                                                            \%metric_description,
                                                                            $elf_arch,
                                                                            $base_va_executable,
                                                                            $ARCHIVES_MAP_NAME, $ARCHIVES_MAP_VADDR, \%elf_rats);

  @function_info         = @{ $function_info_ref };
  %function_address_info = %{ $function_address_info_ref };
  %addressobj_index      = %{ $addressobj_index_ref };

#-------------------------------------------------------------------------------------
# Parse the disassembly information and generate the html files.
#-------------------------------------------------------------------------------------
  gp_message ("verbose", $subr_name, "Parse the disassembly files and generate the html files");

  $ignore_value = parse_dis_files (\$number_of_metrics, \@function_info, 
                   \%function_address_and_index,
                   \$outputdir, \%addressobj_index);

#-------------------------------------------------------------------------------------
# Parse the source information and generate the html files.
#-------------------------------------------------------------------------------------
  gp_message ("verbose", $subr_name, "Parse the source files and generate the html files");

  parse_source_files (\$number_of_metrics, \@function_info, \$outputdir);

#-------------------------------------------------------------------------------------
# Parse the caller-callee information and generate the html files.
#-------------------------------------------------------------------------------------
  gp_message ("verbose", $subr_name, "Process the caller-callee information and generate the html file");

#-------------------------------------------------------------------------------------
# Generate the caller-callee information.
#-------------------------------------------------------------------------------------
  $ignore_value = generate_caller_callee (
                    \$number_of_metrics, 
                    \@function_info, 
                    \%function_view_structure,
                    \%function_address_info, 
                    \%addressobjtextm, 
                    \$outputdir);

#-------------------------------------------------------------------------------------
# Parse the calltree information and generate the html files.
#-------------------------------------------------------------------------------------
  if ($g_user_settings{"calltree"}{"current_value"} eq "on")
    {
      my $msg = "Process the call tree information and generate the html file";
      gp_message ("verbose", $subr_name, $msg);

      $ignore_value = process_calltree (
                        \@function_info, 
                        \%function_address_info, 
                        \%addressobjtextm, 
                        $outputdir);
    }

#-------------------------------------------------------------------------------------
# TBD
#-------------------------------------------------------------------------------------
  gp_message ("verbose", $subr_name, "Generate the html file with the metrics information");

  $ignore_value = process_metrics (
                    $outputdir, 
                    \@sort_fields, 
                    \%metric_description, 
                    \%ignored_metrics);

#-------------------------------------------------------------------------------------
# Generate the function view html files.
#-------------------------------------------------------------------------------------
  gp_message ("verbose", $subr_name, "Generate the function view html files");

  $html_first_metric_file_ref = generate_function_view (
                                  \$outputdir, 
                                  \$summary_metrics, 
                                  \$number_of_metrics, 
                                  \@function_info, 
                                  \%function_view_structure,
                                  \%function_address_info, 
                                  \@sort_fields, 
                                  \@exp_dir_list, 
                                  \%addressobjtextm);

  $html_first_metric_file = ${ $html_first_metric_file_ref };

  gp_message ("debugXL", $subr_name, "html_first_metric_file = $html_first_metric_file");

  my $html_test = ${ generate_home_link ("left") };
  gp_message ("debugXL", $subr_name, "html_test = $html_test");

  my $number_of_warnings_ref = create_html_warnings_page (\$outputdir);

#-------------------------------------------------------------------------------------
# Generate the index.html file.
#-------------------------------------------------------------------------------------
  gp_message ("verbose", $subr_name, "Generate the index.html file");

  $ignore_value = generate_index (\$outputdir, 
                                  \$html_first_metric_file,
                                  \$summary_metrics, 
                                  \$number_of_metrics, 
                                  \@function_info, 
                                  \%function_address_info, 
                                  \@sort_fields, 
                                  \@exp_dir_list, 
                                  \%addressobjtextm, 
                                  \%metric_description_reversed,
                                  $number_of_warnings_ref,
                                  \@table_execution_stats);

#-------------------------------------------------------------------------------------
# We're done.  In debug mode, print the meta data for the experiment directories.
#-------------------------------------------------------------------------------------
  $ignore_value = print_meta_data_experiments ("debug");

  my $results_file = $abs_path_outputdir . "/index.html";
  my $prologue_text = "Processing completed - view file $results_file in a browser";
  gp_message ("diag", $subr_name, $prologue_text);

  return (0);

} #-- End of subroutine main

#------------------------------------------------------------------------------
# Print a message after a failure in $GP_DISPLAY_TEXT.
#------------------------------------------------------------------------------
sub msg_display_text_failure
{
  my $subr_name = get_my_name ();

  my ($gp_display_text_cmd, $error_code, $error_file) = @_;

  my $msg;

  $msg = "error code = $error_code - failure executing the following command:";
  gp_message ("error", $subr_name, $msg);

  gp_message ("error", $subr_name, $gp_display_text_cmd);

  $msg = "check file $error_file for more details";
  gp_message ("error", $subr_name, $msg);

  return (0);

} #-- End of subroutine msg_display_text_failure

#------------------------------------------------------------------------------
# If it is not present, add a "/" to the name of the argument.  This is
# intended to be used for the name of the output directory and makes it 
# easier to construct pathnames.
#------------------------------------------------------------------------------
sub append_forward_slash
{
  my $subr_name = get_my_name ();

  my ($input_string) = @_;

  my $length_of_string = length ($input_string);
  my $return_string    = $input_string;

  if (rindex ($input_string, "/") != $length_of_string-1) 
    {
      $return_string .= "/";
    }

  return ($return_string);

} #-- End of subroutine append_forward_slash

#------------------------------------------------------------------------------
# Return a string with a comma separated list of directory names.
#------------------------------------------------------------------------------
sub build_pretty_dir_list
{
  my $subr_name = get_my_name ();

  my ($dir_list_ref) = @_;

  my @dir_list = @{ $dir_list_ref};

  my $pretty_dir_list = join ("\n", @dir_list);

  return ($pretty_dir_list);

} #-- End of subroutine build_pretty_dir_list

#------------------------------------------------------------------------------
# Calculate the target address in hex by adding the instruction to the 
# instruction address.
#------------------------------------------------------------------------------
sub calculate_target_hex_address
{
  my $subr_name = get_my_name ();

  my ($instruction_address, $instruction_offset) = @_;

  my $dec_branch_target; 
  my $d1;
  my $d2;
  my $first_char;
  my $length_of_string;
  my $mask;
  my $number_of_fields;
  my $raw_hex_branch_target; 
  my $result;

  if ($g_addressing_mode eq "64 bit")
    {
      $mask = "0xffffffffffffffff";
      $number_of_fields = 16;
    }
  else
    {
      gp_message ("abort", $subr_name, "g_addressing_mode = $g_addressing_mode not supported\n");
    }
  
  $length_of_string = length ($instruction_offset); 
  $first_char       = lcfirst (substr ($instruction_offset,0,1));
  $d1               = bigint::hex ($instruction_offset);
  $d2               = bigint::hex ($mask);
#          if ($first_char eq "f")
  if (($first_char =~ /[89a-f]/) and ($length_of_string == $number_of_fields))
    {
#------------------------------------------------------------------------------
# The offset is negative.  Convert to decimal and perform the subtrraction.
#------------------------------------------------------------------------------
#------------------------------------------------------------------------------
# XOR the decimal representation and add 1 to the result.
#------------------------------------------------------------------------------
      $result = ($d1 ^ $d2) + 1;
      $dec_branch_target = bigint::hex ($instruction_address) - $result;
    }
  else
    {
      $result = $d1;
      $dec_branch_target = bigint::hex ($instruction_address) + $result;
    }
#------------------------------------------------------------------------------
# Convert to hexadecimal.
#------------------------------------------------------------------------------
  $raw_hex_branch_target = sprintf ("%x", $dec_branch_target);

  return ($raw_hex_branch_target);

} #-- End of subroutine calculate_target_hex_address

#------------------------------------------------------------------------------
# Sets the absolute path to all commands in array @cmds.  The commands and 
# their respective paths are stored in hash "g_mapped_cmds".
#
# If no such mapping is found, a warning is issued, but execution continues.
# The warning(s) may help with troubleshooting, should a failure occur later.
#------------------------------------------------------------------------------
sub check_and_define_cmds
{
  my $subr_name = get_my_name ();

  my ($cmds_ref, $search_path_ref) = @_;

#------------------------------------------------------------------------------
# Dereference the array addressess first and then store the contents.
#------------------------------------------------------------------------------
  my @cmds        = @{$cmds_ref};
  my @search_path = @{$search_path_ref};

  my $found_match;
  my $target_cmd; 
  my $failed_cmd; 
  my $no_of_failed_mappings; 
  my $failed_cmds;

  gp_message ("debug", $subr_name, "\@cmds = @cmds");
  gp_message ("debug", $subr_name, "\@search_path = @search_path");

#------------------------------------------------------------------------------
# Search for the command to be in the search path given.  In case no such path
# can be found, the entry in $g_mapped_cmds is assigned a special value that
# will be checked for in the next block.
#------------------------------------------------------------------------------
  for my $cmd (@cmds)
    {
      $found_match = $FALSE;
      for my $path (@search_path)
        {
          $target_cmd = $path . "/" . $cmd; 
          if (-x $target_cmd)
            {
              $found_match = $TRUE;
              $g_mapped_cmds{$cmd} = $target_cmd;
              last;
            }
        }

      if (not $found_match)
        {
          $g_mapped_cmds{$cmd} = "road_to_nowhere";
        }
    }

#------------------------------------------------------------------------------
# Scan the results stored in $g_mapped_cmds and flag errors.
#------------------------------------------------------------------------------
  $no_of_failed_mappings = 0;
  $failed_cmds           = "";
  while ( my ($cmd, $mapped) = each %g_mapped_cmds)
    {
      if ($mapped eq "road_to_nowhere")
        {
          my $msg = "cannot find a path for command $cmd - " .
                    "assume this will still work without a path";
          gp_message ("warning", $subr_name, $msg);
          $no_of_failed_mappings++; 
          $failed_cmds .= $cmd; 
          $g_mapped_cmds{$cmd} = $cmd;
        }
      else
       {
          gp_message ("debug", $subr_name, "path for the $cmd command is $mapped");
       }
    }
  if ($no_of_failed_mappings != 0)
    {
      gp_message ("debug", $subr_name, "failed to find a mapping for $failed_cmds");
      gp_message ("debug", $subr_name, "a total of $no_of_failed_mappings mapping failures");
    }

  return ($no_of_failed_mappings);

} #-- End of subroutine check_and_define_cmds

#------------------------------------------------------------------------------
# Look for a branch instruction, or the special endbr32/endbr64 instruction
# that is also considered to be a branch target.  Note that the latter is x86
# specific.
#------------------------------------------------------------------------------
sub check_and_proc_dis_branches
{
  my $subr_name = get_my_name ();

  my ($input_line_ref, $line_no_ref,  $branch_target_ref,
      $extended_branch_target_ref, $branch_target_no_ref_ref) = @_;

  my $input_line = ${ $input_line_ref };
  my $line_no    = ${ $line_no_ref };
  my %branch_target = %{ $branch_target_ref };
  my %extended_branch_target = %{ $extended_branch_target_ref };
  my %branch_target_no_ref = %{ $branch_target_no_ref_ref };

  my $found_it = $TRUE;
  my $hex_branch_target;
  my $instruction_address;
  my $instruction_offset;
  my $msg;
  my $raw_hex_branch_target;

  if (   ($input_line =~ /$g_branch_regex/) 
      or ($input_line =~ /$g_endbr_regex/))
    {
      if (defined ($3))
        {
          $msg = "found a branch or endbr instruction: " .
                 "\$1 = $1 \$2 = $2 \$3 = $3";
        }
      else
        {
          $msg = "found a branch or endbr instruction: " .
                 "\$1 = $1 \$2 = $2";
        }
      gp_message ("debugXL", $subr_name, $msg);

      if (defined ($1))
        {
#------------------------------------------------------------------------------
# Found a qualifying instruction
#------------------------------------------------------------------------------
          $instruction_address = $1;
          if (defined ($3))
            {
#------------------------------------------------------------------------------
# This must be the branch target and needs to be converted and processed.
#------------------------------------------------------------------------------
              $instruction_offset  = $3;
              $raw_hex_branch_target = calculate_target_hex_address (
                                        $instruction_address, 
                                        $instruction_offset); 

              $hex_branch_target = "0x" . $raw_hex_branch_target;
              $branch_target{$hex_branch_target} = 1;
              $extended_branch_target{$instruction_address} = $raw_hex_branch_target;
            }
          if (defined ($2) and (not defined ($3)))
            {
#------------------------------------------------------------------------------
# Unlike a branch, the endbr32/endbr64 instructions do not have a second field.
#------------------------------------------------------------------------------
              my $instruction_name = $2;
              if ($instruction_name =~ /$g_endbr_inst_regex/)
                {
                  my $msg = "found endbr: $instruction_name " .
                            $instruction_address;
                  gp_message ("debugXL", $subr_name, $msg);
                  $raw_hex_branch_target = $instruction_address;

                  $hex_branch_target = "0x" . $raw_hex_branch_target;
                  $branch_target_no_ref{$instruction_address} = 1;
                }
            }
        }
      else
        {
#------------------------------------------------------------------------------
# TBD: Perhaps this should be an assertion or alike.
#------------------------------------------------------------------------------
          $branch_target{"0x0000"} = $FALSE;
          gp_message ("debug", $subr_name, "cannot determine branch target");
        }
    }
  else
    {
      $found_it = $FALSE;
    }

  return (\$found_it, \%branch_target, \%extended_branch_target,
         \%branch_target_no_ref);

} #-- End of subroutine check_and_proc_dis_branches

#------------------------------------------------------------------------------
# Check an input line from the disassembly file to include a function call.
# If it does, process the line and return the branch target results.
#------------------------------------------------------------------------------
sub check_and_proc_dis_func_call
{
  my $subr_name = get_my_name ();

  my ($input_line_ref, $line_no_ref,  $branch_target_ref,
      $extended_branch_target_ref) = @_;

  my $input_line = ${ $input_line_ref };
  my $line_no    = ${ $line_no_ref };
  my %branch_target = %{ $branch_target_ref };
  my %extended_branch_target = %{ $extended_branch_target_ref };

  my $found_it = $TRUE;
  my $hex_branch_target; 
  my $instruction_address;
  my $instruction_offset;
  my $msg;
  my $raw_hex_branch_target; 

  if ( $input_line =~ /$g_function_call_v2_regex/ )
    {
      $msg = "found a function call - line[$line_no] = $input_line";
      gp_message ("debugXL", $subr_name, $msg);
      if (not defined ($2))
        {
          $msg = "line[$line_no] " .
                 "an instruction address is expected, but not found";
          gp_message ("assertion", $subr_name, $msg);
        }
      else
        {
          $instruction_address = $2;

          $msg = "instruction_address = $instruction_address";
          gp_message ("debugXL", $subr_name, $msg);

          if (not defined ($4))
            {
              $msg = "line[$line_no] " .
                     "an address offset is expected, but not found";
              gp_message ("assertion", $subr_name, $msg);
            }
          else
            {
              $instruction_offset = $4;
              if ($instruction_offset =~ /[0-9a-fA-F]+/)
                {
                  $msg = "calculate branch target: " .
                         "instruction_address = $instruction_address";
                  gp_message ("debugXL", $subr_name, $msg);
                  $msg = "calculate branch target: " .
                         "instruction_offset  = $instruction_offset";
                  gp_message ("debugXL", $subr_name, $msg);

#------------------------------------------------------------------------------
# The instruction offset needs to be converted and added to the instruction
# address.
#------------------------------------------------------------------------------
                  $raw_hex_branch_target = calculate_target_hex_address (
                                            $instruction_address, 
                                            $instruction_offset); 
                  $hex_branch_target     = "0x" . $raw_hex_branch_target;

                  $msg = "calculated hex_branch_target = " .
                         $hex_branch_target;
                  gp_message ("debugXL", $subr_name, $msg);

                  $branch_target{$hex_branch_target} = 1;
                  $extended_branch_target{$instruction_address} = $raw_hex_branch_target;

                  $msg = "set branch_target{$hex_branch_target} to 1";
                  gp_message ("debugXL", $subr_name, $msg);
                  $msg  = "added extended_branch_target{$instruction_address}" .
                          " = $extended_branch_target{$instruction_address}";
                  gp_message ("debugXL", $subr_name, $msg);
                }
              else
                {
                  $msg = "line[$line_no] unknown address format";
                  gp_message ("assertion", $subr_name, $msg);
                }
            }
        }
    }
  else
    {
      $found_it = $FALSE;
    }

  return (\$found_it, \%branch_target, \%extended_branch_target);

} #-- End of subroutine check_and_proc_dis_func_call

#------------------------------------------------------------------------------
# Check for the $GP_DISPLAY_TEXT tool to be available.  This is a critical tool 
# needed to provide the information.  If it can not be found, execution is 
# terminated.
#
# We first search foe this tool in the current execution directory.  If it
# cannot be found there, use $PATH to try to locate it.
#------------------------------------------------------------------------------
sub check_availability_tool
{
  my $subr_name = get_my_name ();

  my ($location_gp_command_ref) = @_;

  my $error_code;
  my $error_occurred;
  my $msg;
  my $output_which_gp_display_text;
  my $return_value;
  my $target_cmd;

#------------------------------------------------------------------------------
# Get the path to gp-display-text.
#------------------------------------------------------------------------------
  my ($error_occurred_ref, $return_value_ref) = find_path_to_gp_display_text (
                                                       $location_gp_command_ref
                                                        );
  $error_occurred = ${ $error_occurred_ref};   
  $return_value   = ${ $return_value_ref};

  $msg = "error_occurred = $error_occurred return_value = $return_value";
  gp_message ("debugXL", $subr_name, $msg);

  if (not $error_occurred) 
#------------------------------------------------------------------------------
# All is well and gp-display-text has been located.
#------------------------------------------------------------------------------
    {
      $g_path_to_tools = $return_value;

      $msg = "located $GP_DISPLAY_TEXT in execution directory";
      gp_message ("debug", $subr_name, $msg);
      $msg = "g_path_to_tools = $g_path_to_tools";
      gp_message ("debug", $subr_name, $msg);
    }
  else
#------------------------------------------------------------------------------
# Something went wrong, but perhaps we can still continue.  Try to find
# $GP_DISPLAY_TEXT through the search path.
#------------------------------------------------------------------------------
    {
      $msg = "error accessing $GP_DISPLAY_TEXT: $return_value - " .
             "run time behaviour may be undefined";
      gp_message ("warning", $subr_name, $msg);
  
#------------------------------------------------------------------------------
# Check if we can find $GP_DISPLAY_TEXT in the search path.
#------------------------------------------------------------------------------
      $msg = "check for $GP_DISPLAY_TEXT in search path";
      gp_message ("debug", $subr_name, $msg);

      $target_cmd = $g_mapped_cmds{"which"} . " $GP_DISPLAY_TEXT 2>&1";

      ($error_code, $output_which_gp_display_text) = 
                                               execute_system_cmd ($target_cmd);
   
      if ($error_code == 0)
        {
          my ($gp_file_name, $gp_path, $suffix_not_used) = 
                                     fileparse ($output_which_gp_display_text);
          $g_path_to_tools = $gp_path;

          $msg = "using $GP_DISPLAY_TEXT in $g_path_to_tools instead";
          gp_message ("warning", $subr_name, $msg);

          $msg = "the $GP_DISPLAY_TEXT tool is in the search path";
          gp_message ("debug", $subr_name, $msg);
          $msg = "g_path_to_tools = $g_path_to_tools";
          gp_message ("debug", $subr_name, $msg);
        } 
      else
        {
          $msg = "failure to find $GP_DISPLAY_TEXT in the search path";
          gp_message ("debug", $subr_name, $msg);

          $msg = "fatal error executing command $target_cmd";
          gp_message ("abort", $subr_name, $msg);
        }
     }

  return (\$g_path_to_tools);

} #-- End of subroutine check_availability_tool

#------------------------------------------------------------------------------
# This function determines whether load objects are in ELF format.
#
# Compared to the original code, any input value other than 2 or 3 is rejected
# upfront.  This not only reduces the nesting level, but also eliminates a 
# possible bug.
#
# Also, by isolating the tests for the input files, another nesting level could
# be eliminated, further simplifying this still too complex code.
#------------------------------------------------------------------------------
sub check_loadobjects_are_elf
{
  my $subr_name = get_my_name ();

  my ($selected_archive) = @_;

  my $hostname_current = $local_system_config{"hostname_current"};
  my $arch             = $local_system_config{"processor"};
  my $arch_uname_s     = $local_system_config{"kernel_name"};

  my $extracted_information; 

  my $elf_magic_number;

  my $executable_name;
  my $va_executable_in_hex;
 
  my $arch_exp;
  my $hostname_exp;
  my $os_exp;
  my $os_exp_full;

  my $archives_file;
  my $rc_b;
  my $file;
  my $line;
  my $name;
  my $name_path;
  my $foffset;
  my $vaddr;
  my $modes;

  my $path_to_map_file; 
  my $path_to_log_file;

#------------------------------------------------------------------------------
# TBD: Parameterize and should be the first experiment directory from the list.
#------------------------------------------------------------------------------
  $path_to_log_file  = $g_exp_dir_meta_data{$selected_archive}{"directory_path"}; 
  $path_to_log_file .= $selected_archive;
  $path_to_log_file .= "/log.xml";

  gp_message ("debug", $subr_name, "hostname_current = $hostname_current");
  gp_message ("debug", $subr_name, "arch             = $arch");
  gp_message ("debug", $subr_name, "arch_uname_s     = $arch_uname_s");

#------------------------------------------------------------------------------
# TBD
#
# This check can probably be removed since the presence of the log.xml file is
# checked for in an earlier phase.
#------------------------------------------------------------------------------
  open (LOG_XML, "<", $path_to_log_file)
    or die ("$subr_name - unable to open file $path_to_log_file for reading: '$!'");
  gp_message ("debug", $subr_name, "opened file $path_to_log_file for reading");
    
  while (<LOG_XML>)
    {
      $line = $_;
      chomp ($line);
      gp_message ("debug", $subr_name, "read line: $line");
#------------------------------------------------------------------------------
# Search for the first line starting with "<system".  Bail out if found and
# parsed. These are two examples:
# <system hostname="ruud-vm" arch="x86_64" os="Linux 4.14.35-2025.400.8.el7uek.x86_64" pagesz="4096" npages="30871514">
# <system hostname="sca-m88-092-pd0" arch="sun4v" os="SunOS 5.11" pagesz="8192" npages="602963968">
#------------------------------------------------------------------------------
      if ($line =~ /^\s*<system\s+/)
        {
          gp_message ("debug", $subr_name, "selected the following line from the log.xml file:");
          gp_message ("debug", $subr_name, "$line");
          if ($line =~ /.*\s+hostname="([^"]+)/)
            {
              $hostname_exp = $1;
              gp_message ("debug", $subr_name, "extracted hostname_exp = $hostname_exp");
            }
          if ($line =~ /.*\s+arch="([^"]+)/)
            {
              $arch_exp = $1;
              gp_message ("debug", $subr_name, "extracted arch_exp = $arch_exp");
            }
          if ($line =~ /.*\s+os="([^"]+)/)
            {
              $os_exp_full = $1;
#------------------------------------------------------------------------------
# Capture the first word only.
#------------------------------------------------------------------------------
              if ($os_exp_full =~ /([^\s]+)/)
                {
                  $os_exp = $1;
                }
              gp_message ("debug", $subr_name, "extracted os_exp = $os_exp");
            }
          last;
        }
    } #-- End of while loop

  close (LOG_XML);

#------------------------------------------------------------------------------
# If the current system is identical to the system used in the experiment,
# we can return early.  Otherwise we need to dig deeper.
#
# TBD: How about the other experiment directories?! This needs to be fixed.
#------------------------------------------------------------------------------

  gp_message ("debug", $subr_name, "completed while loop");
  gp_message ("debug", $subr_name, "hostname_exp     = $hostname_exp");
  gp_message ("debug", $subr_name, "arch_exp         = $arch_exp");
  gp_message ("debug", $subr_name, "os_exp           = $os_exp");

#TBD: THIS DOES NOT CHECK IF ELF IS FOUND!

  if (($hostname_current eq $hostname_exp) and
      ($arch             eq $arch_exp)     and 
      ($arch_uname_s     eq $os_exp))
        {
          gp_message ("debug", $subr_name, "early return: the hostname, architecture and OS match the current system");
  gp_message ("debug", $subr_name, "FAKE THIS IS NOT THE CASE AND CONTINUE");
# FAKE          return ($TRUE);
        }

  if (not $g_exp_dir_meta_data{$selected_archive}{"archive_is_empty"})
    {
      gp_message ("debug", $subr_name, "selected_archive = $selected_archive");
      for my $i (sort keys %{$g_exp_dir_meta_data{$selected_archive}{"archive_files"}})
        {
          gp_message ("debug", $subr_name, "stored loadobject $i $g_exp_dir_meta_data{$selected_archive}{'archive_files'}{$i}");
        }
    }

#------------------------------------------------------------------------------
# Check if the selected experiment directory has archived files in ELF format.
# If not, use the information in map.xml to get the name of the executable 
# and the virtual address.
#------------------------------------------------------------------------------

  if ($g_exp_dir_meta_data{$selected_archive}{"archive_in_elf_format"})
    {
      gp_message ("debug", $subr_name, "the files in directory $selected_archive/archives are in ELF format");
      gp_message ("debug", $subr_name, "IGNORE THIS AND USE MAP.XML");
##      return ($TRUE);
    }

      gp_message ("debug", $subr_name, "the files in directory $selected_archive/archives are not in ELF format");

      $path_to_map_file  = $g_exp_dir_meta_data{$selected_archive}{"directory_path"}; 
      $path_to_map_file .= $selected_archive;
      $path_to_map_file .= "/map.xml";

      open (MAP_XML, "<", $path_to_map_file)
        or die ($subr_name, "unable to open file $path_to_map_file for reading: $!");
      gp_message ("debug", $subr_name, "opened file $path_to_map_file for reading");

#------------------------------------------------------------------------------
# Scan the map.xml file.  We need to find the name of the executable with the
# mode set to 0x005.  For this entry we have to capture the virtual address.
#------------------------------------------------------------------------------
    $extracted_information = $FALSE;
    while (<MAP_XML>)
    {
      $line = $_;
      chomp ($line);
      gp_message ("debug", $subr_name, "MAP_XML read line = $line");
##      if ($line =~ /^<event kind="map"\s.*vaddr="0x([0-9a-fA-F]+)"\s+                                 .*modes="0x([0-9]+)"\s.*name="(.*)".*>$/)
      if ($line =~   /^<event kind="map"\s.*vaddr="0x([0-9a-fA-F]+)"\s+.*foffset="\+*0x([0-9a-fA-F]+)"\s.*modes="0x([0-9]+)"\s.*name="(.*)".*>$/)
        {
          gp_message ("debug", $subr_name, "target line = $line");
          $vaddr     = $1;
          $foffset   = $2;
          $modes     = $3;
          $name_path = $4;
          $name      = get_basename ($name_path);
          gp_message ("debug", $subr_name, "extracted vaddr     = $vaddr foffset = $foffset modes = $modes");
          gp_message ("debug", $subr_name, "extracted name_path = $name_path name = $name");
#              $error_extracting_information = $TRUE;
          $executable_name  = $name;
          my $result_VA = bigint::hex ($vaddr) - bigint::hex ($foffset);
          my $hex_VA = sprintf ("0x%016x", $result_VA);
          $va_executable_in_hex = $hex_VA;
          gp_message ("debug", $subr_name, "set executable_name  = $executable_name");
          gp_message ("debug", $subr_name, "set va_executable_in_hex = $va_executable_in_hex");
          gp_message ("debug", $subr_name, "result_VA = $result_VA"); 
          gp_message ("debug", $subr_name, "hex_VA    = $hex_VA"); 
          if ($modes eq "005")
            {
              $extracted_information = $TRUE;
              last;
            }
        }
    }
  if (not $extracted_information)
    {
      my $msg = "cannot find the necessary information in the $path_to_map_file file";
      gp_message ("assertion", $subr_name, $msg);
    }

##  $executable_name = $ARCHIVES_MAP_NAME;
##  $va_executable_in_hex = $ARCHIVES_MAP_VADDR;

  return ($executable_name, $va_executable_in_hex);

} #-- End of subroutine check_loadobjects_are_elf

#------------------------------------------------------------------------------
# Compare the current metric values against the maximum values.  Mark the line
# if a value is within the percentage defined by $hp_value.
#------------------------------------------------------------------------------
sub check_metric_values
{
  my $subr_name = get_my_name ();

  my ($metric_values, $max_metric_values_ref) = @_;

  my @max_metric_values = @{ $max_metric_values_ref };

  my @current_metrics = ();
  my $colour_coded_line;
  my $current_value;
  my $hp_value = $g_user_settings{"highlight_percentage"}{"current_value"};
  my $max_value;
  my $relative_distance;

  @current_metrics = split (" ", $metric_values);
  $colour_coded_line = $FALSE;
  for my $metric (0 .. $#current_metrics)
    {
      $current_value = $current_metrics[$metric];
      if (exists ($max_metric_values[$metric]))
        {
          $max_value     = $max_metric_values[$metric];
          gp_message ("debugXL", $subr_name, "metric = $metric current_value = $current_value max_value = $max_value");
          if ( ($max_value > 0) and ($current_value > 0) and ($current_value != $max_value) )
            {
# TBD: abs needed?
              gp_message ("debugXL", $subr_name, "metric = $metric current_value = $current_value max_value = $max_value");
              $relative_distance = 1.00 - abs ( ($max_value - $current_value)/$max_value );
              gp_message ("debugXL", $subr_name, "relative_distance = $relative_distance");
              if ($relative_distance >= $hp_value/100.0)
                {
                  gp_message ("debugXL", $subr_name, "metric $metric is within the relative_distance");
                  $colour_coded_line = $TRUE;
                  last;
                }
            }
        }
    } #-- End of loop over metrics

  return (\$colour_coded_line);

} #-- End of subroutine check_metric_values

#------------------------------------------------------------------------------
# Check if the system is supported.
#------------------------------------------------------------------------------
sub check_support_for_processor
{
  my $subr_name = get_my_name ();

  my ($machine_ref) = @_;

  my $machine = ${ $machine_ref };
  my $is_supported;

  if ($machine eq "x86_64")
    {
      $is_supported = $TRUE;
    }
  else
    {
      $is_supported = $FALSE;
    }

  return (\$is_supported);

} #-- End of subroutine check_support_for_processor

#------------------------------------------------------------------------------
# Check if the value for the user option given is valid.
#
# In case the value is valid, the g_user_settings table is updated.
# Otherwise an error message is printed.
#
# The return value is TRUE/FALSE.
#------------------------------------------------------------------------------
sub check_user_option
{
  my $subr_name = get_my_name ();

  my ($internal_option_name, $value) = @_;

  my $message;
  my $return_value;

  my $option          = $g_user_settings{$internal_option_name}{"option"};
  my $data_type       = $g_user_settings{$internal_option_name}{"data_type"};
  my $no_of_arguments = $g_user_settings{$internal_option_name}{"no_of_arguments"};

  if (($no_of_arguments >= 1) and 
      ((not defined ($value)) or (length ($value) == 0)))
    {
#------------------------------------------------------------------------------
# If there was no value given, but it is required, flag an error.
# There could also be a value, but it might be the empty string.
#
# Note that that there are currently no options with multiple values.  Should
# these be introduced, the current check may need to be refined.
#------------------------------------------------------------------------------

      $message = "the $option option requires a value";
      push (@g_user_input_errors, $message);
      $return_value = $FALSE;
    }
  elsif ($no_of_arguments >= 1)
    {
#------------------------------------------------------------------------------
# There is an input value.  Check if it is valid and if so, store it.
#
# Note that we allow the options to be case insensitive.
#------------------------------------------------------------------------------
      my $valid = verify_if_input_is_valid ($value, $data_type);

      if ($valid)
        {
          if (($data_type eq "onoff") or ($data_type eq "size"))
            {
              $g_user_settings{$internal_option_name}{"current_value"} = lc ($value);
            }
          else
            {
              $g_user_settings{$internal_option_name}{"current_value"} = $value;
            }
          $g_user_settings{$internal_option_name}{"defined"}       = $TRUE;
          $return_value = $TRUE;
        }
      else
        {
          $message = "incorrect value for $option option: $value";
          push (@g_user_input_errors, $message);

          $return_value = $FALSE;
        }
    }

  return ($return_value);

} #-- End of subroutine check_user_option

#-------------------------------------------------------------------------------
# This subroutine performs multiple checks on the experiment directories. One 
# or more failures are fatal.
#-------------------------------------------------------------------------------
sub check_validity_exp_dirs
{
  my $subr_name = get_my_name ();

  my ($exp_dir_list_ref) = @_;

  my @exp_dir_list = @{ $exp_dir_list_ref };
 
  my %elf_rats = ();

  my $dir_not_found    = $FALSE;
  my $invalid_dir      = $FALSE;
  my $dir_check_errors = $FALSE;
  my $missing_dirs     = 0;
  my $invalid_dirs     = 0;
   
  my $archive_dir_not_empty;
  my $elf_magic_number; 
  my $archives_file;
  my $archives_dir; 
  my $first_line;
  my $count_exp_dir_not_elf;
 
  my $first_time;
  my $filename;

  my $comment;

  my $selected_archive_has_elf_format; 

  my $selected_archive;
  my $archive_dir_selected;
  my $no_of_files_in_selected_archive;

#-------------------------------------------------------------------------------
# Check if the experiment directories exist and are valid.
#-------------------------------------------------------------------------------
  for my $exp_dir (@exp_dir_list)
    {
      if (not -d $exp_dir)
        {
          $dir_not_found = $TRUE;
          $missing_dirs++;
          gp_message ("error", $subr_name, "directory $exp_dir not found");
          $dir_check_errors = $TRUE;
        }
      else
        {
#-------------------------------------------------------------------------------
# Files log.xml and map.xml have to be there.
#-------------------------------------------------------------------------------
          gp_message ("debug", $subr_name, "directory $exp_dir found");
          if ((-e $exp_dir."/log.xml") and (-e $exp_dir."/map.xml"))
            {
              gp_message ("debug", $subr_name, "directory $exp_dir appears to be a valid experiment directory");
            }
          else
            {
              $invalid_dir = $TRUE;
              $invalid_dirs++; 
              gp_message ("debug", $subr_name, "file ".$exp_dir."/log.xml and/or ".$exp_dir."/map.xml missing");
              gp_message ("error"  , $subr_name, "directory $exp_dir does not appear to be a valid experiment directory");
              $dir_check_errors = $TRUE;
            }
        }
    }
  if ($dir_not_found)
    {
      gp_message ("error", $subr_name, "a total of $missing_dirs directories not found");
    }
  if ($invalid_dir)
    {
      gp_message ("abort", $subr_name, "a total of $invalid_dirs directories are not valid");
    }

#-------------------------------------------------------------------------------
# Initialize ELF status to FALSE.
#-------------------------------------------------------------------------------
##  for my $exp_dir (@exp_dir_list)
  for my $exp_dir (keys %g_exp_dir_meta_data)
    {
      $g_exp_dir_meta_data{$exp_dir}{"elf_format"} = $FALSE; 
      $g_exp_dir_meta_data{$exp_dir}{"archive_in_elf_format"} = $FALSE; 
    }
#-------------------------------------------------------------------------------
# Check if the load objects are in ELF format.
#-------------------------------------------------------------------------------
  for my $exp_dir (keys %g_exp_dir_meta_data)
    {
      $archives_dir = $g_exp_dir_meta_data{$exp_dir}{"directory_path"} .  $exp_dir . "/archives";
      $archive_dir_not_empty = $FALSE;
      $first_time            = $TRUE;
      $g_exp_dir_meta_data{$exp_dir}{"archive_is_empty"} = $TRUE;
      $g_exp_dir_meta_data{$exp_dir}{"no_of_files_in_archive"} = 0;

      gp_message ("debug", $subr_name, "g_exp_dir_meta_data{$exp_dir}{'archive_is_empty'} = $g_exp_dir_meta_data{$exp_dir}{'archive_is_empty'}");
      gp_message ("debug", $subr_name, "checking $archives_dir");

      while (glob ("$archives_dir/*"))
        {
          $filename = get_basename ($_);
          gp_message ("debug", $subr_name, "processing file: $filename");

          $g_exp_dir_meta_data{$exp_dir}{"archive_files"}{$filename} = $TRUE;
          $g_exp_dir_meta_data{$exp_dir}{"no_of_files_in_archive"}++;

          $archive_dir_not_empty = $TRUE;
#-------------------------------------------------------------------------------
# Replaces the ELF_RATS part in elf_phdr.
#
# Challenge:  splittable_mrg.c_I0txnOW_Wn5
#
# TBD: Store this for each relevant experiment directory.
#-------------------------------------------------------------------------------
          my $last_dot              = rindex ($filename,".");
          my $underscore_before_dot = $TRUE;
          my $first_underscore      = -1;
          gp_message ("debugXL", $subr_name, "last_dot = $last_dot");
          while ($underscore_before_dot)
            {
              $first_underscore = index ($filename, "_", $first_underscore+1);
              if ($last_dot < $first_underscore)
                {
                  $underscore_before_dot = $FALSE;
                }
            }
          my $original_name  = substr ($filename, 0, $first_underscore);
          gp_message ("debug", $subr_name, "stripped archive name: $original_name");
          if (not exists ($elf_rats{$original_name}))
            {
              $elf_rats{$original_name} = [$filename, $exp_dir];
            }
#-------------------------------------------------------------------------------
# We only need to detect the presence of an object once.
#-------------------------------------------------------------------------------
          if ($first_time)
            {
              $first_time = $FALSE;
              $g_exp_dir_meta_data{$exp_dir}{"archive_is_empty"} = $FALSE;
              gp_message ("debugXL", $subr_name, "g_exp_dir_meta_data{$exp_dir}{'archive_is_empty'} = $g_exp_dir_meta_data{$exp_dir}{'archive_is_empty'}");
            }
        }
    } #-- End of loop over experiment directories

  for my $exp_dir (sort keys %g_exp_dir_meta_data)
    {
      my $empty = $g_exp_dir_meta_data{$exp_dir}{"archive_is_empty"}; 
      gp_message ("debug", $subr_name, "archive directory $exp_dir/archives is ".($empty ? "empty" : "not empty"));
    }

#------------------------------------------------------------------------------
# Verify that all relevant files in the archive directories are in ELF format.
#------------------------------------------------------------------------------
  for my $exp_dir (sort keys %g_exp_dir_meta_data)
    {
      $g_exp_dir_meta_data{$exp_dir}{"archive_in_elf_format"} = $FALSE; 
      if (not $g_exp_dir_meta_data{$exp_dir}{"archive_is_empty"})
        {
          $archives_dir = $g_exp_dir_meta_data{$exp_dir}{"directory_path"} .  $exp_dir . "/archives";
          gp_message ("debug", $subr_name, "exp_dir = $exp_dir archives_dir = $archives_dir");
#------------------------------------------------------------------------------
# Check if any of the loadobjects is of type ELF.  Bail out on the first one
# found.  The assumption is that all other loadobjects must be of type ELF too
# then.
#------------------------------------------------------------------------------
          for my $aname (sort keys %{$g_exp_dir_meta_data{$exp_dir}{"archive_files"}})
            {
              $filename = $g_exp_dir_meta_data{$exp_dir}{"directory_path"} . $exp_dir . "/archives/" . $aname;
              open (ARCF,"<", $filename)
                or die ("unable to open file $filename for reading - '$!'");

              $first_line = <ARCF>;
              close (ARCF);

#------------------------------------------------------------------------------
# The first 4 hex fields in the header of an ELF file are: 7F 45 4c 46 (7FELF).
#
# See also https://en.wikipedia.org/wiki/Executable_and_Linkable_Format
#------------------------------------------------------------------------------
#              if ($first_line =~ /^\177ELF.*/)

              $elf_magic_number = unpack ('H8', $first_line);
#              gp_message ("debug", $subr_name, "elf_magic_number = $elf_magic_number");
              if ($elf_magic_number eq "7f454c46")
                {
                  $g_exp_dir_meta_data{$exp_dir}{"archive_in_elf_format"} = $TRUE; 
                  $g_exp_dir_meta_data{$exp_dir}{"elf_format"} = $TRUE;
                  last;
                }
            }
        }
    }

  for my $exp_dir (sort keys %g_exp_dir_meta_data)
    {
      $comment = "the loadobjects in the archive in $exp_dir are ";
      $comment .= ($g_exp_dir_meta_data{$exp_dir}{"archive_in_elf_format"}) ? "in " : "not in ";
      $comment .= "ELF format";
      gp_message ("debug", $subr_name, $comment);
    }
  for my $exp_dir (sort keys %g_exp_dir_meta_data)
    {
      if ($g_exp_dir_meta_data{$exp_dir}{"archive_is_empty"})
        {
          gp_message ("debug", $subr_name, "there are no archived files in $exp_dir");
        }
    }

#------------------------------------------------------------------------------
# If there are archived files and they are not in ELF format, a debug is
# issued.
#
# TBD: Bail out?
#------------------------------------------------------------------------------
  $count_exp_dir_not_elf = 0;
  for my $exp_dir (sort keys %g_exp_dir_meta_data)
    {
      if (not $g_exp_dir_meta_data{$exp_dir}{"archive_in_elf_format"})
        {
          $count_exp_dir_not_elf++; 
        }
    }
  if ($count_exp_dir_not_elf != 0)
    {
      gp_message ("debug", $subr_name, "there are $count_exp_dir_not_elf experiments with non-ELF load objects");
    }

#------------------------------------------------------------------------------
# Select the experiment directory that is used for the files in the archive.
# By default, a directory with archived files is used, but in case this does
# not exist, a directory without archived files is selected.  Obviously this
# needs to be dealt with later on.
#------------------------------------------------------------------------------

#------------------------------------------------------------------------------
# Try the experiments with archived files first.
#------------------------------------------------------------------------------
  $archive_dir_not_empty = $FALSE;
  $archive_dir_selected  = $FALSE;
##  for my $exp_dir (sort @exp_dir_list)
  for my $exp_dir (sort keys %g_exp_dir_meta_data)
    {
      gp_message ("debugXL", $subr_name, "exp_dir = $exp_dir");
      gp_message ("debugXL", $subr_name, "g_exp_dir_meta_data{$exp_dir}{'archive_is_empty'}");

      if (not $g_exp_dir_meta_data{$exp_dir}{"archive_is_empty"})
        {
          $selected_archive      = $exp_dir;
          $archive_dir_not_empty = $TRUE;
          $archive_dir_selected  = $TRUE;
          $selected_archive_has_elf_format = ($g_exp_dir_meta_data{$exp_dir}{"archive_in_elf_format"}) ? $TRUE : $FALSE;
          last;
        }
    }
  if (not $archive_dir_selected) 
#------------------------------------------------------------------------------
# None are found and pick the first one without archived files.
#------------------------------------------------------------------------------
    {
      for my $exp_dir (sort keys %g_exp_dir_meta_data)
        {
          if ($g_exp_dir_meta_data{$exp_dir}{"archive_is_empty"})
            {
              $selected_archive      = $exp_dir;
              $archive_dir_not_empty = $FALSE;
              $archive_dir_selected  = $TRUE;
              $selected_archive_has_elf_format = $FALSE;
              last;
            }
        }
    }
  gp_message ("debug", $subr_name, "experiment $selected_archive has been selected for archive analysis");
  gp_message ("debug", $subr_name, "this archive is ". (($archive_dir_not_empty) ? "not empty" : "empty"));
  gp_message ("debug", $subr_name, "this archive is ". (($selected_archive_has_elf_format) ? "in" : "not in")." ELF format");
#------------------------------------------------------------------------------
# Get the size of the hash that contains the archived files.
#------------------------------------------------------------------------------
##  $NO_OF_FILES_IN_ARCHIVE = scalar (keys %ARCHIVES_FILES);

  $no_of_files_in_selected_archive = $g_exp_dir_meta_data{$selected_archive}{"no_of_files_in_archive"};
  gp_message ("debug", $subr_name, "number of files in archive $selected_archive is $no_of_files_in_selected_archive");


  for my $exp_dir (sort keys %g_exp_dir_meta_data)
    {
      my $is_empty = $g_exp_dir_meta_data{$exp_dir}{"archive_is_empty"};
      gp_message ("debug", $subr_name, "archive directory $exp_dir/archives is ".($is_empty ? "empty" : "not empty"));
    }
  for my $exp_dir (sort keys %g_exp_dir_meta_data)
    {
      if (not $g_exp_dir_meta_data{$exp_dir}{"archive_is_empty"})
        {
          for my $object (sort keys %{$g_exp_dir_meta_data{$exp_dir}{"archive_files"}})
            {
              gp_message ("debug", $subr_name, "$exp_dir $object $g_exp_dir_meta_data{$exp_dir}{'archive_files'}{$object}");
            }
        }
    }

  return ($dir_check_errors, $archive_dir_not_empty, $selected_archive, \%elf_rats);

} #-- End of subroutine check_validity_exp_dirs

#------------------------------------------------------------------------------
# Color the string and optionally mark it boldface.
#
# For supported colors, see:
# https://www.w3schools.com/colors/colors_names.asp
#------------------------------------------------------------------------------
sub color_string
{
  my $subr_name = get_my_name ();

  my ($input_string, $boldface, $color) = @_;

  my $colored_string;

  $colored_string = "<font color='" . $color . "'>";

  if ($boldface)
    {
      $colored_string .= "<b>";
    }

  $colored_string .= $input_string;

  if ($boldface)
    {
      $colored_string .= "</b>";
    }
  $colored_string .= "</font>"; 

  return ($colored_string);

} #-- End of subroutine color_string

#------------------------------------------------------------------------------
# Generate the array with the info on the experiment(s).
#------------------------------------------------------------------------------
sub create_exp_info
{
  my $subr_name = get_my_name ();

  my ($experiment_dir_list_ref, $experiment_data_ref) = @_;

  my @experiment_dir_list = @{ $experiment_dir_list_ref };
  my @experiment_data     = @{ $experiment_data_ref };

  my @experiment_stats_html = ();
  my $experiment_stats_line; 
  my $plural;

  $plural = ($#experiment_dir_list > 0) ? "s:" : ":";

  $experiment_stats_line  = "<h3>\n";
  $experiment_stats_line .= "Full pathnames to the input experiment" . $plural . "\n";
  $experiment_stats_line .= "</h3>\n";
  $experiment_stats_line .= "<pre>\n";

  for my $i (0 .. $#experiment_dir_list)
    {
      $experiment_stats_line .= $experiment_dir_list[$i] . " (" . $experiment_data[$i]{"start_date"} . ")\n";
    }
  $experiment_stats_line .= "</pre>\n";

  push (@experiment_stats_html, $experiment_stats_line);

  gp_message ("debugXL", $subr_name, "experiment_stats_line = $experiment_stats_line --");

  return (\@experiment_stats_html);

} #-- End of subroutine create_exp_info

#------------------------------------------------------------------------------
# Trivial function to generate a tag.  This has been made a function to ensure
# consistency creating tags and also make it easier to change them.
#------------------------------------------------------------------------------
sub create_function_tag
{
  my $subr_name = get_my_name ();

  my ($tag_id) = @_;

  my $function_tag = "function_tag_" . $tag_id;

  return ($function_tag);

} #-- End of subroutine create_function_tag

#------------------------------------------------------------------------------
# Generate and return a string with the credits.  Note that this also ends
# the HTML formatting controls.
#------------------------------------------------------------------------------
sub create_html_credits
{
  my $subr_name = get_my_name ();

  my $msg;
  my $the_date;

  my @months = qw (January February March April May June July August September October November December); 

  my ($sec, $min, $hour, $mday, $mon, $year, $wday, $yday, $isdst) = localtime ();

  $year += 1900;

  $the_date = $months[$mon] . " " . $mday . ", " . $year;

  $msg  = "<i>\n";
  $msg .= "Output generated by the $driver_cmd command ";
  $msg .= "on $the_date ";
  $msg .= "(GNU binutils version " . $binutils_version . ")";
  $msg .= "\n";
  $msg .= "</i>";

  gp_message ("debug", $subr_name, "the date = $the_date");

  return (\$msg);

} #-- End of subroutine create_html_credits

#------------------------------------------------------------------------------
# Generate a string that contains all the necessary HTML header information,
# plus a title.
#
# See also https://www.w3schools.com for the details on the features used.
#------------------------------------------------------------------------------
sub create_html_header
{
  my $subr_name = get_my_name ();

  my ($title_ref) = @_;

   my $title = ${ $title_ref };

  my $LANG = $g_locale_settings{"LANG"};
  my $background_color = $g_html_color_scheme{"background_color_page"}; 

  my $html_header; 

  $html_header  = "<!DOCTYPE html public \"-//w3c//dtd html 3.2//en\">\n";
  $html_header .= "<html lang=\"$LANG\">\n";
  $html_header .= "<head>\n";
  $html_header .= "<meta http-equiv=\"content-type\" content=\"text/html; charset=iso-8859-1\">\n";
  $html_header .= "<title>" . $title . "</title>\n";
  $html_header .= "</head>\n";
  $html_header .= "<body lang=\"$LANG\" bgcolor=". $background_color . ">\n"; 
  $html_header .= "<style>\n";
  $html_header .= "div.left {\n";
  $html_header .= "text-align: left;\n";
  $html_header .= "}\n";
  $html_header .= "div.right {\n";
  $html_header .= "text-align: right;\n";
  $html_header .= "}\n";
  $html_header .= "div.center {\n";
  $html_header .= "text-align: center;\n";
  $html_header .= "}\n";
  $html_header .= "div.justify {\n";
  $html_header .= "text-align: justify;\n";
  $html_header .= "}\n";
  $html_header .= "</style>";

  return (\$html_header);

} #-- End of subroutine create_html_header

#------------------------------------------------------------------------------
# Create an HTML page with the warnings.  If there are no warnings, include
# line to this extent.  The alternative is to supporess the entire page, but
# that breaks the consistency in the output.
#------------------------------------------------------------------------------
sub create_html_warnings_page
{
  my $subr_name = get_my_name ();

  my ($outputdir_ref) = @_;

  my $outputdir = ${ $outputdir_ref };

  my $file_title;
  my $html_acknowledgement;
  my $html_end;
  my $html_header;
  my $html_home_left;
  my $html_home_right;
  my $html_title_header;
  my $msg_no_warnings = "There are no warning messages issued.";
  my $page_title;
  my $position_text;
  my $size_text;
 
  my $outfile = $outputdir . $g_html_base_file_name{"warnings"} . ".html";

  gp_message ("debug", $subr_name, "outfile = $outfile");

  open (WARNINGS_OUT, ">", $outfile)
    or die ("unable to open $outfile for writing - '$!'");
  gp_message ("debug", $subr_name, "opened file $outfile for writing");

  gp_message ("debug", $subr_name, "building warning file $outfile");

#------------------------------------------------------------------------------
# Get the number of warnings and in debug mode, print the list. 
#------------------------------------------------------------------------------
  my $number_of_warnings = scalar (@g_warning_messages);
  gp_message ("debug", $subr_name, "number_of_warnings = $number_of_warnings");
  
  if ($number_of_warnings > 0)
    {
      for my $i (0 .. $#g_warning_messages)
        {
          print "$g_warning_messages[$i]\n";
          my $msg = "g_warning_messages[$i] = $g_warning_messages[$i]";
          gp_message ("debug", $subr_name, $msg);
        }
    }

#------------------------------------------------------------------------------
# Generate some of the structures used in the HTML output.
#------------------------------------------------------------------------------
  $file_title  = "Warning messages";
  $html_header = ${ create_html_header (\$file_title) };
  $html_home_right   = ${ generate_home_link ("right") };

  $page_title    = "Warning Messages";
  $size_text     = "h2"; 
  $position_text = "center";
  $html_title_header = ${ generate_a_header (\$page_title, \$size_text, \$position_text) };
  
#-------------------------------------------------------------------------------
# Get the acknowledgement, return to main link, and final html statements.
#-------------------------------------------------------------------------------
  $html_home_left       = ${ generate_home_link ("left") };
  $html_acknowledgement = ${ create_html_credits () };
  $html_end             = ${ terminate_html_document () };

#-------------------------------------------------------------------------------
# Generate the HTML file.
#-------------------------------------------------------------------------------
  print WARNINGS_OUT $html_header;
  print WARNINGS_OUT $html_home_right;
  print WARNINGS_OUT $html_title_header;

  if ($number_of_warnings > 0)
    {
      print WARNINGS_OUT "<pre>\n";
      print WARNINGS_OUT "$_\n" for @g_warning_messages;
      print WARNINGS_OUT "</pre>\n";
    }
  else
    {
      print WARNINGS_OUT $msg_no_warnings;
    }

  print WARNINGS_OUT $html_home_left;
  print WARNINGS_OUT "<br>\n";
  print WARNINGS_OUT $html_acknowledgement;
  print WARNINGS_OUT $html_end;

  close (WARNINGS_OUT);

  return (\$number_of_warnings);

} #-- End of subroutine create_html_warnings_page

#-------------------------------------------------------------------------------
# Create a complete table.
#-------------------------------------------------------------------------------
sub create_table
{
  my $subr_name = get_my_name ();

  my ($experiment_data_ref, $table_definition_ref) = @_;
 
  my @experiment_data  = @{ $experiment_data_ref };
  my @table_definition = @{ $table_definition_ref };

  my @html_exp_table_data = ();
  my $html_header_line;
  my $html_table_line;
  my $html_end_table;

  $html_header_line = ${ create_table_header_exp (\@experiment_data) };

  push (@html_exp_table_data, $html_header_line);

  for my $i (sort keys @table_definition)
    {
      $html_table_line = ${ create_table_entry_exp (\$table_definition[$i]{"name"}, 
                              \$table_definition[$i]{"key"}, \@experiment_data) };
      push (@html_exp_table_data, $html_table_line);

      my $msg = "i = $i html_table_line = $html_table_line";
      gp_message ("debugXL", $subr_name, $msg);
    }

  $html_end_table  = "</table>\n";
  push (@html_exp_table_data, $html_end_table);

  return (\@html_exp_table_data);

} #-- End of subroutine create_table

#-------------------------------------------------------------------------------
# Create one row for the table with experiment info.
#-------------------------------------------------------------------------------
sub create_table_entry_exp
{
  my $subr_name = get_my_name ();

  my ($entry_name_ref, $key_ref, $experiment_data_ref) = @_;

  my $entry_name       = ${ $entry_name_ref };
  my $key              = ${ $key_ref };
  my @experiment_data  = @{ $experiment_data_ref };

  gp_message ("debugXL", $subr_name, "entry_name = $entry_name key = $key");

  my $html_line;

  $html_line  = "<tr><div class=\"left\"><td><b>&nbsp; ";
  $html_line  = "<tr><div class=\"right\"><td><b>&nbsp; ";
  $html_line .= $entry_name;
  $html_line .= " &nbsp;</b></td>";
  for my $i (sort keys @experiment_data)
    {
      if (exists ($experiment_data[$i]{$key}))
        {
          $html_line .= "<td>&nbsp; " . $experiment_data[$i]{$key} . " &nbsp;</td>";
        }
      else
        {
##          gp_message ("assertion", $subr_name, "experiment_data[$i]{$key} does not exist");
          gp_message ("warning", $subr_name, "experiment_data[$i]{$key} does not exist");
        }
    }
  $html_line .= "</div></tr>\n";

  gp_message ("debugXL", $subr_name, "return html_line = $html_line");

  return (\$html_line);

} #-- End of subroutine create_table_entry_exp

#-------------------------------------------------------------------------------
# Create the table header for the experiment info.
#-------------------------------------------------------------------------------
sub create_table_header_exp
{
  my $subr_name = get_my_name ();

  my ($experiment_data_ref) = @_;

  my @experiment_data = @{ $experiment_data_ref };
  my $html_header_line;

  $html_header_line  = "<style>\n";
  $html_header_line .= "table, th, td {\n";
  $html_header_line .= "border: 1px solid black;\n";
  $html_header_line .= "border-collapse: collapse;\n";
  $html_header_line .= "}\n";
  $html_header_line .= "</style>\n";
  $html_header_line .= "</pre>\n";
  $html_header_line .= "<table>\n";
  $html_header_line .= "<tr><div class=\"center\"><th></th>";

  for my $i (sort keys @experiment_data)
    {
      $html_header_line .= "<th>&nbsp; Experiment ID " . $experiment_data[$i]{"exp_id"} . "&nbsp;</th>";
    }
  $html_header_line .= "</div></tr>\n";

  gp_message ("debugXL", $subr_name, "html_header_line = $html_header_line");

  return (\$html_header_line);

} #-- End of subroutine create_table_header_exp

#-------------------------------------------------------------------------------
# Handle where the output should go. If needed, a directory is created where 
# the results will go.
#-------------------------------------------------------------------------------
sub define_the_output_directory
{
  my $subr_name = get_my_name ();

  my ($define_new_output_dir, $overwrite_output_dir) = @_;

  my $outputdir;

#-------------------------------------------------------------------------------
# If neither -o or -O are set, find the next number to be used in the name for 
# the default output directory.
#-------------------------------------------------------------------------------
  if ((not $define_new_output_dir) and (not $overwrite_output_dir))
    {
      my $dir_id = 1;
      while (-d "er.".$dir_id.".html") 
        { $dir_id++; }
      $outputdir = "er.".$dir_id.".html";
    }

  if (-d $outputdir)
    {
#-------------------------------------------------------------------------------
# The -o option is used, but the directory already exists.
#-------------------------------------------------------------------------------
      if ($define_new_output_dir)
        {
          gp_message ("error", $subr_name, "directory $outputdir already exists");
          gp_message ("abort", $subr_name, "use the -O option to overwrite an existing directory");
        }
#-------------------------------------------------------------------------------
# This is a bit risky, so we proceed with caution. The output directory exists,
# but it is okay to overwrite it. It is removed here and created again below.
#-------------------------------------------------------------------------------
      elsif ($overwrite_output_dir)
        {
          my $target_cmd = $g_mapped_cmds{"rm"};
          my $rm_output  = qx ($target_cmd -rf $outputdir);
          my $error_code = ${^CHILD_ERROR_NATIVE};
          if ($error_code != 0)
            {
              gp_message ("error", $subr_name, $rm_output);
              gp_message ("abort", $subr_name, "fatal error when trying to remove $outputdir");
            }
          else
            {
              gp_message ("debug", $subr_name, "directory $outputdir has been removed");
            }
        }
    }
#-------------------------------------------------------------------------------
# When we get here, the fatal scenarios have been cleared and the name for 
# $outputdir is known. Time to create it.
#-------------------------------------------------------------------------------
  if (mkdir ($outputdir, 0777))
    {
      gp_message ("debug", $subr_name, "created output directory $outputdir");
    }
  else 
    {
      gp_message ("abort", $subr_name, "a fatal problem occurred when creating directory $outputdir");
    }

  return ($outputdir);

} #-- End of subroutine define_the_output_directory

#------------------------------------------------------------------------------
# Return the virtual address for the load object.
#
# Note that at this point, $elf_arch is known to be supported.
#
# TBD: Duplications?
#------------------------------------------------------------------------------
sub determine_base_va_address
{
  my $subr_name = get_my_name ();

  my ($executable_name, $base_va_executable, $loadobj, $routine) = @_;

  my $name_loadobject;
  my $base_va_address;

  gp_message ("debugXL", $subr_name, "base_va_executable = $base_va_executable"); 
  gp_message ("debugXL", $subr_name, "loadobj = $loadobj"); 
  gp_message ("debugXL", $subr_name, "routine = $routine");

#------------------------------------------------------------------------------
# Strip the pathname from the load object name.
#------------------------------------------------------------------------------
  $name_loadobject = get_basename ($loadobj);

#------------------------------------------------------------------------------
# If the load object is the executable, return the base address determined 
# earlier.  Otherwise return 0x0.  Note that I am not sure if this is always
# the right thing to do, but for .so files it seems to work out fine.
#------------------------------------------------------------------------------
  if ($name_loadobject eq $executable_name)
    {
      $base_va_address = $base_va_executable;
    }
  else
    {
      $base_va_address = "0x0";
    }
   
  my $decimal_address = bigint::hex ($base_va_address);
  gp_message ("debugXL", $subr_name, "return base_va_address = $base_va_address (decimal: $decimal_address)");

  return ($base_va_address);

} #-- End of subroutine determine_base_va_address

#-------------------------------------------------------------------------------
# Now that we know the map.xml file(s) are present, we can scan these and get
# the required information.
#-------------------------------------------------------------------------------
sub determine_base_virtual_address
{
  my $subr_name = get_my_name ();

  my ($exp_dir_list_ref) = @_;

  my @exp_dir_list   = @{ $exp_dir_list_ref };

  my $full_path_exec;
  my $executable_name;
  my $va_executable_in_hex;

  my $path_to_map_file; 

  for my $exp_dir (keys %g_exp_dir_meta_data)
    {
      $path_to_map_file  = $g_exp_dir_meta_data{$exp_dir}{"directory_path"}; 
      $path_to_map_file .= $exp_dir;
      $path_to_map_file .= "/map.xml";

      ($full_path_exec, $executable_name, $va_executable_in_hex) = extract_info_from_map_xml ($path_to_map_file);

      $g_exp_dir_meta_data{$exp_dir}{"full_path_exec"} = $full_path_exec;
      $g_exp_dir_meta_data{$exp_dir}{"exec_name"}      = $executable_name;
      $g_exp_dir_meta_data{$exp_dir}{"va_base_in_hex"} = $va_executable_in_hex;

      gp_message ("debug", $subr_name, "exp_dir              = $exp_dir");
      gp_message ("debug", $subr_name, "full_path_exece      = $full_path_exec");
      gp_message ("debug", $subr_name, "executable_name      = $executable_name");
      gp_message ("debug", $subr_name, "va_executable_in_hex = $va_executable_in_hex");
    }

  return (0);

} #-- End of subroutine determine_base_virtual_address

#------------------------------------------------------------------------------
# Determine whether the decimal separator is a point or a comma.
#------------------------------------------------------------------------------
sub determine_decimal_separator
{
  my $subr_name = get_my_name ();

  my $ignore_count;
  my $decimal_separator;
  my $convert_to_dot;
  my $field;
  my $target_found; 
  my $error_code;
  my $cmd_output;
  my $target_cmd;
  my @locale_info;

  my $default_decimal_separator = "\\.";

  $target_cmd  = $g_mapped_cmds{locale} . " -k LC_NUMERIC";
  ($error_code, $cmd_output) = execute_system_cmd ($target_cmd);
   
  if ($error_code != 0)
#-------------------------------------------------------------------------------
# This is unlikely to happen, but you never know.  To reduce the nesting level,
# return right here in case of an error.
#-------------------------------------------------------------------------------
    {
      gp_message ("error", $subr_name, "failure to execute the command $target_cmd");
      
      $convert_to_dot = $TRUE;

      return ($error_code, $default_decimal_separator, $convert_to_dot);
    }

#-------------------------------------------------------------------------------
# Scan the locale info and search for the target line of the form 
# decimal_point="<target>" where <target> is either a dot, or a comma.
#-------------------------------------------------------------------------------

#-------------------------------------------------------------------------------
# Split the output into the different lines and scan for the line we need.
#-------------------------------------------------------------------------------
  @locale_info  = split ("\n", $cmd_output);
  $target_found = $FALSE;
  for my $line (@locale_info) 
    {
      chomp ($line);
      gp_message ("debug", $subr_name, "line from locale_info = $line");
      if ($line =~ /decimal_point=/) 
        {

#-------------------------------------------------------------------------------
# Found the target line. Split this line to get the value field.
#-------------------------------------------------------------------------------
          my @split_line = split ("=", $line); 

#-------------------------------------------------------------------------------
# There should be 2 fields. If not, something went wrong.
#-------------------------------------------------------------------------------
          if (scalar @split_line != 2) 
            {
#     if (scalar @split_line == 2) {
#        $target_found    = $FALSE;
#-------------------------------------------------------------------------------
# Remove the newline before printing the variables.
#-------------------------------------------------------------------------------
              $ignore_count = chomp ($line);
              $ignore_count = chomp (@split_line);
              gp_message ("debug", $subr_name, "warning - line $line matches the search, but the decimal separator has the wrong format");
              gp_message ("debug", $subr_name, "warning - the splitted line is [@split_line] and does not contain 2 fields");
              gp_message ("debug", $subr_name, "warning - the default decimal separator will be used");
            }
          else
            {
#-------------------------------------------------------------------------------
# We know there are 2 fields and the second one has the decimal point.
#-------------------------------------------------------------------------------
              gp_message ("debug", $subr_name, "split_line[1] = $split_line[1]");

              chomp ($split_line[1]);
              $field = $split_line[1];

              if (length ($field) != 3)
#-------------------------------------------------------------------------------
# The field still includes the quotes.  Check if the string has length 3, which
# should be the case, but if not, we flag an error.  The error code is set such
# that the callee will know a problem has occurred.
#-------------------------------------------------------------------------------
                {
                  gp_message ("error", $subr_name, "unexpected output from the $target_cmd command: $field");
                  $error_code = 1;
                  last;
                }

              gp_message ("debug", $subr_name, "field = ->$field<-");

              if (($field eq "\".\"") or ($field eq "\",\""))
#-------------------------------------------------------------------------------
# Found the separator.  Capture the character between the quotes. 
#-------------------------------------------------------------------------------
                {
                  $target_found      = $TRUE;
                  $decimal_separator = substr ($field,1,1);
                  gp_message ("debug", $subr_name, "decimal_separator = $decimal_separator--end skip loop");
                  last;
                }
            }
        }
    }
  if (not $target_found) 
    {
      $decimal_separator = $default_decimal_separator;
      gp_message ("warning", $subr_name, "cannot determine the decimal separator - use the default $decimal_separator");
    } 

  if ($decimal_separator ne ".")
    {
      $convert_to_dot = $TRUE;
    }
  else
    {
      $convert_to_dot = $FALSE;
    }

  $decimal_separator = "\\".$decimal_separator;
  $g_locale_settings{"decimal_separator"} = $decimal_separator;
  $g_locale_settings{"convert_to_dot"}    = $convert_to_dot;

  return ($error_code, $decimal_separator, $convert_to_dot);

} #-- End of subroutine determine_decimal_separator

#------------------------------------------------------------------------------
# TBD
#------------------------------------------------------------------------------
sub dump_function_info
{
  my $subr_name = get_my_name ();

  my ($function_info_ref, $name) = @_;

  my %function_info = %{$function_info_ref};
  my $kip;

  gp_message ("debug", $subr_name, "function_info for $name");
  $kip = 0;
  for my $farray ($function_info{$name})
    {
      for my $elm (@{$farray})
        {
          gp_message ("debug", $subr_name, "$kip: routine = ${$elm}{'routine'}");
          for my $key (sort keys %{$elm})
            {
              if ($key eq "routine")
                {
                  next;
                }
              gp_message ("debug", $subr_name, "$kip: $key = ${$elm}{$key}");
            }
          $kip++;
        }
    }

  return (0);

} #-- End of subroutine dump_function_info

#------------------------------------------------------------------------------
# This is an early scan to find the settings for some options very early on. 
# For practical reasons the main option parsing and handling is done later, 
# but without this early scan, these options will not be enabled until later
# in the execution.
#
# This early scan fixes that, but it is not very elegant to do it this way
# and in the future, this will be improved.  For now it gets the job done.
#------------------------------------------------------------------------------
sub early_scan_specific_options
{
  my $subr_name = get_my_name ();

  my @options_with_value = qw /verbose warnings debug quiet/;
  my $target_option;

  my $ignore_value;
  my $found_option;
  my $option_requires_value;
  my $option_value;
  my $valid_input;
  my @error_messages = ();

  $option_requires_value = $TRUE;
  for (@options_with_value)
    {
      $target_option = $_;
      ($found_option, $option_value) = find_target_option (
                                         \@ARGV, 
                                         $option_requires_value, 
                                         $target_option);
      if ($found_option)
        {
#------------------------------------------------------------------------------
# This part has been set up such that we can support other options too, should
# this become necessary.
#
# A necessary, but limited check for the validity of a value is performed.
# This avoids that an error message shows up twice later on.
#------------------------------------------------------------------------------

#------------------------------------------------------------------------------
# All option values are converted to lower case.  This makes the checks easier.
#------------------------------------------------------------------------------

          if ($target_option eq "verbose")
            {
              my $verbose_value = lc ($option_value);
              $valid_input = verify_if_input_is_valid ($verbose_value, "onoff");
              if ($valid_input)
                {
                   $g_verbose = ($verbose_value eq "on") ? $TRUE : $FALSE;
                   if ($verbose_value eq "on")
#------------------------------------------------------------------------------
# Set the status and disable output buffering in verbose mode.
#------------------------------------------------------------------------------
                     {
                       $g_user_settings{"verbose"}{"current_value"} = "on";
                       STDOUT->autoflush (1);
                     }
                   elsif ($verbose_value eq "off")
                     {
                       $g_user_settings{"verbose"}{"current_value"} = "off";
                     }
                }
              else
                {
                  my $msg = "$option_value is not supported for the verbose option";
                  push (@error_messages, $msg);
                }
            }
          elsif ($target_option eq "warnings")
            {
              my $warnings_value = lc ($option_value);
              $valid_input = verify_if_input_is_valid ($warnings_value, "onoff");
              if ($valid_input)
                {
                   $g_warnings = ($warnings_value eq "on") ? $TRUE : $FALSE;
                   if ($warnings_value eq "on")
#------------------------------------------------------------------------------
# Set the status and disable output buffering if warnings are enabled.
#------------------------------------------------------------------------------
                     {
                       $g_user_settings{"warnings"}{"current_value"} = "on";
                       STDOUT->autoflush (1);
                     }
                   elsif ($warnings_value eq "off")
                     {
                       $g_user_settings{"warnings"}{"current_value"} = "off";
                     }
                }
              else
                {
                  my $msg = "$option_value is not supported for the warnings option";
                  push (@error_messages, $msg);
                }
            }
          elsif ($target_option eq "quiet") 
            {
              my $quiet_value = lc ($option_value);
              $valid_input = verify_if_input_is_valid ($option_value, "onoff");
              if ($valid_input)
                {
                   $g_quiet = ($quiet_value eq "on") ? $TRUE : $FALSE;
                   if ($quiet_value eq "on")
                     {
                       $g_user_settings{"quiet"}{"current_value"} = "on";
                     }
                   elsif ($quiet_value eq "off")
                     {
                       $g_user_settings{"quiet"}{"current_value"} = "off";
                     }
                }
              else
                {
                  my $msg = "$option_value is not supported for the quiet option";
                  push (@error_messages, $msg);
                }
            }
          elsif ($target_option eq "debug") 
            {
              my $debug_value = lc ($option_value);
              $valid_input = verify_if_input_is_valid ($debug_value, "size");
              if ($valid_input)
                {
                   if ($debug_value ne "off")
#------------------------------------------------------------------------------
# Disable output buffering in debug mode.
#------------------------------------------------------------------------------
                     {
                       $g_user_settings{"debug"}{"current_value"} = "on";
                       STDOUT->autoflush (1);
                     }
#------------------------------------------------------------------------------
# This function also sets $g_user_settings{"debug"}{"current_value"}. 
#------------------------------------------------------------------------------
                   my $ignore_value = set_debug_size (\$debug_value);
                }
              else
                {
                  my $msg = "$option_value is not supported for the debug option";
                  push (@error_messages, $msg);
                }
            }
          else
            {
              my $msg = "target option $target_option not expected";
              gp_message ("assertion", $subr_name, $msg);
            }
        }
    }

#------------------------------------------------------------------------------
# Check for input errors.
#------------------------------------------------------------------------------
  my $input_errors = scalar (@error_messages); 
  if ($input_errors > 0)
    {
      my $plural = ($input_errors == 1) ? 
                        "is one error" : "are $input_errors errors";
      print "There " . $plural . " in the options:\n";
      for my $i (0 .. $#error_messages)
        {
          print "- $error_messages[$i]\n";
        }
      exit (0);
    }
#------------------------------------------------------------------------------
# If quiet mode has been enabled, disable verbose, warnings and debug.
#------------------------------------------------------------------------------
  if ($g_quiet)
    {
      $g_user_settings{"verbose"}{"current_value"} = "off";
      $g_user_settings{"warnings"}{"current_value"} = "off";
      $g_user_settings{"debug"}{"current_value"}   = "off";
      $g_verbose  = $FALSE;
      $g_warnings = $FALSE;
      my $debug_off = "off";
      my $ignore_value = set_debug_size (\$debug_off);
    }

  return (0);

} #-- End of subroutine early_scan_specific_options

#------------------------------------------------------------------------------
# TBD
#------------------------------------------------------------------------------
sub elf_phdr
{
  my $subr_name = get_my_name ();

  my ($elf_loadobjects_found, $elf_arch, $loadobj, $routine, 
      $ARCHIVES_MAP_NAME, $ARCHIVES_MAP_VADDR, $elf_rats_ref) = @_;

  my %elf_rats = %{$elf_rats_ref};

  my $return_value;

#------------------------------------------------------------------------------
# TBD. Quick check. Can be moved up the call tree.
#------------------------------------------------------------------------------
    if ( ($elf_arch ne "Linux") and ($elf_arch ne "SunOS") )
      {
        gp_message ("abort", $subr_name, "$elf_arch is not a supported OS");
      }

#------------------------------------------------------------------------------
# TBD: This should not be in a loop over $loadobj and only use the executable.
#------------------------------------------------------------------------------

#------------------------------------------------------------------------------
# TBD: $routine is not really used in these subroutines. Is this a bug?
#------------------------------------------------------------------------------
  if ($elf_loadobjects_found)
    {
      gp_message ("debugXL", $subr_name, "calling elf_phdr_usual");
      $return_value = elf_phdr_usual ($elf_arch, $loadobj, $routine, \%elf_rats);
    }
  else 
    {
      gp_message ("debugXL", $subr_name, "calling elf_phdr_sometimes");
      $return_value = elf_phdr_sometimes ($elf_arch, $loadobj, $routine, $ARCHIVES_MAP_NAME, $ARCHIVES_MAP_VADDR);
    }

  gp_message ("debug", $subr_name, "the return value = $return_value");

  if (not $return_value)
    {
      gp_message ("abort", $subr_name, "need to handle a return value of FALSE");
    } 
  return ($return_value);

} #-- End of subroutine elf_phdr

#------------------------------------------------------------------------------
# Return the virtual address for the load object.
#------------------------------------------------------------------------------
sub elf_phdr_sometimes
{
  my $subr_name = get_my_name ();

  my ($elf_arch, $loadobj, $routine, $ARCHIVES_MAP_NAME, 
      $ARCHIVES_MAP_VADDR) = @_;

  my $arch_uname_s = $local_system_config{"kernel_name"};
  my $arch_uname   = $local_system_config{"processor"};
  my $arch         = $g_arch_specific_settings{"arch"};

  gp_message ("debug", $subr_name, "arch_uname_s = $arch_uname_s");
  gp_message ("debug", $subr_name, "arch_uname   = $arch_uname");
  gp_message ("debug", $subr_name, "arch         = $arch");

  my $target_cmd;
  my $command_string; 
  my $error_code;
  my $cmd_output;

  my $line;
  my $blo;

  my $elf_offset;
  my $i;
  my @foo;
  my $foo;
  my $foo1;
  my $p_vaddr;
  my $rc;
  my $archives_file;
  my $loadobj_SAVE;
  my $Offset;
  my $VirtAddr;
  my $PhysAddr;
  my $FileSiz;
  my $MemSiz;
  my $Flg;
  my $Align;

  if ($ARCHIVES_MAP_NAME eq $blo)
    {
      return ($ARCHIVES_MAP_VADDR);
    } 
  else 
    {
      return ($FALSE);
    }

  if ($arch_uname_s ne $elf_arch)
    {
#------------------------------------------------------------------------------
# We are masquerading between systems, must leave
#------------------------------------------------------------------------------
      gp_message ("debug", $subr_name, "masquerading arch_uname_s->$arch_uname_s elf_arch->$elf_arch");
      return ($FALSE);
    }
  if ($loadobj eq "DYNAMIC_FUNCTIONS")
#------------------------------------------------------------------------------
# Linux vDSO, leave for now
#------------------------------------------------------------------------------
    {
      return ($FALSE);
    }

# TBD: STILL NEEDED??!!

  $loadobj_SAVE = $loadobj;

  $blo = get_basename ($loadobj);
  gp_message ("debug", $subr_name, "loadobj = $loadobj");
  gp_message ("debug", $subr_name, "blo     = $blo");
  gp_message ("debug", $subr_name, "ARCHIVES_MAP_NAME  = $ARCHIVES_MAP_NAME");
  gp_message ("debug", $subr_name, "ARCHIVES_MAP_VADDR = $ARCHIVES_MAP_VADDR");
  if ($ARCHIVES_MAP_NAME eq $blo)
    {
      return ($ARCHIVES_MAP_VADDR);
    } 
  else 
    {
      return ($FALSE);
    }

} #-- End of subroutine elf_phdr_sometimes

#------------------------------------------------------------------------------
# Return the virtual address for the load object.
#
# Note that at this point, $elf_arch is known to be supported.
#------------------------------------------------------------------------------
sub elf_phdr_usual
{
  my $subr_name = get_my_name ();

  my ($elf_arch, $loadobj, $routine, $elf_rats_ref) = @_;

  my %elf_rats = %{$elf_rats_ref};

  my $return_code;
  my $cmd_output;
  my $target_cmd;
  my $command_string; 
  my $error_code;
  my $error_code1;
  my $error_code2;

  my ($elf_offset, $loadobjARC);
  my ($i, @foo, $foo, $foo1, $p_vaddr, $rc);
  my ($Offset, $VirtAddr, $PhysAddr, $FileSiz, $MemSiz, $Flg, $Align);

  my $arch_uname_s = $local_system_config{"kernel_name"};

  gp_message ("debug", $subr_name, "elf_arch = $elf_arch loadobj = $loadobj routine = $routine");

  my ($base, $ignore_value, $ignore_too) = fileparse ($loadobj);
  gp_message ("debug", $subr_name, "base = $base ".basename ($loadobj));

  if ($elf_arch eq "Linux")
    {
      if ($arch_uname_s ne $elf_arch)
        {
#------------------------------------------------------------------------------
# We are masquerading between systems, must leave.
# Maybe we could use ELF_RATS
#------------------------------------------------------------------------------
          gp_message ("debug", $subr_name, "masquerading arch_uname_s->$arch_uname_s elf_arch->$elf_arch");
          return ($FALSE);
        }
      if ($loadobj eq "DYNAMIC_FUNCTIONS")
        {
#------------------------------------------------------------------------------
# Linux vDSO, leave for now
#------------------------------------------------------------------------------
          gp_message ("debug", $subr_name, "early return: loadobj = $loadobj");
          return ($FALSE);
        }

      $target_cmd     = $g_mapped_cmds{"readelf"};
      $command_string = $target_cmd . " -l " . $loadobj . " 2>/dev/null";

      ($error_code1, $cmd_output) = execute_system_cmd ($command_string);

      gp_message ("debug", $subr_name, "executed command_string = $command_string");
      gp_message ("debug", $subr_name, "cmd_output = $cmd_output");

      if ($error_code1 != 0)
        {
          gp_message ("debug", $subr_name, "call failure for $command_string");
#------------------------------------------------------------------------------
# e.g. $loadobj->/usr/lib64/libc-2.17.so
#------------------------------------------------------------------------------
          $loadobjARC = get_basename ($loadobj);
          gp_message ("debug", $subr_name, "seek elf_rats for $loadobjARC");

          if (exists ($elf_rats{$loadobjARC}))
            {
              my $elfoid  = "$elf_rats{$loadobjARC}[1]/archives/$elf_rats{$loadobjARC}[0]";
              $target_cmd     = $g_mapped_cmds{"readelf"};
              $command_string = $target_cmd . "-l " . $elfoid . " 2>/dev/null";
              ($error_code2, $cmd_output) = execute_system_cmd ($command_string);
 
              if ($error_code2 != 0)
                {
                  gp_message ("abort", $subr_name, "call failure for $command_string");
                }
              else
                {
                  gp_message ("debug", $subr_name, "executed command_string = $command_string");
                  gp_message ("debug", $subr_name, "cmd_output = $cmd_output");
                }
            }
          else 
            {
              my $msg =  "elf_rats{$loadobjARC} does not exist";
              gp_message ("assertion", $subr_name, $msg);
            }
        }
#------------------------------------------------------------------------------
# Example output of "readelf -l" on Linux:
#
# Elf file type is EXEC (Executable file)
# Entry point 0x4023a0
# There are 11 program headers, starting at offset 64
# 
# Program Headers:
#   Type           Offset             VirtAddr           PhysAddr
#                  FileSiz            MemSiz              Flags  Align
#   PHDR           0x0000000000000040 0x0000000000400040 0x0000000000400040
#                  0x0000000000000268 0x0000000000000268  R      8
#   INTERP         0x00000000000002a8 0x00000000004002a8 0x00000000004002a8
#                  0x000000000000001c 0x000000000000001c  R      1
#       [Requesting program interpreter: /lib64/ld-linux-x86-64.so.2]
#   LOAD           0x0000000000000000 0x0000000000400000 0x0000000000400000
#                  0x0000000000001310 0x0000000000001310  R      1000
#   LOAD           0x0000000000002000 0x0000000000402000 0x0000000000402000
#                  0x0000000000006515 0x0000000000006515  R E    1000
#   LOAD           0x0000000000009000 0x0000000000409000 0x0000000000409000
#                  0x000000000006f5a8 0x000000000006f5a8  R      1000
#   LOAD           0x0000000000078dc8 0x0000000000479dc8 0x0000000000479dc8
#                  0x000000000000047c 0x0000000000000f80  RW     1000
#   DYNAMIC        0x0000000000078dd8 0x0000000000479dd8 0x0000000000479dd8
#                  0x0000000000000220 0x0000000000000220  RW     8
#   NOTE           0x00000000000002c4 0x00000000004002c4 0x00000000004002c4
#                  0x0000000000000044 0x0000000000000044  R      4
#   GNU_EH_FRAME   0x00000000000777f4 0x00000000004777f4 0x00000000004777f4
#                  0x000000000000020c 0x000000000000020c  R      4
#   GNU_STACK      0x0000000000000000 0x0000000000000000 0x0000000000000000
#                  0x0000000000000000 0x0000000000000000  RW     10
#   GNU_RELRO      0x0000000000078dc8 0x0000000000479dc8 0x0000000000479dc8
#                  0x0000000000000238 0x0000000000000238  R      1
# 
#  Section to Segment mapping:
#   Segment Sections...
#    00
#    01     .interp
#    02     .interp .note.gnu.build-id .note.ABI-tag .gnu.hash .dynsym .dynstr .gnu.version .gnu.version_r .rela.dyn .rela.plt
#    03     .init .plt .text .fini
#    04     .rodata .eh_frame_hdr .eh_frame
#    05     .init_array .fini_array .dynamic .got .got.plt .data .bss
#    06     .dynamic
#    07     .note.gnu.build-id .note.ABI-tag
#    08     .eh_frame_hdr
#    09
#    10     .init_array .fini_array .dynamic .got
#------------------------------------------------------------------------------

#------------------------------------------------------------------------------
# Analyze the ELF information and try to find the virtual address.
#
# Note that the information printed as part of LOAD needs to have "R E" in it.
# In the example output above, the return value would be "0x0000000000402000".
#
# We also need to distinguish two cases.  It could be that the output is on
# a single line, or spread over two lines:
#
#                 Offset   VirtAddr   PhysAddr   FileSiz  MemSiz   Flg Align
#  LOAD           0x000000 0x08048000 0x08048000 0x61b4ae 0x61b4ae R E 0x1000
# or 2 lines
#  LOAD           0x0000000000000000 0x0000000000400000 0x0000000000400000
#                 0x0000000000001010 0x0000000000001010  R E    200000
#------------------------------------------------------------------------------
      @foo = split ("\n",$cmd_output);
      for $i (0 .. $#foo) 
        {
          $foo = $foo[$i];
          chomp ($foo);
          if ($foo =~ /^\s+LOAD\s+(\S+)\s+(\S+)\s+(\S+)\s+(\S+)\s+(\S+)\s+(R\sE)\s+(\S+)$/)
            {
              $Offset   = $1;
              $VirtAddr = $2;
              $PhysAddr = $3;
              $FileSiz  = $4;
              $MemSiz   = $5;
              $Flg      = $6;
              $Align    = $7;

              $elf_offset = $VirtAddr;
              gp_message ("debug", $subr_name, "single line version elf_offset = $elf_offset");
              return ($elf_offset);
            }
          elsif ($foo =~ /^\s+LOAD\s+(\S+)\s+(\S+)\s+(\S+)$/)
            { 
#------------------------------------------------------------------------------
# is it a two line version?
#------------------------------------------------------------------------------
              $Offset   = $1;
              $VirtAddr = $2; # maybe
              $PhysAddr = $3;
              if ($i != $#foo)
                {
                  $foo1 = $foo[$i + 1]; 
                  chomp ($foo1);
                  if ($foo1 =~ /^\s+(\S+)\s+(\S+)\s+(R\sE)\s+(\S+)$/)
                    {
                      $FileSiz  = $1;
                      $MemSiz   = $2;
                      $Flg      = $3;
                      $Align    = $4;
                      $elf_offset = $VirtAddr;
                      gp_message ("debug", $subr_name, "two line version elf_offset = $elf_offset");
                      return ($elf_offset);
                    }
                }
            }
        }
    }
  elsif ($elf_arch eq "SunOS") 
    {
#------------------------------------------------------------------------------
#Program Header[3]:
#    p_vaddr:      0x10000     p_flags:    [ PF_X PF_R ]
# folowed by
#    p_paddr:      0           p_type:     [ PT_LOAD ]
#------------------------------------------------------------------------------
        if ($arch_uname_s ne $elf_arch)
#------------------------------------------------------------------------------
# we are masquerading between systems, must leave
#------------------------------------------------------------------------------
          { 
            gp_message ("debug", $subr_name,"masquerading arch_uname_s = $arch_uname_s elf_arch = $elf_arch");
            return (0);
           }
        $target_cmd     = $g_mapped_cmds{"elfdump"};
        $command_string = $target_cmd . "-p " . $loadobj . " 2>/dev/null";
        ($error_code, $cmd_output) = execute_system_cmd ($command_string);
        if ($error_code != 0)
          {
            gp_message ("debug", $subr_name,"call failure for $command_string");
            die ("$target_cmd call failure");
          }
        my @foo = split ("\n",$cmd_output);
        for $i (0 .. $#foo) 
          {
            $foo = $foo[$i];
            chomp ($foo);
            if ($foo =~ /^\s+p_vaddr:\s+(\S+)\s+p_flags:\s+\[\sPF_X\sPF_R\s\]$/)
              {
                $p_vaddr = $1; # probably
                if ($i != $#foo)
                  {
                    $foo1 = $foo[$i + 1];
                    chomp ($foo1);
                    if ($foo1 =~ /^\s+p_paddr:\s+(\S+)\s+p_type:\s+\[\sPT_LOAD\s\]$/)
                      {
                        $elf_offset = $p_vaddr;
                        return ($elf_offset);
                      }
                  }
              }
          }
      }

} #-- End of subroutine elf_phdr_usual

#------------------------------------------------------------------------------
# Execute a system command.  In case of an error, a non-zero error code is
# returned.  It is upon the caller to decide what to do next.
#------------------------------------------------------------------------------
sub execute_system_cmd
{
  my $subr_name = get_my_name ();

  my ($target_cmd) = @_;

  chomp ($target_cmd);

  my $cmd_output = qx ($target_cmd);
  my $error_code = ${^CHILD_ERROR_NATIVE};

  if ($error_code != 0)
    {
      gp_message ("error", $subr_name, "failure executing command $target_cmd");
      gp_message ("error", $subr_name, "error code = $error_code");
    }
  else
    {
      chomp ($cmd_output);
      gp_message ("debugM", $subr_name, "executed command $target_cmd");
      gp_message ("debugM", $subr_name, "cmd_output = $cmd_output");
    }

  return ($error_code, $cmd_output);

} #-- End of subroutine execute_system_cmd

#------------------------------------------------------------------------------
# Scan the input file, which should be a gprofng generated map.xml file, and 
# extract the relevant information.
#------------------------------------------------------------------------------
sub extract_info_from_map_xml
{
  my $subr_name = get_my_name ();

  my ($input_map_xml_file) = @_;

  my $extracted_information;
  my $input_line;
  my $vaddr;
  my $foffset;
  my $modes;
  my $name_path;
  my $name;

  my $full_path_exec;
  my $executable_name;
  my $va_executable_in_hex; 

  open (MAP_XML, "<", $input_map_xml_file)
    or die ("$subr_name - unable to open file $input_map_xml_file for reading: $!");
  gp_message ("debug", $subr_name, "opened file $input_map_xml_file for reading");

#------------------------------------------------------------------------------
# Scan the file.  We need to find the name of the executable with the mode set 
# to 0x005.  For this entry we have to capture the name, the mode, the virtual 
# address and the offset.
#------------------------------------------------------------------------------
  $extracted_information = $FALSE;
  while (<MAP_XML>)
    {
      $input_line = $_;
      chomp ($input_line);
      gp_message ("debug", $subr_name, "read input_line = $input_line");
      if ($input_line =~   /^<event kind="map"\s.*vaddr="0x([0-9a-fA-F]+)"\s+.*foffset="\+*0x([0-9a-fA-F]+)"\s.*modes="0x([0-9]+)"\s.*name="(.*)".*>$/)
        {
          gp_message ("debug", $subr_name, "target line = $input_line");

          $vaddr     = $1;
          $foffset   = $2;
          $modes     = $3;
          $name_path = $4;
          $name      = get_basename ($name_path);
          gp_message ("debug", $subr_name, "extracted vaddr = $vaddr foffset = $foffset modes = $modes");
          gp_message ("debug", $subr_name, "extracted name_path = $name_path name = $name");

#------------------------------------------------------------------------------
# The base virtual address is calculated as vaddr-foffset.  Although Perl 
# handles arithmetic in hex, we take the safe way here.  Maybe overkill, but
# I prefer to be safe than sorry in cases like this.
#------------------------------------------------------------------------------
          $full_path_exec       = $name_path;
          $executable_name      = $name;
          my $result_VA         = bigint::hex ($vaddr) - bigint::hex ($foffset);
          $va_executable_in_hex = sprintf ("0x%016x", $result_VA);

##          $ARCHIVES_MAP_NAME  = $name;
##          $ARCHIVES_MAP_VADDR = $va_executable_in_hex;

##          gp_message ("debug", $subr_name, "set ARCHIVES_MAP_NAME  = $ARCHIVES_MAP_NAME");
##          gp_message ("debug", $subr_name, "set ARCHIVES_MAP_VADDR = $ARCHIVES_MAP_VADDR");
          gp_message ("debug", $subr_name, "result_VA            = $result_VA"); 
          gp_message ("debug", $subr_name, "va_executable_in_hex = $va_executable_in_hex"); 

#------------------------------------------------------------------------------
# Stop reading when we found the correct entry.
#------------------------------------------------------------------------------
          if ($modes eq "005")
            {
              $extracted_information = $TRUE;
              last;
            }
        }
    } #-- End of while-loop

  if (not $extracted_information)
    {
      my $msg = "cannot find the necessary information in file $input_map_xml_file";
      gp_message ("assertion", $subr_name, $msg);
    }

  gp_message ("debug", $subr_name, "full_path_exec       = $full_path_exec"); 
  gp_message ("debug", $subr_name, "executable_name      = $executable_name"); 
  gp_message ("debug", $subr_name, "va_executable_in_hex = $va_executable_in_hex"); 

  return ($full_path_exec, $executable_name, $va_executable_in_hex);

} #-- End of subroutine extract_info_from_map_xml

#------------------------------------------------------------------------------
# This routine analyzes the metric line and extracts the metric specifics 
# from it.
# Example input: Exclusive Total CPU Time: e.%totalcpu
#------------------------------------------------------------------------------
sub extract_metric_specifics
{
  my $subr_name = get_my_name ();

  my ($metric_line) = @_;

  my $metric_description;
  my $metric_flavor;
  my $metric_visibility;
  my $metric_name;
  my $metric_spec;

# Ruud   if (($metric =~ /\s*(.*):\s+(\S)((\.\S+)|(\+\S+))/) && !($metric =~/^Current/)){
  if (($metric_line =~ /\s*(.+):\s+([ei])([\.\+%]+)(\S*)/) and !($metric_line =~/^Current/))
    {
      gp_message ("debug", $subr_name, "line of interest: $metric_line");

      $metric_description = $1;
      $metric_flavor      = $2;
      $metric_visibility  = $3;
      $metric_name        = $4;

#------------------------------------------------------------------------------
# Although we have captured the metric visibility, the original code removes
# this from the name.  Since the structure is more complicated, the code is
# more tedious as well.  With our new approach we just leave the visibility
# out.
#------------------------------------------------------------------------------
#      $metric_spec        = $metric_flavor.$metric_visibility.$metric_name;

      $metric_spec        = $metric_flavor . "." . $metric_name;

#------------------------------------------------------------------------------
# From the original code:
#
# On x64 systems there are metrics which contain ~ (for example
# DC_access~umask=0 .  When er_print lists them, they come out
# as DC_access%7e%umask=0 (see 6530691).  Untill 6530691 is
# fixed, we need this.  Later we may need something else, or
# things may just work.
#------------------------------------------------------------------------------
#          $metric_spec=~s/\%7e\%/,/;
#          # remove % metric
#          print "DB: before \$metric_spec = $metric_spec\n";

#------------------------------------------------------------------------------
# TBD: I don't know why the "%" symbol is removed.
#------------------------------------------------------------------------------
#          $metric_spec =~ s/\%//;
#          print "DB: after  \$metric_spec = $metric_spec\n";

      return ($metric_spec, $metric_flavor, $metric_visibility, 
              $metric_name, $metric_description);
    }
  else
    {
      return ("skipped", "void");
    }

} #-- End of subroutine extract_metric_specifics

#------------------------------------------------------------------------------
# TBD
#------------------------------------------------------------------------------
sub extract_source_line_number
{
  my $subr_name = get_my_name ();

  my ($src_times_regex, $function_regex, $number_of_metrics, $input_line) = @_;

#------------------------------------------------------------------------------
# The regex section.
#------------------------------------------------------------------------------
  my $find_dot_regex = '\.';

  my @fields_in_line = ();
  my $hot_line;
  my $line_id;

#------------------------------------------------------------------------------
# To extract the source line number, we need to distinguish whether this is 
# a line with, or without metrics.
#------------------------------------------------------------------------------
      @fields_in_line = split (" ", $input_line);
      if ( $input_line =~ /$src_times_regex/ )
        {
          $hot_line = $1;
          if ($hot_line eq "##")
#------------------------------------------------------------------------------
# The line id comes after the "##" symbol and the metrics.
#------------------------------------------------------------------------------
            {
              $line_id = $fields_in_line[$number_of_metrics+1];
            }
          else
#------------------------------------------------------------------------------
# The line id comes after the metrics.
#------------------------------------------------------------------------------
            {
              $line_id = $fields_in_line[$number_of_metrics];
            }
        }
      elsif ($input_line =~ /$function_regex/)
        {
          $line_id = "func";
        }
      else
#------------------------------------------------------------------------------
# The line id is the first non-blank element.
#------------------------------------------------------------------------------
        {
          $line_id = $fields_in_line[0];
        }
#------------------------------------------------------------------------------
# Remove the trailing dot.
#------------------------------------------------------------------------------
      $line_id =~ s/$find_dot_regex//;

   return ($line_id);

} #-- End of subroutine extract_source_line_number

#------------------------------------------------------------------------------
# For a give routine name and address, find the index into the 
# function_info array
#------------------------------------------------------------------------------
sub find_index_in_function_info
{
  my $subr_name = get_my_name ();

  my ($routine_ref, $current_address_ref, $function_info_ref) = @_;

  my $routine = ${ $routine_ref };
  my $current_address = ${ $current_address_ref };
  my @function_info = @{ $function_info_ref };

  my $addr_offset;
  my $ref_index;

  gp_message ("debugXL", $subr_name, "find index for routine = $routine and current_address = $current_address");
  if (exists ($g_multi_count_function{$routine}))
    {

# TBD: Scan all of the function_info list. Or beter: add index to g_multi_count_function!!

      gp_message ("debugXL", $subr_name, "$routine: occurrences = $g_function_occurrences{$routine}");
      for my $ref (keys @{ $g_map_function_to_index{$routine} })
        {
          $ref_index = $g_map_function_to_index{$routine}[$ref];

          gp_message ("debugXL", $subr_name, "$routine: retrieving duplicate entry at ref_index = $ref_index");
          gp_message ("debugXL", $subr_name, "$routine: function_info[$ref_index]{'alt_name'} = $function_info[$ref_index]{'alt_name'}");

          $addr_offset = $function_info[$ref_index]{"addressobjtext"};
          gp_message ("debugXL", $subr_name, "$routine: addr_offset = $addr_offset");
  
          $addr_offset =~ s/^@\d+://;
          gp_message ("debugXL", $subr_name, "$routine: addr_offset = $addr_offset");
          if ($addr_offset eq $current_address)
            {
              last;
            }
        }
    }
  else
    {
#------------------------------------------------------------------------------
# There is only a single occurrence and it is straightforward to get the index.
#------------------------------------------------------------------------------
      if (exists ($g_map_function_to_index{$routine}))
        {
          $ref_index = $g_map_function_to_index{$routine}[0];
        }
      else
        {
          my $msg = "index for $routine cannot be determined";
          gp_message ("assertion", $subr_name, $msg);
        }
    }

  gp_message ("debugXL", $subr_name, "routine = $routine current_address = $current_address ref_index = $ref_index");

  return (\$ref_index);

} #-- End of subroutine find_index_in_function_info

#------------------------------------------------------------------------------
# TBD
#------------------------------------------------------------------------------
sub find_keyword_in_string
{
  my $subr_name = get_my_name ();

  my ($target_string_ref, $target_keyword_ref) = @_;

  my $target_string  = ${ $target_string_ref };
  my $target_keyword = ${ $target_keyword_ref };
  my $foundit = $FALSE;

  my @index_values = ();

    my $ret_val = 0;
    my $offset = 0;
    gp_message ("debugXL", $subr_name, "target_string = $target_string");
    $ret_val = index ($target_string, $target_keyword, $offset);
    gp_message ("debugXL", $subr_name, "ret_val = $ret_val");

    if ($ret_val != -1)
      {
        $foundit = $TRUE;
        while ($ret_val != -1)
          {
             push (@index_values, $ret_val);
             $offset = $ret_val + 1;
             gp_message ("debugXL", $subr_name, "ret_val = $ret_val offset = $offset");
             $ret_val = index ($target_string, $target_keyword, $offset);
          }
        for my $i (keys @index_values)
          {
            gp_message ("debugXL", $subr_name, "index_values[$i] = $index_values[$i]");
          }
      }
    else
      {
        gp_message ("debugXL", $subr_name, "target keyword $target_keyword not found");
      }

  return (\$foundit, \@index_values);

} #-- End of subroutine find_keyword_in_string

#------------------------------------------------------------------------------
# Retrieve the absolute path that was used to execute the command.  This path
# is used to execute gp-display-text later on.
#------------------------------------------------------------------------------
sub find_path_to_gp_display_text
{
  my $subr_name = get_my_name ();

  my ($full_command_ref) = @_;

  my $full_command = ${ $full_command_ref };

  my $error_occurred = $TRUE;
  my $return_value;

#------------------------------------------------------------------------------
# Get the path name.
#------------------------------------------------------------------------------
  my ($gp_file_name, $gp_path, $suffix_not_used) = fileparse ($full_command);

  gp_message ("debug", $subr_name, "full_command = $full_command");
  gp_message ("debug", $subr_name, "gp_path  = $gp_path");

  my $gp_display_text_instance = $gp_path . $GP_DISPLAY_TEXT;

#------------------------------------------------------------------------------
# Check if $GP_DISPLAY_TEXT exists, is not empty, and executable.
#------------------------------------------------------------------------------
  if (not -e $gp_display_text_instance)
    {
      $return_value = "file not found";
    }
  else
    {
      if (is_file_empty ($gp_display_text_instance))
        {
          $return_value = "file is empty";
        }
      else
        {
#------------------------------------------------------------------------------
# All is well.  Capture the path.
#------------------------------------------------------------------------------
          $error_occurred = $FALSE;
          $return_value = $gp_path;
        }
    }

  return (\$error_occurred, \$return_value);

} #-- End of subroutine find_path_to_gp_display_text

#------------------------------------------------------------------------------
# Scan the command line to see if the specified option is present.
#
# Two types of options are supported: options without a value (e.g. --help) or
# those that are set to "on" or "off".
#
# In this phase, we only need to check if a value is valid. If it is, we have
# to enable the corresponding global setting.  If the value is not valid, we
# ignore it, since it will be caught later and a warning message is issued.
#------------------------------------------------------------------------------
sub find_target_option
{
  my $subr_name = get_my_name ();

  my ($command_line_ref, $option_requires_value, $target_option) = @_;

  my @command_line     = @{ $command_line_ref };
  my $option_value     = undef;
  my $found_option     = $FALSE;

  my ($command_line_string) = join (" ", @command_line);

##  if ($command_line_string =~ /\s*($target_option)\s*(on|off)*\s*/)
#------------------------------------------------------------------------------
# This does not make any assumptions on the values we are looking for.
#------------------------------------------------------------------------------
  if ($command_line_string =~ /\s*\-\-($target_option)\s*(\w*)\s*/)
    {
      if (defined ($1))
#------------------------------------------------------------------------------
# We have found the option we are looking for.
#------------------------------------------------------------------------------
        {
          $found_option = $TRUE;
          if ($option_requires_value and defined ($2))
#------------------------------------------------------------------------------
# There is a value and it is passed on to the caller.
#------------------------------------------------------------------------------
            {
              $option_value = $2;
            }
        }
    }

  return ($found_option, $option_value);

} #-- End of subroutine find_target_option

#------------------------------------------------------------------------------
# Find the occurrences of non-space characters in a string and return their
# start and end index values(s).
#------------------------------------------------------------------------------
sub find_words_in_line
{
  my $subr_name = get_my_name ();

  my ($input_line_ref) = @_;

  my $input_line = ${ $input_line_ref };

  my $finished = $TRUE;

  my $space = 0;
  my $space_position = 0;
  my $start_word;
  my $end_word;

  my @word_delimiters = ();

  gp_message ("debugXL", $subr_name, "input_line = $input_line");

    $finished = $FALSE;
    while (not $finished)
      {
        $space = index ($input_line, " ", $space_position);

        my $txt = "string search space_position = $space_position ";
        $txt   .= "space = $space";
        gp_message ("debugXL", $subr_name, $txt);

        if ($space != -1)
          {
            if ($space > $space_position)
              {
                $start_word = $space_position;
                $end_word   = $space - 1;
                $space_position = $space;
                my $keyword = substr ($input_line, $start_word, $end_word - $start_word + 1); 
                gp_message ("debugXL", $subr_name, "string search start_word = $start_word end_word = $end_word space_position = $space_position $keyword");
                push (@word_delimiters, [$start_word, $end_word]);
              }
            elsif ( ($space == $space_position) and ($space < length ($input_line) - 1))
              {
                $space          = $space + 1;
                $space_position = $space; 
              }
            else
              {
                print "DONE\n";
                $finished = $TRUE;
                gp_message ("debugXL", $subr_name, "completed - finished = $finished");
              }
          }
        else
          {
            $finished = $TRUE;
            $start_word = $space_position;
            $end_word = length ($input_line) - 1;
            my $keyword = substr ($input_line, $start_word, $end_word - $start_word + 1); 
            push (@word_delimiters, [$start_word, $end_word]);
            if ($keyword =~ /\s+/)
              {
                my $txt = "end search spaces only";
                gp_message ("debugXL", $subr_name, $txt);
              }
            else
              {
                my $txt  = "end search start_word = $start_word ";
                $txt    .= "end_word = $end_word ";
                $txt    .= "space_position = $space_position -->$keyword<--";
                gp_message ("debugXL", $subr_name, $txt);
              }
          }

       }

  for my $i (keys @word_delimiters)
    {
      gp_message ("debugXL", $subr_name, "i = $i $word_delimiters[$i][0] $word_delimiters[$i][1]");
    }

  return (\@word_delimiters);

} #-- End of subroutine find_words_in_line

#------------------------------------------------------------------------------
# TBD
#------------------------------------------------------------------------------
sub function_info
{ 
  my $subr_name = get_my_name ();

  my ($outputdir, $FUNC_FILE, $metric, $LINUX_vDSO_ref) = @_;

  my %LINUX_vDSO = %{ $LINUX_vDSO_ref };

  my $index_val;
  my $address_decimal;
  my $full_address_field;

  my $FUNC_FILE_NO_PC;
  my $off_with_the_PC; 

  my $blanks;
  my $lblanks;
  my $lvdso_key;
  my $line_regex;

  my %functions_per_metric_indexes = ();
  my %functions_per_metric_first_index = ();
  my @order;

  my ($line,$line_n,$value);
  my ($df_flag,$n,$u);
  my ($metric_value,$PC_Address,$routine);
  my ($is_calls,$metric_ok,$name_regex,$pc_len);
  my ($segment,$offset,$offy,$spaces,$rest,$not_printed,$vdso_key);

#------------------------------------------------------------------------------
# If the directory name does not end with a "/", add it.
#------------------------------------------------------------------------------
  my $length_of_string = length ($outputdir);

  if (rindex ($outputdir, "/") != $length_of_string-1) 
    {
      $outputdir .= "/";
    }

  gp_message ("debug", $subr_name, "on input FUNC_FILE = $FUNC_FILE metric = $metric");

  $is_calls        = $FALSE;
  $metric_ok       = $TRUE;
  $off_with_the_PC = rindex ($FUNC_FILE, "-PC");
  $FUNC_FILE_NO_PC = substr ($FUNC_FILE, 0, $off_with_the_PC);

  if ($FUNC_FILE_NO_PC eq $outputdir."calls.sort.func")
    {
      $FUNC_FILE_NO_PC = $outputdir."calls";
      $is_calls        = $TRUE;
      $metric_ok       = $FALSE;
    } 
  elsif ($FUNC_FILE_NO_PC eq $outputdir."calltree.sort.func")
    {
      $FUNC_FILE_NO_PC = $outputdir."calltree";
      $metric_ok       = $FALSE;
    } 
  elsif ($FUNC_FILE_NO_PC eq $outputdir."functions.sort.func")
    {
      $FUNC_FILE_NO_PC = $outputdir."functions.func";
      $metric_ok       = $FALSE;
    }
  gp_message ("debugM", $subr_name, "set FUNC_FILE_NO_PC = $FUNC_FILE_NO_PC");

  open (FUNC_FILE, "<", $FUNC_FILE)
    or die ("Not able to open file $FUNC_FILE for reading - '$!'");
  gp_message ("debug", $subr_name, "opened file FUNC_FILE = $FUNC_FILE for reading");

  open (FUNC_FILE_NO_PC, ">", $FUNC_FILE_NO_PC)
    or die ("Not able to open file $FUNC_FILE_NO_PC for writing - '$!'");
  gp_message ("debug", $subr_name, "opened file FUNC_FILE_NO_PC = $FUNC_FILE_NO_PC for writing");

  open (FUNC_FILE_REGEXP, "<", "$FUNC_FILE.name-regex")
    or die ("Not able to open file $FUNC_FILE.name-regex for reading - '$!'");
  gp_message ("debug", $subr_name, "opened file FUNC_FILE_REGEXP = $FUNC_FILE.name-regex for reading");

  $name_regex = <FUNC_FILE_REGEXP>;
  chomp ($name_regex);
  close (FUNC_FILE_REGEXP);

  gp_message ("debugXL", $subr_name, "name_regex = $name_regex");

  $n = 0;
  $u = 0;
  $pc_len = 0;

#------------------------------------------------------------------------------
# Note that the double \\ is needed here.  The regex used will not have these.
#------------------------------------------------------------------------------
  if ($is_calls)
    {
#------------------------------------------------------------------------------
# TBD
# I do not see the "*" in my test output, but no harm to leave the code in.
#
# er_print * before PC for calls ! 101315
#------------------------------------------------------------------------------
      $line_regex = "^(\\s*)(\\**)(\\S+)(:)(\\S+)(\\s+)(.*)";
    } 
  else 
    {
      $line_regex = "^(\\s*)(\\S+)(:)(\\S+)(\\s+)(.*)";
    }
  gp_message ("debugXL", $subr_name, "is_calls = ".(($is_calls) ? "TRUE" : "FALSE")." line_regex->$line_regex<-");
  gp_message ("debugXL", $subr_name, "read FUNC_FILE = $FUNC_FILE");

  $line_n = 0;
  $index_val = 0;
  while (<FUNC_FILE>)
    {
      $line = $_;
      chomp ($line);

#      gp_message ("debug", $subr_name, "FUNC_FILE: input line = $line");

      $line_n++;
      if ($line =~ /$line_regex/) # field 2|3 needs to be \S in case of -ve sign
        {
#------------------------------------------------------------------------------
# A typical target line looks like this:
# 11:0x001492e0  6976.900   <additional_timings> _lwp_start
#------------------------------------------------------------------------------
          gp_message ("debugXL", $subr_name, "select = $line");
          if ($is_calls)
            {
              $segment = $3;
              $offset  = $5;
              $spaces  = $6;
              $rest    = $7;
              $PC_Address = $segment.$4.$offset; # PC Addr.
              gp_message ("debugXL", $subr_name, "is_calls = ".(($is_calls) ? "TRUE" : "FALSE")." \$3 = $3");
              gp_message ("debugXL", $subr_name, "is_calls = ".(($is_calls) ? "TRUE" : "FALSE")." \$5 = $5");
              gp_message ("debugXL", $subr_name, "is_calls = ".(($is_calls) ? "TRUE" : "FALSE")." \$6 = $6");
              gp_message ("debugXL", $subr_name, "is_calls = ".(($is_calls) ? "TRUE" : "FALSE")." \$7 = $7");
            } 
          else 
            {
              $segment = $2;
              $offset  = $4;
              $spaces  = $5;
              $rest    = $6;
              $PC_Address = $segment.$3.$offset; # PC Addr.
              gp_message ("debugXL", $subr_name, "is_calls = ".(($is_calls) ? "TRUE" : "FALSE")." \$2 = $2");
              gp_message ("debugXL", $subr_name, "is_calls = ".(($is_calls) ? "TRUE" : "FALSE")." \$4 = $4");
              gp_message ("debugXL", $subr_name, "is_calls = ".(($is_calls) ? "TRUE" : "FALSE")." \$5 = $5");
              gp_message ("debugXL", $subr_name, "is_calls = ".(($is_calls) ? "TRUE" : "FALSE")." \$6 = $6");
            }
          if ($segment == -1)
            {
#------------------------------------------------------------------------------
# presume vDSO field overflow - er_print used an inadequate format
# or the fsummary (MASTER) had the wrong format for -1?
# rats - get ahead of ourselves - should not be a field abuttal so
#------------------------------------------------------------------------------
              if ($line =~ /$name_regex/)
                {
                  if ($metric_ok)
                    {
                      $metric_value = $1; # whatever
                      $routine = $2;
                    } 
                  else 
                    {
                      $routine = $1;
                    }
                  if ($is_calls)
                    {
                      if (substr ($routine,0,1) eq "*")
                        {
                          $routine = substr ($routine,1);
                        }
                    }
                  for $vdso_key (keys %LINUX_vDSO)
                    {
                      if ($routine eq $LINUX_vDSO{$vdso_key})
                        { 
#------------------------------------------------------------------------------
# presume no duplicates - at least can check offset
#------------------------------------------------------------------------------
                          if ($vdso_key =~ /(\d+):(\S+)/)
#------------------------------------------------------------------------------
# no -ve segments allowed and not expected
#------------------------------------------------------------------------------
                            {
                              if ($2 eq $offset)
                                {
#------------------------------------------------------------------------------
# the real segment
#------------------------------------------------------------------------------
                                  $segment = $1; 
                                  gp_message ("debugXL", $subr_name, "rescued segment for $PC_Address($routine)->$segment:$offset $FUNC_FILE");
                                  $PC_Address = $segment.":".$offset; # PC Addr.
                                  gp_message ("debugXL", $subr_name, "vdso line ->$line");
                                  $line = $PC_Address.(' ' x (length ($spaces)-2)).$rest;
                                  gp_message ("debugXL", $subr_name, "becomes   ->$line");
                                  last;
                                }
                            }
                        }
                    }
                } 
              else 
                {
                  gp_message ("debug", $subr_name, "name_regex failure for file $FUNC_FILE");
                }
            }

#------------------------------------------------------------------------------
# a rotten exception for Linux vDSO
# With a BIG "PC Address" like 32767:0x841fecd0, the functions.sort.func_PC file
# can have lines like
#->32767:0x841fecd0161.553   527182898954  131.936    100003     __vdso_gettimeofday<-
#->32767:0x153ff810 42.460   0                   0   __vdso_gettimeofday<-
#->-1:0xff600000   99.040   0                   0   [vsyscall]<-
#  (Real PC Address: 4294967295:0xff600000)
#-> 4294967295:0xff600000   99.040   0                   0   [vsyscall]<-
#-> 9:0x00000020   49.310   0                   0   <static>@0x7fff153ff600 ([vdso])<-
# Rats!
# $LINUX_vDSO{substr($order[$i]{"addressobjtext"},1)} = $order[$i]{"routine"};
#------------------------------------------------------------------------------

          $not_printed = $TRUE;
          for $vdso_key (keys %LINUX_vDSO)
            {
              if ($line =~ /^(\s*)($vdso_key)(.*)$/)
                {
                  $blanks = 1;
                  $rest   = 3;
                  $lblanks = length ($blanks);
                  $lvdso_key = length ($vdso_key);
                  $PC_Address = $vdso_key; # PC Addr.
                  $offy = ($lblanks+$lvdso_key < $pc_len) ? $pc_len : $lblanks+$lvdso_key;
                  gp_message ("debugXL", $subr_name, "offy = $offy for ->$line<-");
                  if ($pc_len)
                    {
                      print FUNC_FILE_NO_PC substr ($line,$offy)."\n";
                      $not_printed = $FALSE;
                    }
                  else
                    {
                      die ("sod1a");
                    }
                  gp_message ("debugXL", $subr_name, "vdso line ->$line");
                  if (substr ($line,$lblanks+$lvdso_key,1) eq " ")
                    { 
#------------------------------------------------------------------------------
# O.K. no field abuttal
#------------------------------------------------------------------------------
                      gp_message ("debugXL", $subr_name, "vdso no field abuttal line ->$line");
                    } 
                  else 
                    {
                      gp_message ("debugXL", $subr_name, "vdso field abuttal line ->$line");
                      $line = $blanks.$vdso_key." ".$rest;
                    }
                  gp_message ("debugXL", $subr_name, "becomes   ->$line");
                  last;
                }
            }
          if ($not_printed)
            {
              if ($pc_len)
                {
                  print FUNC_FILE_NO_PC substr ($line,$pc_len)."\n";
                }
              else
                {
                  die ("sod1b");
                }
              $not_printed = $FALSE;
            }
        } 
      else 
        {
          if (!$pc_len)
            {
              if ($line =~ /(^\s*PC Addr.\s+)(\S+)/)
                {
                  $pc_len = length ($1); # say 15
                  print FUNC_FILE_NO_PC substr ($line,$pc_len)."\n";
                } 
              else 
                {
                  print FUNC_FILE_NO_PC "$line\n";
                }
            } 
          else 
            {
              if ($pc_len)
                {
                  my $strlen = length ($line);
                  if ($strlen > 0 ) 
                    {
                      print FUNC_FILE_NO_PC substr ($line,$pc_len)."\n";
                    }
                  else
                    {
                      print FUNC_FILE_NO_PC "\n";
                    }
                }
              else
                {
                  die ("sod2");
                }
            }
          next;
        }
      $routine = "";
      if ($line =~ /$name_regex/)
        {
          if ($metric_ok)
            {
              $metric_value = $1; # whatever
              $routine = $2;
            } 
          else 
            {
              $routine = $1;
            }
        }

      if ($is_calls)
        {
          if (substr ($routine,0,1) eq "*")
            {
              $routine = substr ($routine,1);
            }
        }
      if (length ($routine))
        {
          $order[$index_val]{"routine"} = $routine;
          if ($metric_ok)
            {
              $order[$index_val]{"metric_value"} = $metric_value;
            }
          $order[$index_val]{"PC Address"} = $PC_Address;
          $df_flag = 0;
          if (not exists ($functions_per_metric_indexes{$routine}))
            {
              $functions_per_metric_indexes{$routine} = [$index_val];
            } 
          else 
            {
              push (@{$functions_per_metric_indexes{$routine}},$index_val); # add $RI to list
            }
          gp_message ("debugXL", $subr_name, "updated functions_per_metric_indexes $routine [$index_val] line = $line");
          if ($PC_Address =~ /\s*(\S+):(\S+)/)
            {
              my ($segment,$offset);
              $segment = $1;
              $offset = $2;
              $address_decimal = bigint::hex ($offset); # decimal
              $full_address_field = '@'.$segment.":".$offset; # e.g. @2:0x0003f280
              $order[$index_val]{"addressobj"} = $address_decimal;
              $order[$index_val]{"addressobjtext"} = $full_address_field;
            }
#------------------------------------------------------------------------------
# Check uniqueness
#------------------------------------------------------------------------------
          if (not exists ($functions_per_metric_first_index{$routine}{$PC_Address}))
            {
              $functions_per_metric_first_index{$routine}{$PC_Address} = $index_val;
              $u++; #$RI
            } 
          else 
            {
              if (!($metric eq "calls" || $metric eq "calltree"))
                {
                  gp_message ("debug", $subr_name, "file $FUNC_FILE: function $routine already has a PC Address");
                }
            } 

          $index_val++;
          gp_message ("debugXL", $subr_name, "updated index_val = $index_val");
          $n++;
          next;
        } 
      else 
        {
          if ($n && length ($line))
            {
              my $msg = "unexpected line format in functions file $FUNC_FILE line->$line<-";
              gp_message ("assertion", $subr_name, $msg);
            }
        }
    }
  close (FUNC_FILE);
  close (FUNC_FILE_NO_PC);

  for my $i (sort keys %functions_per_metric_indexes)
    {
      my $values = "";
      for my $fields (sort keys @{ $functions_per_metric_indexes{$i} })
        {
           $values .= "$functions_per_metric_indexes{$i}[$fields] ";
        }
      gp_message ("debugXL", $subr_name, "on return: functions_per_metric_indexes{$i} = $values");
    }

  return (\@order, \%functions_per_metric_first_index, \%functions_per_metric_indexes);

} #-- End of subroutine function_info

#------------------------------------------------------------------------------
# Generate a html header.
#------------------------------------------------------------------------------
sub generate_a_header
{
  my $subr_name = get_my_name ();

  my ($page_text_ref, $size_text_ref, $position_text_ref) = @_;

  my $page_text     = ${ $page_text_ref };
  my $size_text     = ${ $size_text_ref };
  my $position_text = ${ $position_text_ref };
  my $html_header;

  $html_header  = "<div class=\"" . $position_text . "\">\n";
  $html_header .= "<". $size_text . ">\n";
  $html_header .= $page_text . "\n";
  $html_header .= "</". $size_text . ">\n";
  $html_header .= "</div>";

  gp_message ("debugXL", $subr_name, "on exit page_title = $html_header");

  return (\$html_header);

} #-- End of subroutine generate_a_header

#------------------------------------------------------------------------------
# Generate the caller-callee information.
#------------------------------------------------------------------------------
sub generate_caller_callee
{
  my $subr_name = get_my_name ();

  my ($number_of_metrics_ref, $function_info_ref, $function_view_structure_ref, 
      $function_address_info_ref, $addressobjtextm_ref, 
      $input_string_ref) = @_;

  my $number_of_metrics       = ${ $number_of_metrics_ref };
  my @function_info           = @{ $function_info_ref };
  my %function_view_structure = %{ $function_view_structure_ref };
  my %function_address_info   = %{ $function_address_info_ref };
  my %addressobjtextm         = %{ $addressobjtextm_ref };
  my $input_string            = ${ $input_string_ref };

  my @caller_callee_data = ();
  my $outfile;
  my $input_line;

  my $fullname;
  my $separator = "cuthere";

  my @address_field = ();
  my @fields = ();
  my @function_names = ();
  my @marker = ();
  my @metric_values = ();
  my @word_index_values = ();
  my @header_lines = ();

  my $all_metrics;
  my $elements_in_name;
  my $full_hex_address;
  my $hex_address;

  my $file_title; 
  my $page_title; 
  my $size_text; 
  my $position_text; 
  my @html_metric_sort_header = ();
  my $html_header;
  my $html_title_header;
  my $html_home;
  my $html_acknowledgement;
  my $html_end;
  my $html_line;
 
  my $marker_target_function;
  my $max_metrics_length = 0;
  my $metrics_length; 
  my $modified_line; 
  my $name_regex;
  my $no_of_fields;
  my $routine;
  my $routine_length;
  my $string_length; 
  my $top_header; 
  my $total_header_lines;
  my $word_index_values_ref;
  my $infile;

  my $outputdir               = append_forward_slash ($input_string);
  my $LANG                    = $g_locale_settings{"LANG"};
  my $decimal_separator       = $g_locale_settings{"decimal_separator"};

  gp_message ("debug", $subr_name, "decimal_separator = $decimal_separator");
  gp_message ("debug", $subr_name, "outputdir = $outputdir");

  $infile  = $outputdir . "caller-callee-PC2";
  $outfile = $outputdir . $g_html_base_file_name{"caller_callee"} . ".html";

  gp_message ("debug", $subr_name, "infile = $infile outfile = $outfile");

  open (CALLER_CALLEE_IN, "<", $infile) 
    or die ("unable to open caller file $infile for reading - '$!'");
  gp_message ("debug", $subr_name, "opened file $infile for reading");

  open (CALLER_CALLEE_OUT, ">", $outfile)
    or die ("unable to open $outfile for writing - '$!'");
  gp_message ("debug", $subr_name, "opened file $outfile for writing");

  gp_message ("debug", $subr_name, "building caller-callee file $outfile");

#------------------------------------------------------------------------------
# Generate some of the structures used in the HTML output.
#------------------------------------------------------------------------------
  $file_title  = "Caller-callee overview";
  $html_header = ${ create_html_header (\$file_title) };
  $html_home   = ${ generate_home_link ("right") };

  $page_title    = "Caller Callee View";
  $size_text     = "h2"; 
  $position_text = "center";
  $html_title_header = ${ generate_a_header (\$page_title, \$size_text, \$position_text) };
  
#------------------------------------------------------------------------------
# Read all of the file into array with the name caller_callee_data.
#------------------------------------------------------------------------------
  chomp (@caller_callee_data = <CALLER_CALLEE_IN>);

#------------------------------------------------------------------------------
# Typical structure of the input file:
#
# Current metrics: address:name:e.totalcpu:e.cycles:e+insts:e+llm
# Current Sort Metric: Exclusive Total CPU Time ( e.totalcpu )
# Functions sorted by metric: Exclusive Total CPU Time
# Callers and callees sorted by metric: Attributed Total CPU Time
# 
# PC Addr.       Name              Attr.     Attr. CPU  Attr.         Attr.
#                                  Total     Cycles     Instructions  Last-Level
#                                  CPU sec.   sec.      Executed      Cache Misses
# 1:0x00000000  *<Total>           3.502     4.005      15396819700   24024250
# 7:0x00008070   start_thread      3.342     3.865      14500538981   23824045
# 6:0x000233a0   __libc_start_main 0.160     0.140        896280719     200205
# 
# PC Addr.       Name              Attr.     Attr. CPU  Attr.         Attr.
#                                  Total     Cycles     Instructions  Last-Level
#                                  CPU sec.   sec.      Executed      Cache Misses
# 2:0x000021f9   driver_mxv        3.342     3.865      14500538981   23824045
# 2:0x000021ae  *mxv_core          3.342     3.865      14500538981   23824045
#------------------------------------------------------------------------------

#------------------------------------------------------------------------------
# Scan the input file.  The first lines are assumed to be part of the header,
# so we store those. The diagnostic lines that echo some settings are also
# stored, but currently not used. 
#------------------------------------------------------------------------------
  my $scan_header = $FALSE;
  my $scan_caller_callee_data = $FALSE;
  my $data_function_block = "";
  my @function_blocks = ();
  my $first = $TRUE;
  my @html_caller_callee = ();
  my @top_level_header = ();

#------------------------------------------------------------------------------
# The regexes.
#------------------------------------------------------------------------------
  my $empty_line_regex       = '^\s*$';
  my $line_of_interest_regex = '\s*(\d+:0x[a-fA-F0-9]+)\s+(\**)(.*)';
  my $get_hex_address_regex  = '(\d+):0x(\S+)';
  my $get_metric_field_regex = ')\s+([\s\d' . $decimal_separator . ']*)';
  my $header_name_regex      = '(.*\.)(\s+)(Name)\s+(.*)';
  my $sorted_by_regex        = 'sorted by metric:';
  my $current_regex          = '^Current';
  my $get_addr_offset_regex  = '^@\d+:';

#------------------------------------------------------------------------------
# Get the length of the first metric field across all lines.  This value is 
# used to pad the first metric with spaces and get the alignment right.
#
# Scan the input data and find the line(s) with metric values.  A complication
# is that a function name may consists of more than one field.
#
# Note.  This part could be used to parse the other elements of the input file,
# but that makes the loop very complicated.   Instead, we re-scan the data 
# below and process each block separately.
#
# Since this data is all in memory and relatively small, the performance should
# not suffer much, but it does improve the readability of the code.
#------------------------------------------------------------------------------
  gp_message ("debug", $subr_name, "determine the maximum length of the first field");

  $g_max_length_first_metric = 0;
  my @hex_addresses = ();
  my @special_marker = ();
  my @the_function_name = ();
  my @the_metrics = ();
  my @length_first_metric = ();

  for (my $line = 0; $line <= $#caller_callee_data; $line++)
    {
      my $input_line = $caller_callee_data[$line];

      if ($input_line =~ /$line_of_interest_regex/)
        {
          if (defined ($1) and defined ($2) and defined ($3))
#------------------------------------------------------------------------------
# This is a line of interest, since it has the address, the function name and 
# the values for the metrics.  Examples of valid lines are:
#
#  2:0x00005028  *xfree_large                             0.              0
# 12:0x0004c2b0   munmap                                  0.143     6402086
#  7:0x0001b2df   <static>@0x1b2df (<libgomp.so.1.0.0>)   0.              0 
#
# The function name marked with a * is the current target.
#------------------------------------------------------------------------------
            {
              my $full_hex_address = $1;
              my $marker           = $2;
              my $remaining_line   = $3;

              if ($full_hex_address =~ /$get_hex_address_regex/)
                {
                  $hex_address = "0x" . $2;
                  push (@hex_addresses, $hex_address); 
                  gp_message ("debugXL", $subr_name, "pushed $hex_address");
                }
              else
                {
                  my $msg = "full_hex_address = $full_hex_address has an unknown format";
                  gp_message ("assertion", $subr_name, $msg);
                }
              if ($marker eq "*")
                {
                  push (@special_marker, "*"); 
                }
              else
                {
                  push (@special_marker, "X"); 
                }
            }
          else
            {
              my $msg = "input_line = $input_line has an unknown format";
              gp_message ("assertion", $subr_name, $msg);
            }

          my @fields_in_line = split (" ", $input_line);

#------------------------------------------------------------------------------
# We stripped the address and marker (if any), off, so this string starts with
# the function name.
#------------------------------------------------------------------------------
              my $remainder              = $3;
              my $number_of_fields       = scalar (@fields_in_line);
              my $words_in_function_name = $number_of_fields - $number_of_metrics - 1;
              my @remainder_array        = split (" ", $remainder);

#------------------------------------------------------------------------------
# If the first metric is 0. (or 0, depending on the locale), the calculation
# of the length needs to be adjusted, because 0. is really 0.000.
#
# While we could easily add 3 to the length, we assign a symbolic value to the
# first metric (ZZZ) and then compute the length.  This makes things clearer.
# I hope ;-)
#------------------------------------------------------------------------------
              my $first_metric = $remainder_array[$words_in_function_name];
              if ($first_metric =~ /^0$decimal_separator$/)
                {
                  gp_message ("debugXL", $subr_name, "fixed up $first_metric");
                  $first_metric = "0.ZZZ";
                }
              push (@length_first_metric, length ($first_metric));

              my $txt = "words in function name = $words_in_function_name ";
              $txt   .= "first_metric = $first_metric length = ";
              $txt   .= length ($first_metric);
              gp_message ("debugXL", $subr_name, $txt);

#------------------------------------------------------------------------------
# Generate the regex for the metrics. 
#
# TBD: This should be an attribute of the function and be done once only.
#------------------------------------------------------------------------------
              my $m_regex = '(\S+';
              for my $f (2 .. $words_in_function_name)
                 {
                   $m_regex .= '\s+\S+';
                 }
#------------------------------------------------------------------------------
# This last part captures all the metric values.
#------------------------------------------------------------------------------
              $m_regex .= $get_metric_field_regex;
              gp_message ("debugXL", $subr_name, "m_regex = $m_regex");
              gp_message ("debugXL", $subr_name, "remainder = $remainder");

              if ($remainder =~ /$m_regex/)
                {
                  my $func_name   = $1;
                  my $its_metrics = $2;
                  my $msg = "found the info - func_name = " . $func_name .
                            " its metrics = " . $its_metrics;
                  gp_message ("debugXL", $subr_name, $msg);

                  push (@the_function_name, $func_name); 
                  push (@the_metrics, $its_metrics); 
                }
              else
                {
                  my $msg = "remainder string $remainder has an unrecognized format";
                  gp_message ("assertion", $subr_name, $msg);
                }

              $g_max_length_first_metric = max ($g_max_length_first_metric, length ($first_metric));

              my $msg = "first_metric = $first_metric " .
                        "g_max_length_first_metric = $g_max_length_first_metric";
              gp_message ("debugXL", $subr_name, $msg);
        }
    }
  gp_message ("debugXL", $subr_name, "final: g_max_length_first_metric = $g_max_length_first_metric");
  gp_message ("debugXL", $subr_name, "#hex_addresses = $#hex_addresses");

#------------------------------------------------------------------------------
# Main loop over the input data.
#------------------------------------------------------------------------------
  my $index_start = 0;  # 1
  my $index_end   = -1;  # 0
  for (my $line = 0; $line <= $#caller_callee_data; $line++)
    {
      my $input_line = $caller_callee_data[$line];

      if ($input_line =~ /$header_name_regex/)
        {
          $scan_header = $TRUE;
          gp_message ("debugXL", $subr_name, "line = $line encountered start of the header scan_header = $scan_header first = $first");
        }
      elsif (($input_line =~ /$sorted_by_regex/) or ($input_line =~ /$current_regex/))
        {
          my $msg =  "line = " . $line . " captured top level header: " .
                     "input_line = " . $input_line;
          gp_message ("debugXL", $subr_name, $msg);

          push (@top_level_header, $input_line);
        }
      elsif ($input_line =~ /$line_of_interest_regex/)
        {
          $index_end++;
          $scan_header             = $FALSE;
          $scan_caller_callee_data = $TRUE;
          $data_function_block    .= $separator . $input_line;

          my $msg = "line = $line updated index_end   = $index_end";
          gp_message ("debugXL", $subr_name, $msg);
        }
      elsif (($input_line =~ /$empty_line_regex/) and ($scan_caller_callee_data))
        {
#------------------------------------------------------------------------------
# An empty line is interpreted as the end of the current block and we process
# this, including the generation of the html code for this block.
#------------------------------------------------------------------------------
          $first = $FALSE;
          $scan_caller_callee_data = $FALSE;

          gp_message ("debugXL", $subr_name, "new block");
          gp_message ("debugXL", $subr_name, "line = $line index_start = $index_start");
          gp_message ("debugXL", $subr_name, "line = $line index_end   = $index_end");
          gp_message ("debugXL", $subr_name, "line = $line data_function_block = $data_function_block");

          push (@function_blocks, $data_function_block);
          my ($html_block_prologue_ref, $html_code_function_block_ref) = 
                                                generate_html_function_blocks (
                                                  \$index_start,
                                                  \$index_end,
                                                  \@hex_addresses,
                                                  \@the_metrics,
                                                  \@length_first_metric,
                                                  \@special_marker,
                                                  \@the_function_name,
                                                  \$separator,
                                                  $number_of_metrics_ref,
                                                  \$data_function_block,
                                                  $function_info_ref,
                                                  $function_view_structure_ref);

          my @html_block_prologue = @{ $html_block_prologue_ref };
          my @html_code_function_block = @{ $html_code_function_block_ref };

          for my $lines (0 .. $#html_code_function_block)
            {
              my $msg = "final html_code_function_block[" . $lines . "] = " .
                        $html_code_function_block[$lines];
              gp_message ("debugXL", $subr_name, $msg);
            }

          $data_function_block = "";

          push (@html_caller_callee, @html_block_prologue);
          push (@html_caller_callee, @header_lines);
          push (@html_caller_callee, @html_code_function_block);

          $index_start = $index_end + 1;
          $index_end   = $index_start - 1;
          gp_message ("debugXL", $subr_name, "line = $line reset index_start = $index_start");
          gp_message ("debugXL", $subr_name, "line = $line reset index_end   = $index_end");
        }

#------------------------------------------------------------------------------
# Only capture the first header.  They are all identical.
#------------------------------------------------------------------------------
      if ($scan_header and $first)
        {
          if (defined ($4))
            {
#------------------------------------------------------------------------------
# This group is only defined for the first line of the header.
#------------------------------------------------------------------------------
              gp_message ("debugXL", $subr_name, "header1 = $4");
              gp_message ("debugXL", $subr_name, "extra   = $3 spaces=x$2x");
              my $newline = "<b>" . $4 . "</b>";
              push (@header_lines, $newline);
            }
          elsif ($input_line =~ /\s*(.*)/)
            {
#------------------------------------------------------------------------------
# Capture the subsequent header lines.
#------------------------------------------------------------------------------
              gp_message ("debugXL", $subr_name, "headern = $1");
              my $newline = "<b>" . $1 . "</b>";
              push (@header_lines, $newline);
            }
        }

    }

  for my $i (0 .. $#header_lines)
    {
      gp_message ("debugXL", $subr_name, "header_lines[$i] = $header_lines[$i]");
    }
  for my $i (0 .. $#function_blocks)
    {
      gp_message ("debugXL", $subr_name, "function_blocks[$i] = $function_blocks[$i]");
    }

  my $number_of_blocks = $#function_blocks + 1;
  gp_message ("debugXL", $subr_name, "There are " . $number_of_blocks . " function blocks:");

  for my $i (0 .. $#function_blocks)
    {
#------------------------------------------------------------------------------
# The split produces an empty first field and is why we skip the first field.
#------------------------------------------------------------------------------
##      my @entries = split ("cuthere", $function_blocks[$i]);
      my @entries = split ($separator, $function_blocks[$i]);
      for my $k (1 .. $#entries)
        {
          my $msg = "entries[" . $k . "] = ". $entries[$k];
          gp_message ("debugXL", $subr_name, $k . $msg);
        }
    }

#------------------------------------------------------------------------------
# Parse and process the individual function blocks.
#------------------------------------------------------------------------------
  for my $i (0 .. $#function_blocks)
    {
      my $msg = "function_blocks[" . $i . "] = ". $function_blocks[$i];
      gp_message ("debugXL", $subr_name, $msg);
#------------------------------------------------------------------------------
# This split produces an empty first field.  This is why skip this.
#------------------------------------------------------------------------------
      my @entries = split ($separator, $function_blocks[$i]);

#------------------------------------------------------------------------------
# An example of @entries:
# <empty>
# 6:0x0003ad20   drand48           0.100     0.084        768240570          0
# 6:0x0003af50  *erand48_r         0.080     0.084        768240570          0
# 6:0x0003b160   __drand48_iterate 0.020     0.                   0          0
#------------------------------------------------------------------------------
      for my $k (1 .. $#entries)
        {
          my $input_line = $entries[$k];

          my $msg = "input_line = entries[" . $k . "] = ". $entries[$k];
          gp_message ("debugXL", $subr_name, $msg);

          @fields = split (" ", $input_line);

          $no_of_fields = $#fields + 1;
          $elements_in_name = $no_of_fields - $number_of_metrics - 1;
     
#------------------------------------------------------------------------------
# TBD: Too restrictive.
# CHECK CODE IN GENERATE_CALLER_CALLEE
#------------------------------------------------------------------------------
          if ($elements_in_name == 1) 
            {
              $name_regex = '\s*(\d+:0x[a-fA-F0-9]+)\s+([\s\*])(\S+)\s+(.*)';
            }
          elsif ($elements_in_name == 2) 
            {
              $name_regex = '\s*(\d+:0x[a-fA-F0-9]+)\s+([\s\*])((\S+)\s+(\S+))\s+(.*)';
            }
          else
#------------------------------------------------------------------------------
# TBD: Handle this better in case a function entry has more than 2 words.
#------------------------------------------------------------------------------
            {
              my $msg = "$elements_in_name elements in name exceeds limit";
              gp_message ("assertion", $subr_name, $msg);
            }

          if ($input_line =~ /$name_regex/)
            {
              $full_hex_address = $1;
              $marker_target_function = $2;
              $routine = $3;
              if ($elements_in_name == 1) 
                {
                  $all_metrics = $4;
                }
              elsif ($elements_in_name == 2) 
                {
                  $all_metrics = $6;
                }

              $metrics_length = length ($all_metrics);
              $max_metrics_length = max ($max_metrics_length, $metrics_length);

              if ($full_hex_address =~ /(\d+):0x(\S+)/)
                {
                  $hex_address = "0x" . $2;
                }
              push (@marker, $marker_target_function);
              push (@address_field, $hex_address); 
              $modified_line = $all_metrics . " " . $routine;
              push (@metric_values, $all_metrics);
              gp_message ("debugXL", $subr_name, "xxxxxxx = $modified_line");
              push (@function_names, $routine);
            }
        }

      $total_header_lines = $#header_lines + 1;
      gp_message ("debugXL", $subr_name, "total_header_lines = $total_header_lines");

      gp_message ("debugXL", $subr_name, "Final output");
      for my $i (keys @header_lines)
        {
          gp_message ("debugXL", $subr_name, "$header_lines[$i]");
        }
      for my $i (0 .. $#function_names)
        {
          my $msg = $metric_values[$i] . " " . $marker[$i] .
                    $function_names[$i] . "(" . $address_field[$i] . ")";
          gp_message ("debugXL", $subr_name, $msg);
        }
#------------------------------------------------------------------------------
# Check if this function has multiple occurrences.
# TBD: Replace by the function call for this.
#------------------------------------------------------------------------------
      gp_message ("debugXL", $subr_name, "check for multiple occurrences");
      for my $i (0 .. $#function_names)
        {
          my $current_address = $address_field[$i];
          my $found_a_match;
          my $ref_index;
          my $alt_name;
          $routine = $function_names[$i];
          $alt_name = $routine;
          gp_message ("debugXL", $subr_name, "checking for routine = $routine");
          if (exists ($g_multi_count_function{$routine}))
            {

#------------------------------------------------------------------------------
# TBD: Scan all of the function_info list. Or beter: add index to g_multi_count_function!!
#------------------------------------------------------------------------------

              $found_a_match = $FALSE;
              gp_message ("debugXL", $subr_name, "$routine: occurrences = $g_function_occurrences{$routine}");
              for my $ref (keys @{ $g_map_function_to_index{$routine} })
                {
                  $ref_index = $g_map_function_to_index{$routine}[$ref];

                  gp_message ("debugXL", $subr_name, "$routine: retrieving duplicate entry at ref_index = $ref_index");
                  gp_message ("debugXL", $subr_name, "$routine: function_info[$ref_index]{'alt_name'} = $function_info[$ref_index]{'alt_name'}");

                  my $addr_offset = $function_info[$ref_index]{"addressobjtext"};
                  gp_message ("debugXL", $subr_name, "$routine: addr_offset = $addr_offset");
  
                  $addr_offset =~ s/$get_addr_offset_regex//;
                  gp_message ("debugXL", $subr_name, "$routine: addr_offset = $addr_offset");
                  if ($addr_offset eq $current_address)
                    {
                      $found_a_match = $TRUE;
                      last;
                    }
                }
              gp_message ("debugXL", $subr_name, "$function_info[$ref_index]{'alt_name'} is the actual function for i = $i $found_a_match");
              $alt_name = $function_info[$ref_index]{'alt_name'};
            }
          gp_message ("debugXL", $subr_name, "alt_name = $alt_name");
        }
      gp_message ("debugXL", $subr_name, "completed check for multiple occurrences");

#------------------------------------------------------------------------------
# Figure out the column width.  Since the columns in the header may include
# spaces, we use the first line with metrics for this.
#------------------------------------------------------------------------------
      my $top_header = $metric_values[0];
      my $word_index_values_ref = find_words_in_line (\$top_header);
      my @word_index_values = @{ $word_index_values_ref };

# $i = 0 0 4
# $i = 1 10 14
# $i = 2 21 31
# $i = 3 35 42
      for my $i (keys @word_index_values)
        {
          gp_message ("debugXL", $subr_name, "i = $i $word_index_values[$i][0] $word_index_values[$i][1]");
        }
    }

  push (@html_metric_sort_header, "<i>");
  for my $i (0 .. $#top_level_header)
    {
      $html_line = $top_level_header[$i] . "<br>";
      push (@html_metric_sort_header, $html_line);
    }
  push (@html_metric_sort_header, "</i>");

  print CALLER_CALLEE_OUT $html_header;
  print CALLER_CALLEE_OUT $html_home;
  print CALLER_CALLEE_OUT $html_title_header;
  print CALLER_CALLEE_OUT "$_" for @g_html_experiment_stats;
##  print CALLER_CALLEE_OUT "<br>\n";
##  print CALLER_CALLEE_OUT "$_\n" for @html_metric_sort_header;
  print CALLER_CALLEE_OUT "<pre>\n";
  print CALLER_CALLEE_OUT "$_\n" for @html_caller_callee;
  print CALLER_CALLEE_OUT "</pre>\n";

#-------------------------------------------------------------------------------
# Get the acknowledgement, return to main link, and final html statements.
#-------------------------------------------------------------------------------
  $html_home            = ${ generate_home_link ("left") };
  $html_acknowledgement = ${ create_html_credits () };
  $html_end             = ${ terminate_html_document () };

  print CALLER_CALLEE_OUT $html_home;
  print CALLER_CALLEE_OUT "<br>\n";
  print CALLER_CALLEE_OUT $html_acknowledgement;
  print CALLER_CALLEE_OUT $html_end;

  close (CALLER_CALLEE_OUT);

  return (0);

} #-- End of subroutine generate_caller_callee

#------------------------------------------------------------------------------
# Generate the html version of the disassembly file.
#
# Note to self (TBD)
# https://software.intel.com/content/www/us/en/develop/blogs/intel-release-new-technology-specifications-protect-rop-attacks.html
#------------------------------------------------------------------------------
sub generate_dis_html
{
  my $subr_name = get_my_name ();

  my ($target_function_ref, $number_of_metrics_ref, $function_info_ref, 
      $function_address_and_index_ref, $outputdir_ref, $func_ref, 
      $source_line_ref, $metric_ref, $addressobj_index_ref) = @_;

  my $target_function            = ${ $target_function_ref };
  my $number_of_metrics          = ${ $number_of_metrics_ref };
  my @function_info              = @{ $function_info_ref };
  my %function_address_and_index = %{ $function_address_and_index_ref };
  my $outputdir                  = ${ $outputdir_ref };
  my $func                       = ${ $func_ref };
  my @source_line                = @{ $source_line_ref };
  my @metric                     = @{ $metric_ref };
  my %addressobj_index           = %{ $addressobj_index_ref };

  my $dec_instruction_start;
  my $dec_instruction_end;
  my $hex_instruction_start;
  my $hex_instruction_end;

  my @colour_line = ();
  my $hot_line; 
  my $metric_values; 
  my $src_line;
  my $dec_instr_address; 
  my $instruction;
  my $operands;
 
  my $html_new_line = "<br>";
  my $add_new_line_before;
  my $add_new_line_after; 
  my $address_key; 
  my $boldface;
  my $file;
  my $filename = $func;
  my $func_name;
  my $orig_hex_instr_address; 
  my $hex_instr_address; 
  my $index_string;
  my $input_metric;
  my $linenumber;
  my $name;
  my $last_address; 
  my $last_address_in_hex; 

  my $file_title; 
  my $html_header;
  my $html_home;
  my $html_end;
  
  my $branch_regex     = $g_arch_specific_settings{"regex"};
  my $convert_to_dot    = $g_locale_settings{"convert_to_dot"};
  my $decimal_separator = $g_locale_settings{"decimal_separator"};
  my $hp_value          = $g_user_settings{"highlight_percentage"}{"current_value"};
  my $linksubexp        = $g_arch_specific_settings{"linksubexp"};
  my $subexp            = $g_arch_specific_settings{"subexp"};

  my $is_empty;

  my %branch_target = ();
  my %branch_target_no_ref = ();
  my @disassembly_file = ();
  my %extended_branch_target = ();
  my %inverse_branch_target = ();
  my @metrics = ();
  my @modified_html = ();

  my $branch_target_ref;
  my $extended_branch_target_ref;
  my $branch_target_no_ref_ref;

  my $branch_address; 
  my $dec_branch_address; 
  my $found_it;
  my $found_it_ref;
  my $func_name_in_dis_file;
  my $hex_branch_target;
  my $instruction_address; 
  my $instruction_offset; 
  my $link;
  my $modified_line;
  my $raw_hex_branch_target;
  my $src_line_ref;
  my $threshold_line;
  my $html_dis_out = $func . ".html";

#------------------------------------------------------------------------------
# The regex section.
#------------------------------------------------------------------------------
  my $call_regex = '.*([0-9a-fA-F]*):\s+(call)\s*0x([0-9a-fA-F]+)';
  my $line_of_interest_regex = '^#*\s+([\d' . $decimal_separator . '\s+]+)\[\s*(\d+|\?)\]';
  my $white_space_regex = '\s+';
  my $first_integer_regex = '^\d+$';
  my $integer_regex = '\d+';
  my $qmark_regex = '\?';
  my $src_regex = '(\s*)(\d+)\.(.*)';
  my $function_regex = '^(\s*)<Function:\s(.*)>';
  my $end_src_header_regex = "(^\\s+)(\\d+)\\.\\s+(.*)";
  my $end_dis_header_regex = "(^\\s+)(<Function: )(.*)>";
  my $control_flow_1_regex = 'j[a-z]+';
  my $control_flow_2_regex = 'call';
  my $control_flow_3_regex = 'ret';

##  my $function_call_regex2 = '(.*)\s+([0-9a-fA-F]*):\s+(call)\s*0x([0-9a-fA-F]+)\s*';
##  my $endbr_regex          = '\.*([0-9a-fA-F]*):\s+(endbr[32|64])';
#------------------------------------------------------------------------------
# Dynamic. Computed below.
#
# TBD: Try to move these up.
#------------------------------------------------------------------------------
  my $dis_regex;
  my $metric_regex;

  gp_message ("debug", $subr_name, "g_branch_regex = $g_branch_regex");
  gp_message ("debug", $subr_name, "call_regex = $call_regex");
  gp_message ("debug", $subr_name, "g_function_call_v2_regex = $g_function_call_v2_regex");

  my $the_title = set_title ($function_info_ref, $func, "disassembly");

  gp_message ("debug", $subr_name, "the_title = $the_title");

  $file_title      = $the_title;
  $html_header     = ${ create_html_header (\$file_title) };
  $html_home       = ${ generate_home_link ("right") };

  push (@modified_html, $html_header);
  push (@modified_html, $html_home);
  push (@modified_html, "<pre>");
 
#------------------------------------------------------------------------------
# Open the input and output files.
#------------------------------------------------------------------------------
  open (INPUT_DISASSEMBLY, "<", $filename) 
    or die ("$subr_name - unable to open disassembly file $filename for reading: '$!'");
  gp_message ("debug", $subr_name , "opened file $filename for reading");

  open (HTML_OUTPUT, ">", $html_dis_out)
    or die ("$subr_name - unable to open file $html_dis_out for writing: '$!'");
  gp_message ("debug", $subr_name , "opened file $html_dis_out for writing");

#------------------------------------------------------------------------------
# Check if the file is empty
#------------------------------------------------------------------------------
  $is_empty = is_file_empty ($filename);
  if ($is_empty)
    {

#------------------------------------------------------------------------------
# The input file is empty.  Write a message in the html file and exit.
#------------------------------------------------------------------------------
      gp_message ("debug", $subr_name ,"file $filename is empty");

      my $comment = "No disassembly generated by $tool_name - file $filename is empty";
      my $gp_error_file = $outputdir . "gp-listings.err";

      my $html_empty_file_ref = html_text_empty_file (\$comment, \$gp_error_file);
      my @html_empty_file = @{ $html_empty_file_ref };

      print HTML_OUTPUT "$_\n" for @html_empty_file;

      close (HTML_OUTPUT);

      return (\@source_line);
    }
  else
    {

#------------------------------------------------------------------------------
# Read the file into memory.
#------------------------------------------------------------------------------
      chomp (@disassembly_file = <INPUT_DISASSEMBLY>);
      gp_message ("debug", $subr_name ,"read file $filename into memory");
    }

  my $max_length_first_metric = 0;
  my $src_line_no;

#------------------------------------------------------------------------------
# First scan through the assembly listing.
#------------------------------------------------------------------------------
  for (my $line_no=0; $line_no <= $#disassembly_file; $line_no++)
    {
      my $input_line = $disassembly_file[$line_no];
      gp_message ("debugXL", $subr_name, "[line $line_no] $input_line");

      if ($input_line =~ /$line_of_interest_regex/)
        {

#------------------------------------------------------------------------------
# Found a matching line.  Examples are:
#      0.370                [37]   4021d1:  addsd  %xmm0,%xmm1
#   ## 1.001                [36]   4021d5:  add    $0x1,%rax
#------------------------------------------------------------------------------
          gp_message ("debugXL", $subr_name, "selected line \$1 = $1 \$2 = $2");

          if (defined ($2) and defined($1))
            {
              @metrics = split (/$white_space_regex/ ,$1);
              $src_line_no = $2;
            }
          else 
            {
              my $msg = "$input_line has an unexpected format";
              gp_message ("assertion", $subr_name, $msg);
            }

#------------------------------------------------------------------------------
# Compute the maximum length of the first metric and pad the field from the 
# left later on.  The fractional part is ignored.
#------------------------------------------------------------------------------
          my $first_metric = $metrics[0];
          my $new_length; 
          if ($first_metric =~ /$first_integer_regex/)
            {
              $new_length = length ($first_metric);
            }
          else
            {
              my @fields = split (/$decimal_separator/, $first_metric);
              $new_length = length ($fields[0]);
            }
          $max_length_first_metric = max ($max_length_first_metric, $new_length);
          my $msg;
          $msg = "first_metric = $first_metric " .
                 "max_length_first_metric = $max_length_first_metric";
          gp_message ("debugXL", $subr_name, $msg);

          if ($src_line_no !~ /$qmark_regex/)
#------------------------------------------------------------------------------
# The source code line number is known and is stored.
#------------------------------------------------------------------------------
            {
              $source_line[$line_no] = $src_line_no;
              my $msg; 
              $msg  = "found an instruction with a source line ref: ";
              $msg .= "source_line[$line_no] = $source_line[$line_no]";
              gp_message ("debugXL", $subr_name, $msg);
            }
            
#------------------------------------------------------------------------------
# Check for function calls.  If found, get the address offset from $4 and 
# compute the target address.
#------------------------------------------------------------------------------
          ($found_it_ref, $branch_target_ref, $extended_branch_target_ref) = 
                                                 check_and_proc_dis_func_call (
                                                   \$input_line,
                                                   \$line_no, 
                                                   \%branch_target,
                                                   \%extended_branch_target);
          $found_it = ${ $found_it_ref };

          if ($found_it)
            {
              %branch_target = %{ $branch_target_ref };
              %extended_branch_target = %{ $extended_branch_target_ref };
            }

#------------------------------------------------------------------------------
# Look for a branch instruction, or the special endbr32/endbr64 instruction
# that is also considered to be a branch target.  Note that the latter is x86
# specific.
#------------------------------------------------------------------------------
          ($found_it_ref, $branch_target_ref, $extended_branch_target_ref,
           $branch_target_no_ref_ref) = check_and_proc_dis_branches (
                                               \$input_line,
                                               \$line_no, 
                                               \%branch_target,
                                               \%extended_branch_target,
                                               \%branch_target_no_ref);
          $found_it = ${ $found_it_ref };

          if ($found_it)
            {
              %branch_target = %{ $branch_target_ref };
              %extended_branch_target = %{ $extended_branch_target_ref };
              %branch_target_no_ref = %{ $branch_target_no_ref_ref };
            }
        }
    } #-- End of loop over line_no

  %inverse_branch_target = reverse (%extended_branch_target);

  gp_message ("debug", $subr_name, "generated inverse of branch target structure");
  gp_message ("debug", $subr_name, "completed parsing file $filename");

  for my $key (sort keys %branch_target)
    {
      gp_message ("debug", $subr_name, "branch_target{$key} = $branch_target{$key}");
    }
  for my $key (sort keys %extended_branch_target)
    {
      gp_message ("debug", $subr_name, "extended_branch_target{$key} = $extended_branch_target{$key}");
    }
  for my $key (sort keys %inverse_branch_target)
    {
      gp_message ("debug", $subr_name, "inverse_branch_target{$key} = $inverse_branch_target{$key}");
    }
  for my $key (sort keys %branch_target_no_ref)
    {
      gp_message ("debug", $subr_name, "branch_target_no_ref{$key} = $branch_target_no_ref{$key}");
      $inverse_branch_target{$key} = $key;
    }
  for my $key (sort keys %inverse_branch_target)
    {
      gp_message ("debug", $subr_name, "inverse_branch_target{$key} = $inverse_branch_target{$key}");
    }

#------------------------------------------------------------------------------
# Process the disassembly.
#------------------------------------------------------------------------------

#------------------------------------------------------------------------------
# Dynamically generate the regexes.
#------------------------------------------------------------------------------
  $metric_regex = '';
  for my $metric_used (1 .. $number_of_metrics)
    {
      $metric_regex .= '(\d+' . $decimal_separator . '*\d*)\s+';
    }

  $dis_regex  = '^(#{2}|\s{2})\s+';
  $dis_regex .= '(.*)';
##  $dis_regex .= '\[\s*([0-9?]+)\]\s+([0-9a-fA-F]+):\s+([a-z0-9]+)\s+(.*)';
  $dis_regex .= '\[\s*([0-9?]+)\]\s+([0-9a-fA-F]+):\s+([a-z0-9]+)(.*)';

  gp_message ("debugXL", $subr_name, "metric_regex = $metric_regex");
  gp_message ("debugXL", $subr_name, "dis_regex    = $dis_regex");
  gp_message ("debugXL", $subr_name, "src_regex    = $src_regex");
  gp_message ("debugXL", $subr_name, "contents of lines array");

#------------------------------------------------------------------------------
# Identify the header lines.  Make the minimal assumptions.
#
# In both cases, the first line after the header has whitespace.  This is
# followed by:
#
# - A source line file has "<line_no>." 
# - A dissasembly file has "<Function:"
#
# These are the characteristics we use below.
#------------------------------------------------------------------------------
  for (my $line_no=0; $line_no <= $#disassembly_file; $line_no++)
    {
      my $input_line = $disassembly_file[$line_no];
      gp_message ("debugXL", $subr_name, "[line $line_no] $input_line");

      if ($input_line =~ /$end_src_header_regex/)
        {
          gp_message ("debugXL", $subr_name, "header time is over - hit source line\n");
          gp_message ("debugXL", $subr_name, "$1 $2 $3\n");
          last;
        }
      if ($input_line =~ /$end_dis_header_regex/)
        {
          gp_message ("debugXL", $subr_name, "header time is over - hit disassembly line\n");
          last;
        }
      push (@modified_html, "<i>" . $input_line . "</i>");
      
    }
  my $line_index = scalar (@modified_html);
  gp_message ("debugXL", $subr_name, "final line_index = $line_index");

  for (my $line_no=0; $line_no <= $line_index-1; $line_no++)
    {
      my $msg = " modified_html[$line_no] = $modified_html[$line_no]";
      gp_message ("debugXL", $subr_name, $msg);
    }

#------------------------------------------------------------------------------
# Source line:
#  20.       for (int64_t r=0; r<repeat_count; r++) {
#
# Disassembly:
#    0.340                [37]   401fec:  addsd   %xmm0,%xmm1
# ## 1.311                [36]   401ff0:  addq    $1,%rax
#------------------------------------------------------------------------------

#------------------------------------------------------------------------------
# Find the hot PCs and store them.
#------------------------------------------------------------------------------
  my @hot_program_counters = ();
  my @transposed_hot_pc = ();
  my @max_metric_values = ();

  gp_message ("debug", $subr_name, "determine the maximum metric values");
  for (my $line_no=$line_index-1; $line_no <= $#disassembly_file; $line_no++)
    {
      my $input_line = $disassembly_file[$line_no];

      if ( $input_line =~ /$dis_regex/ )
        {
##          if ( defined ($1) and defined ($2) and defined ($3) and
##               defined ($4) and defined ($5) and defined ($6) )
          if ( defined ($1) and defined ($2) and defined ($3) and
               defined ($4) and defined ($5) )
            {
              $hot_line      = $1;
              $metric_values = $2;
              $src_line      = $3;
              $dec_instr_address = bigint::hex ($4);
              $instruction   = $5;
              if (defined ($6))
                {
                  my $white_space_regex = '\s*';
                  $operands = $6;
                  $operands =~ s/$white_space_regex//;
                }

              if ($hot_line eq "##")
                {
                  my @metrics = split (" ", $metric_values);
                  push (@hot_program_counters, [@metrics]);
                }
            }
        }
    }
  for my $row (keys @hot_program_counters)
    {
      my $msg = "$filename row[" . $row . "] = ";
      for my $col (keys @{$hot_program_counters[$row]})
        {
          $msg .= "$hot_program_counters[$row][$col] "; 
          $transposed_hot_pc[$col][$row] = $hot_program_counters[$row][$col]; 
        }
      gp_message ("debugXL", $subr_name, "hot PC = $msg");
    }
  for my $row (keys @transposed_hot_pc)
    {
      my $msg = "$filename row[" . $row . "] = ";
      for my $col (keys @{$transposed_hot_pc[$row]})
        {
          $msg .= "$transposed_hot_pc[$row][$col] "; 
        }
      gp_message ("debugXL", $subr_name, "$filename transposed = $msg");
    }
#------------------------------------------------------------------------------
# Get the maximum metric values and if integer, convert to floating-point.
# Since it is easier, we transpose the array and access it over the columns.
#------------------------------------------------------------------------------
  for my $row (0 .. $#transposed_hot_pc)
    {
      my $max_val = 0;
      for my $col (0 .. $#{$transposed_hot_pc[$row]})
        {
          $max_val = max ($transposed_hot_pc[$row][$col], $max_val);;
        }
      if ($max_val =~ /$integer_regex/)
        {
          $max_val = sprintf ("%f", $max_val);
        }
      gp_message ("debugXL", $subr_name, "$filename row = $row max_val = $max_val");
      push (@max_metric_values, $max_val);
    }

    for my $metric (0 .. $#max_metric_values)
      {
        my $msg = "$filename maximum[$metric] = $max_metric_values[$metric]";
        gp_message ("debugM", $subr_name, $msg);
      }

#------------------------------------------------------------------------------
# TBD - Integrate this better.
#
# Scan the instructions to find the instruction address range.  This is used
# to determine if a branch is external to this function.
#------------------------------------------------------------------------------
  $dec_instruction_start = undef;
  $dec_instruction_end   = undef;
  for (my $line_no=$line_index-1; $line_no <= $#disassembly_file; $line_no++)
    {
      my $input_line = $disassembly_file[$line_no];
      if ( $input_line =~ /$dis_regex/ )
        {
#          if ( defined ($1) and defined ($2) and defined ($3) and
##               defined ($4) and defined ($5) and defined ($6) )
          if ( defined ($1) and defined ($2) and defined ($3) and
               defined ($4) and defined ($5) )
            {
              $hot_line      = $1;
              $metric_values = $2;
              $src_line      = $3;
              $dec_instr_address = bigint::hex ($4);
              $instruction   = $5;
##              $operands      = $6;
              if (defined ($6))
                {
                  my $white_space_regex = '\s*';
                  $operands = $6;
                  $operands =~ s/$white_space_regex//;
                }

              if (defined ($dec_instruction_start))
                {
                  if ($dec_instr_address < $dec_instruction_start) 
                    {
                      $dec_instruction_start = $dec_instr_address;
                    }
                }
              else
                {
                  $dec_instruction_start = $dec_instr_address;
                }
              if (defined ($dec_instruction_end))
                {
                  if ($dec_instr_address > $dec_instruction_end) 
                    {
                      $dec_instruction_end = $dec_instr_address;
                    }
                }
              else
                {
                  $dec_instruction_end = $dec_instr_address;
                }
            }
        }
    }

  if (defined ($dec_instruction_start) and defined ($dec_instruction_end))
    {
      $hex_instruction_start = sprintf ("%x", $dec_instruction_start);
      $hex_instruction_end = sprintf ("%x", $dec_instruction_end);

      my $msg;
      $msg = "$filename $func dec_instruction_start = " .
             "$dec_instruction_start (0x$hex_instruction_start)";
      gp_message ("debugXL", $subr_name, $msg);
      $msg = "$filename $func dec_instruction_end   = " .
             "$dec_instruction_end (0x$hex_instruction_end)";
      gp_message ("debugXL", $subr_name, $msg);
    }

#------------------------------------------------------------------------------
# This is where all the results from above come together.
#------------------------------------------------------------------------------
  for (my $line_no=$line_index-1; $line_no <= $#disassembly_file; $line_no++)
    {
      my $input_line = $disassembly_file[$line_no];
      gp_message ("debugXL", $subr_name, "input_line[$line_no] = $input_line");
      if ( $input_line =~ /$dis_regex/ )
        {
          gp_message ("debugXL", $subr_name, "found a disassembly line: $input_line");

          if ( defined ($1) and defined ($2) and defined ($3) and
               defined ($4) and defined ($5) )
            {
#                      $branch_target{$hex_branch_target} = 1;
#                      $extended_branch_target{$instruction_address} = $raw_hex_branch_target;
              $hot_line      = $1;
              $metric_values = $2;
              $src_line      = $3;
              $orig_hex_instr_address = $4;
              $instruction   = $5;
##              $operands      = $6;

              my $msg = "disassembly line: $1 $2 $3 $4 $5";
              if (defined ($6))
                {
                  $msg .= " \$6 = $6";
                  my $white_space_regex = '\s*';
                  $operands = $6;
                  $operands =~ s/$white_space_regex//;
                }
              gp_message ("debugXL", $subr_name, $msg);

#------------------------------------------------------------------------------
# Pad the line with the metrics to ensure correct alignment.
#------------------------------------------------------------------------------
              my $the_length; 
              my @split_metrics = split (" ", $metric_values);
              my $first_metric = $split_metrics[0];
##              if ($first_metric =~ /^\d+$/)
              if ($first_metric =~ /$first_integer_regex/)
                {
                  $the_length = length ($first_metric);
                }
              else
                {
                  my @fields = split (/$decimal_separator/, $first_metric);
                  $the_length = length ($fields[0]);
                }
              my $spaces = $max_length_first_metric - $the_length;
              my $pad = "";
              for my $p (1 .. $spaces)
                {
                  $pad .= "&nbsp;";
                }
              $metric_values = $pad . $metric_values;
              gp_message ("debugXL", $subr_name, "pad = $pad");
              gp_message ("debugXL", $subr_name, "metric_values = $metric_values");

#------------------------------------------------------------------------------
# Since the instruction address variable may change and because we need the
# original address without html controls, we use a new variable for the 
# (potentially) modified address.
#------------------------------------------------------------------------------
              $hex_instr_address   = $orig_hex_instr_address;
              $add_new_line_before = $FALSE;
              $add_new_line_after  = $FALSE;

              if ($src_line eq "?")

#------------------------------------------------------------------------------
# There is no source line number.  Do not add a link.
#------------------------------------------------------------------------------
                {
                  $modified_line = $hot_line . ' ' . $metric_values . ' [' . $src_line . '] ';
                  gp_message ("debugXL", $subr_name, "initialized modified_line = $modified_line");
                }
              else
                {
#------------------------------------------------------------------------------
# There is a source line number.  Mark it as link.
#------------------------------------------------------------------------------
                  $src_line_ref = "[<a href='#line_".$src_line."'>".$src_line."</a>]";
                  gp_message ("debugXL", $subr_name, "src_line_ref = $src_line_ref");
                  gp_message ("debugXL", $subr_name, "hex_instr_address = $hex_instr_address");

                  $modified_line = $hot_line . ' ' . $metric_values . ' ' . $src_line_ref . ' ';
                  gp_message ("debugXL", $subr_name, "initialized modified_line = $modified_line");
                }

#------------------------------------------------------------------------------
# Mark control flow instructions.  Several cases need to be distinguished.
#
# In all cases we give the instruction a specific color, mark it boldface
# and add a new-line after the instruction 
#------------------------------------------------------------------------------
              if ( ($instruction =~ /$control_flow_1_regex/)   or
                   ($instruction =~ /$control_flow_2_regex/)   or
                   ($instruction =~ /$control_flow_3_regex/) )
                {
                  gp_message ("debugXL", $subr_name, "instruction = $instruction is a control flow instruction");

                  $add_new_line_after = $TRUE;

                  $boldface = $TRUE;
                  $instruction = color_string ($instruction, $boldface, $g_html_color_scheme{"control_flow"});
                }

              if (exists ($extended_branch_target{$hex_instr_address}))
#------------------------------------------------------------------------------
# This is a branch instruction and we need to add the target address.
#
# In case the target address is outside of this load object, the link is
# colored differently.
#
# TBD: Add the name and if possible, a working link to this code.
#------------------------------------------------------------------------------
                {
                  $branch_address = $extended_branch_target{$hex_instr_address};

                  $dec_branch_address = bigint::hex ($branch_address);

                  if ( ($dec_branch_address >= $dec_instruction_start) and
                       ($dec_branch_address <= $dec_instruction_end) )
#------------------------------------------------------------------------------
# The instruction is within the range.
#------------------------------------------------------------------------------
                    {
                      $link = "[ <a href='#".$branch_address."'>".$branch_address."</a> ]";
                    }
                  else
                    {
#------------------------------------------------------------------------------
# The instruction is outside of the range.  Change the color of the link.
#------------------------------------------------------------------------------
                      gp_message ("debugXL", $subr_name, "address is outside of range");

                      $link = "[ <a href='#".$branch_address;
                      $link .= "' style='color:$g_html_color_scheme{'link_outside_range'}'>";
                      $link .= $branch_address."</a> ]";
                    }
                  gp_message ("debugXL", $subr_name, "address exists new link = $link");

                  $operands .= ' ' . $link;
                  gp_message ("debugXL", $subr_name, "update #1 modified_line = $modified_line");
                }
              if (exists ($branch_target_no_ref{$hex_instr_address}))
                {
                  gp_message ("debugXL", $subr_name, "NEWBR branch_target_no_ref{$hex_instr_address} = $branch_target_no_ref{$hex_instr_address}");
                }
##              if (exists ($inverse_branch_target{$hex_instr_address}) or
##                  exists ($branch_target_no_ref{$hex_instr_address}))
              if (exists ($inverse_branch_target{$hex_instr_address})) 
#------------------------------------------------------------------------------
# This is a target address and we need to define the instruction address to be
# a label.
#------------------------------------------------------------------------------
                {
                  $add_new_line_before = $TRUE;

                  my $branch_target = $inverse_branch_target{$hex_instr_address};
                  my $target = "<a name='".$hex_instr_address."'><b>".$hex_instr_address."</b></a>:";
                  gp_message ("debugXL", $subr_name, "inverse exists - hex_instr_address = $hex_instr_address");
                  gp_message ("debugXL", $subr_name, "inverse exists - add a target target = $target");

                  $hex_instr_address = "<a name='".$hex_instr_address."'><b>".$hex_instr_address."</b></a>";
                  gp_message ("debugXL", $subr_name, "update #2 hex_instr_address = $hex_instr_address");
                  gp_message ("debugXL", $subr_name, "update #2 modified_line     = $modified_line");
                }

              $modified_line .= $hex_instr_address . ': ' . $instruction . ' ' . $operands;

              gp_message ("debugXL", $subr_name, "final modified_line = $modified_line");

#------------------------------------------------------------------------------
# This is a control flow instruction, but it is the last one and we do not 
# want to add a newline.
#------------------------------------------------------------------------------
              gp_message ("debugXL", $subr_name, "decide where the <br> should go in the html");
              gp_message ("debugXL", $subr_name, "add_new_line_after  = $add_new_line_after");
              gp_message ("debugXL", $subr_name, "add_new_line_before = $add_new_line_before");
                
              if ( $add_new_line_after and ($orig_hex_instr_address eq $hex_instruction_end) )
                {
                  $add_new_line_after = $FALSE;
                  gp_message ("debugXL", $subr_name, "$instruction is the last instruction - do not add a newline");
                }

              if ($add_new_line_before)
                {

#------------------------------------------------------------------------------
# Get the previous line, if any, so that we can check what it is.
#------------------------------------------------------------------------------
                  my $prev_line = pop (@modified_html);
                  if ( defined ($prev_line) )
                    {
                      gp_message ("debugXL", $subr_name, "prev_line = $prev_line");

#------------------------------------------------------------------------------
# Restore the previously popped line.
#------------------------------------------------------------------------------
                      push (@modified_html, $prev_line);
                      if ($prev_line ne $html_new_line)
                        {
                          gp_message ("debugXL", $subr_name, "add_new_line_before = $add_new_line_before pushed $html_new_line");
#------------------------------------------------------------------------------
# There is no new-line yet, so add it.
#------------------------------------------------------------------------------
                          push (@modified_html, $html_new_line);
                        }
                      else
                        {
#------------------------------------------------------------------------------
# It was a new-line, so do nothing and continue.
#------------------------------------------------------------------------------
                          gp_message ("debugXL", $subr_name, "need to restore $html_new_line");
                        }
                    }
                }
#------------------------------------------------------------------------------
# Add the newly created line.
#------------------------------------------------------------------------------

              if ($hot_line eq "##")
#------------------------------------------------------------------------------
# Highlight the most expensive line.
#------------------------------------------------------------------------------
                {
                  $modified_line = set_background_color_string (
                                 $modified_line, 
                                 $g_html_color_scheme{"background_color_hot"});
                }
#------------------------------------------------------------------------------
# Sub-highlight the lines close enough to the hot line.
#------------------------------------------------------------------------------
              else
                {
                  my @current_metrics = split (" ", $metric_values);
                  for my $metric (0 .. $#current_metrics)
                    {
                      my $current_value; 
                      my $max_value;
                      $current_value = $current_metrics[$metric];
#------------------------------------------------------------------------------
# As part of the padding process, non-breaking spaces may have been inserted
# in an earlier phase.  Temporarily remove these to make sure that the maximum
# metric values can be computed.
#------------------------------------------------------------------------------
                      $current_value =~ s/&nbsp;//g;
                      if (exists ($max_metric_values[$metric]))
                        {
                          $max_value     = $max_metric_values[$metric];
                          gp_message ("debugXL", $subr_name, "metric = $metric current_value = $current_value max_value = $max_value");
                          if ( ($max_value > 0) and ($current_value > 0) and ($current_value != $max_value) )
                            {
# TBD: abs needed?
                              gp_message ("debugXL", $subr_name, "metric = $metric current_value = $current_value max_value = $max_value");
                              my $relative_distance = 1.00 - abs ( ($max_value - $current_value)/$max_value );
                              gp_message ("debugXL", $subr_name, "relative_distance = $relative_distance");
                              if (($hp_value > 0) and ($relative_distance >= $hp_value/100.0))
                                {
                                  gp_message ("debugXL", $subr_name, "metric $metric is within the relative_distance");
                                  gp_message ("debugXL", $subr_name, "change bg modified_line = $modified_line");
                                  $modified_line = set_background_color_string (
                                                     $modified_line, 
                                                     $g_html_color_scheme{"background_color_lukewarm"});
                                  last;
                                }
                            }
                        }
                    }
                }

##  my @max_metric_values = ();
              push (@modified_html, $modified_line);
              if ($add_new_line_after)
                {
                  gp_message ("debugXL", $subr_name, "add_new_line_after = $add_new_line_after pushed $html_new_line");
                  push (@modified_html, $html_new_line);
                }

            }
          else
            {
              my $msg = "parsing line $input_line";
              gp_message ("assertion", $subr_name, $msg);
            }
        }
      elsif ( $input_line =~ /$src_regex/ )
        {
          if ( defined ($1) and defined ($2) )
            {
####### BUG?
              gp_message ("debugXL", $subr_name, "found a source code line: $input_line");
              gp_message ("debugXL", $subr_name, "\$1 = $1");
              gp_message ("debugXL", $subr_name, "\$2 = $2");
              gp_message ("debugXL", $subr_name, "\$3 = $3");
              my $blanks        = $1;
              my $src_line      = $2;
              my $src_code      = $3;

#------------------------------------------------------------------------------
# We need to replace the "<" symbol in the code by "&lt;".
#------------------------------------------------------------------------------
              $src_code =~ s/$g_less_than_regex/$g_html_less_than_regex/g;

              my $target = "<a name='line_".$src_line."'>".$src_line.".</a>";
              gp_message ("debugXL", $subr_name, "src target = $target $src_code");

              my $modified_line = $blanks . $target . $src_code;
              gp_message ("debugXL", $subr_name, "modified_line = $modified_line");
              push (@modified_html, $modified_line);
            }
          else
            {
              my $msg = "parsing line $input_line";
              gp_message ("assertion", $subr_name, $msg);
            }
        }
      elsif ( $input_line =~ /$function_regex/ )
        {
          my $html_name;
          if (defined ($1) and defined ($2))
            {
              $func_name_in_dis_file = $2;
              my $spaces = $1;
              my $boldface = $TRUE;
              gp_message ("debugXL", $subr_name, "function_name = $2");
              my $function_line       = "&lt;Function: " . $func_name_in_dis_file . ">"; 

##### HACK 

              if ($func_name_in_dis_file eq $target_function)
                {
                  my $color_function_name = color_string (
                                 $function_line, 
                                 $boldface, 
                                 $g_html_color_scheme{"target_function_name"});
                  my $label = "<a id=\"" . $g_function_tag_id{$target_function} . "\"></a>";
                  $html_name = $label . $spaces . "<i>" . $color_function_name . "</i>";
                }
              else
                {
                  my $color_function_name = color_string (
                             $function_line, 
                             $boldface, 
                             $g_html_color_scheme{"non_target_function_name"});
                  $html_name = "<i>" . $spaces . $color_function_name . "</i>";
                }
              push (@modified_html, $html_name);
            }
          else
            {
              my $msg = "parsing line $input_line";
              gp_message ("assertion", $subr_name, $msg);
            }
        }
    }

#------------------------------------------------------------------------------
# Add an extra line with diagnostics.
#
# TBD: The same is done in process_source but should be done only once.
#------------------------------------------------------------------------------
  if ($hp_value > 0) 
    {
      my $rounded_percentage = sprintf ("%.1f", $hp_value);
      $threshold_line = "<i>The setting for the highlight percentage (-hp) option: $rounded_percentage (%)</i>";
    }
  else
    {
      $threshold_line = "<i>The highlight percentage (-hp) feature is not enabled</i>";
    }

  $html_home = ${ generate_home_link ("left") };
  $html_end  = ${ terminate_html_document () };

  push (@modified_html, "</pre>");
  push (@modified_html, $html_new_line);
  push (@modified_html, $threshold_line);
  push (@modified_html, $html_home);
  push (@modified_html, $html_new_line);
  push (@modified_html, $g_html_credits_line);
  push (@modified_html, $html_end);

  for my $i (0 .. $#modified_html)
    {
      gp_message ("debugXL", $subr_name, "[$i] -> $modified_html[$i]");
    }

  for my $i (0 .. $#modified_html)
    {
      print HTML_OUTPUT "$modified_html[$i]" . "\n";
    }

  close (HTML_OUTPUT);
  close (INPUT_DISASSEMBLY);

  gp_message ("debug", $subr_name, "output is in file $html_dis_out");
  gp_message ("debug", $subr_name ,"completed processing disassembly");

  undef %branch_target;
  undef %extended_branch_target;
  undef %inverse_branch_target;

  return (\@source_line, \@metric);

} #-- End of subroutine generate_dis_html

#------------------------------------------------------------------------------
# Generate all the function level information.
#------------------------------------------------------------------------------
sub generate_function_level_info
{
  my $subr_name = get_my_name ();

  my ($exp_dir_list_ref, $call_metrics, $summary_metrics, $input_string, 
      $sort_fields_ref) = @_;

  my @exp_dir_list = @{ $exp_dir_list_ref };
  my @sort_fields  = @{ $sort_fields_ref };

  my $expr_name;
  my $first_metric;
  my $gp_display_text_cmd;
  my $gp_functions_cmd;
  my $ignore_value;
  my $script_pc_metrics;

  my $outputdir      = append_forward_slash ($input_string);

  my $script_file_PC = $outputdir."gp-script-PC";
  my $result_file    = $outputdir."gp-out-PC.err";
  my $gp_error_file  = $outputdir."gp-out-PC.err";
  my $func_limit     = $g_user_settings{func_limit}{current_value};

#------------------------------------------------------------------------------
# The number of entries in the Function Overview includes <Total>, but that is
# not a concern to the user and we add "1" to compensate for this.
#------------------------------------------------------------------------------
  $func_limit += 1;

  gp_message ("debug", $subr_name, "increased the local value for func_limit = $func_limit");

  $expr_name = join (" ", @exp_dir_list);

  gp_message ("debug", $subr_name, "expr_name = $expr_name");

  for my $i (0 .. $#sort_fields)
    {
       gp_message ("debug", $subr_name, "sort_fields[$i] = $sort_fields[$i]");
    }

# Ruud $count = 0;

  gp_message ("debug", $subr_name, "calling $GP_DISPLAY_TEXT to get function information files");

  open (SCRIPT_PC, ">", $script_file_PC) 
    or die ("$subr_name - unable to open script file $script_file_PC for writing: '$!'");
  gp_message ("debug", $subr_name, "opened file $script_file_PC for writing");

#------------------------------------------------------------------------------
# Get the list of functions.
#------------------------------------------------------------------------------

#------------------------------------------------------------------------------
# Get the first metric.
#------------------------------------------------------------------------------
  $summary_metrics   =~ /^([^:]+)/;
  $first_metric      = $1;
  $g_first_metric    = $1;
  $script_pc_metrics = "address:$summary_metrics";

  gp_message ("debugXL", $subr_name, "$func_limit");
  gp_message ("debugXL", $subr_name, "$summary_metrics");
  gp_message ("debugXL", $subr_name, "$first_metric");
  gp_message ("debugXL", $subr_name, "$script_pc_metrics");

# Temporarily disabled   print SCRIPT_PC "# limit $func_limit\n";
# Temporarily disabled  print SCRIPT_PC "limit $func_limit\n";
  print SCRIPT_PC "# thread_select all\n";
  print SCRIPT_PC "thread_select all\n";

#------------------------------------------------------------------------------
# Empty header.
#------------------------------------------------------------------------------
  print SCRIPT_PC "# outfile $outputdir"."header\n";
  print SCRIPT_PC "outfile $outputdir"."header\n";

#------------------------------------------------------------------------------
# Else the output from the next line goes to last sort.func
#------------------------------------------------------------------------------
  print SCRIPT_PC "# outfile $outputdir"."gp-metrics-functions-PC\n"; 
  print SCRIPT_PC "outfile $outputdir"."gp-metrics-functions-PC\n"; 
  print SCRIPT_PC "# metrics $script_pc_metrics\n";
  print SCRIPT_PC "metrics $script_pc_metrics\n";
#------------------------------------------------------------------------------
# Not really sorted
#------------------------------------------------------------------------------
  print SCRIPT_PC "# outfile $outputdir"."functions.sort.func-PC\n"; 
  print SCRIPT_PC "outfile $outputdir"."functions.sort.func-PC\n"; 
  print SCRIPT_PC "# functions\n";
  print SCRIPT_PC "functions\n";

  print SCRIPT_PC "# outfile $outputdir"."functions.sort.func-PC2\n"; 
  print SCRIPT_PC "outfile $outputdir"."functions.sort.func-PC2\n"; 
  print SCRIPT_PC "# metrics address:name:$summary_metrics\n";
  print SCRIPT_PC "metrics address:name:$summary_metrics\n";
  print SCRIPT_PC "# sort $first_metric\n";
  print SCRIPT_PC "sort $first_metric\n";
  print SCRIPT_PC "# functions\n";
  print SCRIPT_PC "functions\n";
#------------------------------------------------------------------------------
# Go through all the possible metrics and sort by each of them.
#------------------------------------------------------------------------------
  for my $field (@sort_fields)
    {
      gp_message ("debug", $subr_name, "sort_fields field = $field");
#------------------------------------------------------------------------------
# Else the output from the next line goes to last sort.func
#------------------------------------------------------------------------------
      print SCRIPT_PC "# outfile $outputdir"."gp-metrics-".$field."-PC\n"; 
      print SCRIPT_PC "outfile $outputdir"."gp-metrics-".$field."-PC\n"; 
      print SCRIPT_PC "# metrics $script_pc_metrics\n";
      print SCRIPT_PC "metrics $script_pc_metrics\n";
      print SCRIPT_PC "# outfile $outputdir".$field.".sort.func-PC\n";
      print SCRIPT_PC "outfile $outputdir".$field.".sort.func-PC\n";
      print SCRIPT_PC "# sort $field\n";
      print SCRIPT_PC "sort $field\n";
      print SCRIPT_PC "# functions\n";
      print SCRIPT_PC "functions\n";

      print SCRIPT_PC "# metrics address:name:$summary_metrics\n";
      print SCRIPT_PC "metrics address:name:$summary_metrics\n";
      print SCRIPT_PC "# outfile $outputdir".$field.".sort.func-PC2\n";
      print SCRIPT_PC "outfile $outputdir".$field.".sort.func-PC2\n";
      print SCRIPT_PC "# sort $field\n";
      print SCRIPT_PC "sort $field\n";
      print SCRIPT_PC "# functions\n";
      print SCRIPT_PC "functions\n";
    }

#------------------------------------------------------------------------------
# Get caller-callee list
#------------------------------------------------------------------------------
  print SCRIPT_PC "# outfile " . $outputdir."caller-callee-PC2\n";
  print SCRIPT_PC "outfile " . $outputdir."caller-callee-PC2\n";
  print SCRIPT_PC "# metrics address:name:$summary_metrics\n";
  print SCRIPT_PC "metrics address:name:$summary_metrics\n";
  print SCRIPT_PC "# callers-callees\n";
  print SCRIPT_PC "callers-callees\n";
#------------------------------------------------------------------------------
# Else the output from the next line goes to last sort.func
#------------------------------------------------------------------------------
  print SCRIPT_PC "# outfile $outputdir"."gp-metrics-calls-PC\n"; 
  print SCRIPT_PC "outfile $outputdir"."gp-metrics-calls-PC\n"; 
  $script_pc_metrics = "address:$call_metrics";
  print SCRIPT_PC "# metrics $script_pc_metrics\n";
  print SCRIPT_PC "metrics $script_pc_metrics\n";

#------------------------------------------------------------------------------
# Not really sorted
#------------------------------------------------------------------------------
  print SCRIPT_PC "# outfile $outputdir"."calls.sort.func-PC\n"; 
  print SCRIPT_PC "outfile $outputdir"."calls.sort.func-PC\n"; 

#------------------------------------------------------------------------------
# Get caller-callee list
#------------------------------------------------------------------------------
  print SCRIPT_PC "# callers-callees\n";
  print SCRIPT_PC "callers-callees\n";

#------------------------------------------------------------------------------
# Else the output from the next line goes to last sort.func
#------------------------------------------------------------------------------
  print SCRIPT_PC "# outfile $outputdir"."gp-metrics-calltree-PC\n";
  print SCRIPT_PC "outfile $outputdir"."gp-metrics-calltree-PC\n";
  print SCRIPT_PC "# metrics $script_pc_metrics\n";
  print SCRIPT_PC "metrics $script_pc_metrics\n";

  if ($g_user_settings{"calltree"}{"current_value"} eq "on")
    {
      gp_message ("verbose", $subr_name, "Generate the file with the calltree information");
#------------------------------------------------------------------------------
# Get calltree list
#------------------------------------------------------------------------------
      print SCRIPT_PC "# outfile $outputdir"."calltree.sort.func-PC\n";
      print SCRIPT_PC "outfile $outputdir"."calltree.sort.func-PC\n";
      print SCRIPT_PC "# calltree\n";
      print SCRIPT_PC "calltree\n";
    }

#------------------------------------------------------------------------------
# Get the default set of metrics
#------------------------------------------------------------------------------
  my $full_metrics_ref;
  my $all_metrics;
  my $full_function_view = $outputdir . "functions.full";

  $full_metrics_ref = get_all_the_metrics (\$expr_name, \$outputdir);

  $all_metrics  = "address:name:";
  $all_metrics .= ${$full_metrics_ref};
  gp_message ("debug", $subr_name, "all_metrics = $all_metrics");
#------------------------------------------------------------------------------
# Get the name, address, and full overview of all metrics for all functions
#------------------------------------------------------------------------------
   print SCRIPT_PC "# limit 0\n";
   print SCRIPT_PC "limit 0\n";
   print SCRIPT_PC "# metrics $all_metrics\n";
   print SCRIPT_PC "metrics $all_metrics\n";
   print SCRIPT_PC "# thread_select all\n";
   print SCRIPT_PC "thread_select all\n";
   print SCRIPT_PC "# sort default\n";
   print SCRIPT_PC "sort default\n";
   print SCRIPT_PC "# outfile $full_function_view\n";
   print SCRIPT_PC "outfile $full_function_view\n";
   print SCRIPT_PC "# functions\n";
   print SCRIPT_PC "functions\n";

  close (SCRIPT_PC);

  $result_file    = $outputdir."gp-out-PC.err";
  $gp_error_file  = $outputdir.$g_gp_error_logfile;

  $gp_functions_cmd  = "$GP_DISPLAY_TEXT -limit $func_limit ";
  $gp_functions_cmd .= "-viewmode machine -compare off ";
  $gp_functions_cmd .= "-script $script_file_PC $expr_name";

  gp_message ("debug", $subr_name, "calling $GP_DISPLAY_TEXT to get function level information");

  $gp_display_text_cmd = "$gp_functions_cmd 1> $result_file 2>> $gp_error_file";

  gp_message ("debugXL", $subr_name,"cmd = $gp_display_text_cmd");

  my ($error_code, $cmd_output) = execute_system_cmd ($gp_display_text_cmd);

  if ($error_code != 0)
    {
      $ignore_value = msg_display_text_failure ($gp_display_text_cmd, 
                                                $error_code, 
                                                $gp_error_file);
      gp_message ("abort", "execution terminated");
    }

#-------------------------------------------------------------------------------
# Parse the full function view and store the data.
#-------------------------------------------------------------------------------
  my @input_data = ();
  my $empty_line_regex = '^\s*$';
  
##  my $full_function_view = $outputdir . "functions.full";

  open (ALL_FUNC_DATA, "<", $full_function_view)
    or die ("$subr_name - unable to open output file $full_function_view for reading '$!'");
  gp_message ("debug", $subr_name, "opened file $full_function_view for reading");

  chomp (@input_data = <ALL_FUNC_DATA>);

  my $start_scanning = $FALSE;
  for (my $line = 0; $line <= $#input_data; $line++)
    {
      my $input_line = $input_data[$line];
     
#      if ($input_line =~ /^<Total>\s+.*/)
      if ($input_line =~ /\s*(\d+:0x[a-fA-F0-9]+)\s+(\S+)\s+(.*)/)
        {
          $start_scanning = $TRUE;
        }
      elsif ($input_line =~ /$empty_line_regex/)
        {
          $start_scanning = $FALSE;
        }

      if ($start_scanning)
        {
          gp_message ("debugXL", $subr_name, "$line: $input_data[$line]");

          push (@g_full_function_view_table, $input_data[$line]);
 
          my $hex_address;
          my $full_hex_address = $1;
          my $routine = $2;
          my $all_metrics = $3;
          if ($full_hex_address =~ /(\d+):0x(\S+)/)
            {
              $hex_address = "0x" . $2;
            }
          $g_function_view_all{$routine}{"hex_address"} = $hex_address;
          $g_function_view_all{$routine}{"all_metrics"} = $all_metrics;
        }
    }

  for my $i (keys %g_function_view_all)
    {
      gp_message ("debugXL", $subr_name, "key = $i $g_function_view_all{$i}{'hex_address'} $g_function_view_all{$i}{'all_metrics'}");
    }

  for my $i (keys @g_full_function_view_table)
    {
      gp_message ("debugXL", $subr_name, "g_full_function_view_table[$i] = $i $g_full_function_view_table[$i]");
    }

  return ($script_pc_metrics);

} #-- End of subroutine generate_function_level_info

#------------------------------------------------------------------------------
# Generate all the files needed for the function view.
#------------------------------------------------------------------------------
sub generate_function_view
{
  my $subr_name = get_my_name ();

  my ($directory_name_ref, $summary_metrics_ref, $number_of_metrics_ref, 
      $function_info_ref, $function_view_structure_ref, $function_address_info_ref, 
      $sort_fields_ref, $exp_dir_list_ref, $addressobjtextm_ref) = @_;

  my $directory_name          = ${ $directory_name_ref };
  my @function_info           = @{ $function_info_ref };
  my %function_view_structure = %{ $function_view_structure_ref };
  my $summary_metrics         = ${ $summary_metrics_ref };
  my $number_of_metrics       = ${ $number_of_metrics_ref };
  my %function_address_info   = %{ $function_address_info_ref };
  my @sort_fields             = @{ $sort_fields_ref };
  my @exp_dir_list            = @{ $exp_dir_list_ref };
  my %addressobjtextm         = %{ $addressobjtextm_ref };

  my @abs_path_exp_dirs = ();
  my @experiment_directories; 

  my $target_function; 
  my $html_line;
  my $ftag;
  my $routine_length; 
  my %html_source_functions = ();

  my $href_link; 
  my $infile;
  my $input_experiments;
  my $keep_value; 
  my $loadobj; 
  my $address_field; 
  my $address_offset; 
  my $msg;
  my $exe; 
  my $extra_field; 
  my $new_target_function;
  my $file_title; 
  my $html_output_file; 
  my $html_function_view; 
  my $overview_file; 
  my $exp_name; 
  my $exp_type; 
  my $html_header;
  my $routine; 
  my $length_header; 
  my $length_metrics;
  my $full_index_line; 
  my $acknowledgement; 
  my @full_function_view_line = ();
  my $spaces;
  my $size_text; 
  my $position_text; 
  my $html_first_metric_file; 
  my $html_new_line = "<br>";
  my $html_acknowledgement; 
  my $html_end;
  my $html_home; 
  my $page_title; 
  my $html_title_header; 

  my $outputdir         = append_forward_slash ($directory_name);
  my $LANG              = $g_locale_settings{"LANG"};
  my $decimal_separator = $g_locale_settings{"decimal_separator"};

  $input_experiments = join (", ", @exp_dir_list);

  for my $i (0 .. $#exp_dir_list)
    {
      my $dir = get_basename ($exp_dir_list[$i]);
      push @abs_path_exp_dirs, $dir;
    }
  $input_experiments = join (", ", @abs_path_exp_dirs);

  gp_message ("debug", $subr_name, "input_experiments = $input_experiments");

#------------------------------------------------------------------------------
# TBD: This should be done only once and much earlier.
#------------------------------------------------------------------------------
  @experiment_directories = split (",", $input_experiments);

#------------------------------------------------------------------------------
# For every function in the function overview, set up an html structure with
# the various hyperlinks.
#------------------------------------------------------------------------------

#------------------------------------------------------------------------------
# Core loop that generates an HTML line for each function.
#------------------------------------------------------------------------------
  my $top_of_table = $FALSE;
  for my $i (0 .. $#function_info)
    {
      if (defined ($function_info[$i]{"alt_name"}))
        {
          $target_function = $function_info[$i]{"alt_name"};
        }
      else
        {
          my $msg = "function_info[$i]{\"alt_name\"} is not defined";
          gp_message ("assertion", $subr_name, $msg);
        }

      $html_source_functions{$target_function} = $function_info[$i]{"html function block"}; 
    }

  for my $i (sort keys %html_source_functions)
    {
      gp_message ("debugXL", $subr_name, "html_source_functions{$i} = $html_source_functions{$i}");
    }

  $file_title = "Function view for experiments " . $input_experiments;

#------------------------------------------------------------------------------
# Example input file:

# Current metrics: address:name:e.totalcpu:e.cycles:e+insts:e+llm
# Current Sort Metric: Exclusive Total CPU Time ( e.totalcpu )
# Current Sort Metric: Exclusive Total CPU Time ( e.totalcpu )
# Functions sorted by metric: Exclusive Total CPU Time
# 
# PC Addr.        Name              Excl.     Excl. CPU  Excl.         Excl.
#                                   Total     Cycles     Instructions  Last-Level
#                                   CPU sec.   sec.      Executed      Cache Misses
#  1:0x00000000   <Total>           3.502     4.005      15396819700   24024250
#  2:0x000021ae   mxv_core          3.342     3.865      14500538981   23824045
#  6:0x0003af50   erand48_r         0.080     0.084        768240570          0
#  2:0x00001f7b   init_data         0.040     0.028         64020043     200205
#  6:0x0003b160   __drand48_iterate 0.020     0.                   0          0
#  ...
#------------------------------------------------------------------------------

  for my $metric (@sort_fields)
    {
      $overview_file = $outputdir . $metric . ".sort.func-PC2";

      $exp_type = $metric;

      if ($metric eq "functions")
        {
          $html_function_view .= $g_html_base_file_name{"function_view"} . ".html";
        }
      else
        {
          $html_function_view = $g_html_base_file_name{"function_view"} . "." . $metric . ".html";
        }
#------------------------------------------------------------------------------
# The default function view is based upon the first metric in the list.  We use
# this file in the index.html file. 
#------------------------------------------------------------------------------
      if ($metric eq $g_first_metric)
        {
          $html_first_metric_file = $html_function_view;
          my $txt = "g_first_metric = $g_first_metric ";
          $txt   .= "html_first_metric_file = $html_first_metric_file";
          gp_message ("debugXL", $subr_name, $txt);
        }

      $html_output_file = $outputdir . $html_function_view;

      open (FUNCTION_VIEW, ">", $html_output_file) 
        or die ("$subr_name - unable to open file $html_output_file for writing - '$!'");
      gp_message ("debug", $subr_name, "opened file $html_output_file for writing");

      $html_home       = ${ generate_home_link ("right") };
      $html_header     = ${ create_html_header (\$file_title) };

      $page_title    = "Function View";
      $size_text     = "h2"; 
      $position_text = "center";
      $html_title_header = ${ generate_a_header (\$page_title, \$size_text, \$position_text) };

      print FUNCTION_VIEW $html_header;
      print FUNCTION_VIEW $html_home;
      print FUNCTION_VIEW $html_title_header;
      print FUNCTION_VIEW "$_" for @g_html_experiment_stats;
      print FUNCTION_VIEW $html_new_line . "\n";

      my $function_view_structure_ref = process_function_overview (
                                          \$metric, 
                                          \$exp_type, 
                                          \$summary_metrics, 
                                          \$number_of_metrics, 
                                          \@function_info, 
                                          \%function_view_structure, 
                                          \$overview_file);

      my %function_view_structure = %{ $function_view_structure_ref };

#------------------------------------------------------------------------------
# Core part: extract the true function name and find the html code for it.
#------------------------------------------------------------------------------
      gp_message ("debugXL", $subr_name, "the final table");
 
      print FUNCTION_VIEW "<pre>\n";
      print FUNCTION_VIEW "$_\n" for @{ $function_view_structure{"header"} };

      my $max_length_header  = $function_view_structure{"max header length"}; 
      my $max_length_metrics = $function_view_structure{"max metrics length"};

#------------------------------------------------------------------------------
# Add 4 more spaces for the distance to the function names.  Purely cosmetic.
#------------------------------------------------------------------------------
      my $pad    = max ($max_length_metrics, $max_length_header) + 4;
      my $spaces = "";
      for my $i (1 .. $pad)
        {
          $spaces .= "&nbsp;";
        }

#------------------------------------------------------------------------------
# Add extra space for the /blank/*/ marker!
#------------------------------------------------------------------------------
      $spaces .= "&nbsp;";
      my $func_header = $spaces . $function_view_structure{"table name"};
      gp_message ("debugXL", $subr_name, "func_header = " . $func_header);

      
      print FUNCTION_VIEW $spaces . "<b>" . 
                          $function_view_structure{"table name"} . 
                          "</b>" . $html_new_line . "\n";

#------------------------------------------------------------------------------
# If the header is longer than the metrics, add spaces to padd the difference.
# Also add the same 4 spaces between the metric values and the function name.
#------------------------------------------------------------------------------
      $pad = 0;
      if ($max_length_header > $max_length_metrics)
        {
          $pad = $max_length_header - $max_length_metrics;
        }
      $pad += 4;
      $spaces = "";
      for my $i (1 .. $pad)
        {
          $spaces .= "&nbsp;";
        }

#------------------------------------------------------------------------------
# This is where it literally all comes together.  The metrics and function
# parts are combined.
#------------------------------------------------------------------------------
##      for my $i (keys @{ $function_view_structure{"function table"} })
      for my $i (0 .. $#{ $function_view_structure{"function table"} })
        {
          my $p1 = $function_view_structure{"metrics part"}[$i];
          my $p2 = $function_view_structure{"function table"}[$i];

          $full_index_line = $p1 . $spaces . $p2;

          push (@full_function_view_line, $full_index_line);
        }

      print FUNCTION_VIEW "$_\n" for @full_function_view_line;

#-------------------------------------------------------------------------------
# Clear the array before filling it up again.
#-------------------------------------------------------------------------------
      @full_function_view_line = ();

#-------------------------------------------------------------------------------
# Get the acknowledgement, return to main link, and final html statements.
#-------------------------------------------------------------------------------
      $html_home            = ${ generate_home_link ("left") };
      $html_acknowledgement = ${ create_html_credits () };
      $html_end             = ${ terminate_html_document () };

      print FUNCTION_VIEW "</pre>\n";
      print FUNCTION_VIEW $html_home;
      print FUNCTION_VIEW $html_new_line . "\n";
      print FUNCTION_VIEW $html_acknowledgement;
      print FUNCTION_VIEW $html_end;

      close (FUNCTION_VIEW);
    }

  return (\$html_first_metric_file); 

} #-- End of subroutine generate_function_view

#------------------------------------------------------------------------------
# Generate an html line that links back to index.html.  The text can either
# be positioned to the left or to the right.
#------------------------------------------------------------------------------
sub generate_home_link
{
  my $subr_name = get_my_name ();

  my ($which_side) = @_;

  my $html_home_line; 

  if (($which_side ne "left") and ($which_side ne "right"))
    {
      my $msg = "which_side = $which_side not supported";
      gp_message ("assertion", $subr_name, $msg);
    }

  $html_home_line .= "<div class=\"" . $which_side . "\">";
  $html_home_line .= "<br><a href='" . $g_html_base_file_name{"index"}; 
  $html_home_line .= ".html' style='background-color:"; 
  $html_home_line .= $g_html_color_scheme{"index"};
  $html_home_line .= "'><b>Return to main view</b></a>";
  $html_home_line .= "</div>";

  return (\$html_home_line);

} #-- End of subroutine generate_home_link

#------------------------------------------------------------------------------
# Generate a block of html for this function block.
#------------------------------------------------------------------------------
sub generate_html_function_blocks
{
  my $subr_name = get_my_name ();

  my (
  $index_start_ref,
  $index_end_ref,
  $hex_addresses_ref,
  $the_metrics_ref,
  $length_first_metric_ref,
  $special_marker_ref,
  $the_function_name_ref,
  $separator_ref, 
  $number_of_metrics_ref, 
  $data_function_block_ref, 
  $function_info_ref, 
  $function_view_structure_ref) = @_; 

  my $index_start = ${ $index_start_ref };
  my $index_end   = ${ $index_end_ref };
  my @hex_addresses = @{ $hex_addresses_ref };
  my @the_metrics     = @{ $the_metrics_ref };
  my @length_first_metric = @{ $length_first_metric_ref };
  my @special_marker = @{ $special_marker_ref };
  my @the_function_name = @{ $the_function_name_ref};

  my $separator               = ${ $separator_ref };
  my $number_of_metrics       = ${ $number_of_metrics_ref };
  my $data_function_block     = ${ $data_function_block_ref };
  my @function_info           = @{ $function_info_ref };
  my %function_view_structure = %{ $function_view_structure_ref };

  my $decimal_separator = $g_locale_settings{"decimal_separator"}; 

  my @html_block_prologue = ();
  my @html_code_function_block = ();
  my @function_lines           = ();
  my @fields = ();
  my @address_field = ();
  my @metric_values = ();
  my @function_names = ();
  my @final_function_names = ();
  my @marker = ();
  my @split_number = ();
  my @function_tags = ();

  my $all_metrics; 
  my $current_function_name;
  my $no_of_fields;
  my $name_regex;
  my $full_hex_address;
  my $hex_address;
  my $target_function; 
  my $marker_function; 
  my $routine; 
  my $routine_length; 
  my $metrics_length; 
  my $max_metrics_length = 0;
  my $modified_line;
  my $string_length; 
  my $addr_offset; 
  my $current_address; 
  my $found_a_match;
  my $ref_index;
  my $alt_name;
  my $length_first_field; 
  my $gap;
  my $ipad; 
  my $html_line; 
  my $target_tag; 
  my $tag_for_header; 
  my $href_file; 
  my $found_alt_name; 
  my $name_in_header;
  my $create_hyperlinks;

  state $first_call = $TRUE;
  state $reference_length;

#------------------------------------------------------------------------------
# If the length of the first metric is less than the maximum over all first
# metrics, add spaces to the left to ensure correct alignment.
#------------------------------------------------------------------------------
  for my $k ($index_start .. $index_end)
    {
      my $pad = $g_max_length_first_metric - $length_first_metric[$k];
      if ($pad ge 1)
        {
          my $spaces = "";
          for my $s (1 .. $pad)
            {
              $spaces .= "&nbsp;";
            }
          $the_metrics[$k] = $spaces . $the_metrics[$k];

          my $msg = "padding spaces = $spaces the_metrics[$k] = $the_metrics[$k]";
          gp_message ("debugXL", $subr_name, $msg);
        }

##      my $end_game = "end game3=> pad = $pad" . $hex_addresses[$k] . " " . $the_metrics[$k] . " " . $special_marker[$k] . $the_function_name[$k];
##      gp_message ("debugXL", $subr_name, $end_game);
    }

#------------------------------------------------------------------------------
# An example what @function_lines should look like after the split:
# <empty>
# 6:0x0003ad20   drand48           0.100     0.084        768240570          0
# 6:0x0003af50  *erand48_r         0.080     0.084        768240570          0
# 6:0x0003b160   __drand48_iterate 0.020     0.                   0          0
#------------------------------------------------------------------------------
  @function_lines = split ($separator, $data_function_block);

#------------------------------------------------------------------------------
# Parse the individual lines.  Replace multi-occurrence functions by their
# unique alternative name and mark the target function.
#
# The above split operation produces an empty first field because the line
# starts with the separator.  This is why skip the first field.
#------------------------------------------------------------------------------
  for my $i ($index_start .. $index_end)
    {
      my $input_line = $the_metrics[$i];

      gp_message ("debugXL", $subr_name, "the_metrics[$i] = ". $the_metrics[$i]);

#------------------------------------------------------------------------------
# In case the last metric is 0. only, we append 3 extra characters that
# represent zero.  We cannot change the number to 0.000 though because that
# has a different interpretation than 0.
# In a later phase, the "ZZZ" symbol will be removed again, but for now it
# creates consistency in, for example, the length of the metrics part.
#------------------------------------------------------------------------------
      if ($input_line =~ /[\w0-9$decimal_separator]*(0$decimal_separator$)/)
        {
          if (defined ($1) )
            {
              my $decimal_point = $decimal_separator;
              $decimal_point =~ s/\\//;
              my $txt = "input_line = $input_line = ended with 0"; 
              $txt   .= $decimal_point;
              gp_message ("debugXL", $subr_name, $txt);

              $the_metrics[$i] .= "ZZZ";
            }
        }

      $hex_address     = $hex_addresses[$i];
      $marker_function = $special_marker[$i];
      $routine         = $the_function_name[$i];
#------------------------------------------------------------------------------
# Get the length of the metrics line before ZZZ is replaced by spaces.
#------------------------------------------------------------------------------
      $all_metrics     = $the_metrics[$i];
      $metrics_length  = length ($all_metrics);
      $all_metrics     =~ s/ZZZ/&nbsp;&nbsp;&nbsp;/g;

      $max_metrics_length = max ($max_metrics_length, $metrics_length);

      push (@marker, $marker_function);
      push (@address_field, $hex_address); 
      push (@metric_values, $all_metrics);
      push (@function_names, $routine);

      my $index_into_function_info_ref = get_index_function_info (
                                         \$routine, 
                                         \$hex_addresses[$i], 
                                         $function_info_ref);

      my $index_into_function_info = ${ $index_into_function_info_ref }; 
      $target_tag = $function_info[$index_into_function_info]{"tag_id"};
      $alt_name = $function_info[$index_into_function_info]{"alt_name"};

#------------------------------------------------------------------------------
# Keep the name of the target function (the one marked with a *) for later use.
# This is the tag that identifies the block in the caller-callee output.  The
# tag is used in the link to the caller-callee in the function overview.
#------------------------------------------------------------------------------
      if ($marker_function eq "*")
        {
          $tag_for_header = $target_tag;
          $name_in_header = $alt_name;

#------------------------------------------------------------------------------
# We need to replace the "<" symbol in the code by "&lt;".
#------------------------------------------------------------------------------
          $name_in_header =~ s/$g_less_than_regex/$g_html_less_than_regex/g;

        }
      push (@final_function_names, $alt_name);
      push (@function_tags, $target_tag);

      gp_message ("debugXL", $subr_name, "index_into_function_info = $index_into_function_info");
      gp_message ("debugXL", $subr_name, "target_tag = $target_tag");
      gp_message ("debugXL", $subr_name, "alt_name   = $alt_name");

    } #-- End of loop for my $i ($index_start .. $index_end)

  my $tag_line = "<a id='" . $tag_for_header . "'></a>";
  $html_line  = "<br>\n";
  $html_line .= $tag_line . "Function name: ";
  $html_line .= "<span style='color:" . $g_html_color_scheme{"target_function_name"} . "'>";
  $html_line .= "<b>" . $name_in_header . "</b></span>\n";
  $html_line .= "<br>";

  push (@html_block_prologue, $html_line);

  gp_message ("debugXL", $subr_name, "the final function block for $name_in_header");

  $href_file = $g_html_base_file_name{"caller_callee"} . ".html";

#------------------------------------------------------------------------------
# Process the function blocks and generate the HTML structure for them.
#------------------------------------------------------------------------------
  for my $i (0 .. $#final_function_names)
    {
      $current_function_name = $final_function_names[$i];
      gp_message ("debugXL", $subr_name, "current_function_name = $current_function_name");

#------------------------------------------------------------------------------
# Do not add hyperlinks for <Total>.
#------------------------------------------------------------------------------
      if ($current_function_name eq "<Total>")
        {
          $create_hyperlinks = $FALSE;
        }
      else
        {
          $create_hyperlinks = $TRUE;
        }

#------------------------------------------------------------------------------
# We need to replace the "<" symbol in the code by "&lt;".
#------------------------------------------------------------------------------
      $current_function_name =~ s/$g_less_than_regex/$g_html_less_than_regex/g;

      $html_line = $metric_values[$i] . " ";

      if ($marker[$i] eq "*")
        {
          $current_function_name = "<b>" . $current_function_name . "</b>";
        }
      $html_line .= " <a href='" . $href_file . "#" . $function_tags[$i] . "'>" . $current_function_name . "</a>";

      if ($marker[$i] eq "*")
        {
            $html_line = "<br>" . $html_line; 
        }
      elsif (($marker[$i] ne "*") and ($i == 0))
        {
            $html_line = "<br>" . $html_line; 
        }

      gp_message ("debugXL", $subr_name, "html_line = $html_line");

#------------------------------------------------------------------------------
# Find the index into "function_info" for this particular function.
#------------------------------------------------------------------------------
      $routine         = $function_names[$i];
      $current_address = $address_field[$i];

      my $target_index_ref = find_index_in_function_info (\$routine, \$current_address, \@function_info); 
      my $target_index     = ${ $target_index_ref };

      gp_message ("debugXL", $subr_name, "routine = $routine current_address = $current_address target_index = $target_index");

#------------------------------------------------------------------------------
# TBD Do this once for each function and store the result.  This is a saving
# because functions may and typically will appear more than once.
#------------------------------------------------------------------------------
      my $spaces_left = $function_view_structure{"max function length"} - $function_info[$target_index]{"function length"}; 

#------------------------------------------------------------------------------
# Add the links to the line. Make sure there is at least one space.
#------------------------------------------------------------------------------
      my $spaces = "&nbsp;";
      for my $k (1 .. $spaces_left)
        {
          $spaces .= "&nbsp;";
        }

      if ($create_hyperlinks)
        {
          $html_line .= $spaces;
          $html_line .= $function_info[$target_index]{"href_source"};
          $html_line .= "&nbsp;";
          $html_line .= $function_info[$target_index]{"href_disassembly"};
        }

      push (@html_code_function_block, $html_line); 
    }

    for my $lines (0 .. $#html_code_function_block)
      {
        gp_message ("debugXL", $subr_name, "final html block = " . $html_code_function_block[$lines]);
      }

  return (\@html_block_prologue, \@html_code_function_block); 

} #-- End of subroutine generate_html_function_blocks

#------------------------------------------------------------------------------
# Generate the index.html file.
#------------------------------------------------------------------------------
sub generate_index
{
  my $subr_name = get_my_name ();

  my ($outputdir_ref, $html_first_metric_file_ref, $summary_metrics_ref, 
      $number_of_metrics_ref, $function_info_ref, $function_address_info_ref, 
      $sort_fields_ref, $exp_dir_list_ref, $addressobjtextm_ref,
      $metric_description_reversed_ref, $number_of_warnings_ref,
      $table_execution_stats_ref) = @_;

  my $outputdir               = ${ $outputdir_ref };
  my $html_first_metric_file  = ${ $html_first_metric_file_ref };
  my $summary_metrics         = ${ $summary_metrics_ref };
  my $number_of_metrics       = ${ $number_of_metrics_ref };
  my @function_info           = @{ $function_info_ref };
  my %function_address_info   = %{ $function_address_info_ref };
  my @sort_fields             = @{ $sort_fields_ref };
  my @exp_dir_list            = @{ $exp_dir_list_ref };
  my %addressobjtextm         = %{ $addressobjtextm_ref };
  my %metric_description_reversed = %{ $metric_description_reversed_ref };
  my $number_of_warnings      = ${ $number_of_warnings_ref };
  my @table_execution_stats   = @{ $table_execution_stats_ref };

  my @file_contents = ();

  my $acknowledgement; 
  my @abs_path_exp_dirs = ();
  my $input_experiments;
  my $target_function; 
  my $html_line;
  my $ftag;
  my $max_length = 0;
  my %html_source_functions = ();
  my $html_header; 
  my @experiment_directories = ();
  my $html_acknowledgement; 
  my $html_file_title; 
  my $html_output_file; 
  my $html_function_view;
  my $html_caller_callee_view;
  my $html_experiment_info; 
  my $html_warnings_page;
  my $href_link; 
  my $file_title; 
  my $html_gprofng;
  my $html_end;
  my $max_length_metrics;
  my $page_title;
  my $size_text;
  my $position_text;
 
  my $ln;
  my $base;
  my $base_index_page;
  my $infile;
  my $outfile;
  my $rec;
  my $skip;
  my $callsize;
  my $dest;
  my $final_string;
  my @headers;
  my $header;
  my $sort_index;
  my $pc_address;
  my $anchor;
  my $directory_name;
  my $f2;
  my $f3;
  my $file;
  my $sline;
  my $src;
  my $srcfile_name;
  my $tmp1;
  my $tmp2;
  my $fullsize;
  my $regf2;
  my $trimsize;
  my $EIL;
  my $EEIL;
  my $AOBJ;
  my $RI;
  my $HDR;
  my $CALLER_CALLEE;
  my $NAME;
  my $SRC;
  my $TRIMMED;

#------------------------------------------------------------------------------
# Add a forward slash to make it easier when creating file names.
#------------------------------------------------------------------------------
  $outputdir         = append_forward_slash ($outputdir);
  gp_message ("debug", $subr_name, "outputdir = $outputdir");

  my $LANG              = $g_locale_settings{"LANG"};
  my $decimal_separator = $g_locale_settings{"decimal_separator"};

  $input_experiments = join (", ", @exp_dir_list);

  for my $i (0 .. $#exp_dir_list)
    {
      my $dir = get_basename ($exp_dir_list[$i]);
      push @abs_path_exp_dirs, $dir;
    }
  $input_experiments = join (", ", @abs_path_exp_dirs);

  gp_message ("debug", $subr_name, "input_experiments = $input_experiments");
  
#------------------------------------------------------------------------------
# TBD: Pass in the values for $expr_name and $cmd
#------------------------------------------------------------------------------
  $html_file_title = "Main index page";

  @experiment_directories = split (",", $input_experiments);
  $html_acknowledgement = ${ create_html_credits () };

  $html_end              = ${ terminate_html_document () };

  $html_output_file = $outputdir . $g_html_base_file_name{"index"} . ".html"; 

  open (INDEX, ">", $html_output_file) 
    or die ("$subr_name - unable to open file $html_output_file for writing - '$!'");
  gp_message ("debug", $subr_name, "opened file $html_output_file for writing");

  $page_title    = "GPROFNG Performance Analysis";
  $size_text     = "h1";
  $position_text = "center";
  $html_gprofng = ${ generate_a_header (\$page_title, \$size_text, \$position_text) };

  $html_header     = ${ create_html_header (\$html_file_title) };

  print INDEX $html_header;
  print INDEX $html_gprofng;
  print INDEX "$_" for @g_html_experiment_stats;
  print INDEX "$_" for @table_execution_stats;

  $html_experiment_info  = "<a href=\'";
  $html_experiment_info .= $g_html_base_file_name{"experiment_info"} . ".html";
  $html_experiment_info .= "\'><h3>Experiment Details</h3></a>\n";

  $html_warnings_page  = "<a href=\'";
  $html_warnings_page .= $g_html_base_file_name{"warnings"} . ".html";
  $html_warnings_page .= "\'><h3>Warnings (" . $number_of_warnings . ")</h3></a>\n";

  $html_function_view  = "<a href=\'";
  $html_function_view .= $html_first_metric_file;
  $html_function_view .= "\'><h3>Function View</h3></a>\n";

  $html_caller_callee_view  = "<a href=\'";
  $html_caller_callee_view .= $g_html_base_file_name{"caller_callee"} . ".html";
  $html_caller_callee_view .= "\'><h3>Caller Callee View</h3></a>\n";

  print INDEX "<br>\n";
##  print INDEX "<b>\n";
  print INDEX $html_experiment_info;
  print INDEX $html_warnings_page;;
##  print INDEX "<br>\n";
##  print INDEX "<br>\n";
  print INDEX $html_function_view;
##  print INDEX "<br>\n";
##  print INDEX "<br>\n";
  print INDEX $html_caller_callee_view;
##  print INDEX "</b>\n";
##  print INDEX "<br>\n";
##  print INDEX "<br>\n";
 
  print INDEX $html_acknowledgement;
  print INDEX $html_end;

  close (INDEX);

  gp_message ("debug", $subr_name, "closed file $html_output_file");

  return (0);

} #-- End of subroutine generate_index

#------------------------------------------------------------------------------
# Get all the metrics available 
#
# (gp-display-text) metric_list
# Current metrics: e.totalcpu:i.totalcpu:e.cycles:e+insts:e+llm:name
# Current Sort Metric: Exclusive Total CPU Time ( e.totalcpu )
# Available metrics:
#          Exclusive Total CPU Time: e.%totalcpu
#          Inclusive Total CPU Time: i.%totalcpu
#              Exclusive CPU Cycles: e.+%cycles
#              Inclusive CPU Cycles: i.+%cycles
#   Exclusive Instructions Executed: e+%insts
#   Inclusive Instructions Executed: i+%insts
# Exclusive Last-Level Cache Misses: e+%llm
# Inclusive Last-Level Cache Misses: i+%llm
#  Exclusive Instructions Per Cycle: e+IPC
#  Inclusive Instructions Per Cycle: i+IPC
#  Exclusive Cycles Per Instruction: e+CPI
#  Inclusive Cycles Per Instruction: i+CPI
#                              Size: size
#                        PC Address: address
#                              Name: name
#------------------------------------------------------------------------------
sub get_all_the_metrics
{
  my $subr_name = get_my_name ();

  my ($experiments_ref, $outputdir_ref) = @_;

  my $experiments = ${ $experiments_ref };
  my $outputdir   = ${ $outputdir_ref };

  my $ignore_value;
  my $gp_functions_cmd; 
  my $gp_display_text_cmd; 

  my $metrics_output_file = $outputdir . "metrics-all";
  my $result_file   = $outputdir . $g_gp_output_file;
  my $gp_error_file = $outputdir . $g_gp_error_logfile;
  my $script_file_metrics = $outputdir . "script-metrics";

  my @metrics_data = ();

  open (SCRIPT_METRICS, ">", $script_file_metrics) 
    or die ("$subr_name - unable to open script file $script_file_metrics for writing: '$!'");
  gp_message ("debug", $subr_name, "opened script file $script_file_metrics for writing");

  print SCRIPT_METRICS "# outfile $metrics_output_file\n";
  print SCRIPT_METRICS "outfile $metrics_output_file\n";
  print SCRIPT_METRICS "# metric_list\n";
  print SCRIPT_METRICS "metric_list\n";

  close (SCRIPT_METRICS);

  $gp_functions_cmd  = "$GP_DISPLAY_TEXT -script $script_file_metrics $experiments";

  gp_message ("debug", $subr_name, "calling $GP_DISPLAY_TEXT to get all the metrics");

  $gp_display_text_cmd = "$gp_functions_cmd 1>> $result_file 2>> $gp_error_file";
  gp_message ("debug", $subr_name, "cmd = $gp_display_text_cmd");

  my ($error_code, $cmd_output) = execute_system_cmd ($gp_display_text_cmd);

  if ($error_code != 0)
    {
      $ignore_value = msg_display_text_failure ($gp_display_text_cmd, 
                                                $error_code, 
                                                $gp_error_file);
      gp_message ("abort", $subr_name, "execution terminated");
    }

  open (METRICS_INFO, "<", $metrics_output_file) 
    or die ("$subr_name - unable to open file $metrics_output_file for reading '$!'");
  gp_message ("debug", $subr_name, "opened file $metrics_output_file for reading");

#------------------------------------------------------------------------------
# Read the input file into memory.
#------------------------------------------------------------------------------
  chomp (@metrics_data = <METRICS_INFO>);
  gp_message ("debug", $subr_name, "read all contents of file $metrics_output_file into memory");
  gp_message ("debug", $subr_name, "\$#metrics_data = $#metrics_data");

  my $input_line;
  my $ignore_lines_regex = '^(?:Current|Available|\s+Size:|\s+PC Address:|\s+Name:)';
  my $split_line_regex = '(.*): (.*)';
  my $empty_line_regex = '^\s*$';
  my @metric_list_all = ();
  for (my $line_no=0; $line_no <= $#metrics_data; $line_no++)
    {

      $input_line = $metrics_data[$line_no];

##      if ( not (($input_line =~ /$ignore_lines_regex/ or ($input_line =~ /^\s*$/))))
      if ( not ($input_line =~ /$ignore_lines_regex/) and not ($input_line =~ /$empty_line_regex/) )
        {
          if ($input_line =~ /$split_line_regex/)
            {
#------------------------------------------------------------------------------
# Remove the percentages.
#------------------------------------------------------------------------------
              my $metric_definition = $2;
              $metric_definition =~ s/\%//g;
              gp_message ("debug", $subr_name, "line_no = $line_no $metrics_data[$line_no] metric_definition = $metric_definition");
              push (@metric_list_all, $metric_definition);
            }
        }

    }

  gp_message ("debug", $subr_name, "\@metric_list_all = @metric_list_all");

  my $final_list = join (":", @metric_list_all);
  gp_message ("debug", $subr_name, "final_list = $final_list");

  close (METRICS_INFO);

  return (\$final_list);

} #-- End of subroutine get_all_the_metrics

#------------------------------------------------------------------------------
# A simple function to return the basename using fileparse.  To keep things
# simple, a suffixlist is not supported.  In case this is needed, use the
# fileparse function directly.
#------------------------------------------------------------------------------
sub get_basename
{
  my ($full_name) = @_;

  my $ignore_value_1;
  my $ignore_value_2;
  my $basename_value;

  ($basename_value, $ignore_value_1, $ignore_value_2) = fileparse ($full_name);

  return ($basename_value);

} #-- End of subroutine get_basename

#------------------------------------------------------------------------------
# Get the details on the experiments and store these in a file.  Each 
# experiment has its own file.  This makes the processing easier.
#------------------------------------------------------------------------------
sub get_experiment_info
{
  my $subr_name = get_my_name ();

  my ($outputdir_ref, $exp_dir_list_ref) = @_;

  my $outputdir    = ${ $outputdir_ref };
  my @exp_dir_list = @{ $exp_dir_list_ref };

  my $cmd_output;
  my $current_slot;
  my $error_code;
  my $exp_info_file; 
  my @exp_info       = ();
  my @experiment_data = ();
  my $gp_error_file;
  my $gp_display_text_cmd;
  my $gp_functions_cmd; 
  my $gp_log_file; 
  my $ignore_value;
  my $overview_file;
  my $result_file;
  my $script_file;
  my $the_experiments;

  $the_experiments = join (" ", @exp_dir_list);

  $script_file   = $outputdir . "gp-info-exp.script";
  $exp_info_file = $outputdir . "gp-info-exp-list.out";
  $overview_file = $outputdir . "gp-overview.out";
  $gp_log_file   = $outputdir . $g_gp_output_file;
  $gp_error_file = $outputdir . $g_gp_error_logfile;

  open (SCRIPT_EXPERIMENT_INFO, ">", $script_file) 
    or die ("$subr_name - unable to open script file $script_file for writing: '$!'");
  gp_message ("debug", $subr_name, "opened script file $script_file for writing");

#------------------------------------------------------------------------------
# Attributed User CPU Time=a.user : for calltree - see P37 in manual
#------------------------------------------------------------------------------
  print SCRIPT_EXPERIMENT_INFO "# compare on\n";
  print SCRIPT_EXPERIMENT_INFO "compare on\n";
  print SCRIPT_EXPERIMENT_INFO "# outfile $exp_info_file\n";
  print SCRIPT_EXPERIMENT_INFO "outfile $exp_info_file\n";
  print SCRIPT_EXPERIMENT_INFO "# exp_list\n";
  print SCRIPT_EXPERIMENT_INFO "exp_list\n";
  print SCRIPT_EXPERIMENT_INFO "# outfile $overview_file\n";
  print SCRIPT_EXPERIMENT_INFO "outfile $overview_file\n";
  print SCRIPT_EXPERIMENT_INFO "# overview\n";
  print SCRIPT_EXPERIMENT_INFO "overview\n";

  close SCRIPT_EXPERIMENT_INFO;

  $gp_functions_cmd = "$GP_DISPLAY_TEXT -script $script_file $the_experiments";

  gp_message ("debug", $subr_name, "executing $GP_DISPLAY_TEXT to get the experiment information");

  $gp_display_text_cmd = "$gp_functions_cmd 1>> $gp_log_file 2>> $gp_error_file";

  ($error_code, $cmd_output) = execute_system_cmd ($gp_display_text_cmd);

  if ($error_code != 0)
    {
      $ignore_value = msg_display_text_failure ($gp_display_text_cmd, 
                                                $error_code, 
                                                $gp_error_file);
      gp_message ("abort", $subr_name, "execution terminated");
    }

#-------------------------------------------------------------------------------
# The first file has the following format:
#
# ID Sel     PID Experiment
# == === ======= ======================================================
#  1 yes 2078714 <absolute_path/mxv.hwc.1.thr.er
#  2 yes 2078719 <absolute_path/mxv.hwc.2.thr.er
#-------------------------------------------------------------------------------
  open (EXP_INFO, "<", $exp_info_file) 
    or die ("$subr_name - unable to open file $exp_info_file for reading '$!'");
  gp_message ("debug", $subr_name, "opened script file $exp_info_file for reading");

  chomp (@exp_info = <EXP_INFO>);

#-------------------------------------------------------------------------------
# TBD - Check for the groups to exist below:
#-------------------------------------------------------------------------------
  $current_slot = 0;
  for my $i (0 .. $#exp_info)
    {
      my $input_line = $exp_info[$i];

      gp_message ("debug", $subr_name, "$i => exp_info[$i] = $exp_info[$i]");

      if ($input_line =~ /^\s*(\d+)\s+(.+)/)
        {
          my $exp_id    = $1;
          my $remainder = $2;
          $experiment_data[$current_slot]{"exp_id"} = $exp_id;
          $experiment_data[$current_slot]{"exp_data_file"} = $outputdir . "gp-info-exp-" . $exp_id . ".out";
          gp_message ("debug", $subr_name, $i . " " . $exp_id . " " . $remainder);
          if ($remainder =~ /^(\w+)\s+(\d+)\s+(.+)/)
            {
              my $exp_name = $3;
              $experiment_data[$current_slot]{"exp_name_full"} = $exp_name;
              $experiment_data[$current_slot]{"exp_name_short"} = get_basename ($exp_name);
              $current_slot++;
              gp_message ("debug", $subr_name, $i . " " . $1 . " " . $2 . " " . $3);
            }
          else
            {
              my $msg = "remainder = $remainder has an unexpected format";
              gp_message ("assertion", $subr_name, $msg);
            }
        }
    }
#-------------------------------------------------------------------------------
# The experiment IDs and names are known.  We can now generate the info for
# each individual experiment.
#-------------------------------------------------------------------------------
  $gp_log_file   = $outputdir . $g_gp_output_file;
  $gp_error_file = $outputdir . $g_gp_error_logfile;

  $script_file = $outputdir . "gp-details-exp.script";

  open (SCRIPT_EXPERIMENT_DETAILS, ">", $script_file) 
    or die ("$subr_name - unable to open script file $script_file for writing: '$!'");
  gp_message ("debug", $subr_name, "opened script file $script_file for writing");

  for my $i (sort keys @experiment_data)
    {
      my $exp_id = $experiment_data[$i]{"exp_id"};

      $result_file = $experiment_data[$i]{"exp_data_file"};

# statistics
# header
      print SCRIPT_EXPERIMENT_DETAILS "# outfile "    . $result_file . "\n";
      print SCRIPT_EXPERIMENT_DETAILS "outfile "      . $result_file . "\n";
      print SCRIPT_EXPERIMENT_DETAILS "# header "     . $exp_id . "\n";
      print SCRIPT_EXPERIMENT_DETAILS "header "       . $exp_id . "\n";
      print SCRIPT_EXPERIMENT_DETAILS "# statistics " . $exp_id . "\n";
      print SCRIPT_EXPERIMENT_DETAILS "statistics "   . $exp_id . "\n";

    }

  close (SCRIPT_EXPERIMENT_DETAILS);

  $gp_functions_cmd = "$GP_DISPLAY_TEXT -script $script_file $the_experiments";

  gp_message ("debug", $subr_name, "executing $GP_DISPLAY_TEXT to get the experiment details");

  $gp_display_text_cmd = "$gp_functions_cmd 1>> $gp_log_file 2>> $gp_error_file";

  ($error_code, $cmd_output) = execute_system_cmd ($gp_display_text_cmd);

  if ($error_code != 0)
#-------------------------------------------------------------------------------
# This is unlikely to happen, but you never know.
#-------------------------------------------------------------------------------
    {
      $ignore_value = msg_display_text_failure ($gp_display_text_cmd, 
                                                $error_code, 
                                                $gp_error_file);
      gp_message ("abort", $subr_name, "execution terminated");
    }

  return (\@experiment_data);

} #-- End of subroutine get_experiment_info

#------------------------------------------------------------------------------
# This subroutine returns a string of the type "size=<n>", where <n> is the
# size of the file passed in.  If n > 1024, a unit is appended.
#------------------------------------------------------------------------------
sub getfilesize
{
  my $subr_name = get_my_name ();

  my ($filename) = @_;

  my $size;
  my $file_stat;

  if (not -e $filename)
    {
#------------------------------------------------------------------------------
# The return value is used in the caller.  This is why we return the empty
# string in case the file does not exist.
#------------------------------------------------------------------------------
      gp_message ("debug", $subr_name, "filename = $filename not found");
      return ("");
    }
  else
    {
      $file_stat = stat ($filename);
      $size      = $file_stat->size;

      gp_message ("debug", $subr_name, "filename = $filename");
      gp_message ("debug", $subr_name, "size     = $size");

      if ($size > 1024)
        {
          if ($size > 1024*1024)
            {
              $size = $size/1024/1024;
              $size =~ s/\..*//;
              $size = $size."MB";
            }
          else
            {
              $size = $size/1024;
              $size =~ s/\..*//;
              $size = $size."KB";
            }
        }
      else
        {
          $size=$size." bytes";
        }
      gp_message ("debug", $subr_name, "size = $size title=\"$size\"");

      return ("title=\"$size\"");
    }

} #-- End of subroutine getfilesize

#------------------------------------------------------------------------------
# Parse the fsummary output and for all functions, store all the information 
# found in "function_info".  In addition to this, several derived structures 
# are stored as well, making this structure a "onestop" place to get all the
# info that is needed.
#------------------------------------------------------------------------------
sub get_function_info
{ 
  my $subr_name = get_my_name ();

  my ($FSUMMARY_FILE) = @_;

#------------------------------------------------------------------------------
# The regex section.
#------------------------------------------------------------------------------
  my $white_space_regex = '\s*';

  my @function_info              = ();
  my %function_address_and_index = ();
  my %LINUX_vDSO                 = ();
  my %function_view_structure    = ();
  my %addressobjtextm            = ();
#------------------------------------------------------------------------------
# TBD: This structure is no longer used and most likely can be removed.
#------------------------------------------------------------------------------
  my %functions_index             = ();

# TBD: check
  my $full_address_field;
  my %source_files   = ();

  my $i;
  my $line;
  my $routine_flag;
  my $value;
  my $whatever;
  my $df_flag;
  my $address_decimal;
  my $routine;

  my $num_source_files           = 0;
  my $number_of_functions        = 0;
  my $number_of_unique_functions = 0;
  my $number_of_non_unique_functions = 0;

#------------------------------------------------------------------------------
# Open the file generated using the -fsummary option.
#------------------------------------------------------------------------------
  open (FSUMMARY_FILE, "<", $FSUMMARY_FILE)
    or die ("$subr_name - unable to open $FSUMMARY_FILE for reading: '$!'");
  gp_message ("debug", $subr_name, "opened file $FSUMMARY_FILE for reading");

#------------------------------------------------------------------------------
# This is the typical structure of the fsummary output:
#
# Current Sort Metric: Exclusive Total CPU Time ( e.totalcpu )
# Functions sorted by metric: Exclusive Total CPU Time
# 
# <Total>
#         Exclusive Total CPU Time: 11.538 (100.0%)
#         Inclusive Total CPU Time: 11.538 (100.0%)
#                             Size:      0
#                       PC Address: 1:0x00000000
#                      Source File: (unknown)
#                      Object File: (unknown)
#                      Load Object: <Total>
#                     Mangled Name:
#                          Aliases:
# 
# a_function_name
#         Exclusive Total CPU Time:  4.003 ( 34.7%)
#         Inclusive Total CPU Time:  4.003 ( 34.7%)
#                             Size:    715
#                       PC Address: 2:0x00006c61
#                      Source File: <absolute path to source file> 
#                      Object File: <object filename> 
#                      Load Object: <executable name>
#                     Mangled Name:
#                          Aliases:
#
# The previous block is repeated for every function.
#------------------------------------------------------------------------------

#------------------------------------------------------------------------------
# Skip the header.  The header is defined to end with a blank line.
#------------------------------------------------------------------------------
  while (<FSUMMARY_FILE>)
    {
      $line = $_;
      chomp ($line);
      if ($line =~ /^\s*$/)
        {
          last;
        }
    }

#------------------------------------------------------------------------------
# Process the remaining blocks.  Note that the first line should be <Total>,
# but this is currently not checked.
#------------------------------------------------------------------------------
  $i = 0;
  $routine_flag = $TRUE;
  while (<FSUMMARY_FILE>)
    {
      $line = $_;
      chomp ($line);
      gp_message ("debugXL", $subr_name, "line = $line");

      if ($line =~ /^\s*$/)
#------------------------------------------------------------------------------
# Blank line.
#------------------------------------------------------------------------------
        {
          $routine_flag = $TRUE;
          $df_flag = 0;

#------------------------------------------------------------------------------
# Linux vDSO exception
#
# TBD: Check if still relevant.
#------------------------------------------------------------------------------
          if ($function_info[$i]{"Load Object"} eq "DYNAMIC_FUNCTIONS")
            {
              $LINUX_vDSO{substr ($function_info[$i]{"addressobjtext"},1)} = $function_info[$i]{"routine"};
            }
          $i++;
          next;
        }

      if ($routine_flag)
#------------------------------------------------------------------------------
# Should be the first line after the blank line.
#------------------------------------------------------------------------------
        {
          $routine                      = $line;
          push (@{ $g_map_function_to_index{$routine} }, $i);
          gp_message ("debugXL", $subr_name, "pushed i = $i to g_map_function_to_index{$routine}");

#------------------------------------------------------------------------------
# In a later parsing phase we need to know how many fields there are in a
# function name. For example, "<static>@0x21850 (<libc-2.28.so>)" is name that
# may show up in a function list.
#
# Here we determine the number of fields and store it.
#------------------------------------------------------------------------------
          my @fields_in_name = split (" ", $routine);
          $function_info[$i]{"fields in routine name"} = scalar (@fields_in_name);

#------------------------------------------------------------------------------
# This name may change if the function has multiple occurrences, but in any
# case, at the end of this routine this component has the final name to be
# used.
#------------------------------------------------------------------------------
          $function_info[$i]{"alt_name"} = $routine;
          if (not exists ($g_function_occurrences{$routine}))
            {
              gp_message ("debugXL", $subr_name, "the entry in function_info for $routine does not exist");
              $function_info[$i]{"routine"} = $routine;
              $g_function_occurrences{$routine} = 1;

              gp_message ("debugXL", $subr_name, "g_function_occurrences{$routine} = $g_function_occurrences{$routine}");
            }
          else
            {
              gp_message ("debugXL", $subr_name, "the entry in function_info for $routine exists already");
              $function_info[$i]{"routine"} = $routine;
              $g_function_occurrences{$routine} += 1;
              if (not exists ($g_multi_count_function{$routine}))
                {
                  $g_multi_count_function{$routine} = $TRUE;
                }
              my $msg = "g_function_occurrences{$routine} = " .
                        $g_function_occurrences{$routine};
              gp_message ("debugXL", $subr_name, $msg);
            }
#------------------------------------------------------------------------------
# New: used when generating the index.
#------------------------------------------------------------------------------
          $function_info[$i]{"function length"} = length ($routine);
          $function_info[$i]{"tag_id"} = create_function_tag ($i);
          if (not exists ($g_function_tag_id{$routine}))
            {
              $g_function_tag_id{$routine} = create_function_tag ($i);
            }
          else
            {

#------------------------------------------------------------------------------
## TBD HACK!!! CHECK!!!!!
#------------------------------------------------------------------------------
              $g_function_tag_id{$routine} = $i;
            }

          $routine_flag = $FALSE;
          gp_message ("debugXL", $subr_name, "stored " . $function_info[$i]{"routine"});

#------------------------------------------------------------------------------
# The $functions_index hash contains an array.  After an initial assignment, 
# other values that have been found are pushed onto the arrays.
#------------------------------------------------------------------------------
          if (not exists ($functions_index{$routine}))
            {
              $functions_index{$routine} = [$i];
            } 
          else 
            {
#------------------------------------------------------------------------------
# Add the array index to the list
#------------------------------------------------------------------------------
              push (@{$functions_index{$routine}}, $i);
            }
          next;
        }

#------------------------------------------------------------------------------
# Expected format of an input line:
#   Exclusive Total CPU Time:  4.003 ( 34.7%)
# or:
#   Source File: <absolute_path>/name_of_source_file
#------------------------------------------------------------------------------
      $line =~ s/^\s+//;

      my @input_fields   = split (":", $line);
      my $no_of_elements = scalar (@input_fields);

      gp_message ("debugXL", $subr_name, "#input_fields = $#input_fields");
      gp_message ("debugXL", $subr_name, "no_of_elements = $no_of_elements");
      gp_message ("debugXL", $subr_name, "input_fields[0] = $input_fields[0]");

      if ($no_of_elements == 1)
        {
          $whatever = $input_fields[0];
          $value    = "";
        }
      elsif ($no_of_elements == 2)
        {
#------------------------------------------------------------------------------
# Note that value may consist of multiple fields (e.g. 1.651 ( 95.4%)).
#------------------------------------------------------------------------------
          $whatever = $input_fields[0];
          $value    = $input_fields[1];
        }
      elsif ($no_of_elements == 3)
        {
#------------------------------------------------------------------------------
# Assumption: must be an address field.  Restore the second colon.
#------------------------------------------------------------------------------
          $whatever = $input_fields[0];
          $value    = $input_fields[1] . ":" . $input_fields[2];
        }
      else
        {
          my $msg = "unexpected: number of fields = " . $no_of_elements; 
          gp_message ("assertion", $subr_name, $msg);
        }
#------------------------------------------------------------------------------
# Remove any leading whitespace characters.
#------------------------------------------------------------------------------
      $value =~ s/$white_space_regex//;

      gp_message ("debugXL", $subr_name, "whatever = $whatever value = $value");

      $function_info[$i]{$whatever} = $value;

#------------------------------------------------------------------------------
# TBD: Seems to be not used anymore and can most likely be removed. Check this.
#------------------------------------------------------------------------------
      if ($whatever =~ /Source File/)
        {
          if (!exists ($source_files{$value}))
            {
              $source_files{$value} = $TRUE;
              $num_source_files++;
            }
        }

      if ($whatever =~ /PC Address/)
        {
          my $segment;
          my $offset;
#------------------------------------------------------------------------------
# The format of the address is assumed to be the following 2:0x000070a8
# Note that the regex is pretty wide.  This is from the original code and 
# could be made more specific:
#          if ($value =~ /\s*(\S+):(\S+)/)
#------------------------------------------------------------------------------
#          if ($value =~ /\s*(\S+):(\S+)/)
          if ($value =~ /\s*(\d+):0x([0-9a-zA-Z]+)/)
            {
              $segment = $1;
              $offset  = $2;
#------------------------------------------------------------------------------
# Convert to a base 10 number
#------------------------------------------------------------------------------
              $address_decimal = bigint::hex ($offset); # decimal
#------------------------------------------------------------------------------
# Construct the address field.  Note that we use the hex address here.
#------------------------------------------------------------------------------
              $full_address_field = '@'.$segment.":0x".$offset; # e.g. @2:0x0003f280

              $function_info[$i]{"addressobj"}     = $address_decimal;
              $function_info[$i]{"addressobjtext"} = $full_address_field;
              $addressobjtextm{$full_address_field} = $i; # $RI
            }
          if (not exists ($function_address_and_index{$routine}{$value}))
            {
              $function_address_and_index{$routine}{$value} = $i;

              my $msg = "function_address_and_index{$routine}{$value} = " .
                        $function_address_and_index{$routine}{$value};
              gp_message ("debugXL", $subr_name, $msg);
            } 
          else 
            {
              gp_message ("debugXL", $subr_name, "function_info: $FSUMMARY_FILE: function $routine already has a PC Address");
            } 

          $number_of_functions++;
        }
    }
  close (FSUMMARY_FILE);
 
#------------------------------------------------------------------------------
# For every function in the function overview, set up an html structure with
# the various hyperlinks.
#------------------------------------------------------------------------------
  gp_message ("debugXL", $subr_name, "augment function_info with alt_name");
  my $target_function; 
  my $html_line;
  my $ftag;
  my $routine_length; 
  my %html_source_functions = ();
  for my $i (keys @function_info)
    {
      $target_function = $function_info[$i]{"routine"};

      gp_message ("debugXL", $subr_name, "i = $i target_function = $target_function");

      my $href_link;
##      $href_link  = "<a href=\'file." . $i . ".src.new.html#";
      $href_link  = "<a href=\'file." . $i . ".";
      $href_link .= $g_html_base_file_name{"source"};
      $href_link .= ".html#";
      $href_link .= $function_info[$i]{"tag_id"};
      $href_link .= "\'>source</a>";
      $function_info[$i]{"href_source"} = $href_link;

      $href_link  = "<a href=\'file." . $i . ".";
      $href_link .= $g_html_base_file_name{"disassembly"};
      $href_link .= ".html#";
      $href_link .= $function_info[$i]{"tag_id"};
      $href_link .= "\'>disassembly</a>";
      $function_info[$i]{"href_disassembly"} = $href_link;

      $href_link  = "<a href=\'";
      $href_link .= $g_html_base_file_name{"caller_callee"};
      $href_link .= ".html#";
      $href_link .= $function_info[$i]{"tag_id"};
      $href_link .= "\'>caller-callee</a>";
      $function_info[$i]{"href_caller_callee"} = $href_link;

      gp_message ("debug", $subr_name, "g_function_occurrences{$target_function} = $g_function_occurrences{$target_function}");

      if ($g_function_occurrences{$target_function} > 1)
        {
#------------------------------------------------------------------------------
# In case a function occurs more than one time in the function overview, we
# add the load object and address offset info to make it unique.
#
# This forces us to update some entries in function_info too.
#------------------------------------------------------------------------------
          my $loadobj = $function_info[$i]{"Load Object"};
          my $address_field = $function_info[$i]{"addressobjtext"};
          my $address_offset; 

#------------------------------------------------------------------------------
# The address field has the following format: @<n>:<address_offset>
# We only care about the address offset.
#------------------------------------------------------------------------------
          if ($address_field =~ /(^@\d*:*)(.+)/)
            {
              $address_offset = $2;
            }
          else
            {
              my $msg = "failed to extract the address offset from $address_field - use the full field";
              gp_message ("warning", $subr_name, $msg);
              $address_offset = $address_field;
            }
          my $exe = get_basename ($loadobj);
          my $extra_field = " (<" . $exe . " $address_offset" .">)";
###          $target_function .= $extra_field;
          $function_info[$i]{"alt_name"} = $target_function . $extra_field;
          gp_message ("debugXL", $subr_name, "function_info[$i]{\"alt_name\"} = " . $function_info[$i]{"alt_name"});

#------------------------------------------------------------------------------
# Store the length of the function name and get the tag id.
#------------------------------------------------------------------------------
          $function_info[$i]{"function length"} = length ($target_function . $extra_field);
          $function_info[$i]{"tag_id"} = create_function_tag ($i);

          gp_message ("debugXL", $subr_name, "updated function_info[$i]{'routine'} = $function_info[$i]{'routine'}");
          gp_message ("debugXL", $subr_name, "updated function_info[$i]{'alt_name'} = $function_info[$i]{'alt_name'}");
          gp_message ("debugXL", $subr_name, "updated function_info[$i]{'function length'} = $function_info[$i]{'function length'}");
          gp_message ("debugXL", $subr_name, "updated function_info[$i]{'tag_id'} = $function_info[$i]{'tag_id'}");
        }
    }
  gp_message ("debug", $subr_name, "augment function_info with alt_name completed");

#------------------------------------------------------------------------------
# Compute the maximum function name length. 
#
# The maximum length is stored in %function_view_structure.
#------------------------------------------------------------------------------
  my $max_function_length = 0;
  for my $i (0 .. $#function_info)
    {
      $max_function_length = max ($max_function_length, $function_info[$i]{"function length"});

      gp_message ("debugXL", $subr_name, "function_info[$i]{\"alt_name\"} = " . $function_info[$i]{"alt_name"} . " length = " . $function_info[$i]{"function length"});
    }

#------------------------------------------------------------------------------
# Define the name of the table and take the length into account, since it may
# be longer than the function name(s).
#------------------------------------------------------------------------------
  $function_view_structure{"table name"} = "Function name";

  $max_function_length = max ($max_function_length, length ($function_view_structure{"table name"}));

  $function_view_structure{"max function length"} = $max_function_length;

#------------------------------------------------------------------------------
# Core loop that generates an HTML line for each function.  This line is
# stored in function_info.
#------------------------------------------------------------------------------
  my $top_of_table = $FALSE;
  for my $i (keys @function_info)
    {
      my $new_target_function; 

      if (defined ($function_info[$i]{"alt_name"}))
        {
          $target_function = $function_info[$i]{"alt_name"};
          gp_message ("debugXL", $subr_name, "retrieved function_info[$i]{'alt_name'} = $function_info[$i]{'alt_name'}");
        }
      else
        {
          my $msg = "function_info[$i]{\"alt_name\"} is not defined";
          gp_message ("assertion", $subr_name, $msg);
        }

      my $function_length  = $function_info[$i]{"function length"};
      my $number_of_blanks = $function_view_structure{"max function length"} - $function_length;

      my $spaces = "&nbsp;&nbsp;";
      for my $i (1 .. $number_of_blanks)
        {
          $spaces .= "&nbsp;";
        }
      if ($target_function eq "<Total>")
#------------------------------------------------------------------------------
# <Total> is a pseudo function and there is no source, or disassembly for it.
# We could add a link to the caller-callee part, but this is currently not 
# done.
#------------------------------------------------------------------------------
        {
          $top_of_table = $TRUE;
          $html_line  = "&nbsp;<b>&lt;Total></b>";
        }
      else
        {
#------------------------------------------------------------------------------
# Add the * symbol as a marker in case the same function occurs multiple times.
# Otherwise insert a space.
#------------------------------------------------------------------------------
          my $base_function_name = $function_info[$i]{"routine"};
          if (exists ($g_function_occurrences{$base_function_name}))
            {
              if ($g_function_occurrences{$base_function_name} > 1)
                {
                  $new_target_function = "*" . $target_function;
                }
              else
                {
                  $new_target_function = "&nbsp;" . $target_function;
                }
            }
          else
            {
              my $msg = "g_function_occurrences{$base_function_name} does not exist";
              gp_message ("assertion", $subr_name, $msg);
            }

#------------------------------------------------------------------------------
# Create the block with the function name, in boldface, plus the links to the 
# source, disassembly and caller-callee views.
#------------------------------------------------------------------------------

#------------------------------------------------------------------------------
# We need to replace the "<" symbol in the code by "&lt;".
#------------------------------------------------------------------------------
          $new_target_function =~ s/$g_less_than_regex/$g_html_less_than_regex/g;

          $html_line  = "<b>$new_target_function</b>" . $spaces;
          $html_line .= $function_info[$i]{"href_source"}      . "&nbsp;";
          $html_line .= $function_info[$i]{"href_disassembly"} . "&nbsp;";
          $html_line .= $function_info[$i]{"href_caller_callee"};
        }

      gp_message ("debugXL", $subr_name, "target_function = $target_function html_line = $html_line");
      $html_source_functions{$target_function} = $html_line;

#------------------------------------------------------------------------------
# TBD: In the future we want to re-use this block elsewhere.
#------------------------------------------------------------------------------
      $function_info[$i]{"html function block"} = $html_line;
    }

  for my $i (keys %html_source_functions)
    {
      gp_message ("debugXL", $subr_name, "html_source_functions{$i} = $html_source_functions{$i}");
    }
  for my $i (keys @function_info)
    {
      gp_message ("debugXL", $subr_name, "function_info[$i]{\"html function block\"} = " . $function_info[$i]{"html function block"}); 
    }

#------------------------------------------------------------------------------
# Print the key data structure %function_info.  This is a nested hash.
#------------------------------------------------------------------------------
  for my $i (0 .. $#function_info)
    {
      for my $role (sort keys %{ $function_info[$i] })
        {
           gp_message ("debug", $subr_name, "on return: function_info[$i]{$role} = $function_info[$i]{$role}");
        }
    }
#------------------------------------------------------------------------------
# Print the data structure %function_address_and_index. This is a nested hash.
#------------------------------------------------------------------------------
  for my $F (keys %function_address_and_index)
    {
      for my $fields (sort keys %{ $function_address_and_index{$F} })
        {
           gp_message ("debug", $subr_name, "on return: function_address_and_index{$F}{$fields} = $function_address_and_index{$F}{$fields}");
        }
    }
#------------------------------------------------------------------------------
# Print the data structure %functions_index. This is a hash with an arrray.
#------------------------------------------------------------------------------
  for my $F (keys %functions_index)
    {
      gp_message ("debug", $subr_name, "on return: functions_index{$F} = @{ $functions_index{$F} }");
# alt code      for my $i (0 .. $#{ $functions_index{$F} } )
# alt code        {
# alt code           gp_message ("debug", $subr_name, "on return: \$functions_index{$F} = $functions_index{$F}[$i]");
# alt code        }
    }

#------------------------------------------------------------------------------
# Print the data structure %function_view_structure. This is a hash. 
#------------------------------------------------------------------------------
  for my $F (keys %function_view_structure)
    {
      gp_message ("debug", $subr_name, "on return: function_view_structure{$F} = $function_view_structure{$F}");
    }

#------------------------------------------------------------------------------
# Print the data structure %g_function_occurrences and use this structure to
# gather statistics about the functions.
#
# TBD: add this info to the experiment data overview.
#------------------------------------------------------------------------------
  $number_of_unique_functions = 0;
  $number_of_non_unique_functions = 0;
  for my $F (keys %g_function_occurrences)
    {
      gp_message ("debug", $subr_name, "on return: g_function_occurrences{$F} = $g_function_occurrences{$F}");
      if ($g_function_occurrences{$F} == 1)
        {
          $number_of_unique_functions++; 
        }
      else
        {
          $number_of_non_unique_functions++; 
        }
    }

  for my $i (keys %g_map_function_to_index)
    {
      my $n = scalar (@{ $g_map_function_to_index{$i} });
      gp_message ("debug", $subr_name, "on return: g_map_function_to_index [$n] : $i => @{ $g_map_function_to_index{$i} }");
    }

#------------------------------------------------------------------------------
# TBD: Include in experiment data. Include names with multiple occurrences.
#------------------------------------------------------------------------------
  my $msg;

  $msg = "Number of source files                                        : " .
         $num_source_files;
  gp_message ("debug", $subr_name, $msg);
  $msg = "Total number of functions: $number_of_functions"; 
  gp_message ("debug", $subr_name, $msg);
  $msg = "Number of functions functions with a unique name              : " .
         $number_of_unique_functions; 
  gp_message ("debug", $subr_name, $msg);
  $msg = "Number of functions functions with more than one occurrence   : " .
         $number_of_non_unique_functions; 
  gp_message ("debug", $subr_name, $msg);
  my $multi_occurrences = $number_of_functions - $number_of_unique_functions; 
  $msg = "Total number of multiple occurences of the same function name : " .
         $multi_occurrences; 
  gp_message ("debug", $subr_name, $msg);

  return (\@function_info, \%function_address_and_index, \%addressobjtextm, 
          \%LINUX_vDSO, \%function_view_structure);

} #-- End of subroutine get_function_info
#------------------------------------------------------------------------------
# TBD
#------------------------------------------------------------------------------
sub get_hdr_info
{
  my $subr_name = get_my_name ();

  my ($outputdir, $file) = @_;

  state $first_call = $TRUE;

  my $ASORTFILE;
  my @HDR;
  my $HDR;
  my $metric;
  my $line;
  my $ignore_directory;
  my $ignore_suffix;
  my $number_of_header_lines;

#------------------------------------------------------------------------------
# Add a "/" to simplify the construction of path names in the remainder.
#------------------------------------------------------------------------------
  $outputdir = append_forward_slash ($outputdir);

# Could get more header info from
# <metric>[e.bit_fcount].sort.func file - etc.

  gp_message ("debug", $subr_name, "input file->$file<-");
#-----------------------------------------------
  if ($file eq $outputdir."calls.sort.func")
    {
      $ASORTFILE=$outputdir."calls";
      $metric = "calls"
    } 
  elsif ($file eq $outputdir."calltree.sort.func")
    {
      $ASORTFILE=$outputdir."calltree";
      $metric = "calltree"
    }
  elsif ($file eq $outputdir."functions.sort.func")
    {
      $ASORTFILE=$outputdir."functions.func";
      $metric = "functions";
    }
  else
    {
      $ASORTFILE = $file;
#      $metric = basename ($file,".sort.func");
      ($metric, $ignore_directory,  $ignore_suffix) = fileparse ($file, ".sort.func");
      gp_message ("debug", $subr_name, "ignore_directory = $ignore_directory ignore_suffix = $ignore_suffix");
    }

  gp_message ("debug", $subr_name, "file = $file metric = $metric");

  open (ASORTFILE,"<", $ASORTFILE)
    or die ("$subr_name - unable to open file $ASORTFILE for reading: '$!'");
  gp_message ("debug", $subr_name, "opened file $ASORTFILE for reading");

  $number_of_header_lines = 0;
  while (<ASORTFILE>)
    {
      $line =$_;
      chomp ($line);

      if ($line  =~ /^Current/)
        {
          next;
        }
      if ($line  =~ /^Functions/)
        {
          next;
        }
      if ($line  =~ /^Callers/)
        {
          next;
        }
      if ($line  =~ /^\s*$/)
        {
          next;
        }
      if (!($line  =~ /^\s*\d/))
        {
          $HDR[$number_of_header_lines] = $line;
          $number_of_header_lines++;
          next;
        }
      last;
     }
  close (ASORTFILE);
#-------------------------------------------------------------------------------
# Ruud - Fixed a bug. The output should not be appended, but overwritten.
# open (HI,">>$OUTPUTDIR"."hdrinfo");
#-------------------------------------------------------------------------------
  my $outfile = $outputdir."hdrinfo";

  if ($first_call)
    {
      $first_call = $FALSE;
      open (HI ,">", $outfile)
        or die ("$subr_name - unable to open file $outfile for writing: '$!'");
      gp_message ("debug", $subr_name, "opened file $outfile for writing");
    }
  else
    {
      open (HI ,">>", $outfile)
        or die ("$subr_name - unable to open file $outfile in append mode: '$!'");
      gp_message ("debug", $subr_name, "opened file $outfile in append mode");
    }

  print HI "\#$metric hdrlines=$number_of_header_lines\n";
  my $len = 0;
  for $HDR (@HDR)
    {
      print HI "$HDR\n";
      gp_message ("debugXL", $subr_name, "HDR = $HDR\n");
    }
  close (HI);
  if ($first_call)
    {
      gp_message ("debug", $subr_name, "wrote file $outfile");
    }
  else
    {
      gp_message ("debug", $subr_name, "updated file $outfile");
    }
#-----------------------------------------------

} #-- End of subroutine get_hdr_info

#------------------------------------------------------------------------------
# Get the home directory and the location(s) of the configuration file on the 
# current system.
#------------------------------------------------------------------------------
sub get_home_dir_and_rc_path
{
  my $subr_name = get_my_name ();

  my ($rc_file_name) = @_;

  my @rc_file_paths;
  my $target_cmd;
  my $home_dir;
  my $error_code;

  $target_cmd  = $g_mapped_cmds{"printenv"} . " HOME";

  ($error_code, $home_dir) = execute_system_cmd ($target_cmd);
   
  if ($error_code != 0)
    {
      my $msg = "cannot find a setting for HOME - please set this"; 
      gp_message ("assertion", $subr_name, $msg);
    }
  else

#------------------------------------------------------------------------------
# The home directory is known and we can define the locations for the 
# configuration file.
#------------------------------------------------------------------------------
    {
      @rc_file_paths = (".", "$home_dir");
    } 
  
  gp_message ("debug", $subr_name, "upon return: \@rc_file_paths = @rc_file_paths");

  return ($home_dir, \@rc_file_paths);

} #-- End of subroutine get_home_dir_and_rc_path

#------------------------------------------------------------------------------
# This subroutine generates a list with the hot functions.
#------------------------------------------------------------------------------
sub get_hot_functions
{
  my $subr_name = get_my_name ();

  my ($exp_dir_list_ref, $summary_metrics, $input_string) = @_;

  my @exp_dir_list = @{ $exp_dir_list_ref };

  my $cmd_output;
  my $error_code;
  my $expr_name;
  my $first_metric;
  my $gp_display_text_cmd;
  my $ignore_value;

  my @sort_fields = ();

  $expr_name = join (" ", @exp_dir_list);

  gp_message ("debug", $subr_name, "expr_name = $expr_name");

  my $outputdir = append_forward_slash ($input_string);

  my $script_file   = $outputdir."gp-fsummary.script";
  my $outfile       = $outputdir."gp-fsummary.out";
  my $result_file   = $outputdir."gp-fsummary.stderr";
  my $gp_error_file = $outputdir.$g_gp_error_logfile;

  @sort_fields = split (":", $summary_metrics);

#------------------------------------------------------------------------------
# This is extremely unlikely to happen, but if so, it is a fatal error.
#------------------------------------------------------------------------------
  my $number_of_elements = scalar (@sort_fields);

  gp_message ("debug", $subr_name, "number of fields in summary_metrics = $number_of_elements");

  if ($number_of_elements == 0)
    {
      my $msg = "there are $number_of_elements in the metrics list";
      gp_message ("assertion", $subr_name, $msg);
    }

#------------------------------------------------------------------------------
# Get the summary of the hot functions
#------------------------------------------------------------------------------
  open (SCRIPT, ">", $script_file) 
    or die ("$subr_name - unable to open script file $script_file for writing: '$!'");
  gp_message ("debug", $subr_name, "opened script file $script_file for writing");

#------------------------------------------------------------------------------
# TBD: Check what this is about:
# Attributed User CPU Time=a.user : for calltree - see P37 in manual
#------------------------------------------------------------------------------
  print SCRIPT "# limit 0\n";
  print SCRIPT "limit 0\n";
  print SCRIPT "# metrics $summary_metrics\n";
  print SCRIPT "metrics $summary_metrics\n";
  print SCRIPT "# thread_select all\n";
  print SCRIPT "thread_select all\n";

#------------------------------------------------------------------------------
# Use first out of summary metrics as first (it doesn't matter which one)
# $first_metric = (split /:/,$summary_metrics)[0];
#------------------------------------------------------------------------------

  $first_metric = $sort_fields[0];

  print SCRIPT "# outfile $outfile\n";
  print SCRIPT "outfile $outfile\n";
  print SCRIPT "# sort $first_metric\n";
  print SCRIPT "sort $first_metric\n";
  print SCRIPT "# fsummary\n";
  print SCRIPT "fsummary\n";

  close SCRIPT;

  my $gp_functions_cmd = "$GP_DISPLAY_TEXT -viewmode machine -compare off -script $script_file $expr_name";

  gp_message ("debug", $subr_name, "executing $GP_DISPLAY_TEXT to get the list of functions");

  $gp_display_text_cmd = "$gp_functions_cmd 1> $result_file 2>> $gp_error_file";

  ($error_code, $cmd_output) = execute_system_cmd ($gp_display_text_cmd);

  if ($error_code != 0)
    {
      $ignore_value = msg_display_text_failure ($gp_display_text_cmd, 
                                                $error_code, 
                                                $gp_error_file);
      gp_message ("abort", $subr_name, "execution terminated");
      my $msg = "error code = $error_code - failure executing command $gp_display_text_cmd";
      gp_message ("abort", $subr_name, $msg);
    }

  return ($outfile,\@sort_fields);

} #-- End of subroutine get_hot_functions

#------------------------------------------------------------------------------
# For a given function name, return the index into "function_info".  This
# index gives access to all the meta data for the input function.
#------------------------------------------------------------------------------
sub get_index_function_info
{
  my $subr_name = get_my_name ();

  my ($routine_ref, $hex_address_ref, $function_info_ref) = @_;

  my $routine     = ${ $routine_ref };
  my $hex_address = ${ $hex_address_ref };
  my @function_info = @{ $function_info_ref };

#------------------------------------------------------------------------------
# Check if this function has multiple occurrences.
#------------------------------------------------------------------------------
  gp_message ("debug", $subr_name, "check for multiple occurrences");

  my $current_address = $hex_address;
  my $alt_name = $routine;

  my $found_a_match;
  my $index_into_function_info;
  my $target_tag;

  if (not exists ($g_multi_count_function{$routine}))
    {
#------------------------------------------------------------------------------
# There is only a single occurrence and it is straightforward to get the tag.
#--------------------------------------------------------------------------
##          push (@final_function_names, $routine);
      if (exists ($g_map_function_to_index{$routine}))
        {
          $index_into_function_info = $g_map_function_to_index{$routine}[0];
        }
      else
        {
          my $msg = "no entry for $routine in g_map_function_to_index";
          gp_message ("assertion", $subr_name, $msg);
        }
    }
  else
    {
#------------------------------------------------------------------------------
# The function name has more than one occurrence and we need to find the one
# that matches with the address.
#------------------------------------------------------------------------------
      $found_a_match = $FALSE;
      gp_message ("debug", $subr_name, "$routine: occurrences = $g_function_occurrences{$routine}");
      for my $ref (keys @{ $g_map_function_to_index{$routine} })
        {
          my $ref_index   = $g_map_function_to_index{$routine}[$ref];
          my $addr_offset = $function_info[$ref_index]{"addressobjtext"};

          gp_message ("debug", $subr_name, "$routine: retrieving duplicate entry at ref_index = $ref_index");
          gp_message ("debug", $subr_name, "$routine: addr_offset = $addr_offset");
  
#------------------------------------------------------------------------------
# TBD: Do this substitution when storing "addressobjtext" in function_info.
#------------------------------------------------------------------------------
          $addr_offset =~ s/^@\d+://;
          gp_message ("debug", $subr_name, "$routine: addr_offset = $addr_offset");
          if ($addr_offset eq $current_address)
            {
              $found_a_match = $TRUE;
              $index_into_function_info = $ref_index;
              last;
            }
        }

#------------------------------------------------------------------------------
# If there is no match, something has gone really wrong and we bail out.
#------------------------------------------------------------------------------
      if (not $found_a_match)
        {
          my $msg = "cannot find the mapping in function_info for function $routine";
          gp_message ("assertion", $subr_name, $msg);
        }
    }

  return (\$index_into_function_info);

} #-- End of subroutine get_index_function_info

#-------------------------------------------------------------------------------
# Get the setting for LANG, or assign a default if it is not set.
#-------------------------------------------------------------------------------
sub get_LANG_setting
{
  my $subr_name = get_my_name ();

  my $error_code;
  my $lang_setting;
  my $target_cmd;
  my $command_string; 
  my $LANG;

  $target_cmd = $g_mapped_cmds{"printenv"};
#------------------------------------------------------------------------------
# Use the printenv command to get the settings for LANG.
#------------------------------------------------------------------------------
  if ($target_cmd eq "road_to_nowhere")
    {
      $error_code = 1;
    }
  else
    {
      $command_string = $target_cmd . " LANG";
      ($error_code, $lang_setting) = execute_system_cmd ($command_string);
    }

  if ($error_code == 0)
    {
      chomp ($lang_setting);
      $LANG = $lang_setting;
    }
  else
    {
      $LANG = $g_default_setting_lang;
      my $msg = "cannot find a setting for LANG - use a default setting";
      gp_message ("warning", $subr_name, $msg);
    }

  return ($LANG);

} #-- End of subroutine get_LANG_setting

#------------------------------------------------------------------------------
# This subroutine gathers the basic information about the metrics.
#------------------------------------------------------------------------------
sub get_metrics_data
{
  my $subr_name = get_my_name ();

  my ($exp_dir_list_ref, $outputdir, $outfile1, $outfile2, $error_file) = @_;

  my @exp_dir_list = @{ $exp_dir_list_ref };

  my $cmd_options; 
  my $cmd_output; 
  my $error_code;
  my $expr_name;
  my $metrics_cmd;
  my $metrics_output;
  my $target_cmd;

  $expr_name = join (" ", @exp_dir_list);

  gp_message ("debug", $subr_name, "expr_name = $expr_name");

#------------------------------------------------------------------------------
# Execute the $GP_DISPLAY_TEXT tool with the appropriate options.  The goal is
# to get all the output in files $outfile1 and $outfile2.  These are then
# parsed.
#------------------------------------------------------------------------------
  $cmd_options   = " -viewmode machine -compare off -thread_select all"; 
  $cmd_options  .= " -outfile $outfile2";
  $cmd_options  .= " -fsingle '<Total>' -metric_list $expr_name";

  $metrics_cmd   = "$GP_DISPLAY_TEXT $cmd_options 1> $outfile1 2> $error_file";

  gp_message ("debug", $subr_name, "command used to gather the information:");
  gp_message ("debug", $subr_name, $metrics_cmd);

  ($error_code, $metrics_output) = execute_system_cmd ($metrics_cmd);

#------------------------------------------------------------------------------
# Error handling.  Any error that occurred is fatal and execution 
# should be aborted by the caller.
#------------------------------------------------------------------------------
  if ($error_code == 0)
    {
      gp_message ("debug", $subr_name, "metrics data in files $outfile1 and $outfile2");
    }
  else
    {
      $target_cmd  = $g_mapped_cmds{"cat"} . " $error_file";

      ($error_code, $cmd_output) = execute_system_cmd ($target_cmd);

      chomp ($cmd_output);

      gp_message ("error", $subr_name, "contents of file $error_file:");
      gp_message ("error", $subr_name, $cmd_output);
    }

  return ($error_code);

} #-- End of subroutine get_metrics_data

#------------------------------------------------------------------------------
# Wrapper that returns the last part of the subroutine name.  The assumption is
# that the last part of the input name is of the form "aa::bb" or just "bb".
#------------------------------------------------------------------------------
sub get_my_name
{
  my $called_by = (caller (1))[3];
  my @parts     = split ("::", $called_by);
  return ($parts[$#parts]);

##  my ($the_full_name_ref) = @_;

##  my $the_full_name = ${ $the_full_name_ref };
##  my $last_part;

#------------------------------------------------------------------------------
# If the regex below fails, use the full name."
#------------------------------------------------------------------------------
##  $last_part = $the_full_name;

#------------------------------------------------------------------------------
# Capture the last part if there are multiple parts separated by "::".
#------------------------------------------------------------------------------
##  if ($the_full_name =~ /.*::(.+)$/)
##    {
##      if (defined ($1))
##        {
##          $last_part = $1;
##        }
##    }

##  return (\$last_part);

} #-- End of subroutine get_my_name

#-------------------------------------------------------------------------------
# Determine the characteristics of the current system
#-------------------------------------------------------------------------------
sub get_system_config_info
{
#------------------------------------------------------------------------------
# The output from the "uname" command is used for this. Although not all of
# these are currently used, we store all fields in separate variables.
#------------------------------------------------------------------------------
#
#------------------------------------------------------------------------------
# The options supported on uname from GNU coreutils 8.22:
#------------------------------------------------------------------------------
#   -a, --all                print all information, in the following order,
#                              except omit -p and -i if unknown:
#   -s, --kernel-name        print the kernel name
#   -n, --nodename           print the network node hostname
#   -r, --kernel-release     print the kernel release
#   -v, --kernel-version     print the kernel version
#   -m, --machine            print the machine hardware name
#   -p, --processor          print the processor type or "unknown"
#   -i, --hardware-platform  print the hardware platform or "unknown"
#   -o, --operating-system   print the operating system
#------------------------------------------------------------------------------
# Sample output:
# Linux ruudvan-vm-2-8-20200701 4.14.35-2025.400.8.el7uek.x86_64 #2 SMP Wed Aug 26 12:22:05 PDT 2020 x86_64 x86_64 x86_64 GNU/Linux
#------------------------------------------------------------------------------
  my $subr_name = get_my_name ();

  my $target_cmd;
  my $hostname_current;
  my $error_code;
  my $ignore_output; 
#------------------------------------------------------------------------------
# Test once if the command succeeds.  This avoids we need to check every 
# specific # command below.
#------------------------------------------------------------------------------
  $target_cmd    = $g_mapped_cmds{uname};
  ($error_code, $ignore_output) = execute_system_cmd ($target_cmd);
   
  if ($error_code != 0)
#-------------------------------------------------------------------------------
# This is unlikely to happen, but you never know.
#-------------------------------------------------------------------------------
    {
      gp_message ("abort", $subr_name, "failure to execute the uname command");
    }
  
  my $kernel_name       = qx ($target_cmd -s); chomp ($kernel_name);
  my $nodename          = qx ($target_cmd -n); chomp ($nodename);
  my $kernel_release    = qx ($target_cmd -r); chomp ($kernel_release);
  my $kernel_version    = qx ($target_cmd -v); chomp ($kernel_version);
  my $machine           = qx ($target_cmd -m); chomp ($machine);
  my $processor         = qx ($target_cmd -p); chomp ($processor);
  my $hardware_platform = qx ($target_cmd -i); chomp ($hardware_platform);
  my $operating_system  = qx ($target_cmd -o); chomp ($operating_system);
  
  $local_system_config{"kernel_name"}       = $kernel_name;
  $local_system_config{"nodename"}          = $nodename;
  $local_system_config{"kernel_release"}    = $kernel_release;
  $local_system_config{"kernel_version"}    = $kernel_version;
  $local_system_config{"machine"}           = $machine;
  $local_system_config{"processor"}         = $processor;
  $local_system_config{"hardware_platform"} = $hardware_platform;
  $local_system_config{"operating_system"}  = $operating_system;
  
  gp_message ("debug", $subr_name, "the output from the $target_cmd command is split into the following variables:");
  gp_message ("debug", $subr_name, "kernel_name       = $kernel_name");
  gp_message ("debug", $subr_name, "nodename          = $nodename");
  gp_message ("debug", $subr_name, "kernel_release    = $kernel_release");
  gp_message ("debug", $subr_name, "kernel_version    = $kernel_version");
  gp_message ("debug", $subr_name, "machine           = $machine");
  gp_message ("debug", $subr_name, "processor         = $processor");
  gp_message ("debug", $subr_name, "hardware_platform = $hardware_platform");
  gp_message ("debug", $subr_name, "operating_system  = $operating_system");
  
#------------------------------------------------------------------------------
# Check if the system we are running on is supported.
#------------------------------------------------------------------------------
  my $is_supported = ${ check_support_for_processor (\$machine) };

  if (not $is_supported)
    {
      gp_message ("error", $subr_name, "$machine is not supported");
      exit (0);
    }
#------------------------------------------------------------------------------
# The current hostname is used to compare against the hostname(s) found in the
# experiment directories.
#------------------------------------------------------------------------------
  $target_cmd       = $g_mapped_cmds{hostname};
  $hostname_current = qx ($target_cmd); chomp ($hostname_current);
  $error_code       = ${^CHILD_ERROR_NATIVE};
   
  if ($error_code == 0)
    {
      $local_system_config{"hostname_current"} = $hostname_current;
    }
  else
#-------------------------------------------------------------------------------
# This is unlikely to happen, but you never know.
#-------------------------------------------------------------------------------
    {
      gp_message ("abort", $subr_name, "failure to execute the hostname command");
    }
  for my $key (sort keys %local_system_config)
    {
      gp_message ("debug", $subr_name, "local_system_config{$key} = $local_system_config{$key}");
    }

  return (0);

} #-- End of subroutine get_system_config_info

#-------------------------------------------------------------------------------
# This subroutine prints a message.  Several types of messages are supported.
# In case the type is "abort", or "error", execution is terminated.  
#
# Note that "debug", "warning", and "error" mode, the name of the calling 
# subroutine is truncated to 30 characters.  In case the name is longer, 
# a warning message # is issued so you know this has happened.
#
# Note that we use lcfirst () and ucfirst () to enforce whether the first 
# character is printed in lower or uppercase.  It is nothing else than a
# convenience, but creates more consistency across messages.
#-------------------------------------------------------------------------------
sub gp_message
{
  my $subr_name = get_my_name ();

  my ($action, $caller_name, $comment_line) = @_;

#-------------------------------------------------------------------------------
# The debugXL identifier is special.  It is accepted, but otherwise ignored.
# This allows to (temporarily) disable debug print statements, but keep them
# around.
#-------------------------------------------------------------------------------
  my %supported_identifiers = (
    "verbose" => "[Verbose]",
    "debug"   => "[Debug]",
    "error"   => "[Error]",
    "warning" => "[Warning]",
    "abort"   => "[Abort]",
    "assertion" => "[Assertion error]",
    "diag"    => "",
  );

  my $debug_size; 
  my $identifier;
  my $fixed_size_name; 
  my $string_limit = 30;
  my $strlen = length ($caller_name);
  my $trigger_debug = $FALSE;
  my $truncated_name; 
  my $msg;

  if ($action =~ /debug\s*(.+)/)
    {
      if (defined ($1))
        {
          my $orig_value = $1;
          $debug_size = lc ($1);

          if ($debug_size =~ /^s$|^m$|^l$|^xl$/)
            {
              if ($g_debug_size{$debug_size})
                {
#-------------------------------------------------------------------------------
# All we need to know is whether a debug action is requested and whether the
# size has been enabled.  By setting $action to "debug", the code below is
# simplified.  Note that only using $trigger_debug below is actually sufficient.
#-------------------------------------------------------------------------------
                  $trigger_debug = $TRUE;
                }
            }
          else
            {
              die "$subr_name: debug size $orig_value is not supported";
            }
          $action = "debug";
        }
    }
  elsif ($action eq "debug")
    {
      $trigger_debug = $TRUE;
    }

#-------------------------------------------------------------------------------
# Catch any non-supported identifier.
#-------------------------------------------------------------------------------
  if (defined ($supported_identifiers{$action}))
    {
      $identifier = $supported_identifiers{$action};
    }
  else
    {
      die ("$subr_name - input error: $action is not supported");
    }
  if (($action eq "debug") and ($g_user_settings{"debug"}{"current_value"} eq "off"))
    {
      $trigger_debug = $FALSE;
    }

#-------------------------------------------------------------------------------
# Unconditionally buffer all warning messages.  These are meant to be displayed
# separately. 
#-------------------------------------------------------------------------------
  if ($action eq "warning")
    {
      push (@g_warning_messages, ucfirst ($comment_line));
    }

#-------------------------------------------------------------------------------
# Quick return in several cases.  Note that "debug", "verbose", "warning", and 
# "diag" messages are suppressed in quiet mode, but "error", "abort" and
# "assertion" always pass.
#-------------------------------------------------------------------------------
  if ((
           ($action eq "verbose") and (not $g_verbose))
       or (($action eq "debug")   and (not $trigger_debug))
       or (($action eq "verbose") and ($g_quiet)) 
       or (($action eq "debug")   and ($g_quiet)) 
       or (($action eq "warning") and (not $g_warnings)) 
       or (($action eq "diag")    and ($g_quiet)))
    {
      return (0);
    }

#-------------------------------------------------------------------------------
# In diag mode, just print the input line and nothing else.
#-------------------------------------------------------------------------------
  if ((
          $action eq "debug") 
      or ($action eq "abort")
      or ($action eq "warning") 
      or ($action eq "assertion") 
      or ($action eq "error"))
    {
#-------------------------------------------------------------------------------
# Construct the string to be printed.  Include an identifier and the name of 
# the function. 
#-------------------------------------------------------------------------------
      if ($strlen > $string_limit)
        {
          $truncated_name  = substr ($caller_name, 0, $string_limit);
          $fixed_size_name = sprintf ("%-"."$string_limit"."s", $truncated_name);
          print "Warning in $subr_name - the name of the caller is: $caller_name\n";
          print "Warning in $subr_name - the string length is $strlen and exceeds $string_limit\n";
        }
      else
        {
          $fixed_size_name = sprintf ("%-"."$string_limit"."s", $caller_name);
        }

      if (($action eq "error") or ($action eq "abort")) 
#-------------------------------------------------------------------------------
# Enforce that the message starts with a lowercase symbol.  Since these are
# user errors, the name of the routine is not shown.  The same for "abort".
# If you want to display the routine name too, use an assertion.
#-------------------------------------------------------------------------------
        {
          printf ("%-9s %s\n", $identifier, lcfirst ($comment_line));
        }
      elsif ($action eq "assertion")
#-------------------------------------------------------------------------------
# Enforce that the message starts with a lowercase symbol.
#-------------------------------------------------------------------------------
        {
          printf ("%-9s %-30s - %s\n", $identifier, $fixed_size_name, $comment_line);
        }
      elsif (($action eq "debug") and ($trigger_debug))
#-------------------------------------------------------------------------------
# Debug messages are printed "as is".  Avoids issues when searching for them ;-)
#-------------------------------------------------------------------------------
        {
          printf ("%-9s %-30s - %s\n", $identifier, $fixed_size_name, $comment_line);
        }
      else
#-------------------------------------------------------------------------------
# Enforce that the message starts with a lowercase symbol.
#-------------------------------------------------------------------------------
        {
          printf ("%-9s %-30s - %s\n", $identifier, $fixed_size_name, lcfirst ($comment_line));
        }
    }
  elsif ($action eq "verbose")
#-------------------------------------------------------------------------------
# The first character in the verbose message is capatilized.
#-------------------------------------------------------------------------------
    {
      printf ("%s\n", ucfirst ($comment_line));
    }
  elsif ($action eq "diag")
#-------------------------------------------------------------------------------
# The diag messages are meant to be diagnostics.  Only the comment line is
# printed.
#-------------------------------------------------------------------------------
    {
      printf ("%s\n", $comment_line);
      return (0);
    }

#-------------------------------------------------------------------------------
# Terminate execution in case the identifier is "abort".
#-------------------------------------------------------------------------------
  if (($action eq "abort") or ($action eq "assertion"))
    {
##      print "ABORT temporarily disabled for testing purposes\n";
      exit (-1);
    }
  else
    {
      return (0);
    }
   
} #-- End of subroutine gp_message

#------------------------------------------------------------------------------
# Dynamically load the modules needed.  Returns a list with the modules that
# could not be loaded.
#------------------------------------------------------------------------------
sub handle_module_availability
{
  my $subr_name = get_my_name ();

  gp_message ("verbose", $subr_name, "Handling module requirements");

#------------------------------------------------------------------------------
# This is clunky at best, but there is a chicken egg problem here.  For the
# man page to be generated, the --help and --version options need to work,
# but this part of the code only works if the "stat" function is available.
# The "feature qw (state)" is required for the code to compile.
#
# TBD: Consider using global variables and to decouple parts of the option
# handling.
#;
##  my @modules_used = ("feature", 
##                     "File::stat", 
#------------------------------------------------------------------------------
  my @modules_used = (
                      "List::Util", 
                      "Cwd", 
                      "File::Basename", 
                      "File::stat", 
                      "POSIX", 
                      "bigint", 
                      "bignum");

  my @missing_modules = ();
  my $cmd;
  my $result;
  
#------------------------------------------------------------------------------
# This loop checks for the availability of the modules and if so, imports 
# the module.
#
# The names of missing modules, if any, are stored and printed in the error
# handling section below.
#------------------------------------------------------------------------------
  for my $i (0 .. $#modules_used)
    {
      my $m = $modules_used[$i];
      if (eval "require $m;")
        {
          if ($m eq "feature")
            {
              $cmd = $m . "->import ( qw (state))";
            }
          elsif ($m eq "List::Util")
            {
              $cmd = $m . "->import ( qw (min max))";
            }
          elsif ($m eq "bigint")
            {
              $cmd = $m . "->import ( qw (hex))";
            }
          else
            {
              $cmd = $m . "->import";
            }
          $cmd .= ";";
          $result = eval ("$cmd");
          gp_message ("debugM", $subr_name, "cmd = $cmd");
        }
      else
        {
          push (@missing_modules, $m);
        }
    }

#------------------------------------------------------------------------------
# Count the number of missing modules.  It is upon the caller to decide what 
# to do in case of errors.  Currently, execution is aborted.
#------------------------------------------------------------------------------
  my $errors = scalar (@missing_modules);

  return (\$errors, \@missing_modules);

} #-- End of subroutine handle_module_availability

#------------------------------------------------------------------------------
# Generate the HTML with the experiment summary.
#------------------------------------------------------------------------------
sub html_generate_exp_summary
{
  my $subr_name = get_my_name ();

  my ($outputdir_ref, $experiment_data_ref) = @_;

  my $outputdir       = ${ $outputdir_ref };
  my @experiment_data = @{ $experiment_data_ref };
  my $file_title;
  my $outfile;
  my $page_title;
  my $size_text; 
  my $position_text;
  my $html_header;
  my $html_home;
  my $html_title_header;
  my $html_acknowledgement;
  my $html_end;
  my @html_exp_table_data = ();
  my $html_exp_table_data_ref;
  my @table_execution_stats = ();
  my $table_execution_stats_ref;

  gp_message ("debug", $subr_name, "outputdir = $outputdir");
  $outputdir = append_forward_slash ($outputdir);
  gp_message ("debug", $subr_name, "outputdir = $outputdir");

  $file_title = "Experiment information";
  $page_title = "Experiment Information";
  $size_text = "h2";
  $position_text = "center";
  $html_header = ${ create_html_header (\$file_title) };
  $html_home   = ${ generate_home_link ("right") };

  $html_title_header = ${ generate_a_header (\$page_title, \$size_text, \$position_text) };

  $outfile = $outputdir . $g_html_base_file_name{"experiment_info"} . ".html";
  open (EXP_INFO, ">", $outfile)
    or die ("unable to open $outfile for writing - '$!'");
  gp_message ("debug", $subr_name, "opened file $outfile for writing");

  print EXP_INFO $html_header;
  print EXP_INFO $html_home;
  print EXP_INFO $html_title_header;

  ($html_exp_table_data_ref, $table_execution_stats_ref) = html_generate_table_data ($experiment_data_ref);

  @html_exp_table_data   = @{ $html_exp_table_data_ref };
  @table_execution_stats = @{ $table_execution_stats_ref };

  print EXP_INFO "$_" for @html_exp_table_data;
;
##  print EXP_INFO "<pre>\n";
##  print EXP_INFO "$_\n" for @html_caller_callee;
##  print EXP_INFO "</pre>\n";

#-------------------------------------------------------------------------------
# Get the acknowledgement, return to main link, and final html statements.
#-------------------------------------------------------------------------------
  $html_home            = ${ generate_home_link ("left") };
  $html_acknowledgement = ${ create_html_credits () };
  $html_end             = ${ terminate_html_document () };

  print EXP_INFO $html_home;
  print EXP_INFO "<br>\n";
  print EXP_INFO $html_acknowledgement;
  print EXP_INFO $html_end;

  close (EXP_INFO);

  return (\@table_execution_stats);

} #-- End of subroutine html_generate_exp_summary

#-------------------------------------------------------------------------------
# Generate the entries for the tables with the experiment info.
#-------------------------------------------------------------------------------
sub html_generate_table_data
{
  my $subr_name = get_my_name ();

  my ($experiment_data_ref) = @_;

  my @experiment_data     = ();
  my @html_exp_table_data = ();
  my $html_line;
##  my $html_header_line;
  my $entry_name; 
  my $key;
  my $size_text; 
  my $position_text;
  my $title_table_1; 
  my $title_table_2; 
  my $title_table_3; 
  my $title_table_summary; 
  my $html_table_title; 

  my @experiment_table_1_def = ();
  my @experiment_table_2_def = ();
  my @experiment_table_3_def = ();
  my @exp_table_summary_def = ();
  my @experiment_table_1 = ();
  my @experiment_table_2 = ();
  my @experiment_table_3 = ();
  my @exp_table_summary = ();
  my @exp_table_selection = ();

  @experiment_data = @{ $experiment_data_ref };

  for my $i (sort keys @experiment_data)
    {
      for my $fields (sort keys %{ $experiment_data[$i] })
        {
          gp_message ("debugXL", $subr_name, "$i => experiment_data[$i]{$fields} = $experiment_data[$i]{$fields}");
        }
    }

  $title_table_1 = "Target System Configuration";
  $title_table_2 = "Experiment Statistics";
  $title_table_3 = "Run Time Statistics";
  $title_table_summary = "Main Statistics";

  $size_text     = "h3"; 
  $position_text = "left";

  push @experiment_table_1_def, { name => "Experiment name" , key => "exp_name_short"}; 
  push @experiment_table_1_def, { name => "Hostname"        , key => "hostname"}; 
  push @experiment_table_1_def, { name => "Operating system", key => "OS"}; 
  push @experiment_table_1_def, { name => "Architecture",     key => "architecture"}; 
  push @experiment_table_1_def, { name => "Page size",        key => "page_size"}; 
  
  push @experiment_table_2_def, { name => "Target command"          , key => "target_cmd"}; 
  push @experiment_table_2_def, { name => "Date command executed"   , key => "start_date"}; 
  push @experiment_table_2_def, { name => "Data collection duration", key => "data_collection_duration"}; 
  push @experiment_table_2_def, { name => "End time of the experiment", key => "end_experiment"}; 

  push @experiment_table_3_def, { name => "User CPU time (seconds)", key => "user_cpu_time"}; 
##  push @experiment_table_3_def, { name => "User CPU time (percentage)", key => "user_cpu_percentage"}; 
  push @experiment_table_3_def, { name => "System CPU time (seconds)", key => "system_cpu_time"}; 
##  push @experiment_table_3_def, { name => "System CPU time (percentage)", key => "system_cpu_percentage"}; 
  push @experiment_table_3_def, { name => "Sleep time (seconds)", key => "sleep_time"}; 
##  push @experiment_table_3_def, { name => "Sleep time (percentage)", key => "sleep_percentage"}; 

  push @exp_table_summary_def, { name => "Experiment name" , key => "exp_name_short"}; 
  push @exp_table_summary_def, { name => "Hostname"        , key => "hostname"}; 
  push @exp_table_summary_def, { name => "User CPU time (seconds)", key => "user_cpu_time"}; 
  push @exp_table_summary_def, { name => "System CPU time (seconds)", key => "system_cpu_time"}; 
  push @exp_table_summary_def, { name => "Sleep time (seconds)", key => "sleep_time"}; 

  $html_table_title = ${ generate_a_header (\$title_table_1, \$size_text, \$position_text) };

  push (@html_exp_table_data, $html_table_title);

  @experiment_table_1 = @{ create_table (\@experiment_data, \@experiment_table_1_def) };

  push (@html_exp_table_data, @experiment_table_1);

  $html_table_title = ${ generate_a_header (\$title_table_2, \$size_text, \$position_text) };

  push (@html_exp_table_data, $html_table_title);

  @experiment_table_2 = @{ create_table (\@experiment_data, \@experiment_table_2_def) };

  push (@html_exp_table_data, @experiment_table_2);

  $html_table_title = ${ generate_a_header (\$title_table_3, \$size_text, \$position_text) };

  push (@html_exp_table_data, $html_table_title);

  @experiment_table_3 = @{ create_table (\@experiment_data, \@experiment_table_3_def) };

  push (@html_exp_table_data, @experiment_table_3);

  $html_table_title = ${ generate_a_header (\$title_table_summary, \$size_text, \$position_text) };

  push (@exp_table_summary, $html_table_title);

  @exp_table_selection = @{ create_table (\@experiment_data, \@exp_table_summary_def) };

  push (@exp_table_summary, @exp_table_selection);

  return (\@html_exp_table_data, \@exp_table_summary);

} #-- End of subroutine html_generate_table_data

#------------------------------------------------------------------------------
# Generate the HTML text to print in case a file is empty.
#------------------------------------------------------------------------------
sub html_text_empty_file
{
  my $subr_name = get_my_name ();

  my ($comment_ref, $error_file_ref) = @_;

  my $comment; 
  my $error_file; 
  my $error_message; 
  my $file_title; 
  my $html_end;
  my $html_header;
  my $html_home; 

  my @html_empty_file = ();

  $comment     = ${ $comment_ref };
  $error_file  = ${ $error_file_ref };

  $file_title  = "File is empty";
  $html_header = ${ create_html_header (\$file_title) };
  $html_end    = ${ terminate_html_document () };
  $html_home   = ${ generate_home_link ("left") };

  push (@html_empty_file, $html_header);

  $error_message = "<b>" . $comment . "</b>";
  $error_message = set_background_color_string ($error_message, $g_html_color_scheme{"error_message"});
  push (@html_empty_file, $error_message);

  if (not is_file_empty ($error_file))
    {
      $error_message = "<p><em>Check file $error_file for more information</em></p>";
    }
  push (@html_empty_file, $error_message);
  push (@html_empty_file, $html_home);
  push (@html_empty_file, "<br>");
  push (@html_empty_file, $g_html_credits_line);
  push (@html_empty_file, $html_end);

  return (\@html_empty_file);

} #-- End of subroutine html_text_empty_file

#------------------------------------------------------------------------------
# This subroutine checks if a file is empty and returns $TRUE or $FALSE.
#------------------------------------------------------------------------------
sub is_file_empty
{
  my $subr_name = get_my_name ();

  my ($filename) = @_;

  my $size;
  my $file_stat;
  my $is_empty;

  chomp ($filename);

  if (not -e $filename)
    {
#------------------------------------------------------------------------------
# The return value is used in the caller.  This is why we return the empty
# string in case the file does not exist.
#------------------------------------------------------------------------------
      gp_message ("debug", $subr_name, "filename = $filename not found");
      $is_empty = $TRUE;
    }
  else
    {
      $file_stat = stat ($filename);
      $size      = $file_stat->size;
      $is_empty  = ($size == 0) ? $TRUE : $FALSE;
    }

  gp_message ("debug", $subr_name, "filename = $filename size = $size is_empty = $is_empty");

  return ($is_empty);

} #-- End of subroutine is_file_empty

#------------------------------------------------------------------------------
# Check if a file is executable and return $TRUE or $FALSE.
#------------------------------------------------------------------------------
sub is_file_executable
{
  my $subr_name = get_my_name ();

  my ($filename) = @_;

  my $file_permissions;
  my $index_offset;
  my $is_executable;
  my $mode;
  my $number_of_bytes; 
  my @permission_settings = ();
  my %permission_values = ();

  chomp ($filename);

  gp_message ("debug", $subr_name, "check if filename = $filename is executable");

  if (not -e $filename)
    {
#------------------------------------------------------------------------------
# The return value is used in the caller.  This is why we return the empty
# string in case the file does not exist.
#------------------------------------------------------------------------------
      gp_message ("debug", $subr_name, "filename = $filename not found");
      $is_executable = $FALSE;
    }
  else
    {
      $mode = stat ($filename)->mode;

      gp_message ("debugXL", $subr_name, "mode = $mode");
#------------------------------------------------------------------------------
# Get username.  We currently do not do anything with this though and the
# code is commented out.
#
#      my $my_name = getlogin () || getpwuid($<) || "Kilroy";;
#      gp_message ("debug", $subr_name, "my_name = $my_name");
#------------------------------------------------------------------------------

#------------------------------------------------------------------------------
# Convert file permissions to octal, split the individual numbers and store
# the values for the respective users.
#------------------------------------------------------------------------------
      $file_permissions = sprintf("%o", $mode & 07777);

      @permission_settings = split (//, $file_permissions);

      $number_of_bytes = scalar (@permission_settings);

      gp_message ("debugXL", $subr_name, "file_permissions = $file_permissions");
      gp_message ("debugXL", $subr_name, "permission_settings = @permission_settings");
      gp_message ("debugXL", $subr_name, "number_of_settings = $number_of_bytes");

      if ($number_of_bytes == 4)
        {
          $index_offset = 1;
        }
      elsif ($number_of_bytes == 3)
        {
          $index_offset = 0;
        }
      else
        {
          my $msg = "unexpected number of $number_of_bytes bytes " .
                    "in permission settings: @permission_settings";
          gp_message ("assertion", $subr_name, $msg);
        }

      $permission_values{user}  = $permission_settings[$index_offset++];
      $permission_values{group} = $permission_settings[$index_offset++];
      $permission_values{other} = $permission_settings[$index_offset];

#------------------------------------------------------------------------------
# The executable bit should be set for user, group and other.  If this fails
# we mark the file as not executable.  Note that this is gprofng specific.
#------------------------------------------------------------------------------
      $is_executable = $TRUE;
      for my $k (keys %permission_values)
        {
          my $msg = "permission_values{" . $k . "} = " .
                    $permission_values{$k};
          gp_message ("debugXL", $subr_name, $msg);
    
          if ($permission_values{$k} % 2 == 0)
            {
              $is_executable = $FALSE;
              last;
            }
        }
    }

  gp_message ("debug", $subr_name, "is_executable = $is_executable");

  return ($is_executable);

} #-- End of subroutine is_file_executable

#-------------------------------------------------------------------------------
# TBD.
#-------------------------------------------------------------------------------
sub name_regex
{
  my $subr_name = get_my_name ();

  my ($metric_description_ref, $metrics, $field, $file) = @_;

  my %metric_description = %{ $metric_description_ref };

  my @splitted_metrics;
  my $splitted_metrics;
  my $m;
  my $mf;
  my $nf;
  my $re;
  my $Xre;
  my $noPCfile;
  my @reported_metrics;
  my $reported_metrics;
  my $hdr_regex;
  my $hdr_href_regex;
  my $hdr_src_regex;
  my $new_metrics;
  my $pre;
  my $post;
  my $rat;
  my @moo = ();

  my $gp_metrics_file;
  my $gp_metrics_dir;
  my $suffix_not_used;

  my $is_calls    = $FALSE;
  my $is_calltree = $FALSE;

  gp_message ("debugXL", $subr_name,"1:metrics->$metrics<- field->$field<- file->$file<-");

#-------------------------------------------------------------------------------
# According to https://perldoc.perl.org/File::Basename, both dirname and 
# basename are not reliable and fileparse () is recommended instead.
#
# Note that $gp_metrics_dir has a trailing "/".
#-------------------------------------------------------------------------------
  ($gp_metrics_file, $gp_metrics_dir, $suffix_not_used) = fileparse ($file, ".sort.func-PC");

  gp_message ("debugXL", $subr_name, "gp_metrics_dir = $gp_metrics_dir gp_metrics_file = $gp_metrics_file");
  gp_message ("debugXL", $subr_name, "suffix_not_used = $suffix_not_used");

  if ($gp_metrics_file eq "calls")
    {
      $is_calls = $TRUE;
    }
  if ($gp_metrics_file eq "calltree")
    {
      $is_calltree = $TRUE;
    }

  $gp_metrics_file = "gp-metrics-" . $gp_metrics_file . "-PC";
  $gp_metrics_file = $gp_metrics_dir . $gp_metrics_file;

  gp_message ("debugXL", $subr_name, "gp_metrics_file is $gp_metrics_file");

  open (GP_METRICS, "<", $gp_metrics_file)
    or die ("$subr_name - unable to open gp_metrics file $gp_metrics_file for reading - '$!'");
  gp_message ("debug", $subr_name, "opened file $gp_metrics_file for reading");

  $new_metrics = $metrics;

  while (<GP_METRICS>)
    {
      $rat = $_;
      chomp ($rat);
      gp_message ("debugXL", $subr_name, "rat = $rat - new_metrics = $new_metrics");
#-------------------------------------------------------------------------------
# Capture the string after "Current metrics:" and if it ends with ":name",
# remove it.
#-------------------------------------------------------------------------------
      if ($rat =~ /^\s*Current metrics:\s*(.*)$/)
        {
          $new_metrics = $1;
          if ($new_metrics =~ /^(.*):name$/)
            {
              $new_metrics = $1;
            }
          last;
        }
    }
  close (GP_METRICS);

  if ($is_calls or $is_calltree)
    {
#-------------------------------------------------------------------------------
# Remove any inclusive metrics from the list.
#-------------------------------------------------------------------------------
      while ($new_metrics =~ /(.*)(i\.[^:]+)(.*)$/)
        {
          $pre  = $1;
          $post = $3;
          gp_message ("debugXL", $subr_name, "1b: new_metrics = $new_metrics pre = $pre post = $post");
          if (substr ($post,0,1) eq ":")
            {
              $post = substr ($post,1);
            }
          $new_metrics = $pre.$post;
        }
    }

  $metrics = $new_metrics;

  gp_message ("debugXL", $subr_name, "2:metrics->$metrics<- field->$field<- file->$file<-");

#-------------------------------------------------------------------------------
# Find the line starting with "address:" and strip this part away.
#-------------------------------------------------------------------------------
  if ($metrics =~ /^address:(.*)/)
    {
      $reported_metrics = $1;
#-------------------------------------------------------------------------------
# Focus on the filename ending with "-PC".  When found, strip this part away.
#-------------------------------------------------------------------------------
      if ($file =~ /^(.*)-PC$/)
        {
          $noPCfile = $1;
          if ($noPCfile =~ /^(.*)functions.sort.func$/)
            {
              $noPCfile = $1."functions.func";
            }
          push (@moo, "$reported_metrics\n");
        }
    }

#-------------------------------------------------------------------------------
# Split the list into an array with the individual metrics.
#
# TBD: This should be done only once!
#-------------------------------------------------------------------------------
  @reported_metrics = split (":", $reported_metrics);
  for my $i (@reported_metrics)
    {
      gp_message ("debugXL", $subr_name, "reported_metrics = $i");
    }

  $hdr_regex      = "^\\s*";
  $hdr_href_regex = "^\\s*";
  $hdr_src_regex  = "^(\\s+|<i>\\s+)";

  for my $m (@reported_metrics)
    {

      my $description = ${ retrieve_metric_description (\$m, \%metric_description) };
      gp_message ("debugXL", $subr_name, "m = $m description = $description");
      if (substr ($m,0,1) eq "e")
        {
          push (@moo,"$m:$description\n");
          $hdr_regex .= "(Excl\\.\.*)";
          $hdr_href_regex .= "(<a.*>)(Excl\\.)(<\/a>)([^<]+)";
          $hdr_src_regex .= "(Excl\\.\.*)";
          next;
        }
      if (substr ($m,0,1) eq "i")
        {
          push (@moo,"$m:$description\n");
          $hdr_regex .= "(Incl\\.\.*)";
          $hdr_href_regex .= "(<a.*>)(Incl\\.)(<\/a>)([^<]+)";
          $hdr_src_regex .= "(Incl\\.\.*)";
          next;
        }
      if (substr ($m,0,1) eq "a")
        {
          my $a;
          my $am;
          $a = $m; 
          $a =~ s/^a/e/; 
          $am = ${ retrieve_metric_description (\$a, \%metric_description) };
          $am =~ s/Exclusive/Attributed/;
          push (@moo,"$m:$am\n");
          $hdr_regex .= "(Attr\\.\.*)";
          $hdr_href_regex .= "(<a.*>)(Attr\\.)(<\/a>)([^<]+)";
          $hdr_src_regex .= "(Attr\\.\.*)";next;
        }
    }

  $hdr_regex      .= "(Name\.*)";
  $hdr_href_regex .= "(Name\.*)";

  @splitted_metrics = split (":","$metrics");
  $nf               = scalar (@splitted_metrics);
  gp_message ("debug", $subr_name,"number of fields in $metrics -> $nf");

  open (ZMETRICS, ">", "$noPCfile.metrics")
    or die ("Not able to open file $noPCfile.metrics for writing - '$!'");
  gp_message ("debug", $subr_name, "$noPCfile - opened file $noPCfile.metrics for writing");

  print ZMETRICS @moo;
  close (ZMETRICS);

  gp_message ("debug", $subr_name, "wrote file $noPCfile.metrics");

  open (XREGEXP, ">", "$noPCfile.c.regex")
    or die ("Not able to open file $noPCfile.c.regex for writing - '$!'");
  gp_message ("debug", $subr_name, "$noPCfile - opened file $noPCfile.c.regex for writing");

  print XREGEXP "\# Number of metric fields\n";
  print XREGEXP "$nf\n";
  print XREGEXP "\# Header regex\n";
  print XREGEXP "$hdr_regex\n";
  print XREGEXP "\# href Header regex\n";
  print XREGEXP "$hdr_href_regex\n";
  print XREGEXP "\# src Header regex\n";
  print XREGEXP "$hdr_src_regex\n";

  $mf = 1;
#---------------------------------------------------------------------------
# Find the index of "field" in the metric list, plus one.
#---------------------------------------------------------------------------
  if ( ($field eq "functions") or ($field eq "calls") or ($field eq "calltree"))
    {
      $mf = $nf + 1;
    } 
  else
    {
      for my $candidate_metric (@splitted_metrics)
        {
          gp_message ("debugXL", $subr_name, "field = $field candidate_metric = $candidate_metric and mf = $mf");
          if ($candidate_metric eq $field)
            {
              last;
            }
          $mf++;
        }
    }
  gp_message ("debugXL", $subr_name, "Final value mf = $mf");

  if ($mf == 1)
    {
      $re = "^\\s*(\\S+)"; # metric value
    } 
  else 
    {
      $re = "^\\s*\\S+";
    }
  $Xre = "^\\s*(\\S+)";

  $m = 2;
  while (--$nf)
    {
      if ($nf)
        {
          if ($m == $mf)
            {
              $re .= "\\s+(\\S+)"; # metric value
            } 
          else 
            {
              $re .= "\\s+\\S+";
            }
          if ($nf != 1)
            {
              $Xre .= "\\s+(\\S+)";
            }
          $m++;
        }
    }

  if ($field eq "calltree")
    {
      $re .= "\\s+.*\\+-(.*)"; # name
      $Xre .= "\\s+.*\\+-(.*)\$"; # name (Right?)
    } 
  else 
    {
      $re .= "\\s+(.*)"; # name
      $Xre .= "\\s+(.*)\$"; # name
    }

  print XREGEXP "\# Metrics and Name regex\n";
  print XREGEXP "$Xre\n";
  close (XREGEXP);

  gp_message ("debug", $subr_name, "wrote file $noPCfile.c.regex");
  gp_message ("debugXL", $subr_name, "on return Xre = $Xre");
  gp_message ("debugXL", $subr_name, "on return re  = $re");

  return ($re);

} #-- End of subroutine name_regex

#-------------------------------------------------------------------------------
# TBD
#-------------------------------------------------------------------------------
sub nosrc
{
  my $subr_name = get_my_name ();

  my ($input_string) = @_;

  my $directory_name = append_forward_slash ($input_string);
  my $LANG           = $g_locale_settings{"LANG"};
  my $result_file    = $directory_name."no_source.html";

  gp_message ("debug", $subr_name, "result_file = $result_file");

  open (NS, ">", $result_file)
    or die ("$subr_name: cannot open file $result_file for writing - '$!'");

  print NS "<!doctype html public \"-//w3c//dtd html 3.2//en\">\n<html lang=\"$LANG\">\n<head>\n".
           "<meta http-equiv=\"content-type\" content=\"text/html; charset=iso-8859-1\">\n" .
           "<title>No source</title></head><body lang=\"$LANG\" bgcolor=".$g_html_color_scheme{"background_color_page"}."><pre>\n";
  print NS "<a name=\"line1\"></a><font color=#C80707>"."No source was found"."</font>\n"; # red font
  print NS "</pre>\n<pre>Output generated by $version_info</pre>\n";
  print NS "</body></html>\n";

  close (NS);

  return (0);

} #-- End of subroutine nosrc

#------------------------------------------------------------------------------
# TBD.
#------------------------------------------------------------------------------
sub numerically 
{
  my $f1;
  my $f2;

  if ($a =~ /^([^\d]*)(\d+)/)
    {
      $f1 = int ($2);
      if ($b=~ /^([^\d]*)(\d+)/)
        {
          $f2 = int ($2);
          $f1 == $f2 ? 0 : ($f1 < $f2 ? -1 : +1);
        }
    } 
  else 
    {
      return ($a <=> $b);
    }
} #-- End of subroutine numerically

#------------------------------------------------------------------------------
# Parse the user options. Also perform a basic check.  More checks and also
# some specific to the option will be performed after this subroutine.
#------------------------------------------------------------------------------
sub parse_and_check_user_options
{
  my $subr_name = get_my_name ();

  my ($no_of_args_ref, $option_list_ref) = @_;

  my $no_of_args  = ${ $no_of_args_ref };
  my @option_list = @{ $option_list_ref };

  my @exp_dir_list;

  my $arg;
  my $calltree_value; 
  my $debug_value; 
  my $default_metrics_value; 
  my $func_limit_value; 
  my $found_exp_dir = $FALSE;
  my $ignore_metrics_value; 
  my $ignore_value;
  my $message;
  my $outputdir_value;
  my $quiet_value; 
  my $hp_value;
  my $valid;
  my $verbose_value; 

  $no_of_args++;

  gp_message ("debug", $subr_name, "no_of_args  = $no_of_args");
  gp_message ("debug", $subr_name, "option_list = @option_list");

  my $option_errors = 0;

  while (defined ($arg = shift @ARGV))
    {
      gp_message ("debug", $subr_name, "parsing options arg = $arg");
      gp_message ("debug", $subr_name, "parsing options \@ARGV = @ARGV");

#------------------------------------------------------------------------------
# The gprofng driver adds this option.  We need to get rid of it.
#------------------------------------------------------------------------------
      next if ($arg eq "--whoami=gprofng display html");

#------------------------------------------------------------------------------
# Parse the input options and check for the values to be valid.
#
# Valid values are stored in the main option table.
#
# TBD: The early check handles some of these already and the duplicates
# can be removed.  Be aware of some global settings though.
#------------------------------------------------------------------------------
      if ($arg eq "--version")
        {
          print_version_info (); 
          exit (0);
        }
      elsif ($arg eq "--help")
        {
          $ignore_value = print_help_info ();
          exit (0);
        }
      elsif (($arg eq "-v") or ($arg eq "--verbose"))
        {
          $verbose_value = shift @ARGV; 
          $valid = check_user_option ("verbose", $verbose_value);
          if (not $valid)
            {
              $option_errors++;
            }
          else
            {
              $g_verbose = $g_user_settings{"verbose"}{"current_value"} eq "on" ? $TRUE : $FALSE;
            }
          next;
        }
      elsif (($arg eq "-w") or ($arg eq "--warnings"))
        {
          my $warnings_value = shift @ARGV; 
          $valid = check_user_option ("warnings", $warnings_value);
          if (not $valid)
            {
              $option_errors++;
            }
          else
            {
              $g_warnings = $g_user_settings{"warnings"}{"current_value"} eq "on" ? $TRUE : $FALSE;
            }
          next;
        }
      elsif (($arg eq "-d") or ($arg eq "--debug"))
        {
          $debug_value = shift @ARGV;
          $valid = check_user_option ("debug", $debug_value);
          if (not $valid)
            {
              $option_errors++;
            }
          else
            {
#------------------------------------------------------------------------------
# This function internally converts the value to uppercase. 
#------------------------------------------------------------------------------
              my $ignore_value = set_debug_size (\$debug_value);
            }
          next;
        }
      elsif (($arg eq "-q") or ($arg eq "--quiet"))
        {
          $quiet_value = shift @ARGV; 
          $valid = check_user_option ("quiet", $quiet_value);

          if (not $valid)
            {
              $option_errors++;
            }
          else
            {
              $g_quiet = $g_user_settings{"quiet"}{"current_value"} eq "on" ? $TRUE : $FALSE;
            }
          next;
        }
      elsif (($arg eq "-o") or ($arg eq "--output"))
        {
          $outputdir_value = shift @ARGV; 
          $valid = check_user_option ("output", $outputdir_value);

          if (not $valid)
            {
              $option_errors++;
            }

          next;
        }
      elsif (($arg eq "-O") or ($arg eq "--overwrite"))
        {
          $outputdir_value = shift @ARGV; 
          $valid = check_user_option ("overwrite", $outputdir_value);

          if (not $valid)
            {
              $option_errors++;
            }

          next; 
        }
      elsif (($arg eq "-hp") or ($arg eq "--highlight-percentage"))
        { 
          $hp_value     = shift @ARGV; 
          $valid = check_user_option ("highlight_percentage", $hp_value);

          if (not $valid)
            {
              $option_errors++;
            }

          next;
        }
# Temporarily disabled       elsif (($arg eq "-fl") or ($arg eq "--func-limit"))
# Temporarily disabled         {
# Temporarily disabled           $func_limit_value = shift @ARGV; 
# Temporarily disabled           $valid = check_user_option ("func_limit", $func_limit_value);
# Temporarily disabled 
# Temporarily disabled           if (not $valid)
# Temporarily disabled             {
# Temporarily disabled               $option_errors++;
# Temporarily disabled             }
# Temporarily disabled 
# Temporarily disabled           next;
# Temporarily disabled         }
# Temporarily disabled       elsif (($arg eq "-ct") or ($arg eq "--calltree"))
# Temporarily disabled         {
# Temporarily disabled           $calltree_value = shift @ARGV;
# Temporarily disabled           $valid = check_user_option ("calltree", $calltree_value);
# Temporarily disabled 
# Temporarily disabled           if (not $valid)
# Temporarily disabled             {
# Temporarily disabled               $option_errors++;
# Temporarily disabled             }
# Temporarily disabled 
# Temporarily disabled           next; 
# Temporarily disabled         }
# Temporarily disabled       elsif (($arg eq "-tp") or ($arg eq "--threshold-percentage"))
# Temporarily disabled         { 
# Temporarily disabled           $tp_value     = shift @ARGV; 
# Temporarily disabled           $valid = check_user_option ("threshold_percentage", $tp_value);
# Temporarily disabled 
# Temporarily disabled           if (not $valid)
# Temporarily disabled             {
# Temporarily disabled               $option_errors++;
# Temporarily disabled             }
# Temporarily disabled 
# Temporarily disabled           next;
# Temporarily disabled         }
# Temporarily disabled       elsif (($arg eq "-dm") or ($arg eq "--default-metrics"))
# Temporarily disabled         { 
# Temporarily disabled           $default_metrics_value = shift @ARGV;
# Temporarily disabled           $valid = check_user_option ("default_metrics", $default_metrics_value);
# Temporarily disabled 
# Temporarily disabled           if (not $valid)
# Temporarily disabled             {
# Temporarily disabled               $option_errors++;
# Temporarily disabled             }
# Temporarily disabled 
# Temporarily disabled           next;
# Temporarily disabled         }
# Temporarily disabled       elsif (($arg eq "-im") or ($arg eq "--ignore-metrics"))
# Temporarily disabled         { 
# Temporarily disabled           $ignore_metrics_value = shift @ARGV; 
# Temporarily disabled           $valid = check_user_option ("ignore_metrics", $ignore_metrics_value);
# Temporarily disabled 
# Temporarily disabled           if (not $valid)
# Temporarily disabled             {
# Temporarily disabled               $option_errors++;
# Temporarily disabled             }
# Temporarily disabled 
# Temporarily disabled           next;
# Temporarily disabled         }
      else
        {
  
#------------------------------------------------------------------------------
# When we get to this part of the code it means that the current command line 
# argument is not a known option.
#
# We check if it is the name of an experiment directory and if so, add it to 
# the list with directories to use.
#
# If not, print an error message and increment the error variable because this
# is clearly something that is not right.
#-------------------------------------------------------------------------------

          if ($arg =~ /^\-.*/)
            {
#-------------------------------------------------------------------------------
# It is an option, but not a supported one.  Print a message and increment
# the error count.
#-------------------------------------------------------------------------------
              $message = "option $arg is not a known option";
              push (@g_user_input_errors, $message);

              $option_errors++;
            }
          else
            {
#-------------------------------------------------------------------------------
# Other than options, the input has to consist of at least one directory name.  
# First remove any trailing slashes (/) and then check if the name is valid.
#-------------------------------------------------------------------------------
              $arg =~ s/\/*\/$//;
              if ($arg =~ /.+\.er$/)
                {
#-------------------------------------------------------------------------------
# It is the name of an experiment directory and is added to the list.
#-------------------------------------------------------------------------------
                  $found_exp_dir = $TRUE;
                  push (@exp_dir_list, $arg);
                }
              else
                {
#-------------------------------------------------------------------------------
# It is not a valid experiment directory name. Print a message and exit.
#-------------------------------------------------------------------------------
                  $message = "not a valid experiment directory name: $arg";
                  push (@g_user_input_errors, $message);

                  $option_errors++;
                }
            }

        } #-- End of last else

    } #-- End of while-loop

#-------------------------------------------------------------------------------
# Check if the name of the experiment directories is valid.  Note that later
# we check for these directories to exist.
#-------------------------------------------------------------------------------
  if (not $found_exp_dir) 
    {
      $message = "experiment directory name(s) are either not valid, or missing";
      push (@g_user_input_errors, $message);

      $option_errors++;
    }

#------------------------------------------------------------------------------
# Check for fatal errors to have occurred. If so, stop execution.  Otherwise,
# confirm the verbose setting.
#------------------------------------------------------------------------------
  if ($option_errors > 0)
    {
      gp_message ("debug", $subr_name, "a total of $option_errors input errors have been found");
    }
  else
    {
      gp_message ("debug", $subr_name, "no errors in the options found");
    }

  return ($option_errors, $found_exp_dir, \@exp_dir_list);

} #-- End of subroutine parse_and_check_user_options

#------------------------------------------------------------------------------
# Parse the generated .dis files
#------------------------------------------------------------------------------
sub parse_dis_files
{
  my $subr_name = get_my_name ();

  my ($number_of_metrics_ref, $function_info_ref, 
      $function_address_and_index_ref, $input_string_ref, 
      $addressobj_index_ref) = @_;

#------------------------------------------------------------------------------
# Note that $function_address_and_index_ref is not used, but we need to pass 
# in the address into generate_dis_html.
#------------------------------------------------------------------------------
  my $number_of_metrics = ${ $number_of_metrics_ref };
  my @function_info     = @{ $function_info_ref };
  my $input_string      = ${ $input_string_ref };
  my %addressobj_index  = %{ $addressobj_index_ref };

#------------------------------------------------------------------------------
# The regex section.
#------------------------------------------------------------------------------
  my $dis_filename_id_regex = 'file\.([0-9]+)\.dis';

  my $filename;
  my $outputdir = append_forward_slash ($input_string);

  my @source_line = ();
  my $source_line_ref; 

  my @metric = ();
  my $metric_ref;

  my $target_function;
 
  gp_message ("debug", $subr_name, "building disassembly files");
  gp_message ("debug", $subr_name, "outputdir = $outputdir");

  while (glob ($outputdir.'*.dis'))
    {
      gp_message ("debug", $subr_name, "processing disassembly file: $_");

      my $base_name = get_basename ($_);

      if ($base_name =~ /$dis_filename_id_regex/)
        {
          if (defined ($1))
            {
              gp_message ("debug", $subr_name, "processing disassembly file: $base_name $1");
              if (exists ($function_info[$1]{"routine"}))
                {
                  $target_function = $function_info[$1]{"routine"};
                  gp_message ("debug", $subr_name, "processing disassembly file: $base_name target_function = $target_function");
                }
              if (exists ($g_function_tag_id{$target_function}))
                {
                  gp_message ("debug", $subr_name, "target_function = $target_function ftag = $g_function_tag_id{$target_function}");
                }
              else
                {
                  my $msg = "no function tag found for $target_function";
                  gp_message ("assertion", $subr_name, $msg);
                }
            }
          else
            {
              gp_message ("debug", $subr_name, "processing disassembly file: $base_name unknown id");
            }
        }
        
      $filename = $_;
      gp_message ("verbose", $subr_name, "  Processing disassembly file $filename");
      ($source_line_ref, $metric_ref) = generate_dis_html (
                                          \$target_function,
                                          \$number_of_metrics, 
                                          $function_info_ref, 
                                          $function_address_and_index_ref, 
                                          \$outputdir, 
                                          \$filename, 
                                          \@source_line, 
                                          \@metric, 
                                          \%addressobj_index);

      @source_line = @{ $source_line_ref };
      @metric      = @{ $metric_ref };
    }
 
  return (0)

} #-- End of subroutine parse_dis_files

#------------------------------------------------------------------------------
# Parse the .src.txt files
#------------------------------------------------------------------------------
sub parse_source_files
{
  my $subr_name = get_my_name ();

  my ($number_of_metrics_ref, $function_info_ref, $outputdir_ref) = @_;

  my $number_of_metrics = ${ $number_of_metrics_ref };
  my $outputdir         = ${ $outputdir_ref };
  my $ignore_value;

  my $outputdir_with_slash = append_forward_slash ($outputdir);

  gp_message ("verbose", $subr_name, "building source files");

  while (glob ($outputdir_with_slash.'*.src.txt'))
    {
      gp_message ("verbose", $subr_name, "  Processing source file: $_");
      gp_message ("debug", $subr_name, "processing source file: $_");

      my $found_target = process_source (
                           $number_of_metrics, 
                           $function_info_ref, 
                           $outputdir_with_slash, 
                           $_);

      if (not $found_target)
        {
          gp_message ("debug", $subr_name, "target function not found");
        }
    }

} #-- End of subroutine parse_source_files

#------------------------------------------------------------------------------
# Routine to prepend \\ to selected symbols.
#------------------------------------------------------------------------------
sub prepend_backslashes
{
  my $subr_name = get_my_name ();

  my ($target_string) = @_;

  gp_message ("debug", $subr_name, "target_string on entry  = $target_string");

  $target_string =~ s/\(/\\\(/g; 
  $target_string =~ s/\)/\\\)/g; 
  $target_string =~ s/\+/\\\+/g; 
  $target_string =~ s/\[/\\\[/g; 
  $target_string =~ s/\]/\\\]/g; 
  $target_string =~ s/\*/\\\*/g; 
  $target_string =~ s/\./\\\./g; 
  $target_string =~ s/\$/\\\$/g; 
  $target_string =~ s/\^/\\\^/g; 
  $target_string =~ s/\#/\\\#/g; 

  gp_message ("debug", $subr_name, "target_string on return = $target_string");

  return ($target_string);

} #-- End of subroutine prepend_backslashes

#------------------------------------------------------------------------------
# TBD
#------------------------------------------------------------------------------
sub preprocess_function_files
{
  my $subr_name = get_my_name ();

  my ($metric_description_ref, $script_pc_metrics, $input_string, $sort_fields_ref) = @_;

  my $outputdir   = append_forward_slash ($input_string);
  my @sort_fields = @{ $sort_fields_ref };
  
  my $error_code; 
  my $cmd_output;
  my $re;

# TBD  $outputdir .= "/";

  gp_message ("debug", $subr_name, "enter subroutine");

  my %metric_description = %{ $metric_description_ref };

  for my $m (keys %metric_description)
    {
      gp_message ("debug", $subr_name, "metric_description{$m} = $metric_description{$m}");
    }

  $re = name_regex ($metric_description_ref, $script_pc_metrics, "functions", $outputdir."functions.sort.func-PC");
  ($error_code, $cmd_output) = execute_system_cmd ("echo '$re' > $outputdir"."functions.sort.func-PC.name-regex");
  if ($error_code != 0 )
    {
      gp_message ("abort", $subr_name, "execution terminated");
    }

  for my $field (@sort_fields)
    {
      $re = name_regex ($metric_description_ref, $script_pc_metrics, $field, $outputdir."$field.sort.func-PC");
      ($error_code, $cmd_output) = execute_system_cmd ("echo '$re' > $outputdir"."$field.sort.func-PC.name-regex");
      if ($error_code != 0 )
        {
          gp_message ("abort", $subr_name, "execution terminated");
        }
    }

  $re = name_regex ($metric_description_ref, $script_pc_metrics, "calls", $outputdir."calls.sort.func-PC");
  ($error_code, $cmd_output) = execute_system_cmd ("echo '$re' > $outputdir"."calls.sort.func-PC.name-regex");
  if ($error_code != 0 )
    {
      gp_message ("abort", $subr_name, "execution terminated");
    }

  if ($g_user_settings{"calltree"}{"current_value"} eq "on")
    {
      $re = name_regex ($metric_description_ref, $script_pc_metrics, "calltree", $outputdir."calltree.sort.func-PC");
      ($error_code, $cmd_output) = execute_system_cmd ("echo '$re' > $outputdir"."calltree.sort.func-PC.name-regex");
      if ($error_code != 0 )
        {
          gp_message ("abort", $subr_name, "execution terminated");
        }
    }

  return (0);

} #-- End of subroutine preprocess_function_files

#-------------------------------------------------------------------------------
# Print the help overview
#-------------------------------------------------------------------------------
sub print_help_info 
{
  print
    #-------Marker line - do not go beyond this line ------------------------------
    "Usage: $driver_cmd [OPTION(S)] EXPERIMENT(S)\n".
    "\n".
    "Process one or more experiments to generate a directory containing the\n" .
    "index.html file that may be used to browse the experiment data.\n".
    "\n".
    "Options:\n".
    "\n".
    " --help              print usage information and exit.\n".
    " --version           print the version number and exit.\n".
    " --verbose {on|off}  enable/disable verbose mode that shows diagnostic\n" .
    "                       messages about the processing of the data; default\n" .
    "                       is off.\n".
    #-------Marker line - do not go beyond this line ------------------------------
    " -d, --debug {on|s|m|l|xl|off}  control the printing of run time information\n" .
    "                        to assist with troubleshooting, or further\n" .
    "                        development of this tool; on gives a modest amount\n" .
    "                        of information; s, m, l, or xl gives an increasing\n" .
    "                        amount of information and off disables the printing\n" .
    "                        of debug information; note that currently on, s, m,\n" .
    "                        and l are equivalent; this is expected to change in\n" .
    "                        future updates; default is off.\n" .
    #-------Marker line - do not go beyond this line ------------------------------
    " -hp, ----highlight-percentage <value>  a percentage value in the interval\n" .
    "                                 [0,100] to select and color code source\n" .
    "                                 lines as well as instructions that are\n" .
    "                                 within this percentage of the maximum\n" .
    "                                 metric value(s); a value of zero (-hp 0)\n" .
    "                                 disables this feature; the default is 90.\n".
    #-------Marker line - do not go beyond this line ------------------------------
    " -o, --output <dir-name>  use <dir-name> to store the results in; the\n" .
    "                            default name is ./display.<n>.html with <n> the\n" .
    "                            first positive integer number not in use; an\n" .
    "                            existing directory is not overwritten.\n".
    #-------Marker line - do not go beyond this line ------------------------------
    " -O, --overwrite <dir-name>  use <dir-name> to store the results in and\n" .
    "                               overwrite any existing directory with the\n" .
    "                               same name; make sure that umask is set to the\n" .
    "                               correct access permissions.\n" .
    #-------Marker line - do not go beyond this line ------------------------------
    " -q, --quiet {on|off}  disable/allow the display of all warning, debug and\n" .
    "                         verbose messages; if set to on, the settings for\n" .
    "                         verbose, warnings and debug are ignored; default\n" .
    "                         is off.\n".
    #-------Marker line - do not go beyond this line ------------------------------
    " -w, --warnings {on|off}  enable/disable run time warning messages;\n" .
    "                            default is on.\n".
    "\n".
# Temmporarily disabled    " -fl, --func-limit <limit>  impose a limit on the number of functions processed;\n".
# Temmporarily disabled    "                             this is an integer number; set to 0 to process all\n".
# Temmporarily disabled    "                             functions; the default value is 100.\n".
# Temmporarily disabled    "\n".
# Temmporarily disabled    "  -ct, --calltree {on|off}  enable or disable an html page with a call tree linked\n".
# Temmporarily disabled    "                             from the bottom of the first page; default is off.\n".
# Temmporarily disabled    "\n".
# Temmporarily disabled    "  -tp, --threshold-percentage <percentage>  provide a percentage of metric accountability; the\n".
# Temmporarily disabled    "                                             inclusion of functions for each metric will take\n".
# Temmporarily disabled    "                                             place in sort order until the percentage has been\n".
# Temmporarily disabled    "                                             reached.\n".
# Temmporarily disabled    "\n".
# Temmporarily disabled    "  -dm, --default-metrics {on|off}  enable or disable automatic selection of metrics\n".
# Temmporarily disabled    "                                   and use a default set of metrics; the default is off.\n".
# Temmporarily disabled    "\n".
# Temmporarily disabled    "  -im, --ignore-metrics <metric-list>  ignore the metrics from <metric-list>.\n".
# Temmporarily disabled    "\n".
# Temmporarily disabled     "Environment:\n".
# Temmporarily disabled     "\n".
# Temmporarily disabled     "The options can be set in a configuration file called .gp-display-html.rc.  This\n".
# Temmporarily disabled     "file needs to be either in the current directory, or in the home directory of the user.\n".
# Temmporarily disabled     "The long name of the option without the leading dashes is supported.  For example calltree\n".
# Temmporarily disabled     "to enable or disable the call tree.  Note that some options take a value.  In case the same option\n".
# Temmporarily disabled     "occurs multiple times in this file, only the last setting encountered is preserved.\n".
# Temmporarily disabled     "\n".
    "Documentation:\n".
    "\n".
    "A getting started guide for gprofng is maintained as a Texinfo manual.\n" .
    "If the info and gprofng programs are properly installed at your site,\n" .
    "the command \"info gprofng\" should give you access to this document.\n".
    "\n".
    "See also:\n".
    "\n".
    "gprofng(1), gp-archive(1), gp-collect-app(1), gp-display-src(1), " .
    "gp-display-text(1)\n";

    return (0);

} #-- End of subroutine print_help_info

#-------------------------------------------------------------------------------
# Print the meta data for each experiment directory.
#-------------------------------------------------------------------------------
sub print_meta_data_experiments
{
  my $subr_name = get_my_name ();

  my ($mode) = @_;

  for my $exp (sort keys %g_exp_dir_meta_data)
    {
      for my $meta (sort keys %{$g_exp_dir_meta_data{$exp}})
        {
          gp_message ($mode, $subr_name, "$exp => $meta = $g_exp_dir_meta_data{$exp}{$meta}");
        }
    }

  return (0);

} #-- End of subroutine print_meta_data_experiments

#------------------------------------------------------------------------------
# Brute force subroutine that prints the contents of a structure with function
# level information.  This version is for a top level array structure, 
# followed by a hash.
#------------------------------------------------------------------------------
sub print_metric_function_array
{
  my $subr_name = get_my_name ();

  my ($metric, $struct_type_name, $target_structure_ref) = @_;

  my @target_structure = @{$target_structure_ref}; 

  gp_message ("debugXL", $subr_name, "contents of structure ".$struct_type_name."{".$metric."}:");

  for my $fields (sort keys @target_structure)
    {
          for my $elems (sort keys % {$target_structure[$fields]})
            {
              my $msg = $struct_type_name."{$metric}[$fields]{$elems} = ";
              $msg   .= $target_structure[$fields]{$elems};
              gp_message ("debugXL", $subr_name, $msg);
            }
    }

  return (0);

} #-- End of subroutine print_metric_function_array

#------------------------------------------------------------------------------
# Brute force subroutine that prints the contents of a structure with function
# level information.  This version is for a top level hash structure.  The
# next level may be another hash, or an array.
#------------------------------------------------------------------------------
sub print_metric_function_hash
{
  my $subr_name = get_my_name ();

  my ($sub_struct_type, $metric, $struct_type_name, $target_structure_ref) = @_;

  my %target_structure = %{$target_structure_ref}; 

  gp_message ("debugXL", $subr_name, "contents of structure ".$struct_type_name."{".$metric."}:");

  for my $fields (sort keys %target_structure)
    {
      gp_message ("debugXL", $subr_name, "metric = $metric fields = $fields");
      if ($sub_struct_type eq "hash_hash")
        {
          for my $elems (sort keys %{$target_structure{$fields}})
            {
              my $txt = $struct_type_name."{$metric}{$fields}{$elems} = ";
              $txt   .= $target_structure{$fields}{$elems};
              gp_message ("debugXL", $subr_name, $txt);
            }
        }
      elsif ($sub_struct_type eq "hash_array")
        {
          my $values = "";
          for my $elems (sort keys @{$target_structure{$fields}})
            {
              $values .= "$target_structure{$fields}[$elems] ";
            }
          gp_message ("debugXL", $subr_name, $struct_type_name."{$metric}{$fields} = $values");
        }
      else
        {
          my $msg = "sub-structure type '$sub_struct_type' is not supported";
          gp_message ("assertion", $subr_name, $msg);
        }
    }
        
  return (0);

} #-- End of subroutine print_metric_function_hash

#------------------------------------------------------------------------------
# Print the opening message.
#------------------------------------------------------------------------------
sub print_opening_message
{
  my $subr_name = get_my_name ();
#------------------------------------------------------------------------------
# Since the second argument is an array, we pass it in by reference.  The
# alternative is to make it the last argument.
#------------------------------------------------------------------------------
  my ($outputdir, $exp_dir_list_ref, $time_percentage_multiplier) = @_;

  my @exp_dir_list = @{$exp_dir_list_ref};

  my $msg;
  my $no_of_dirs = scalar (@exp_dir_list);
#------------------------------------------------------------------------------
# Build a comma separated list with all directory names.  If there is only one
# entry, the leading comma will not be inserted.
#------------------------------------------------------------------------------
  my $dir_list   = join (", ", @exp_dir_list);

#------------------------------------------------------------------------------
# If there are at least two entries, find the last comma and replace it by
# " and".  Note that we know there is at least one comma, so the value 
# returned by rindex () cannot be -1.
#------------------------------------------------------------------------------
  if ($no_of_dirs > 1)
    {
      my $last_comma   = rindex ($dir_list, ",");
      my $ignore_value = substr ($dir_list, $last_comma, 1, " and");
    }
  $msg = "start $tool_name, generating directory $outputdir from $dir_list";

  gp_message ("verbose", $subr_name, $msg);

  if ($time_percentage_multiplier < 1.0)
    {
      $msg = "Handle at least ";
    }
  else
    {
      $msg = "Handle ";
    }

  $msg .= ($time_percentage_multiplier*100.0)."% of the time";
      
  gp_message ("verbose", $subr_name, $msg);

} #-- End of subroutine print_opening_message

#------------------------------------------------------------------------------
# TBD.
#------------------------------------------------------------------------------
sub print_program_header
{
  my $subr_name = get_my_name ();

  my ($mode, $tool_name, $binutils_version) = @_;

  my $header_limit = 60;
  my $dashes = "-";

#------------------------------------------------------------------------------
# Generate the dashed line
#------------------------------------------------------------------------------
  for (2 .. $header_limit)
    {
      $dashes .= "-";
    }

    gp_message ($mode, $subr_name, $dashes);
    gp_message ($mode, $subr_name, "Tool name: $tool_name");
    gp_message ($mode, $subr_name, "Version  : $binutils_version");
    gp_message ($mode, $subr_name, "Date     : " . localtime ());
    gp_message ($mode, $subr_name, $dashes);

} #-- End of subroutine print_program_header

#------------------------------------------------------------------------------
# Print a comment string, followed by the values of the options. The list
# with the keywords is sorted alphabetically.
#
# The value stored in $mode is passed on to gp_message ().  The intended use
# for this is to call this function in verbose and/or debug mode.
#
# The comment string is converted to uppercase.
#
# In case the length of the comment exceeds the length of the dashed line,
# the comment line is allowed to stick out to the right.
#
# If the length of the comment is less than the dashed line, it is centered 
# relative to the # length of the dashed line. 

# If the length of the comment and this line do not divide, an extra space is 
# added to the left of the comment.
#
# For example, if the comment is 55 long, there are 5 spaces to be distributed.
# There will be 3 spaces, followed by the comment. 
#------------------------------------------------------------------------------
sub print_table_user_settings
{
  my $subr_name = get_my_name ();

  my ($mode, $comment) = @_;

  my $leftover;
  my $padding;

  my $keyword;
  my $user_option;
  my $defined;
  my $value;
  my $data_type; 

  my $HEADER_LIMIT = 60;
  my $header = sprintf ("%-20s   %-9s   %8s   %s", "keyword", "option", "user set", "value");

#------------------------------------------------------------------------------
# Generate the dashed line
#------------------------------------------------------------------------------
  my $dashes = "-";
  for (2 .. $HEADER_LIMIT)
    {
      $dashes .= "-";
    }

#------------------------------------------------------------------------------
# Determine the padding needed to the left of the comment.
#------------------------------------------------------------------------------
  my $length_comment = length ($comment);

  $leftover = $length_comment%2;

  if ($length_comment <= ($HEADER_LIMIT-2))
    {
      $padding = ($HEADER_LIMIT - $length_comment + $leftover)/2;
    }
  else
    {
      $padding = 0;
    }
    
#------------------------------------------------------------------------------
# Generate the first blank part of the line.
#------------------------------------------------------------------------------
  my $blank_line = "";
  for (1 .. $padding)
    {
      $blank_line .= " ";
    }

#------------------------------------------------------------------------------
# Add the comment line with the first letter in uppercase.
#------------------------------------------------------------------------------
  my $final_comment = $blank_line.ucfirst ($comment);

  gp_message ($mode, $subr_name, $dashes);
  gp_message ($mode, $subr_name, $final_comment);
  gp_message ($mode, $subr_name, $dashes);
  gp_message ($mode, $subr_name, $header);
  gp_message ($mode, $subr_name, $dashes);

#------------------------------------------------------------------------------
# Print a line for each option. The list is sorted alphabetically.
#------------------------------------------------------------------------------
  for my $rc_keyword  (sort keys %g_user_settings)
    {
      $keyword     = $rc_keyword;
      $user_option = $g_user_settings{$rc_keyword}{"option"};
      $defined     = ($g_user_settings{$rc_keyword}{"defined"} ? "set" : "not set");
      $data_type   = $g_user_settings{$rc_keyword}{"data_type"};

      if (defined ($g_user_settings{$rc_keyword}{"current_value"}))
        {
          $value = $g_user_settings{$rc_keyword}{"current_value"};
          if ($data_type eq "boolean")
            {
              $value = $value ? "on" : "off";
            }
        }
      else
        {
          $value       = "undefined";
        }

      my $print_line = sprintf ("%-20s   %-9s   %8s   %s", $keyword, $user_option, $defined, $value);

      gp_message ($mode, $subr_name, $print_line);
    }
} #-- End of subroutine print_table_user_settings

#------------------------------------------------------------------------------
# Dump the contents of nested hash "g_user_settings".  Some simple formatting 
# is applied to make it easier to distinguish the various values.
#------------------------------------------------------------------------------
sub print_user_settings
{
  my $subr_name = get_my_name ();

  my ($mode, $comment) = @_;

  my $keyword_value_pair; 

  gp_message ($mode, $subr_name, $comment);

  for my $rc_keyword (keys %g_user_settings)
    {
      my $print_line = sprintf ("%-20s =>", $rc_keyword);
      for my $fields (sort keys %{ $g_user_settings{$rc_keyword} })
        {
          if (defined ($g_user_settings{$rc_keyword}{$fields}))
            {
              $keyword_value_pair = $fields." = ".$g_user_settings{$rc_keyword}{$fields};
            }
          else
            {
              $keyword_value_pair = $fields." = ". "undefined";
            }
           $print_line = join ("  ", $print_line, $keyword_value_pair);
        }
        gp_message ($mode, $subr_name, $print_line);
    }
} #-- End of subroutine print_user_settings

#------------------------------------------------------------------------------
# Print the version number and license information.
#------------------------------------------------------------------------------
sub print_version_info 
{
  print "$version_info\n";
  print "Copyright (C) 2023 Free Software Foundation, Inc.\n";
  print "License GPLv3+: GNU GPL version 3 or later <https://gnu.org/licenses/gpl.html>.\n";
  print "This is free software: you are free to change and redistribute it.\n";
  print "There is NO WARRANTY, to the extent permitted by law.\n";

  return (0);

} #-- End of subroutine print_version_info

#------------------------------------------------------------------------------
# Process the call tree input data and generate HTML output.
#------------------------------------------------------------------------------
sub process_calltree
{
  my $subr_name = get_my_name ();

  my ($function_info_ref, $function_address_info_ref, $addressobjtextm_ref, 
       $input_string) = @_;

  my @function_info         = @{ $function_info_ref };
  my %function_address_info = %{ $function_address_info_ref };
  my %addressobjtextm       = %{ $addressobjtextm_ref };

  my $outputdir = append_forward_slash ($input_string);

  my @call_tree_data = ();

  my $LANG              = $g_locale_settings{"LANG"};
  my $decimal_separator = $g_locale_settings{"decimal_separator"};

  my $infile  = $outputdir . "calltree";
  my $outfile = $outputdir . "calltree.html";

  open (CALL_TREE_IN, "<", $infile) 
    or die ("Not able to open calltree file $infile for reading - '$!'");
  gp_message ("debug", $subr_name, "opened file $infile for reading");

  open (CALL_TREE_OUT, ">", $outfile) 
    or die ("Not able to open $outfile for writing - '$!'");
  gp_message ("debug", $subr_name, "opened file $outfile for writing");

  gp_message ("debug", $subr_name, "building calltree file $outfile");
  
#------------------------------------------------------------------------------
# The directory name is potentially used below, but since it is a constant,
# we get it here and only once.
#------------------------------------------------------------------------------
#  my ($ignore_file_name, $directory_name, $ignore_suffix) = fileparse ($infile,"");
#  gp_message ("debug", $subr_name, "directory_name = $directory_name");

#------------------------------------------------------------------------------
# Generate some of the structures used in the HTML output.
#------------------------------------------------------------------------------
  my $file_title      = "Call Tree overview";
  my $html_header     = ${ create_html_header (\$file_title) };
  my $html_home_right = ${ generate_home_link ("right") };

  my $page_title    = "Call Tree View";
  my $size_text     = "h2";
  my $position_text = "center";
  my $html_title_header = ${ generate_a_header (
                            \$page_title, 
                            \$size_text, 
                            \$position_text) };

#-------------------------------------------------------------------------------
# Get the acknowledgement, return to main link, and final html statements.
#-------------------------------------------------------------------------------
  my $html_home_left       = ${ generate_home_link ("left") };
  my $html_acknowledgement = ${ create_html_credits () };
  my $html_end             = ${ terminate_html_document () };

#------------------------------------------------------------------------------
# Read all of the file into array with the name call_tree_data.
#------------------------------------------------------------------------------
  chomp (@call_tree_data = <CALL_TREE_IN>);
  close (CALL_TREE_IN);

#------------------------------------------------------------------------------
#------------------------------------------------------------------------------
# Process the data here and generate the HTML lines.
#------------------------------------------------------------------------------
#------------------------------------------------------------------------------

#------------------------------------------------------------------------------
# Print the top part of the HTML file.
#------------------------------------------------------------------------------
  print CALL_TREE_OUT $html_header;
  print CALL_TREE_OUT $html_home_right;
  print CALL_TREE_OUT $html_title_header;

#-------------------------------------------------------------------------------
# Print the generated HTML structures here.
#-------------------------------------------------------------------------------
##  print CALL_TREE_OUT "$_" for @whatever;
##  print CALL_TREE_OUT "<pre>\n";
##  print CALL_TREE_OUT "$_\n" for @whatever2;
##  print CALL_TREE_OUT "</pre>\n";

#-------------------------------------------------------------------------------
# Print the last part of the HTML file.
#-------------------------------------------------------------------------------
  print CALL_TREE_OUT $html_home_left;
  print CALL_TREE_OUT "<br>\n";
  print CALL_TREE_OUT $html_acknowledgement;
  print CALL_TREE_OUT $html_end;

  close (CALL_TREE_OUT);

  return (0);

} #-- End of subroutine process_calltree

#-------------------------------------------------------------------------------
# Process the generated experiment info file(s).
#-------------------------------------------------------------------------------
sub process_experiment_info
{
  my $subr_name = get_my_name ();

  my ($experiment_data_ref) = @_;

  my @exp_info;
  my @experiment_data = @{ $experiment_data_ref };

  my $exp_id;
  my $exp_name;
  my $exp_data_file;
  my $input_line;
  my $target_cmd;
  my $hostname ;
  my $OS;
  my $page_size;
  my $architecture;
  my $start_date;
  my $end_experiment;
  my $data_collection_duration;
  my $total_thread_time;
  my $user_cpu_time;
  my $user_cpu_percentage;
  my $system_cpu_time;
  my $system_cpu_percentage;
  my $sleep_time;
  my $sleep_percentage;

#-------------------------------------------------------------------------------
# Define the regular expressions used to capture the info.
#-------------------------------------------------------------------------------
# Target command (64-bit): './../bindir/mxv-pthreads.exe -m 3000 -n 2000 -t 2'

  my $target_cmd_regex = '\s*Target command\s+(\(.+\)):\s+\'(.+)\'';

# Host `ruudvan-vm-haswell-2-20210609', OS `Linux 5.4.17-2102.202.5.el8uek.x86_64', page size 4096, architecture `x86_64'

  my $host_system_regex = '\s*Host\s+\`(.+)\',\s+OS\s+\`(.+)\',\s+page size\s+(\d+),\s+architecture\s+\`(.+)\'';

# Experiment started Mon Aug 30 13:03:20 2021

  my $start_date_regex = '\s*Experiment started\s+(.+)';

# Experiment Ended: 1.812441219

  my $end_experiment_regex = '\s*Experiment Ended:\s+(.+)';

# Data Collection Duration: 1.812441219

  my $data_collection_duration_regex = '\s*Data Collection Duration:\s+(.+)';

#                           Total Thread Time (sec.): 1.812

  my $total_thread_time_regex = '\s*Total Thread Time (sec.):\s+(.+)';

#                                          User CPU: 1.685 ( 95.0%)

  my $user_cpu_regex = '\s*User CPU:\s+(.+)\s+\(\s*(.+)\)';

#                                        System CPU: 0.088 (  5.0%)

  my $system_cpu_regex = '\s*System CPU:\s+(.+)\s+\(\s*(.+)\)';

#                                             Sleep: 0.    (  0. %)

  my $sleep_regex = '\s*Sleep:\s+(.+)\s+\(\s*(.+)\)';

#-------------------------------------------------------------------------------
# Scan the experiment data and select the info of interest.
#-------------------------------------------------------------------------------
  for my $i (sort keys @experiment_data)
    {
      $exp_id        = $experiment_data[$i]{"exp_id"};
      $exp_name      = $experiment_data[$i]{"exp_name_full"};
      $exp_data_file = $experiment_data[$i]{"exp_data_file"};

      my $msg = "exp_id = $exp_id name = $exp_name file = $exp_data_file";
      gp_message ("debug", $subr_name, $msg);

      open (EXPERIMENT_INFO, "<", $exp_data_file) 
        or die ("$subr_name - unable to open file $exp_data_file for reading '$!'");
      gp_message ("debug", $subr_name, "opened file $exp_data_file for reading");

      chomp (@exp_info = <EXPERIMENT_INFO>);

#-------------------------------------------------------------------------------
# Process the info for the current experiment.
#-------------------------------------------------------------------------------
      for my $line (0 .. $#exp_info)
        {
          $input_line = $exp_info[$line];

          my $msg = "exp_id = $exp_id: input_line = $input_line";
          gp_message ("debugM", $subr_name, $msg);

          if ($input_line =~ /$target_cmd_regex/)
            {
              $target_cmd = $2;
              gp_message ("debugM", $subr_name, "$exp_id => $target_cmd");
              $experiment_data[$i]{"target_cmd"} = $target_cmd;
            }
          elsif ($input_line =~ /$host_system_regex/)
            {
              $hostname  = $1;
              $OS        = $2;
              $page_size = $3;
              $architecture = $4;
              gp_message ("debugM", $subr_name, "$exp_id => $hostname $OS $page_size $architecture");
              $experiment_data[$i]{"hostname"} = $hostname;
              $experiment_data[$i]{"OS"} = $OS;
              $experiment_data[$i]{"page_size"} = $page_size;
              $experiment_data[$i]{"architecture"} = $architecture;
            }
          elsif ($input_line =~ /$start_date_regex/)
            {
              $start_date = $1;
              gp_message ("debugM", $subr_name, "$exp_id => $start_date");
              $experiment_data[$i]{"start_date"} = $start_date;
            }
          elsif ($input_line =~ /$end_experiment_regex/) 
            {
              $end_experiment = $1;
              gp_message ("debugM", $subr_name, "$exp_id => $end_experiment");
              $experiment_data[$i]{"end_experiment"} = $end_experiment;
            }
          elsif ($input_line =~ /$data_collection_duration_regex/) 
            {
              $data_collection_duration = $1;
              gp_message ("debugM", $subr_name, "$exp_id => $data_collection_duration");
              $experiment_data[$i]{"data_collection_duration"} = $data_collection_duration;
            }
#------------------------------------------------------------------------------
#                                       Start Label: Total
#                                          End Label: Total
#                                  Start Time (sec.): 0.000
#                                    End Time (sec.): 1.812
#                                    Duration (sec.): 1.812
#                           Total Thread Time (sec.): 1.812
#                          Average number of Threads: 1.000
# 
#                               Process Times (sec.):
#                                           User CPU: 1.666 ( 91.9%)
#                                         System CPU: 0.090 (  5.0%)
#                                           Trap CPU: 0.    (  0. %)
#                                          User Lock: 0.    (  0. %)
#                                    Data Page Fault: 0.    (  0. %)
#                                    Text Page Fault: 0.    (  0. %)
#                                  Kernel Page Fault: 0.    (  0. %)
#                                            Stopped: 0.    (  0. %)
#                                           Wait CPU: 0.    (  0. %)
#                                              Sleep: 0.056 (  3.1%)
#------------------------------------------------------------------------------
          elsif ($input_line =~ /$total_thread_time_regex/) 
            {
              $total_thread_time = $1;
              gp_message ("debugM", $subr_name, "$exp_id => $total_thread_time");
              $experiment_data[$i]{"total_thread_time"} = $total_thread_time;
            }
          elsif ($input_line =~ /$user_cpu_regex/) 
            {
              $user_cpu_time       = $1;
              $user_cpu_percentage = $2;
              gp_message ("debugM", $subr_name, "$exp_id => $user_cpu_time $user_cpu_percentage");
              $experiment_data[$i]{"user_cpu_time"} = $user_cpu_time . "&nbsp; (" . $user_cpu_percentage . ")";
              $experiment_data[$i]{"user_cpu_percentage"} = $user_cpu_percentage;
            }
          elsif ($input_line =~ /$system_cpu_regex/) 
            {
              $system_cpu_time       = $1;
              $system_cpu_percentage = $2;
              gp_message ("debugM", $subr_name, "$exp_id => $system_cpu_time $system_cpu_percentage");
              $experiment_data[$i]{"system_cpu_time"} = $system_cpu_time . "&nbsp; (" . $system_cpu_percentage . ")";
              $experiment_data[$i]{"system_cpu_percentage"} = $system_cpu_percentage;
            }
          elsif ($input_line =~ /$sleep_regex/) 
            {
              $sleep_time       = $1;
              $sleep_percentage = $2;
              $experiment_data[$i]{"sleep_time"} = $sleep_time . "&nbsp; (" . $sleep_percentage . ")";
              $experiment_data[$i]{"sleep_percentage"} = $sleep_percentage;

              my $msg = "exp_id = $exp_id => sleep_time = $sleep_time " .
                        "sleep_percentage = $sleep_percentage";
              gp_message ("debugM", $subr_name, $msg);
            }
        }
    }

  for my $keys (0 .. $#experiment_data)
    {
      for my $fields (sort keys %{ $experiment_data[$keys] })
        {
          my $msg = "experiment_data[$keys]{$fields} = " .
             $experiment_data[$keys]{$fields};
          gp_message ("debugM", $subr_name, $msg);
        }
    }

  return (\@experiment_data);

} #-- End of subroutine process_experiment_info

#------------------------------------------------------------------------------
# TBD
#------------------------------------------------------------------------------
sub process_function_files
{
  my $subr_name = get_my_name ();

  my ($exp_dir_list_ref, $executable_name, $time_percentage_multiplier, 
      $summary_metrics, $process_all_functions, $elf_loadobjects_found, 
      $outputdir, $sort_fields_ref, $function_info_ref, 
      $function_address_and_index_ref, $LINUX_vDSO_ref, 
      $metric_description_ref, $elf_arch, $base_va_executable, 
      $ARCHIVES_MAP_NAME, $ARCHIVES_MAP_VADDR, $elf_rats_ref) = @_;

  my $old_fsummary; 
  my $total_attributed_time;
  my $current_attributed_time;
  my $value;

  my @exp_dir_list               = @{ $exp_dir_list_ref };
  my @function_info              = @{ $function_info_ref };
  my %function_address_and_index = %{ $function_address_and_index_ref };
  my @sort_fields                = @{ $sort_fields_ref };
  my %metric_description         = %{ $metric_description_ref };
  my %elf_rats                   = %{ $elf_rats_ref };

#------------------------------------------------------------------------------
# The regex section.
#
# TBD: Remove the part regarding clones. Legacy.
#------------------------------------------------------------------------------
  my $replace_quote_regex = '"/\"';
  my $find_clone_regex    = '^(.*)(\s+--\s+cloned\s+version\s+\[)([^]]+)(\])';

  my %addressobj_index = ();
  my %function_address_info = ();
  my $function_address_info_ref;

  $outputdir = append_forward_slash ($outputdir);

  my %functions_per_metric_indexes = ();
  my $functions_per_metric_indexes_ref;

  my %functions_per_metric_first_index = ();
  my $functions_per_metric_first_index_ref;

  my %routine_list = ();
  my %handled_routines = ();

#------------------------------------------------------------------------------
# TBD: Name cleanup needed.
#------------------------------------------------------------------------------

  my $number_of_metrics;
  my $expr_name;
  my $routine;
  my $tmp;
  my $loadobj;
  my $PCA;
  my $address_field;
  my $limit_txt;
  my $n_metrics_text;
  my $disfile;
  my $srcfile;
  my $RIN;
  my $gp_listings_cmd;
  my $gp_display_text_cmd; 
  my $ignore_value;

  my $result_file   = $outputdir . "gp-listings.out";
  my $gp_error_file = $outputdir . "gp-listings.err";

  my $convert_to_dot    = $g_locale_settings{"convert_to_dot"};
  my $decimal_separator = $g_locale_settings{"decimal_separator"};
  my $length_of_string  = length ($outputdir);

  $expr_name = join (" ", @exp_dir_list);

  gp_message ("debug", $subr_name, "expr_name = $expr_name");

#------------------------------------------------------------------------------
# Loop over the files in $outputdir.
#------------------------------------------------------------------------------
  while (glob ($outputdir.'*.sort.func-PC'))
    {
      my $metric;
      my $infile;
      my $ignore_value;
      my $suffix_not_used;

      $infile = $_;

      ($metric, $ignore_value, $suffix_not_used) = fileparse ($infile, ".sort.func-PC");

      gp_message ("debugXL", $subr_name, "suffix_not_used = $suffix_not_used");
      gp_message ("debugXL", $subr_name, "func-PC->$infile<- metric->$metric<-");
  
   # Function_info creates the functions files from the PC ones
   # as well as culling PC and metric information

      ($function_address_info_ref, 
       $functions_per_metric_first_index_ref, 
       $functions_per_metric_indexes_ref) = function_info (
                                              $outputdir, 
                                              $infile, 
                                              $metric, 
                                              $LINUX_vDSO_ref);

      @{$function_address_info{$metric}}            = @{$function_address_info_ref};
      %{$functions_per_metric_indexes{$metric}}     = %{$functions_per_metric_indexes_ref};
      %{$functions_per_metric_first_index{$metric}} = %{$functions_per_metric_first_index_ref};

      $ignore_value = print_metric_function_array ($metric, 
                                                   "function_address_info", 
                                                   \@{$function_address_info{$metric}});
      $ignore_value = print_metric_function_hash ("hash_hash",  $metric, 
                                                  "functions_per_metric_first_index", 
                                                  \%{$functions_per_metric_first_index{$metric}});
      $ignore_value = print_metric_function_hash ("hash_array", $metric, 
                                                  "functions_per_metric_indexes", 
                                                  \%{$functions_per_metric_indexes{$metric}});
    }

#------------------------------------------------------------------------------
# Get header info for use in post processing er_html output
#------------------------------------------------------------------------------
  gp_message ("debugXL", $subr_name, "get_hdr_info section");

  get_hdr_info ($outputdir, $outputdir."functions.sort.func");

  for my $field (@sort_fields)
    {
      get_hdr_info ($outputdir, $outputdir."$field.sort.func");
    }

#------------------------------------------------------------------------------
# Caller-callee
#------------------------------------------------------------------------------
  get_hdr_info ($outputdir, $outputdir."calls.sort.func");

#------------------------------------------------------------------------------
# Calltree
#------------------------------------------------------------------------------
  if ($g_user_settings{"calltree"}{"current_value"} eq "on")
    {
      get_hdr_info ($outputdir, $outputdir."calltree.sort.func");
    }
  
  gp_message ("debug", $subr_name, "process functions");

  my $scriptfile     = $outputdir.'gp-script';
  my $script_metrics = "$summary_metrics";
  my $func_limit     = $g_user_settings{"func_limit"}{"current_value"};

  open (SCRIPT, ">", $scriptfile)
    or die ("Unable to create script file $scriptfile - '$!'");
  gp_message ("debug", $subr_name, "opened script file $scriptfile for writing");

  print SCRIPT "# limit $func_limit\n";
  print SCRIPT "limit $func_limit\n";
  print SCRIPT "# thread_select all\n";
  print SCRIPT "thread_select all\n";
  print SCRIPT "# metrics $script_metrics\n";
  print SCRIPT "metrics $script_metrics\n";

  for my $metric (@sort_fields)
    {
      gp_message ("debug", $subr_name, "handling $metric->$metric_description{$metric}");
  
      $total_attributed_time   = 0;
      $current_attributed_time = 0;
  
      $value = $function_address_info{$metric}[0]{"metric_value"}; # <Total>
      if ($convert_to_dot)
        {
          $value =~ s/$decimal_separator/\./;
        }
      $total_attributed_time = $value;
  
#------------------------------------------------------------------------------
# start at 1 - skipping <Total>
#------------------------------------------------------------------------------
      for my $INDEX (1 .. $#{$function_address_info{$metric}}) 
        {
#------------------------------------------------------------------------------
#Looking to handle at least 99% of the time - or what the user asked for
#------------------------------------------------------------------------------
          $value   = $function_address_info{$metric}[$INDEX]{"metric_value"};
          $routine = $function_address_info{$metric}[$INDEX]{"routine"};

          gp_message ("debugXL", $subr_name, " total $total_attributed_time current $current_attributed_time");
          gp_message ("debugXL", $subr_name, "  (found routine $routine : value $value)");

          if ($convert_to_dot) 
            {
              $value =~ s/$decimal_separator/\./;
            }

          if ( ($value > $total_attributed_time*(1-$time_percentage_multiplier)) or
               ( ($total_attributed_time == 0) and ($value>0) ) or 
               $process_all_functions) 
            {
              $PCA = $function_address_info{$metric}[$INDEX]{"PC Address"};

              if (not exists ($functions_per_metric_first_index{$metric}{$routine}{$PCA}))
                {
                  gp_message ("debugXL", $subr_name, "not exists: functions_per_metric_first_index{$metric}{$routine}{$PCA}");
                }
              if (not exists ($function_address_and_index{$routine}{$PCA}))
                {
                  gp_message ("debugXL", $subr_name, "not exists: function_address_and_index{$routine}{$PCA}");
                }

              if (exists ($functions_per_metric_first_index{$metric}{$routine}{$PCA}) and 
                  exists ($function_address_and_index{$routine}{$PCA}))
                {
#------------------------------------------------------------------------------
# handled_routines now contains $RI from "first_metric" (?)
#------------------------------------------------------------------------------
                  $handled_routines{$function_address_and_index{$routine}{$PCA}} = 1; 
                  my $description = ${ retrieve_metric_description (\$metric, \%metric_description) };
                  if ($metric_description{$metric} =~ /Exclusive Total CPU Time/)
                    {
                      $routine_list{$routine} = 1 
                    }

                  gp_message ("debugXL", $subr_name, " $routine is candidate");
                } 
              else 
                {
                  die ("internal error for metric $metric and routine $routine");
                }

              $current_attributed_time += $value;
            }
        }
    }
#------------------------------------------------------------------------------
# Sort numerically in ascending order.
#------------------------------------------------------------------------------
  for my $routine_index (sort {$a <=> $b} keys %handled_routines)
    {
      $routine = $function_info[$routine_index]{"routine"};
      gp_message ("debugXL", $subr_name, "routine_index = $routine_index routine = $routine");
      next unless $routine_list{$routine};

# not used      $source = $function_info[$routine_index]{"Source File"};

      $function_info[$routine_index]{"srcline"} = "";
      $address_field = $function_info[$routine_index]{"addressobjtext"};

##      $disfile = "file\.$routine_index\.dis"; 
      $disfile = "file." . $routine_index . "." . $g_html_base_file_name{"disassembly"};
      $srcfile = "";
      $srcfile = "file\.$routine_index\.src.txt";

#------------------------------------------------------------------------------
# If the file is unknown, we can disassemble anyway and add disassembly 
# to the script.
#------------------------------------------------------------------------------
      print SCRIPT "# outfile $outputdir"."$disfile\n";
      print SCRIPT "outfile $outputdir"."$disfile\n";
#------------------------------------------------------------------------------
# TBD: Legacy. Not sure why this is needed, but it won't harm things. I hope.
#------------------------------------------------------------------------------
      $tmp = $routine;
      $tmp =~ s/$replace_quote_regex//g;
      print SCRIPT "# disasm \"$tmp\" $address_field\n";
      print SCRIPT "disasm \"$tmp\" $address_field\n";
      if ($srcfile=~/file/)
        {
          print SCRIPT "# outfile $outputdir"."$srcfile\n";
          print SCRIPT "outfile $outputdir"."$srcfile\n";
          print SCRIPT "# source \"$tmp\" $address_field\n";
          print SCRIPT "source \"$tmp\" $address_field\n";
        }

      if ($routine =~ /$find_clone_regex/)
        {
          my ($clone_routine) = $1.$2.$3.$4;
          my ($clone) = $3;
        }
     }
  close SCRIPT;

#------------------------------------------------------------------------------
# Remember the number of handled routines depends on the limit setting passed
# to er_print together with the sorting order on the metrics, which usually results
# in different routines at the top. Thus $RIN below can be greater than the limit.
#------------------------------------------------------------------------------

  $RIN = scalar (keys %handled_routines);

  if (!$func_limit)
    {
      $limit_txt = "unlimited";
    }
  else
    {
      $limit_txt = $func_limit - 1;
  }

  $number_of_metrics = scalar (@sort_fields); 

  $n_metrics_text = ($number_of_metrics == 1) ? "metric" : "metrics";

  gp_message ("debugXL", $subr_name, "built function list with $RIN functions");
  gp_message ("debugXL", $subr_name, "$number_of_metrics $n_metrics_text and a function limit of $limit_txt");

# add ELF program header offset 

  for my $routine_index (sort {$a <=> $b} keys %handled_routines)
    {
      $routine = $function_info[$routine_index]{"routine"};
      $loadobj = $function_info[$routine_index]{"Load Object"};

      gp_message ("debugXL", $subr_name, "routine = $routine loadobj = $loadobj elf_arch = $elf_arch");

      if ($loadobj ne '')
        {
    # <Truncated-stack> is associated with <Total>. Its load object is <Total>
          if ($loadobj eq "<Total>")
            {
              next;
            }
    # Have seen a routine called <Unknown>. Its load object is <Unknown>
          if ($loadobj eq "<Unknown>")
            {
              next;
            }
###############################################################################
## RUUD: The new approach gives a different result. Investigate this.
#
# Turns out the new code improves the result.  The addresses are now correct
# and as a result, more ftag's are created later on.
###############################################################################
          gp_message ("debugXL", $subr_name, "before function_info[$routine_index]{addressobj} = $function_info[$routine_index]{'addressobj'}");

          $function_info[$routine_index]{"addressobj"} += bigint::hex (
                                                determine_base_va_address (
                                                  $executable_name, 
                                                  $base_va_executable, 
                                                  $loadobj, 
                                                  $routine));
          $addressobj_index{$function_info[$routine_index]{"addressobj"}} = $routine_index;

          gp_message ("debugXL", $subr_name, "after  function_info[$routine_index]{addressobj} = $function_info[$routine_index]{'addressobj'}");
          gp_message ("debugXL", $subr_name, "after  addressobj_index{function_info[$routine_index]{addressobj}} = $addressobj_index{$function_info[$routine_index]{'addressobj'}}");
        }
    }

#------------------------------------------------------------------------------
# Get the disassembly and source code output.
#------------------------------------------------------------------------------
  $gp_listings_cmd = "$GP_DISPLAY_TEXT -limit $func_limit -viewmode machine " .
                     "-compare off -script $scriptfile $expr_name";

  $gp_display_text_cmd = "$gp_listings_cmd 1> $result_file 2>> $gp_error_file";

  gp_message ("debugXL", $subr_name,"gp_display_text_cmd = $gp_display_text_cmd");

  gp_message ("debug", $subr_name, "calling $GP_DISPLAY_TEXT to produce disassembly and source code output");

  my ($error_code, $cmd_output) = execute_system_cmd ($gp_display_text_cmd);

  if ($error_code != 0)
    {
      $ignore_value = msg_display_text_failure ($gp_display_text_cmd, 
                                                $error_code, 
                                                $gp_error_file);
      gp_message ("abort", "execution terminated");
    }

  return (\@function_info, \%function_address_info, \%addressobj_index);

} #-- End of subroutine process_function_files

#------------------------------------------------------------------------------
# Process the information found in the function overview file passed in.
#
# Example input:
#
# Current Sort Metric: Exclusive Total CPU Time ( e.totalcpu )
# Functions sorted by metric: Exclusive Total CPU Time
# 
# PC Addr.       Name              Excl.     Excl. CPU  Excl.         Excl.         Excl.   Excl.
#                                  Total     Cycles     Instructions  Last-Level    IPC     CPI
#                                  CPU sec.   sec.      Executed      Cache Misses
# 1:0x00000000   <Total>           3.713     4.256      15396819712   27727992       1.577  0.634
# 2:0x000021ae   mxv_core          3.532     4.116      14500538992   27527781       1.536  0.651
# 2:0x00001f7b   init_data         0.070     0.084         64020034     200211       0.333  3.000
#------------------------------------------------------------------------------
sub process_function_overview
{
  my $subr_name = get_my_name ();

  my ($metric_ref, $exp_type_ref, $summary_metrics_ref, $number_of_metrics_ref,
      $function_info_ref, $function_view_structure_ref, $overview_file_ref) = @_;

  my $metric                  = ${ $metric_ref };
  my $exp_type                = ${ $exp_type_ref };
  my $summary_metrics         = ${ $summary_metrics_ref };
  my $number_of_metrics       = ${ $number_of_metrics_ref };
  my @function_info           = @{ $function_info_ref };
  my %function_view_structure = %{ $function_view_structure_ref };
  my $overview_file           = ${ $overview_file_ref };

  my $all_metrics; 
  my $decimal_separator = $g_locale_settings{"decimal_separator"};
  my $length_of_block;
  my $elements_in_name; 
  my $full_hex_address;
  my $header_line;
  my $hex_address;
  my $html_line;
  my $input_line;
  my $name_regex; 
  my $no_of_fields; 
  my $metrics_length;
  my $missing_digits; 
  my $remaining_part_header;
  my $routine; 
  my $routine_length; 
  my $scan_header        = $FALSE;
  my $scan_function_data = $FALSE;
  my $string_length;
  my $total_header_lines; 

  my @address_field           = ();
  my @fields                  = (); 
  my @function_data           = ();
  my @function_names          = ();
  my @function_view_array     = ();
  my @function_view_modified  = ();
  my @header_lines            = ();
  my @metrics_part            = ();
  my @metric_values           = ();

#------------------------------------------------------------------------------
# The regex section.
#------------------------------------------------------------------------------
  my $header_name_regex     = '(.*\.)(\s+)(Name)\s+(.*)';
  my $total_marker_regex    = '\s*(\d+:0x[a-fA-F0-9]+)\s+(<Total>)\s+(.*)';
  my $empty_line_regex      = '^\s*$';
  my $catch_all_regex       = '\s*(.*)';
  my $get_hex_address_regex = '(\d+):0x(\S+)';
  my $get_addr_offset_regex = '^@\d+:';
  my $zero_dot_at_end_regex = '[\w0-9' . $decimal_separator . ']*(0' . $decimal_separator . '$)';
  my $backward_slash_regex  = '\/';

#------------------------------------------------------------------------------
  if (is_file_empty ($overview_file))
    {
      gp_message ("error", $subr_name, "assertion error: file $overview_file is empty");
    }

  open (FUNC_OVERVIEW, "<", $overview_file) 
    or die ("$subr_name - unable to open file $overview_file for reading '$!'");
  gp_message ("debug", $subr_name, "opened file $overview_file for reading");

  gp_message ("debug", $subr_name, "processing file for exp_type = $exp_type");

  gp_message ("debugM", $subr_name, "header_name_regex  = $header_name_regex");
  gp_message ("debugM", $subr_name, "total_marker_regex = $total_marker_regex");
  gp_message ("debugM", $subr_name, "empty_line_regex   = $empty_line_regex");
  gp_message ("debugM", $subr_name, "catch_all_regex    = $catch_all_regex");
  gp_message ("debugM", $subr_name, "get_hex_address_regex = $get_hex_address_regex");
  gp_message ("debugM", $subr_name, "get_addr_offset_regex = $get_addr_offset_regex");
  gp_message ("debugM", $subr_name, "zero_dot_at_end_regex = $zero_dot_at_end_regex");
  gp_message ("debugM", $subr_name, "backward_slash_regex  = $backward_slash_regex");

#------------------------------------------------------------------------------
# Read the input file into memory.
#------------------------------------------------------------------------------
  chomp (@function_data = <FUNC_OVERVIEW>);
  gp_message ("debug", $subr_name, "read all of file $overview_file into memory");

#-------------------------------------------------------------------------------
# Parse the function view info and store the data.
#-------------------------------------------------------------------------------
  my $max_header_length  = 0;
  my $max_metrics_length = 0;

#------------------------------------------------------------------------------
# Loop over all the lines.  Extract the header, metric values, function names,
# and the addresses.
#
# This is also where the maximum lengths for the header and metric lines are
# computed.  This is used to get the correct alignment in the HTML output.
#------------------------------------------------------------------------------
  for (my $line = 0; $line <= $#function_data; $line++)
    {
      $input_line = $function_data[$line];
      gp_message ("debugXL", $subr_name, "input_line = $input_line");

#------------------------------------------------------------------------------
# The table header is assumed to start at the line that has "Name" in it.
# The header ends when we see the function name "<Total>".
#------------------------------------------------------------------------------
      if ($input_line =~ /$header_name_regex/)
        {
          $scan_header = $TRUE;
        }
      elsif ($input_line =~ /$total_marker_regex/) 
        {
          $scan_header        = $FALSE;
          $scan_function_data = $TRUE;
        }

      if ($scan_header)
        {
#------------------------------------------------------------------------------
# This group is only defined for the first line of the header and $4 contains 
# the remaining part of the line after "Name", without the leading spaces.
#------------------------------------------------------------------------------
          if (defined ($4))
            {
              $remaining_part_header = $4;
              my $msg =  "remaining_part_header = $remaining_part_header";
              gp_message ("debugXL", $subr_name, $msg);

#------------------------------------------------------------------------------
# Determine the maximum length of the header.  This needs to be done before 
# the HTML controls are added.
#------------------------------------------------------------------------------
              my $header_length = length ($remaining_part_header);
              $max_header_length = max ($max_header_length, $header_length);

#------------------------------------------------------------------------------
# TBD Should change this and not yet include html in header_lines
#------------------------------------------------------------------------------
              $html_line = "<b>" . $remaining_part_header . "</b>";

              push (@header_lines, $html_line);

              gp_message ("debugXL", $subr_name, "max_header_length = $max_header_length");
              gp_message ("debugXL", $subr_name, "html_line = $html_line");
            }
#------------------------------------------------------------------------------
# Captures the subsequent header lines.  Assume they exist.
#------------------------------------------------------------------------------
          elsif ($input_line =~ /$catch_all_regex/)
            { 
              $header_line = $1;
              gp_message ("debugXL", $subr_name, "header_line = $header_line");

              my $header_length = length ($header_line);
              $max_header_length = max ($max_header_length, $header_length);

#------------------------------------------------------------------------------
# TBD Should change this and not yet include html in header_lines
#------------------------------------------------------------------------------
              $html_line = "<b>" . $header_line . "</b>";

              push (@header_lines, $html_line);

              gp_message ("debugXL", $subr_name, "max_header_length = $max_header_length");
              gp_message ("debugXL", $subr_name, "html_line = $html_line");
            } 
        }
#------------------------------------------------------------------------------
# This is a line with function data.
#------------------------------------------------------------------------------
      if ($scan_function_data and (not ($input_line =~ /$empty_line_regex/)))
        {
          @fields = split (" ", $input_line);

          $no_of_fields = $#fields + 1;
          $elements_in_name = $no_of_fields - $number_of_metrics - 1;

          gp_message ("debugXL", $subr_name, "no_of_fields = $no_of_fields elements_in_name = $elements_in_name");
     
#------------------------------------------------------------------------------
# TBD: Handle this better in case a function entry has more than 2 words.
# Build the regex dynamically and use eval to capture the correct group.
# CHECK CODE IN GENERATE_CALLER_CALLEE
#------------------------------------------------------------------------------
          if ($elements_in_name == 1) 
            {
              $name_regex = '\s*(\d+:0x[a-fA-F0-9]+)\s+(\S+)\s+(.*)';
            }
          elsif ($elements_in_name == 2) 
            {
              $name_regex = '\s*(\d+:0x[a-fA-F0-9]+)\s+((\S+)\s+(\S+))\s+(.*)';
            }
          else
            {
              gp_message ("error", $subr_name, "assertion error: $elements_in_name elements in name exceeds limit");
            }

          if ($input_line =~ /$name_regex/)
            {
              $full_hex_address   = $1;
              $routine            = $2;

              if ($elements_in_name == 1) 
                {
                  $all_metrics = $3;
                }
              elsif ($elements_in_name == 2) 
                {
                  $all_metrics = $5;
                }

#------------------------------------------------------------------------------
# In case the last metric is 0. only, we append 3 extra characters that 
# represent zero.  We cannot change the number to 0.000 though because that
# has a different interpretation than 0.
# In a later phase, the "ZZZ" symbol will be removed again, but for now it 
# creates consistency in, for example, the length of the metrics part.
#------------------------------------------------------------------------------
              if ($all_metrics =~ /$zero_dot_at_end_regex/)
                {
                  if (defined ($1) )
                    {
#------------------------------------------------------------------------------
# Somewhat overkill, but remove the leading "\" from the decimal separator
# in the debug print since it is used for internal purposes only.
#------------------------------------------------------------------------------
                      my $decimal_point = $decimal_separator;
                      $decimal_point =~ s/$backward_slash_regex//;
                      my $txt = "all_metrics = $all_metrics ended with 0"; 
                      $txt   .= "$decimal_point ($decimal_separator)";
                      gp_message ("debugXL", $subr_name, $txt);

                      $all_metrics .= "ZZZ";
                    }
                }
              $metrics_length = length ($all_metrics);
              $max_metrics_length = max ($max_metrics_length, $metrics_length);
              gp_message ("debugXL", $subr_name, "$routine all_metrics = $all_metrics metrics_length = $metrics_length"); 

              if ($full_hex_address =~ /$get_hex_address_regex/)
                {
                  $hex_address = "0x" . $2;
                }

              push (@address_field, $hex_address); 
              push (@metric_values, $all_metrics);

#------------------------------------------------------------------------------
# Record the function name "as is".  Below we figure out what the final name
# should be in case there are multiple occurrences of the same name.
#
# The reason to decouple this is to avoid the code gets too complex here.
#------------------------------------------------------------------------------
              push (@function_names, $routine);
            }
        }
    } #-- End of loop over the input lines

#------------------------------------------------------------------------------
# Store the maximum lengths for the header and metrics.
#------------------------------------------------------------------------------
    gp_message ("debugXL", $subr_name, "final max_header_length  = $max_header_length");
    gp_message ("debugXL", $subr_name, "final max_metrics_length = $max_metrics_length");

    $function_view_structure{"max header length"}  = $max_header_length;
    $function_view_structure{"max metrics length"} = $max_metrics_length;

#------------------------------------------------------------------------------
# Determine the final name for the functions and set up the HTML block.
#------------------------------------------------------------------------------
  my @final_html_function_block = ();
  my @function_index_list       = ();

#------------------------------------------------------------------------------
# First, an index list is built.  If we are to index the functions in order of 
# appearance in the function overview from 0 to n-1, the value of the array
# for index "i" is the index into the large "function_info" structure.  This
# has the final name, the html function block, etc.
#------------------------------------------------------------------------------

#------------------------------------------------------------------------------
## TBD: Use get_index_function_info??!!
#------------------------------------------------------------------------------
  for my $i (keys @function_names)
    {
#------------------------------------------------------------------------------
# Get the function name and the address from the function overview.  The
# address is used to differentiate in case a function has multiple occurences.
#------------------------------------------------------------------------------
      my $routine = $function_names[$i];
      my $current_address = $address_field[$i];

      my $found_a_match = $FALSE;
      my $final_function_name; 
      my $ref_index; 

#------------------------------------------------------------------------------
# Check if there are duplicate entries for this function.  If there are, use
# the address to find the right match in the function_info structure.
#------------------------------------------------------------------------------
      gp_message ("debugXL", $subr_name, "$routine: first check for multiple occurrences");
      if (exists ($g_multi_count_function{$routine}))
        {
          gp_message ("debugXL", $subr_name, "$routine: occurrences = $g_function_occurrences{$routine}");
          for my $ref (keys @{ $g_map_function_to_index{$routine} })
            {
              my $ref_index = $g_map_function_to_index{$routine}[$ref];
              my $addr_offset = $function_info[$ref_index]{"addressobjtext"};
#------------------------------------------------------------------------------
# The address has the following format: 6:0x0003af50, but we only need the
# part after the colon and remove the first part.
#------------------------------------------------------------------------------
              $addr_offset =~ s/$get_addr_offset_regex//;
             
              gp_message ("debugXL", $subr_name, "$routine: ref_index = $ref_index");
              gp_message ("debugXL", $subr_name, "$routine: function_info[$ref_index]{'alt_name'} = $function_info[$ref_index]{'alt_name'}");
              gp_message ("debugXL", $subr_name, "$routine: addr_offset = $addr_offset");

              if ($addr_offset eq $current_address)
#------------------------------------------------------------------------------
# There is a match and we can store the index.
#------------------------------------------------------------------------------
                {
                  $found_a_match = $TRUE;
                  push (@function_index_list, $ref_index);
                  last;
                }
            }
        }
      else
        {
#------------------------------------------------------------------------------
# This is the easy case.  There is only one index value.  We do check if the
# array element that contains it, exists.  If this is not the case, something
# has gone horribly wrong earlier and we need to bail out.
#------------------------------------------------------------------------------
          if (defined ($g_map_function_to_index{$routine}[0]))
            {
              $found_a_match = $TRUE;
              $ref_index = $g_map_function_to_index{$routine}[0]; 
              push (@function_index_list, $ref_index);
              my $final_function_name = $function_info[$ref_index]{"routine"};
              gp_message ("debugXL", $subr_name, "pushed single occurrence: ref_index = $ref_index final_function_name = $final_function_name");
            }
          }
      if (not $found_a_match)
#------------------------------------------------------------------------------
# This should not happen. All we can do is print an error message and stop.
#------------------------------------------------------------------------------
        {
          my $msg = "cannot find the index for $routine: found_a_match = ";
          $msg .= ($found_a_match == $TRUE) ? "TRUE" : "FALSE";
          gp_message ("assertion", $subr_name, $msg);
        }
    }

#------------------------------------------------------------------------------
# The loop over all function names has completed and @function_index_list 
# contains the index values into @function_info for the functions.
#
# All we now need to do is to retrieve the correct field(s) from the array.
#------------------------------------------------------------------------------
  for my $i (keys @function_index_list)
    {
      my $index_for_function = $function_index_list[$i];
      push (@final_html_function_block, $function_info[$index_for_function]{"html function block"});
    }
  for my $i (keys @final_html_function_block)
    {
      my $txt = "final_html_function_block[$i] = $final_html_function_block[$i]";
      gp_message ("debugXL", $subr_name, $txt);
    }

#------------------------------------------------------------------------------
# Since the numbers are right aligned, we know that any difference between the
# metric line length and the maximum must be caused by the first column.  All
# we need to do is to prepend spaces in case of a difference.
#
# While we have the line with the metric values, we also replace ZZZ by 3
# spaces.
#------------------------------------------------------------------------------
    for my $i (keys @metric_values)
      {
        if (length ($metric_values[$i]) < $max_metrics_length)
          {
            my $pad = $max_metrics_length - length ($metric_values[$i]);
            my $spaces = "";
            for my $s (1 .. $pad)
              {
                $spaces .= "&nbsp;";
              }
            $metric_values[$i] = $spaces . $metric_values[$i];
          }
          $metric_values[$i] =~ s/ZZZ/&nbsp;&nbsp;&nbsp;/g;
      }

#------------------------------------------------------------------------------
# Determine the column widths.  The start and end index of the words in the
# input line are stored in elements 0 and 1 of @word_index_values.
#
# The assumption made is that the first digit of a metric value on the first
# line is left # aligned with the header text.  These are the Total values
# and other than for some derived metrics, e.g. CPI, should be the largest.
#
# The positions of the start of the value is what we should then use for the
# word "(sort)" to start.
#
# For example:
#
# Excl.     Excl. CPU  Excl.         Excl.         Excl.  Excl.
# Total     Cycles     Instructions  Last-Level    IPC    CPI
# CPU sec.     sec.    Executed      Cache Misses
# 174.664   179.250    175838403203  1166209617    0.428   2.339
#------------------------------------------------------------------------------

    my $foundit_ref;
    my $foundit;
    my @index_values = ();
    my $index_values_ref;

#------------------------------------------------------------------------------
# Search for "Excl." in the top row.  The metric values are aligned with this
# word and we can use it to position "(sort)" in the last header line.
#
# In @index_values, we store the position(s) of "Excl." in the header line.
# If none can be found, an exception is raised because at least one should
# be there.
#
# TBD: Check if this can be done only once.
# ------------------------------------------------------------------------------
    my $target_keyword = "Excl.";

    ($foundit_ref, $index_values_ref) = find_keyword_in_string (
                                          \$remaining_part_header, 
                                          \$target_keyword);

    $foundit      = ${ $foundit_ref };
    @index_values = @{ $index_values_ref };

    if ($foundit) 
      {
        for my $i (keys @index_values)
          {
            my $txt = "index_values[$i] = $index_values[$i]";
            gp_message ("debugXL", $subr_name, $txt);
          }
      }
    else
      {
        my $msg = "keyword $target_keyword not found in $remaining_part_header";
        gp_message ("assertion", $subr_name, $msg);
      }

# ------------------------------------------------------------------------------
# Compute the number of spaces we need to add between the "(sort)" strings.
#
# For example:
#
# 01234567890123456789
#
# Excl.         Excl.
# (sort)        (sort)
#       xxxxxxxx
#
# The number of spaces required is 14 - 6 = 8.
#
# The number of spaces to be added is stored in @padding_values.  These are
# the spaces to be added before the occurrence of "(sort)".  This is why the
# first padding value is 0.
# ------------------------------------------------------------------------------

# ------------------------------------------------------------------------------
# TBD: This needs to be done only once.
# ------------------------------------------------------------------------------
    my @padding_values = ();
    my $P_previous     = 0;
    for my $i (keys @index_values)
      {
        my $L = $index_values[$i];
        my $P = $L + length ("(sort)");
        my $pad_spaces = $L - $P_previous;

        push (@padding_values, $pad_spaces);

        $P_previous = $P;
      }

    for my $i (keys @padding_values)
      {
        my $txt = "padding_values[$i] = $padding_values[$i]";
        gp_message ("debugXL", $subr_name, $txt);
      }
    
#------------------------------------------------------------------------------
# Build up the sort line.  Mark the current metric and make sure the line is
# aligned with the header.
#------------------------------------------------------------------------------
    my $sort_string = "(sort)";
    my $length_sort_string = length ($sort_string);
    my $sort_line = "";
    my @active_metrics = split (":", $summary_metrics);
    for my $i (0 .. $number_of_metrics-1)
      {
        my $pad          = $padding_values[$i];
        my $metric_value = $active_metrics[$i];

        my $spaces = "";
        for my $s (1 .. $pad)
          {
            $spaces .= "&nbsp;";
          }

        gp_message ("debugXL", $subr_name, "i = $i metric_value = $metric_value pad = $pad");

        if ($metric_value eq $exp_type)
#------------------------------------------------------------------------------
# The current metric should have a different background color.
#------------------------------------------------------------------------------
          {
            $sort_string = "<a href=\'" . $g_html_base_file_name{"function_view"} . 
                           "." . $metric_value . ".html' style='background-color:" . 
                           $g_html_color_scheme{"background_selected_sort"} . 
                           "\'><b>(sort)</b></a>";
          }
        elsif (($exp_type eq "functions") and ($metric_value eq $g_first_metric))
#------------------------------------------------------------------------------
# Set the background color for the sort metric in the main function overview. 
#------------------------------------------------------------------------------
          {
            $sort_string = "<a href=\'" . $g_html_base_file_name{"function_view"} . 
                           "." . $metric_value . ".html' style='background-color:" . 
                           $g_html_color_scheme{"background_selected_sort"} . 
                           "'><b>(sort)</b></a>";
          }
        else
#------------------------------------------------------------------------------
# Do not set a specific background for all other metrics.
#------------------------------------------------------------------------------
          {
            $sort_string = "<a href=\'" . $g_html_base_file_name{"function_view"} . 
                           "." . $metric_value . ".html'>(sort)</a>";
          }

#------------------------------------------------------------------------------
# Prepend the spaces to ensure correct alignment with the rest of the header.
#------------------------------------------------------------------------------
          $sort_line .= $spaces . $sort_string;
      }

    push (@header_lines, $sort_line);

#------------------------------------------------------------------------------
# Print the final results for the header and metrics.
#------------------------------------------------------------------------------
  for my $i (keys @header_lines)
    {
      gp_message ("debugXL", $subr_name, "header_lines[$i] = $header_lines[$i]");
    }
  for my $i (keys @metric_values)
    {
      gp_message ("debugXL", $subr_name, "metric_values[$i] = $metric_values[$i]");
    }

#------------------------------------------------------------------------------
# Construct the lines for the function overview.
#
# TBD: We could eliminate two structures here because metric_values and
# final_html_function_block are only copied and the result stored.
#------------------------------------------------------------------------------
   for my $i (keys @function_names)
      {
        push (@metrics_part, $metric_values[$i]);
        push (@function_view_array, $final_html_function_block[$i]);
      }

  for my $i (0 .. $#function_view_array)
    {
      my $msg = "function_view_array[$i] = $function_view_array[$i]";
      gp_message ("debugXL", $subr_name, $msg);
    }
#------------------------------------------------------------------------------
# Element "function table" contains the array with all the function view data. 
#------------------------------------------------------------------------------
  $function_view_structure{"header"}         = [@header_lines];
  $function_view_structure{"metrics part"}   = [@metrics_part];
  $function_view_structure{"function table"} = [@function_view_array];

  return (\%function_view_structure);

} #-- End of subroutine process_function_overview

#------------------------------------------------------------------------------
# TBD
#------------------------------------------------------------------------------
sub process_metrics
{
  my $subr_name = get_my_name ();

  my ($input_string, $sort_fields_ref, $metric_description_ref, $ignored_metrics_ref) = @_;

  my @sort_fields        = @{ $sort_fields_ref };
  my %metric_description = %{ $metric_description_ref };
  my %ignored_metrics    = %{ $ignored_metrics_ref };

  my $outputdir = append_forward_slash ($input_string);
  my $LANG      = $g_locale_settings{"LANG"};
  my $max_len   = 0;
  my $metric_comment;

  my ($imetricn,$outfile);
  my ($html_metrics_record,$imetric,$metric);

  $html_metrics_record =
    "<!doctype html public \"-//w3c//dtd html 3.2//EN\">\n<html lang=\"$LANG\">\n<head>\n" . 
    "<meta http-equiv=\"content-type\" content=\"text/html; charset=iso-8859-1\">\n" .
    "<title>Function Metrics</title></head><body lang=\"$LANG\" bgcolor=".$g_html_color_scheme{"background_color_page"}."<pre>\n";

  $outfile = $outputdir . "metrics.html";

  open (METRICSOUT, ">", $outfile) 
    or die ("$subr_name - unable to open file $outfile for writing - '$!'");
  gp_message ("debug", $subr_name, "opened file $outfile for writing");

  for $metric (@sort_fields)
    {
      $max_len = max ($max_len, length ($metric));
      gp_message ("debug", $subr_name, "sort_fields: metric = $metric max_len = $max_len");
    }

# TBD: Check this
#  for $imetric (@IMETRICS)
  for $imetric (keys %ignored_metrics)
    {
      $max_len = max ($max_len, length ($imetric));
      gp_message ("debug", $subr_name, "ignored_metrics imetric = $imetric max_len = $max_len");
    }

  $max_len++;

  gp_message ("debug", $subr_name, "max_len = $max_len");

  $html_metrics_record .= "<p style=\"font-size:14px;color:red\"> Metrics used (".($#sort_fields + 1).")\n</p><p style=\"font-size:14px\">";
  for $metric (@sort_fields)
    {
      my $description = ${ retrieve_metric_description (\$metric, \%metric_description) };
      gp_message ("debug", $subr_name, "handling metric metric = $metric->$description");
      $html_metrics_record .= "       $metric".(' ' x ($max_len - length ($metric)))."$description\n";
    }

#  $imetricn = scalar (keys %IMETRICS);
  $imetricn = scalar (keys %ignored_metrics);
  if ($imetricn) 
    {
      $html_metrics_record .= "</p><p style=\"font-size:14px;color:red\"> Metrics ignored ($imetricn)\n</p><p style=\"font-size:14px\">";
#      for $imetric (sort keys %IMETRICS){
      for $imetric (sort keys %ignored_metrics)
        {
              $metric_comment = "(inclusive, exclusive, and percentages)";
          $html_metrics_record .= "       $imetric".(' ' x ($max_len - length ($imetric))).$metric_comment."\n";
          gp_message ("debug", $subr_name, "handling metric imetric = $imetric $metric_comment");
        }
    }

  print METRICSOUT $html_metrics_record;
  print METRICSOUT $g_html_credits_line;
  close (METRICSOUT);

  gp_message ("debug", $subr_name, "closed metrics file $outfile");

  return (0);

} #-- End of subroutine process_metrics

#-------------------------------------------------------------------------------
# TBD
#-------------------------------------------------------------------------------
sub process_metrics_data
{
  my $subr_name = get_my_name ();

  my ($outfile1, $outfile2, $ignored_metrics_ref) = @_;

  my %ignored_metrics    = %{ $ignored_metrics_ref };

  my %metric_value       = ();
  my %metric_description = ();
  my %metric_found       = ();

  my $user_metrics;
  my $system_metrics;
  my $wall_metrics;
  my $metric_spec;
  my $metric_flavor;
  my $metric_visibility;
  my $metric_name;
  my $metric_text;
  my $metricdata;
  my $metric_line; 

  my $summary_metrics;
  my $detail_metrics;
  my $detail_metrics_system;
  my $call_metrics;

  if ($g_user_settings{"default_metrics"}{"current_value"} eq "off")
    {
      gp_message ("debug", $subr_name, "g_user_settings{default_metrics}{current_value} = " . $g_user_settings{"default_metrics"}{"current_value"});
  # get metrics

      $summary_metrics='';
      $detail_metrics='';
      $detail_metrics_system='';
      $call_metrics = '';
      $user_metrics=0;
      $system_metrics=0;
      $wall_metrics=0;

      my ($last_metric,$metric,$value,$i,$r);

      open (METRICTOTALS, "<", $outfile2) 
        or die ("Unable to open metric value data file $outfile2 for reading - '$!'");
      gp_message ("debug", $subr_name, "opened $outfile2 to parse metric value data");

#------------------------------------------------------------------------------
# Below an example of the file that has just been opened.  The lines I marked 
# with a * has been wrapped by my for readability.  This is not the case in the
# file, but makes for a really long line.
#
# Also, the data comes from one PC experiment and two HWC experiments.
#------------------------------------------------------------------------------
# <Total>
#              Exclusive Total CPU Time:      32.473 (100.0%)
#              Inclusive Total CPU Time:      32.473 (100.0%)
#                  Exclusive CPU Cycles:      23.586 (100.0%)
#                               " count: 47054706905
#                  Inclusive CPU Cycles:      23.586 (100.0%)
#                               " count: 47054706905
#       Exclusive Instructions Executed: 54417033412 (100.0%)
#       Inclusive Instructions Executed: 54417033412 (100.0%)
#     Exclusive Last-Level Cache Misses:   252730685 (100.0%)
#     Inclusive Last-Level Cache Misses:   252730685 (100.0%)
#  *   Exclusive Instructions Per Cycle:      Inclusive Instructions Per Cycle:      
#  *         Exclusive Cycles Per Instruction:      
#  *         Inclusive Cycles Per Instruction:                                  
#  *         Size:           0
#                            PC Address: 1:0x00000000
#                           Source File: (unknown)
#                           Object File: (unknown)
#                           Load Object: <Total>
#                          Mangled Name:
#                               Aliases:
#------------------------------------------------------------------------------

      while (<METRICTOTALS>)
        {
          $metricdata = $_; chomp ($metricdata);
          gp_message ("debug", $subr_name, "file metrictotals: $metricdata");

#------------------------------------------------------------------------------
# Ignoring whitespace, search for any line with a ":" in it, followed by 
# a number with or without a dot.  So, an integer or floating-point number.
#------------------------------------------------------------------------------
          if ($metricdata =~ /\s*(.*):\s+(\d+\.*\d*)/)
            {
              gp_message ("debug", $subr_name, "  candidate => $metricdata");
              $metric = $1;
              $value  = $2;
              if ( ($metric eq "PC Address") or ($metric eq "Size"))
                {
                  gp_message ("debug", $subr_name, "  skipped => $metric $value");
                  next;
                }
              gp_message ("debug", $subr_name, "  proceed => $metric $value");
              if ($metric eq '" count')
#------------------------------------------------------------------------------
# Hardware counter experiments have this info.  Note that this line is not the
# first one to be encountered, so $last_metric has been defined already.
#------------------------------------------------------------------------------
                {
                  $metric = $last_metric." Count"; # we presume .......
                  gp_message ("debug", $subr_name, "last_metric = $last_metric metric = $metric");
                }
              $i=index ($metricdata,":");
              $r=rindex ($metricdata,":");
              gp_message ("debug", $subr_name, "metricdata = $metricdata => i = $i r = $r");
              if ($i == $r)
                {
                  if ($value > 0) # Not interested in metrics contributing zero
                    {
                      $metric_value{$metric} = $value;
                      gp_message ("debug", $subr_name, "archived metric_value{$metric} = $metric_value{$metric}");
                      # e.g. $metric_value{Exclusive Total Thread Time} = 302.562
                      # e.g. $metric_value{Exclusive Instructions Executed} = 2415126222484
                    }
                }
              else
#------------------------------------------------------------------------------
# TBD This code deals with an old bug and may be removed.
#------------------------------------------------------------------------------
                { # er_print bug - e.g.
#  Exclusive Instructions Per Cycle:       Inclusive Instructions Per Cycle:       Exclusive Cycles Per Instruction:   Inclusive Cycles Per Instruction:             Exclusive OpenMP Work Time: 162.284 (100.0%)
                  gp_message ("debug", $subr_name, "metrictotals odd line:->$metricdata<-");
                  $r=rindex ($metricdata,":",$r-1);
                  if ($r == -1)
                    { # ignore
                      gp_message ("debug", $subr_name, "metrictotals odd line ignored<-");
                      $last_metric = "foo";
                      next;
                    }
                  my ($good_part)=substr ($metricdata,$r+1);
                  if ($good_part =~ /\s*(.*):\s+(\d+\.*\d*)/)
                    {
                      $metric = $1;
                      $value  = $2;
                      if ($value>0) # Not interested in metrics contributing zero
                        {
                          $metric_value{$metric} = $value;
                          my $msg = "metrictotals odd line rescued '$metric'=$value";
                          gp_message ("debug", $subr_name, $msg);
                        }
                    }
                }
#------------------------------------------------------------------------------
# Preserve the current metric.
#------------------------------------------------------------------------------
              $last_metric = $metric;
            }
        }
      close (METRICTOTALS);
    }

    if (scalar (keys %metric_value) == 0)
#------------------------------------------------------------------------------
# If we have no metrics > 0, fudge a "Exclusive Total CPU Time", else we 
# blow up later.
#
# TBD: See if this can be handled differently.
#------------------------------------------------------------------------------
      {
        $metric_value{"Exclusive Total CPU Time"} = 0;
        gp_message ("debug", $subr_name, "no metrics found and a stub was added");
      }

  for my $metric (sort keys %metric_value)
    {
      gp_message ("debug", $subr_name, "Stored metric_value{$metric} = $metric_value{$metric}");
    }

  gp_message ("debug", $subr_name, "proceed to process file $outfile1");

#------------------------------------------------------------------------------
# Open and process the metrics file.
#------------------------------------------------------------------------------
  open (METRICS, "<", $outfile1)
    or die ("Unable to open metrics file $outfile1: '$!'");
  gp_message ("debug", $subr_name, "opened file $outfile1 for reading");

#------------------------------------------------------------------------------
# Parse the file.  This is a typical example:
#
# Exp Sel Total
# === === =====
#   1 all     2
#   2 all     1
#   3 all     2
# Current metrics: e.totalcpu:i.totalcpu:e.cycles:e+insts:e+llm:name
# Current Sort Metric: Exclusive Total CPU Time ( e.totalcpu )
# Available metrics:
#          Exclusive Total CPU Time: e.%totalcpu
#          Inclusive Total CPU Time: i.%totalcpu
#              Exclusive CPU Cycles: e.+%cycles
#              Inclusive CPU Cycles: i.+%cycles
#   Exclusive Instructions Executed: e+%insts
#   Inclusive Instructions Executed: i+%insts
# Exclusive Last-Level Cache Misses: e+%llm
# Inclusive Last-Level Cache Misses: i+%llm
#  Exclusive Instructions Per Cycle: e+IPC
#  Inclusive Instructions Per Cycle: i+IPC
#  Exclusive Cycles Per Instruction: e+CPI
#  Inclusive Cycles Per Instruction: i+CPI
#                              Size: size
#                        PC Address: address
#                              Name: name
#------------------------------------------------------------------------------
  while (<METRICS>)
    {
      $metric_line = $_;
      chomp ($metric_line);

      gp_message ("debug", $subr_name, "processing line $metric_line");
#------------------------------------------------------------------------------
# The original regex has bugs because the line should not be allowed to start
# with a ":".  So this is wrong:
#  if (($metric =~ /\s*(.*):\s+(\S)((\.\S+)|(\+\S+))/) and !($metric =~/^Current/))
# 
# This is better:
#      if (($metric =~ /\s*(.+):\s+(\S)((\.\S+)|(\+\S+))/) and !($metric =~/^Current/))
#
# In general, this regex has some potential issues and has been replaced by
# the one shown below.
#
# We select a line that does not start with "Current" and aside from whitespace
# starts with anything (although it should be a string with words only),
# followed by whitespace and either an "e" or "i". This is called the "flavor"
# and is followed by a visibility marker (.,+,%, or !) and a metric name.
#------------------------------------------------------------------------------
# Ruud   if (($metric =~ /\s*(.*):\s+(\S)((\.\S+)|(\+\S+))/) && !($metric =~/^Current/)){

      ($metric_spec, $metric_flavor, $metric_visibility, $metric_name, $metric_text) = 
              extract_metric_specifics ($metric_line);

#      if (($metric_line =~ /\s*(.+):\s+([ei])([\.\+%]+)(\S*)/) and !($metric_line =~/^Current/))
      if ($metric_spec eq "skipped")
        {
          gp_message ("debug", $subr_name, "skipped line: $metric_line");
        }
      else
        {
          gp_message ("debug", $subr_name, "line of interest: $metric_line");

          $metric_found{$metric_spec} = 1;

          if ($g_user_settings{"ignore_metrics"}{"defined"})
            {
              gp_message ("debug", $subr_name, "check for $metric_spec");
              if (exists ($ignored_metrics{$metric_name}))
                {
                  gp_message ("debug", $subr_name, "user asked to ignore metric $metric_name");
                  next;
                }
              }

#------------------------------------------------------------------------------
# This metric is not on the ignored list and qualifies, so store it.
#------------------------------------------------------------------------------
          $metric_description{$metric_spec} = $metric_text;

# TBD: add for other visibilities too, like +
          gp_message ("debug", $subr_name, "stored $metric_description{$metric_spec}          = $metric_description{$metric_spec}");

          if ($metric_flavor ne "e")
            {
              gp_message ("debug", $subr_name, "metric $metric_spec is ignored");
            }
          else
#------------------------------------------------------------------------------
# Only the exclusive metrics are shown.
#------------------------------------------------------------------------------
            {
              gp_message ("debug", $subr_name, "metric $metric_spec ($metric_text) is considered");

              if ($metric_spec =~ /user/)
                {
                  $user_metrics = $TRUE;
                  gp_message ("debug", $subr_name, "m: user_metrics set to TRUE");
                } 
              elsif ($metric_spec =~ /system/)
                { 
                  $system_metrics = $TRUE;
                  gp_message ("debug", $subr_name, "m: system_metrics set to TRUE");
                } 
              elsif ($metric_spec =~ /wall/)
                {
                  $wall_metrics = $TRUE;
                  gp_message ("debug", $subr_name, "m: wall_metrics set to TRUE");
                } 
#------------------------------------------------------------------------------
# TBD I don't see why these need to be skipped.  Also, should be totalcpu.
#------------------------------------------------------------------------------
              elsif (($metric_spec =~ /^e\.total$/) or ($metric_spec =~/^e\.total_cpu$/))
                {
                # skip total thread time and total CPU time
                  gp_message ("debug", $subr_name, "m: skip above");
                }
              elsif (defined ($metric_value{$metric_text}))
                {
                  gp_message ("debug", $subr_name, "Total attributed to this metric metric_value{$metric_text} = $metric_value{$metric_text}");
                  if ($summary_metrics ne '')
                    {
                      $summary_metrics = $summary_metrics.':'.$metric_spec;
                      gp_message ("debug", $subr_name, "updated summary_metrics = $summary_metrics - 1");
                      if ($metric_spec !~ /\.wait$|\.ulock$|\.text$|\.data$|\.owait$|total$|mpiwork$|mpiwait$|ompwork$|ompwait$/)
                        {
                          $detail_metrics = $detail_metrics.':'.$metric_spec;
                          gp_message ("debug", $subr_name, "updated m:detail_metrics=$detail_metrics - 1");
                          $detail_metrics_system = $detail_metrics_system.':'.$metric_spec;
                          gp_message ("debug", $subr_name, "updated m:detail_metrics_system=$detail_metrics_system - 1");
                        } 
                      else
                        {
                          gp_message ("debug", $subr_name, "m: no want above metric for detail_metrics or detail_metrics_system");
                        }
                    } 
                  else 
                    {
                      $summary_metrics = $metric_spec;
                      gp_message ("debug", $subr_name, "initialized summary_metrics = $summary_metrics - 2");
                      if ($metric_spec !~ /\.wait$|\.ulock$|\.text$|\.data$|\.owait$|total$|mpiwork$|mpiwait$|ompwork$|ompwait$/)
                        {
                          $detail_metrics = $metric_spec;
                          gp_message ("debug", $subr_name, "m:detail_metrics=$detail_metrics - 2");
                          $detail_metrics_system = $metric_spec;
                          gp_message ("debug", $subr_name, "m:detail_metrics_system=$detail_metrics_system - 2");
                        } 
                      else 
                        {
                          gp_message ("debug", $subr_name, "m: no want above metric for detail_metrics or detail_metrics_system");
                        }
                    }
                  gp_message ("debug", $subr_name, " metric $metric_spec added");
                } 
              else 
                {
                  gp_message ("debug", $subr_name, "m: no want above metric was a 0 total");
                }
            } 
        }
    }

  close METRICS;

  if ($wall_metrics > 0)
    {
      gp_message ("debug", $subr_name,"m:wall_metrics set adding to summary_metrics");
      $summary_metrics = "e.wall:".$summary_metrics;
      gp_message ("debug", $subr_name,"m:summary_metrics=$summary_metrics - 3");
    }

  if ($system_metrics > 0)
    {
      gp_message ("debug", $subr_name,"m:system_metrics set adding to summary_metrics,call_metrics and detail_metrics_system");
      $summary_metrics       = "e.system:".$summary_metrics;
      $call_metrics          = "i.system:".$call_metrics;
      $detail_metrics_system ='e.system:'.$detail_metrics_system;

      gp_message ("debug", $subr_name,"m:summary_metrics=$summary_metrics - 4");
      gp_message ("debug", $subr_name,"m:call_metrics=$call_metrics");
      gp_message ("debug", $subr_name,"m:detail_metrics_system=$detail_metrics_system - 3");
    }


#------------------------------------------------------------------------------
# TBD: e.user and i.user do not always exist!!
#------------------------------------------------------------------------------

  if ($user_metrics > 0)
    {
      gp_message ("debug", $subr_name,"m:user_metrics set adding to summary_metrics,detail_metrics,detail_metrics_system and call_metrics");
# Ruud      if (!exists ($IMETRICS{"i.user"})){
      if ($g_user_settings{"ignore_metrics"}{"defined"} and exists ($ignored_metrics{"user"}))
        {
          $summary_metrics = "e.user:".$summary_metrics;
        }
      else 
        {
          $summary_metrics = "e.user:i.user:".$summary_metrics;
        }
      $detail_metrics        = "e.user:".$detail_metrics;
      $detail_metrics_system = "e.user:".$detail_metrics_system;

      gp_message ("debug", $subr_name,"m:summary_metrics=$summary_metrics - 5");
      gp_message ("debug", $subr_name,"m:detail_metrics=$detail_metrics - 3");
      gp_message ("debug", $subr_name,"m:detail_metrics_system=$detail_metrics_system - 4");

      if ($g_user_settings{"ignore_metrics"}{"defined"} and exists ($ignored_metrics{"user"}))
        {
          $call_metrics = "a.user:".$call_metrics;
        } 
      else 
        {
          $call_metrics = "a.user:i.user:".$call_metrics;
        }
      gp_message ("debug", $subr_name,"m:call_metrics=$call_metrics - 2");
    }

  if ($call_metrics eq "")
    {
      $call_metrics = $detail_metrics;

      gp_message ("debug", $subr_name,"m:call_metrics is not set, setting it to detail_metrics ");
      gp_message ("debug", $subr_name,"m:call_metrics=$call_metrics - 3");
    }

  for my $metric (sort keys %ignored_metrics)
    {
      if ($ignored_metrics{$metric})
        {
          gp_message ("debug", $subr_name, "active metric, but ignored: $metric");
        }

    }

  return (\%metric_value, \%metric_description, \%metric_found, $user_metrics, $system_metrics, $wall_metrics,
          $summary_metrics, $detail_metrics, $detail_metrics_system, $call_metrics);

} #-- End of subroutine process_metrics_data

#------------------------------------------------------------------------------
# Process source lines that are not part of the target function.
#
# Generate straightforward HTML, but define an anchor based on the source line
# number in the list.
#------------------------------------------------------------------------------
sub process_non_target_source
{
  my $subr_name = get_my_name ();

  my ($start_scan, $end_scan, 
      $src_times_regex, $function_regex, $number_of_metrics,
      $file_contents_ref, $modified_html_ref) = @_;

  my @file_contents = @{ $file_contents_ref };
  my @modified_html = @{ $modified_html_ref };
  my $colour_code_line = $FALSE;
  my $input_line;
  my $line_id;
  my $modified_line;

#------------------------------------------------------------------------------
# Main loop to parse all of the source code and take action as needed.
#------------------------------------------------------------------------------
  for (my $line_no=$start_scan; $line_no <= $end_scan; $line_no++)
    {
      $input_line = $file_contents[$line_no];

#------------------------------------------------------------------------------
# Generate straightforward HTML, but define an anchor based on the source line
# number in the list.
#------------------------------------------------------------------------------
      $line_id = extract_source_line_number ($src_times_regex, 
                                             $function_regex, 
                                             $number_of_metrics, 
                                             $input_line);

      if ($input_line =~ /$function_regex/)
        {
          $colour_code_line = $TRUE;
        }

#------------------------------------------------------------------------------
# We need to replace the "<" symbol in the code by "&lt;".
#------------------------------------------------------------------------------
      $input_line =~ s/$g_less_than_regex/$g_html_less_than_regex/g;

#------------------------------------------------------------------------------
# Add an id.
#------------------------------------------------------------------------------
      $modified_line = "<a id=\"line_" . $line_id . "\"></a>";

      my $coloured_line; 
      if ($colour_code_line)
        {
          my $boldface = $TRUE;
          $coloured_line = color_string (
                             $input_line, 
                             $boldface, 
                             $g_html_color_scheme{"non_target_function_name"});
          $colour_code_line = $FALSE;
          $modified_line .= "$coloured_line";
        }
      else
        {
          $modified_line .= "$input_line";
        }
      gp_message ("debugXL", $subr_name, " $line_no : modified_line = $modified_line");
      push (@modified_html, $modified_line);
    }

  return (\@modified_html);

} #-- End of subroutine process_non_target_source

#------------------------------------------------------------------------------
# This function scans the configuration file and adapts the internal settings
# accordingly.
#
# Errors are stored during the parsing and processing phase.  They are printed
# at the end and sorted by line number.
#------------------------------------------------------------------------------
sub process_rc_file
{
  my $subr_name = get_my_name ();

  my ($rc_file_name, $rc_file_paths_ref) = @_;

#------------------------------------------------------------------------------
# Local structures.
#------------------------------------------------------------------------------
  my %rc_settings_user = ();  #-- Store the values extracted from the config file
  my %error_and_warning_msgs = ();
  my @rc_file_paths = (); 

  my @split_line;
  my @my_fields;

  my $message;
  my $first_part; 
  my $line;
  my $line_number;
  my $number_of_fields; 
  my $number_of_paths; 
  my $parse_errors;   #-- Count the number of errors
  my $parse_warnings; #-- Count the number of errors

  my $rc_config_file;
  my $rc_file_found;
  my $rc_keyword;
  my $rc_value;

  @rc_file_paths   = @{$rc_file_paths_ref};
  $number_of_paths = scalar (@rc_file_paths);

  if ($number_of_paths == 0)
#------------------------------------------------------------------------------
# This should not happen, but is a good safety net to add.
#------------------------------------------------------------------------------
    {
      my $msg = "search path list is empty";
      gp_message ("assertion", $subr_name, $msg);
    }

#------------------------------------------------------------------------------
# Check for the presence of a configuration file.
#------------------------------------------------------------------------------
  gp_message ("debug", $subr_name, "number_of_paths = $number_of_paths rc_file_paths = @rc_file_paths");

  $rc_file_found = $FALSE;
  for my $path_name (@rc_file_paths)
    {
      $rc_config_file = $path_name . "/" . $rc_file_name;
      gp_message ("debug", $subr_name, "looking for configuration file $rc_config_file");
      if (-f $rc_config_file) 
        {
          gp_message ("debug", $subr_name, "found configuration file $rc_config_file");
          $rc_file_found  = $TRUE;
          last;
        }
    }

  if (not $rc_file_found)
#------------------------------------------------------------------------------
# There is no configuration file and we can skip this subroutine.
#------------------------------------------------------------------------------
    {
      gp_message ("verbose", $subr_name, "Configuration file $rc_file_name not found");
      return (0);
    }
  else
    {
      open (GP_DISPLAY_HTML_RC, "<", "$rc_config_file")
        or die ("$subr_name - unable to open file $rc_config_file for reading: $!");
#------------------------------------------------------------------------------
# The configuration file has been opened for reading.
#------------------------------------------------------------------------------
      gp_message ("debug", $subr_name, "file $rc_config_file has been opened for reading");
    }

  gp_message ("verbose", $subr_name, "Found configuration file $rc_config_file");
  gp_message ("debug",   $subr_name, "processing configuration file $rc_config_file");

#------------------------------------------------------------------------------
# Here we scan the configuration file for the settings.
#
# A setting consists of a keyword, optionally followed by a value.  It is
# optional because not all keywords may require a value.
#
# At the end of this block, all keyword/value pairs are stored in a hash.
#
# We do not yet check for the validity of these pairs. This is done next.
#
# The original code had this all integrated, but it made the code very
# complex with deeply nested if-statements. The flow was also hard to follow.
#------------------------------------------------------------------------------
  $parse_errors   = 0;
  $parse_warnings = 0;
  $line_number    = 0;
  while (my $line = <GP_DISPLAY_HTML_RC>)
    {
      chomp ($line);
      $line_number++;

      gp_message ("debug", $subr_name, "read input line = $line");

#------------------------------------------------------------------------------
# Ignore a line with whitespace only
#------------------------------------------------------------------------------
      if ($line =~ /^\s*$/)
        {
          gp_message ("debug", $subr_name, "ignored a line with whitespace");
          next;
        }

#------------------------------------------------------------------------------
# Ignore a comment line, defined by starting with a "#", possibly prepended by
# whitespace.
#------------------------------------------------------------------------------
      if ($line =~ /^\s*\#/)
        {
          gp_message ("debug", $subr_name, "ignored a full comment line");
          next;
        }

#------------------------------------------------------------------------------
# Split the input line using the "#" symbol as a separator.  We have already 
# handled the case of an isolated comment line, so there may only be an 
# embedded comment.
#
# Regardless of this, we are only interested in the first part.
#------------------------------------------------------------------------------
      @split_line = split ("#", $line);

      for my $i (@split_line)
        {
          gp_message ("debug", $subr_name, "elements after split of line: $i");
        }

      $first_part = $split_line[0];
      gp_message ("debug", $subr_name, "relevant part = $first_part");

      if ($first_part =~ /[&\^\*\@\$]+/)
#------------------------------------------------------------------------------
# The &, ^, *, @ and $ symbols should not occur.  If they do, we flag an error
# an fetch the next line.
#------------------------------------------------------------------------------
        {
          $parse_errors++;
          $message = "non-supported character(s) (\&,\^,\*,\@,\$) found: $line"; 
          $error_and_warning_msgs{"error"}{$line_number}{"message"} = $message;
          next;
        }
      else
#------------------------------------------------------------------------------
# Split the first part on whitespace and verify the number of fields to be
# valid.  Although we currently only have keywords with a value, a keyword
# without value is supported to.
#
# If the number of fields is valid, the keyword and value are stored.  In case
# of a single field, the value is assigned a special string.
#
# Although this situation should not occur, we do abort if something unexpected
# is encountered here.
#------------------------------------------------------------------------------
        {
          @my_fields = split (/\s/, $split_line[0]);

          $number_of_fields = scalar (@my_fields);
          gp_message ("debug", $subr_name, "number of fields = $number_of_fields");
        }

      if ($number_of_fields ge 3) 
#------------------------------------------------------------------------------
# This is not supported.
#------------------------------------------------------------------------------
        {
          $parse_errors++;
          $message = "more than 2 fields found: $first_part"; 
          $error_and_warning_msgs{"error"}{$line_number}{"message"} = $message;
          next;
        }
      elsif ($number_of_fields eq 2)
        {
          $rc_keyword = $my_fields[0];
          $rc_value   = $my_fields[1];
        }
      elsif ($number_of_fields eq 1)
        {
          $rc_keyword = $my_fields[0];
          $rc_value   = "the_field_is_empty";
        }
      else
        {
          my $msg = "[line $line_number] $rc_config_file - number of fields = $number_of_fields";
          gp_message ("assertion", $subr_name, $msg);
        }

#------------------------------------------------------------------------------
# Store the keyword, value and line number. 
#------------------------------------------------------------------------------
      if (exists ($rc_settings_user{$rc_keyword}))
        {
          $parse_warnings++;
          my $prev_value = $rc_settings_user{$rc_keyword}{"value"};
          my $prev_line_number = $rc_settings_user{$rc_keyword}{"line_no"};
          if ($rc_value ne $prev_value)
            {
              $message = "option $rc_keyword previously set at line $prev_line_number: new value '$rc_value' overrides '$prev_value'";
            }
          else
            {
              $message = "option $rc_keyword previously set to the same value at line $prev_line_number";
            }
          $error_and_warning_msgs{"warning"}{$line_number}{"message"} = $message;
        }
      $rc_settings_user{$rc_keyword}{"value"}   = $rc_value;
      $rc_settings_user{$rc_keyword}{"line_no"} = $line_number;

      gp_message ("debug", $subr_name, "stored keyword     = $rc_keyword"); 
      gp_message ("debug", $subr_name, "stored value       = $rc_value"); 
      gp_message ("debug", $subr_name, "stored line number = $line_number"); 
    }

#------------------------------------------------------------------------------
# Completed the parsing of the configuration file. It can be closed.
#------------------------------------------------------------------------------
  close (GP_DISPLAY_HTML_RC);

#------------------------------------------------------------------------------
# Print the raw input as just collected from the configuration file.
#------------------------------------------------------------------------------
  gp_message ("debug", $subr_name, "contents of %rc_settings_user:");
  for my $keyword (keys %rc_settings_user)
    {
      my $key_value = $rc_settings_user{$keyword}{"value"};
      gp_message ("debug", $subr_name, "keyword = $keyword value = $key_value");
    }

  for my $rc_keyword  (keys %g_user_settings)
    {
       for my $fields (keys %{ $g_user_settings{$rc_keyword} })
         {
           gp_message ("debug", $subr_name, "before config file: $rc_keyword $fields = $g_user_settings{$rc_keyword}{$fields}");
         }
    }

#------------------------------------------------------------------------------
# We are almost done.  Check for all keywords found whether they are valid.  
# Also verify that the corresponding value is valid.
#
# Update the g_user_settings table if everything is okay.
#------------------------------------------------------------------------------

  for my $rc_keyword (keys %rc_settings_user)
    {
      my $rc_value = $rc_settings_user{$rc_keyword}{"value"};

      if (exists ( $g_user_settings{$rc_keyword}))
        {

#------------------------------------------------------------------------------
# This is a supported keyword.  There are two more things left to do:
# - Check how many values it requires (currently exactly one is supported)
# - Is the value a valid number or string?
#------------------------------------------------------------------------------
          my $no_of_arguments = $g_user_settings{$rc_keyword}{"no_of_arguments"};

          if ($no_of_arguments eq 1)
            {
              my $input_value = $rc_value;
              if ($input_value ne "the_field_is_empty")
#
#------------------------------------------------------------------------------
# So far, so good.  We only need to check if the value is valid for the keyword.
#------------------------------------------------------------------------------
                {
                  my $data_type   = $g_user_settings{$rc_keyword}{"data_type"};
                  my $valid_input = verify_if_input_is_valid ($input_value, $data_type);
#------------------------------------------------------------------------------
# Check if the value is valid.
#------------------------------------------------------------------------------
                  if ($valid_input)
                    {
                      $g_user_settings{$rc_keyword}{"current_value"} = $rc_value;
                      $g_user_settings{$rc_keyword}{"defined"}  = $TRUE;
                    }
                  else
                    {
                      $parse_errors++;
                      $line_number = $rc_settings_user{$rc_keyword}{"line_no"};
                      $message = "input value '$input_value' for keyword $rc_keyword is not valid";
                      $error_and_warning_msgs{"error"}{$line_number}{"message"} = $message;
                      next;
                    }
                }
              else
#------------------------------------------------------------------------------
# This keyword requires a value, but none has been found.
#------------------------------------------------------------------------------
                {
                  $parse_errors++;
                  $line_number = $rc_settings_user{$rc_keyword}{"line_no"};
                  $message = "missing value for keyword '$rc_keyword'";
                  $error_and_warning_msgs{"error"}{$line_number}{"message"} = $message;
                  next;
                }
            }
          elsif ($no_of_arguments eq 0)
#------------------------------------------------------------------------------
# Currently a theoretical scenario since all commands require a value, but in
# case this is no longer true, we need to at least flag the fact the user set
# this command.
#------------------------------------------------------------------------------
            {
              $g_user_settings{$rc_keyword}{"defined"}  = $TRUE;
            }
          else
#------------------------------------------------------------------------------
# The code is not prepared for the situation one command has multiple values,
# but this situation should never occur. Still it won't hurt to add a check.
#------------------------------------------------------------------------------
            {
               my $msg = "cannot handle $no_of_arguments in the input";
               gp_message ("assertion", $subr_name, $msg);
            }
        }
      else
#------------------------------------------------------------------------------
# A non-valid keyword is found. This is flagged as an error.
#------------------------------------------------------------------------------
        {
          $parse_errors++;
          $line_number = $rc_settings_user{$rc_keyword}{"line_no"};
          $message = "keyword $rc_keyword is not supported";
          $error_and_warning_msgs{"error"}{$line_number}{"message"} = $message;
        }
    }
  for my $rc_keyword  (keys %g_user_settings)
    {
       for my $fields (keys %{ $g_user_settings{$rc_keyword} })
         {
           gp_message ("debug", $subr_name, "after config file: $rc_keyword $fields = $g_user_settings{$rc_keyword}{$fields}");
         }
    }
  print_table_user_settings ("debug", "upon the return from $subr_name");

  if ( ($parse_errors == 0) and ($parse_warnings == 0) )
    {
      gp_message ("verbose", $subr_name, "Successfully parsed and processed the configuration file");
    }
  else
    {
      if ($parse_errors > 0)
        {
          my $plural_or_single = ($parse_errors > 1) ? "errors" : "error";
          $message = $g_error_keyword . "found $parse_errors fatal $plural_or_single in the configuration file:";
          gp_message ("debug", $subr_name, $message);
#------------------------------------------------------------------------------
# Sort the hash keys, the line numbers, alphabetically and print the 
# corresponding error messages.
#------------------------------------------------------------------------------
          for my $line_no (sort {$a <=> $b} (keys %{ $error_and_warning_msgs{"error"} }))
            {
              $message  = $g_error_keyword. "[line $line_no] in file $rc_config_file - ";
              $message .= $error_and_warning_msgs{"error"}{$line_no}{"message"};
              gp_message ("debug", $subr_name, $message);
            }
        }

      if (not $g_quiet)
        {
          if ($parse_warnings > 0)
            {
              $message = $g_warn_keyword . "found $parse_warnings warnings in the configuration file:";
              gp_message ("debug", $subr_name, $message);
              for my $line_no (sort {$a <=> $b} (keys %{ $error_and_warning_msgs{"warning"} }))
                {
                  $message = $g_warn_keyword . "[line $line_no] in file $rc_config_file - ";
                  $message .= $error_and_warning_msgs{"warning"}{$line_no}{"message"};
                  gp_message ("debug", $subr_name, $message);
                }
            }
        }
    }

  return ($parse_errors);

} #-- End of subroutine process_rc_file

#------------------------------------------------------------------------------
# Generate the annotated html file for the source listing.
#------------------------------------------------------------------------------
sub process_source
{
  my $subr_name = get_my_name ();

  my ($number_of_metrics, $function_info_ref, 
      $outputdir, $input_filename) = @_;

  my @function_info = @{ $function_info_ref };

#------------------------------------------------------------------------------
# The regex section
#------------------------------------------------------------------------------
  my $end_src1_header_regex = '(^\s+)(\d+)\.\s+(.*)';
  my $end_src2_header_regex = '(^\s+)(<Function: )(.*)>';
  my $function_regex        = '^(\s*)<Function:\s(.*)>';
  my $function2_regex       = '^(\s*)&lt;Function:\s(.*)>';
  my $src_regex             = '(\s*)(\d+)\.(.*)';
  my $txt_ext_regex         = '\.txt$';
  my $src_filename_id_regex = '^file\.(\d+)\.src\.txt$';
  my $integer_only_regex    = '\d+';
#------------------------------------------------------------------------------
# Computed dynamically below.
# TBD: Try to move this up.
#------------------------------------------------------------------------------
  my $src_times_regex; 
  my $hot_lines_regex; 
  my $metric_regex; 
  my $metric_extra_regex;

  my @components = (); 
  my @fields_in_line = ();
  my @file_contents = ();
  my @hot_source_lines  = ();
  my @max_metric_values = ();
  my @modified_html = ();
  my @transposed_hot_lines = ();

  my $colour_coded_line; 
  my $colour_coded_line_ref; 
  my $line_id;
  my $ignore_value;
  my $func_name_in_src_file; 
  my $html_new_line = "<br>";
  my $input_line; 
  my $metric_values;
  my $modified_html_ref; 
  my $modified_line; 
  my $is_empty;
  my $start_all_source;
  my $start_target_source;
  my $end_target_source;
  my $output_line; 
  my $hot_line;
  my $src_line_no;
  my $src_code_line; 

  my $decimal_separator = $g_locale_settings{"decimal_separator"};
  my $hp_value = $g_user_settings{"highlight_percentage"}{"current_value"};
 
  my $file_title;
  my $found_target; 
  my $html_dis_record; 
  my $html_end; 
  my $html_header;
  my $html_home; 
  my $rounded_percentage; 
  my $start_tracking; 
  my $threshold_line; 

  my $base;
  my $boldface;
  my $msg;
  my $routine;

  my $LANG      = $g_locale_settings{"LANG"};
  my $the_title = set_title ($function_info_ref, $input_filename, 
                             "process source");
  my $outfile   = $input_filename . ".html";

#------------------------------------------------------------------------------
# Remove the .txt from file.<n>.src.txt
#------------------------------------------------------------------------------
  my $html_output_file  = $input_filename;
  $html_output_file     =~ s/$txt_ext_regex/.html/; 

  gp_message ("debug", $subr_name, "input_filename = $input_filename");
  gp_message ("debug", $subr_name, "the_title = $the_title");

  $file_title  = $the_title;
  $html_header = ${ create_html_header (\$file_title) };
  $html_home   = ${ generate_home_link ("right") };

  push (@modified_html, $html_header);
  push (@modified_html, $html_home);
  push (@modified_html, "<pre>");

#------------------------------------------------------------------------------
# Open the html file used for the output.
#------------------------------------------------------------------------------
  open (NEW_HTML, ">", $html_output_file)
    or die ("$subr_name - unable to open file $html_output_file for writing: '$!'");
  gp_message ("debug", $subr_name , "opened file $html_output_file for writing");

  $base = get_basename ($input_filename);

  gp_message ("debug", $subr_name, "base = $base");

  if ($base =~ /$src_filename_id_regex/)
    {
      my $file_id = $1;
      if (defined ($function_info[$file_id]{"routine"}))
        {
          $routine = $function_info[$file_id]{"routine"};

          gp_message ("debugXL", $subr_name, "target routine = $routine");
        }
      else
        {
          my $msg = "cannot retrieve routine name for file_id = $file_id";
          gp_message ("assertion", $subr_name, $msg);
        }
    }

#------------------------------------------------------------------------------
# Check if the input file is empty.  If so, generate a short text in the html
# file and return.  Otherwise open the file and read the contents.
#------------------------------------------------------------------------------
  $is_empty = is_file_empty ($input_filename);

  if ($is_empty)
    {
#------------------------------------------------------------------------------
# The input file is empty. Write a diagnostic message in the html file and exit.
#------------------------------------------------------------------------------
      gp_message ("debug", $subr_name ,"file $input_filename is empty");

      my $comment = "No source listing generated by $tool_name - " .
                    "file $input_filename is empty";
      my $error_file = $outputdir . "gp-listings.err";

      my $html_empty_file_ref = html_text_empty_file (\$comment, \$error_file);
      my @html_empty_file     = @{ $html_empty_file_ref };

      print NEW_HTML "$_\n" for @html_empty_file;

      close NEW_HTML;

      return (0);
    }
  else
#------------------------------------------------------------------------------
# Open the input file with the source code
#------------------------------------------------------------------------------
    {
      open (SRC_LISTING, "<", $input_filename) 
        or die ("$subr_name - unable to open file $input_filename for reading: '$!'");
      gp_message ("debug", $subr_name, "opened file $input_filename for reading");
    }

#------------------------------------------------------------------------------
# Generate the regex for the metrics.  This depends on the number of metrics.
#------------------------------------------------------------------------------
  gp_message ("debug", $subr_name, "decimal_separator = $decimal_separator<--");

  $metric_regex = '';
  $metric_extra_regex = '';
  for my $metric_used (1 .. $number_of_metrics)
    {
      $metric_regex .= '(\d+' . $decimal_separator . '*\d*)\s+';
    }
  $metric_extra_regex = $metric_regex . '(\d+' . $decimal_separator . ')';

  $hot_lines_regex = '^(#{2})\s+';
  $hot_lines_regex .= '('.$metric_regex.')';
  $hot_lines_regex .= '([0-9?]+)\.\s+(.*)';

  $src_times_regex = '^(#{2}|\s{2})\s+';
  $src_times_regex .= '('.$metric_extra_regex.')';
  $src_times_regex .= '(.*)';

  gp_message ("debugXL", $subr_name, "metric_regex   = $metric_regex");
  gp_message ("debugXL", $subr_name, "hot_lines_regex = $hot_lines_regex");
  gp_message ("debugXL", $subr_name, "src_times_regex = $src_times_regex");
  gp_message ("debugXL", $subr_name, "src_regex      = $src_regex");

  gp_message ("debugXL", $subr_name, "end_src1_header_regex = $end_src1_header_regex");
  gp_message ("debugXL", $subr_name, "end_src2_header_regex = $end_src2_header_regex");
  gp_message ("debugXL", $subr_name, "function_regex = $function_regex");
  gp_message ("debugXL", $subr_name, "function2_regex = $function2_regex");
  gp_message ("debugXL", $subr_name, "src_regex = $src_regex");

#------------------------------------------------------------------------------
# Read the file into memory.
#------------------------------------------------------------------------------
  chomp (@file_contents = <SRC_LISTING>);

#------------------------------------------------------------------------------
# Identify the header lines.  Make the minimal assumptions.
#
# In both cases, the first line after the header has whitespace.  This is
# followed by either one of the following:
#
# - <line_no>. 
# - <Function:
#
# These are the characteristics we use below.
#------------------------------------------------------------------------------
  for (my $line_number=0; $line_number <= $#file_contents; $line_number++)
    {
      $input_line = $file_contents[$line_number];

#------------------------------------------------------------------------------
# We found the first source code line.  Bail out.
#------------------------------------------------------------------------------
      if (($input_line =~ /$end_src1_header_regex/) or
          ($input_line =~ /$end_src2_header_regex/))
        {
          gp_message ("debugXL", $subr_name, "header time is over - hit source line");
          gp_message ("debugXL", $subr_name, "line_number = $line_number");
          gp_message ("debugXL", $subr_name, "input_line = $input_line");
          last;
        }
      else
#------------------------------------------------------------------------------
# Store the header lines in the html structure.
#------------------------------------------------------------------------------
        {
          $modified_line = "<i>" . $input_line . "</i>";
          push (@modified_html, $modified_line); 
        }
    }
#------------------------------------------------------------------------------
# We know the source code starts at this index value:
#------------------------------------------------------------------------------
  $start_all_source = scalar (@modified_html);
  gp_message ("debugXL", $subr_name, "source starts at start_all_source = $start_all_source");

#------------------------------------------------------------------------------
# Scan the file to identify where the target source starts and ends.
#------------------------------------------------------------------------------
  gp_message ("debugXL", $subr_name, "search for target function $routine");
  $start_tracking = $FALSE;
  $found_target   = $FALSE;
  for (my $line_number=0; $line_number <= $#file_contents; $line_number++)
    {
      $input_line = $file_contents[$line_number];

      gp_message ("debugXL", $subr_name, "[$line_number] $input_line");

      if ($input_line =~ /$function_regex/)
        {
          if (defined ($1) and defined ($2))
            {
              $func_name_in_src_file = $2;
              my $msg = "found a function - name = $func_name_in_src_file";
              gp_message ("debugXL", $subr_name, $msg);

              if ($start_tracking)
                {
                  $start_tracking = $FALSE;
                  $end_target_source = $line_number - 1;
                  my $msg =  "end_target_source = $end_target_source";
                  gp_message ("debugXL", $subr_name, $msg);
                  last;
                }

              if ($func_name_in_src_file eq $routine)
                {
                  $found_target        = $TRUE;
                  $start_tracking      = $TRUE;
                  $start_target_source = $line_number;

                  gp_message ("debugXL", $subr_name, "found target function $routine");
                  gp_message ("debugXL", $subr_name, "function_name = $2 routine = $routine");
                  gp_message ("debugXL", $subr_name, "routine = $routine start_tracking = $start_tracking"); 
                  gp_message ("debugXL", $subr_name, "start_target_source = $start_target_source");
                }
            }
          else
            {
              my $msg = "parsing line $input_line";
              gp_message ("assertion", $subr_name, $msg);
            }
        }
    }

#------------------------------------------------------------------------------
# This is not supposed to happen, but it is not a fatal error either.  The
# hyperlinks related to this function will not work, so a warning is issued.
# A message is issued both in debug mode, and as a warning.
#------------------------------------------------------------------------------
  if (not $found_target)
    {
      my $msg; 
      gp_message ("debug", $subr_name, "target function $routine not found");

      $msg = "function $routine not found in $base - " .
             "links to source code involving this function will not work";
      gp_message ("warning", $subr_name, $msg);

      return ($found_target);
    }

#------------------------------------------------------------------------------
# Catch the line number of the last function.
#------------------------------------------------------------------------------
  if ($start_tracking)
    {
      $end_target_source = $#file_contents;
    }
  gp_message ("debugXL", $subr_name, "routine = $routine start_tracking = $start_tracking"); 
  gp_message ("debugXL", $subr_name, "start_target_source = $start_target_source"); 
  gp_message ("debugXL", $subr_name, "end_target_source   = $end_target_source");

#------------------------------------------------------------------------------
# We now have the index range for the function of interest and will parse it.
# Since we already handled the first line with the function marker, we start
# with the line following.
#------------------------------------------------------------------------------

#------------------------------------------------------------------------------
# Find the hot source lines and store them.
#------------------------------------------------------------------------------
  gp_message ("debugXL", $subr_name, "determine the maximum metric values");
  for (my $line_number=$start_target_source+1; $line_number <= $end_target_source; $line_number++)
    {
      $input_line = $file_contents[$line_number];
      gp_message ("debugXL", $subr_name, " $line_number : check input_line = $input_line");

      if ( $input_line =~ /$hot_lines_regex/ )
        {
          gp_message ("debugXL", $subr_name, " $line_number : found a hot line");
#------------------------------------------------------------------------------
# We found a hot line and the metric fields are stored in $2.  We turn this   
# string into an array and add it as a row to hot_source_lines.
#------------------------------------------------------------------------------
              $hot_line      = $1;
              $metric_values = $2;

              gp_message ("debugXL", $subr_name, "hot_line = $hot_line");
              gp_message ("debugXL", $subr_name, "metric_values = $metric_values");

              my @metrics = split (" ", $metric_values);
              push (@hot_source_lines, [@metrics]);
        }
      gp_message ("debugXL", $subr_name, " $line_number : completed check for hot line");
    }

#------------------------------------------------------------------------------
# Transpose the array with the hot lines.  This means each row has all the
# values for a metrict and it makes it easier to determine the maximum values.
#------------------------------------------------------------------------------
  for my $row (keys @hot_source_lines)
    {
      my $msg = "row[" . $row . "] = ";
      for my $col (keys @{$hot_source_lines[$row]})
        {
          $msg .= "$hot_source_lines[$row][$col] ";
          $transposed_hot_lines[$col][$row] = $hot_source_lines[$row][$col];
        }
    }

#------------------------------------------------------------------------------
# Print the maximum metric values found.  Each row contains the data for a
# different metric.
#------------------------------------------------------------------------------
  for my $row (keys @transposed_hot_lines)
    {
      my $msg = "row[" . $row . "] = ";
      for my $col (keys @{$transposed_hot_lines[$row]})
        {
          $msg .= "$transposed_hot_lines[$row][$col] ";
        }
      gp_message ("debugXL", $subr_name, "hot lines = $msg");
    }

#------------------------------------------------------------------------------
# Determine the maximum value for each metric.
#------------------------------------------------------------------------------
  for my $row (keys @transposed_hot_lines)
    {
      my $max_val = 0;
      for my $col (keys @{$transposed_hot_lines[$row]})
        {
          $max_val = max ($transposed_hot_lines[$row][$col], $max_val);
        }
#------------------------------------------------------------------------------
# Convert to a floating point number.
#------------------------------------------------------------------------------
      if ($max_val =~ /$integer_only_regex/)
        {
          $max_val = sprintf ("%f", $max_val);
        }
      push (@max_metric_values, $max_val);
    }

    for my $metric (keys @max_metric_values)
      {
        my $msg = "$input_filename max_metric_values[$metric] = " .
                  $max_metric_values[$metric];
        gp_message ("debugXL", $subr_name, $msg);
      }

#------------------------------------------------------------------------------
# Process those functions that are not the current target.
#------------------------------------------------------------------------------
  $modified_html_ref = process_non_target_source ($start_all_source, 
                                                  $start_target_source-1,
                                                  $src_times_regex,
                                                  $function_regex, 
                                                  $number_of_metrics, 
                                                  \@file_contents,
                                                  \@modified_html);
  @modified_html = @{ $modified_html_ref };

#------------------------------------------------------------------------------
# This is the core part to process the information for the target function.
#------------------------------------------------------------------------------
  gp_message ("debugXL", $subr_name, "parse and process the target source");
  $modified_html_ref = process_target_source ($start_target_source,
                                              $end_target_source,
                                              $routine,
                                              \@max_metric_values,
                                              $src_times_regex,
                                              $function2_regex, 
                                              $number_of_metrics, 
                                              \@file_contents,
                                              \@modified_html);
  @modified_html = @{ $modified_html_ref };

  if ($end_target_source < $#file_contents)
    {
      $modified_html_ref = process_non_target_source ($end_target_source+1,
                                                      $#file_contents,
                                                      $src_times_regex,
                                                      $function_regex, 
                                                      $number_of_metrics, 
                                                      \@file_contents,
                                                      \@modified_html);
      @modified_html = @{ $modified_html_ref };
    }

  gp_message ("debug", $subr_name, "completed reading source");

#------------------------------------------------------------------------------
# Add an extra line with diagnostics.
#
# TBD: The same is done in generate_dis_html but should be done only once.
#------------------------------------------------------------------------------
  if ($hp_value > 0) 
    {
      my $rounded_percentage = sprintf ("%.1f", $hp_value);
      $threshold_line = "<i>The setting for the highlight percentage (-hp) option: $rounded_percentage (%)</i>";
    }
  else
    {
      $threshold_line = "<i>The highlight percentage (-hp) feature is not enabled</i>";
    }

  $html_home = ${ generate_home_link ("left") };
  $html_end  = ${ terminate_html_document () };

  push (@modified_html, "</pre>");
  push (@modified_html, "<br>");
  push (@modified_html, $threshold_line);
  push (@modified_html, $html_home);
  push (@modified_html, "<br>");
  push (@modified_html, $g_html_credits_line);
  push (@modified_html, $html_end);

  for my $i (0 .. $#modified_html)
    {
      gp_message ("debugXL", $subr_name, "[$i] -> $modified_html[$i]");
    }

#------------------------------------------------------------------------------
# Write the generated HTML text to file.
#------------------------------------------------------------------------------
  for my $i (0 .. $#modified_html)
    {
      print NEW_HTML "$modified_html[$i]" . "\n";
    }
  close (NEW_HTML);
  close (SRC_LISTING);
  
  return ($found_target);

} #-- End of subroutine process_source

#------------------------------------------------------------------------------
# Process the source lines for the target function.
#------------------------------------------------------------------------------
sub process_target_source
{
  my $subr_name = get_my_name ();

  my ($start_scan, $end_scan, $target_function, $max_metric_values_ref,
      $src_times_regex, $function2_regex, $number_of_metrics,
      $file_contents_ref, $modified_html_ref) = @_;

  my @file_contents = @{ $file_contents_ref };
  my @modified_html = @{ $modified_html_ref };
  my @max_metric_values = @{ $max_metric_values_ref };

  my @components = ();

  my $colour_coded_line;
  my $colour_coded_line_ref;
  my $hot_line;
  my $input_line;
  my $line_id;
  my $modified_line;
  my $metric_values;
  my $src_code_line;
  my $src_line_no;

  gp_message ("debug", $subr_name, "parse and process the core loop");

  for (my $line_number=$start_scan; $line_number <= $end_scan; $line_number++)
    {
      $input_line = $file_contents[$line_number];

#------------------------------------------------------------------------------
# We need to replace the "<" symbol in the code by "&lt;".
#------------------------------------------------------------------------------
      $input_line =~ s/$g_less_than_regex/$g_html_less_than_regex/g;

      $line_id = extract_source_line_number ($src_times_regex, 
                                             $function2_regex, 
                                             $number_of_metrics, 
                                             $input_line);

      gp_message ("debug", $subr_name, "line_number = $line_number : input_line = $input_line line_id = $line_id");

      if ($input_line =~ /$function2_regex/)
#------------------------------------------------------------------------------
# Found the function marker.
#------------------------------------------------------------------------------
        {
          if (defined ($1) and defined ($2))
            {
              my $func_name_in_file = $2;
              my $spaces = $1;
              my $boldface = $TRUE;
              gp_message ("debug", $subr_name, "function_name = $2");
              my $function_line       = "&lt;Function: " . $func_name_in_file . ">";
              my $color_function_name = color_string (
                                          $function_line, 
                                          $boldface, 
                                          $g_html_color_scheme{"target_function_name"});
              my $ftag;
              if (exists ($g_function_tag_id{$target_function}))
                {
                  $ftag = $g_function_tag_id{$target_function};
                  gp_message ("debug", $subr_name, "target_function = $target_function ftag = $ftag");
                }
              else
                {
                  my $msg = "no ftag found for $target_function";
                  gp_message ("assertion", $subr_name, $msg);
                }
              $modified_line = "<a id=\"" . $ftag . "\"></a>";
              $modified_line .= $spaces . "<i>" . $color_function_name . "</i>";
            }
        }
      elsif ($input_line =~ /$src_times_regex/)
#------------------------------------------------------------------------------
# This is a line with metric values.
#------------------------------------------------------------------------------
        {
          gp_message ("debug", $subr_name, "input line has metrics");

          $hot_line      = $1;
          $metric_values = $2;
          $src_line_no   = $3;
          $src_code_line = $4;

          gp_message ("debug", $subr_name, "hot_line = $hot_line");
          gp_message ("debug", $subr_name, "metric_values = $metric_values");
          gp_message ("debug", $subr_name, "src_line_no = $src_line_no");
          gp_message ("debug", $subr_name, "src_code_line = $src_code_line");

          if ($hot_line eq "##")
#------------------------------------------------------------------------------
# Highlight the most expensive line.
#------------------------------------------------------------------------------
            {
              @components = split (" ", $input_line, 1+$number_of_metrics+2);
              $modified_line = set_background_color_string (
                                 $input_line, 
                                 $g_html_color_scheme{"background_color_hot"});
            }
          else
            {
#------------------------------------------------------------------------------
# Highlight those lines close enough to the most expensive line.
#------------------------------------------------------------------------------
              @components = split (" ", $input_line, $number_of_metrics + 2);
              for my $i (0 .. $number_of_metrics-1)
                {
                  gp_message ("debugXL", $subr_name, "$line_number : time check components[$i] = $components[$i]");
                }

              $colour_coded_line_ref = check_metric_values ($metric_values, \@max_metric_values);

              $colour_coded_line = $ {$colour_coded_line_ref};
              if ($colour_coded_line)
                {
                  gp_message ("debugXL", $subr_name, "$line_number : change background colour modified_line = $modified_line");
                  $modified_line = set_background_color_string ($input_line, $g_html_color_scheme{"background_color_lukewarm"});
                }
              else
                {
                  $modified_line = "<a id=\"line_" . $line_id . "\"></a>";
                  $modified_line .= "$input_line";
                }
            }
        }
      else
#------------------------------------------------------------------------------
# This is a regular line that is not modified.
#------------------------------------------------------------------------------
        {
#------------------------------------------------------------------------------
# Add an id.
#------------------------------------------------------------------------------
          gp_message ("debug", $subr_name, "$line_number : input line is a regular line");
          $modified_line = "<a id=\"line_" . $line_id . "\"></a>";
          $modified_line .= "$input_line";
        }
      gp_message ("debug", $subr_name, "$line_number : mod = $modified_line");
      push (@modified_html, $modified_line);
    }

  return (\@modified_html);

} #-- End of subroutine process_target_source

#------------------------------------------------------------------------------
# Process the options.  Set associated variables and check the options for
# correctness.  For example, detect if conflicting options have been set.
#------------------------------------------------------------------------------
sub process_user_options
{
  my $subr_name = get_my_name ();

  my ($exp_dir_list_ref) = @_;
  
  my @exp_dir_list = @{ $exp_dir_list_ref };

  my %ignored_metrics = ();

  my $error_code; 
  my $message;

  my $outputdir;

  my $target_cmd;
  my $rm_output_msg; 
  my $mkdir_output_msg;
  my $time_percentage_multiplier; 
  my $process_all_functions;

  my $option_errors = 0;

#------------------------------------------------------------------------------
# The -o and -O options are mutually exclusive.
#------------------------------------------------------------------------------
  my $define_new_output_dir = $g_user_settings{"output"}{"defined"};
  my $overwrite_output_dir  = $g_user_settings{"overwrite"}{"defined"};
  my $dir_o_option          = $g_user_settings{"output"}{"current_value"};
  my $dir_O_option          = $g_user_settings{"overwrite"}{"current_value"};

  if ($define_new_output_dir and $overwrite_output_dir)
    {
      my $msg;

      $msg  = "the -o/--output and -O/--overwrite options are both set, " .
              "but are mutually exclusive";
      push (@g_user_input_errors, $msg);

      $msg  = "(setting for -o = $dir_o_option, " .
              "setting for -O = $dir_O_option)";
      push (@g_user_input_errors, $msg);

      $option_errors++;
    }

#------------------------------------------------------------------------------
# Define the quiet mode.  While this is an on/off keyword in the input, we 
# use a boolean in the remainder, because it reads easier.
#------------------------------------------------------------------------------
  my $quiet_value = $g_user_settings{"quiet"}{"current_value"};
  $g_quiet        = ($quiet_value eq "on") ? $TRUE : $FALSE;

#------------------------------------------------------------------------------
# In quiet mode, all verbose, warnings and debug messages are suppressed.
#------------------------------------------------------------------------------
  if ($g_quiet)
    {
      $g_user_settings{"verbose"}{"current_value"} = "off";
      $g_user_settings{"warnings"}{"current_value"} = "off";
      $g_user_settings{"debug"}{"current_value"}   = "off";
      $g_verbose  = $FALSE;
      $g_warnings = $FALSE;
      my $debug_off = "off";
      my $ignore_value = set_debug_size (\$debug_off);
    }
  else
    {
#------------------------------------------------------------------------------
# Get the verbose mode.
#------------------------------------------------------------------------------
      my $verbose_value = $g_user_settings{"verbose"}{"current_value"};
      $g_verbose        = ($verbose_value eq "on") ? $TRUE : $FALSE;
#------------------------------------------------------------------------------
# Get the warning mode.
#------------------------------------------------------------------------------
      my $warning_value = $g_user_settings{"warnings"}{"current_value"};
      $g_warnings       = ($warning_value eq "on") ? $TRUE : $FALSE;
    }

#------------------------------------------------------------------------------
# The value for HP should be in the interval (0,100]. We already enforced
# the number to be positive, but the limits have not been checked yet.
#------------------------------------------------------------------------------
  my $hp_value = $g_user_settings{"highlight_percentage"}{"current_value"};

  if (($hp_value < 0) or ($hp_value > 100))
    {
      my $msg = "the value for the highlight percentage is set to $hp_value, ";
      $msg   .= "but must be in the range [0, 100]"; 
      push (@g_user_input_errors, $msg);

      $option_errors++;
    }

#------------------------------------------------------------------------------
# The value for TP should be in the interval (0,100]. We already enforced
# the number to be positive, but the limits have not been checked yet.
#------------------------------------------------------------------------------
  my $tp_value = $g_user_settings{"threshold_percentage"}{"current_value"};

  if (($tp_value < 0) or ($tp_value > 100))
    {
      my $msg = "the value for the total percentage is set to $tp_value, " .
                "but must be in the range (0, 100]"; 
      push (@g_user_input_errors, $message);

      $option_errors++;
    }
  else
    {
      $time_percentage_multiplier = $tp_value/100.0;

# Ruud  if (($TIME_PERCENTAGE_MULTIPLIER*100.) >= 100.)

      if ($tp_value == 100)
        {
          $process_all_functions = $TRUE; # ensure that all routines are handled
        }
      else
        {
          $process_all_functions = $FALSE;
        }

      my $txt;
      $txt = "value of time_percentage_multiplier = " .
             $time_percentage_multiplier; 
      gp_message ("debugM", $subr_name, $txt);
      $txt = "value of process_all_functions      = " .
             ($process_all_functions ? "TRUE" : "FALSE");
      gp_message ("debugM", $subr_name, $txt);
    }

#------------------------------------------------------------------------------
# If imetrics has been set, split the list into the individual metrics that
# need to be excluded.  The associated hash called $ignore_metrics has the
# to be excluded metrics as an index.  The value of $TRUE assigned does not
# really matter.
#------------------------------------------------------------------------------
  my @candidate_ignored_metrics;

  if ($g_user_settings{"ignore_metrics"}{"defined"})
    {
      @candidate_ignored_metrics = 
              split (":", $g_user_settings{"ignore_metrics"}{"current_value"});
    }
  for my $metric (@candidate_ignored_metrics)
    {
# TBD: bug?      $ignored_metrics{$metric} = $FALSE;
      $ignored_metrics{$metric} = $TRUE;
    }
  for my $metric (keys %ignored_metrics)
    {
      my $txt = "ignored_metrics{$metric} = $ignored_metrics{$metric}";
      gp_message ("debugM", $subr_name, $txt);
    }

#------------------------------------------------------------------------------
# Check if the experiment directories exist.
#------------------------------------------------------------------------------
  for my $i (0 .. $#exp_dir_list)
    {
      if (-d $exp_dir_list[$i])
        {
          my $abs_path_dir = Cwd::abs_path ($exp_dir_list[$i]);
          $exp_dir_list[$i] = $abs_path_dir;
          my $txt = "directory $exp_dir_list[$i] exists";
          gp_message ("debugM", $subr_name, $txt);
        }
      else
        {
          my $msg = "directory $exp_dir_list[$i] does not exist";

          push (@g_user_input_errors, $msg);
          $option_errors++;
        }
    }

  return ($option_errors, \%ignored_metrics, $outputdir, 
          $time_percentage_multiplier, $process_all_functions,
          \@exp_dir_list);

} #-- End of subroutine process_user_options

#------------------------------------------------------------------------------
# This is a hopefully temporary routine to disable/ignore selected user
# settings.  As the functionality expands, this list will get shorter.
#------------------------------------------------------------------------------
sub reset_selected_settings
{
  my $subr_name = get_my_name ();

  $g_locale_settings{"decimal_separator"} = "\\.";
  $g_locale_settings{"convert_to_dot"}    = $FALSE;
  $g_user_settings{func_limit}{current_value} = 1000000;

  gp_message ("debug", $subr_name, "reset selected settings");

  return (0);

} #-- End of subroutine reset_selected_settings

#------------------------------------------------------------------------------
# There may be various different visibility characters in a metric definition.
# For example: e+%CPI.
#
# Internally we use a normalized definition that only uses the dot (e.g.
# e.CPI) as an index into the description structure.
#
# Here we reduce the incoming metric definition to the normalized form, look
# up the text, and return a pointer to it.
#------------------------------------------------------------------------------
sub retrieve_metric_description
{
  my $subr_name = get_my_name ();

  my ($metric_name_ref, $metric_description_ref) = @_;

  my $metric_name        = ${ $metric_name_ref };
  my %metric_description = %{ $metric_description_ref };

  my $description;
  my $normalized_metric;

  $metric_name =~ /([ei])([\.\+%]+)(.*)/;

  if (defined ($1) and defined ($3))
    {
      $normalized_metric = $1 . "." . $3;
    }
  else
    {
      my $msg = "metric $metric_name has an unknown format";
      gp_message ("assertion", $subr_name, $msg);
    }

  if (defined ($metric_description{$normalized_metric}))
    {
      $description = $metric_description{$normalized_metric};
    }
  else
    {
      my $msg = "description for normalized metric $normalized_metric not found";
      gp_message ("assertion", $subr_name, $msg);
    }

  return (\$description);

} #-- End of subroutine retrieve_metric_description

#------------------------------------------------------------------------------
# TBD.
#------------------------------------------------------------------------------
sub rnumerically 
{
  my ($f1,$f2);
  if ($a =~ /^([^\d]*)(\d+)/)
    {
      $f1 = int ($2);
      if ($b=~ /^([^\d]*)(\d+)/)
        {
          $f2 = int ($2);
          $f1 == $f2 ? 0 : ($f1 > $f2 ? -1 : +1);
        }
    } 
  else 
    {
      return ($b <=> $a);
    }
} #-- End of subroutine rnumerically

#------------------------------------------------------------------------------
# TBD: Remove - not used any longer.
# Set the architecture and associated regular expressions.
#------------------------------------------------------------------------------
sub set_arch_and_regexes
{
  my $subr_name = get_my_name ();

  my ($arch_uname) = @_;

  my $architecture_supported;

  gp_message ("debug", $subr_name, "arch_uname = $arch_uname");

  if ($arch_uname eq "x86_64") 
    {
      #x86/x64 hardware uses jump
      $architecture_supported = $TRUE;
#      $arch='x64';
#      $regex=':\s+(j).*0x[0-9a-f]+';
#      $subexp='(\[\s*)(0x[0-9a-f]+)';
#      $linksubexp='(\[\s*)(0x[0-9a-f]+)';
      gp_message ("debug", $subr_name, "detected $arch_uname hardware");

      $architecture_supported = $TRUE;
      $g_arch_specific_settings{"arch_supported"}  = $TRUE;
      $g_arch_specific_settings{"arch"}       = 'x64';
      $g_arch_specific_settings{"regex"}     = ':\s+(j).*0x[0-9a-f]+';
      $g_arch_specific_settings{"subexp"}     = '(\[\s*)(0x[0-9a-f]+)';
      $g_arch_specific_settings{"linksubexp"} = '(\[\s*)(0x[0-9a-f]+)';
    }
#-------------------------------------------------------------------------------
# TBD: Remove the elsif block
#-------------------------------------------------------------------------------
  elsif ($arch_uname=~m/sparc/s) 
    {
      #sparc hardware uses branch
      $architecture_supported = $FALSE;
#      $arch='sparc';
#      $regex=':\s+(c|b|fb).*0x[0-9a-f]+\s*$';
#      $subexp='(\s*)(0x[0-9a-f]+)\s*$';
#      $linksubexp='(\s*)(0x[0-9a-f]+\s*$)';
#      gp_message ("debug", $subr_name, "detected $arch_uname hardware arch = $arch - this is no longer supported");
      $architecture_supported = $FALSE;
      $g_arch_specific_settings{arch_supported}  = $FALSE;
      $g_arch_specific_settings{arch}       = 'sparc';
      $g_arch_specific_settings{regex}     = ':\s+(c|b|fb).*0x[0-9a-f]+\s*$';
      $g_arch_specific_settings{subexp}     = '(\s*)(0x[0-9a-f]+)\s*$';
      $g_arch_specific_settings{linksubexp} = '(\s*)(0x[0-9a-f]+\s*$)';
    }
  else 
    {
      $architecture_supported = $FALSE;
      gp_message ("debug", $subr_name, "detected $arch_uname hardware - this not supported; limited functionality");
    }

    return ($architecture_supported);

} #-- End of subroutine set_arch_and_regexes

#------------------------------------------------------------------------------
# Set the background color of the input string.
#
# For supported colors, see:
# https://www.w3schools.com/colors/colors_names.asp
#------------------------------------------------------------------------------
sub set_background_color_string
{
  my $subr_name = get_my_name ();

  my ($input_string, $color) = @_;

  my $background_color_string;
  my $msg;

  $msg = "color = $color input_string = $input_string";
  gp_message ("debugXL", $subr_name, $msg);

  $background_color_string = "<span style='background-color: " . $color . 
                             "'>" . $input_string . "</span>";

  $msg = "color = $color background_color_string = " .
         $background_color_string;
  gp_message ("debugXL", $subr_name, $msg);

  return ($background_color_string);

} #-- End of subroutine set_background_color_string

#------------------------------------------------------------------------------
# Set the g_debug_size structure for a given value for "size".  Also set the
# value in $g_user_settings{"debug"}{"current_value"}
#------------------------------------------------------------------------------
sub set_debug_size
{
  my $subr_name = get_my_name ();

  my ($debug_value_ref) = @_;

  my $debug_value = lc (${ $debug_value_ref });

#------------------------------------------------------------------------------
# Regardless of the value, the debug settings are defined here.
#------------------------------------------------------------------------------
  $g_user_settings{"debug"}{"defined"} = $TRUE;

#------------------------------------------------------------------------------
# By default, set the value to "on", but correct below if needed.
#------------------------------------------------------------------------------
  $g_user_settings{"debug"}{"current_value"} = "on";

  if (($debug_value eq "on") or ($debug_value eq "s"))
    {
      $g_debug_size{"on"} = $TRUE;
      $g_debug_size{"s"}  = $TRUE;
    }
  elsif ($debug_value eq "m")
    {
      $g_debug_size{"on"} = $TRUE;
      $g_debug_size{"s"}  = $TRUE;
      $g_debug_size{"m"}  = $TRUE;
    }
  elsif ($debug_value eq "l")
    {
      $g_debug_size{"on"} = $TRUE;
      $g_debug_size{"s"}  = $TRUE;
      $g_debug_size{"m"}  = $TRUE;
      $g_debug_size{"l"}  = $TRUE;
    }
  elsif ($debug_value eq "xl")
    {
      $g_debug_size{"on"} = $TRUE;
      $g_debug_size{"s"}  = $TRUE;
      $g_debug_size{"m"}  = $TRUE;
      $g_debug_size{"l"}  = $TRUE;
      $g_debug_size{"xl"} = $TRUE;
    }
  else
#------------------------------------------------------------------------------
# Any other value is considered to disable debugging.
#------------------------------------------------------------------------------
    {
      $g_user_settings{"debug"}{"current_value"} = "off";
      $g_debug_size{"on"} = $FALSE;
      $g_debug_size{"s"}  = $FALSE;
      $g_debug_size{"m"}  = $FALSE;
      $g_debug_size{"l"}  = $FALSE;
      $g_debug_size{"xl"} = $FALSE;
    }

#------------------------------------------------------------------------------
# Activate in case of an emergency :-)
#------------------------------------------------------------------------------
##  if ($g_debug_size{$debug_value})
##    {
##      for my $i (keys %g_debug_size)
##        {
##          print "$subr_name g_debug_size{$i} = $g_debug_size{$i}\n";
##        }
##    }

  return (0);

} #-- End of subroutine set_debug_size

#------------------------------------------------------------------------------
# This subroutine defines the default metrics.
#------------------------------------------------------------------------------
sub set_default_metrics
{
  my $subr_name = get_my_name ();

  my ($outfile1, $ignored_metrics_ref) = @_;

  my %ignored_metrics = %{ $ignored_metrics_ref };

  my %metric_description = ();
  my %metric_found       = ();

  my $detail_metrics;
  my $detail_metrics_system;

  my $call_metrics    = "";
  my $summary_metrics = "";

  open (METRICS, "<", $outfile1)
    or die ("Unable to open metrics file $outfile1 for reading - '$!'");
  gp_message ("debug", $subr_name, "opened $outfile1 for reading");

  while (<METRICS>)
    {
      my $metric_line = $_;
      chomp ($metric_line);

      gp_message ("debug", $subr_name,"the value of metric_line = $metric_line");

#------------------------------------------------------------------------------
# Decode the metric part of the input line. If a valid line, return the 
# metric components. Otherwise return "skipped" in the metric_spec field.
#------------------------------------------------------------------------------
      my ($metric_spec, $metric_flavor, $metric_visibility, $metric_name, $metric_description) = extract_metric_specifics ($metric_line);

      gp_message ("debug", $subr_name, "metric_spec   = $metric_spec");
      gp_message ("debug", $subr_name, "metric_flavor = $metric_flavor");

      if ($metric_spec eq "skipped")
#------------------------------------------------------------------------------
# Not a valid input line.
#------------------------------------------------------------------------------
        {
          gp_message ("debug", $subr_name, "skipped line: $metric_line");
        }
      else
        {
#------------------------------------------------------------------------------
# A valid metric field has been found.
#------------------------------------------------------------------------------
          gp_message ("debug", $subr_name, "metric_name        = $metric_name");
          gp_message ("debug", $subr_name, "metric_description = $metric_description");

#        if (exists ($IMETRICS{$m})){
          if ($g_user_settings{"ignore_metrics"}{"defined"} and exists ($ignored_metrics{$metric_name}))
            {
              gp_message ("debug", $subr_name, "user requested to ignore metric $metric_name");
              next;
            }

#------------------------------------------------------------------------------
# Only the exclusive metric is selected.
#------------------------------------------------------------------------------
          if ($metric_flavor eq "e")
            {
              $metric_found{$metric_spec}       = $TRUE;
              $metric_description{$metric_spec} = $metric_description;

# TBD: remove the -AO:
              gp_message ("debug", $subr_name,"-AO metric_description{$metric_spec} = $metric_description{$metric_spec}");

              $summary_metrics .= $metric_spec.":";
              $call_metrics .= "a.".$metric_name.":";
            }
        }
    }
  close (METRICS);

  chop ($call_metrics);
  chop ($summary_metrics);

  $detail_metrics        = $summary_metrics;
  $detail_metrics_system = $summary_metrics;

  return (\%metric_description, \%metric_found, 
         $summary_metrics, $detail_metrics, $detail_metrics_system, $call_metrics);

} #-- End of subroutine set_default_metrics

#------------------------------------------------------------------------------
# Set various system specific variables.  These depend upon both the processor
# architecture and OS. The values are stored in global structure 
# g_arch_specific_settings.
#------------------------------------------------------------------------------
sub set_system_specific_variables
{
  my $subr_name = get_my_name ();

  my ($arch_uname, $arch_uname_s) = @_;

  my $elf_arch;
  my $read_elf_cmd;
  my $elf_support; 
  my $architecture_supported;
  my $arch;
  my $regex;
  my $subexp;
  my $linksubexp;

  if ($arch_uname eq "x86_64") 
    {
#------------------------------------------------------------------------------
# x86/x64 hardware uses jump
#------------------------------------------------------------------------------
      $architecture_supported = $TRUE;
      $arch       = 'x64';
      $regex     =':\s+(j).*0x[0-9a-f]+';
      $subexp     ='(\[\s*)(0x[0-9a-f]+)';
      $linksubexp ='(\[\s*)(0x[0-9a-f]+)';

#      gp_message ("debug", $subr_name, "detected $arch_uname hardware arch = $arch");

      $g_arch_specific_settings{"arch_supported"} = $TRUE;
      $g_arch_specific_settings{"arch"}           = 'x64';
#------------------------------------------------------------------------------
# Define the regular expressions to parse branch instructions.
#------------------------------------------------------------------------------

#------------------------------------------------------------------------------
# TBD: Need much more than these
#------------------------------------------------------------------------------
      $g_arch_specific_settings{"regex"} = '\.*([0-9a-fA-F]*):\s+(j).*\s*0x([0-9a-fA-F]+)';
      $g_arch_specific_settings{"subexp"} = '(0x[0-9a-f]+)';
      $g_arch_specific_settings{"linksubexp"} = '(\s*)(0x[0-9a-f]+)';
    }
  else 
    {
      $architecture_supported = $FALSE;
      $g_arch_specific_settings{"arch_supported"}  = $FALSE;
    }

#------------------------------------------------------------------------------
# TBD Ruud: need to handle this better
#------------------------------------------------------------------------------
  if ($arch_uname_s eq "Linux") 
    {
      $elf_arch     = $arch_uname_s;
      $read_elf_cmd = $g_mapped_cmds{"readelf"};

      if ($read_elf_cmd eq "road_to_nowhere")
        {
          $elf_support = $FALSE;
        }
      else
        {
          $elf_support = $TRUE;
        }
      gp_message ("debugXL", $subr_name, "elf_support = $elf_support read_elf_cmd = $read_elf_cmd elf_arch = $elf_arch");
    } 
  else 
    {
      gp_message ("abort", $subr_name, "the $arch_uname_s operating system is not supported");
    }

  return ($architecture_supported, $elf_arch, $elf_support);

} #-- End of subroutine set_system_specific_variables

#------------------------------------------------------------------------------
# TBD
#------------------------------------------------------------------------------
sub set_title
{
  my $subr_name = get_my_name ();

  my ($function_info_ref, $func, $from_where) = @_ ;

  my $msg;
  my @function_info = @{$function_info_ref};
  my $filename = $func ;

  my $base;
  my $first_line;
  my $src_file;
  my $RI;
  my $the_title;
  my $routine = "?";
  my $DIS;
  my $SRC;

  chomp ($filename);

  $base = get_basename ($filename);

  gp_message ("debug", $subr_name, "from_where = $from_where");
  gp_message ("debug", $subr_name, "base = $base filename = $filename");

  if ($from_where eq "process source")
    {
      if ($base =~ /^file\.(\d+)\.src\.txt$/)
        {
          if (defined ($1))
            {
              $RI = $1;
            }
          else
            {
              $msg = "unexpected error encountered parsing $filename";
              gp_message ("assertion", $subr_name, $msg);
            }
        }
      $the_title = "Source";
    } 
  elsif ($from_where eq "disassembly")
    {
      if ($base =~ /^file\.(\d+)\.dis$/)
        {
          if (defined ($1))
            {
              $RI = $1;
            }
          else
            {
              $msg = "unexpected error encountered parsing $filename";
              gp_message ("assertion", $subr_name, $msg);
            }
        }
      $the_title = "Disassembly";
    } 
  else 
    {
      $msg = "called from unknown routine - $from_where";
      gp_message ("assertion", $subr_name, $msg);
    }

  if (defined ($function_info[$RI]{"routine"}))
    {
      $routine = $function_info[$RI]{"routine"};
    }
  
  if ($from_where eq "process source")
    {
      my $is_empty = is_file_empty ($filename);

      if ($is_empty)
        {
          $src_file = "";
        }
      else
        {
          open ($SRC, "<", $filename) 
            or die ("$subr_name - unable to open source file $filename for reading:'$!'");
          gp_message ("debug", $subr_name, "opened file $filename for reading");

          $first_line = <$SRC>;
          chomp ($first_line);

          close ($SRC);

          gp_message ("debug", $subr_name, "first_line = $first_line");

          if ($first_line =~ /^Source\s+file:\s+([^\s]+)/)
            {
              $src_file = $1
            }
          else
            {
              $src_file = "";
            }
        }
    }
  elsif ($from_where eq "disassembly")
    {
      open ($DIS, "<", $filename)
        or die ("$subr_name - unable to open disassembly file $filename for reading: '$!'");
      gp_message ("debug", $subr_name, "opened file $filename for reading");

      $first_line = <$DIS>;
      close ($DIS);
  
      if ($first_line =~ /^Source\s+file:\s+([^\s]+)/)
        {
          $src_file = "$1"
        }
      else
        {
          $src_file = "";
        }
    }

  if (length ($routine))
    {
      $the_title .= " $routine";
    }

  if (length ($src_file))
    {
      if ($src_file ne "(unknown)")
        {
          $the_title .= " ($src_file)";
        } 
      else 
        {
          $the_title .= " $src_file";
        }
    }

  return ($the_title);

} #-- End of subroutine set_title

#------------------------------------------------------------------------------
# Handles where the output should go.  If needed, a directory is # created 
# where the results will go.
#------------------------------------------------------------------------------
sub set_up_output_directory
{
  my $subr_name = get_my_name ();

  my $error_code;
  my $message;
  my $mkdir_output_msg;
  my $option_errors;
  my $outputdir = "does_not_exist_yet";
  my $rm_output_msg;
  my $target_cmd;

  my $define_new_output_dir = $g_user_settings{"output"}{"defined"};
  my $overwrite_output_dir  = $g_user_settings{"overwrite"}{"defined"};

  $option_errors = 0;

  if ((not $define_new_output_dir) and (not $overwrite_output_dir))
#------------------------------------------------------------------------------
# If neither -o or -O are set, find the next number to be used in the name for 
# the default output directory.
#------------------------------------------------------------------------------
    {
      my $dir_id = 1;
      while (-d "display.".$dir_id.".html") 
        { $dir_id++; }
      $outputdir = "display.".$dir_id.".html";
    }
  elsif ($define_new_output_dir)
#------------------------------------------------------------------------------
# The output directory is defined with the -o option.
#------------------------------------------------------------------------------
    {
      $outputdir = $g_user_settings{"output"}{"current_value"};
    }
  elsif ($overwrite_output_dir)
#------------------------------------------------------------------------------
# The output directory is defined with the -O option.
#------------------------------------------------------------------------------
    {
      $outputdir = $g_user_settings{"overwrite"}{"current_value"};
    }

#------------------------------------------------------------------------------
# The name of the output directory is known and we can proceed.
#------------------------------------------------------------------------------
  gp_message ("debug", $subr_name, "the target output directory is $outputdir");

  if (-d $outputdir)
    {
#------------------------------------------------------------------------------
# The -o option is used, but the directory already exists.
#------------------------------------------------------------------------------
      if ($define_new_output_dir)
        {
          $message  = "directory $outputdir already exists";
          $message .= " (use the -O option to overwrite an existing directory)";
          push (@g_user_input_errors, $message);

          $option_errors++;

          return ($option_errors, $outputdir);
        }
      elsif ($overwrite_output_dir)
#------------------------------------------------------------------------------
# It is a bit risky to remove this directory and so we proceed with caution.
# What if the user decides to call it "*" e.g. "-O \*" for example? While this
# should have been caught when processing the options, we still like to 
# be very cautious here before executing /bin/rm -rf.
#------------------------------------------------------------------------------
        {
          if ($outputdir eq "*") 
            {
              $message = "it is not allowed to use * as a value for the -O option";
              push (@g_user_input_errors, $message);

              $option_errors++;

              return ($option_errors, $outputdir);
            }
          else
            {
#------------------------------------------------------------------------------
# The output directory exists, but it is okay to overwrite it. It is 
# removed here and created again below.
#------------------------------------------------------------------------------
              $target_cmd = $g_mapped_cmds{"rm"} . " -rf " . $outputdir;
              ($error_code, $rm_output_msg) = execute_system_cmd ($target_cmd);

                if ($error_code != 0)
                  {
                    gp_message ("error", $subr_name, $rm_output_msg);
                    gp_message ("abort", $subr_name, "fatal error when trying to remove $outputdir");
                  }
                else
                  {
                    gp_message ("debug", $subr_name, "directory $outputdir has been removed");
                  }
            }
        }
    } #-- End of if-check for $outputdir

#-------------------------------------------------------------------------------
# When we get here, the fatal scenarios have been cleared and the name for 
# $outputdir is known.  Time to create it.  Note that recursive creation is
# supported and umask controls the access permissions.
#-------------------------------------------------------------------------------
  $target_cmd = $g_mapped_cmds{"mkdir"} . " -p " . $outputdir;
  ($error_code, $mkdir_output_msg) = execute_system_cmd ($target_cmd);

  if ($error_code != 0)
    {
      my $msg = "a fatal problem occurred when creating directory $outputdir";
      gp_message  ("abort", $subr_name, $msg);
    }
  else
    {
      gp_message  ("debug", $subr_name, "created output directory $outputdir");
    }

  return ($option_errors, $outputdir);

} #-- End of subroutine set_up_output_directory

#------------------------------------------------------------------------------
# Routine to generate webfriendly names
#------------------------------------------------------------------------------
sub tag_name
{
  my $subr_name = get_my_name ();

  my ($target_name) = @_;

#------------------------------------------------------------------------------
# Keeps track how many names have been tagged already.
#------------------------------------------------------------------------------
  state $S_total_tagged_names = 0; 

  my $unique_name;

  gp_message ("debug", $subr_name, "target_name on entry  = $target_name");

#------------------------------------------------------------------------------
# Undo conversion of < in to &lt;
#------------------------------------------------------------------------------

#------------------------------------------------------------------------------
# TBD: Legacy - What is going on here and is this really needed?!
# We need to replace the "<" symbol in the code by "&lt;".
#------------------------------------------------------------------------------
  $target_name =~ s/$g_html_less_than_regex/$g_less_than_regex/g;

#------------------------------------------------------------------------------
# Remove inlining info
#------------------------------------------------------------------------------
  $target_name =~ s/, instructions from source file.*//; 

  if (defined $g_tagged_names{$target_name})
    {
      gp_message ("debug", $subr_name, "target_name = $target_name is already defined: $g_tagged_names{$target_name}");
      gp_message ("debug", $subr_name, "target_name on return = $target_name");
      return ($g_tagged_names{$target_name});
    }
  else
    {
      $unique_name = "ftag".$S_total_tagged_names;
      $S_total_tagged_names++; 
      $g_tagged_names{$target_name} = $unique_name;
      gp_message ("debug", $subr_name, "target_name = $target_name is new and added: g_tagged_names{$target_name} = $g_tagged_names{$target_name}");
      gp_message ("debug", $subr_name, "target_name on return = $target_name");
      return ($unique_name);
    }

} #-- End of subroutine tag_name

#------------------------------------------------------------------------------
# Generate a string to terminate the HTML document.
#------------------------------------------------------------------------------
sub terminate_html_document
{
  my $subr_name = get_my_name ();

  my $html_line;

  $html_line  = "</body>\n";
  $html_line .= "</html>";

  return (\$html_line);

} #-- End of subroutine terminate_html_document

#-------------------------------------------------------------------------------
# Perform some basic checks to ensure the input data is consistent.  This part
# could be refined and expanded over time.  For example by using a checksum
# mechanism to verify the consistency of the executables.
#-------------------------------------------------------------------------------
sub verify_consistency_experiments
{
  my $subr_name = get_my_name ();

  my ($exp_dir_list_ref) = @_;

  my @exp_dir_list    = @{ $exp_dir_list_ref };

  my $executable_name;
  my $full_path_executable_name;
  my $ref_executable_name;

  my $first_exp_dir     = $TRUE;
  my $count_differences = 0;

#-------------------------------------------------------------------------------
# Enforce that the full path names to the executable are the same.  This could
# be overkill and a checksum approach would be more flexible.
#-------------------------------------------------------------------------------
  for my $full_exp_dir (@exp_dir_list)
    {
      my $exp_dir = get_basename ($full_exp_dir);
      gp_message ("debug", $subr_name, "exp_dir = $exp_dir");
      if ($first_exp_dir)
        {
          $first_exp_dir = $FALSE;
          $ref_executable_name = $g_exp_dir_meta_data{$exp_dir}{"full_path_exec"}; 
          gp_message ("debug", $subr_name, "ref_executable_name = $ref_executable_name");
          next;
        }
        $full_path_executable_name = $g_exp_dir_meta_data{$exp_dir}{"full_path_exec"}; 
        gp_message ("debug", $subr_name, "full_path_executable_name = $full_path_executable_name");

        if ($full_path_executable_name ne $ref_executable_name)
          {
            $count_differences++;
            gp_message ("debug", $subr_name, "$full_path_executable_name does not match $ref_executable_name");
          }
    }

  $executable_name = get_basename ($ref_executable_name);

  return ($count_differences, $executable_name);

} #-- End of subroutine verify_consistency_experiments

#------------------------------------------------------------------------------
# Check if the input item is valid for the data type specified. Validity is
# verified in the context of gprofng.  The definition for the metrics is a 
# good example of that.
#------------------------------------------------------------------------------
sub verify_if_input_is_valid
{
  my $subr_name = get_my_name ();

  my ($input_item, $data_type) = @_;

  my $return_value = $FALSE;

#------------------------------------------------------------------------------
# These value are allowed to be case insensitive, so we convert to lower
# case first.
#------------------------------------------------------------------------------
  if (($data_type eq "onoff") or ($data_type eq "size"))
    {
      $input_item = lc ($input_item);
    }

  if ($data_type eq "metrics")
#------------------------------------------------------------------------------
# A gprofng metric definition.  Either consists of "default" only, or starts
# with e or i, followed by one or more from the set {.,%,!,+} and a keyword.
# This pattern may be repeated with a ":" as the separator.
#------------------------------------------------------------------------------
    {
      my @metric_list = split (":", $input_item);

#------------------------------------------------------------------------------
# Check if the pattern is valid.  If not, bail out and return $FALSE.
#------------------------------------------------------------------------------
      for my $metric (@metric_list)
        {
          if ($metric =~ /^default$|^[ei]*[\.%\!\+]+[a-z]*$/)
            {
              $return_value = $TRUE;
            }
          else
            {
              $return_value = $FALSE;
              last;
            }
        }
    }
  elsif ($data_type eq "metric_names")
#------------------------------------------------------------------------------
# A gprofng metric definition but without the flavour and visibility .  Either 
# the name consists of "default" only, or a keyword with lowercase letters
# only.  This pattern may be repeated with a ":" as the separator.
#------------------------------------------------------------------------------
    {
      my @metric_list = split (":", $input_item);

#------------------------------------------------------------------------------
# Check if the pattern is valid.  If not, bail out and return $FALSE.
#------------------------------------------------------------------------------
      for my $metric (@metric_list)
        {
          if ($metric =~ /^default$|^[a-z]*$/)
            {
              $return_value = $TRUE;
            }
          else
            {
              $return_value = $FALSE;
              last;
            }
        }
    }
  elsif ($data_type eq "path")
#------------------------------------------------------------------------------
# This can be almost anything, including "/" and "."
#------------------------------------------------------------------------------
    {
      if ($input_item =~ /^[\w\/\.]*$/)
        {
          $return_value = $TRUE;
        }
    }
  elsif ($data_type eq "boolean")
    {
#------------------------------------------------------------------------------
# This is TRUE (=1) or FALSE (0).
#------------------------------------------------------------------------------
      if ($input_item =~ /^[01]$/)
        {
          $return_value = $TRUE;
        }
    }
  elsif ($data_type eq "onoff")
#------------------------------------------------------------------------------
# This is either "on" OR "off".
#------------------------------------------------------------------------------
    {
      if ($input_item =~ /^on$|^off$/)
        {
          $return_value = $TRUE;
        }
    }
  elsif ($data_type eq "size")
#------------------------------------------------------------------------------
# Supported values are "on", "off", "s", "m", "l", OR "xl".
#------------------------------------------------------------------------------
    {
      if ($input_item =~ /^on$|^off$|^s$|^m$|^l$|^xl$/)
        {
          $return_value = $TRUE;
        }
    }
  elsif ($data_type eq "pinteger")
#------------------------------------------------------------------------------
# This is a positive integer.
#------------------------------------------------------------------------------
    {
      if ($input_item =~ /^\d*$/)
        {
          $return_value = $TRUE;
        }
    }
  elsif ($data_type eq "integer")
#------------------------------------------------------------------------------
# This is a positive or negative integer.
#------------------------------------------------------------------------------
    {
      if ($input_item =~ /^\-?\d*$/)
        {
          $return_value = $TRUE;
        }
    }
  elsif ($data_type eq "pfloat")
#------------------------------------------------------------------------------
# This is a positive floating point number, but we accept a positive integer
# number as well.
#
# TBD: Note that we use the "." here. Maybe should support a "," too.
#------------------------------------------------------------------------------
    {
      if (($input_item =~ /^\d*\.\d*$/) or ($input_item =~ /^\d*$/))
        {
          $return_value = $TRUE;
        }
    }
  elsif ($data_type eq "float")
#------------------------------------------------------------------------------
# This is a positive or negative floating point number, but we accept an
# integer number as well.
#
# TBD: Note that we use the "." here. Maybe should support a "," too.
#------------------------------------------------------------------------------
    {
      if (($input_item =~ /^\-?\d*\.\d*$/) or ($input_item =~ /^\-?\d*$/))
        {
          $return_value = $TRUE;
        }
    }
  else
    {
      my $msg = "the $data_type data type for input $input_item is not supported";
      gp_message ("assertion", $subr_name, $msg);
    } 

  return ($return_value);

} #-- End of subroutine verify_if_input_is_valid
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                      LPAŅ5  HnWH|$p=   L|$pLLt<H|$xrIHvH$   HL$xLHt$pHP(ab  LE1L$  MD9~/LLHDHHK,ID9Ѹ!   1D)McM  s  t
AE    $     L$@  L$`  D $   EDD)΍QD!!	H$   уD$VHLL@DLLL   L$   A   H$   H$(  L$   H$0  H$8  H$   MH$@  H$H  L$   H$P  H$X  HHH	HH?H?H$`  H    H!H$p  H$x  $   H$h  L$   f.     D  D     	DAȉ)֍B!!	H߉D$VLI   lH$   LܨH$   DLfH$   HHA  FH$    L$   _11HT H$   L$Ht$XHt$pHD$h0@ H$   e  H$   H    H HHHD$hHD$XH  Ht$hk  HIH  H$   H|$XLkLHD$XLLHL$pLMHLHD$XMdL|$pH$   H$   D$   H$   ^fI}H$@     蚀I}    H5 }{AE(   HL$xLLH$   EY}H[LaHkID    H1҉уIt
 9r0L$   Ll$A?   H$   H$D  Au EI!?A)׍B!HH   A!D	ȉD4WLоH$   H$   [H$   H$   DH$   LHL9dH\$hH|$@  HH|$H  HH|$8  HѾD$H$   H$   He{
H   H HHD$h)1Ҿq   1   +>
H|$h  H )1Ҿ   1   U+
H|$hg  Hz )1Ҿ  1   "+W	H|$hm  HG R)1Ҿ  1   *HD$p    0    D    a	H   H HHD$h(1Ҿ  1   *1fT@	H|$h  H (1Ҿ  1   W*AE     AD    L$   LLLLLLLLLL}D$`   11fA|-ff.     HHtG 1HtkUSHHG t~H[]1111H{H-U   H`H{(/HHHߺ  []Af     1111    AWAVAUATUHSHH   dH%(   H$   1qH9HP  HIAƅt>A   H$   dH+%(     HĨ   D[]A\A]A^A_1111E1ÐH'    H5k 0   aHD$H  L|$   IIG   AG 3IG(H  HD$    H  H莙HCHH  E  g  H5 @P 觺IH  H~HI~HD$M  H  LHƤ  LHL$PLl$8HD$$    ILp@H@P Ld$HHD$0HD$pMHD$(Ht$Ltl  Ld$@MHH   HQ  HLHЅ>  Iw   Ly  IwH|$(   y  T$$LLA   5D  HLLH*  AuHD$0I   I9XHT$HL$HIHLd$@H   D$$D$$@HD$Ll$8A   LhE1HH@   L`H   1ǃ      HD$DD  `  E1E1H H= m$1Ҿr   1   
&HD$    H_H|$0H|$%  H5 L蹸L	H|$f.     kH$ D  H=h #1Ҿq   1   %E1     +H h  H=( #1Ҿ  1   @%HD$    E1E1+@ H   ܪHHtHD$f.     Ll$8E1 HD   H= ##1Ҿ  1   $; sH   H=p "1Ҿ  1   $H|$  H5G ZLl$8#Hܧ   H=  "1Ҿ   1   8$8yff.      HY(      AWE1AVAUATIUHSLH(Ht$L$M   H,HHHD$וHI̕HH$IHtHHU@H<$HLSt1HE H    tcHU@HLL1,  f     1H]Ln-  f     H   HH  I<HLLH   tHE Ht$ILLH   tUp  LM HU`I   H  HLHЅUHM@H$ILL߲7Ht$HM@LHVHE HUhH   H	  HLHЅHM@LHt$HlVoHU@HLHt$+H  D$E1A@L訍D9S  L?Hu@,  H<$H_(f  x Hq    H= 1Ҿn   1   !(     HM@H|$ILL話v@ 1H([]A\A]A^A_1111E1E1    L$$HU@LLFHM@LLL3UHt$HM@LHDdzf.     H$ILHA   OLL脋<LDD9t>JHC    H=פ 1Ҿ 1   _ HM@H$Ht$HIL1=@H_   uHHtoPHĤ u   H=X C1Ҿ  1   {H    H=# 1Ҿm   1   F% ouGURHK p   AWAAVMAUIATMUHSHH8D$tuMLH2't~HtM   A   H8L[]A\A]A^A_1111E1E1E1@ H    H=H 31Ҿh   1   E1L(E1H}@PHAHcHALL	HL$LDH-  M9  E1M  LLL$ 跏LoLHD$bHD$(Hl  HT$MHLHN  |$LL$ DK  @+H|$LL$aHl$PHHH)E  HLL$-  HH{1LL$4LL$HH|$H4+LL$$LL$LcHD$IHL9   EAAB  M9  LLL$LWLL$HLL$o'LL$D  Hԡ    H= s1Ҿd   1   F H    H=P ;1Ҿ 1   LV H|$(LL$iLL$AGE@ H   LL$OLL$HIIfD  +H    H= 1Ҿd   1   @k H|$(LL$Hl$PHHH)   HLL$tJ<+H1LL$`LL$IH|$(J4+LL$#LL$HILfD  {HT      [H4    EH    }@ AWAVAUATUSH8H  HHIIM LAAAA   <    Au	E  I@HT$cHT$HHD$HHD$ HD H9   HD$    H  HHǌHHD$躌HD$(HL  HT$t$H}
CH1  Iw@H|$p  EA-  HD$ t$H|Hl$(HBH  Iw@H=p  A#  HL$(HT$ILL17@  fD        E   H   HE 1  H= 1Ҿf   1   1H8[]A\A]A^A_1111E1 ;H   H=ȝ 1Ҿd   1   PfD  H8[]A\A]A^A_u#D  H +  Zf.     H@HT$b HT$HHD$HHD$ HH9 HM >   I   tHHHD$fD  SH '  f;H Q  H=Ȝ 1Ҿf   1   P1fD  HQH|$V"HT$IDLL1訞@H \  D  H|$(螃D9HY a  `f.     D  SHWVHC@NVHC`EVH{@HChHt H{` tHtCp       [1@ cH{`ZH{hQ1[1ff.     SHH@3H{`*H{h[ SHUHCUHCUH{C(    HC Ht!H{ t   Ht[11     ˫H{«H{ 蹫1[11ff.     @ SHH蓫H{芫H{ [逫SHH@CXH{`:XH{h[0XSHH#XH{XH{ XC(    [1fD  UHSHHHv@H@7HtBHu`H{`%Ht0HuhH{hHtEpCpH   []11     H1[]11 UHSHHHvHǟHtBHuH{赟Ht0Hu H{ 裟HtE(C(ECH   []11fH1[]11 H@    AWAVIAUIATIHUHSLH"  Hʀ  HD$    H  HHH IH4  I|$@HH  I|$@1HHLLD   I$I|$`H  H   HHLLЅ   I|$hHHLWD   I$H  HtIt$hHLHЅ      L
StvIt$@L   脣AD$pWD  H    1H=Ԙ 11Ҿg   1   0@ LНH=    1HVMH|$H[]A\A]A^A_1111E1I$   3HD$HHb1ff.      AVAUMATIUHSHHtHHs@;H   HL	   HH   HtwE1M   Ht)HHS`LHЉŅt+   Mt!HH   HShLLH1@L[]A\A]A^1111E1     HtKHs`H菜IH   Mu.E1   @ 1[]A\A]A^1111E1     HshL1BH@E1m H   ԗIHtHMH   f.     13f     H~ w/    HHHHP@~ff.      HHHHHH@ۡff.     AWIAVE1AUATUSHH(HG@HD$H  H诂HgHH\HIQHHD$DHHD$7H   IIW`H   H  HHLAŅthIIWhHLL   tKHs.   LA   ].u,Ll$L|$HHLL^   fD  E1H5JLH(D[]A\A]A^A_1111E1H   HIH H   E1H= u1Ҿ  1   LE1-Amf.     HHHLIwhLH2fH|$ILHLHt$   L}LLd$HLL2   L
PILLLHQfHE1,A HF(    H~ S   H11ff.      AWAVAUIATUHSLH8HT$HL$2  HD$    AH
  HH譀HI袀HHD$ 蕀HHD$(舀IH   HE IU H   H  HLHЅtuLKHE    H   H  H|$ tIUHt$HHЅt4H|$    HE IUHHHt$E1   AfD  HxGH|$H8D[]A\A]A^A_1111E1ÐH   THD$HH  fD  Ht$ HLH    HE H   b  HU@Ht$ HH|$(\H|$ t&HE IUIHHL$(Ht$   .H|$    HE H   X  HM@HT$ ILHt$(HE IUILHt$HE1   AD  KHd    H=f 
1Ҿj   1   `E1     I     H|$ tIuH|$:HQH|$ t!IuH|$E1HA,@ A   D  HT$ Ht$(HH   D  {H 2  H= 	1Ҿ  1    HL$ HT$(ILH   fAWAVIAUATIUHSLHhH9  HI"L  HAǅ|  HD$    HE H   H   HD$ HE@HL$HD$@H}  H%|H|HHD$|HHD$(|HHD$0|HHD$8|HHD$H|HHD$P|HD$XH  Au(%  IU Ht$HHHD$ Ѕw  IT$HL$IHHt$(HD$ЅS  HT$IM IHHD$HЅ2  IT$HL$IHHt$0HD$Ѕ  AL$(  IT$ Ht$HHHD$ Ѕ   IUHL$IHHt$8HD$Ѕ   HT$IL$ IHHD$HЅ   IUHL$IHHt$HHD$Ѕt~HL$@HT$8Ht$(H|$P,taHL$@HT$HHt$0H|$X,tDH|$P&-  H|$X&@  HBHLLH1AfHxBH|$HhD[]A\A]A^A_1111E1E1fD  LHhL[]A\A]A^A_    HhL[]A\A]A^A_fH   HHtHD$efIt$H|$(AHXIt$H|$0)H2; IuH|$8
H!IuH|$HHHt$(HL$@HT$8H;Ht$0HL$@HT$HH;  AT$(AE(    Iu H|$耑HIv HL$PIHHT$HD$Ѕt1HT$XHt$HAF(HHD$ ЅOLl$HHT$PHHLL$ LAх,Ll$HLLl$8IHT$(Ld$HLAԅLl$8LLl$I~HL$@Lc*IvHT$@L,HL$@Ht$8LL-*HL$XILLHAԅHD$PHT$HIHHHAԅhHL$PHT$0IHHt$(AԅHHL$@HT$(LL)+LqtHt$HT$@H}I~Ht$E1NAf     I~ A   JAF(    E1IT$ u?IM Ht$IHHD$ЅI~ Ht$PbHtH|$HGHYf     AWAVIHAUATIUHSHHH~  HD$    AHE H   H   HD$ HE@HL$0HD$(H  HvHvHHD$vHHD$vHHD$8vIHt)At$(t\IT$Ht$HHLL$ Aх  H=H|$bHHD[]A\A]A^A_1111E1E1E1    Ep  IT$ Ht$HHHD$ ЅtIt$HL$(HT$H|$	8tIt$HL$(HT$H|$8l'`HL$8HT$IHHt$HD$0Ѕ<HT$(Ht$H|$( HT$HL$(Ht$H7D  AL$(IT$.  IL$ Ht$IHHD$0ЅI~ HT$(Ht$(IT$HD$ HLAF(    HЅIT$Ld$8ILLT$0HLA҅eHL$(   LL4$HHT$(H|$LLd$8()IvHT$HHLd$ Aԅ
I~HL$(HT$H%Ht$HLHAԅLd$(Ht$   LL#IVHt$8LH|$%HL$HT$IHLT$0HA҅pI~Ht$LLE1]%ANfH   THHFHD$fD  I~ A   IFAF(    @ IT$Ht$HHHD$ ЅHT$(Ht$H|$&Ht$HL$(HT$H65IT$ Ht$HHHD$ ЅHT$HD$ HHHЅnHT$HM`IHHD$0HЅMHt$HL$(HT$H42)D  HT$(Ht$H|$%Ht$HL$(HT$Hu4HU`HL$(Ht$H|$U4     H|$HHD  AWILAVAUIATIUSLH8HL$(qHqHIqHHD$ qHHD$qHHD$qHH$qHHD$qH   HIIMIIT$HL      IIM ILIT$ L   txIIM ILIT$H4$   tXIIMILIT$ Ht$   t7IIW`ILHt$L   tHT$IO@HH2u01HV8H8[]A\A]A^A_1111E1E1    IO@H$HHt$2tHL$IIHLH   tIHLLL   tIO@Iwh   H|$aIHT$ILLL   ?HD$IW@HH[##LL$IO@H4$LLk!IIu HLHT$   HL$(IILIU H4$HI   IO@HT$LL1I}L,$LIO@L IIT$HLL   aIIT$ HLHt$   @IIO`IHHT$L   IO@IT$ It$H|$ 0Ht$ IHLH   Ht$ IO@LH* Ht$ IO@HT$H IO@H|$HLHt$IHLH   iIHL$ ILHT$L   EIHT$ILLL   #LLt$IO@I|$LjIO@HLL/IHT$HLL   IHL$ILLL   LILt$ ILLL   IW@LL kIO@I|$ LL15/@Lf.     AWAVAUATUSH(HB DI(LbHD$HF HD$HFH$HBHD$Et&HIHIHQILLL   u$1H([]A\A]A^A_1111E1E1D  IN@IV`LH<$tH$IHLH   tIINhILIUHt$   tHD$IN@   HHiIN@IHT$H4$KLLd$IN@IV`L-+LILd$IIULL   IN@IvhLL-IN@I    Lu     It(Iv@I1HauH{ tIv@H{ 1H9utIIwL  Mt9HHLAЅMHs IHLH  /IIwIW HILH   
IwIILIOH   IHK ILIUHs   1AG(C(   ff.      AWE1AVIAUIATIUHSHH   HRiH
jHHu"Ht$It$@1HHu1_f.     I$IHLLL   tIT$@HLL@HtsI$HILLL1   H1L{H[]A\A]A^A_1111E1    H   zHHtI1H\|   1H={ I1Ҿ   1   vAWIAVAUIHATIUSHhLhLHhIHu9  H8tTcIu@1LH',uӻ   L0H[]A\A]A^A_1111E1f.     IE L  MtLHHLAЅtIE Iw MHLH   tIE LHLL   sIwIE MLLH   QIE MHLLL   0IwIE MLLH   AG(        #H|z   1H=<z 1Ҿ  1   6AVAUATUSHt;HHt3MIIH"MHHL[L]IA\A]A^ Hz   H=y 11Ҿ    [1]A\A]A^1111E1E1ff.     @ AWAVAUIATIUHSHH8aLH  N  ED$(EtA}(  HE H$    H   L   HL$H  H`eHfHHD$fHHD$(eHHD$eIH   Au(Q  ID$HD$ AL$(  IT$ Ht$HHAׅ   L|$(IUIHHL$HD$LЅteH|$ L؂¸   uRAU(a  IM HD$ILLHЅt&IT$Ht$ILHD$HЅ.  @ H߉D$,H<$D$H8[]A\A]A^A_1111E1E1D     H8[]A\A]A^A_1111E1E1fD  H8[]A\A]A^A_1111E1E1fD  IU HHHAׅPIT$Ht$ILLL$HAх-HD$HD$ ofD  H   wHH   H$    M}    ID$HD$ AD$(   Lt$IL$ IHLd$LLAԅIUHt$(ILHAԅuFD  IuI|$IuI|$܀    M}H|$ L跀/f.     [fD  AWAVAUA   ATIUHSHH8.  HD$    HE H   L   HE@HL$ HD$(H  HbHbHIbHHD$bHHD$bIH  IT$HLHAׅ  AT$(=  IT$ Ht$HHAׅb  HT$Ht$HHAׅG  HL$HT$ILHD$ HЅ%  Ep  HM`HT$IHHt$HD$ Ѕ   HL$(HT$LL#   IL$HD$ ILLHЅ   HUhHt$ILHD$ HЅ   HL$(HT$    LL#tyIT$Ht$HHAׅtbH|$LE1BEAPf.     Lt$(HU`LLL9#t%IL$HD$ ILLHЅuif     AH(H|$H8D[]A\A]A^A_1111E1 H   \tHH   HD$fD  HUhL@ HT$(Ht$H|$tHt$HL$(HT$Hm"UHL$(HT$LL^3 A=D  AWAVAUATUSHN(t+A   HD[]A\A]A^A_1111E1     IHHAąuE1H   H^H_HI_HHtILHLHD$uH
'LrhD  HL$ILHL
t̋E(t7A       I   rHHIY     Hr   H=q #1Ҿ 1   Yff.     AWA   AVAUATUSHHHT$H$H   HD$    IHH  L4$L]Ln^LHD$a^HD$ H   H      H5q E1HHD$(~HHu   fIOH9   I*JD HuE1H<$%H|$E1fD  -IL9t
J| HuP  H5p H~HHD[]A\A]A^A_1111E1E1E1ÐH<$'%H|$E1     H   qH$HD$HHD$HL$0H Hx HL$0   IE H} HL$0H(  HL  HH$LHL$0   HD$HT$(LuL`LH   L|$8MMH\$0LL4$5fD  IHSMLH3HH IE    t.IHM9tyIHx 
tHsH;mtHuH\$0]fD  HD$H} H Hp CtHL$0H>D  H<$#H|$-E1*D  L|$8H\$0HD$(H$LHt$HTIE   @  IE H  Ht6HT$H$LHЅtHT$IE LH$H  hM   L|$(MLd$L|$ H\$ H\$ JHx udIE JTLLL$L     JL$LLLHH IE    l  JLHx sHS  IuL|$(H\$ HD$H Hx j|  Hl$(Lt$E1H\$0H,$L|$ H\$.HHLЅ   AG(   ID$L9d$ S  IO<I uIE IW HHL      IwIE IHLH   tfIE IO IHHL   tHIwIE IHLH   t*IE I H(  H0   1Hl$(\   HL$0xH\$ IHm   H=dl 1Ҿ  1   ^H<$!H|$k9HD$Ht$H Hx @qHeHl$(H\$0A   ff.     fAWIAVIAUIATUHSLHHH~ zZ  I~ iAą  HXHXHHD$0XHHD$XHHD$8XHHD$(XHHD$}XHHD$ pXHD$H   IU@IwH|$tlIE HUILHL$Ht$   tJH|$IE IIV HHL   t'IE HU ILHL$Ht$    u}D  HxHHD[]A\A]A^A_1111E1 LHbAątHHLE1EAD  HHHL[]A\A]A^A_    IU@IuhH|$
nHt$IE ILIV H   JIE HU HLHt$(   )IE HL$ILHT$(Ht$8   IE IM`ILHU Ht$   IE HMILIWHt$   H|$IM@HT$HH|$IE IIV HHL   sIWIE ILL|$0HM L   KLIM@HuL|$0L|$L.&IE HL$ILLL   IM@HT$8LLHt$0IM@HUHRHt$0IE HLH   Ht$0IE ILINH   H|$0IM@LHjL|$IE ILIV HL$L   AIE HT$(ILLL   IE L   MtHT$HLHAЅIE HT$HLH  IE L  MtHT$HLHAЅIE HuHL$ILHT$    IE HuILHL$HT$0   `IE H} H(  Ht%HHLЅ9E(   A   '   u@ UHSHHtH   []111f     H{GuH{Hu@H[]HmLff.     fHy(      AWE1AVIAUIATIUHSLHLD$M  Mt@HU@I|$HL   HE H  HtIt$HHHЅtcMt<HU@I|$HLtFHE H  HtIt$HHHЅt"H|$ tHU@I|$ HHt$u*1LH[]A\A]A^A_1111E1E1ÐI|$ FHU AH  HtIt$ EuAHHHЅtEl$(   fD  H   eHHt,I@ H(  HtHHхuQ 1QAWIIAVAUMATIUSHHH       HLE1M#  Mt'HLT$LHIWH   LT$AtJMtHIWHLH   Aąt(M   HIW HLHE1   ALEHD[]A\A]A^A_1111E1E1E1fHtHvHHL$hLT$HtPMtIwLhHt:Mt%Iw LE1hHAE1z    E1A   efE1E1XD  H   HL$/dHHtLT$If.     E1#     HG`tdw2   HwPHMD     H1111fD  uHOHWPHwH?Gu螼Hd /   )HOHWPHwH?輗usHd %   H=cd 11Ҿ      1nHwPH賘Vff.      AUATUSH(dH%(   HD$1H$    HD$    HtTHHH5
 AH8IEu@Ht/HCHD$HL$Ht$9   L_tHD$H9CXtc1h     HH5 HLH	tHtHSXHHsP^tH4$H9sXuKHCHD$MuH=tK   HT$dH+%(   u9H([]A\A]1111D  H{PT   Hb S:HCP    11fAUL-b o   ATALUHp   SHRH  HfHChH!  HE cHHEXHCXE`C`   CdH}Ht   LHCH   AtEuIAt%H}P tH  Ht_H{PHuPHSX~dHH[]A\A]111f.     oECoM!K!oU1S1o]:KA[:tHx  ùHa    L1=1Ҿ  1   wD  苹Ha r   D  Hߺx   L1mCAWMAVAAUEATUHSH(dH%(   HD$1LD$`A   IHtCH11LD$Ht$)|$LD$  LD$I<$  fLD$Ht+t'
  tY?  tQ       A9tb襸H`    H=` 1Ҿf   1   E1]D  A u
  t?  .  1
  @L   L  IH,  EuGHxIcHxbHD$dH+%(     H(L[]A\A]A^A_1111E1E1@ HX  IH  A  
     ?     1Ɂ  H8HE I~HHIHD
IDI)DL)HLhH[Ht_    H=K_ 1Ҿ   1   p                   dLD$9H_    ?     A8tD      fD  8
  t`?  tX     1ɺ9   HLj-fL   [Ht^    f.     1ɺ    LL-~
  AFA&@AFfD  H^    H=] s1Ҿ  1   Q õH]    H=] ;1Ҿ  1   #1ɺ8   HLq,	A&AN7v,fD  AUII1ATIU1SH(dH%(   HD$1H\$HL$HT$H t_HcT$H1_HHtwH]HHD$Ht$D$HMA   1AUH|$ lHHXZHD$dH+%(   u6H(H[]A\A]1111E1E1 HD$    11D$    +@ AWIp   AVIAUL-\ ATAԺ   ULSHNLH   L8H@AA	DctxwfHHH8HCXk`   CdMt*   LLHCHtKHChHt=HH[]A\A]A^A_1111 uHCX9   띐HCX    fD  苳H\ 4   L1Ҿ  1   5   LH|g1H   USHHGdt~H[]11111f.     H-v[ H{F   H gHsXH{PHG   C2H{h@HHHߺI   []f@ 11111D  H711        Gd1    SHHX_   H5Z WHCP[111f.     HG =
  t=?  t=  81     1HG =
  t#=?  t=    1       1     HG =
  t   =?  t11ú   11@    f.     u       11 11ff.         f.     @   f.     r   f.     1D@1ÐSHHHHH1HtHCHߋ0K   [1111    ATIUHSH^ HtH߾   HHt(u HLjKt[]A\111 HP[1]A\111 H 7    AUATIHUSHHFHKH       IōHsa1
  @H{1HHtx   LHtDHډLJt3H   []A\A]1111 1  @ƍt6fD  Hx1H[]A\A]1111 諯HZ   H=9X #11Ҿ     1ff.     
  fD    fD  ?  fD  @  fD  AVAUIATIU1SLw PHtkINXIVHHH5' KtdIVPHtkINXH5 H߽   Kt?HWLIHAԉHLw5[]A\A]A^1111@ 1E1f        f     HG H   H   L@PM   HGL
 =
  te=?  t^1=  1H8I9rUH
I H~HHIDHDHLH)H)Ƹ   H1111E1E1fD      1I9s1111E1E1D  11111E1E1    HG =
  t3=?  t,=  H8H   1111E1E1fD      f     HG H   H   HOL	
  ti?  ta  H81I9r9H
HxHPH>HD	H~HHDHH)H)HH   1111E1     f     HG =
  t3=?  t,=  H8H     11111E1ø    f     ATIUHSLO`HMtLrH* IHEHE1L1j HX1YHtHEH0F   []A\1111E1E1f.     ATIUHSLO`HMtLHZ* IHEHA   L1j 9HX1YHtHEH0/F   []A\1111E1E1    U1HE1SA   H1HHGx1j HX1YHtHCxH0E   H[]1111E1E1@ UHSHH	   
   H H   HC =
     =?     1=  @H8H   H6S HE HtjHC =
     =?     =  8H[]1111E1E1     HGHE1E1H1j ZYHuH1[]1111E1E1fD  HSHߋ2HDH   []1111E1E1D      !fD      YfD  AUATUSH8dH%(   HD$(HF HD$    H   H@PH   HD$HFHH =
     =?     =  8Ht$H|$D$HD$     $Aą   HCLl$80H1ATHME1HKX   Y   HT$(dH+%(      H8[]A\A]1111E1E1D      ^fD  蓨HR l   H=!Q 11Ҿ{      1@ [HR v   H=P 11Ҿ     p1Of     H|$HP Ic|   HHXR }   Hf     HG Hv HtcHt^HHW
  t<?  t4  H8HHxH111@     f     111@ AUATIUSHH~ H  HFH =
     =?     1=  @H8L-O H)   L0HH  HC8
  tn?  tf1ہ  Ã8.AIH1L¸   t8H[]A\A]1111E1E1        ffD      롐1   LHZ[HP 2   L11Ҿ     t1+HtP %   H=N 11Ҿt      @1Qf     H4P +   ff.     fSIH1H dH%(   HD$1HL$HT$Ht$Ru+1HT$dH+%(   u]H [1111E1E1D  HCHE1E1j T$Ht$H|$ ZYHtHSHߋ2H?   7    H   ?  1A   %   H1111E1H   @  1A      H1111E1U1LSHH(dH%(   HD$1Ht$H|$3H|$iR-?  w|$tXsHN *  H=M 11Ҿf      1HT$dH+%(   u3H([]1111E1E1Ð111IH$ff.      AUIATMUHSHH%H    HtLH@tH1[]A\A]1111E1E1 LHL HL[LHHH]A\A]kD  sHlM b  H=L 1Ҿt   1   fD  AUIATMUHSHHuH   ) H   Mt+H;?vMHL@PHHLj E1HLMZYtXH@   H   []A\A]1111E1E1 賢HL 5  H=AK +1Ҿd   1   1H[]A\A]1111E1E1D  cH<L ,  H=J 11Ҿt      x1@ AUIATMUHSHHeH    HtdHrtH1[]A\A]1111E1E1 H8pLLj HE1L@ZYH[]A\A]1111E1E1     蛡HDK t  H=)J 1Ҿt   1   mff.     AUMATIUHSHHH   I H   Ht3H} qvTHLHPH8pj L@LLj HH tXHE r   H   []A\A]1111E1E1fˠHTJ P  H=YI C1Ҿd   1   1H[]A\A]1111E1E1D  {HJ G  H=	I 11Ҿt      1ff.     U?  HSLH(1ɺHH8Ht?  '1ɺHHH   []1111E1U@  HSLH'1ɺHHؽHt@  '1ɺHH跽H   []1111E1Ãtu   1111 SHHtGH9t=HHI   H=G 11Ҿ      ]1[1111Ð   [1111ÐAUATUSHHH   HtgH    t]IH H   I M   IUPHtyH   HI$HE H   []A\A]111fD  {HH   H=	G 11Ҿ      萿1H[]A\A]111D  3HLH   H=F 諽11Ҿ{      H1@ HH   H=F s11Ҿ      1{f     UHSHH(dH%(   HD$1HT$Ht$tIHtHT$Ht$Ht.HE 8      HT$dH+%(   uH([]111@ 1Off.     @ UHSHH(dH%(   HD$1HT$Ht$tIHtHT$Ht$H:yt.HE        HT$dH+%(   uH([]111@ 1ff.     @ AVAUAATIUHSHFLv 8>IA   MH  L-m 1LLH5PE   1LLH5    HEK =
  I  =?  >  1=  H8IvLl[]A\A]A^1111E1M   I~P    L- 1LLH5wD O~[1LLH55 5~AHEK =
     =?     1=  H8IvPL[1]A\A]A^1111E1f.     H
% H5C L1[]A\A]A^1111E1f.     H
 H5C fD      fD      Zff.      1f        fD  HY$      HI$      H9$      H)$      USATAUAVAWHd$HLLbLjHjLr H|$ HIL$HHHILd$IHO<IILl$IHK<~IHIHIIIHFIHHHFHHIHFIHIHF IHHkIHFIHHl$IHFIHHHFHHIHF IHHkIHFIHIHFIHHl$IHFIHHHF HHIHFIHHkIHFIHIHFIHH,$IHF IHHHFHHIHFIHIHFIHIHF IHIIH|$   ff.     ff.     fD  USATAUAVAWHd$HL~Hn H|$ L4 HHHFHIILL<$IIIHFIHkIIHIIIHIHIHFIHvH, HIH$IHIHIHIHIHkHHH6HHIHIHIH$IH4 HIHIHHHHHIIH|$     H LI3I
H!M	MI HH3H
H!H	II LI3I
H!M	MI LI3I
H!M	LMI3I
I!M	O4O<wLIH!I3LIH!I3LHHOHWH_LW L|$(Lt$0Ll$8Ld$@H\$HHl$PHd$Xff.     USATAUAVAWHd$ظB H&HøB HHfIB IHfI¸B IHfIĸB IHf IIf
* 1    D    USATAUAVAWWHd$HH*HHHLpLx1fL8«fL8BHVfL8L4$fL8L8fL8L8fL8L8fL8BHVL8fL8L8fL8L8fL8L8fL8L8BHVfL8L8fL8L8fL8L8fL8$L8fL8B&   L8fL8L8  ff.     f     USATAUAVAWWHd$HHNHnHvb1fL8bHfL8fL8L8fL8bHL8fL8bHL8fL8L8fM8M8fM8HfM8L8fM8L8HfM8L8fM8L8b&   L8fL8L8    fL8L8fL8L8fL8L8BfL8L8fL8H|$LMI I I HH&ILOLWL_LL|$Lt$ Ll$(Ld$0H\$8Hl$@Hd$HúB FINIFIH Hk&II I I HH&ILOLWL_Lf     LLNLVL^LLJLRLZHH&II I LOI LWHL_H&ILff.     fD  LLNLVL^L+LJLRLZHH&I)I I LOI LWHL_H&I)Lff.     fD  LLNLVL^KI?HIIMI I H L H?IHHI)I I I LLOLWL_X25519 primitives for x86_64, CRYPTOGAMS by <appro@openssl.org> f.      He  Ht
   H1ÐH=	$ Ԟ   H1     UHSHHFuH[]111fD  HHuHH[]Dff.     Htw   111@ H蟐H>    H=T; 11Ҿ <   贱1H111    HtH7   111@ H?H8>    H=: 路11Ҿ <   T1H111    HtHw   111 HߏH=    H=: W11Ҿ <   1H111    HtKSHHHt
HP@HHC    HECH    H[  H5&: Cf     1111    AWAVAUATUSHH   L=9 HI   L(   'HH   HfH
 HI!  IH   H J LH LHz HCHM  Hi LL HtHLK HCHWD   H+LsHH[]A\A]A^A_1111E1 KH;    1H=8 1Ҿ 1<   ^@    L1H; 荭1Ҿ  1<   *uD  ۍHd;    LWH <   H8 H1H1%D  苍L  H; 1Ҿ 1<   褮f[H:    L׬HHIdM HM8 H<   1VmSHHHHtH[111fD  Ht$VHt$HHCHuH: $  H=u7 811Ҿ  <   խ1럐AUATUSHH   HH   HHH/HS8IHtHHHIH   HH¸      H[]A\A]111fD  1a1H[]A\A]111fD  H9 >  H=6 [11Ҿ <   1@ 1	LS@1    L1ff.     HtHHt
]D  11 HtHw    111 H?H(8 8  H=5 跪11Ҿ <   T1H111    HtHw0   111 HߊH7 C  H=5 W11Ҿ <   1H111    HtHw(   111 HH7 N  H=45 11Ҿ <   蔫1H111    HtHG 1@ 11ff.     HtHG01@ 11ff.     HtHG(1@ 11ff.     HtH1D  11ff.     HtHG1@ 11ff.     AWAVAUATUSHHtUIHtMHHtEMMt=HIJHIMHLHIGxHL[]A\A]A^A_@ 3H5 w  H=3 諨11Ҿ <   HH1[]A\A]A^A_1111E1ff.     HtHG1@ 11ff.     AWAVAUATUSH   dH%(   H$   1H  H I  HHD$H  Lt$H5SHE1L%L=I|$fHD$h    HLd$PHD$D$XHD$     HcH\$pfHnL|$HI޹   D$`    flD$xHD$ H9   H\$@IŉL$<    I|$DHH|$ HD$X   HD$1Ll$0fD  H|$HHH*Ht$HI)5t8HD$ IL9rvfD  IM9sgI|$DJH H@H9CuHH9l$uLl$0HD$@II9;L$<HÉL$`   HD$h   HD$  LS8IHtHHH   |$<HD$(HuW
HH_4HT$(tWHLHT$(vHT$(t>IHL$   H9l$;D  HH4HT$(tHHH9l$LHS@H9l$vL|$HH\$hLt$pH\$ IL9tI
wLH58* H|$]   H$   dH+%(      HĘ   []A\A]A^A_1111蒅H2   H=G0 
11Ҿ <   触1^Hg2   H=0 ֤11Ҿ  <   s1d7    HtG HG11f     111f     AWfIAVAUATUSH   L6H|$dH%(   H$   1HFD$xN HLt$`HD$P    HD$X    HD$xD$hH   I~vHHKAg IIF HtIV0Ht$HЅ0H|$H5.v 藴Ht
x  D$0    1@ AO 1D$0   HXH|$h藃H$   dH+%(     D$0HĘ   []A\A]A^A_1111E1E1@ L0IOHIGHL$ HpH|$ 11Ҿ   腈D$4HHD$8H  H|$ XHH<  IWD$0    HjH9HD$LHL$(HD$`  fD  H|$L0;  Ht$PHtL0!  H|$XH  H
  HB6   AG u#IvHtAO H6   D  H\$ HT$81ɾ   H菇11Ҿ   H~9D$4  AW Hl$pH$   H
bL
k 	Ј$   HD$hPH8PHt$8H|$ LD$pAUp$   D$@AG 	AG Z^    $   X  HN  I~HH HImHHD$ Ht$HD$L    I8H|$ HQI>HZL4J AG IvHHpfHxp${HD$ HD$hHH|$H57- `HHtHt$PH|$H5- 5HtHt$XHH|$P H|$XtHtH5i 4u	HD$X    Ld$IGfHL$(mfD  kH. 0  H= + 1Ҿ   1<   耡 HL$(HL$	HL$H. 5  H=* 蒟1Ҿ  1<   /D  AWAVAUATUSHXdH%(   HD$H1HY  II.  11Ҿ   LH荄%  Ld$(Me8fH\$ L)D$0HD$@    Ll$ H H1^AD$@  1Mu M}M  M,  Hz+ L-]m HD$H HD$HI+ HD$TH9t
HuR~HY- e   H=) XHMLAWH*  1t$ <   t$0LD$(ןH Lk H   E1HGH~   f.     
HSHH   LMe8Lt$ H3fLHD$@    )D$0Ll$ HD$( L1AD$@L kf.     }HT, ;   H=( SH4) f   1<   E1HD$HdH+%(      HXD[]A\A]A^A_1111E1E1@ LH fD  [}H+ 6   H=( Ӝ1Ҿ 1<   pfD  L-- Ll$MLl$Mt/HS) HD$fD  L- HG) HD$Ll$Ll$Mff.      ATIUHS	H詬HHt9L1Ҿj   H菁HHH|[]A\1111 c|H* |   1H=' ٛ1Ҿ   1<   v@ AUATUSHHtQIH>HHtCHHt;2vLHIAąuoL{HD[]A\A]1111Ð{H*    E1H=}& @11Ҿ <   ݜHD[]A\A]1111    H1Ҿ   LnA   HE pf.     D  HHr"    HG Ht1@ SHH?$ HC [1ff.      ff.     AWIAVMAUE1ATMUHSHHHT$Ht:   H	II)H   I<$ HHt~HL~! ÅtmHtKH5-* LHt$MHL
0* = ZYH[]A\A]A^A_1111E1E1fD  I<$H]$    c HHuH1[]A\A]A^A_1111E1E1@ HI>     AVAUIATIUSHHjdH%(   HD$1H$    uPHz    H: Ls:   HLHL)H   H}   HLR  ŅtlMtGHSILL tOH$HT$dH+%(   uSH[]A\A]A^1111E1 H;H6$    <
 IHu@ 1@ LдHb Ht醼 fD  HH>H$     HHtHW     1H111 Ht fD  HH>H$     HHtH     1H111 ۺ ff.     G(   1 -ff.     AWL={ AVIAUATIUHHSfHnHfHnH   fHnH$ H   H?dH%(   H$   HfHnHfHnH  flfHnfl)D$fl)$)T$  I>I MHD$@    MEMHD$0HT$?  Ht<  HD$>L$>t     fot$Af(M1AF    fo<$HT$HH  InI>LD$P   M~)t$Pfot$ H$   HD$H    )|$`)t$p HD$@H  H  |$? AV(   H$   dH+%(     HĘ   []A\A]A^A_1111E1E1@ LD$@L1L 1҅   fo|$Af(M1A^I>LD$PH  Infot$ HT$H   M~)|$Pfo<$H$   HD$H    )|$`)t$p- HD$@IH  AV(҃fHD$@HA
 A)Hp  kuHt%   H=# H# I>MLDHHD HADATHH# 1I<   QHD$PZYD  H|$0HS Å@ tH$ }  H=h# S11Ҿ <   1>f     H|$0H Å   LD$@HHY  LPHt$XL
GL AV(^_HD$@҃H;tHD$ t  H=" 賓11Ҿ <   P1f     H|$01҉ Hzf.     AV(҃At$>@t$?Bff.     fHt{USHHG(t~H[]1111H{H-" =   H'H{  H;G H{0NHHHߺA   []`'     1111    &ff.     &ff.     AWAVAHAUL-! ATIUHSHH^v    L   HD$
IH[  nIG0HI     AG(EwH,
 IGH  HuH|$Io IG H  I8H
C! Iw@t6 w#HcHf.     HW      CHuH  H  Ip   MtLk 3  M'HL[]A\A]A^A_1111fD  Ix uHCHIGx[댐Ip uHCHIGp7ef.     Ih EHCHIGh5f.     I` HCHIG`f.     IX HCHIGXf.     IP HCHIGPwf.     IH HCHIGHGuf.     HWHsCHIw@F L $KpHt  "   LǏ1Ҿ  1<   dE1<@ HL#pL'  HC  ~1Ҿ 1<   f     H{CHI8q@ Lx#fD  ATIUHSHH+ H H1:   H t%HHމ`Ht[]A\1111fD  AL$(1[]A\1111 SHH1H@dH%(   HD$81H<$HHD$     H|$ HHt茱 HD$8dH+%(   uH@H[1111fD  SH1H@dH%(   HD$81H<$HHD$     H|$ HHt HD$8dH+%(   uH@H[1111if     HHe$    k Hu   H111fD  HHD @ SH H $    H# Hu   [111ÐHH[鄵 @ HtH111ÐHmH   H=D /11Ҿ <   ̎1H111ff.     @ HtHGH@111@ HOmH    H= ǌ11Ҿ <   d1H111    HtHG 111HlH   H= o11Ҿ <   1H111ff.     @ HtG111ÐHlH    H=$ 11Ҿ <   謍1H111ff.     @ HG1f     HGH@1D  U1SHHH?Ht$H H= HHb 9CH[]11ff.      AT1I1UH1SHHPdH%(   HD$H1H|$H|$HD$0    H|$0L$$IHl$H-9HtLH蹳 H$    H LHH藳 H|$0Ht HD$HdH+%(   uHP[]A\111110Ht[AT   USHH?Hu[]A\1111f.     HI H
 sL[HH]A\      11111D  Ht;SHP Ht H HHCP[f     1[1f.     11ff.     HtHGHHt
HD  111ÐHt;SH` Ht 蛫H# HHC`[f     1[1f.     11ff.     UH-   h   SHHHHtHH[]111f     iHﾎ  H '11Ҿ  <   ĊHH[]111@ AWAVAUATUSHHt$H   H H   LcMtyE1A   H}D4IHLHΟHHtHCXHtHt$Ѕ    DDIM9uHD[]A\A]A^A_111f.     A        hH   E1H=5  1Ҿ 1<   轉ff.     HtKSHG(HHtH0H{H5؞H{8O H[  H5 Rf.     1111    AWAVIAUATUHSHHHdH%(   HD$81HIH$蕞LHD$8H5 LIHto1HHt$ HD$     u51HT$8dH+%(     HH[]A\A]A^A_1111E1D  H} _   H5 sHD$ HE H5Bm L蓗HtxuHHH}H@HL$HD$^Aƅ~~E1
AE9toH}DHHII9uHg tHu HtE9}/HOHu>HE(H8     HUHu H} mHHtHIM9tsE   H\$ LD$ HD$(    H
N Ht$H|$DHT$D$0H$PxLd$(MtLH)V Ht/IĐHE(HL JHT$Ht$Hf ILHH$e H$ff.     AVIAUATUHS
H	AF   I>H   IHEhHtIVLrЅtrI>J]1LcMu    HI9tI>EHHtLU8HHtAHHIHteI~HtAF[]A\A]A^1111L7AN[]A\A]A^1111ÐAf[]A\A]A^1111f.     HU@AN HHHBfUHSHHuH[]111fD  HH
HH[]ff.     UH- SHHHH5%* 蠚H{H   'H{ H   HHHߺ   []      Htf     1ff.     fH8     H8     H8     H8g     AWAVIAUATIUSLHHH|$HL$dH%(   HD$81D$    HtH5 HkD$     P  H5 0   
HHy  Ht!R  H5x HHEH   FHEH   4IH   HD$H|$Lu(H5HU@H} E0^H}gZAƅL  1      D$  A9(  H}MIMtLHtLLH5褃AǅubH q  H= 老1Ҿ 1<   9 aH U  H=X K1Ҿ  1<   E1E1HjL"HD$8dH+%(   A  HHD[]A\A]A^A_1111E1ÐH5 LD$-H5 L!@ H\$H|$HT$ H5ZHD$0    Ll$ H\$(©LzD$47HA   E1N$H\$H5H"HH[H5H| s`U  E1E1HA H= 1Ҿ  1<   肁H     AWIAVIAUMATEUHSHH|$	hH   LHHtNHH[t?DHt0LD$PHt$LLHHtHT$PLHu
H1HH[]A\A]A^A_1111E1E1fD  k_H$   H= ~1Ҿ  1<   耀f.     @ He rHt
   H1ÐH=I|$ l   H1     HHtWt7   H111Ð^H    H= C~11Ҿ ;   1H111 ^Ht    H= ~11Ҿ ;   1ff.     HtHtHw   111fD  H'^H    H=D }11Ҿ ;   <1H111ff.     @ HtHtHw   111fD  H]H0    H= /}11Ҿ ;   ~1H111ff.     @ HtKSHHHt
HP@HHC    HMH    H[   H5^ Qf     1111    AWAVAUATUSHHI  HH=  HHBHZ HS8IH  L=
        LIH  Hc  HH# HI8  H  H LHHD$x LH
 HL$HIE  H LHI HtHL IEH}I] MeH   L踩¸   LuD  1H[]A\A]A^A_1111E1@ 1I    [H %  H= #{1Ҿ 1;   |fD  HEHHc^[L  HO z1Ҿ  1;   w|Ef+[HT    Lz1Ҿ 1;   D|L1LS@
f.     ZL   H
 Wz1Ҿ  1;   {fZH
    L'zHX <   H H1{k    cZH
    LyHHH|XI H H<   1^{f        f.     HtHHt
QD  11 HtHw    111 HYH O  H=
 7y11Ҿ ;   z1H111    HtHw0   111 H_YH Z  H=|
 x11Ҿ ;   tz1H111    HtHw(   111 HXHx e  H=
 wx11Ҿ ;   z1H111    HtH1D  11ff.     HtHG1@ 11ff.     HtHG1@ 11ff.     HtHG1@ 11ff.     AWE1AVIAUATUSHH  dH%(   H$8  1H   AFh  Ld$XE1E  IHxHHbHHD$腺HHD$ؾHH$AvfIHAF A$AD$AD$ AD$0D$pFHT$Pl$`H\$hD$dE   HrHtH<$HL$

  IHL$HzHtHtH
u9AF Ll$PLoL$xH$   H$   IV8AN(   H I~0  H
IF0    1RVH$8  dH+%(   z  HH  []A\A]A^A_1111E1E1f     H4$LHL$/pI~}IRD  E1>F@ '    He  I~(Hl$ L$   IV@1HH5 H$voT$ o\$0HT$@H$)$   H$   )$   HtEH1H5 H0HD$@oT$ L$   o\$0H$   $   $   IN8IV0H5BG HHMod$ HA$$ol$0Al$HD$@ID$ ot$ H$    H$   At$(o|$0A|$8HD$@ID$HE  I~E1HL$1*IHt4IHL
ˣ LD H8PHD$HL$(HT$H|$ PpZYL=)I^(I~0  H5 IF0    Mt11Ls   LUYHD$PfHPIV0HIV8 @LSH<$ qIHx0P(b@ HA   HxG      An 2IHHp0P H|$H$HR1IF@HH 1f     SH H 1K  Hs1Ҿ 1;   tfD  HL$FSHNIHt*HL$H\f     H$    14,11'I^(I~0  H5/ "1IF0ff.     @ UfSHHXdH%(   HD$H1D$D    H<$Ht$D$D$$D$4ΐD$t~H{( t?H{  t8H@HT$HdH+%(      HX[]111    KRH ?   H=h q11Ҿ ;   `s1@ RH\ 7   H=0 q1e   H ;   #s1d    ATIUHSH蹁HHt9L1Ҿj   HVHH$H*Q[]A\1111 sQH L   1H= p1Ҿ  1;   r@ AUATUHSHdH%(   HD$1H$    H   IIPHHHtHL|u81H~PHD$dH+%(      H[]A\A]1111D  1Hs   HUH~H$HM   I} HtpHM H9rH)HpHM HH$H IE    i    CPHL h   H=` o1Ҿ 1;   Xq5 HU HPIU H@    f.     HU D  HHr"    HG Ht1@ SHH?贒 HC [1ff.     雒 ff.     AWIAVMAUE1ATMUHSHHHT$Ht:   H虹II)H   I<$q HHt~HL ÅtmHtKH5* LHt$MHL
* ͒ ZYH[]A\A]A^A_1111E1E1fD  I<$HMl$ 
    HHuH1[]A\A]A^A_1111E1E1@ HpI>     AVAUIATIUSHHjdH%(   HD$1H$    uPHz    H:i Ls:   HLeHL)H   H}   HL ŅtlMtGHSILLS tOH$HT$dH+%(   uSH[]A\A]A^1111E1 H;H&k$ 
    IHu@ 1@ L`Hb Ht fD  HH>Hj$ 
   x HHtH     1H111 Ht馐 fD  HH>Hj$ 
   ( HHtHw     1H111 k ff.     G(   1 ff.     AWL=O AVIAUATIHUfHnHHSfHnHfHnҾ
   Hi$ H   H?dH%(   H$   HfHnHfHnHj  flfHnfl)D$ fl)$)T$& I>I HHD$@    LEMHD$0AHA  t|M  to1LD$@LL+   HD$@1H  H$   dH+%(     HĘ   []A\A]A^A_1111E1E1E1f     H|$0LD\$? D\$?ofo|$ Af(M1AF    I>HT$HH7  Mffot$LD$P   M~)|$Pfo<$D\$?H$   HD$H    )|$`)t$p0 HD$@H   H|$0L LD$@v@ fot$ Af(M1A^fo<$LD$PH  MfI>HT$H   M~)t$Pfot$H$   HD$H    )|$`)t$p HD$@IHtfHH;  LPHt$XL
ILa ^_HD$@AAV(Mu	EN҃;    D\$?     AV(҃A
 A)M   IHx   H= iHH HDI> HAMUHH 1D;   }jHD$PZY+IH ~  H= h11Ҿ ;   @j1vf     HH   H=@ ch11Ҿ ;    j16f     H|$01҉ IHH   H= hH HHDMLDs Ht{USHHG(t~H[]1111H{H- =   H@H{ 诮 H; H{0HHHߺA   []     1111    ff.     ff.     AWAVIHAUATIUHSH1 H I1:   H    HM~A        H5 HD$UHH   sHC0Hts   C(DkL HCH  IvH|$Lsh HC Hk  AHs8Hm H{@      HcHfD  HFHT "   H=  #f1Ҿ  1;   gAL$(1HH[]A\A]A^A_1111fD  H_      AGIhHO  HO  H{p [  HtH   H+뉐H    uIGH   f     H{x uIGHCx    H{p uIGHCphH{h ]IGHChP     H{` =IGHC`0     H{X IGHCX     H{P IGHCP     H{H IGHCH     HIH{@f.     IwHs8 HH{x H   tYHHDH| 1  H= +d1Ҿ 1;   e H HAD  SHH1H@dH%(   HD$81H<$HHD$     H|$ HHt輆 HD$8dH+%(   uH@H[1111fD  SH1H@dH%(   HD$81H<$HHD$     !H|$ HHtO HD$8dH+%(   uH@H[1111虺f     HH`$ 
    Hu   H111fD  HHt @ SH H`$ 
   HS Hu   [111ÐHH[鴊 @ HtH111ÐHBHp   H=< _b11Ҿ ;   c1H111ff.     @ HtHGH@111@ HBH 	  H= a11Ҿ ;   c1H111    HtHG 111H'BHp   H=| a11Ҿ ;   <c1H111ff.     @ HtG111ÐHAH   H= ?a11Ҿ ;   b1H111ff.     @ HG1f     HGH@1D  U1SHHH?Ht$H Hm HH 9CH[]11ff.      AT1I1UH1SHHPdH%(   HD$H1H|$H|$HD$0    1H|$0L$$IHl$H-HtLH H"^$ 
   H LHHǈ H|$0Ht HD$HdH+%(   uHP[]A\11111`Ht[AT   USHH?Hu[]A\1111f.     HI赾 H= sL[HH]A\      11111D  Ht;SHP Ht +Hü HHCP[f     1[1f.     11ff.     HtHGHHt
HD  111ÐHt;SH` Ht HS HHC`[f     1[1f.     11ff.     UH-   h   SHHHHtHH[]111f     >Hﾐ  H W^11Ҿ  ;   _HH[]111@ AWAVAUATUSHHt$H   H H   |LcMtyE1A   H}DdIHeLHHHtHCXHtHt$Ѕ    DDIM9uHD[]A\A]A^A_111f.     A        =H   E1H=- P]1Ҿ 1;   ^ff.     HtSUH- SHHHH5tH{0H  H{8q HHHߺ  []s 111ÐATUSHLgHo HHtdH{    HC     I9t[]A\11 HC    []A\11ff.     @ AWAVAUATUSHLfMt!HL[]A\A]A^A_1111E1@ HH-dL;II`辬LII9t>SIwhHkII`H
5   ЃE%? tLc Lc{@ MghLcj AUATIUSHHLnLcLHɞsLHUxHHC H[]A\A]111ff.     @ F,  AWAVIAUATUHSHH>F,   H   3LcM   E1     IM9   H} DwLIHHH9]HE(8uLLHL$qtIFhHL$HtHU Hϋ2ЅtH;]tI~x zH} LffD  E,    H[]A\A]A^A_1111111111D  Ft111ÐSHFHH;K~c[111ff.     AT   UHHH5U SHH   dH%(   H$   1H|$0IHLwHD$ 1Ho$oL$H5Qf LHD$P)D$0)L$@wo$o\$HHD$ Ht$0T$XHD$x\$hH$   dH+%(   uHİ   []A\1111诰ff.     @ H8}     H8     H8~     H8G     AWAVAUATUSH   LD$dH%(   H$   1HN  H  HAII  HHf  Lu`MtLH} ILH菍  MtLH5  DH$l  H}`H7  躨HHD$ H}` HD$  L-    (   LdIH  éHD$PH-  H}`HT$Pd$XH5pYD$X  ~CH|$HT$`H5*~L$PD$HT$K)D$p)L$`$   Ǆ$       H$   =HT$H|$H5$   =H|$P$$     Hu  1H:?  LL HT$LH  EHfH|$ H56 HT$`)$   D$`)$   )$   )$   )$   ׿oT$ Ho\$0HD$@H$   )$   H$   )$   ޯfD  H$   dH+%(      H   H[]A\A]A^A_1111E1Ð{6H *  LU1Ҿ  1;   W1H9?  LLbf.     H1膯iHh 6H S  1H= UH7  1;   W!f     5Hd N  1H= AU1Ҿ 1;   Vf     5H$ Y  1H= U1Ҿ  1;   Vf     H|$Pִ;5L   H T1Ҿ  1;   TV    5H|   fH5	HLH>8rH5Hu[I,$E|$I謫f.     f1 v  $@ Hf.     {H=* HHuH=* ۳H*     H11    SHt?H=d* HtHρt   [11{H<* HHuH1[11ff.     AWAVAUATE1USHHHHt$dH%(   HD$81NHHGHHy  Hs+D9  f.     DHu.   HD$0LxLpLLt$肝H|$LHPHIDHT$՚IHq  D$     E11Dd$$H\$(   D  H5 H1   H5 H   Mq  LH5{% Ho; H߅Hָ    LDHR;   H5 H  LL$V   @ L=*9=  LK.   HXIHgH5 MgHHPHEHQ	Ld$f.     D$    fD  H= tIH  1LH5 Ht71Hr H5 Lt11H5 L!LH- MH- I]1H꾋   HPIMN1MF&   f   HU jRL21HT$8dH+%(   /  HH[]A\A]A^A_1111E1E1    1LHLxR Ht$H|$HL$0V3HD$0H   H<LH- MH> Ix0HH߾v   O1Ҿ   1&   QH|$IHyD$   MdMH E1H-a @ Dd$$H\$(MtH|$0t~LHA'D9d   f.     LX2 /H <   H=N O1Ҿ   1&   PQL;r^/H    H=	 N1Ҿf   1&   sPL;Dd$$H\$(Wb)
/Hv    H= N1Ҿ   1&   "P     HIH5H= ƭfD  AWAVAUATUSHH   L=* HIIMI?*u 1H[]A\A]A^A_1111E1@    T$I?FT$HCp   
   UwuH$  D   A   HMLLH[]A\A]A^A_D  -H    H=W [M1Ҿ 1&   N; Hu-H    H= M1Ҿx   1&   NfD  HH[]A\A]A^A_1111E1D  C-Hl    H= L1Ҿ   1&   XN G  
c  u	M]  H   H  DHtHy t9sQ H AuA9  McIJ8   H
> HcHBHrH~/ LHHDL;hHzHW/ HHDhHrLޫLhHzgB Hz( +H |   H=g kK1Ҿn   1&   MJH   H8.Hz %M   
H   Ht.U Ht$H{HtULtIC H AuE+H^ Z   H= J1Ҿ   1&   ZLMD  H{ tMcIBD= *H    H=g kJ1Ҿx   1&   L*H e   H=2 6J1Ҿ   1&   K*H R   H= J1Ҿ 1&   Kf     HcHE11ɾ   ҅xH1111E1@ *H    H= I11   &   (K1H1111E1@ AVAUATUSH   H   Hp HDt#IIMHE11Ҿ
   >   t"\[   ]A\A]A^1111E1E1Ð[)HD    H= H1Ҿ   1&   pJ[1]A\A]A^1111E1E1    )H    H= H1Ҿ 1&    JfD  MLLH߉u[]A\A]A^1111E1E1fD  AUATUSHdH%(   HD$1H   H   Hp Ht HIE11Ҿ
   Aą   t[   :     +(H   H= G1Ҿ   1&   @I1HT$dH+%(   M  H[]A\A]1111E1@ 'H    H=? CG1Ҿ 1&   HfD  H   E11IcԾ   H!     M     `  
   HL訃H$L9  :   E11Hf.     DH     &H   H=_ cF1Ҿ   1&    H Mt;&Hw   H=" &F1Ҿ   1&   G~fD  E111\@ c&H,   H= E1Ҿn   1&   xG3 E1L1 &H =  H= E1Ҿ   1&   0G %H 8  {%H '  H=A EE1Ҿ   1&   F訜     1ff.     f}   H5 ff.     @ HtcUH- SHHH>sH{H   ZH{(   HIH{PH5[HHHߺ   []# 1111ff.     @ AWAVAUIATIUHSH(  5) dH%(   H$  1xGHNIH   M7M       H HcH     L
E1111
   :Aƃ  L=* I?   5
) m  I?
5) HNIH`H(    X   HHD$IHq  DIFPH  H H
  AFH   fHnH * fHnflH8AF8g  I~PHt$   L@ S#H|$/  HJ B1Ҿp   1&   jDf.     1H$  dH+%(   W	  H(  []A\A]A^A_1111E1E1    "H 5  H= SB1Ҿd   1&   CfD  I?D5) 虞5) fD  IHWI ,  AHa  IPHAŅ9  H E1HD$7@ I?11HYqH  Ht$  HA2E9t%IPD	pIwI?HJkHHuf!H|$  H UA1Ҿ   1&   BI?ڽI    ~fD  I=  M~  A<$ s  H H?  HL|VI1MMw*     1MAG    f.     I(J  M  A<$   H8 HL  HLVI1MMw(I  Eo0I  EoHyD  MtA<$     H c  H= @1Ҿ   1&   AC^ H_ v  H= ?1Ҿw   1&   sAfD  H] HD$    5) H"JIH  HG) H8I~PnHt$   L4    H- g  LHTHH=  IPHQmUm  HHtHu n  H>1Ҿ  1&   @(     I( 1ɺ      H聠Iw(I?ufIG@ H5= $1D  H5% 15) HLfH) H8p  赚Ht$1M   	@ H    Hp HHD$>1Ҿ   1&   ? SH|$   H =1Ҿ  1&   j?D  AOHHI HD$# IwI?11 mHtIw@I?/IGH  AW uQIw8I?IGH     H=   I?H5 ڴHrtH  oU o]H\$oe om0ou@o}P)T$0)\$@oU`o]p)d$Po   )l$`o   )t$po   )$   o   )$   o   )$   o   )$   )$   )$   )$   )$   )$   7HT$(Ht$ H|$HD$WH  Iw   H  	  Iw(HHAW   AG0&H2PA0Z  zOD  +H|$   H ;1Ҿ  1&   B=D  H [  [fH R  Cf.     fI?AG߷I    H\   H= ;1Ҿ   1&   <S   Hv  fI?AG腷I    IH   H=r :1Ҿm   1&   ^<fod$0fol$@fot$Pfo|$`fo$   e fod$pfo$   mfo$   u fo$   }0fo$   e@fo$   mPfo$   u`fo$   }pfo$                     @[H\ i  EHt$  HV>I?QI    H   H=> 91Ҿh   1&   *;H   H=	 X91Ҿg   1&   :軐ff.     1ff.     fSHH   H5t HH   H5x Ht|H5H2tiH5HbKtVH5GH/tC   Ht2H56$ H+_trHLH[o@ H[߳[111    Hd  Ht
   H1ÐH=97$ D&   H1     H   AV   AUATIUHSHcH5 H9HFHI(8t<LH5G H8u6A$A$   []A\A]A^111    A$
  D  LH5 H7t2   H5o HH9HFI7u0A$    A$    1111    LH5 H^7t:   H5 HH9HFHI97u%A$"f     A$
@    H5x HH9HFHI6uA$@LH5Q H6uA$LH53 H6uA$   H5 HH9HFH~6uA$g
   H5 HH9HFHP6uA$91;f     UHSH@   À      u=uX               H[]11@ H耎u@ 1H[]11 HttED  {tÀkHkt_HqdO1D  HhtMHss=Hjr-UD  HH[]11ff.     fATH
wI   UH,   SHHdH%(   HD$1LD$D$    Rt8t$L輨HD$dH+%(   uVH[]A\1111E1@ yH V   H= 3H龖   1H &   5Off.     @ SHwHRHIHO HHdH~H(Hǭ   [1ff.      S(Ht6HHXHHt!   uHH7HHu߸   [1fD     SHuHG`HtЅu[1             [1ATUSH   u(HGhHtu{ЉŅu1[]A\111@    1H  t[]A\111     H J   1H= Q21Ҿj   1&   3@ L%) I<$蘎HShI<$`1_     USHH   HH5w  H=) t
H)  uJ5H Y   H= 11Ҿ  1&   J31H[]111f     H-A) H} PtHTH} ɍH[]111f.     H U   H=R #11Ҿ 1&   2qff.     ATU   SHtL%) HI<$
u1[]A\111@ H߾   I<$ uH o   1H= 01Ҿj   1&   *2     H=H() H1HH) H11 SHHߺ   [H5 D  USHH5H=) 7tcH)  tVH-v        H]HHt<      
   H   H tRHH[]111fH-  !   H1Hk ~/1Ҿ  1&   1f     Hߺ'   H1ff.     fHG     HG0    HǇ       Ǉ       HǇ       GG8GXGhGx1fH   UH   SHHu$~"H   []111    uH5  H(  HCXHtHЉH  H   H޿
   Hߺ`   H5 H   []111D     111ff.        &fD  H=)  ATUHStoL%       L6HHtfH(H=) 1HzS¸   t[]A\111@    LH81[]A\111 {H\) Hu1 
H<    L_-11Ҿ  &   .1     H=)  ATUHStOL%       LfHHtfH(H=) H,[¸   ~1[]A\111fD  ~H) Hu1[]A\111f   LHH1@ 
Hl    L,11Ҿ  &   ,.1     H=A) SHtH5WCH$)     H
) H;譚H    [11HǨ   d@ HǨ   @ HtH7   111@ H_H    H=c +11Ҿ &   t-1H111    HtHw   111 HH8    H= w+11Ҿ &   -1H111    HwX   11fHw`   11fHwh   11fHwp   11f      11H      11ff.     @ H1f.     HG1f     HGX1f     HG`1f     HGh1f     HGp1f        1    H   1fD  H))      AVAUATUSH  H    HHA     H) HtUHHu:f.     H   Ht$H;   uE1Eus[D]A\A]A^111ÐH    uH   H) H  HtH    uH   H   A   H-e) Hǅ       EtD  L51) I>х[D]A\A]A^111    L5	) I>E1[]DA\A]A^111@ Htu?H) HHE1H=)  H   H-) 1=fD  L5) I>tH) HHE1H    0@ HD  H   USHHH    tTu^H   Hǃ       HtH   H   H   HtH   H9) tMH9) t[u(H[]1111ÐH) H8u H) H8H[]C H   H9) H) uH) t@ 1111ff.     @ USHH5H=@) tSH,)  tFH-') H} 6tbHC) Ht   H} 襃HH[]111D  H    H= '1Ҿ  1&   (1HH[]111ff.      USHH5SH=) tSHl)  tFH-g) H} vtbH{) Ht   H} HH[]111D  H4    H=; C&1Ҿ  1&   '1HH[]111ff.      ATUSHtOL%) HI<$thH   Ht   I<$CHKH[]A\111D  #H| 	  H= %1Ҿ 1&   8'1[H]A\111     ATUSHtOL%() HI<$4thH   Ht   I<$裁H諠H[]A\111D  H   H= $1Ҿ 1&   &1[H]A\111     AUATUSHHU  H? H  H   L-f) I} uuH1ۉ[]A\A]111@ Hi) H8  Le @ H;L
H   ~  Huq  H") HtH      H ]   H H#1Ҿn   1&   %WH߾>  1H #1Ҿn   1&   n%I} %H[]A\A]111fHD 8  H={ #1Ҿl   1&    % H 4  H=C K#1Ҿ 1&   $ H) H   H N   f.     H   H         H-) Hǅ       fD  3H H   HP H"1Ҿg   1&   E$H=  DtH-q) {H U   Pff.      USHHA  H-) HH} u1H[]1111    H) HH9tHt@ H   Ht|H9uHtrH   HtH   H   H   HtH   H9   H;)    H1   H} }H[]1111fD  HW {   H HP!11Ҿi   &   "H߾P  1H "!1Ҿn   1&   "zf.     kH| J  H=ۿ  1Ҿ 1&   " H
) @ H   H) D  H=) Ht$H蛘H=|) HuH11fD  11ff.     AUATUSHH  H՛H5H=) b
  H)  	  L-) I} !  H) Hu0  H   H   H3H荵u     ?/IH   oKoC 11oLH@ HC0ID$0o[8A\$8HCHID$HoKhoCxocXAL$hAd$XAD$xH   I$      A$   H   LI$   I} {8fD  {Hd   H= 1Ҿ  1&    1HH[]A\A]1111     I} H  {HH]   H= q HHIH LDHH   1HH5J H؝   1H H56 H踝   1LH5# H蜝tj1H4 H5 H耝tN11H5 Hi1       I} 7zHH[]A\A]1111Ð1H&H   H= Ht   1H &   f     H z  H=; C1Ҿ 1&   Kff.     Ht      111    HgH@   H=׻ 11Ҿ &   |1H111f.     D  UHH SH   HH) H81WH5Щ HȏHt3H111HBHHgHH[]1111D  1HH[]1111ff.     USHH;) HtHH[]11þA   @   HHt   HL.u H`.H) HH[]11 @   H{tϾh   Hzt1HtH5a  HQtH5  HtH5   H@sHs USHHtEH@tH    1H[]1111D  HH   []1111@ ) t ) H) H@ HT$H) HT$HHtHc-) E) HT$Hc
) )        H     SH藀H[H髎ff.     UHSHHoHHHH[]k ff.     HGHHۅff.     USHH+) HtHH[]111fD           4HHt1Hu&HHH) HH[]111       H[tH5  HJtH5m  H5t  H4tHff.     USHHS) HtHH[]111fD           4HHt1Hu&HGH) HH[]111       H苀tH5  HItH5  Het  H3tHff.     USHHtUHt=atH    1H[]1111HH   []1111@ f     ) t ) H) H@ HT$H) HT$HHtHc-) E) HT$HT$kHT$HHtHc-) E) HT$Hc
z) t)        HhHH=m) )H=q) HV)     )FH=R) HO)     F   H2)     H1ff.     ATIUHSHLHHHx<[   ]A\1111f.     ATIUHS1.      H=ȶ H) H~<HcHcLH5HMHIBL   Hxs[]A\1111S%H  H5 HHuH[邑fH5h HctH5HxtyHH芜t.HH9tmNHHDtiHH螖{hHH3cH5H_LH5He5H5H'Hl)H蔐[nL[111fD  Hwx   11fH      11ff.     @ H      11ff.     @ HGx1f     H   1fD  H   1fD  AVAUATUSH   H-0) HIIIH} 3      H} t=pHCxH   LLLHH   []A\A]A^1111 kpfHߴ E   H=j 1Ҿu   1&   {1[]A\A]A^1111     H >   H= 11Ҿ &   01@ H\ J   H= [11Ҿ}   &   1xH$ O   H= #11Ҿ   &   1@f     AVAUATUSH   H-) HIIIH}       H} t=(oH   H   LLLHH   []A\A]A^1111nH? b   H= ^1Ҿu   1&   1[]A\A]A^1111     H [   H= 11Ҿ &   1@ cH g   H=g 11Ҿ}   &   x1x+H l   H=/ 11Ҿ   &   @1@f     AWAVAUATUSH(Lt$`L|$hHt$HT$HL$H   L-) HLMI}       I} tQmH   H   L|$hHL$MILt$`HT$HHt$H([]A\A]A^A_f.     ;m6Ho    H=: 1Ҿu   1&   KH(1[]A\A]A^A_1111E1E1@ H y   H= [1Ҿ 1&   fD  H    H= #1Ҿ}   1&   pf.        f.        f.     xSHcH  H9[11Ð111f     H) @@u111@ SHH   H5 HuH[f.     H5h Ha\tھ   H谓tH5EH]tH5) H,t~HY#H聊[[F [111Hc1f.     +11    LGHNHWH?Lf.     Ht;SHHnH{Ht1Hߺ   H5 [f     1111    UHSHHfH{C    H{HDƅyH9ktH[]111 H1>HC    H[]111f     *) f     =) 1    AWAVEAUEATIUHSHHHH4$dH%(   HD$8Hb) H8rAǅ   I<$   E   JHD$HD$H$    HH9\$   I<$H4$D$IH   I~Hn0I~HB;j  AF    EtHU  I~Ht1
InHAF   H9\$yA   H}) H8iHD$8dH+%(   I  HHD[]A\A]A^A_1111E1E1f     j   H5     誠IH   @   A-^IGH   IG    I<$LI<$H4$II9Ikx   H5 L~D@ H5H=
 Ht(I$H<$7I<$zSI$    fE1H̬    H= {1Ҿm   1&   
ƺq   H5} Lbff.     ATL%) UHSHI<$t*H;HtHH5KI<$[]A\ngfD  []A\1111ff.     USHHH-) H} t3H;HtH5oH;wRH    H} H[]gH[]111 AUATU1SH@   H8dH%(   HD$(1eEH;   L%) I<$   yH;Ht>H,$HHt+HxHt	uutMH]E   D  1I<$Mf8AHD$(dH+%(      H8H[]A\A]11fDH}Dn 8HHt   	) uHmtH9]yHWiH}Ht1H]PfD  1a`@ H(dH%(   HD$1H4$HT$HtHH54?HD$dH+%(   u
H(1111]`f.      H=) @ AWAVAUATUSH(dH%(   HD$1Hy t3HD$dH+%(      H([]A\A]A^A_11111fD  HD$AIIHD$1L9}L6Ht$D1HHSPHD$HtLhL^$IcW9uIwLzufHnD$AH^_ff.      HH=) SHdH%(   HD$HGPHt11HHЅ,   HT$dH+%(   u9H[1111E1E1 H$E1AHH5H=) x^SjHtHfHxH0HHu[11fSHdH%(   HD$HGPHt11HHЅ,   HT$dH+%(   u<H[1111E1E1 H$A   AHH5H=) ^ff.      P   Hȧ H=) fD  HGP1f     USHHdH%(   HD$1'Ht;1HHЅt+H$HT$dH+%(   uKH[]1111     [H \   H=. 11Ҿe   &   p17]    HwP   11fAUATUSH(dH%(   HD$HGPHtb11HT$HЅ~PH1Ll$L$    f.     HI9t*HD$1LHUPtH|$HI9uHD$dH+%(   uH([]A\A]11111s\ AWAVAUATUSH8HoPH4$dH%(   HD$(1H   HAՃuH A11HT$HՅ~yHE1Lt$ L$    IcHD$D  IM9tOHD$1LHB8SPHD$ HtHhH A9uHT$H4$H诂uHD$ @ 1HT$(dH+%(   uH8[]A\A]A^A_1111r[fUfSHH8H=) dH%(   HD$(1Ht$H5PT$)$tHh)  trH-c) H} r   H=) HH5DH$Ht   H$HH} _HD$HT$(dH+%(   uBH8[]111ÐH    H=n 1Ҿ  1&   1wZ    H=9) @ HH=&) SHdH%(   HD$HG8Ht11HHЅ,   HT$dH+%(   u9H[1111E1E1 H$E1AHH5tH=) YSzHtHfHFH@HHu[11fSHdH%(   HD$HG8Ht11HHЅ,   HT$dH+%(   u<H[1111E1E1 H$A   AHH5H=) Yff.      E   H< H=˿) fD  HG81f     USHHdH%(   HD$1kHt;1HHЅt+H$HT$dH+%(   uKH[]1111     kHԢ N   H=  11Ҿ   &   1GX    Hw8   11fH=) @ HH=) QH  u   1111E1E1D  HE1A   H
i H5H=) zf.     SjHtHfH蘉H0HHu[11fH  u   1111E1E1D  HA   A   H
 H5#H=$)     >   H    H= ) # HG 1f     Hw    11fH=ٽ) @ HH=ƽ) !SHdH%(   HD$HG@Ht11HHЅ,   HT$dH+%(   u9H[1111E1E1 H$E1AHH5tH=M) aVS
HtHfHHHHu[11fSHdH%(   HD$HG@Ht11HHЅ,   HT$dH+%(   u<H[1111E1E1 H$A   AHH5H=) eUff.      E   H" H=k) fD  HG@1f     USHHdH%(   HD$1p+Ht;1HHЅt+H$HT$dH+%(   uKH[]1111     H N   H= s11Ҿ   &   1T    Hw@   11fH=) T@ HH=) H u   1111E1E1D  HE1A   H
I H5H=G) 
f.     SHtHfHhHHHu[11fH u   1111E1E1D  HA   A   H
ƞ H5#H=ĺ)     >   H    H=)  HG1f     Hw   11fH=y) $@ HH=f) H( u   1111E1E1D  HE1A   H
9 H5H=) f.     SHtHfH,HHHu[11fH( u   1111E1E1D  HA   A   H
 H5#H=) W    >   Ht    H=x)  HG(1f     Hw(   11fH=Q) @ HH=>) SHdH%(   HD$HGHHt11HHЅ,   HT$dH+%(   u9H[1111E1E1 H$E1AHH5tH=Ÿ) xQSjHtHfHH0HHu[11fSHdH%(   HD$HGHHt11HHЅ,   HT$dH+%(   u<H[1111E1E1 H$A   AHH5H=) Qff.      F   H H=) fD  HGH1f     USHHdH%(   HD$1Ht;1HHЅt+H$HT$dH+%(   uKH[]1111     [H O   H=X 11Ҿe   &   p17P    HwH   11fAUATUSH(dH%(   HD$HGHHtb11HT$HЅ~PH1Ll$L$    f.     HI9t*HD$1LHUHtH|$H誌I9uHD$dH+%(   uH([]A\A]11111sO H=i) @ HH=V) H0 u   1111E1E1D  HE1A   H
m H5H=) f.     SHtHfHBHpHHu[11fH0 u   1111E1E1D  HA   A   H
 H5#H=) 7    >   H    H=h) c HG01f     Hw0   11fH=A) @ HH=.) aH u   1111E1E1D  HE1A   H
] H5H=) f.     SzHtHfHH@HHu[11fH u   1111E1E1D  HA   A   H
ژ H5#H=d)     >   H    H=@) 3 HG1f     Hw   11fH      u
HHH1H_Cy
5HHHHBHH)H@HH1111fHH1H9tH91111ff.     @ H1   0u1=     H) HtH5H=A	   HX) HtI) H1111     H=9) c1H')     D  H1H=) )    D) H111 SHH=)  u:f.     H=) HHH; uH=) [zPf.     [111     ATUSH) HGH   H1H1EkL% fD     tH      L1H@  V   LHǄ       HǄ݀      Ǆ       D@    D     HǄ݀       Ǆ  ҇H   X   LHǄ@      豇HǄ       HHG[H   ]H5 A\    []A\1111 Hv) u:H=[) &aH=G) HD)     o:H,)     H11 H=-) Xf.     HH5UH=) t
) uH11fH=i) H=ݎ)    H11f.     UHSHt<HHE HH  HtHH	HHBHHuHu   H[]1111ÐSH7u[1    H@   [1    SH= ) HH5^t
) u1[11 H=) $ufD  H=ɰ) HHuH; uH=) M   [11     ff.     @ SH5HH=) H dH%(   HD$1taO) tW      uH%  H=;) H$t.H=) H?H=) HLHtHCD  1HT$dH+%(   uH [111Gff.     f1ff.     fUH5SHH=) H(dH%(   HD$1$   z)          H=k) H݁ H$t/H=@) H`H=9) HLHtHCHfD  H=) H,$t,H=) HH=) HKHuf     1HT$dH+%(   u
H([]111Fff.     AWAVAUIATIUHSHHh  dH%(   H$X  1      IIAHD$IHC  HH% H$_5H   HHLMPH MH1&H
Y^HID$H9   H$X  dH+%(     Hh  []A\A]A^A_11111E1E1IH   HLt$P   %LH$I HD$   tL>@ Lt$PH$H` L1   %Lf     HH̐ E11t$LD$HLH%XZfL|$HL$H 1@   L`% L|$   H 1@   L8%Dff.      HtfD  1111    HHH5_ ff.      SHHU) HHDغ   H!ZH[111fD  ff.     @ ff.     @ AVAUATUS>1   D Hq'  H5H=) v  ȫ)   L-ի) L@HH|  HtDe H[]A\A]A^111f     HLacA  L5     L@dHH  11Ht t HLct1   &q1L%k        tH      LH@  V   LHǄ       HǄ      Ǆ       D@        HǄ       Ǆ  H   X   LHǄ@      jHǄ       HHH   LH@1LbfD  1ATUSH   H1L%f    D  H   Ht  Ǆ      D@    H@  V   LD     HǄ݀       Ǆ  ~H   X   LHǄ@      ~HǄ       HHt:   dHǄ       HǄ݀      Ǆ       W@ Hǅ      []A\1111     AWMAVIAUIATIULSHH      9  LcJ  W)HcLAt  9     HHu  H    MtHcH@  H5D HHEI6MtHc񋴰  Au MtHcH   H5 HHEI4$H  Hc񋼰   } Mb  H   H  IHH[]A\A]A^A_1111E1E1fD  J   D       JǄ       JǄ      ǂ       JB@    H5ӊ     Hǁ       ǂ  H@  V   HD$H$B|H$X   H5 Hǁ@      H   |H$HD$Hǁ         JҺ   Nʉ    9	     1f     J   H. ǂ      D  HcH      h  H   H    r     MtHcH   H% HHEDD    A      H   Ht Aǁ      HV   AA@    H5E A    Hǁ       Aǁ  H@  HD$H$zH$X   H5 Hǁ@      H   zH$HD$Hǁ         f     HE IE     df.     HǄ       HǄ      Aǁ            HǄ       HǄȀ          ff.     E1E11111ff.     fMIHHH1f.     HE1HE111{ff.     IIH1H1[ff.     E1E1111   :f.     HE1HE11ɿ        HE1E111   f     II111   f.     MIHHH       IIH1H        E1E1111   zf.     HE1HE11ɿ   X     HE1E111   9f     II111   f.     MIHHH       IIH1H        AWAAVIAUIATAUSHH1H   Hc  H   teLI   E   L} Ht& Hc  L} H      tvJ<I   H5 H$H0IwH$" L} H0J    H        N4   L,D$H[]A\A]A^A_1111E1fD  H0f   H58 HL$L$vL$HL$1Iǀ       Iǀ      #ff.     AUATUHSH.41   D HuH1[]A\A]11    H59H=f) tы3) tL-D) Lp5HLHE XtD#H   []A\A]11fHtHH=) X 111ÐSH5(H=٠) \t
) u1ۉ[11@ H=) t}) H=) C}) U=[11ff.     fUSHHHHHp[   ]W    AWAVAUATIUSHH  Hc  H   "  HH   D  Hǂ           Ht$H|$Ãyp    IT$A$L:MtqLRD9|uDkH|$a  H McLsH   HD$H|$LLMr@A$/vIT$HBID$L:Mu   L= D9}McMcfD  H|$1ɺ   LtxH[]A\A]A^A_11111    Q  H5B Q   zsHD$Ht  AQ   fc  H|$HH5	 []A\A]A^A_s@ k  ֐H   Ht$(HT$0HL$8LD$@LL$Ht7)D$P)L$`)T$p)$   )$   )$   )$   )$   dH%(   HD$1H$   H$   HD$HD$ HD$D$0   '_HD$dH+%(   uH   11111E1E15f.     HHt*Hc  19  t
D@   H11@ 1H11ff.     ATUS7H.      HL% 9      H   Ht
 ǀ      H,@@    V   L     Hǅ       ǀ  H@  qH   X   LHǅ@      qHǅ           P   NЉ  9tgHcHx@u9   DHǄ       HǄˀ      ǀ       7D  9tl@   []A\1111D  [1]A\1111ÐHHtb    9tRHct@u$t%P|u   D     l@   H1111f.     1H1111ff.     @ SXHtڃHc  !҃	[1111f.     @ H'u1H@ t taKtX t/tt2 t轋 tt tTtt@g ttn$sAf脾 Y LS ?0 2%S V)% lJ 
 0X\G  !X 
 |Z$ lf.      {Sff.     ˇff.     ff.     ff.     {rff.     +/ff.     {ff.     kff.     e ff.     Fff.     ;Iff.     ff.     "ff.     ˠff.     ff.      ff.     / ff.     H ff.     ; ff.     P ff.     ; ff.     . ff.      ff.     KW ff.      ff.     {
 ff.      ff.     ; f.     USHH   H  ȃ)ȉ  ;  uH)񉊄  HH   tH   Ht1 ǁ      "HǄ       HǄ      ǁ       HA@    H-pz V       HHǃ       ǁ  H@  kH   X   HHǃ@      kHǃ       H[]11111fAWAVAUATIUHSHt$sHtxLc  L5y 8   HLN<I@  ]kHt}     1D$I@  >   LB  I   %kMtA<$ u)IǇ       H[]A\A]A^A_1111    LLB   I   H[]A\A]A^A_1111f.     H<   LHT     AWAVIAUATIUSH(t$aHW  HHc  M  HL  L   Hǂ       Ǆ       I    L=} M  LLLLLD$J1ҹg   LILcLMCD
  ALL$McL8iLL$LD$IIH  A Hc     H         H   Ht Hc        Dl$H  A L	L,I   Mt)L         M   M  B,H([]A\A]A^A_11111E1E1fHǄ       HǄÀ          el$   of     E11E1 L=m| T      LLLD$gLD$HXIA   S I   I   H5v Ph  L1g      LD$A   gLD$HII^Hc  M1]@ Hc  MM   BH   HL$8LD$@LL$Ht7)D$P)L$`)T$p)$   )$   )$   )$   )$   dH%(   HD$1H$   H$   HD$HD$ HD$D$0   ?HD$dH+%(   uH   11111E1E1*@ HH׉H %AWAVAUATUSH  H|$0Ht$8dH%(   H$x  1mHD$PHD$LHD$(HD$`HD$HD$hHD$HD$HHD$ HD$XHD$   fH$     1H)D$pD$LuHc HD$`1H|$P   A    H\$p   H
` HH^A IHHE1	HHt$hLHL<H)ILjLLL$`DD$HLB<0HL$XHy 1HcH)HU	+   H5y LeHyHT$8HHHD$0Ѕ~*LD$(HL$HT$Ht$ H|$HHH$x  dH+%(   u"HĈ  []A\A]A^A_11111E1E1/(ff.     @ AWIAVAUATUH-	 SHHxdH%(   HD$h1HD$P    HD$X    HD$`    %MLDIH  LȺ   LL$8HA   DHD$LHD$HD$`HD$(HD$XHD$ HD$HHD$HD$PT$4HD$   f     HU A  1HD$`H$LA  
HI)L9    LCA?    HJ,#L4I9  H4$Hڿ   1L[    ; ?  LD$HL$(HT$ Ht$H|$D$LVH|$`|HH=    E1A? L<$nE1; HIu<tf     LE15IALAH)ڄt2I9   LLHGIHuHLt LH)I9   ELLH߹   H)Hv H)JHHt=H4$H¿   1ZZHL   H5v b; f.     HD$hdH+%(      Hx[]A\A]A^A_11111E1E1D  H9tHHH߹{   H)HXv iIHHtHL   1Y   H5-v H3b\$HLl$PLd$XLHLxt$8|$411H$ɭ11HM11   1L$$A  L<$I)Uff.     fATUSHdH%(   HD$1Ht3HIH1L   HHH~H$| uHH*fHD$dH+%(   u\H[]A\11111D  H4$Hf.        H5 H~L1Ҿ   HƱ#ff.     @ HH=QS1HCHt#HH=H1H[     [111     H9#      H#      HY#      H
	# @ H# 鄫@ H=# @ H5#  @ HH=# H
y# 4@ Hi# 4@ H=Y# T@ H5I#  @ HH=6# H#      ATIUHSH莯LHHH[]A\f     UHSHH_HHHH[]雪ff.     H7HHff.     SHH[Hff.     SHH[Hff.     H
# @ H# @ H=# 4@ H5# @ HH=# aHI#      ATIUHSHFLHHH[]A\f     UHSHHFHHHH[]{ff.     HFHHff.     SHFH[Hff.     SHgFH[Hf.     Hk  Ht
   H1ÐH=# $   H1     AUATAUHSH(dH%(   HD$1HH   zSI1HHL8   H;   L   E   H{    nIHtf    H8?H ID$HtIHCLH8gt6HCHxn]HnHkHHEHuNf     E1L[H1VHr _   H=q 1Ҿ  16   kHD$dH+%(   u2H(H[]A\A]1111D  蛾HCHy@ AWfAVAAUIATUHSHhdH%(   HD$X1D$@   )D$)D$ )D$0)D$@蔴HH   H5	 HE1N  L#Ld$HL$HLL#7   H{T$L;   E   ŽHCHt|觢IHto    Lq=HYIGH   HCLH8   HCHx[L蠪HkHHEHCHx uUD  E1E1LRZLYH1@{Hdp    H=p 1Ҿ  16   HD$XdH+%(   uXHhH[]A\A]A^A_1111fD  TIHoHHDM<$MXfE1N AWAVAUATUSH   T$,HL$dH%(   H$   HH	(  IIH
  D$@SHA1H\$@D$D 41H1'HD$H	  THD$<1HD$    I$D0L$   HL$Ht$HL4T  D9t$<I  DM   I$LHx],uiMt$M   HtVI>ΜuII>18HD$ u5H-;HT$ HHzLuH耨I~HdthH|$s9s  H|$HMIGD0    IGLHx+uMwMD    D$,8Y  H|$H$   dH+%(     H   []A\A]A^A_1111fˣHm   H=^m C1Ҿg   16   f     HH   H\$@H1ɾ2   H>     HHD$H,;Hl    H=l 1Ҿj   16   P Hl   1H=l y1Ҿh   16   D$@SHA2H\$@D$C256 .豢Hjl   H=Dl )1Ҿi   16   |   H+l H=
l 1Ҿ 16   BRfAUATIUSHH) IH   H8    H߉HH   I} Ht1;f     L   HiHHtQI} HutCL薙9HL[]A\A]111fD  IE HcfD  1LE1CHVHk 5   H=j 11Ҿ  6   kHL[]A\A]111    AVAAUIATUHSHIH   HDLHHtuI<$HtgE17DH   LHHHt=I<$HQt/AHqD9[L]A\A]A^1111     1LE1H:FH_j    H=i 辿11Ҿ  6   [[L]A\A]A^1111    AWAVAUIATUHSHH   IH?ȗAMtpI} 跗AE      E   1fD  A9   I?1HHH[]A\A]A^A_1111Åt,   AfD  H   H>'Aƅu@+Hh ,  H=h 裾1Ҿk   16   @fD  E~?1    A9t,I} 1HH>D  uH   []A\A]A^A_1111苞HTh (  H=h 1Ҿl   16   蠿[f.     G    1 HtkUSHHG t~H[]1111H{H-h   H RH{ H{(+HHHߺ  []Q1111    AWA   AVIֺ0  AUIATUH-,h SHH^H5H+  I;ID$(Hu  Mt$L    AD$ E<$L7 ID$H   IEID$tmE1E1111Hg f.     wHcHfI$    q  CHuՃu tuD	D	t8軜Hg   H71Ҿ   1   ԽLE1QHL[]A\A]A^A_1111E1E1f     I|$x dHCHAID$x)O@ I|$p 4HCHAID$p@ I|$h HCHAID$h@ I|$` HCHID$`     I|$X HCHID$XjD  I|$P tHCHID$P:`D  I|$H DHCHID$H
0D  I|$@ HCHID$@ D  I|$8 HCHID$8D  I|$0 HCHID$0zD  HCHAI$   RxD  SH,e 3  HϹ1Ҿ  1   l'N  HE1He 蠹1Ҿ  1   =dH9  Hd o1Ҿ  1   :  HLMf.     SH H  ?   H  H0MHt'HC(LP@1HtHH IH[A    HCxH|  L   Ml  @uH HM[A    H   HL$HT$H4$LD$/H4$HT$HHL$LL$HtH   H9   HCxL   ˘Hd    H=Gc C1Ҿ   1   1H [1111E1E1E1肘Hc    H=b 11Ҿ      藹H   AHzc    H=b 蹷1Ҿ   1   VqHEc    H=b 脷11Ҿ      !9җHc    @ SH H  ?   H  H0MHt'HC(LPP1HtHH IH[A    HCxH|  L   Ml  @uH HM[A    H   HL$HT$H4$LD$-H4$HT$HHL$LL$HtH   H9   HCxL   ۖHa )  H=Wa S1Ҿ   1   1H [1111E1E1E1蒖Ha   H=a 
11Ҿ      觷H   QHja )  H=` ɵ1Ҿ   1   fqH5a   H=` 蔵11Ҿ      19H` &  @ HG1f     H5J) HL
I) HL
    H1111E1E1D  H5J) HL
DI) HL
   h H1111E1E1D  AWAVAUATUSH8t$HT$dH%(   HD$(1HD$     Hd  I?F D$As#I H  I   H  H@`H9AHAD4$x  
   A   1ƌ IHud蔔H_ @      IwIOHT$ I    HHH|$     A      A   HbIH|$  HA  IWIL^HHtHNHI MwHLH HD$ HHO$1HD$Ht$GD$Ht$A\@ H  H4$~I_(H{Hk0} HH4$HIG0H  D$=     =     HCHH  HT$ЉÅd  H|$ F           I 7IWLHHuHHH|$ FIGxHD$     H[  H    M  A   w        H   HiLЉÅ   @ H|$ FFHD$(dH+%(     H8[]A\A]A^A_1111Ð14H] 8   H=\ 謱1Ҿ 1   I?       HJ] H=r\ n1Ҿ   1    L C A    <@ 諑H]    H='\ 1!1Ҿ   1   農@ HC8H.fH\    H=[ ٰ1Ҿ   1   viH   H 1He\ .   H=[ 脰1Ҿ   1   !HFʐH#\    贐H
\    I螐H[     H=[ 1Ҿ   1   讱dH[    a1Ҿ   @ H    1Ҿ   @ H    H7H1 1ff.     HG1f     HG1f     H5D) HL
C) HL
    H1111E1E1D  HGHu   1111f     ?HHH ff.      Ht;SHp Ht H3 1HHCp[    1[11     111f     Ht;SH    Ht8H 1HH   [1[11     111f     UHSH`HtHHH[]     H1[]111ÐHt[USHH
 H1Ht6H} e   H5Y H^B1H1H2   H[]1111111    ATL%qY G   ULH
  S%HtKHH1 HCx=HC HtoHHtH   跥[   ]A\111    苍HZ H   L11Ҿ     褮1[]A\111    P   LHhA1ff.     AWAVAUATUSHXH|$Ht$dH%(   HD$H1H  ILIHD$ M  H     LvA  A  IcG9  )9OӉT$4    Hcl$4Ld$It(HL)6HHD$AGAGA;uI    -  IG(D$8    H$HD$DHD$(   f.     H|$8  Ht$H<$DT$<p	HcT$<ōBHA  =-  A    A/Ao9H4$H|$NLcL6l$4AoA;/uI    )Ll$  EWE   IcGH|$    )I  f!Ņ  EwAEOEwE  I  HD$A  AGH|$t+  Ht$H<$DT$<cHcT$<ŃAIcH|$I  H1EwA    AoAG       A    D$8    H|$聚D$4DD$8D$8HD$HdH+%(   ?  D$8HX[]A\A]A^A_1111E1E1E1AG   I I    AG    zAOD$4    H|$D  D$8    q I HL$ELH4$AG    AG    AoA/fH|$%   tXI  AG    HD$L    H|$      EwAoE  l$8    EGEI  D$D    HL$E  IcDt$<MAI  IAHHfAD$    LAL9t[IA}
uA|$uEI|$ HT$(HH4$A)Ot$DI|$ uBAL$t9ܯf.     DMIDDt$<A9tGAG    *D  HL$DMIDDt$<L9   I 耯AG    A9uT$DuL9d$   M9gM1M)AqE~fD  AA  HHH9uEO.fD  BHA  =tCLH)A)EeD1f     AA  HH9u<xl$8A   HeT IGD$8       H5xR H=R r   H5`R H=R Zf.     AWAVAUIATAUHSHdHIiM   HH      H7At AG   I I    AG    Aw  k  E7A  s  D9  A)u/pD9  AwAw    A;7  A)tC(DHHcLH$$H[]A\A]A^A_1111E1 I    Mu$@ 1H[]A\A]A^A_1111E1@ E~D$    A   HE9END4$e  AG  J  A   A)IcΉ$D9~$      HcAI  t1At @4D9rAGHL$$L$AW   I  I(/HL$=  AA\  A;G:  AG    AG    IJf.     IcGDHIt(~PA9  A)AGAG=  |  A;[  E$I    A)ED$~@ H$-L$$EH[]A\A]A^A_1111E1I D$Iw(LLФ   E7A    E;w  Hc$L$
A   $I(LHH!@$AA=  -  A;G}  H5N H=O ԰@ g  H5N H=N 踰i  H5N H=O 蠰j  H5N H=N 舰L$EG  H5cN H=N ]  H5KN H=jO E  H53N H=DN -$I  t1$At @49r$D$AO  H5M H="N ݯ  H5M H=N ů  H5M H=N 譯  H5M H=M 蕯  H5M H=jN }y  H5kM H=N e]  H5SM H=N M^  H5;M H="N 5_  H5#M H=bM ff.     fAWAAVIAUIATUHSH!HH&HtqIHtiA
#E~~A
wxHAN DHcHD  AeuZ   HͩLLe   L
HHD$
HD$fD  1H[]A\A]A^A_1111    LLDHL[]A\A]A^A_鱅S9i  )uTSD  LL
       HM C   LL   HC뚐S91  )   HH[]A\A]A^A_1111fK      - L{(@ C9t11H-xC9uHUt(StyH  L*HC    fD  CtQH{ tDC    H{ HL~yf     LL   LL
   LL   H{   H5J H=J 袬  H5J H=J 芬f.     UHHSHH̺HHH[]	f     Hn'      UHSHp	HtHHH[]     H1[]111ÐHtkUSHHH1Ht;H}c   P  HHK !1H1H=   H[]1111f     11111D  ATL%?K D   ULHP  SHtcHCHCH   HP  C   HHfHnC   flC YH   蜕[   ]A\111@ s}HK E   L11Ҿ     茞1[]A\111    K   LHP11@ AWAVAUATUSHXdH%(   HD$H1H  IHLIHD$M  H  AE E1{  I}R.1DЅ8  HD$DMe0Lt$8MHD$IP  fHnHD$0flT$L$$)D$     I~   ~TD$AEHT$HA)E9EN賅b  HcT$DE)AH)E  IN McI~LIN A   H4$LE9EOEd   AMcAF   MF t/9NA̅F  LcH4$HELD)L%Ef  AF  IN IF(H9   H)AŅH|$   ŷR  I~H4$EnLAF   QAF    AAFWMLt$8   L踣AE    E1HD$HdH+%(   7  HXD[]A\A]A^A_1111E1E1E1fD  foL$ Ht$0   H|$AN AŅ2HIN IF('    IF(IF MLt$8L   LcEME}DIcUH)It09OLcLM$AEDAEA;E uIE     LD)@EMLt$8EuE{L   膢LމLt$8   Lgff.     fAWAVAUATIUHSHT$3HI8M  HH     HAWE7A)E]D  AWA)AWE~FHcHIt0D+HD$D$H[]A\A]A^A_1111E1D  M  D$  IG0AG    Dt$HD$A   ILLE9Ht$ENE   McE)E/1AG    MEd@ A)AGAGE~PHDHIt0^HD$ND$D)D9D$EH[]A\A]A^A_1111E1ÐI    ECHD$   H蒠AG    f.     1f     AWAVAAUIATUHSHHQ	HIVM   IA
,E   A
   HD DHcHfD  Aq6  A   u7IG   HHE @   H[]A\A]A^A_1111E1E1Ae      H觟HLe   L{HHD$HD$H	D IIGIE1111Aw  H1[]A\A]A^A_1111E1E1HLDHL[]A\A]A^A_a{AW$HL       AA+GHHHL
   몐HH而HCHHaIwgHH   HHD$HD$AA+GHHHL
   7fD  IG0AHD$@ AG9uIAG   AG   ILAG    Ht$HAWH'AAG9t)1HA1xAA+wD9uHD  IcG    HL        HL   iH9e'      AWIAVAUEATIUSHHH$]HtlHHIH   Icž   H1HD$IA   Lj jA^_H~)   HhH}L$1ELLu,1H[]A\A]A^A_1111E1E1E1f.     j L1HjA   LL$   AZYH[]A\A]A^A_1111E1E1E1    H H   McE1HD$   ML   HLT$HM   HLT$臋H}L$1ELL/LT$A   MLH߹      A   H3H}L$1ELL   f     UHSHHtHHH[]     H1[]111ÐUHSHH1Ht   H蛊HH@x   H[]11AWAVIAUATIUHSHHIof  I      euO   HʚLLe   LwHHD$
HD$H[]A\A]A^A_1111fD     H  H1[]A\A]A^A_1111fD  x      uHgtLH8wNfD  puSHCtLI$)LLHͰv   H8   )fD  LLHL[]A\A]A^A_uf.     M,$   HD  1LL{	HH   HHD$辈HD$@ LH1LH;	HHLL   `ATIUSHdH%(   HD$1HHHk 19~#HT$dH+%(   u4H[]A\111@ HT$LH	~D$øf.     AUATUSHHtqHHAsHIxMtSHtNDHHHAuE~uLH߾   /HHD[]A\A]111 E1HD[]A\A]111f     IcHL2A     AVAUATUSHt7Aԅ~0HH HIIMtHu)HMu|E1[]DA\A]A^111    DHHHAtE~IcHLt4H߾   /H~[D]A\A]A^111D  E1    HjfD  Ht3SHHzH1sH1&   [11 111ÐH^'      UHSHHtHHH[]     H1[]111ÐATL%G;    ULH   SHtK@    H@4   UHC(HtlH1rHHs[   ]A\111    ;mH,;    L跌11Ҿ     T1[]A\111       LH!1ff.     AUATUHSH~L`(HLoHHs<LLcHHPȉC8u&H   9H1[]A\A]111fD  H1LHt8tL+   C0   H[]A\A]111f.     AWIAVAUIATUHSHHIIƃ
'   
   H9 HcH@ oo  pu)H  1H[]A\A]A^A_1111ÃeulH   ?LLLe   |pHHD${HD$H[]A\A]A^A_1111 AD$0tI$I+D$Hf     LLHL[]A\A]A^A_pfIcD$ H[]A\A]A^A_1111@ fLL   H9 A$AD$ID$ H8 ID$0@ AT$       AD$0    ufLL   H֎ A$ID$ ?    I|$(1L   HLf.     I|$(IE rD  LL        H6AD$0VfD  AWAVAUATUSH   dH%(   HD$x1H  IIYLH^IH\  HS  LaC  E1D\$C      Ht8L)d  HHC4K  twC     S0HtHsL)Ht389OHcIH$XH$D|$D)IHSHSH;  h  H`     LhIH@(HH$UHxIEW8LcLL$AEO\
M9L\$=H<$Iw<LLT$ _W         L   LE1HD$xdH+%(     HĈ   D[]A\A]A^A_1111E1E1E1E1fD  LLH(IMtLLL$HHD$$gH|$m$LL$IIA+G	9X  Ht$1LL\$ L$L$$ HcL$IGH|$ HIt8HL$HL$L$IHtD8DPPp1    AЉDADEHH9rEA{AsASIO4   H54 LHL$L$~H<$Ht$01Ht$y aMOHL$Ht$K|8HLL$ H$H$LL$ LIOB  IAG4    HH)H9tIt8I8H$H$IIG    fD  C4HSHCHC    H9   H    C0    ,@ H<$Ht$01Ht$(LT$ HT$Ht$(K|<L$&~   L$IIG   L\$AG0   IIGM_MWfD  H)Ht8H{8H_    D\$   LD$LZuD$AG     AG     1AWAVAUATAUSH(H4$  HHIHM  H  H  Av4  Dd$   H]I6IFAN0AA)Ņ   E)   f.     AV0HIFE)IFtkE~fIt8DHfAǅHWt   H誠uAF     H(D[]A\A]A^A_1111E1E1E1E1     I6AF0    H9ufo(2 AL,$M  ILc|$II|8H  vMA  LA)IcH$H$I>D)|$HII>L,$H    D$,H4$L
M>M>I  vHmh  H   H@sE     HIH@(HHD$HHD$'H|$LcHD$CD- HIH=   Ht$H|$1n   H|$D   IHt$LI|8MO\8MtJC|8EK1ASAsfD  A҉DADEHL9rGL8A{AsASM/H|$4   H5!0 t;IH|$1It8t#H10 M/IG0.H^   H耊E1     Ht[USHH]Hx(H   HH2/    hH1>gH1yH   []111111111D  HiR'      SH/ #iHp&HpIHp|HpoXHpHpHpHpmHpHvpaHipHھ  H=. 5Hھ  H=. !H H-pHھ  H=ƞ Hھ  H=. H. HoHoHھ  H=. Hھ  H=z. Hs. @HoHoHھ  H=R. gHھ  H=J. SH* wH_oHھ  H=.. +Hھ  H='. H2. +H#oHY   H=. 趲Hn艖HnHnHnB\HnHnX[HnHھ  H=- |Hھ  H=4 hH- |HtnϪHgnHZn[HMn8H@nHھ  H=I- Hھ  H=9- Hj <HnOHmHmHmHm{HmHھ  H=' Hھ  H=, {Hھ  H=, gH,   H=, OH,   H=, 7H, HCmH6mH)m}HmHھ  H=d, Hھ  H=S, Hھ  H=B, H?, HlHlHl]HlHھ  H=, qHھ  H=+ ]Hھ  H=+ IHھ  H=+ 5H+ ypHAlH4loH'l蒄HlezH
lyH lvHkHkaHkHkW}HkrHkHU   H=U zHkHھ  H=+ YHھ  H=	+ EH+ )HQkiHDkφH7kH*kHkHHkrHkNHjqHjDHjeHjHT   H=T rsHjHھ  H=M* vHھ  H=@* bH;* 膁HnjHajHTj蟴HGjH:jH-jXH jHjHj}HiHiWHiHT   H=S 2HiHھ  H=w) Hھ  H=j) rHe) fH~i	Hqi,yHdiHWi2	HJiH=iXH0ifH#iNHiaH	iHhW[HhHhHھ  H=( Hھ  H=( H( Hh_HhzHhGHhHrhHehИHXhcHKhfH>hHھ  H=3( 
Hھ  H='( H#( :Hh-~Hg@HgSgHgfHgHg謕HgHg袯HgHھ  H=' fHھ  H=' RH' H^g9HQgHDgH7g袈H*g5HgHھ  H=P' Hھ  H=H' HH' 蹉HflHfOHfHf%Hf(HfHھ  H=& lHھ  H=& XH& lpHdfjHWf"YHJfH=fH0fH#fHھ  H=& Hھ  H=& ۿxHeHe<fHe_He[Hef     SH ^H;vH.H   H='& V!wH	HHX   H=% $H%   H=% 藒H迄Hھ  H=% Hھ  H=% ׾H芄jH}[Hp論HcHVQHITH<跫H/`H"}HHÕHHbHHԃ[HƃfD  ATAUSP Ht(D`X@   []A\111Hx   SHWw?贎H   oH    oKHoS P o[0X0oc@`@okPhPos`p`o{pxpo      o      o      o      o      o      o      o      H   @   [1111[111fD  1111    Htt1f ff.     W1uw   111     1H u	Hw   11f     W81uw8   111     1H  t11fHw    11f1H( t11fHw(   11f1H0 t11fHw0   11f1H@ t11fHw@   11f1HH t11fHwH   11f1HP t11fHwP   11fHG 1f     HG(1f     HG01f     HG@1f     HGH1f     HGP1f     SHHdH%(   HD$1H$    t[   Hz0HftbHH4$HxuNC      HT$dH+%(   umH[111fD  H uJB       D  PHL(   H=`! Cp1Ҿ 1   qC    1AUHATL$UHSHH     CKI݃@ǃ@@8u\st#utOt
;Et;Mu@Et!;Cu4HL[]A\A]1111fD  H}H   t+ H@L9{HE1[L]A\A]1111fHsHt
*   Hs HtH} uHE 1HE LHUH[]A\A]1111H}(Htu1Hs(H8_HL[]A\A]1111Ð;E t>HU1ff.       ff.     ff.      ff.     ;ff.     AWIAVAUATUSH   otdH%(   H$   1DM  T$ALl$PH<$Z    T$X\     D$lLLH$   D$lHt  H5 D$mD$   I(IH1  1   LDd$HfD$l$H|$H5{# )D$0HT$8U   H  Dd$Xl$D$)D$ )D$@=IHtHX8HZ  HHDAFD$\H$LL   L$   HD$PӅH$   Ht  H5 1H$   dH+%(   uYH   []A\A]A^A_1111E1E1f.     LL$pDD$lL$\T$H<$#yfD     ff.     H   w9uH   H~(    ~0      H1111    wH   NtV0uoLH $ N  H= k11Ҿ    mD     Ht>   H~( tv0kLH# A  H= k11Ҿ    #m14KHh# /  cKHR# *  H=V 9k11Ҿ      lKH# I  tKH# <  fD  AWAVAUIATIUSHXdH%(   HD$H1UŅ~7n  H  HcH@ A|$Al$      HD$HdH+%(   	  HX[]A\A]A^A_1111E1E1D  AL$  A}:  I$  =      t=   t@t=   Z	  Hz0   aJ  H " H= i1Ҿ   1   qk4@ A|$$AE0ID$0H@ AD$f     AD$  A}0I$   ID$ @ IH\!   H=H +iAL$A1H     j1|@ A|$D$D    Mt$M|$ b  M  Mm(At$Ml$S  I<$IL$ HHHL$I|$0LHHL$ILL$Dxq   L$DiHD  H~  H=o RhHAL$1AWMA      H    iXZ    Hz0 uHz( A}0jAE0H; HcHfD  AE0HcͅuIL$(uI}8 \  ID$0@n  H HcH     ID$0HPH@IT$xI$   I\$@L2   AD$@hex HIoHG7  HO H=@ #g1Ҿ 1   h Iu(H|$IT$I\$0@oD$oL$ KHD$0HC G    IcL$IT$ H|$Iu(I\$0od$#ol$ kHD$0HC f.     IcL$IT$ H|$Iu(I\$0>ot$3o|$ {HD$0HC fIcL$IT$ H|$Iu(I\$03oT$o\$ [HD$0HC zfI|$ Ha    NH   xHIHcI$   	ID$xHH  I|$ A$   &  IT$xIu(H|$I$   I\$0BFf     IcL$IT$ H|$Iu(I\$0CNHD$HdH+%(   ~  ID$ I|$0HH0HX[]A\A]A^A_HD$HdH+%(   G  It$ I|$0HXH[]A\A]A^A_#HD$HdH+%(     It$ I|$0HX[]A\A]A^A_It$ I|$0Hi  HD$HdH+%(     HX[]A\A]A^A_(HD$HdH+%(     I|$0HX[]A\A]A^A_EDHN   1H=8 dAL$EM01Aؾ    H ejfA}0  AE0Hn HcHHD$HdH+%(     It$ I|$0HXIT$([]A\A]A^A_黇HD$HdH+%(     IT$(I|$0HXIL$[It$ ]A\A]A^A_0HD$HdH+%(     IT$(It$ I|$0HX[]A\A]A^A_It$ I|$0H  "1@}HD$HdH+%(   E  I|$0HXIt$[]A\A]A^A_$@ ;CH   1H= bAL$EM01A       Hg :dD  BH &  1H=~ abAL$A   1H       cf     BHD   1H=. bAL$A   1H     caf     MCBH   1H= aAL$A   1H     Fc	Iu(H|$IT$I\$0)HIt$1x@AHq   1H=[ >a1Ҿ 1   bHD$HdH+%(   ujHX[]A\A]A^A_顴I|$x  H1ID$x    WJA  H1H `1Ҿ  1   ab$'  poefATIUSHӃ   tV5     ~&HL>~u{u
{y  []A\1111     B      ~HL[   ]A\    J1uz   B   L   9~{   HL   []A\1111fD  B   L   CHL   X+{!CfD  B   f@ R1   HL   {C C    B   /Cvff.     UHSH~t1tH[]111 1}uHE HU(HH   []111ff.     AUIATUSHHLb L=  tKf>H?   H= ]1Ҿ   1   {_H1[]A\A]111     LnHsx,HS0zuǉCHLHC     H[]A\A]=H   H=p S]1Ҿ   1   ^pff.     ATIUSHz HtH{ =  u H{ KHHt
HS0zt[1]A\111f     HC HL[]A\ff.     AUIATIUHSH&~TueEuF}  E   L   ~&}tOHHL[]A\A]W    1H[]A\A]1111 L~܃u@}uI}H   ED  I}IH   A;E uH} (xEHL~u}wIuEHu   IuIH   H} ^uAE E   HE     +f     HE@E2   HE E   D  UvEfD  fD  f     H
Y^# 4@ H
	^# $@ AWIAVIAUMATIUSH?Å~2tLtLLÅ~  A|$   H[]A\A]A^A_1111E1 AD$tN  HLL   []A\A]A^A_7    A|$tPLL   @ AD$2   ID$ ID$8ID$@ID$ LL   U@ ID$ H=8= Ht	HAHI|$ uAD$D  I$Il$8It$ HxAHE AD$   A|$I$It$ HxAAD$    ID$ f     I|$ HtAHI|$ fuAD$)A|$Hff.     fL9H
B
ff.     fL9H
Bff.     fATIUHS/~>EtCut>HL~E   utB   []A\111fuE         [1]A\111ÐLe H5
 LtEH5
 L   H5
 Lu   tHH:\# EHE     U    ELe H5]
 LLu1H=Y
 H} sEH=.
 H=
 ݸ   ff.     AWAVAUIATIUSHHdH%(   HD$81Å     uA|$  LLÅ   AD$         M|$ L5vZ# E1 I6Le  IIIu7L  Ha H= uVAL$A1EL$v      H  XAD${  fm    HD$8dH+%(     HH[]A\A]A^A_1111E1E1D  AD$tNIu(HIT$I\$0o$oL$KHD$ HC    zf.     AD$2   ID$ ID$8ID$@ID$ }fD  I|$0G      H5Y# AL$1HD  ;
   HHHu5H
 .  H=2 UAL$1EL$A   v      HB V IHX# B(ttAD$ID$     f     HD$8dH+%(   usHHIt$[]A\A]A^A_     HD$8dH+%(   uCHHIt$[]A\A]A^A_騊IT$8HH|HtI|$ pAD$,訫4H 8  H=( T1Ҿ   1   U AUIATIUSHiÅ~
A|$t1H[]A\A]111fD  uSAD$       4m  H? H= sS1Ҿ   1   UfD  LL[ÃwoIl$ H5M HtH5K HuV   AD$ID$     ,D  HJ ID$ LL   AD$    H[]A\A]HqM AD$1ID$ 
fAUIATIUSHÅ~CAD$tQutQLLrÅ~AD$   u	   H[]A\A]1111 t[uAL$I\$@      Hd 2   H1I\$ H&nAD$]@ AD$2   ID$ ID$8ID$@ID$ 7fD  WMl$ H5Z L;   H5 L$   H5= L
   
   1Lt)AD$ID$     H[]A\A]1111fD  IT$8H5AZ 1   HCAD$q H5  H5 1HHT# 놸      fD  AUIATIUSHdH%(   HD$1H$    Å~
1A|$t1HD$dH+%(      H[]A\A]111f.     tktLL9D  ID$@LL   H$HID$ ID$(2   Å{H<$QID$     AD$_A|$|LL   ID$ AD$    0ff.     ATIUHS~]}uUt`HL[]A\o    /H   H=X  ;O1Ҿ   1   P     1[]A\111 }, H- HE HtE    {ff.     ATIUHS_   }   tXu8H} H   
   1zC, HK- HE HtE    HL[]A\zf.     }, H- HE Hu.H 
  H=G *N1Ҿ   1   O    1[]A\111n.H   ATIUHSo~]}uUt`HL[]A\    #.H, 8  H= M1Ҿ   1   8O     1[]A\111 H} 
   1@)  HE HHtiEpAUIATIUSHÅ   t*uTA|$t%HLL   []A\A] A|$upI\$@IT$ 1ɾ2   HI\$ AD$    LLÅ~uQA|$uI|$ 1e-ID$ H[]A\A]1111 HLL   []A\A]nfD  uA|$tH[]A\A]1111fD  AWAVAUATIUSHH(Lj dH%(   HD$1HB     HD$    L=     PtVtB  HC0x  1HT$dH+%(     H([]A\A]A^A_1111E1@ =     HC0@  uL7Ht$   1H$HC(HD$HC HLJH|$  H5A D$D$U    HC0x>L:\HI诡HWLI|aLIQxHMLHL$M   耣LHC(HD$HC kVOfD  *H z  H= sJ1Ҿ   1   L L 6HHnHC     LHؿHC 蚡f.     AUATUSHHB0Lj HB     xtH1[]A\A]111D  ALHH臾~   =  u/LZHHC HHH[D]A\A] )H\  =  H= kI11Ҿ      KH1[]A\A]111D  L4H ff.      AUATIUSHHLj HB     L躽tU=     U)H   H= H11Ҿ      jJH1[]A\A]111    LH4H0u|H{ Ht[dHLCH[]A\A]t@ LYH^HtHtxgHC H    H   []A\A]111f% H& HC HmD  ATIUSHz H蛼t6tu H{ 舜Hp1Ht
HS0zt)[1]A\111@ H{ G3HϩD  HC HL[]A\ ATIUSHz Ht6tu H{ HHt
HS0zt)[1]A\111@ H{ 2HoAD  HC HL[]A\ AVIAUAATUHSHH   Hz dH%(   H$   1y5IHHuNIHt
HU0ztjH$   dH+%(      Hİ   1[]A\A]A^1111f     kEHHH9sHT$PHL`tHDPD  HE H$   dH+%(   uHİ   HLD[]A\A]A^w    ATAUHSHz H蚺t%H{ 茺=  t[1]A\1111fD  HH[D]   A\f     ATAUHSHz H:t%H{ ,=  t[1]A\1111fD  HH[D]   A\If     ATAUHSHz Hڹt%H{ ̹=  t[1]A\1111fD  HH[D]   A\f     ATAUHSHz Hzt%H{ l=  t[1]A\1111fD  HH[D]   A\f     ATAUHSHz Ht%H{ =  t[1]A\1111fD  HH[D]   A\)f     ATAUHSHz H躸t%H{ 謸=  t[1]A\1111fD  HH[D]   A\f     ATAUHSHz HZt%H{ L=  t[1]A\1111fD  HH[D]   A\if     ATAUHSHz Ht%H{ =  t[1]A\1111fD  HH[D]   A\	f     AVAUIATAUHSHH`Hz dH%(   HD$X11IHtOH   HHAHH9   HD$XdH+%(      H`1[]A\A]A^1111 H "HtHU0zuHE HD$XdH+%(   uFH`HLD[]A\A]A^3 H蘭fD  HLŸgHrfATAUHSHz H蚶t%H{ 茶=  t[1]A\1111fD  HH[D]	   A\f     ATAUHSHz H:t%H{ ,=  t[1]A\1111fD  HH[D]   A\If     ATAUHSHz Hڵt%H{ ̵=  t[1]A\1111fD  HH[D]   A\f     ATAUHSHz Hzt%H{ l=  t[1]A\1111fD  HH[D]   A\f     ATAUHSHz Ht%H{ =  t[1]A\1111fD  HH[D]   A\)f     ATAUHSHz H躴t%H{ 謴=  t[1]A\1111fD  HH[D]   A\f     ATAUHSHz HZt%H{ L=  t[1]A\1111fD  HH[D]   A\if     ATAUHSHz Ht%H{ =  t[1]A\1111fD  HH[D]   A\	f     AVAUIATAUHSHH   Hz dH%(   H$   1y-IHtYH   HH=HH9   H$   dH+%(      Hİ   1[]A\A]A^1111    HdHtHU0zuHE H$   dH+%(   uPHİ   HLD[]A\A]A^D  H@WfD  HT$PHLPHUD  ATAUHSHz Hzt%H{ l=  t[1]A\1111fD  HH[D]	   A\f     ATAUHSHz Ht%H{ =  t[1]A\1111fD  HH[D]   A\)f     ATAUHSHz H躱t%H{ 謱=  t[1]A\1111fD  HH[D]   A\f     ATAUHSHz HZt%H{ L=  t[1]A\1111fD  HH[D]   A\if     ATAUHSHz Ht%H{ =  t[1]A\1111fD  HH[D]   A\	f     ATAUHSHz H蚰t%H{ 茰=  t[1]A\1111fD  HH[D]   A\f     ATAUHSHz H:t%H{ ,=  t[1]A\1111fD  HH[D]   A\If     ATAUHSHz Hگt%H{ ̯=  t[1]A\1111fD  HH[D]   A\f     AUATIUSHHLj LrtMt   H   H= :1Ҿ   1   $<H1[]A\A]111ÐL&HbHtHS0zuHC HHL[]A\A]6fD  L؎HPff.      ATIUSHz H諮tH{ 蝮=  u H{ (HHt
HS0zt[1]A\111f     HC HL[]A\ff.     ATIUSHz H+tH{ =  u H{ 
(H-Ht
HS0zt[1]A\111f     HC HL[]A\ff.     ATIUSHz H諭tH{ 蝭=  u H{ 'HHt
HS0zt[1]A\111f     HC HL[]A\ff.     ATIUSHz H+tH{ =  u H{ 
'HţHt
HS0zt[1]A\111f     HC HL[]A\ff.     ATIUSHz H諬tH{ 蝬=  u H{ &H]Ht
HS0zt[1]A\111f     HC HL[]A\ff.     ATIUSHz H+tH{ =  u H{ 
&HPHt
HS0zt[1]A\111f     HC HL[]A\ff.     ATIUSHz H諫tH{ 蝫=  u H{ %HeHt
HS0zt[1]A\111f     HC HL[]A\ff.     AWfAVEAUATU͹   SHHH  LL$L$   LdH%(   H$8  1)D$)D$ )D$0)D$@)D$P)D$`H)D$p)$   )$   ustfnfnfnƺU   fbfbH|$flH5DD# D$IH<  HCxHt A;Gt
A;G  Mo8LL   HMLDA$   D$   $   HD$H$   H$   HD$PH$   AՉŅ~+$      umH$   H ŅWH$  Ht  H5 H$8  dH+%(      HH  []A\A]A^A_1111E1E1É$   LL   AՋ$   fH$   H nb
  H H=} `41Ҿ   1   5OË AW   ffHnAVflIH5B# AUATIUSHӺH8  dH%(   H$(  1L$   )D$L)D$ )D$0)D$@)D$P)D$`HA$)D$pH)$   A~D$p$   DfpU   L$fD$D$dHH   Lx8H}MLDE $   1H|$  $   HL$   OLH   $   HD$@H$   L$   H$   A׉Å~$   txLH   A׉H$  Ht  H5 bH$(  dH+%(   uVH8  []A\A]A^A_1111 Ǆ$      L=7H$   L Å~i܉ff.     H  t	1111H    H  t	1111H    AWA   AVAUATUSH   dH%(   H$   1H   IHHl$@E1L%x6# XfD  H@8H   Lt$`H\$pT$H   1HH$   AHt  H5 
H(HHtTfL   HHD$$LHHT$('   $   D$D$D$0HHXAH$   dH+%(   uH   D[]A\A]A^A_1111]f.      HtSuIH     t
111fD  HGx t=  u   111ø111fD  HH    H= W011Ҿ      1H111@ USHH   t$<dH%(   H$   18~mHH5m HT$<H=HD$ o$HoL$HD$`)D$@)L$P&fo$o\$HHD$ Ht$@T$hH$   \$x H$   dH+%(   uHĨ   []111ff.     @ AUATIUHSHH   dH%(   H$   1b~kIH5x HLLHD$ o$LoL$HD$P)D$0)L$@Oeo$o\$HHD$ Ht$0T$XHD$x\$h3 H$   dH+%(   uHĘ   []A\A]1111D  AE1ɹ        fD  UHcSHH   dH%(   H$   1Ht$8t~mHH5 HT$8HIHD$ o$HoL$HD$`)D$@)L$Pbdo$o\$HHD$ Ht$@T$hH$   \$xC H$   dH+%(   uHĨ   []111+ff.     UHcSHH   dH%(   H$   1Ht$8~mHH5N HT$8HyHD$ o$HoL$HD$`)D$@)L$Pco$o\$HHD$ Ht$@T$hH$   \$xs H$   dH+%(   uHĨ   []111[ff.     USHH   t$<dH%(   H$   1~mHH5n HT$<HݕHD$ o$HoL$HD$`)D$@)L$Pbo$o\$HHD$ Ht$@T$hH$   \$x H$   dH+%(   uHĨ   []111菃ff.     @ AE1ɹ       vfD  [ff.     AE1ɹ        FfD  USH   dH%(   H$   1t$<H   ?   H   HH5y HT$<HHD$ o$HoL$HD$`)D$@)L$Pao$o\$HHD$ Ht$@T$hH$   \$x{ H$   dH+%(   uOHĨ   []111     KH    H=# *11Ҿ      `,$@ AE1ɹ       fD  E1A        IE1
       ֚fD  IE1       鶚fD  IE1       閚fD  IE1       vfD  USH   dH%(   H$   1HcHD$8H+  ?   H  H        HH5B HT$8H~HD$ o$HoL$HD$`)D$@)L$P_o$o\$HHD$ Ht$@T$hH$   \$x tWH$   dH+%(      HĨ   []111     HGx H=  =    3	H   H= (1Ҿ   1   H*ofD  H\ %   ATUSH   dH%(   H$   HD$8H9  ?   H*  H  H   IH5 HT$8L-}HD$ o$LoL$HD$`)D$@)L$PF^o$o\$HHD$ Ht$@T$hH$   \$x tj   HT$8H   U H$   dH+%(      HĠ   []A\111 HGx 5=  *4@ H   H= +'1Ҿ   1   (zfD  sH %   H=K &11Ҿ      (:I~f     ATUSH   dH%(   H$   1   HHN  ?   B  H  H   Ld$HcH5+ HLHD$0oD$LoL$ HD$`)D$@)L$P\oT$o\$ HHD$0Ht$@T$hH$   \$xr t}tXH$   dH+%(      HĠ   []A\1111D  HGx E=  :    ;  H5 HD$ D$fH 9  H= c%11Ҿ       'NfD  H %   |     USH   dH%(   H$   1H+  ?   H  H     H1HHH5 ʐHD$ o$HoL$HD$P)D$0)L$@[o$o\$HHD$ Ht$0T$XHD$x\$h tb   HD$PH=w|H$   dH+%(      HĘ   []1111 HGx @=  54@ {H P  H=S #1Ҿ   1   %zfD  ;H %   H= #11Ҿ      P%:{Hn t*H5 tH tH     HE11D  AVIAUL-F# ATAU1SLCD9t.t)HHHu[]A\A]A^11f     H;L譸uH[AD-]A\A]A^11f.     HGH   USHHHx@ t   觫u
HCHP@H{  tEHC@L~:   Hztt%HCH{ %   H HcpL\HC     H[]11111@ 11111ff.     fSH   ";tHtH9tu[1111f.     [1111ú   H5* H   :f.     Ht{HHG(Ht.tw   to          @   HGHt'Hxp t GuH   H   H8HHG0HtVH   1111fHx0 t   ti|H   H=_  1Ҿ   1   "1H1111fHx0 uT@ Hx0 EH
@ Hύ    H<   D  AUATUSHHHdH%(   HD$1H$    H  IIŅ  HCHxp tnH   H   LH{8HcHAMtH$HH    A$HD$dH+%(      HD[]A\A]1111     @   LHP0AMtA,$HCHP@HtHҾ   H3oHCHcpLH{ {D  H   H= K1Ҿ   1    E1>H   v  H5r H= ,HtH   HtHf.     111f     Ht;SH   HtfH!| HH[     1[1f.     11ff.     HG(Ht/Qu"HP0HtH@(H   Ht	H@ HGHtH   HtH8D  11111ff.     fAUATUSH   HT$8dH%(   H$   HGH  Hxp HH   H    )  ILl$8H5/ LLrHD$ o$LoL$HD$`)D$@)L$PSo$o\$HHD$ Ht$@T$hH$   \$x   HCHH{8LHL$8   H$   dH+%(   ;  HĨ   []A\A]1111    @t HT$8Hw1ɾ   PP   =H6   H=  1Ҿ   1   R1m H   1H= y1Ҿ   1   3H   1H= A1Ҿ   1   f     HCHHP0HCHP@HtHҾ   HkHCHcpLH{ aWs    Ht;SH    HtcH y 1HH   [1[11     111f     H   SHG(HHt*QuHx0HtH@(H   Ht[H{Ht/H    t%cHx H{8HHC[H    1[1111@ 11111ff.     fHG(Ht/Qu"HP0HtH@(H   Ht	H@ HGHtH   HtH8D  11111ff.     fHt;SH    HtHbHw 1HH   [1[11     111f     H   SHG(HHt*QuHx0HtH@(H   Ht[H{Ht/H    t%aH0w H{8HHC[H    1[1111@ 11111ff.     fSfHH   dH%(   H$   1)D$@)D$P)D$`)D$p)$   HY  HOHHtHyp *        t1Y    ҹ'  HDH5p HcH6o$od$HHD$ Ht$@)\$@HD$`)d$PV1҅HH$   dH+%(   .  HĠ   [1111E1 HcHH5 HHD$ o,$ot$HD$`)l$@)t$PHt$@HD  HcHH5 HT$8HT$8<mo$oT$HD$ )L$@HD$`)T$P LAPMtOHA/@ KH /  H=. 11Ҿ    `1f     H R  H= 11Ҿ       1n@ UH- _     SHHHt<Hd$H   Ht   CxHH[]111úd  HH蘫1ff.     HHu  HHPL
G      Lk  &` H1111E1E1 Gt	   1ÐGx   1 ff.     HtGt11    Gxt鐈 鋈 ff.     ATAUSHH8Ht,HCHtH   HtHC8       HeH%tHC    H{`NHC    Et[]A\1111fD  H{@8HC@    H    []A\1111ff.     HtSS   H}t)H11-H߾H      [111 H{(HC(    D     111ff.     Ht#SHH[   H5h 镩D  1111ff.     @ AVIAUIATIUHSHHtOHLLHHt9MtA$It$Hk~QHHDH[]A\A]A^1111HT q   1H= Q1Ҿ  1
   HH1aH[]A\A]A^1111     USHH2H߉H[]111f     AUIATIUHSHHHG(Ht5v     j          @  H߾   bH{8Ht#HCHy  H   HtHC8    H*  H{H+HtHCHt 9E :  KHC    M  H{@H;{  a5HC@    L  u L5HH  LkH9k      HHkC	  Hc}L  H{(Ht@@ PPt=     H( 
  C   HkHE HH[]A\A]Hx0    I  H    H=w 11Ҿ      1gD  H{(HS|fD  Hx0 u@@ Hx0 1HHE11[]A\A]rfD  H{(H   H[]A\A]1111E1E1D  HC    3]fD  E1Iٹ     ΁1f     HCH  H{HHfD  } H{ t9H{@H9{  HD$13HD$HC@    HI H
  C   }      HH}p    H{8H  HCH  H9  H   HtHC8    H}p _  H{8 Hk_  H   H  H{8HL[]A\A]D  H{@H9{t6Q2HC@    @ HLHHE1[1]A\A]s} HC    fD  } H5Z =  H 1>HHF  H{@1H{8Hk@H(HCH9H
HC    HD$1HD$g H +  H=~ 11Ҿ      1kf     [H    D  H9k@HG  H{@1Hk@u@ HE(H- L  HHC0HC HHC N  Hf11Ҿ     1@ H 7  H= +1Ҿ   1   LF1{f     kH    H=N 
11Ҿ      1;H}pL   )k HAHC8H   HkuH{@H;{HD$tf/HC@    HD$H;   B<:HH   H    	HC    {/HC@    HD$NtH    1	f     UHSHHHHH1[1]f.     H1fD  AWIAVAUIATIULSLHHT$ɅI1Mt1   L\HHLtu01LD$ZD$H[]A\A]A^A_1111E1E1ÐLLL肚tHt$LL.@ AUATUSHH  HFHHH  Hxp   F   H      Ht!   蘔      1HAH{@HE@H  H9  -ou 3o}{oE C oM0K0HE@HC(    HC@H}@HC8    HtH}8HtHE   HC8H  H߾   YH}(HtCHC(H     H[]A\A]111 H}HtʘB  HEE1H9C  HioM    HoUSo] [ oe0c0HE@HC@QYfC H}  t%HCHcPLtMm  Lc Hu LHE0H}(HC0HtGBHC(HJ  HCH@8HHHH[]A\A]    om +ouso} { om0k0HU@HC(    HS@HC8    H9sH}@Haaf.     H{(HC(    f.     H   H= 3	11Ҿ    
1Mf     H{@Ht]+oU o][oe c ou0s0HE@HC@D     HLc gX!fH1H #  H= 11Ҿ       
1f     H P  H= C11Ҿ&     	1]f     Hd 6  {f.     kHD B  H=N 1Ҿ   1   	H1L- Hck  LHC IHt
HCHcPLgH m  Lw11Ҿ     	1ff.     fUHSHHHHH[].'ff.      AWE1AVAUMATMUHSHdH%(   HD$1Lt$P6D$    Ht'HHHL$E1ILLSHA)MtD$IHD$dH+%(   u HD[]A\A]A^A_1111E1E1]    (ff.     AVAAUIATUHSH   H^dH%(   H$  1H       HDHHIV 5  A<$*  Et$XL ID$`H?  IE1H ID$h   
w#HcHf.     I$    A  CHuͅe  k  T  Il$pHtHJf HHT$@H5޾ D$8    HD$<    HD$@    HD$H    AZo$oL$HHD$ HT$HH5( )D$P)L$`HD$pZo$o\$HHD$ HT$8H5l T$x$   H$   no$$ol$HHD$ HT$<H57 )$   )$   H$   mo4$HD$ Ho|$H$   $   $   :o$oL$LHD$ Ht$P)$   H$  )$   D HL$H   H9sHt$@H9o  LO&ZH   H== 1Ҿ   1   oE1H$  dH+%(     H   L[]A\A]A^1111f.     I$    HCHI$   fI$    HCHI$   ofI$    HCHI$   ?mfI$    QHCHI$   =fI$    !HCHI$   
fI$    HCHI$   fI$    HCHI$   fI$    HCHI$   Lz    I$    YHCHI$   Ef.     I$    !HCHI$   
    I$    HCHI$       I$    HCHI$   l    I$    La#lH   H=O  1Ҿ   1   
@ 3Hܺ   H=  1Ҿ 1   HL" T$8At$HAL$tIL$D$<IL$HCHI$   {fD  H<   H=v  1Ҿ  1   4nWff.      HHeHHPL
7   L[&O H11111E1E1ÐHt;u1HWx   Ht1:tD 111111f     HHp    H=F ?11Ҿ       H111ff.     ATUHSHH   dH%(   H$   1G~jIH5; 1HLHD$ o$LoL$HD$P)D$0)L$@5o$o\$HHD$ Ht$0T$XHD$x\$hCH$   dH+%(   uHĐ   []A\1111Uff.     fUSHH   t$<dH%(   H$   1x~mHH5} HT$<HMgHD$ o$HoL$HD$`)D$@)L$P64o$o\$HHD$ Ht$@T$hH$   \$xCH$   dH+%(   uHĨ   []111Tff.     @ AUATIUHSHH   dH%(   H$   1~kIH5G HLLHD$ o$LoL$HD$P)D$0)L$@_3o$o\$HHD$ Ht$0T$XHD$x\$hCBH$   dH+%(   uHĘ   []A\A]1111%TD  UHcSHH   dH%(   H$   1Ht$8~mHH54 HT$8HyQHD$ o$HoL$HD$`)D$@)L$P2o$o\$HHD$ Ht$@T$hH$   \$xsAH$   dH+%(   uHĨ   []111[Sff.     UHcSHH   dH%(   H$   1Ht$8~mHH5~ HT$8HPHD$ o$HoL$HD$`)D$@)L$P1o$o\$HHD$ Ht$@T$hH$   \$x@H$   dH+%(   uHĨ   []111Rff.     AUATIUHSHH   dH%(   H$   12   ILH5 1LLd$Xo$oL$HD$ )D$0HD$P)L$@Ht;1HH51 LHD$ o$$L$   ol$HD$xd$Xl$hL0o$Ht$0HA$o\$A\$HD$ ID$ ?H$   dH+%(   uHĸ   []A\A]1111lQff.     IE1     t   VjfD  ATIUSHŃt*uf     []A\1111@ LhH  Ht#H9t[1]A\1111     H  H  HtH   H9uH   H  닐AWAVIAUIATIUSHHLC(HL   LD$HMtFqjLD$HLALLAH   []A\A]A^A_1111E1E1     +jLD$HLL   LLtZ
     wf     AVAAUIATUSH:HHHGAăHW(    H@tXA  HL4    1H
^H   H      xN[]A\A]A^1111@ KHL4    T1H
h( H   H      yHE h	  H= l11      	1[]A\A]A^1111@ @%   EuSH߅   A&  HL4    7HHǅ       H   	f     t<HdHL4    1AH_f.     H(HL4    SA   H5( HL4    YHʋ( H   1AH(  HL4    YS~و( (    fD  HL4    ~Q( *(    1ff.     @ AVAUIATIUHSH'gHA|ELC(LHLH}[   ]A\A]A^1111E1E1     AVAAUIATUSH*HHH7HAăwEtdHL4    HIH   AtiA   Hǅ          xb[]A\A]A^1111     ;HL4    IHrIH   1Au
 H|H      yH    H= L11      1[]A\A]A^1111@ HW    AWAVIAUIATUSHHHL$HLcHL$IM)L9r&H1    I4I| LH   I9sH   []A\A]A^A_1111fAVIAUIATIUSHHdH%(   HD$1SHH$HLLC(D$HLL   LL$01t$H(XZHD$dH+%(   u H   []A\A]A^1111E1E1mJff.     fAWAVIAUIATIUSHHdH%(   HD$1HH#L   H߉D$#dAWLLC(PHLLLL$t$H(XZHD$dH+%(   u"H   []A\A]A^A_1111E1E1IAWAVAUATUHSHHHHT$H$dH%(   HD$81    HI4H$z  HH<  HE(HT$(Ld$H       HHD$I       H<HH<HHL$ H$HD$4HD$     H"M   HD$4bAVLHPLL$ LLLD$MH       t$DH&Y^H$H9uHL$ HL$HHT$(H!Hu:HD$8dH+%(      HH   []A\A]A^A_1111E1E1@ HHT$!I   HD$48bHT$SLE(PHt$LHLL$DH|$("t$DH&&XZm    HH$!M   HD$4aATLE(LPHHT$LL$DH$ GfAWAVIAUIATIUSHHdH%(   HD$1HH!L   H߉D$caAWLLC(PHLLLL$nt$HZ%XZHD$dH+%(   u"H   []A\A]A^A_1111E1E1FAWAVIAUIATIUSHH(dH%(   HD$1q H߉'   l$H   LC(ILD$HtsHULLILLHD$PLD$Y^t$H$   HT$dH+%(   u[H([]A\A]A^A_1111E1E1 1@ H   H1LLLUILHD$PLD$XZE     AVAAUIATUHS8%wH IHcH[]A\A]A^1111E1E1E1E1fD  A$  AE    D  IǄ$       H} H(I$  A$  I$  AǄ$  @ LHI$  H  L9  1Q@ E~A   E9$  }I$  H(H H9t

  HҁIc
  HzI$  Hu=H 
  H11Ҿ     1f.     E$   AF@E5A$  %HE8Aj  AA  EU8AU AyEBD0fCD5eAFEHE8A  A  EtAU U8A  E$  @ A&  AqA$  D)]I$  IcLHvD]E  AǄ$     @ E$  EE$   EIc$  I$  I$   	Ic$  E  D9  HcIcH)LI$  vIc$     I$  tV@Ƅ҈TH@u    A
kIE HE8IEHE=AǄ$  
   IǄ$      ECff1MPuPf   fUC^f     E$  EA$   uIc$  IcLH)I$  uIc$  I$  I$   AǄ$           H  H(I9$  tKIc$  H- 
  H~H  HH<  Ic$  I$  wtfI(L  Hc?     IU H@HUDHILHLH)I)D51҉уIt
 Ht
 9rHU8I}HIU DHLILI)L)HC.1҉փL1L79r    I$  Ic$  LsAǄ$     A$  I$  HD)t1ZD  H 
  H^AU U8DALL6U8EAU BD0CD5:DALfL
 USHHH1Ht7H     H(sH  H9t	  H5 n|   H[]111@ AWAVIAUIATIUHSHD   E  D  HE      p  M  L   M  AVL  H  MH  L;Yz( u
HU  LLLG
  H[]A\A]A^A_1111E1E1E1D  LIM9  H  A~~     L   L  IF8I   Ic  HHHD$*  AvIIHM    M  L;py( u
H  LLHHkY+  Lt$   HLoI4,   LV     fD  AF  Hc    Iv8H   t  ǃ       1H[]A\A]A^A_1111E1E1E1f     M_  Hv
L;x( $  LLLXN  :    H     tH 
  H=H 1Ҿ   1   D  AǇ       AǇ  H[]A\A]A^A_1111E1E1E1D  HLL
)    M  L;w( LHu
Hm  LH
kIt-    HAnEVf     Iv8H      nǃ     g@ LLLfMfD  LLLuމ    Hy H9h  Dp  LLLLT$AALuH  LD$HK<<Kt= L)L@  = HH8  L  ILT$L)MM!fD  H H9h  Dp  LLLLT$AAL H  LD$HK<<Kt= L)L@   HH8  L  ILT$L)MMNHLLH6HLLHcX~H I9h  &111H4LI  IHLM@  L= HI8  M  HH)IT LH I9h  111HI  IHLM@  L萌 HI8  M  H)IT I)HLff.     @ AWAVAAUIATIUHSHQHLH	   H   LD<    E   HO( 1B   H  HHDL$HcL$Hfv( Lt
 H-s( H   H   DL	>H  H  MtH   H  Ao$AE(   H[]A\A]A^A_1111    HY@ HcHLt LtAHz( 1BtHH  HHDf=H-r( H5    D$wH` P  H=' 1Ҿ   1   L$; AWAVAAUIATIUHSHHLH	   H   L!D<    EtZHcHHL HHL$HL$A   HHDHL$_qH-3HL$HLH6    HHDL$pHcL$H3HKSHH-3H   DH   HH  pH  H  MtH   H  Ao$AE(A   HD[]A\A]A^A_1111D  H   H= c1Ҿ   1    ff.      AUIATIUHSHHLH	t{H   At$hH8( HHL   @tj-;Hp( HLKHH  MteHc  LLVǃ      ǃ      H   []A\A]111@ :HDp( HL1H  Mu   tL  Mu    Hc  t?H   Lǃ         ǃ      H[]A\A]111fD  H  Lg    AUIATIUHSHHLH	tyH   L<HHH   4    nH1HHH
@H  M   Hc  LHǃ      ǃ      H   []A\A]111fD     Hc  ugH  Lfǃ         ǃ      H[]A\A]111fD     tL  MTkf     H   LAff.     @ AWAVIAUIATIUHSHaH  H   L  HM   MM   H   H   wGH  M~(HtoMHLLи   H[]A\A]A^A_1111E1E1    KHL   H= 1Ҿ   1   `1@ L0LILLAH  L5t     AVAUIATAUHSH%wH4 IHcH[]A\A]A^1111f.        D)AAD$w-E  [   ]A\A]A^1111fD  A
>  [1]A\A]A^1111    A+  AE fD  H fAǆ  A   I  f     LhIH  HdL9uHH  S    HJbA   SIcI  LHH8Iǆ       Aǆ       AAD$HhJ   ME   AAE E(fH8IU HHIUHPAǆ  
   HX
@	fyHXIuA  9X)HHxXA  fM@Aǆ      HAs6Au}EAU ADALfL IU HpHHDILHLH)I)D1҉уI|
 H<9rAU DALL@ AWAVIAUIATIUHSH8dH%(   HD$(1D   E    HÅ   Mu1M      {  L  M  HZHu   Q    u/   Hu(LL+  HcL"  ǃ     HHLLLLP  L  M    ǃ      DHT$(dH+%(     H8[]A\A]A^A_1111E1fD  HHL  M9~  Hc  HI9j  HYG  I$   Hu(LHE,  +  HcHI)LK  Hc  HIIHT$
HT$LHHFLLLLP  Lt{M     Hc  Kt5 LDH     BD0 M    uMuqLLLjDfMg  Vt7Hl$Hc  LH2DHtHc  K44H;LL)D  M  zVt Ld$Hc  LLCH   LLHǃ       ǃ          HH I$@    Hu(LL+  Hc;ILǃ     DmLc  H1LHL#ZDA]Hf     VU	{*ff.     AVAUIATIUHSHHL	   MteH( L  L@   VHL4    贞    LHLf HǃP      ǃ      Ht%   +  I|$(HHc1]ǃ      [   ]A\A]A^1111E1fD  øHL4    a/    Ld( hf     AVAAUIATIUHSHLH	   HtYL[HH4    c  Hً  L3&H  gEubH3HP  ǃ      Mt%   +  I|$(LHc*\ǃ      [   ]A\A]A^1111E1    HY2    AUATIUHSHHILH	tiHt8HBH߅uqtLH4    һMuIǅ       ,Mt'H1҅xH(HcLHk[I      H[]A\A]111@ LH4    -ff.     @ AWAVAUIATIUHSHH!HIvME  H   HAA   At	   LL     HM!  A   RAI   uWL
(e( ILLLeHt2H[]A\A]A^A_1111E1E1D  HsfD  ǐL
!b( ILLLefD  @I      L
a( ILLLbp    sH,   H=# 1Ҿ   1   H1[]A\A]A^A_1111E1E1f     ;@CHCHAHD؍CfD  L
c( ILLL b AVIAUAATIUS8%wH HHcH[]A\A]A^1111f.       A[   ]A\A]A^1111ÐHǅ      I<$I(ȽL    ǅ     Hǅ      @ L[H  ]HA\H   A]H  A^ AEwD  d D9  tO[1]A\A]A^1111@ Mt[D9  uL>uH  IcLW    L>tIcH  LWD  AwD  fD  HH     H1ff.     @ AWAVAUIATIUHSHH(q      Iǅ  H	  Mp  Ic  H  HH$M  L*  "  Ic>X  H$   )HH9P  HHT$I  VHT$LH)HM  L]=H4$LL   N  "I  IA    AH  HD$   IHHD$LLL$<LL$  HL$LHL!LL$   D$HD$D)HMM  DA  Ad  t H$tTH$fTD  E
  Ic  H  M  H$IAH  HD$    I  HHD$MLHT$HLL$LL$)        fD    1   Ic  ~"I  I  tAǇ      L;   Ic  xI  I  uAǇ      H([]A\A]A^A_1111E1f.     L8;Ic  I  LI    Ic  A  AǇ      %BD  I  I     XNf.     1f     H4$   L|$mIA    AHv!HD$   H|$HHD$<    fD  HHuSA.1 HL$LHLLL$0LL$4fD  fD  HH$HJDHqHJD	HH)H)A31҉уH<H<9rkH J  1H= 1Ҿ   1   ~f     k8NfD  H$TT AWAVAUIATIUHSHdHLH	F  H  H( L   L  L@   ŭHH4    #L諭LH4    9LH
kE1LHL't+M   Hc  Hc  LL   H1[]A\A]A^A_1111E1E1@ #HH4    #L	LH4    gL[( H
!Y( E1Y  Hc  tHc  H  LYǃ     H   []A\A]A^A_1111E1E1D    t L  M@ ǃ     ǃ     fH  LPff.     @ AWAVAAUIATIUHSHqHLH	   H   LL   HH4    hWLЫLH4    VE   L
.GH  LLHH
H%   M   Hc  Hc  LH   ǃ     ǃ     H   []A\A]A^A_1111E1E1f  Hc  u/H  L@Oǃ     @ L
@6@ Hc  H  Lj     H1[]A\A]A^A_1111E1E1Ð  DL  M/ff.     fAVAUIATIUHSHUHH9r'HH5HAEHLHLi[   ]A\A]A^1111E1H( Hb,# @HW+# HE1H( HB*# @H7)# HE1Hi( H"(# @H'# HE1HI( H&# @H$# HE1H)( H## @H"# HE1H	( H!# @H # HE1H( H# @H# HE1Hɯ( H# @Hw# HE1H( Hb# @HW# HE1H( HB# @H7# HE1Hi( H"# @H# HE1HI( H# @H# HE1H)( H# @H# HE1H	( H# @H# HE1H( H# @H
# HE1Hɮ( H# @Hw# HE1H( Hb
# @HW	# HE1H( HB# @H7# HE1Hi( H"# @H# HE1HI( H# @H# HE1H)( H# @H # HE1H	( H" @H" HE1H( H" @H" HE1Hɭ( H" @Hw" HE1H( Hb" @HW" HE1H( HB" @H7" HE1Hi( H"" @H" HE1HI( H" @H" HE1H)( H" @H" HE1H"      H"      H"      H"      H"      Hy"      H( Hb" @HW" HE1H( HB" @H7" HE1Hi( H"" @H" HE1AUATIUHSHHG\Hu-IA?HuKM   H[]A\A]1111@ A@   I)I9LGL)LMIA?HtHLHH+	 HH    ~EHfnfnfbff~fE9sfpf~؃EIM`HLLH[]A\A]w    AWAVAUATIUHSHIH   H4$dH%(   H$   1L  D  Hǀ  AtH1H$   dH+%(   	  HĘ   []A\A]A^A_1111E1E1E1E1f     HLT$I/LT$tg@   D)I  IR$HH9uE1A     AINK4M9  HE(H\$H,$M  HD$   IF  C  C  	    H$H$Ao,$HIm(LE(H,$LE1LHLT$IHDS   Dd)LT$Ao   I   Ao  Ao4  AoD  	ȉȉʉL$ D)D1D1	1șT$(!A!LA	AD$I)LG  C  I  A  HAo  A  Ao$  A  A  A  A  HD$HKH?  (  A  Hl$ofA  HM  BE    ȉD$)E H$LIHL$8L\$HM)N(L|$0Ll$@MMDd$LILID  LLC47AHH8H8H!H	H%   H	B  @uhA   D$Ht$   M)H|$LH?!	  V	 IFo  1H?H!fn#  A	D$fp ffA$A)$IM9QHL$8L\$ILL|$0Ll$@HL$Dd$L׃?"  @   I>  E1H)  A  t G  HA@H÷H)L)H8  D$H|$L޺   HL$0A  p	 HL$0}A  A  HA  A  Aod  H?Aot  !!!!E U	A#  ]fnfnuAo  fnfnfbH\$fb̺   Ao  Ao  flHAoT  ΉuH)E A  A  A  A  A  A  HH5-D$ HT$AH)HI)Ս{H$IEHH4A)H1A)DL NEE0A)AAB2D= D1E!AD!D!		AIHH9uЋ\$(	؃y    H9  LE1IILH}(H\$H,$L)H|$M  HL$H?  LLLT$L)LT$I9!  H$I9tLK4<HL)BLT$H$LLT$N$L+   LLAoT  Aod  Aot  Ao  A  Ao  A  Ao  A  A  A  A  LL{+LT$sIz)H9sH$HS@L)HHLD$HT$LHA   H ?    fD  HL<$HLE1LE(LL>I  HLrAH    JD    LFIL)E1AO9r-@ I  HLHE(HD$LD$H4$LHA   LP>+ HLL\$0LT$(LD$ HD$L|$MLHLLD$(LIHMAPHt$LD$LJ    HfnfnfbA~  ffAֆ  f~AYAZ9HD$LT$(L\$0sfpf~A  IH$MJ,8HK4L)HD$-fIEH|$L޺   H)HL$@H÷H?L\$0L)ID$LD$8D!A	  y	 HL$@LD$8Ao  L\$0HH@H?L!fnA#  	Efp ffE )E fAACAC AC0fD  HH,$@   A+  HH|$HL$0HHHI)*HfHl$oHHL$0HHD$    H$A  M  E    A  B)E ȉD$H)    D    E1fDDCH,$H\$MfAUAATIUHSH舵HHE   HL4    EH   4o   o  o  o$  Hǃ  o4  oD  T  d  t                    H[]A\A]1111 CHL4    QD*f.     AWEAVE1AUF,    ATIUHSHH  Ht$PDDD$LdH%(   H$x  1H$  Dl$0HHD$@  H$  AOHH |$HD$()L$9  fo$  |$H\$pH$p  H\$PG$$  HSC\$0H$x    HL$pAH\$@AHL$ IH$  H$x  IؐH1fo2HHH(LH1HpHpHH0vfozxL9uM$  \$D$L$  I9FÃ3D$XD$0H|$ H$   LL$8HT$@LD$(Ht$L$   A$  H|$`D$A$  Ld$hE$  D$4A$  E$  A$  E$  D$H1E$  Af\$49D$E4L$DL$E| HA\@\$HJA\`H\$8E   H4H\$HH2΃3   	D	D	։rHwo.H3j
ovro~z-DNOHHHDJ<H\$0HHwAD
    9=Lt$T$LH|$(H\$`LLd$h- |$X?    H|$(T$LHt$  H|$@1   D$4    HH$p  HD$XD$4H|$@E1Ld$hM)1Ll$8l$HHl$xH|$`I2G<   HL$8B!HD$J< CHI9D$0  ËD$Ct% DD$Hl$9Dl$HD$ A)E4(J4 L9HǉHH  HAƄ0h  A7mG|   hLt$T$LH|$XL}H|$@   ۭH|$(   ̭H$x  dH+%(   {  HĈ  L[]A\A]A^A_1111E1E1E1E1ÍAAU?9ȃD)|$D$L$LH$  HH       HHHH(@    HHB؀   H9uDl$XD$L$p  L|$XDt$LAHH   Dl$4HH\$fH|$(DH DLL|EHD$ Hfo/k Ltdf.     H8h HHF    H(H   HHHNoBB   foffH~Jo  bH9uA A XDl$4\$LH|$(Ht$ A!AAED$4 H|$@   1Hp  L$       Hl$(T$L\$0Ht$Ld$hHH\$`̕ H|$@1   E$T  E$X  Hl$ A  HD$A$d  E$\  E$`  LD$LTHA@ p D8HP<x\DpIfnfnDh<fnfnfbfbfl)P|DX\ʉSh|CDK<IXHA@   L9uT$LHt$E1E1H|$(Hl$  \$4   Lt$L|$P)H\$XD$    fD  Ab  Et
@x]  D$ MH(HCA$  AA$  AGA$  AGBffAGBHD$AED9l$0*AMϋD$Dt$H{H3A9DDt$D$4D)M5HCu IfnHAFAvLU@} fnʋ   DE`LPʉPfnAfAnfbfbDJflIL AHxHMHK|
I)DE1EAJ<A9rxC|
fC|
M$  \$D$L$  I9FÃ3D$XD$L   H$   H|$(1HHD$ |$X?  vD$0D$HD$pHD$ H|$(Ht$p1谒 H|$@1   HH$p  HD$XLt$H\$(1LH} H|$@1L   1E1HH^ NHD$pHD$ 5 D  AWAVIAUIATUSHXdH%(   HD$H1sIčCwXHQf HcH     $E    HT$HdH+%(     HX[]A\A]A^A_1111E1ff     
uAmLfy  I$  AE	fA$   f=vf:  ffAEAo$   
   LAo$  Ao$  Ao$$  I$  Ao$4  Ao$D  A$  A$  A$  A$  A$  A$  C$)fD  IELXfIuF	ff=k    @    r  H( @ EAL   EEIMLIUIu A    fIM$   Hc)$)D$)D$ )D$0@   LLLHLLifo
!d LHl$@Lfo Hf)@H9uL@   LLfo
c foHf)CH9uIT  L}@   LL}@   L   61/@   HLL<NAEŃ2A]DuAo$   
   Ao$  I$  Ao$  Ao$$  Ao$4  Ao$D  A$  A$  A$  A$  A$  A$  D)9sSM?9s)$$DAmPD)&IE I$   IEIǄ$  
   I$%        A    HY(     @H	G( HD1fH9(     @HE( HD1fAUATIUHSHHGhHu-IA?HuKM   H[]A\A]1111@ A@   I)I9LGL)LMjIA?HtHLHH{	 HH    ~E Hfnfnfbff~fE 9sfpf~؃E$IM`HLLH[]A\A]    AWAVAUIATUHSHH   Ht$dH%(   H$   1蹤LH  D<  IHǀH  H؃HD$t@1H$   dH+%(   	  H   []A\A]A^A_1111E1E1E1E1ÐL  I  ID$0HH9u1AP    HHt HH( IM(M  HL$B f  z   t      @	E  D  H\$ Lt$LLH)I9?  HD$H9tHD$LLH)Ht e,HD$LJ, Hq    HLAod  Aot  Ao  Ao  Ao  A  Ao  Ao  A  A  A  A  A$  A4  
LHI|$ s)H9sHD$HS@L)HHLD$HT$ LLA   L(   D  @   D)LM9MH\$ Lt$M)I?LLT$L\$ gHT$LMHHL\$(HJD PLD$(Ht$wLT$ A~  ILJ    LT$ HfnfnfbffAև  f~Y^9L\$ sfpf~A  HL$H|$L4HIH)Ht H|$     Ht$E1ME(LHHD$'I   C'L  D$C'M  	  HHr!H9HD$H)Ao   IP  Ao  IAo  HЍSDlHD$(   )	ȉȉʉL$4D)D1D1	1șT$H!A!LA	AE!I)LG'O  C'N  I  A  HAo$  A  Ao4  A  AoD  A  AoT  A  A$  A4  HD$EHKH?    I  H$   fA<  HD$A  H)E F)EAH  HD$(LIHL$8DL$ M)HN$0Lt$@Dl$LMMIHD  HHA4.AHH8H8H!H	H%   H	C  @ux   T$ Ht$H)H|$H?!A	8     HN	 HUAo  Ao  H?H!fn1fp fffAL$fA$A)L$A)$HL9AHL$8Lt$@LDl$LDL$ Hˉ׃?  @   I?  E1H)x    t   H@IķH)M)8  E8  Ht$   LH|$HL$ H?`	 A  }E  E  !E  A  A  	A!A!A  DUA!!Ao  DM!Ao  DE!Aod  A#  Aot  uUE] AADMDEADUEω] }ʉuHU    A  A  A  A  Ao  H\$Ao  Ao  HA  A$  A4  @HHT$4HD$ AHL$(L\$H)HI)ƍ{ H4IVA)HDL1HA)D  NEA0A)AB2T D1A!!D!		AIHH9uL$H	ȃ@ H1I\ H|$LD$LLHT$ A   H"Ht$I  HL    AH    JD    LFIL)s1AO9r[IFHt$H|$IķH)غ   M)HL$@H?DL$8IDD!A	8  LD$ 	 J#LD$ Ao  H?HL$@DL$8H@Ao  L!fnHD$fp fffE fM)E f)MA  @@ @0Hl$(@   H|$H`  A+<  HHL$HHHI)HL$HHHD$(H)1
    D    3fD  %1AUAATIUHSH舚HHE   HL4    *H   $o   o  o  o$  HǃH  o4  oD  d  oT  t                      $  4  H[]A\A]1111D  +~HL4    9)fAWEAVF4    AUATIUHSHH  Ht$DDD$ldH%(   H$  1H$  Dt$hHHD$`HD$      H$  AODLL$HH A|$HD$(D)9ωL$  |$t$hIQH$   fo$  H$  G0H$  AA$    H$   AHt$`AHL$ IH$  H$  IH1fo*HHH(LH1HpHpHH0nforpL9uL  |$D$L$  I9Fǃ3D$pD$hLD$ LT$X1    L$   H$  LD$xHT$`D$  AHl$D  H$  D$0  H$   D  D$8  D  D  D$@  D$H  ˉD$PHD$(@ t$09|$D   L$DL$   I0t$8HJpt$@D   p<t$Hp\t$P   Ht$XHHH2΃3   D	D	D	މrIpo.H3j
ovro~z-DVIpHt$AHHHHDR<HHD
    L$h9#L$   T$lIH|$(Ld$xLL$0H$   E	 |$p?  LL$0  H|$(T$lLL$8Ht$ E	 H|$`1   D$0    LL$8HH$  HD$HD$0H|$`E1H\$XALL$pLA)1H|$PDl$8AL$   Hl$@7@ G<   HL$@HD$H<AD$HH9D$hx  AċD$At DD$8Dt$A9DDt$HD$ A)C,0H4HHDHH   HƄBh  ȃ7hG|   cL  |$D$L$  I9Fǃ3D$pD$l!  H$  H|$(1LL$0HHD$8D	 |$p?    H|$(H$   1D	 H|$`1   HH$  HD$HLt$L|$(1LLC	 H|$`11ҹ   LHLC	 HD$    fD  T$lH|$HHgaH|$`   舑H|$(   yH$  dH+%(   L  HD$H  []A\A]A^A_1111E1E1E1E1ÍAAv?9ȃD)|$D$L$LH$  HH   fI$HIH(@    HHB؀   H9uًD$Dl$pLL$8Dt$lL|$HAH   H$  Dl$0HD$HIHf     H|$(DLB	 DHH2`EHD$ LfoN Htdf.     H8h HHF    H(H   HHHNoBB   foffH~Jo  bL9uA A XDl$0D|$lH|$(Ht$ A!DAAED$0A	 H|$`   1HELL$8H$      Hl$(LL$pDd$hT$lHt$HH\$XLL$@Ld$PYA	 H|$`1   h  Hl$    HD$Dl  H\$8HL$Dd  H|HDLL$@Dp  Dt  Dx  D|  D      D8HHA$PAT$P<AT$P\AT$P|AT$   AT$   AT$   LaIʉXh<D@\Dp|D   D   AT$D   AD$At$A   H9XH|$(T$lE1Ht$H\$8LL$8Hl$ @	 |$0   HD$    Ld$HL|$8)D$    @ Al  Et
@x g  D$ MI(HAD$  A  AG  AGBffAGBHD$AED9l$hAMϋD$Dt$I|$I4$A9DDt$D$0D)ID$Av U II$AFLU LP ʉPU@ʉPU`ʉP   ʉP   ʉP   ʉP   ʉP҃DJILAHx H(MHK|
I)DE1EAJ<A9rx C|
fC|
D$hLL$0D$H$   HD$ _H$   HD$ AWAVIAUAATIUSHXdH%(   HD$H1RHōCwWHJ HcH    AE0fD  HT$HdH+%(     HX[]A\A]A^A_1111E1ff     A
uEl$LfAAc  AHH  AD$	fЉP  f=vfAL  ffAD$o   o  H  
   o  o$  Lo4    oD    oT        $  4   C0) AID$LXfnIt$F	ff=n    [    X  Hw( @ EAAEAQ  D  ED$IL$HIT$I4$A@ fI)$)D$)D$ )D$0EL   IcA@  LğLLHLLfo
G LLd$@Lfo Hf)@L9uL{@   LLfo
G foHf)CL9uHd  H?@   LH@   L   (     1AD$AŃA1A\$EuAo   o  
   H  o  o$  o4  oD    oT          $  4  D)9sSAM?9s	D)00DEl$PD)*HLL\A   A   I$HP  ID$HǅH  
   HU      D  H)u( @t[H11E1j E111*XH,( YtH1111E1E1     1H1111E1E1 11111E1E1    Ht( @t[H11E1j E111誖XH@+( YtH1111E1E1     1H1111E1E1 11111E1E1    AWAVIAUIATIUHSH1jLcxM9r1M)1 HXH谈It I<LHWI9sH   []A\A]A^A_1111ff.     {ff.     kff.     ATIUSHiHWH߅uv@#HHlHL4    ]   x@[]A\1111fD  HHxlHL4    vi   y8fHE L   H=D 谅11      M1[]A\1111ff.     AWAVAUATIԺ   @USH(dH%(   HD$1H9HFH   HG(HHH$HD$IIHD$@ HM)MH߉D$HALHL5( HMLAULL$LD$
bt$$H聺M9XZMGMuHD$dH+%(   u"H(   []A\A]A^A_1111E1E1ff.     ff.     ff.     AWIHAVIAUATUSHH8dH%(   HL$(1H?Y  H   HD$$LLT$H   H$L(L-UH   @HT$Ht$M$6f.     HH߉D$$輅HLHAULL$HM   @I   @H   @t$4HAY^M9uHt$LT$HT$I?Hu=HD$(dH+%(      H8   []A\A]A^A_1111E1E1E1@ HHT$L$OH߉D$$HLC(L5"( HT$HH|$LL$4t$4H菸XZk     IVC [ff.     Kff.     AWA   AVAUATUSH8dH%(   HD$(1L9LFH   HG(HHHD$HD$$IIHD$Mf.     HhH߉D$$HA    HHD$5)( HLAUJ    IELL$(M)MLD$ HL$Lvet$4HzM9XZMGMt	M9sHD$(dH+%(   u%H8   []A\A]A^A_1111E1E1E1f     ff.     ff.     AWAVAUATIԺ   @USH(dH%(   HD$1H9HFH   HG(HHH$HD$IIHD$@ HM)H߉D$qHAƂLHL5( HMLAULL$LD$t$$HQM9XZMGMuHD$dH+%(   u"H(   []A\A]A^A_1111E1E1ff.     ff.     ff.     AWAVIAUIATIUSHHdH%(   HD$11H߉xsH߉l$I脌LLC(L5( ILLHD$PYt$HdX   ZHT$dH+%(   u!H[]A\A]A^A_1111E1E11    SHH(SH  H9t  H5=    [111f     AVIAUAATUHS%wH|= IHcH[]A\A]A^1111E1    A$  A   fD  IǄ$      H} H(nI$  A$  H    AǄ$  I$      L`HI$  H  L9  1Q@ E~A   E9$  }I$  H(Hh< H9t
  HIc  HJI$  Hu=X^H=   H}11Ҿ     q1f.     E$   AE@H0A$   HA  Ak  EyAAiEBD(fCD.Uf.     AEHH蛉A  A  EtAA  E$  D  A  AYA$  D)EI$  IcLHRH
  AǄ$     A$  A$  Ic$  I$  I$   ãIc$  E  D9  HcIcH)LI$  Ic$     I$   tV@Ƅ҈TH@u   A
SH>IHHIVHPAǄ$  
   HD`XAD	HDcuADcHՇDHhǇD`   f     A$  A$  HxIc$  IcLH)I$  Ic$  I$  I$   EAǄ$     @ H  H(I9$  tKIc$  H-8   HH  HH1  Ic$  I$  ]fI(L  KHc     IHpHHDILHLH)I)D1҉уI<H<9rD  I$  Ic$  LxAǄ$     A$  I$  HD)\1rD  HI~HIDHLILI)CT5 L)a1ɉ΃L0L79rFYH8   H)ADALLEABD(CD. DALfLfAWAVIAUIATIUHSHz  3    HÅyn    M?  H   M  LHLLH߅   n   H[]A\A]A^A_1111D  L zHM9   H   LL   LG~3Hc  LL   HT$XHT$LH   ǃ      ǃ  H[]A\A]A^A_1111KU- "fD  HLH袻     L     xL讃HcH   Huǃ      1    LIIH\HLLLu\TLID   LH L,   LHHLu苩I4.   L2 Ef.     LȂH      H ǃ     
D  AUIATIUHSHwHLH	tuH   LL   U\HHڍ4    3MHFHL   M   Hc  LLǃ     ǃ        H[]A\A]111f  Hc  u/H  L  ǃ     ǃ      f.     H   L衜      xL  MLcD  ;UH4    H=3 t11Ҿ      Pv16f     AVAUIATAUHShv%wHt3 IHcH[]A\A]A^1111f.        D)AAD$w-E(  [   ]A\A]A^1111fD  A
>  [1]A\A]A^1111    A+(  AE fD  H1 fAǆ0  A  I(  f     LuIh  HdL9uHh  S    HbA   SIcI8  LH8Iǆ      Aǆ$       AAD$H   ME,   AAE E(fHXIU HHIUHPAǆ0  
   6HX*@	fyHXuA,  9X)H~Hx~XA,  fM@Aǆ      H~As6Au}EAU ADALfL IU HpHHDILHLH)I)D1҉уI|
 H<9rAU DALL@ AWAVIAUIATIUHSH8dH%(   HD$(11sD  E  0  HÅ   Mu1M     {  L8  M  Hzu   Q  $  u/   Hu(LL+(  Hc1"  ǃ$     H'LLLLp  L  M  >b  ǃ      DHT$(dH+%(     H8[]A\A]A^A_1111E1fD  HrHL8  M9~  Hc,  HI9j  Hy  I$   Hu(LHE,,  +(  HcHI)L.  Hc0  HIIHT$*|HT$LHIHLLLLp  Lt{M  a   Hc,  Kt5 LH   ,  BD0 M  $  uMuqLLLHDfMg  t7Hl$Hc,  LHRHtHc,  K44H:;LLn)D  M  t Ld$Hc,  LLH   LLmHǃ      ǃ$          HzH I$@    Hu(LL+(  Hc[Lǃ$     DmLc,  HQzLHLCZDA]Hf     +軦	蛦ff.     AUIATIUHSHoHLH	   HtWLSHHڍ4    jD(  Hً,  L=H8  薚xbHǃp      ǃ     Mt%   +(  I|$(LHc]ǃ        H[]A\A]1111E1     LH+   H=* Cl11Ҿ      m1ff.     AWAVAUATIUSHH(Ht$HL$H?  HLw(HH-   @H%   H   @HD$L,fD  }H   @H   @L9t@L8LAmM   @HL
<HHEuf     Hd$?HT$HT$H|$ u%H(   []A\A]A^A_1111E1E1 LI\$(L	mHT$ILL
<Ht$Ht|@ ;f     I{     ff.     ff.     HG&      HF&      HyE&      HiD&      HYC&      HIB&      H9A&      H)@&      H?&      H	>&      H<&      H;&      H"      H"      H"      H"      H"      H"      Hy"      Hi"      HY"      HI"      H9"      H)"      H"      H	"      H"      AWAVAUATIUSHH(HT$HL$H?   HLw(HH-   @H%   H   @HD$L,L8LAjHHEHM   @H   @
H   @L9uHd$?Ht$Ht$H|$ u&H(   []A\A]A^A_1111E1E1@ LLjHT$ALH|$HMD$(    I ATIUHSqN1xHiLHG   []A\111@ AWAVAUATUS   @H(dH%(   HD$1H9HFH   IH9HHW(IIH$HT$HT$thD  HI)uHD$HAiHHLAWLL$LHLD$IIt$$H諜L9XZIGMuHD$dH+%(   u"H(   []A\A]A^A_1111E1E16fD  AWAVAUATUHSHH8HT$HL$dH%(   HD$(1H?  HL(Lt$$IH-   @H%   H   @HD$L, HpHD$$$hHLMHM   @H   @贛t$$HI   @豛L9uHd$?HT$HT$H|$ u9HD$(dH+%(   uyH8   []A\A]A^A_1111E1E1    HЖHD$$gH|$HT$LHLL$$LE(t$$H     IoӼ AWAVIAUIATIUHSHHLcxM9rAM)1Ld$fD  HHAfIt I<DHL辔H9\$sH   []A\A]A^A_1111ff.     HE&      HD&      HC&      HyB&      AWAVIAUIATIUSHHQfLC(HL   LD$HMtFLD$HLALLAH   []A\A]A^A_1111E1E1     LD$HLL  LLtu     f     AUAATIUSHHeHH-JHL4    xgHFH1ɍPv-H' H     H   H[]A\A]1111EucuH
' H' fD  CH4#    H=" c11Ҿ      dH1[]A\A]1111 bH
' V AWAVIAUIATUSHHHL$HLcdHL$IM)L9r&H1    I4I| LH  I9sH   []A\A]A^A_1111fAVIAUIATIUSHHdH%(   HD$1dHH8HLLC(D$HLL  LL$t$H脗XZHD$dH+%(   u H   []A\A]A^1111E1E1ff.     fAWAVIAUIATIUSHHdH%(   HD$1QcHH膒L  H߉D$AWLLC(PHLLLL$V>t$HʖXZHD$dH+%(   u"H   []A\A]A^A_1111E1E1aAWAVAUATUHSHHHHT$H$dH%(   HD$81b    HI^H$z  HH<  HE(HT$(Ld$H       HHD$I       H<HH<HHL$ H$HD$4HD$     HXM  HD$4AVLHPLL$ LLLD$MH       Ct$DH莕Y^H$H9uHL$ HL$HHT$(H!Hu:HD$8dH+%(      HH   []A\A]A^A_1111E1E1@ HHT$蛐I  HD$4HT$SLE(PHt$LHLL$DH|$(Bt$DH֔XZm    HH$<M  HD$4ATLE(LPHHT$LL$DH$ RfAWAVIAUIATIUSHHdH%(   HD$1`HHƏL  H߉D$AWLLC(PHLLLL$Vt$H
XZHD$dH+%(   u"H   []A\A]A^A_1111E1E1衵AWAVIAUIATIUSHH(dH%(   HD$1!H߉_   l$H   LC(ILD$HtsH[jULLILLHD$PLD$[rY^t$H=   HT$dH+%(   u[H([]A\A]A^A_1111E1E1 1@ H  HiLLLUILHD$PLD$17XZ蘴     H"      H"      H"      H"      H"      H"      H"      H"      Hy"      Hi"      HY"      HI"      H9"      H)"      H"      H	"      H"      H"      H"      H"      H"      AWAVAUATIUSHH(HT$HL$H?   HLw(HH-   @H%   H   @HD$L,LLAM]HHEHM   @H   @݄H   @L9uHd$?Ht$Ht$H|$ u&H(   []A\A]A^A_1111E1E1@ LxL\HT$ALH|$HMD$(a    I ATIUHS1A1~H\LHdm   []A\111@ AWAVAUATUS   @H(dH%(   HD$1H9HFH   IH9HHW(IIH$HT$HT$thD  HI)5HD$HA[HHLAWLL$LHLD$IIOt$$HkL9XZIGMuHD$dH+%(   u"H(   []A\A]A^A_1111E1E1fD  AWAVAUATUHSHH8HT$HL$dH%(   HD$(1H?  HL(Lt$$IH-   @H%   H   @HD$L, H0HD$$ZHLMHM   @H   @Mt$$HI   @qL9uHd$?HT$HT$H|$ u9HD$(dH+%(   uyH8   []A\A]A^A_1111E1E1    H萉HD$$DZH|$HT$LHLL$$LE(vLt$$Hڍ     Io蓯 AWAVIAUIATIUHSHA;LcxM9rAM)1Ld$fD  H`HAYIt I<DHL~H9\$sH   []A\A]A^A_1111ff.     Hi<&      HY;&      HI:&      H99&      HHxHHtH1    DDLAAAD	DD	DLHAD	BH uHt?1DDDAD	DD	DDHAD	D HuGp       1111E1E1f.     AWIAVAUIATIUSH(LwxAFp	  An D?I)ǉD$HD$I?   IF HD$WfD  LHHH9saH)LD$LLHL1HH6I)AF$IAF     II?vSH?      L9s      HH9rHLD$LLHLH'6I)An III?wD$   H(   []A\A]A^A_1111E1f     Hu\ AFpMtAn @AFp    An AF$ A$IIA2T60AUIt?v     I~0fMF LAF0@   HGG G0C51AA2T0AT HH9D$uD$AFpf     SHH dH%(   HT$HH	taLWxfIǂ       Iǂ   A   H   Ic   fI)$~TLIB$IBxAB,A   HD$dH+%(      H    [1111E1E1E1E1fD  MI)IHs8uHtDEtDfADvf1I    LML\M\MYIM)LL)HH5HE1JKII9rDEDAD蛪ff.     ATUSLgx%wH͉H
g HHcH []A\1111E1E1A$   E D     f     Mg  IǄ$   fA$   fo A$   fA$   fD  Mtk H 
  LH   HXHExHs2H7   HR1Ҿ   1   S    1f     BwA$    BwЋwtI$   8    M DfD    BtHI$     &  tM ;  A$   q'E AD$$AD$xEAD$(AD$|EAD$,A$   8     
HE I$   HEI$   EOfЅufffA$   fAnD$xAǄ$       I$   AD$|A3$   fnA$   A3$   fbAD$,   fAD$$ff     h H-l   H   HHCxIHi{0H   HO11Ҿ      Q1D  HM M$   II$   Ht
HtL)HH)Ѓ_1L9M89rDfI$   H}HHM HtHt
HH)H)уHƃ1LL9rkM ыt
t҉M DDCt
ftfAWAVAUATUSHX  H_xHL$L   dH%(   H$H  1IGH9o  C     HIILC L   I   g  HD$ Hٺ@   LD$HH5 HD$.Ht$L$g C       LCp    H   rg MLD$Hǃ   
   L     LLLH.LLL1g LH5 LMHMg HD$`   HD$@   Io   LL f Ht$H|$MULtH   L_h EHǃ      o   A$D$H$H  dH+%(   k  HX  []A\A]A^A_1111E1@ IGH|$ HHH59 H|$HHD$-Ht$Le o   Cp    Hǃ   
   L   )L$PM   DEHT$`LLLE   d HL$PHMMH)IHfD     LLeHD$1I)HPI|$h.     fD  LLLLD$]e LD$HLLL,fHL$P    HD$`I,f     c ;QAWAVAUIATIUHSHH8LxdH%(   HD$(1E   M   E   IH T$J  IG0MG L@   HH5 AG     H$+I   H4$HH$ d fAG    AGp    AǇ      A   I  M   M=  E   EtI     AǇ       IǇ   I  IFH9o  }I   H$   LLLHH<$LLc I   LI   I9  HT$(dH+%(     H8[]A\A]A^A_1111E1E1ÐI   D$ H$A   q  I     H<$I      c MHt$tI   H<$d |$ AǇ       tNU  Ao   A$<H<$LLb LLLHI   LEIc   I   H|$a HD$(dH+%(   t  H8L[]A\A]A^A_fD  H<$I   
   #b IǇ   
   AǇ      Mt8M    H<$HLa I   AǇ      >I      I   AǇ       tH<$   H5	 H)a W        I   H5]	 H)ea OIt     H|$   L`LL1L)*H<$   H5 	 H)a C D$MMI   H$ff.     Hx t)SH@` H{xH   F   [11D     11fD  H9"      H)'      UHSHHIHHǀ       HHH豬H   []11ÐAWAVAUATUHSHH8HT$HL$dH%(   HD$(1H?E  HL(IH-   @H%   H   @HD$L,HD$$H$    HwH߉D$$HAQHHHLAVLL$HM   @H   @I   @貉t$4H{Y^L9uHd$?HT$HT$H|$ u<HD$(dH+%(      H8   []A\A]A^A_1111E1E1fD  HvH߉D$$DH߉GHLC(LUHT$HH|$ LL$4t$4H+{XZp@ I\ AWAVAUATUHSHH8HT$HL$dH%(   HD$(1H?  HL(Lt$$IH-   @H%   H   @HD$L, H vHD$$FHLMHM   @H   @;t$$HI   @azL9uHd$?HT$HT$H|$ u9HD$(dH+%(   uyH8   []A\A]A^A_1111E1E1    HuHD$$4FH|$HT$LHLL$$LE(F;t$$Hy     Io胛 AWAVIAUIATIUHSH1'LcxM9rAM)1Ld$fD  HPHAEIt I<DHL~H9\$sH   []A\A]A^A_1111ff.     AWA   AVAUATUSHHdH%(   HD$81L9LFH  HG(IHD$L9   MIII LHH$   HD$7LL$ E1HD$HD$6LHD$L\$( ILIC/D$6LLDH      SHt$ ILL$(H|$|t$GK,   H   "	XZH$H9tLL$ L\$(M)MMM9MGMHD$8dH+%(   u%HH   []A\A]A^A_1111E1E1E1w    AWAVAUATIUSHH(HT$HL$H?   HLw(HH-   @H%   H   @HD$L,L(LA}CHHHAW   @IM   H   @H   @NY^L9uHd$?HL$HL$H|$ u,H(   []A\A]A^A_1111E1E1f.     L蘲LBH   LSHL$IML$(H|$ ʣXZfD  Iff.     t1111D  S   HHG1~
H&   [1111     AWAVAUIATUHSHH(Ht$?BHH   Ht8Ht$LE(LHH(   []A\A]A^A_1111E1E1D  II?v~ELF          >    Z      @       S         @ 8 
 @         @       @       @                                                                                                     4      4                    @       @       @                                                  =      =                   0>     0N     0N                              hM     h]     h]                                8      8      8                                   X      X      X      D       D              Std   8      8      8                             Ptd   @     @     @     t      t             Qtd                                                  Rtd   0>     0N     0N                        /lib64/ld-linux-x86-64.so.2              GNU                     GNU g?I8R֦#         GNU                      K             K   L   M   em铔qg                                             E                                           T                                                                5                     ;                     )                                                               r                     I                                                                                    H                                                                ]                                                                                     ]                     F                      f                     {                                                                                                                               P                                                               ]                                          l                                                               z                                          \                                          B                                                               S                                           4                     =                                           L                     .                     D                     Y                                                                                                                                                     c                     C                                          $                     g                                                                  ,                                                                                      b                     X   "                       i                `             _ITM_deregisterTMCloneTable __gmon_start__ _ITM_registerTMCloneTable __libc_start_main __cxa_finalize _Z19catch_out_of_memoryPFiiPPcEiS0_ _ZN14DbeApplicationC2EiPPcS0_ stdout dbeSession _ZN10DbeSession10createViewEii _ZN10DbeSession7getViewEi strncmp _ZN7Command11get_commandEPcRiS1_ parse_fname free strtol gettext stderr fprintf strcmp fputc _ZN7DbeView13set_view_modeE5VMode stdin _Z15print_anno_filePcPKcS1_bP8_IO_FILES3_S3_P7DbeViewb fclose _ZN11Application14fetch_commentsEv opterr _ZN11Application18print_version_infoEv exit strdup _ZN10DbeSession16createLoadObjectEPKcl _ZN7DbeFile9find_fileEPKc read_from_file _ZN10LoadObject15sync_read_stabsEv _ZN10DbeSession16map_NametoModuleEPcP6VectorIP8HistableEi _ZN10DbeSession12createModuleEP10LoadObjectPKc _ZN10LoadObject12set_platformE10Platform_ti _ZN10DbeSession15createClassFileEPc _ZN7DbeFile12set_locationEPKc _ZN11DbeMessages9get_errorEv _ZN10LoadObject10status_strENS_11Arch_statusEPc realloc _ZN8Settings12proc_compcomEPKcbb _ZN7Command14get_err_stringE10Cmd_status strcasecmp _ZN10LoadObject14dump_functionsEP8_IO_FILE strstr getenv strchr dbe_sprintf fopen _ZN14DbeApplicationD2Ev fputs fwrite strlen memcpy cplus_demangle malloc memcmp strcpy _ZTS6VectorIP8HistableE _ZTI14DbeApplication snprintf memmove sbrk __environ _ZdlPvm _ZTVN10__cxxabiv117__class_type_infoE _ZTVN10__cxxabiv120__si_class_type_infoE _Znwm _Unwind_Resume __gcc_personality_v0 libgprofng.so.0 libstdc++.so.6 libgcc_s.so.1 libc.so.6 CXXABI_1.3.9 GLIBCXX_3.4 CXXABI_1.3 GCC_3.0 GCC_3.3.1 GLIBC_2.14 GLIBC_2.34 GLIBC_2.2.5 /usr/lib/x86_64-linux-gnu/gprofng                                                                 	                          @   yѯ        t)        ӯk                0   P&y  	      a_&	                                    ui	   
      0N            p[      8N            0[      HN                 XN                 N                 N                 N                 N                 N                 N                 N                  O            0     O                 (O                 8O            x     HO                 `O                 pO                 O                 O                 O                 O                 O            R     O            R      P            !     P            &      P            Y     0P            .     @P            8     PP            8     `P            3     pP            3     P            ?     P            ?     P            E     P            E     P            P     P            P     P            g     P            g      Q            ^     Q            k     @Q            }     PQ            }     `Q            t     pQ            t     Q                 Q                 Q                 Q                  R                 0R                 @R                 PR                 R                 R                 R                 R            Y     R                 R            }     R                 R                  S            m     S            m      S                 0S                 @S                 PS                 `S                 pS                 S                 S                 S                 S                 S                 S                 S                 S                  T                 T                  T                 0T                 @T                 PT                 `T                 hT                 xT                 T                  T            !     T            $     T            P     T            %     T            +     T            %     T            8     T            '     T            0     T            3     U            =     U            '      U            @     (U            C     8U            6     @U            N     PU            Q     XU            T     hU            V     pU            Y     U            [     U            ^     U            a     U            d     U            k     U            n     U            x     U            {     U            J     U            U     U                  V                  V                 V                 (V                 0V                 @V                 HV            o     XV                 `V            |      pV                 xV            h     V                 V                 V                 V                 V            
     V                 V                 V            m     V                 V            m      W                 W            m     W                  W            m     0W            !     8W            B     HW                 PW                 `W                 hW            4     xW            9     W                 W                 W                 W                 W                 W                 W                 W                 W                 W                 W                 X                 X                  X                 (X                 8X                 @X                 PX                 XX            U     hX                 pX                 X                 X                 X                 X                 X                 X                 X                 X                 X                 X                 X                  Y                 Y                 Y                 (Y                 0Y                 @Y                 HY                 XY                 `Y            +     pY                  xY            #     Y            '     Y            *     Y            -     Y            +     Y            0     Y            3     Y            <     Y            6     Y            8     Y            ;      Z            >     Z            A     Z            E      Z            H     0Z            Y     8Z            \     HZ            ^     PZ            a     `Z            d     hZ            g     xZ            o     Z            g     Z            q     Z            t     Z                 Z                 Z                 Z                 Z                 Z                 Z                 Z                 [                 [                 @[            {     H[                 P[                 X[                 `[                 h[                 p[                 x[                 [                 [                 [            H     [            I     [                 [                 [                 [                 [                 [                 [                 [                 [                 [                  \                 \                 \                 \                   \                 (\            ^     0\                 8\                 @\                 H\                 P\                 X\            4     `\                  h\            B     p\            $     x\            +     \            )     \                 \            3     \            %     \            ;     \            U     \            E     \            |      \            M     \            T     \            @]     \            NT      \            XT       ]            S      ]            T      ]            P]      ]            tT      (]            ]      0]            ]      8]             W      H]            `     X]            x     a            a     @]                  P]        2          `]        "           _                   _        K           _                   _                   _                   _        3           _        ;           _        =           _        >           _        E           _        F           a                    `                   `                   `                   `                    `                   (`                   0`                   8`        	           @`                   H`        
           P`                   X`                   ``                   h`                   p`                   x`                   `                   `                   `                   `                   `                   `                   `                   `                   `                    `        !           `        #           `        $           `        %           `        &           `        '           `        (            a        )           a        *           a        +           a        ,            a        -           (a        .           0a        /           8a        0           @a        1           Ha        4           Pa        5           Xa        6           `a        7           ha        8           pa        9           xa        :           a        <           a        ?           a        @           a        A           a        B           a        C           a        D           a        G           a        H           a        I           a        J                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                           HH HtH         5 % @ % h    % h   % h   % h   % h   % h   % h   % h   p% h   `% h	   P%z h
   @%r h   0%j h    %b h
   %Z h    %R h   %J h   %B h   %: h   %2 h   %* h   %" h   % h   % h   p%
 h   `% h   P% h   @% h   0% h    % h   % h    % h   % h    % h!   % h"   % h#   % h$   % h%   % h&   % h'   p% h(   `% h)   P%z h*   @%r h+   0%j h,    %b h-   %Z h.    %R h/   %J h0   %B h1   %: h2   %2 h3   %* h4   %" h5   % h6   % h7   p%
 h8   `% h9   P% h:   @% f        LcIKH8H$H   ?-   A9   KLI1Ht$(HLD$D$HD$(D$LD$H   LL$(AHDHH$E1  H<$#H|$(  H߾   WH1
   L$LD$DT$%DT$LD$L$tDyL+ IcIBA9tH$KLH8?-#1
   HL$DT$HL$  H$H8H=  C1HHg H81H|$(C  HD$MDHD$IL  HD$H5 DT$H HHH$1      H<$H5 E1E111҅   o   H  H=+ 1HH  HCp1H   H   H= $e1HH\  HCpH   H  E1
  H	H{(  H<$H5 o>|$ DT$  HD$MDHD$ILAE1DH߉  D|$   1H  #Hz GHRA   LH   IVH9V%A@@u5AxD t.   IHHE1L 1Ҿ   HF  HCp   H   E1L9r~HRNIHz HR$A   LH   IVH9VA@@u1AxD t*ubIHHE1Lr 1Ҿ   H  HCp   H   E1L9r~HRNIH   
   L$L$H   
   L$L$H5; HDT$HL$DT$  AƉ$A  DT$H= 74$HH-  HCpDT$H   Hj  E1      tH     H{h   eH=m AHH  HCpH   H   Hz    HRH      L% L21H   HMH9O   AF@uMA~D tFI  H I~HRLj 11sh   LME :H   HCpH    H   E1H9i~HIL4HvHM  H     A    1H$HL$H8lH     DT$H=? o  Hz HRA   1HH   IvH9wgB@u9zD t3u[HJH$DE1L׵ HDT$&  HCpDT$   H   1L9v~HVJI돿
   1H   
   HT$DT$HT$DT${o   =      IH5 HxIH|$  H|$H5a   H LH5_ H81   M*
  AV+  H8D[]A\A]A^A_Ã   Dl$(W  IcI<Ht?-t+AF9:  En1  IHcD$$HDHC(  1
   Ou   Dl$(  Dl$(  IMH H5 HS H81Mm N  Au	  AE9}	HHPAD9~	HHPLJL%{ 1HHI<$rHx8HCpH   H   1L1Aƃt#Ht$,   H   D>{xH{p   kAƅ  HCp1҉Sx   p(    fI<$1HH HH1HBB  BH0HspI<$HHP	
  HCpH=g H[ H@8H   KHHHn HH81   |$,Cx   HHA   P~11Ҿ   OtHCpI,$LH@HHHHCpL   HEXIT$ID$H9}zID$HrH}8It$LH,HE HPP   H}(KH   H=* HhH[ NHHt HHH81	  HID$      H9:  H< H   @H=   @HHOID$H{pett    q	hH= H[ LHH HH819H= H[ LHH HH81
H= H[ TLHHw HH81H{p1҉IHt'HHF HS H5Ұ H81qL    AA	~I|$H4    qIT$ID$Y[]A\A]A^A_H=* HHHH H8AY1[]A\A]A^A_fH= HWHHHz H8AZ1[]A\A]A^A_H=U (H   H1HCpH   H
  Hz   HRA   L*H   ID$H9BE  ImPHM  HuH}/  HCpE      H= HIEPH  HCpE1H   L;b  IH=g 5K  HZ  H5 H   H: H- L H   H   HtH H;8tTL     jtho  HGpH{  H   HuH}=  E H=D AHH  H   H{pA[[]A\A]A^A_P  HH@^[]A\A]A^A_H5k HxH=_ IIHHAMt	E   ~   HtH  E  HpH=  1PHH5 HIHH= HHH	
 H81?[H[]A\A]A^A_IT$H= 1HH=6 IHLHH H81HCh11HH  oǅ_  PH= HAHHHHa H8AX1[]A\A]A^A_H=` HnHx pHPA   L:IVH9PUIL1PIO8IW`HH   I1E1'IEPL9p~HPN<IHRN,HjHu1ÐHH   HH   HH6HA`HV`H9uH   H   H9ÐHISHH;H߾(   [}H HMUHSHAQ@uH   
      ~0H   Ht(   H   AX   [H=	 ]X[]1HD$H%   AWAVIAUIATIUSH(IIl$wyHD$   H$L9  L}1HLAօ~FHE HD$HEHE M9s(I1H4$H|$Aօ~IGH|$HGIHD$IHHL1O|LHIHA1LH߅~!Aօ;1LLAօ~7LHL=Aօ~R1LLALLHLLLHHLLHH9tH8H1H9H9tH
HH2IH9rL,1HHAօVH$1HHAH$	HH9rH9t:HE HHU HH9uHEIHHHLyHH9tHEHHIHLL)HI)I9rHL I/LHILH([]A\A]A^A_@ AWAVAUATIUSHH8HIMH 10   HD$$D$A   HD$IcM4M>A?-lHT$IHt$(-Aǃju#H   HDl$(PAD9eVu|$ tHƃ   D$ K@w;Dt$(   ƃ   EED9&A   HHPYfD  AWAVAUATUSHPVu#H H H9   DX[]A\A]A^A_AH̓sHn MMHcHHGh1ɺ   HH  ǅ#HGh11HH  ǅtHGh1ɺ   HH  hǅXH=l =1HH4H= $H   H1H{p1HPH=9 HH   HH1THCp   `H=s HH H8Z1[]A\A]A^A_Hh1H=< AHH   LLH ATHj sh   LHY L IH JHh   1LLHK AWHj sh   LH L H      1I^HHPTE11H=    f.     @ H=) H" H9tH Ht	        H= H5 H)HH?HHHtH HtfD      =  u+UH=J  HtH= d ]     w    HH=   ff.     @ AWAVAUATIU   SH8#1LHHL- 11H< L5 Hsp1HA   H H   IE    I>Cx   H   ǃ       ƃ    I>A   C`$LHHChD9+H   I;u    HHPH81[]A\A]A^A_IcHHD$LH8HD$?-	   H5h H<$NH<$vHT$$Ht$ HAoJvHH    Hqt
vD@ws|$ <A        5AE1DHD|$ At@w&L$    DA9tMH     PH= H1H= H1s1ff.     H9 SHHH߾   [ff.     @ HO<ntuPЀ	   E1҃0H1AA@ DH)IH#9|(HO4P0<	vԉEE    HQHWAHЀ	wHA   x1f.     uHG8 t#HPHW0ht#vu)HG8_t1D  HHGHG8_uHHG   @ HG8TugHPHWP_t^ntQHcxDHG8_u;HO(HG9O,~+HcHHG H@    O(    HP    1D  HO(HG;O,}1@ HG8_uHPHWx_tDx/   f.     HHG#x	~HG8_t	1fD  HHGff.      USHHH   H=   t&HPH   @4@  H[]f     Ƈ    H       H@  Hǃ      @+@  H[] Hg  H^     ?/H  HH8        tstUt7t?/	  HH   ?/   HH   ?/   HH   ?/   HH   ?/   HH   ?/   HH|   ?/uwtvHHtg?/ubHHtY?/uTHHtK?/uFHHt=?/u8HHt/?/u*HHt!?/uHHt?/uHHuf1HG     H   H  HNH@H@d  HT     8/B  H@H2        tstUt7t8/  H@H   8/   H@H   8/   H@H   8/   H@H   8/   H@H   8/   H@Htz8/uuttH@Hte8/u`H@HtW8/uRH@HtI8/uDH@Ht;8/u6H@Ht-8/u(H@Ht8/uH@Ht8/uH@Hu1H@D  Ǉ0     @ H   AVIAUA   ATI g   UH- SHwHcD H'5wLHLu%tHsLHuH[HufD  1[]A\A]A^D  HLHt8/t1    1D  AUATUHHSHHXH   H   L,%fHHQHH   Dd
 D  I9t]D#H   uHƅ       HH    H@  Hǅ      De D  I9t
D#   fH[]A\A]D  AUIATIUSHHHzHjRHD>H9r8uH;LLHLHC  LcH[]A\A]f.     uHt7    HH9rH;H}Ht%HCHkuH{@    HwH;1fC   HCD  AU1H5. ATUHSH(HH-HH   H   L,*    HHQHH   Dd
 D  I9teD#H   uHƅ       HH    H@  Hǅ      De D  L9tD#   f.     H([]A\A]D  AVAUATAUSHH Y  Z   Xs  Ǉ0     H1H5 DH"HH   H   Ll % HHQHH   D$D  I9t^De H   uHƃ       HH    H@  Hǃ      D#D  I9tDe    fH []A\A]A^ A   H-T H   Dm H      HBH   D,D  DmH=      HPH   D,D  ImH      HBH   @,@      A   H- [fD  A   H- CfD  ƃ    H     H  D+   DmH@  Gf.     ƃ    H     H  H@  Hǃ      D+D  Im       H  ƃ       H  H@     1     AWAVAUATUHSH    D     A     ǀE     q  Hh  }  ^  } _T  }DJ  fH5 HHD$p    )D$`      HH  HD$`H@ HD$pin  fGHGD maHD$h       HT$`HA3 IH   Hĸ   L[]A\A]A^A_HIC AfHD$     HD$x1ALl$ D$8    $   
HD$h    ?_Ll$pHǄ$       HǄ$       Ǆ$       $   HǄ$       D$(tY1j   nfD  E1;HT$`%   H^2 IHOD  @8D  G<R  <ZuNuH1Ҁ} Ǆ$   H|$`HL A@aHHT$h<_  Ar  $<w
I  H|$ &D     HH5g L=U HEHDE1E E$GD$A   LGHXIĸ   HcHHDHIHg  |$<  HHH5 1fH(H|$`HT$@HHl$@D$H{ H|$`Ht	8   H	  f11HD$p    )D$`fD  H9/H)$H|$`   R HD$h  Lt$`F HX   HcHHDHIH{  D$LIA  <OHD$   L%
 HT$H5 D$    7    I4$ID$H{HHt$Ht$HD$HLuHD$IHcD$HHH HtHHt$"Ht$H{HI0HAE L"H_<T  <EP     A} uB           HLIHHAWu_uFAGuH\$Ee LA_  A<_  QLiE$WHA   _  y_  H/    E1L=[ &fD  L{HAMLHLLuMcH IJl HnL|$HHHLHHD  IT$HH LAEIIAGu<_  AEAGurH9 HD$hH4H¾   HH   HtMHt!IHȀEI  HL$h1.@IHt	E#  HD$h1.@IHt	E  1.HD$h@HTIHHt	E  1.HL$hT@IHAt	E  1.HD$hI@THAt	E  1.HD$hI@THA`ROHWL=Q HT$`HAOt-1<.t'HHL$h<_tAGBHuLd$`   L< $   mH$   H;T$h!  H;T$h	ЅE   L; T$8u
HD$(HD$   Lt$ ME    HD$hfD  HL$.HYh    A}KAE<Bt0<_A}_
AU.IHE$WHA} @ B|'EMt$Lt$hII   H5ڎ L@wHD$@HD$HD$`HD$Ht$H|$e+ $   HD$@H	L9$   rH|$H!8h11A   'a@WD	HB  H8DYЉA	wŃ0D  <Bt<EHAIHAOtHHHAOusx H\$<Xu$DbLjAnuEeIAntAbtH\$A.u5AEAGYAUIEIAWtPHIAWuEZ&<S   AEEeA_tEtEe <RtdH<ItU<OH IMHHHT$HL$'H|$MHL$HHD$"<WH H H Ǆ$      1LS9 $   H$   HwJ <Xu>AEIU<nufD  BH<nt<bt<SuB!II<DwAE<At*<FH- HHJHrH
H- H\$IV1уfHffuH1H$   EuLd$hL%> H$    tH$    uHT$p   LT$xLt$H|$L=( H LfoL$`foT$p$T$\+ H HD$hH9$   r$   q    #I  Iȃ1wx(wS   HH  |  H   Ht[O(;O,}RHcHHG H@    O(0HPL@@ F׃w"H
- HcH     Ow3w&1 F	wH
! HcH     N̸   Hd. 
t;HtMU H      H=H Hu1fD  N1ff.     HGRtOtH OHRt HH    OH1HG HH   OH1HG O(;O,}8HcHHG H@    O(Ht~H@         HpP1ff.     f1~qHwHOHcH)H9|XHHGGt8$tN	~0H_GLOBAL_H9u!F$<;wHHr~	Nt)DHG@    1HG@ÐHHG	ؐGH)ЋW(GH;W,}HcH
ˈ HHG W(H@         HH@   f.     HGI8WtCzfIS   H+IHtUW8;W<}MHO0HcHHGW88Wu9HPHWxPuHHGIT   HIHu1    fHW:SuxHBHGBuwWutHO   	Cv1@<t  <a   <b  <s	  <i
  <o  H <d   E1L     HBHGBPЀ	v<_u1<_u";O8sHG0LLÍPND  1@ HPHW <_tIʍHЀ	wҍL9rHG8 uE1w HeҍL9sU@ vH LJ(G(DG,Mt8DR0D92  HcȃHHO HA    G(   LIDQHO@   HJR WHA9   Lc؃IL_ IC    G(A   IKASHG8BSH_@ HHGLھM   HIHG8BtH_@MtG8;G<}HW0HcȃL[G8LE1[LHJRSG(DG,H^ 1H E1`H H H> 1f.     USHHHG8Jt^t:H   HHt<H
  HHt,HHH߾)   []@ H1V
  HHuH1[]D  HHGfD  SHGu&WX   wBGXHG8FtWX1[D  HG8FuHPHSxYuHHC   H$HHYHS:Et1CukX[fHHSCtAVAUATUSHH HoHU|    E <T-<@   A<   H HcH    H%   H >      HHt]aH HHHЋS(;S,LcHILc ID$    S(ID$@A$'   CHHk   @ /     H H߾   []A\A]A^   D  Ht$1H  HH   HCH߀8FtqHE H  0VwHL$HPHHHE HD$HU Ld$M  C8;C<  HS0HcȃL$ʉC8H L[]A\A]A^HE Hup  D  HHHk81ɾ%   HH6HD$H:  S89S<.  HK0HcHLd$S8H [L]A\A]A^D  HHHk1ɾ$   HHHD$    HHHk1ɾ&   HHHD$d@ HHD$NfD  HEHC} y  HEHCEF<0b  H HcH@ HHHk1ɾ#   HHHD$@ HHHk1ɾ"   HHHD$@ HHkHD$} ISP  H   S8;S<   HK0HcH1ɉS8E PwHHk  HHT$   H\HD$"fHuHsE<_  0<	  IfD  MILCA 0<	vDH)HHtAAL<_?  E1eD  HHHkHHtHHHtH+   HHD$nkLCL   HL  kL1ɾD   HHwHD$HtHS: sHJHK:EbS8;S<(QfD  HHK)@b  @xt@_"1s(;s,  HcփHHS HB    s(H5 \   HrfB@jHLl$HT$HKH5~ L1誽Ld$L-IL$HCHA@ЉCHC(;C,LcC(IH~ Lc ID$    A$    ID$AD$   C(;C,=LcC(IHt~ Lc ID$    A$    ID$AD$   nC(;C,sLcILc ID$    C(H A$'   ID$CH+C(;C,0LcILc ID$    C(HN A$'   ID$CH	C(;C,LcILc ID$    C(HK A$'   ID$CH
C(;C,LcILc ID$    C(H A$'   ID$CH	b}_  C(;C,HcHHHk HE    C(E C   dHHEHC8_HHHCqH-   HHnHD$4C(;C,LcILc ID$    C(H A$'   ID$CHC(;C,LcILc ID$    C(Hd A$'   ID$CH^H1ɾL   HHHD$C(;C,?LcILc ID$    C(H= A$'   ID$CHC(;C,LcILc ID$    C(H A$'   ID$CH@ HHHk1ɾ(   HHD$    HHHkHD$HHC8It^HH!   HHHD$f.     1HHHsH*   HHHD$QHHC  HT$   HH_HD$HsDcLCL   H
  DcLHHBLCA *HEDs(Dk8HCDcH  HS:ItHkHD$Ds(Dk8DcHHt$HS8;S<HK0HcH4HH߉S8H   HD$nHC(HK;C,LcILc ID$    C(HP ID$CHA$'   HDcLCL   HHk	  DcLHH+1BUSHHHGD E   HPHWDPD EtsHPHWDPAv   EZA	wRW(H;W,~   HcHHG H@    W(Ht`EH@     3   DXHHFE1ҾH   1L
o     )щHcHII<HD8tTP9u1H[]@ D8QuS(;S,}HcHHC H@    S( 2   HxH[]     9tAcaAvWWL1oPGPsP1Hu4   HkPH[]þ5   Hff.     fUSHHOHD$    <E@@uo<.HHl$t@\    1ɾ.   H!HE Ht=HKHh<E@@u-<.t)<Rt<OuyEtHHHu1H[]fHD$HtHx uHP:'uHRz	uӋR)SHH@    ff.     HG8T   UHSHHPt   8ntspu]HHG[   HHt<HH1[]4@ yu*H11ҾX   HGHH[]@ E    H1[]     HHGHHtӾY   @ 1D  HHG+   HHtHC8EuHZ   HCT     ATIUHSHHD$    H\$	fHHXLHHuHT$HtHH1ɾW   []A\8     H1[]A\D  AVAUATIUSHH Ht$HT$_  HWHЀ	|  H   DoL<o  HDkLHH|  82  HL$HtHU   HHHC8BA  MtHL   HiHH H[]A\A]A^fD  <Dh  H  <Lt  <U  B<l  <t  HBHl$HGzt  HJHOB<_  <n    HO9_  HS(HK;S,~  HcHHHk HE    S(HEC8E I   ;C<L  HS0HcȃH,ʉC8fD  3HL$HHHC8BD  L[@@ HHHCHM   HHHC8BtL[@ zn*HGL    HWfB<CD  HO@Ht1    0<wyH5 HcHfD  H@KHPH TSH8lxix H/H7   HOH<C,      1   HC(HS;C,}HcHHk HE    C(HtHE    E    uHM8   밾   멾   뢾       HHWHHtfD  1+HE1HW IAM;HC8E  H.1ɾR   MHLIMuHHO@H1tu    ACH<CuoB<Ii  p@HDhHSC(;C,HcHHk HE    C(HHE    E    DmHM<DdB HBHGzlFHHt$D$    HWDt$IEHH
M   IEHS:EHBHCR_t*nHAHC8_HHCC(;C,HcHHk HE    C(E G   LmDu@ HCHBHCBHπNHHDhHSbHK@{1I%HH1    AVAUATUSHWH<LV  <T^  <stZ<f   HЀ	v<o  znuPHHW11HHHA  HC8I  [H]A\A]A^ B<rD  <p<  HHH   2   3  4  HC8_  H&HI  fD  zpuHBHGB<T  <_&  <n    HW:_v  HHWb  S(;S,S  HcHHHk HE    S(E    HE HUL2BCHAs   A~t   A~    HuH7   HH   fHBHGBWT  <9   C<7  H H  CT1Ha	  HHC8Eu
HHCD  1HHHC8IfD  HHHCh  H   HH[]A\A]A^D  DbA:    A  A   q  d  A~X  A~   H HIHI
HH   L<   H.L;   HH:   HDfD  <it<t   zlFH1HS<t  : t@z t:E   H  H1   HHD  E6tt1[H]A\A]A^D  Eu1H6   HApk  mb  E1s  A~P  A~   H  HEtHʾ9   HHH7   H;D  <uLHHWHs  H?   HH[]A\A]A^   []A\A]A^ A~cA  f  d  A~i  A~   11HMIAcE  A~l:  A~ /  E   Hj  ILL9   H$H8   HJ@ H   HWfD  A:VHS:_HHSAvA~u>A~ R.HE   HHC  H     HHHSH1HWwHHW#1ɾL   HH</H1H1f     HHSH<@ d#  A~t  A~ 
  HCg4  su
xr  11HIHC8IHHHC>  L   HHI\A<f   <nAF<wt<a_   H  HIFIHCE   p   ixlHH    JvJ[HIpuA~tuA~ HIH}IKxsHI/H,xiHE   HHC  H'H1HCfD  AWAVAUATUHSHHLwT$҃LH4$E>ET$AAEAAW_        IFHEAr  AV,  AK2  A~    IFHEAF<x"  ߀Oe  EH	1ɾP   <Otu1H{HH   LuHXLE>^ kD$u~AFuxH$H9toH$H(E    f.     E       @ DuLEL   HDuLHHt!HE8EuHP   HEQfD  1HH[]A\A]A^A_@ EH	11D%     EH	11D
EHt$1EH1ɾN   t3HEH$H9tH$H(E +uE    D  E    <wWEHHHH?HE8E2HQ   HEkHW<LteI<wTHHWbf<XuDUHHHWoLGL   H|$kH|$HWoL:Eu"HHWH]@ s 
   1@ ATUSHHHGLg@8EtxHD$    Hl$-     1ɾ/   H1HE HtHhHC8EtH#HHuH1[]A\HLc@HCHD$H[]A\fD  H11Ҿ/   HGH[]A\fATE1USHHK1@D   @I!  @T   MujHRIMtZHK9EtT   1@D   @IuHHHKHHtL   H.IHufD  E1L[]A\D  @M   @S      H/HHtǋ SvMuHKI1@Dh@ A<TuUMuHI!C8;C<tHS0HcL$C8fD  MJf.     1LH3IH"fHHK AUATAUSHH(HW<U     <N  <SK  ztY  1*HH   S"  HC8IuQHHHCGHH   HHEt&Hs  C8;C<g  HS0HcȃH,ʉC8H(H[]A\A]     <Z   HBHGB<G  <T  1  HH	  HC8E  HPHSPs'  d  1HHH   G  }   H   HH     1E1HLH}HHC8IHd  S8;S<X  HK0HcH,S8Q111'HEfD  H  HHHt$HW   HH   1H   I&HE H   M  Hl$HCLl$Im8EL   HHCE&@ HBHGG(;G,  LcG(IH_ Lo IE    AE     IEAE   GHzS   1HHL$莽HL$G1f     HPHS@<_r  <ntH谻AxHS:_uH1HHSIHt G5  C(;C,   HcȃHHK HA    C(H   DiLYGHzSE11HHH8 SMq1f.     HC8EHl$gf     HE8)3H@    &fD  1f     HHHC0C(;C,}HcȃC(HH^ HK HA        HAA   E1Hڻ1ff.     USHHOHAGHHGTtJGujHPHWx t\HPHWPV^@~FAw>H
n HcHfD  HPHWx tHPHW@A<5  H1[]f.     ruv~HW: tLJLO:_uDPBt<$'  1AQS  _  $   $uH{K(LO;K,   HcуIAHHS HB    HЉK(B   rLKMtHLھA   HH,E
  AIÀ$YLIcE1t`Ht9HtA(  <$   A   C
  <$  ICD  <$  II9tpC  <$  IHA	IȄ  <$  IC  <$  AD	LAD  <$y  LAI9uLcA)LHlLKMLKH  H5l HcHD  11ɾ   HHH[]f     x   HPHWxn@)  <Gt<T   HH1ɾJ   1HŋC(;C,   Lc؃HIL[ IC    C(AC   ҶHICLH   U@ HD$    Ht$
HT$HH1ɾV   []D  @<Gt <Tt1e  H1ɾ   fD  H(H 1H6  HE1Zq1ɾ0   Hv   踶mHG <G  <T  1  H1ɾ   lh   y.HG <G  <T  1  H1ɾ   -1=1.HG <G  <T  1X  H1ɾ   1R1ɾ   HOHX1ɾ	   H
OH>1ɾ
   H*1ɾ
   H1ɾ   Hp1ɾ   H\11ɾ   HF1ɾ   H2HH艴HC8_HHCCHH   H DE)D  .   fD  /   fD  E1z     LKt<Gt:<Tt61  H1ɾK   HH9HHHHHHW1H¾@   6ff.     fATUSHG8Lu}LHHLOP_c  ZtnHHtS8'Lc   A$A=   <n   <En  IT$ f.     HSIHR<E   u1H[]A\@ _   IAHCAA<G   <T   1H  LKHA<EuIHLK[]A\f     H@PtP)SHH8H5JV @A$*<E   A=   <n* IT$A>   HSAD$I DLHD)HDHYHAPD  LH1LK@<Z5D  HLKHAILc1LHvHDHLKHA     AUATAUSHHHGHD$    Hl$@80u.w    1ɾ.   HHE Ht,HhHCD8 t3DkLCL   H(DkLHHuH1[]A\A]    HHCHD$H[]A\A]H11Ҿ.   HGH[]A\A]H@  UHH g SH   HC74     )C3}   w tuTH[HuH[]fD  HHH   HsH4  lHsH`4  H[]ÃvMul      4!wHH??uH      Hu   lH[^wH[]ÐI       Lu3;- Hs>F\  :fD  UHSHHtrBHӃg4     YfHnÉCHH  4  HHH  )$81  HD$HH  k4  H[]f.     ǅ0     H[]ff.     @ AUATAUHSHHNwH@d HcH HHDH[]A\A]     H   H=   5
  HPH    Ƈ   H     HPH   DrƇ  rH   N  HPH   DeƇ  eH     HHH   DsƇ  sH     Ƈ    H       H@     tric  D  H   H=     HPH    Ƈ   H     HPH   DvƇ  vH     HPH   DoƇ  oH   j  HHH   DlƇ  lH     H  Ƈ         H@  at  f   iHBDlHPH   eƃ  e!  H   H=     HPH    Ƈ   H     HPH   DcƇ  cH   ~  HPH   DoƇ  oH   
  HPH   DnƇ  nH     Ƈ    H       s   H@  D  HPH   tƃ  tH[]A\A]    H   H=     HPH   &ƃ  &H[]A\A]@ H   H=     HPH    Ƈ   H   J  HPH   DtƇ  tH     HPH   DhƇ  hH   Z  HHH   DrƇ  rH     H  Ƈ         o   H@  HBH   wƃ  wHUHHH%  f     H   H=   M  HPH    Ƈ   H      ƃ    H     H  &   H@  tf     H   H=     HPH    Ƈ   HUAfD  A?H   H=     HPH   *ƃ  *HU    H   H   2HBH   &ƃ  &H=   {  D  H   H=   	  HPH    Ƈ   H   Z  HPH   D_Ƈ  _H     HPH   DCƇ  CH   
  HHH   DoƇ  oH     H  Ƈ         Amp     H@  fDlHBDeHPH   xƃ  xfD  H   H=     HPH    Ƈ   H     HPH   D_Ƈ  _H     HPH   DIƇ  IH     HHH   DmƇ  mH     Ƈ    H       H@     aginHPH   aƃ  aH     ƃ    H     H  r   H@  HPH   yƃ  y       (k  HUDHH   H=     HPH   :ƃ  :H   F  HPH   D:ƃ  :H   
  HBH   *ƃ  *    H   H=   %	  HPH    Ƈ   H     HPH   D_Ƈ  _H   ^	  HPH   D_Ƈ  _H     HPH   DvƇ  vH     Ƈ    H       ec     H@  ftHPDoHBH   rƃ  rH=   8	  H  ƃ       H  H@     1H   (ƃ  (HU   H-I H   Lm*@ HHBHH   D$D  I9cDe H=   uHƃ       HH    H@  Hǃ      D#D  L9De    {H   H=     HPH    Ƈ   H     HPH   DnƇ  nH     HPH   DoƇ  oH     HPH   DeƇ  eH   J  H  Ƈ         H@     xcepHBH   tƃ  tHUHH=   H  ƃ       H  H@  HU1   H   (ƃ  (DHH   H=     HPH   )ƃ  )H[]A\A] H   H   \  HBH    Ƈ   H=   5ƃ    H     H  H@  Hǃ      &ƃ  &
@ H   H=   <  HPH    ƃ   gf.     H     ƃ    H  ::     H@  f3f.     Ƈ    H       H@      _ImHQH   aƃ  aH     ƃ    H     H  Agi     H@  fDnHPDaHBH   rƃ  rH=   <H  ƃ       H  H@     1    Ƈ    H       H@      resHQH   tƃ  tH   
  H  ƃ       H  ri     H@  fcHB Ƈ    H       H@      volHQH   aƃ  aH     H  ƃ       H  t   H@  P     Ƈ    H       H@      _CoHQH   mƃ  mH   =  H  ƃ       H  p   H@  "H  Ƈ         H@      conHBH   sƃ  sH=   rH  ƃ       H  H@     1Ff &  Ƈ       H    f+   H@  HD  H  Ƈ          ƃ   HUH@  Hǃ      f     Ƈ    H           H@  fƇ    H       H@      thrHQH   oƃ  oH   M  H  ƃ       H  w   ƃ  wHUH@  Hǃ      HDBH  Ƈ         H@      noeHBH   xƃ  xH=     H  ƃ       H  ce  Cp   H@  f     H  Ƈ         H@      __vHBH   eƃ  eH=   ]  ƃ    H     H  c   H@  H  Ƈ         H@     _vecHBH   tƃ  tH=     ƃ    H     H  H@  or  f   HP     H  ƃ       H  H@     1H  Ƈ         H@     throHBH   wƃ  wHUH@ H  ƃ       H  H@     1H  ƃ       H  :   H@      H  Ƈ         H@     omplHBH   eƃ  eH=   H  ƃ       H  H@     1UfH  Ƈ         H@     latiHBH   lƃ  lH=   H  ƃ       H  H@     1{fƇ    H       H@     CompHPH   lƃ  lH   ƃ    H     H  e   H@  OH  Ƈ         H@     _ComHBH   pƃ  pH=   ^ƃ    H     H  Ale     H@  fDf.     H  Ƈ         H@     magiHBH   nƃ  nH=   `Hƃ       H    ar     H@  f;y@ Aro  H     Ƈ      fD+   H@   H  Ƈ         hr  Co   H@  fef     Ƈ    H       H@     olatHPH   iƃ  iH   Mƃ    H     H  l   H@  H  Ƈ         H@     volaHBH   tƃ  tH=   ^ƃ    H     H  il  H@  f   a@ H  Ƈ         n   H@  sHBfƇ    H       H@     ImagHPH   iƃ  iH   ƃ    H     H  Ana  Cr   H@  fD2H  Ƈ         H@     _ImaHBH   gƃ  gH=   Sƃ    H     H  i   H@  HfD  Ƈ    H       H@     vectHPH   oƃ  oH   ƃ    H     H  r   H@  Ƈ    H       H@     exceHPH   pƃ  pH   OH  ƃ       H  t   ƃ  tHUH@  Hǃ      H42Ƈ    H       H@     __veHPH   cƃ  cH   H  ƃ       H  to  Cr   H@  f     H  Ƈ         H@     striHBH   cƃ  cH=   D  Ƈ    H       H@     estrHPH   iƃ  iH   uƃ    H     H  c   H@  |H  Ƈ         H@     restHBH   rƃ  rH=   bH  ƃ       H  i   H@  %D  H  Ƈ         on     H@  fƇ    H       H@     cons@ H  Ƈ         H@     oexcHBH   eƃ  eH=   H  ƃ       H  p   H@  HBH   tƃ  tHUHA?Ƈ    H       H@     noexHPH   cƃ  cH   ;H  ƃ       H  ep     H@  fSH  Ƈ         H@     1H  Ƈ         H@     18ff.     @ AUHIATAUHSHHHu}  D  H H   HuH@8*h  H1DH  H   H      HBH   [ƃ  [IUH   DHH   H=      HPH   ]ƃ  ]H[]A\A]f1HDH`  H   H=   O  HPH    ƃ   H   VH  ƃ       H  [ƃ  [IUH@  Hǃ      H3   Gf.     H=   1H  ƃ       H  H@     1@ H   H     HBH    ƃ   H=   *  HPH   1HD(Hƃ  (4  H   H      HBH   )ƃ  )H=   H  ƃ       H   [  ƃ  [fIU   H@  Hǃ      Hf     H   H  ƃ       H  )   H@  f   ƃ    H     H      H@  H  ƃ       H  H@     1H  AWAVI     4 AUAATUHSHH8  0  tiH8[]A\A]A^A_D  Ir=HKC   L   H   )X  *s  DHDL   HHt0  uCuHSH5vHKC   L   H   uL(  HRDHHǅ(      7L(  A  H   H     HBH   D :ƅ  :H=     HPH   D ::      D  CuDHSHKL   C   H   )tE*td?DH,L   HH0  tH8[]A\A]A^A_HDH2
  L   H8[]A\A]A^A_HDHL   H8[]A\A]A^A_H   H=   tnHPH   D ..     HCHXH   H     4 5w
H   HDHL   H8[]A\A]A^A_H  ƅ       H  H@     1fƅ    H     H  E :   H@  JH[]H   H=     HPH   D {ƅ  {H     HPH   Ddƅ  dH     HPH   Deƅ  eH     ƅ    H     H  Afa  Eu   H@  fD] HPH   D lƅ  lH     Hƅ       H    t   Ea   H@  f} HPH   D rƅ  rH     ƅ    H     H  E g   H@  HPH   LD$H5`, D #Lƅ  #CL$P1UkH<$kHH   H  L$I4MH4$R  HtbHt.E8H=     HHH   MpD| D  E>H=     HHH   ID| D  E>H=   %  HHH   ID| D  L94$      @ HHH   MFD| D  E~H=     HHH   D| D  ExH=     HHH   D| D  ExH=   ;  HHH   MpD| D  L94$t@E>H=   GH  ƅ       H  H@     1H=     HPH   D }ƅ  }H   r  HPH   D:ƅ  :H     HBH   D :ƅ  :H[~H  ƅ       H  H@     1=H  ƅ       H  {d  Ee   H@  fE HBH   D fƅ  fH=     H  ƅ       H  Aau  El   H@  fDU HBH   D tƅ  tH=     H     ƅ    H   a  Er   H@  fu HBH   D gƅ  gH=   OH  ƅ       H  H@     1#ƅ    H     H  Ade  Ef   H@  fD} HPH   D aƅ  aH   	  ƅ    H     H  Aul  Et   H@  fDM HPH   D  ƅ   H     ƅ    H     H  ar  Eg   H@  fM ,LD$H     Hƅ      H@  LD$1Ҹ   H  ƅ       H  Aef  Ea   H@  fDu HBH   D uƅ  uH=   H  ƅ       H  Alt  E    H@  fDE HBH   D aƅ  aH=   H  ƅ       H  rg     H@  fU LD$H     Hƅ      H@  LD$1Ҹ   @LD$H     Hƅ      H@  LD$1Ҹ   H  ƅ       H  H@     1H  ƅ       H  E :   H@  H  ƅ       H  }:     H@  fE IH  ƅ       H  H@     1LD$H     Hƅ      H@  LD$1Ҹ   H  ƅ       H  H@     1f.     AVHAUIATAH   b  UHSH   HI  Pu5HP
+w"HHH   H       H  H HuL(  H1DHǃ(      HcH   H   .  HBH   (ƃ  (IUH\  DHQH   H=   J  HPH   )ƃ  )HDH߹   L(  []A\A]A^D     H   t%H=     HPH    Hƃ   H=   .  HPH   (L(  1HDƃ  (HHǃ(      WH   H=   $  HPH   )ƃ  )H   H  ƃ       H  (ƃ  (IUH@  Hǃ      H   H=   ƃ    H     H  H@  Hǃ      )D    Ѓ<(   H   H=   ƃ    H     H  H@  Hǃ      (f.     H  ƃ       H  )(  ƃ  (fIU   H@  Hǃ      HH     fD  ƃ    H     H      H@      L(  11DHǃ(      HWH   ff.     AWAVAUATUSHH   HtGD0  EuED*HA\w/Hx4 DAHcHH$   H(  f.     ǃ0     HĨ   []A\A]A^A_H   H=   D_  HPH   VƇ  VH   w  HPH   DTƇ  TH   [|  HHH   DTƇ  TH   
_  H  ƃ       H  A f  Co   H@  fD+HBH   rƃ  rH=     H  ƃ       H  H@     1H    ƃ   HUDHĨ   H[]A\A]A^A_H(  HD$ Ht$ HH(  1D$0H   Hl$(HD$8HWHDH|t$0B  HD$ H(  EUL   I    H(  HH  HH HkDHEuHPJPA9u    HD$ fHnHU~(  H(  H   flD$0    HD$8)D$ D\$0Ej  HD$ H(  f.     HU:'N  HBDpARE  E?  H   H=   }  HHH   DH(ƃ  (4H   H=   }  HPH   )ƃ  )} >}  A|      HU    HUH!N  } TN  H} tA.   H   H=   L  HPH   D,D  @ H}D8  EuE1~  H(  A9t#t$<  HHD$ fHnfHnD$0    H(  H   fl)D$ HD$8D  HUHtH} H   H   o  H5| HHUDHL@  L   L9@  H   L9HH   f.     HUwAMJ  H5 H>LuA>Hs  LlH   H=   W  HPH   {Ƈ  {H   `  HPH   DlƇ  lH   b  HHH   DaƇ  aH   xW  H  Ƈ         Amb  Cd   H@  fDHBH   aH   ƃ  aLmHT$HT$D8  H      ǃ8      HD$    MtA} W  8  H=   v  HPH   DLH(ƃ  (HD$H   D8  H   H   t  HBH   )ƃ  )H=   Dt  HPH   Ll$ H5J #L1ƃ  #UDYLYH   H9  MMt X  HtdHt/Am H     HHH   Me@,@  A,$H   Ӄ  HHH   I@,@  A,$H     HHIH   @,@  M9   9  @ HHH   Ml$@,@  Al$H   a  HHH   @,@  AmH   ?c  HHH   @,@  AmH   b  HHMeH   @,@  M9^8  A,$H   AH  ƃ       H  H@     1L= H   IO&  HHH   MwD,D  EoH=   k  HHH   D,D  EnH=   .l  HHH   D,D  EnH=   k  HHH   D,D  EnH=   l  HHH   D,D  EnH=   l  HHH   D,D  EnH=   k  HHM~H   D,D  I9E/H=   H  ƃ       H  H@  1Ҹ   H
R LcmHmM&H   I&HHBHH   D$D  L9De H=   uHƃ       HH    H@  Hǃ      D#D  L9De    {L- H   M}*@ HHBIH   D4D  M9zEu H=   uIƃ       HH    H@  Hǃ      D3D  M9'Eu    {HUHmHtH   H=   r  HPH   DHH{ƃ  {H   H=   +r  HPH   }ƃ  }{H   H=   T  HPH   jƇ  jH   U  HPH   DaƇ  aH   V  HHH   DvƇ  vH   T  H  Ƈ       Aa     fD+   H@  CrHBH   eƃ  eH=   T  H  ƃ       H  Aso  Cu   H@  fDHBH   rƃ  rH=   T  H  ƃ       H  ce     H@  f HP%H   L= E/MwH=   Yo  HHH   ID,D  &  HHH   IOD,D  EoH=   d  HHH   D,D  DiH=   ud  HHH   D,D  DiH=   f  HHH   D,D  DiH=   e  HHH   D,D  DiH=   We  HHH   D,D  DiH=   d  HHLyH   D,D  M9E/H=   H  ƃ       H  H@     1H   H=   N  HPH   dƇ  dH   FU  HPH   DeƇ  eH   &X  HHH   DcƇ  cH   N  H  Ƈ         lt  Cy   H@  fHBH   pƃ  pH=   N  ƃ    H     H  Ae      H@  fD+HPH   (ƃ  (HUDHCH   H=   A  HPH   )ƃ  )Ld$ U1H5 LOLDPHH   LM,) HHPHH   D$D  L9De H   uHƃ       HH    H@  Hǃ      D#D  L9XDe    zL- H   M}) HHBIH   D4D  M92Eu H=   uIƃ       HH    H@  Hǃ      D3D  M9Eu    {ALcmHm);  MH   INt- AT  ItaIt.De H=   Ԁ  HHH   L}D$D  E'H=   5  HHH   ID$D  E'H=   I{  HHIH   D$D  M9   f.     HHH   IoD$D  EgH=   [l  HHH   D$D  DeH=   k  HHH   D$D  DeH=   wk  HHL}H   D$D  M9"E'H=   HH  ƃ       H  H@     1H   H=   g  HPH   [ƃ  [=D  HBH   ,ƃ  ,H=   ^-  HPH    ƃ   HUDHqHmH  H   H   uƃ    H     H  ,   H@  H   L=
 E/MwH=   g  HHIH   D,D  E/H=   -g  HHH   ID,D  &  HHH   IOD,D  EoH=   _  HHH   D,D  DiH=   ]  HHH   D,D  DiH=   \  HHH   D,D  DiH=   U\  HHH   D,D  DiH=   [  HHH   D,D  DiH=   [  HHLyH   D,D  M9E/H=   H  ƃ       H  H@     1HUHĨ   DH[]A\A]A^A_Ϟ  H
 H   Lq   HHH   LyD,D  DiH=   
Y  HHH   D,D  EoH=   SX  HHH   D,D  EoH=   W  HHH   D,D  EoH=   _X  HHH   D,D  EoH=   X  HHIOH   D,D  L9,  D)H=   HL$H     Hƃ      H@  HL$1Ҹ   L-( H   M},fD  HHBIH   D4D  M9p+  Eu H=   uIƃ       HH    H@  Hǃ      D3D  M9+  Eu    {L-l
 H   M}*@ HHBIH   D4D  M9Eu H=   uIƃ       HH    H@  Hǃ      D3D  M9Eu    {L-	 H   M}*@ HHBIH   D4D  M9rEu H=   uIƃ       HH    H@  Hǃ      D3D  M9Eu    {L-	 H   M}*@ HHBIH   D4D  M9Eu H=   uIƃ       HH    H@  Hǃ      D3D  M9Eu    {H5Q $j_L-% H   M}) HHBIH   D4D  M9"Eu H=   uIƃ       HH    H@  Hǃ      D3D  M9Eu    {L-t H   M}*@ HHBIH   D4D  M9Eu H=   uIƃ       HH    H@  Hǃ      D3D  M9/Eu    {mH   H=   +  HPH   @,@  HUƲH   H=   'C  HPH    ƃ   H   (  HPH   D[ƃ  [H   eJ  HHH   Dcƃ  cH   B  H  ƃ       H  Alo  Cn   H@  fDHBH   eƃ  eH=   (  H  ƃ       H  H@     1H    ƃ   HUDH裱H   H=   *  HPH   ]ƃ  ]oH   H=   Z  HPH   E1<ƃ  <HmHu'%   HDHA&HmH%  EtH   H   y*  HBH   ,ƃ  ,H=   '*  HPH    ƃ   HE89HUHBH xcd  HDH{  HDH0  rHE82p  H@L5 LH8DHUHRu	:t  DHy  LmH5 IEL8L[D6q  LLHDOu  HEDHHPmy  HE82H@xH@)   8>HĨ   H[]A\A]A^A_7aLp  L}Hp  L(  HǇ(      @tAuAi  LDH]  <]  H   H=   _]  HPH   DH<ƃ  <HU  >]  H   H=   \  HPH   >ƃ  >L(  Lp  H   H=   ;  HPH   vƇ  vH   <  HPH   DtƇ  tH   }?  HPH   DaƇ  aH   S;  Ƈ    H     Abl    fD+   H@  CeHPH    ƃ   H   !  ƃ    H     H  Afo  Cr   H@  fDL-} H   M}0f.     HHBIH   D4D  M9Eu H=   uIƃ       HH    H@  Hǃ      D3D  M9GEu    {L-  H   M}*@ HHBIH   D4D  M9Eu H=   uIƃ       HH    H@  Hǃ      D3D  M9Eu    {H   H=   2  HPH   tƇ  tH   D  HPH   DyƇ  yH     HPH   DpƇ  pH   2  Ƈ    H       Cnei  H@  f   HPH   fƃ  fH   2  ƃ    H     H  Ao   Cf   H@  fD3HPH   oƃ  oH   ƃ    H     H  r   H@  HUH   H=   ZS  HPH   (ƃ  (HUfHnLt$ L(  H   L(  LA   fInHD$8LflD$0    )D$ MuZ9$      Pu?AgoDAH)L oPHL IH(  )T0@   H HtHPvHUDHL(  D|$0EA#  AEIHIIVDHI }A#  AHUĩHU趩H   H=   Q  HPH   @ƃ  @HUHU{H   H=   X  HPH   .ƃ  .H   mX  HPH   D.ƃ  .H   X  HBH   .ƃ  . H   H=   ,  HPH   oƇ  oH   n-  HPH   DpƇ  pH   .  HPH   DeƇ  eH   },  Ƈ    H       Ctra  H@  f   HPH   oƃ  oH   ,  ƃ    H     H  r   H@  HPH    ƃ   HUH   H=   -  HPH   oƇ  oH   .  HPH   DpƇ  pH   3  HPH   DeƇ  eH   ,  Ƈ    H       Ara  Ct   H@  fDHPH   oƃ  oH   ,  ƃ    H     H  r   H@  HPH    Hp  ƃ   Ht"~   fHnHD$ H   fl)D$ HU:#E  DH苦Hp   wHD$ H   fH
 H   Lq   HHH   LyD,D  DiH=   zG  HHH   D,D  EoH=   G  HHH   D,D  EoH=   VG  HHH   D,D  EoH=   G  HHH   D,D  EoH=   bG  HHIOH   D,D  L9yD)H=   HL$H     Hƃ      H@  HL$1Ҹ   H   L=  E/H=   !N  HHIH   D,D  E/H=   M  HHH   ID,D    HHH   MwD,D  EoH=   C  HHH   D,D  EnH=   }D  HHH   D,D  EnH=   #D  HHH   D,D  EnH=   C  HHH   D,D  EnH=   oC  HHM~H
Y  H   D,D  I9E/H=   H  ƃ       H  H@     1L-  H   M}) HHBIH   D4D  M9BEu H=   uIƃ       HH    H@  Hǃ      D3D  M9Eu    {HU跢H   H=   0  HPH   [ƃ  [H   EK  HPH   Daƃ  aH   J  HPH   Dbƃ  bH   /  ƃ    H     H  i   H@  HPH   :ƃ  :@D8  HmE  HE1WHu"  f     Hx tH@AHt8/tEE~AA  D<  HDHA   uH   H   a  HBH   ,ƃ  ,H=   a  HPH    ƃ   A   AteD<  HDHA H   H   j  HBH   ,ƃ  ,H=   i  HPH    ƃ   D<  HDHA蛠H   H     HBH   ,ƃ  ,H=   Vg  HPH    ƃ   D<  HDHE}6E9'H   H   xf  HBH   ,ƃ  ,H=   &f  HPH   DHH Eoƃ   D<  ȟH   H   tf  HBH   ,ƃ  ,H=   "f  HPH   DHH D<  Eoƃ   cH   H   g  HBH   ,ƃ  ,H=   g  HPH   DHH D<  Eoƃ   H   H   cƃ    H     H  ,   H@  Tf     H   H=   \0  HPH   tƇ  tH     HPH   DeƇ  eH   8  HHH   DmƇ  mH   #0  H  Ƈ       Apl    fD+   H@  CaHBH   tƃ  tH=     H  ƃ       H  H@     1H   DHeƃ  eHU萝H   H=   X%  HPH    ƃ   H   )  HPH   Dcƃ  cH   %M  HHH   Dlƃ  lH   $%     ƃ    H  H  as     H@  f3HPH   sƃ  sHEL(  HǇ(      HH   HD$     HD$(QD$0    Ht$85D  H     4 HX  Lt$ A   LH(  	H  uHT$fHnfHnH   fl)D$HUDHHD$HD$8uHD$H   EuLLHT0S  tJAmHIHD0BV  Et+AmHIHD0eV  EtD$0_Z  L(  {AH(  A@ g:  HUHt
A@?L  H(  HDHHĨ   []A\A]A^A_AHE  HcPL0HH   MM,U  HtaHt-A.H=   `  HHH   Mf@,@  A,$H=   ]  HHH   I@,@  A,$H=   %Y  HHIH   @,@  M9   R     HHH   Mt$@,@  Al$H=   J  HHH   @,@  AnH=   .L  HHH   @,@  AnH=   K  HHMfH   @,@  M9A,$H=   EH  ƃ       H  H@     1HEHcPL0H5
  H   MM<R  HtaHt-E&H=   Q\  HHH   MnD$D  Ee H=   U  HHH   ID$D  Ee H=   R  HHIH   D$D  M9   {      HHH   MuD$D  EeH=   -4  HHH   D$D  EfH=   c4  HHH   D$D  EfH=   	4  HHMnH   D$D  M9  Ee H=   GH  ƃ       H  H@     1H   H=     HPH   {Ƈ  {H   !  HPH   DuƇ  uH   "  HHH   DnƇ  nH     H  Ƈ         na  Cm   H@  fHBH   eƃ  eH=     H  ƃ       H  d   Ct   H@  fHBH   yƃ  yH=     ƃ    H     H  Ape     H@  fD#HPH   Ll$ H5  #L1ƃ  #HU'L`(H   H[  MMt \  HtdHt/Am H   xY  HHH   Me@,@  A,$H   R  HHH   I@,@  A,$H   N  HHIH   @,@  M9          HHH   Ml$@,@  Al$H   J0  HHH   @,@  AmH   /2  HHH   @,@  AmH   1  HHMeH   @,@  M9  A,$H   AH  ƃ       H  H@     1LmHmAE 21  4{3  Lz  HĨ   HDH[]A\A]A^A_]  H   H=    #  HPH   tƇ  tH     HPH   DyƇ  yH   *  HHH   DpƇ  pH   "  H  Ƈ         en  Ca   H@  fHBH   mƃ  mH=     H  ƃ       H  H@     1H   eƃ  eHE8;H@8<H^  HDHpd  HELuH5U  LhH@LxHhIFH8&'W  LDH[  LDH	y  DHL[  H5  H,H    H   H=   ?  HPH   ~ƃ  ~HU2HUHc8  HJH9&  H   H@H@y4  Hу   tytdtOt:t%tH@HH@H{H@HkH@H[H@HKH@H;H@H+3  H@HH@H	H@HH@HH@HH@HH@HH@Hu    HmH  H5v  HĨ   H[]A\A]A^A_sFLeH   Al$H=   %  HPH   oƇ  oH   9  HPH   DpƇ  pH   *  HHH   DeƇ  eH   %  H  Ƈ         ra  Ct   H@  f;HBH   oƃ  oH=   $  H  ƃ       H  H@     1H   rƃ  rMl$AE a<.  HcHBA| HDHFH   MMt N  HtbHt.Am H=   Q  HHH   Me@,@  A,$H=   K  HHH   I@,@  A,$H=   H  HHIH   @,@  M9   HHH   Ml$@,@  Al$H=   )  HHH   @,@  AmH=   *  HHH   @,@  AmH=   g*  HHMeH   @,@  M9A,$H=   EH  ƃ       H  H@     1H   +  HBH   }ƃ  }wHD$ HWHL$ H(  H   Hl$(D$0    HD$8HHfD  ƃ    H     H  H@  Hǃ       zH  Ƈ         pe  Ci   H@  fHBH   nƃ  nH=   H  ƃ       H  Afo  C    H@  fD;HBH   fƃ  fH=   ƃ    H     H  Aor     H@  fDLd$ U1H5  LLJH   H   M4&@ HHPIH   D,D  M9t\E,$H   uIƃ       HH    H@  Hǃ      D+D  M9tE,$   m@OSH   HPH=   "3  H   >ƃ  >HUDHH   H=   HPH    ƃ   H   HPH   Dfƃ  fH   eHPH   Doƃ  oH   JQHUDH聊H   H=   7  HPH   -ƃ  -H     HPH   Diƃ  iH   1  HPH   Dnƃ  nH     H  ƃ       H  H@     1H   -ƃ  -ѾHDHS>H  ƃ       H  A[c  Cl   H@  fDHBH   oƃ  oH=   !     ƃ    H  H  ne     H@  f3HPWH  Ƈ         Ape  Cr   H@  fDHBH   aƃ  aH=   #  ƃ    H     H  to     H@  fHPH  Ƈ       Aem    fD;   H@  CpHBH   lƃ  lH=   "  ƃ    H     H  Aat     H@  fDHPHH  Ƈ         Ceyp  H@  f   HBH   nƃ  nH=     ƃ    H     H  H@  am  f   HP\H  ƃ       H  in     H@  fHBYH  ƃ       H  H@     1DHHsP  H5  ;H  ƃ       H  H@     1+H  ƃ       H  H@     1ƃ    H     H  ,   H@  xHUM1҃|$0 H(  3H(  HDH贤AHExA=H@ <0+O  <1tH5  $(  H   H=   B  HPH   aƇ  aH   fE  HPH   DuƇ  uH   E  HPH   DtƇ  tH   nB  Ƈ    H       o   H@  HPH   Lt$ H5  :L1ƃ  :HUL6HHԶH   MM,  HtaHt-A.H=   K  HHH   Mf@,@  A,$H=   hI  HHH   I@,@  A,$H=   E  HHIH   @,@  M9   HHH   @,@  AnH=   _?  HHH   @,@  AnH=   ?  HHMfH   @,@  M9A,$H=   >  HHH   Mt$@,@  Al$H=   EH  ƃ       H  H@     1HcPLpHH   MM,W  HtaHt-A.H=   H  HHH   Mf@,@  A,$H=   fE  HHH   I@,@  A,$H=   	B  HHIH   @,@  M9   df.     HHH   Mt$@,@  Al$H=   j5  HHH   @,@  AnH=   5  HHH   @,@  AnH=   D4  HHMfH   @,@  M9A,$H=   EH  ƃ       H  H@     1IL9rCb     H   H=     HPH   D$D  HL9$LDe H)H~A_u}_u}UuLuM9sL1L)p  HtuHt5APЀ	;J  P$J  PD  WHcIAPЀ	uH  PI  PoD  WHHIHAPЀ	H  PhH  P5D  WHHIHM9   HIvHHIPЀ	=  HHLvHFPЀ	i=  P@  PC  WHHLvHFPЀ	&=  P;B  PC  WHHLvHM9APЀ	CP8C  7H/D  H  ƃ       H  H@     1H   H=   g9  HPH   .ƃ  .锵H5  Lt$ 4L1H5~  LH  H   MM,O  HtcHt.A.H   .D  HHH   Mf@,@  A,$H   M?  HHH   I@,@  A,$H   g<  HHIH   @,@  M9      HHH   Mt$@,@  Al$H   M/  HHH   @,@  AnH   .  HHH   @,@  AnH   0  HHMfH   @,@  M9tBA,$H   EH  ƃ       H  H@     1}   KH@HUE  8Lt$ HD$HLt$@WD$P    Ht$X58  H8!  A   HT$@eE1JATA:   H  ƃ       H  H@     1AH  ƃ       H  H@     1H  Ƈ         Ceop  H@  f   HBH   rƃ  rH=      H  ƃ       H  at  Co   H@  fHBH   rƃ  rH=   H  ƃ       H  H@     1_Ƈ    H       Crpe  H@  f   HPH   aƃ  aH   K  ƃ    H     H  to  Crf   H@  H  Ƈ       Aop    fD3   H@  CeHBH   rƃ  rH=     H  ƃ       H  Aat  Co   H@  fDHBH   rƃ  rH=   =H  ƃ       H  H@     1H  Ƈ         er  Ca   H@  fHBH   tƃ  tH=   JAor  ƃ       HH    fD;   H@  aH  Ƈ         Cpty  H@  f   HBH   eƃ  eH=     H  ƃ       H  in  Cf   H@  fHBH   oƃ  oH=   GƇ    H     Ape    fD+   H@  CrHPH   aƃ  aH     ƃ    H     H  Ato  Cr   H@  fD>ƃ    H     H  A c  Cl   H@  fDHQH   aƃ  aH     ƃ    H     H  s   H@     Ƈ    H    {u  Cn   H@  f3HQH   nƃ  nH     ƃ    H     H  Ceam  H@  f   HPH   dƃ  dH     ƃ    H     H  A t  Cy   H@  fD;HPH   pƃ  pH     ƃ    H     H  e   H@  H  Ƈ         un  Cn   H@  fHBH   aƃ  aH=     H  ƃ       H  me  Cd   H@  fHBH    ƃ   H=     H  ƃ       H  Aty  Cp   H@  fD3HBH   eƃ  eH=   H  ƃ       H  H@     1H  Ƈ         nn  Ca   H@  fHPH   mƃ  mH   ƃ    H     H  C ed  H@  f   HPH   tƃ  tH   Ayp  ƃ       HH    fD+   H@  CeH  ƃ       H  Acl  Ca   H@  fDHBH   sƃ  sH=   H  ƃ       H  H@     1H  Ƈ         Aer  Ca   H@  fDHBH   tƃ  tH=   0Hƃ       H    or     H@  f;IH  Ƈ         vt  Ca   H@  fHBH   bƃ  bH=      H  ƃ       H  Ale  C    H@  fD*H  ƃ       H  [a  Cb   H@  fHBH   iƃ  iH=   <H  ƃ       H  H@     1Ƈ    H     Ata    fD;   H@  CbHPH   lƃ  lH     ƃ    H     H  Ae   Cf   H@  fDƇ    H       A{l  Ca   H@  fDHQH   mƃ  mH     H  H߾   ƃ      bd     H@  f;cƇ    H       Cpty  H@  f   HQH   eƃ  eH   ƃ    H     H  na  Cmf   H@  Ƈ    H       de  Cc   H@  fHQH   lƃ  lH   V  ƃ    H     H  Cpty  H@  f   HPH   eƃ  eH   W  ƃ    H     H      H@  $ƃ    H     H  A [  Cc   H@  fDHQH   lƃ  lH   Hƃ       H    on  Ce   H@  f;H  Ƈ       Aab    fD3   H@  ClHBH   eƃ  eH=   ,Ƈ    H       AVT  CT   H@  fDHQH    ƃ   H   LƇ    H       te  Cm   H@  fHQH   pƃ  pH   ƃ    H     H  Ala  Ct   H@  fDƇ    H       ja  Cv   H@  fHQH   aƃ  aH     ƃ    H     H  A r  Ce   H@  fDHPH   sƃ  sH     Hƃ       H    ou  Cr   H@  f;HPH   cƃ  cH     ƃ    H     H  e   H@  XH  Ƈ       Aav    fD;   H@  CaHBH    ƃ   H=      H  ƃ       H  Are  Cs   H@  fDHBH   oƃ  oH=      H     ƃ    H  ur  Cc   H@  f3HBH   eƃ  eH=   UMƇ    H     Ava    fD3   H@  C HPH   rƃ  rH   Gƃ    H     H  Aes  Co   H@  fDHPH   uƃ  uH   Fƃ    H     H  rc  Ce   H@  fbƇ    H       Aop  Ce   H@  fDHQH   rƃ  rH   D   ƃ    H  H  at  Co   H@  f3]H  Ƈ         ec  Cl   H@  fHBH   tƃ  tH=     H  ƃ       H  Ayp  Ce   H@  fD;HBH    ƃ   H=   ܪH  ƃ       H  H@     1鰪Ƈ    H       Cnpe  H@  f   HPH   aƃ  aH   cƃ    H     H  m   H@  H  Ƈ         Ala  Cm   H@  fDHBH   bƃ  bH=     H  ƃ       H  d   H@  qƃ    H     H  Acl  Co   H@  fDHPH   nƃ  nH   ƃ    H     H  e   H@  XƇ    H       Ceyp  H@  f   HPH   iƃ  iH   Xƃ    H     H  nf  Cof   H@  иƇ    H       Ctcl  H@  f   HPH   yƃ  yH   ۧApe  ƃ       HH    fD3   H@  C Ƈ    H       Aam  Cb   H@  fDHPH   dƃ  dH   oH  ƃ       H  H@     1CƇ    H     Amp    fD3   H@  ClHPH   aƃ  aH   ƃ    H     H  t   H@  KƇ    H       Aer  Ca   H@  fDHPH   tƃ  tH   ƃ    H     H  o   H@  1H  ƃ       H  H@     1H  ƃ       H  H@     1H  ƃ       H  H@     1H  ƃ       H  H@     1H  ƃ       H  H@     1H  ƃ       H  H@     1tH  ƃ       H  H@     1pH  ƃ       H  H@     1H  ƃ       H  H@     1H  ƃ       H  H@     1阜H  ƃ       H  H@     1H  ƃ       H  H@     1IEL0AauAVduAVM u	\"  9%  sucA~Z  EFE  HHRHu Hx tH@AHt8/tHĨ   HD[]A\A]A^A_SLDHuH  AguA~suA~ H۔sA~txA~ m(   HDHH}a)   鳱HRDHdaHp   tHD$ H     <  <   HHEDHHP!a  >  >   HHD׎HUDHܒ    HeMl$eHDH]a
(   >IUDH`)   H"bH  ƃ       H  H@     1H  ƃ       H  H@     1hH  ƃ       H  H@     1H  ƃ       H  H@     1鴻H  ƃ       H  H@     1ZH  ƃ       H  H@     1ާH  ƃ       H  H@     1鄧H  ƃ       H  H@     1ҧH  ƃ       H  H@     1xH  ƃ       H  H@     1ʦH  ƃ       H  H@     1]H  ƃ       H  H@     1選H  ƃ       H  H@     1'H  ƃ       H  H@     1uH  ƃ       H  H@     1HEH8/u<  HHH   DHHU H   Hp]H   ^HK[uH@H7HĨ   H߉[]A\A]A^A_xHL$H     Hƃ      H@  HL$1Ҹ   @HL$H     Hƃ      H@  HL$1Ҹ   ܣHL$H     Hƃ      H@  HL$1Ҹ   xHL$H     Hƃ      H@  HL$1Ҹ   HL$H     Hƃ      H@  HL$1Ҹ   鰢HL$H     Hƃ      H@  HL$1Ҹ   XHL$H     Hƃ      H@  HL$1Ҹ   H@HN$  8HT$@HD$hHT$`HT$`D$p    Ht$x5HH@H$  HT$`E1H$   H$   D$   H$   5   H     4 HʌA   H$   鋾HL$H     Hƃ      H@  HL$1Ҹ   ښHL$H     Hƃ      H@  HL$1Ҹ   vHL$H     Hƃ      H@  HL$1Ҹ   HL$H     Hƃ      H@  HL$1Ҹ   鮙3 HH    H@  Hǃ       HL$H     Hƃ      H@  HL$1Ҹ   H  ƃ       H  H@  1Ҹ   H
p  H  ƃ       H  H@  1Ҹ   H
9  H  ƃ       H  H@  1Ҹ   H
  颓H  ƃ       H  H@  1Ҹ   H
˭  H  ƃ       H  H@  1Ҹ   H
  鲓H  ƃ       H  H@  1Ҹ   H
]  QH  ƃ       H  n   H@  H  ƃ       H  H@     1H  ƃ       H  H@     1Lt$ A   LOH  ƃ       H  H@     1zAbi  ƃ       HH    fD3   H@  /Aab  ƃ       HH    fD;   H@  CiH  ƃ       H  H@     1H  Ƈ         H@     1鹱H  Ƈ         ATT  C    H@  fDH  Ƈ         H@     1ߤH5  HLl$ 	AFH5ɨ  LP1LYHH  IL H   MHL$N  HtaHt.Am H=     HHH   M}@,@  A/H=     HHH   I@,@  A/H=     HHH   I@,@  L9|$      @ HHH   Mo@,@  AoH=     HHH   @,@  AmH=     HHH   @,@  AmH=   b  HHH   M}@,@  L9|$t@A/H=   JH  ƃ       H  H@     1!H5§  H#
MvH@8H  Q5wI     4 IrɷAAUDfHnE1HHfo| ILL< M>)|< fo|0L(  A)yfHnflHD(D8H@D\0AUH5wMILـ  AՋ/H  ƃ       H  H@     1鐋ƃ    H     H  )   H@  [H  Ƈ         H@     1H     ƃ    H  -i  Cn   H@  f3pH  ƃ       H  H@     1骘H  Ƈ         H@     1PH  Ƈ         H@     1H  ƃ       H  H@     1    HsӢH  ƃ       H  H@     1u    H1LH  Ƈ         H@     1遐H  ƃ       H  H@     1 Ƈ    H       T   Cf   H@  f;隥H  ƃ       H  H@     1黧H  ƃ       H  .   H@  醧H  ƃ       H  ..     H@  fPH  ƃ       H  H@     1驍H  ƃ       H  H@     1BHƃ       H    la  Cs   H@  f;H  ƃ       H  H@     1`H  ƃ       H  H@     1H  ƃ       H  H@     1.H  ƃ       H  H@     1|HD$ fHnfHnDH(  H   flD$0    HD$8)D$ NHD$ L$0H(      HG \H  ƃ       H  H@     1H  ƃ       H  H@     1H  ƃ       H  H@  HU1   ͂[   HHUDHN]   8H  ƃ       H  H@     1H  ƃ       H  H@     1驳H  ƃ       H  H@     1H  ƃ       H  H@     1-   H%H  ƃ       H  H@     1فH  ƃ       H  H@     1H  ƃ       H  H@     1m Hvc<ܛDH3  <   HHEDHHPULH5  H&HEDHHP3L)   iHE0A>  HDHAKA}H  JcHH5  -H5  !l   u   H5m  D  X     HP  HcHHHHH   HtlHtYHtFHt3Ht Ht
H;:  HH;:  HH;:  HH;:  HH;:  HH;:  HH;:  HH9tuH;:  HBHH;8  HH;:  HP H;x   HP0H;x0  HP@H;x@w  HPPH;xPi  HP`H;x`[  HPpH9u;\  ^|HcH   HHP  X  HHyH  Lch  l  LƉT$I)AA   T$9{H`  LPh  LILRHH HH:  AthAt1H`  LPh  LILRHH HH   H`  LPh  LILRHH HH   T$9Q{H`  LPD~MXDh  LLRHH HH   H`  LPMCh  LLRHH HHt`H`  LPAwh  LMC LRHH HHt2H`  LPAwh  LMC0LRHH HH4E1LHH HHtzEσ/~<  {HH   }H  ƃ       H  H@     1}HH  HHu$$  @ H9t	H9gH@H  HH9uMH   HPH=     H   IDH JT4(ƃ   KH˫<   HLl$$M}Muh   fD  LDHrGH   H   tfHJH    ƃ   A7[uMA78  HߍP|MMtW8  J8  tH5  H|H  ƃ       H  H@     1n>   HO8  MmPH   q~H  ƃ       H  H@     1黭H  ƃ       H  H@     1ڰH  ƃ       H  H@     1>H  ƃ       H  H@     12I   H5Q  Q^HUDHEH5  HĖƃ    H     H  H@  1nH   HPH=   	  H   HDH HT,(ƃ   E|H   HPH=     H   HDH HT,(ƃ   EYH  ƃ       H  H@     19H  ƃ       H  H@     1H  ƃ       H  H@     1xs{A~PpE1A~ ta@ AHmH0} /&HEH8LuHpH71HufD  Hx tH@Ht8/tAHT$@A   vH  ƃ       H  H@     1鹴H  ƃ       H  H@     1ЭH  ƃ       H  H@     1RH  ƃ       H  H@     1|H  Ƈ         fau   H@  CtHBH   oƃ  oH=   H  ƃ       H  H@     1mHHP  PK  WHOH  ƃ       H  H@     1uH  ƃ       H  H@     1H  ƃ       H  H@     1H  ƃ       H  H@     1p    Hn    H/H@H6NsH  ƃ       H  H@     1鲦H   H=     HPH   HT$(DH ƃ   AcHBL   HHH   cHHQ  A   8H  ƃ       H  H@     1鎄H  ƃ       H  H@     1νƇ    H       fto   H@  Ƈ    H       fut   H@  Co׺HU:HM9)HDHPzbHR:>U(   HCHE?H  ƃ       H  H@     1?ƃ    H     H  ,   H@  
H  ƃ       H  H@     1պ7HBH  ƃ       H  H@     1H߾[   `HEDHHP>]   H@龎7H难pfo|< HfHnfInflA)| fAoyE1)|0LH(  HD<(D<8H@DL<0H1p5 IAApfo|$`fHnfHnfol$pflH$   HD$h)$   D$xH@H(  1ɉL$p)$   Ho5wH     4 HoA   VH  ƃ       H  H@     1鿢7H̽H  ƃ       H  H@     1qH  ƃ       H  H@     1H  ƃ       H  H@     1颀H  Ƈ         H@     1鉣H  ƃ       H  H@     1:uHUDH  LH  ƃ       H  H@     1_PwWHM9A>_H   HLw髺H  ƃ       H  H@     1NHB8)t
ǃ0     HRDH  VH  Ƈ         H@     1H5
  H/I} tDHL      HLDH;HmH  ƃ       H  H@     1oH  ƃ       H  H@     1LDHC!  鞊H  ƃ       H  H@     1H$   A   H  ƃ       H  H@     1驻H  Ƈ         H@     1&H  Ƈ         H@     1H  ƃ       H  H@     1鮙ƃ    H     H  ,   H@  yH  ƃ       H  H@     1鲙ƃ    H     H  ,   H@  }H  ƃ       H  H@     1~H  ƃ       H  H@     1 H  ƃ       H  H@     1߳EfjL   ZjH  ƃ       H  H@     1-   HEH顷H  ƃ       H  H@     17H韷H閷H  ƃ       H  H@     1HD$ H(  iH  ƃ       H  H@     1?ƃ    H     H  ,   H@  
HD$@H(  iH(  
iH  ƃ       H  H@     1$ƃ    H     H  ,   H@  H5q  7H$7۵ff.      AUATAUHSHHv
1tu4E4        ǃ0     H[]A\A]D  H   H=     HHH   (ƃ  (E4  E1   ~Dǃ0     H      HAH   )ƃ  )H[]A\A]fD  A   fHnDEHH  H߉4  HHH  )$fHD$HH  m4  EH   H   hƃ    H     H  H@     1<    Ƈ    H       H@     1 HBH@H9ft  AWAVAUATUSHHHBLxLhA?<K  D<  E1Ǉ<  A<lP  <l+  <Lt<R   H   H=   \  HPH   (ƃ  (LHLH  H   H=   I  HPH   .ƃ  .H     HPH   D.ƃ  .H   :  HBH   H.Lƃ  .?  LHH   H=   _  HPH   )ƃ  )D<  H   []A\A]A^A_fD  1D  <ruH   H=   y  HPH   (ƃ  (LHLH  H   H=     HPH   .ƃ  .H   S  HPH   D.ƃ  .H     HPH   D.ƃ  .H   <  H  ƃ       H  H@     1   MwD<  MǇ<  A<lH   H=     HPH   (ƃ  (H   m  HPH   D.ƃ  .H     HPH   D.ƃ  .H   5  HBH   .ƃ  .LH"  Lf.     H  ƃ       H  H@  ..  f   HBH   )ƃ  )@ H  ƃ       H  H@     1uƃ    H     H  H@  Hǃ      (|f     ƃ    H     H  H@  Hǃ      (_f     ƃ    H     H  H@  Hǃ      .f     H  ƃ       H  .   H@  Z    H  ƃ       H  .   H@      H  ƃ       H  ..     H@  ff.     H     ƃ    H  ..     H@  f3f.     H  H߾   ƃ      (.  C.   H@  f;afD  H  ƃ       H  .   H@      H  ƃ       H  ..  C.   H@  fOfD  H  ƃ       H  H@     1     1Ƀ80  AVAUATUSHBH@L(A} dt[]A\A]A^ AuH<Xt@iuHBLpL`H   @i   H=     HPH   [[     LH-AE<X   <it)H   H=     HPH   ]ƃ  ]A$8uID$H@H 8dtxH   H=   E  HPH   =ƃ  =LH   []A\A]A^fD  H=     HPH   ..   ! @߀Xt<irLH, H   H=      HPH    ƃ   H     HPH   D.ƃ  .H   .  HPH   D.ƃ  .H      ƃ    H     H  .   H@  HPH   H ƃ   IT$+A}iMd$d6@ H  ƃ       H   .  C.   H@  fHBH   .ƃ  .H=   kH  ƃ       H  H@     1?f     ƃ    H     H  H@  Hǃ      [Bf     ƃ    H     H  H@  Hǃ      =f     ƃ    H     H  ]ƃ  ]A$H@  Hǃ      8   (D  H  ƃ       H  H@     1@     ƃ    H     H  ..  H@  f   f.     H  ƃ       H  ..  C.   H@  ffD  IHt\L  A@tH1AIHHH4AAPt'0LHcH)HIHH9s1f     tI3HD  IHtxL
  AAtbI׉؉	1%@ AHHcHAqt4I9r/H4@aHHw̃a1HcHH~HWI HÐ1Hf.     UH-     SHDM uCI_tLQuMHHHt$6Ht7HD$LH+H9|'HADE H[]f.     _t
H1[]ÐGT<ff.     @ HH LVL9  1LL
Џ  H)Iw  L9  N(x  F(     H:_l  V(P  HHH)HtLGAILF L`  0HcHHB_  D^(E   HHH)HjIxAIH~ 4  0HcHHBL_   ~(   HHH)HIxAIH~ 	  0HcHHBL_thV(uPHHH)HIxH~ AI  0HcHL9N(HH:_u4HHH~     H1<:_'HH~ 1fD  D^(Eu2HAIH~    0HcIiItXH:_yDF(E[HHH)HHAIH~ 0  0HcHH:_!V(HHHH)HntWHcN   RHc7tWHcH   (HcH|tWHcH   HcHtWHcH   HcHtWHcHL9   HcHL9tWHcH   bHcHH    H1HL  f.     HB H;BrH!HB H;Brx1B(   H H:<_tgH!HB H;Bs<@tHDHB @CHu!a@wWHHHH    0HHHfH: HHB Hff.     a@wHp  @HcH 1D  Hz  H"       H       Hz       Hy       Hڌ       H       H       H       H       H       Hd       H{       HQ       HG       HQ       H	       H5       H       Hw       Hjw       UH1H  S   HH(HH+H{( uHHSHHSH([]     ATUHSHHH( u[HW   H=  SHtkLc@HC(I)I~   AaDd$HuHSH|$   SH[]A\fD  HtLg@I)IvHLH[]A\ H{( uHSHCH   [H=   ]A\ HuHS   H=  SfD  G(t	     AWAVAUATUSHHHG H;GrH[]A\A]A^A_fD  H<GuHHG JIHtH{(   fD  M1L5t  A-  HC@   HA   H{( uHS   LSLI   It!HC@   HICH{( 8  HC@   HI"H{( uHS   LSL   @ H{( uHS   LSHC@   HH{( uHS   LSHC@   HH{( uHS   LSHC@   HH{( uHS   LSIl$HC@   LeHWL9NH{( NHSHCH   [H=D  ]A\A]A^A_    HS   H=  SPHS   LSff.     USHHHt$=HHvDH{( uIH=q  HS   SH{ H)H;H{( u%HSHCHH[]fD  HuC(   H[]D  Ht$HH[]D  UH1H  S   HH(HH+H{( uHHSHHSH([]     AUATUSHHG8t
G8=   w
HS HsH9r!C(   tC8H[]A\A]@ H,@Bts@tfLBLC @yX@g   M   Hǥ u|R uk@pu-H{( uNHS   H=&  SC8y@at=D  C8_HHHS s,u  D  C8>     I9  S(uHC(uыC0tH{( uHS   H=p  S@HH|H{( HuHSHSC8@b   @c9Ht$HHHw}H{(    Ld$I	t[I
tUI
tOID$H\vDLHH{( u2HS   H=  SHC(HuL-  HS   LSC(@ C(   @ Ht$H;HuHD$H   HuH{( uHS   H=o  SC(    L-5  HS   LSLd$HC(I	   I
	  I
$  IT$H\:  Dd$H:HSH|$   SHC(@ H{( HS   H=4o  SC(f.     B< nHH{( HS HS   H=q  Sf.     K(Hk HC uHHk C8D  H{HS   H=!  SH{( NXHOHS   H=  SHC(H*HS   H=փ  SHC(HHS   H=  SAUATUSHH:2tH[]A\A]?    HBLchHhM   H   I)    HHBHH   D$D  I9t^De H=   uHƃ       HH    H@  Hǃ      D#D  L9tDe     H[]A\A]D  ATA1UHSH  HEt6Eu0H     4 B5   H   H[]A\fD  HE t<EtH     4 Hڋ   vO5wHra1HHH   Eu	;   HH[   ]A\yf     uHRHuH[I    HRKHSHt/H     4 5*H HRHSHu1H[]A\    HRHt'w0.wHRHufD     fD  15@f.     8)
H@    f.     UHAWAVAUATSHH  ?_HV     H5؀  H  E1  1AǅD   EAƃADHCH   @ AG  Lk{_Lu
{Z  L0HLHHH1qLIMT LtH8 u	Mg  DF  ǅD    LH詧HHHH  ǅ    ,ǅ(    Hǅ0    Hǅ8    ǅ@    ǅH       v
   HcHIHH   H)HHH)HH A;_H{ZHHCHHC<G  <T     HHI H>.HIFP<_0    <	  FH^f     CHPHЀ	u<_tfD  <.u8C0<	w-CHKHˍPЀ	wfD  CHPЀ	v<.tȉLH)LO   LH;.I9  H"fHIHC
HHC
<Gtw<Tts1HpLHHC$<;THH@C	<Dt<I0{
_&E1<IAA$HLHHHHIHe1[A\A]A^A_]ÀZA   1LHe[A\A]A^A_]HHPfLH`HHHǅP    ƅX Hǅp    Hǅx    HE    HhHE    HE    HE    )EF}  E    HcUE   I勵HHE    HNHEH)ԅNHHULHHH)He2HPLHhHƄ5P `U1H[<	H-D  SfHH HH$    D$    D$t3T$   tHH$H [f     HD$f     H<$wH    1ff.     ATIHUS^4HF LN   L9r5G(   L[]I     I@    A\I@    I@        LE1Au<  tHPH-w  HW Du t0H0uEtIL9sDA<_u=H7 E1L9gLAWfG(   H0L9  H1HHO @I9&HLE  H  IHA   I   ItsIt[ItCIt+ItHH<
_     H<
_   HH<
_   HH<
_   HH<
_   HH<
_   HH<
_   HH   LIB<
_L   HLV<
_LtrHB|
_IItbB|
_IrIItRB|
_IrIItBB|
_IrIIt2B|
_IrIIt"B|
_IrIItIrHpD  H   H)HHH1HHD[I@L]A\IIxIp HA   HF D  A4DBDe tPHH0HHcHW H     11|1D  G(   H11ktff.     @ AWAVAUATUSHXHO(H<$H$   H$   L$   L$   H   4   <   A   M  I9  MI9  MI9  MI9  MI9  MI9  MI9  MI9  MI9  MI9{  M	uH$@(   HX[]A\A]A^A_f     H  E <_  L,$L%c  1D  H  }.  H  HH E <$  <.tH1t\Ht8HtE <$  <.     D5 <$  <.  HD5 <$  <.  HH9tlD5 <$  <.  HVD H<$  <.  HD5 <$  <.  DHr<$w  <.o  HrH9uHH$HHPPfJ    LT$HLD$HD$QHHbHLD$LT$  H1   H   Ht|Ht^Ht@Ht"H  T f  D THT f  D THT f  D THT f  D THT f  D THT f  D THH9   T HHf  D TTHf  TT D TT
f  D HATT
f  D HATT
f  D HATT
f  D HATT
f  D HAf  D THAH97M  E1Ld$AH   1HD$  LMMA   L
p  $      E1L).@ aILMA$   H$M)IL9  LHrNA      L9LFMLDL9sHHET,LGQAuAtIL L9sA   H$@(   HX[]A\A]A^A_HE    fD  H  E<C  HSH{  <S  <B4  }P     A   *     D  Lt5 H)H  IUHAUH+LIM(    HH$   H=_  HPP HuIU   H={Z  AUHHHuD  IU   LHAUHIM(    LSID5 1IAHD$HT$ L9s+HHD$L9HH>wH    HD$Ht$LT$0H|$(H|$(LT$0HH@HD$ LT$8HL$0H4H)H~H    Ht$(诚Ht$(HL$0A  LT$8L
m  w A  b  DD?	кFD?	ЈFD?ȀFI9W  L1Ht$ 1Ht$1HIIJ(H  v+I    HHH$IHHW>  wHHz&1HD$   HHLL9  LHnH$HHHPH@HX[]A\A]A^A_   A   ,   | $t+ D$O HH$HHHPP@ D$OHuIUH|$O   AUIFHH)1U f     G W <R   <L   <G  }Tf   A   >   G   G}$#HH$   }P!   A   @   MH$LH<$HPPH<$E<FtJ<P   A   )   E<Tt:<P   A   (   L   A   &   w   A   <   bIH\I4:HE1HH)   H   HttHt[HtBHt)Ht   ? LEHGtBIHtBIHtBIHtBIHtBIHtBIHH9tBIPHHtBIQtBIQtBIQtBIQtBIQtBIQtBIHAH9pL    <uHtoEpЉ@	vjaWUzЉ@	vKa@W	<   A   j   j0릃0ƋWuiUHSHHWHGHH)H9sCHH9r]Hһ   HE    HH9r@H9rH} H臕HtHE H]H[] H} ֒1fHE EE   H[]f.     ATIHUHSHKCuH{HH;LRHk[]A\f     AWAVAUATUSHH8G8t
G8=   w
HS LCL9r+C(   tC8H8[]A\A]A^A_f.     H3D$Et-HJAD$HK <wH=k  HcHL9V  C8떐L9  D[(Dk,C,   Eu
H9Dk,H{(   H  AMt1H{(   HS   H=i  SDS(Eu
1HH{(    HS   H=V  SC8DK(Eu
HHC(tH   HS   H=iR  SH{( uHS   H=#V  SDC(Eu1L%bS  2HtH{( uHS   LSHH	  {(CHC H;CsH<EuHHC #fD  S(t    HPs,  C8L9t  H|$HH HfoD$0foL$@$L$C0H t1H{( uHS   H=<h  SHHH{( uHS   H=*U  SC8fH=T  HS   SH  AM;fD  C( +HL%Ie  DD$HS Cl|Ds(EuHHS LCDl$1L96  H|$HL|$Lt$ Cl  H{( 9  HS   H=5g  SD$HS(<C@  <S  H  HSH|$   SM	HC(t=HuHS   H=O  SH Hfod$0fol$@$$l$QH H{( uHS   H=P  SHHhH{( HS   H=lf  SC8H{( uHS   H=GS  SHp  o <s'HHHS f     1<suHHHS HhH|$HGH HfoT$0fo\$@$\$fD{0H ElK(Lc HC u
HLc C8 M	H{( uHS   H=N  SH Hfot$0fo|$@4$|$C8H      H<sHHHS Hhf.     M	%EHuHS   H=d  SHuHS   H=d  S     ATUSW8HtYW8   w3HG H;GrYO(ut1HS81tS8[]A\ G(   1u1[]A\ HG H;GrG(t1 HBt$ItWDC(EtS8t1f.     HHHC HC,   S81fg    DK(HHC E   1HH{( tr{(   1L%M  2@ HtH{( uHS   LSHH	  s(uzHC H;CsH<EuHS8HC    UfHS   H=P  Sv     DS(Hk HS EuHGHk S8 H{( tS8    AWAVAUATUSHH((tH([]A\A]A^A_f     HC HKH9   C(   E1HHt0HpH{( uHSHKH(H[H]A\A]A^A_ C8t0PS8     AD$<w]Hc  HcHfAD$<w?Hd  HcH@ HD$EPHAHC IfD  S(Hk u1HfC8C8H([]A\A]A^A_    H{( uHS   H=M  SHKHC H9  ARtH{( uHS   H=da  SHe H{( uHS   H=O  SAPuH{( uHS   H="a  S@ H{( uHS   H=`  SHAAL  H{( 	HS   H=M  SH{( uHS   H=J  SDk(1L%J  EuLHC H;C  HtH{( uHS   LSHHpD[(EtHC(HD  H{( nHS   H=}L  SVHK,CHk HC HHk *HLc@HC HSH9}  H{( uHS   H=_  SDS(1L-I  Eu>HC H;C  HtH{( uHS   LSHHDK(EtH{(   HS   H=K  SHC H;C  H{( uHS   H=X_  SH5Lc@LH{( uHS   H=2_  SHLc@DC(E  HS 1L-_  @ HCH9  HtH{( uHS   LS{(t!Lc@HS H;SrKC(       HHS H;Srv  s(HtHCLc@H9sfD  H<LuHHHS HH[H{( uHS   H=F^  SHH1H<puHHS HS(c  HuHS   H=J  SHH H HfoD$ foL$0$L$H H{( uHS   H=]  SHHS    H;SffD  H{( HS   H=yJ  SHS f     C(   C8IH<EHHHS fD  H<ElHHC fD  H<E0HHC SfD  HC H;CH<uxHHC sH{(    HS   H=\  SDs(EHu|H3U  KjHHHK H9  HHkL4$Ll$MtH|$   C(   H,HS   H=@H  SH<LZHHHC WHAHHH{( KHS   H=nH  SC(HHS   H=E  SH<uHH{( HC uHS   H=A[  SHC HSH9=H3HS H{(    HC(M*1LL9   A<._L}uHu-HSHLSHC(HuHS   H=G  SHC(IMI)   멀|CNHL5{Z  A   HC HC(HuHS   H=mZ  SHC(MUH{( tHSLLSH{( \HS   H=F  S*    HG H;GrHLtKuHHG G(u0 HHHG H|$BH|$HHff.     @ SH1H.  IH+,  IH5B_  1H:H)A  HF   謂ff.     AUATUSHHH?HtcHSHCH)H9rH[]A\A]H)A   HIH,6HLELHtcHJ HHSHCH[]A\A]@     H9HCHHfHnflHtHHCH[]A\A]HLff.      > uf.     ATUHHSH.IHu[]A\ÐHHHEH} HPH9r@ HBD"H} H9sLHpLef.     HBATIUHSHHwqH
Z  HcHf     
   H5_X  H4     LWID$HHSPID$HID$H+[]A\    H   H[]A\       H5~W  HLD     H5iW  H0X  H5YW     HH5MW  L     H5JW  H~)  HLI|$HH.ID$H4   H5
W  H~uH5W  LID$I$H9  H)ЃHHHCIT$fD  
   H5V  HT~c
   LID$s)  Hthis(thiHfPHC
ID$
D     H5V  H}      LID$HHSPID$H;     H5>  L1ID$I$H9   H)ЃHHHCIT$fD  H5"V  LID$I$H9   H)ЃHHHCIT$fD  H5U  LID$I$H9   H)ЃHHHCIT$fD     LID$ thisHCID$Uf        LsID$ ~thi@sHCID$!HH6HjHD  AVAUAATIUSHH0<utratmb  H
Q  A0  HD  HEHAuH)HI  AhA  H6V  EJcHD  Ht$H裿HH     LjID$H\$ 'ID$Aa]  Au  AwY     L,ID$A\U     fD ID$HW     Ll$D  0HAD HBt!H؉у	~߃WHAD HBuHD$    t~Z   HcHcI00000000HNFE1HH؅INHDL  6  t 0  )HcA   LI)LCID$IT A   A  Et
A  Mt$   LID$ 'ID$H0H[]A\A]A^ÐHt1@ HLI|$LHezMt$    LID$ uID$뚾   L~ID$ LID$z   L^ID$uL  fID$UfD  H
L@IHDHt
HtL)H)D1DHA¾   H<
AAAI<9E   AtnAt[AtHAt5At"At   H<
I<H<
I<H<
I<H<
I<H<
I<H<
I<H<
I<D9BH<
I<NH<
HI<Np8H<
I<HH<
I<HH<
I<H H<
I<H(H<
I<H0H<
I<D9r@ L@LILLL)hyA˸   OA9GthtQtCt5t'tt   MMMMMMMD9MHMHύHMOG8MOMO MO(MO0MD9rHCH^y     LID$A\x     fDID$H   Ll$    LID$A\u     fDID$HgfD  Ht$H{HH  HD$LL-8  HH8  HHH|$ HLEID$߃m  IU L@IHILHLL)<I)Ń[  1wA   IL AI 93     tot\tIt6t#tк   IL I ЃIL I ЃIL I ЃIL I ЃIL I ЃIL I ЃIL I D9   IL I BIL HI BV8IL I FIL I FIL I F IL I F(IL I F0IL I D9r4fD  1f        tAU @   I\$00  f|
   L\ID$ID$>
DT
T% 0000D0000DT
fT AU AT=T8{AT=fT8kff.     fAUATUHSHHNu@~Au:~Nu4   HHCNa  f0@NHHCH[]A\A] IO     H5|L  Hs  E <Nw  L-I  ADE     HLe3HC0x  H߾   fHCHCU H߾   HCHC .HCUHADUt8fD     HIAT$HCHCA$HADUu<P      HIl$HC pHCAD$<Nu*     HH_UHCHCE ADE uHH[]A\A]fD  }N}FH߾   HHCIn  f@fHHCH[]A\A]        HL-G  HHC -HCE ADEhH1[H]A\A]@ H߾   HHC -InfHHCH[]A\A]f.        HIl$NHC -HCAD$    USHH  HH  <x   F<N   <Oun   HHHE  sha@aredHEHHEf.     <yu0
   HHHEle  H immutabHfHHE
HH[]f   HHoHEst    confpHHEH[]D  {gu:   HH1HEut    inofPHEHHED  1uAWIAVAUATE1UHSHHHL$fA?0tjMl$M   LHHN%  IH   <M   F<   H  HL貴t+A?0MuD  IA?0tHL苴sHHL[]A\A]A^A_Ð   H3HC .HCVfLsHL9  fIwH|$ I)HD$0    E)T$ HHHCH9t	H)EA)LT$ Ey
IcHHS11IHLT$J  LT$IƋD$tZHD$(L9tPL)HcHtEHHLT$HT$pLT$HT$H{LHT$LT$ oHT$HSLT$fMtA> u*HKHDHH))H9ADԅy
McLHCMMtLmMHMLHCHE1fIH)L$ HD$0    HH)H9DE1L1E  T$Iƅt
E1fE1H     HLM袲D  fIwH|$ HD$0    )D$ HHHCH9tE1NLT$ E1^@ HH1[]A\A]A^A_    AVAUATUSH Ht/t(A<9w!IHG  HHcH     1H H[]A\A]A^H LH]     HHHCHfunctionHHCD  H LH1[]A\A]A^VfD  fHHHD$    )$Ll$L4$HM9  M)McHt%E <Q	    HLH  Hž   HHCHdelegateHHCM  MLk@ HH~H蹯HH   HHC Tupl@le!(HCf.     H$LhL,$HP  HLH=HHqMt̾   HHCA,   fDHCf.     HL   HHHCA[]  fDHC@ Hn   HC charHCfD  H L1[]A\A]A^  f.     FHNF<w HHLHT   HHDHC *HCu Hn   "HC shar@red(HCHLHHž   HHC )HCD  Hn   HCin  f8@tHCHn   HC ubyt@eHCf.     Hn   rHC byteHCfD  Hn   JHC floa@tHCtfHn   "HC realHCPfD  Hn   HCle   doubfpHCD  Hn   HC crea@lHCfHn   HC boolHCfD  Hn
   zHCAe(  HimmutablHfDXHC
H@ Hn   BHC consAt(  fDhHC Hn   HC dcha@rHC<f.     Hn   HC voidHCfD  Hn   HC wcha@rHCfHn   HCArt   ushofD@HC Hn   bHC shor@tHCf.     Hn   2HC cdou@ubleHCY    Hn   HCat   cflofPHC'D  Hn   HC idou@ubleHC    Hn   HCat   iflofHHCD  Hn   rHCHtypeof(nH@ull)HCHn   BHC ulon@gHClf.     Hn   HC longHC@fD  Hn   HC uintHCfD  Hn   HC irea@lHCf.     F<i  <kHn   ~HC ucen@tHCfD  FH=;  LnG  HF HHWuILHI)H   HIHHC [HCMtLHH{LLeLs   HHC ]HC F<g  <h  1<nHn
   HCHtypeof(*HHf(*null)HHHC
 HfLHHD$    )$@HT$HH$H9   H)HLcL   HH
HC [HCMt"L$$LHH{LLdLkH߾   HC ]H<$HCHLHH{LLBdLkHn   {HC centHC1rE1HA   HGHCHdelegateHHCjLH!   HHHC [HC)H   LH=	  HHn   HC inouLLH   HHHC [HCHn	   HCH__vectorH@(HC	`ff.     AWfAVIAUATIUSH(HH)$HD$    LDH      F<wHH=  MHcHD  Mtp   L1ID$ (ID$HID$fD     LID$ )ID$H<$HtaH(H[]A\A]A^A_D  MuH<$1Ҿ   LHYjIFfo?  @-C)  HIFHHDD  =LsL=*=  <N2  fAFLa<
wIcLD     HHE scopAe   IfDHHE;Nt      HIHE retu@urn HE;Nx      HIHEAc    @nogfDPHE;N<g         HCHE @safK@ 	   H#HEH@trustedH@ HEH	HEI;N   
   HHEAy   H@propertHfDXHEH
D     HHE ref HEH       HHEHnothrow HHEH_D     HSHE pure@ HEH2        H#HE @liv+   LHYIFfoW=   HIFHHD   LHYIFHextern(PHPascal) HHHHIFHHD\
   LHYA)   IFHextern(CHfDxHIF
HHD   LHYJIFHextern(CH@++) HIFHHDHHHYHD 1H
YI^@ HMt   LLID$ (ID$E1   <Y   <Z   <X   M  <M  <Nk  <J    <K   H   HdHE ref HEHLHICHHpMf|f     HH   HE..  f8@.HEM)?@ HM)fD  HMt   HHEA,   fD HED  <LC   HHHE lazy@ HE    <I   HLsOHEin  f@ HE{K   L     {k   HLsHE retu@urn HECLX    HHE,   f0HEf.        HLsHEe    scopfHHECL    HHgHE out HEHf.     AUfHATUHSHIHHhHT$@H|$ )D$@)D$ )$HD$P    HD$0    HD$    HHHL,$IHD$L9tL)HcH   HD$(Ll$ L9tL)HcH      HHC  HD$HLl$@HCL9tL)HcHu4MuMH|$ Ht8ZH<$Ht*ZHhL[]A\A]@ HH-H{HLZHkLYHHH{HLZHkND  HHH{LH~ZHD$(Ll$ HkL9	fAWAVAUATUHSHHcBH+*H9   jIIHAIHtP>QuKH~Ht$IHt5HD$H9|+LH)Eth> tSHLD{Hu%AD  Eu3H1LE1D{HtHL[]A\A]A^A_     D{E1    HL SH   HH0Ht	8ZuHH0[fD  fH|$HHHD$     )D$~H|$HtHD$JXHD$H0[ff.     @ AWAVAUATUSH(Ht=D6Et4AF<Gw,IHW4  HHcMH~_H^  f1H(H[]A\A]A^A_@ HH(H[]A\A]A^A_ H~Ht$ڛHt8_u   HHXHEL=T-  L-E5  L%4   "HD$HEHPHT$H      AWHLsHA4wf 5  p@     0  7	ЍPHS  IcL    H^   HE nullHEfD  HD$H~HϚHHMt)LVHHIH}LL)WLu   HhHE (HE@ HD$LhLl$Hq  HM11HHH#Mtƾ   HHE,   fHEfD  H^   L$HEL$H -HE H~Ht$H  љHH   HHE [HE@ HD$LhLl$H  HM11HHHSMtƾ   HAHE,   fHEfD  H(H[]A\A]A^A_1H'   HHHE +HEH;cHsH   HHHE iHE@ ЈD$AW     HD$HUHEHfD  HEHD$HPHT$H   HHHE "HEAa4   H%HED0HE@ {DH~L*H(LHH[]A\A]A^A_fD  HH   HHE [HEfD  HD$LhLl$H  HM11H'HHk   H^HEHM11H :HEHH4Mt   H"HE,   f0HEl@    HHE  HEHw       HHEA\r  fDHEO    HHEA\f  fDHE'    HHEA\v  fD HE    H[HEA\n  fDHEH   H3HE\t  fHEHf.     @0H	ЍPIIcT L@ W	fD     HHE )HEf   HHE ]HEf   HHE\x     f8HHEeHESfHEHff.     fAWIAVIAUATLfHUHLSHH   D  A0	  HLH  fIHD$P    I)D$@D$/H   HD$@L|$E1HD$ Lt$MA  <Z  ME  <Hu	AFI<V     <S  <TuIvH|$@HIYIHuL|$Lt$D$/ E1fD     H+HE!(  fHD$HLd$@HEI9tL)HcH   H   HE )H|$@HEHtO|$/ tLL)L9   HĈ   L[]A\A]A^A_f     <XHI~Ht$`誓IH.HOLl$`L9M  IfD  H|$    AHD$H,   fHD$HAD  HHH}HLOH]D  E12A~_MnuA}DuI~H
  A~Q  Ht$`LҒIHVHL$`HHHT$HHD$@E1HL$Ld$0IHHl$8LH)H9ADA@ HHMuE耓   } _  ILd$0Hl$8MfD  IMifD  ;  } _u
}Di   HHH)L9  HgfffffffILH?HH)HD$HIHT$@H9   H)A9   HM4Ld$0Hl$8]D  1H|$@HHnH  Ld$LE1HgfffffffILH?HH)HD$HIHT$@H9uD  E~    IcHHT$Hg     EnM^AQ]  Lt$`fLHL)D$`HD$p       LIHD$hA  HT$`H|$@ILGH|$`IH^aLIM    }D Ld$E1H}HzHuAM(  LM@D  1H|$@HHH      H|$@HH HuLMH|$@LH|$HLLMpLLl$HWfD  H|$@1HLInfD  Ll$`I~LH&HT$`LH+H9LfLLH)HD0)D$`HD$p    8   LI(HD$hA  k    Ld$0Hl$8IfD  ML|$Lt$fD  ML|$Lt$If.     H|$@HLI     Ld$0Hl$8IIMI)ff.     @ AVIAUL-"   ATIUHSHH  A  <Qs  <_uA{_  HL=HH  L4$M  HJL9  Iv-;_  HLHH[]A\A]A^f.     uڀ;_uՀ{_uπ{SuL[J3I9l  HL)؃   H   HtlHtRHt8HtH!  AADE !  IAADE 
  IAADE    IAADE    IAADE    IAADE    II9AADE    ACISIADE    ACIADE twBLZADE tgBLZADE tWBLZADE tGBLZADE t7BLZADE t'LZI9AADE jf.     L9>fACT<HLLHH[]A\A]A^    {_CT<LLHLl$I{LSHH   HD$LI+$H9|oLH)L訋IHt(HGHT$H9rLHHufD  1HH[]A\A]A^fD  CADE  I111ff.     fB<'vDt!1fD  HHWxtotOw	ø     HH                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                 1 <stdout> Annotated source
 --whoami= Annotated disassembly
 dall %s: %s
 %s: Error: %s
 Error: invalid option: `%s'
 ~/ HOME %s/%s /home/%s Unable to open file: %s Function list
 
Load Object: %s

   0x%08llx  %8lld      %s
   0x%016llx  %16lld      %s
 Dump functions
 Error: %s Error: %s: %s Invalid option %d $T $TT $N Oabs 'Read 'Write 'Input 'Output .Finalize .Adjust _elabb 17h _ada_ <%s> _Dmain (anonymous namespace) auto decltype(auto) string literal std decltype(nullptr)  transaction_safe {default arg# }:: JArray initializer for module  construction vtable for  typeinfo name for  typeinfo fn for  non-virtual thunk to  covariant return thunk to  java Class for  guard variable for  TLS init function for  TLS wrapper function for  reference temporary # hidden alias for  non-transaction clone for  ,  >( cl ix qu  :  new  ul ull false true this {parm# global constructors keyed to  global destructors keyed to  std::allocator std::basic_string std::string std::istream basic_istream std::ostream basic_ostream std::iostream basic_iostream bool boolean byte long double float __float128 unsigned char unsigned int unsigned unsigned long unsigned __int128 unsigned short void wchar_t unsigned long long decimal32 decimal64 decimal128 half char8_t char16_t char32_t _Float std::bfloat16_t aN &= aS aa && alignof  aw co_await  az cc const_cast () cm , co ~ dV /= dX [...]= da delete[]  dc dynamic_cast di dl delete  ds .* dt dv dx eO ^= eo ^ == fL fR fl fr gs lS <<= li operator""  ls << mI -= mL *= mi ml mm -- na new[] != ! nw new oR |= oo || pL += pl pm ->* pp ++ ps pt -> ? rM %= rS >>= rc reinterpret_cast rm % rs >> sP sizeof... sc static_cast ss <=> sizeof  sz throw tw throw  'Elab_Body _elabs 'Elab_Spec _size 'Size _alignment 'Alignment _assign .":=" Oand Omod Onot Oor Orem Oxor Oeq One Olt Ole Ogt Oge Oadd Osubtract Oconcat Omultiply Odivide Oexpon **  Error: Invalid function/file setting: %s
       %s: Error: unable to open file %s
      %s: Error: Could not read class file `%s'
      %s: Error: `%s' is interface; disassembly annotation not available
     Usage: gprofng display src [OPTION(S)] TARGET-OBJECT
   
Display the source code listing, or source code interleaved with disassembly code,
as extracted from the target object (an executable, shared object, object file, or
a Java .class file).

Options:

 --version           print the version number and exit.
 --help              print usage information and exit.
 --verbose {on|off}  enable (on) or disable (off) verbose mode; the default is "off".

 -func                   list all the functions from the given object.

 -source item tag    show the source code for item; the tag is used to
                     differentiate in case of multiple occurences with
                     the same name; the combination of "all -1" selects
                     all the functions in the object; the default is
                     "-source all -1".

 -disasm item tag        show the source code, interleaved with the disassembled
                         instructions; the same definitions for item and tag apply.

 -outfile <filename>     write results to file <filename>; a dash (-) writes to
                         stdout; this is also the default; note that this only
                         affects options included to the right of this option.

Documentation:

A getting started guide for gprofng is maintained as a Texinfo manual. If the info and
gprofng programs are properly installed at your site, the command "info gprofng"
should give you access to this document.

See also:

gprofng(1), gp-archive(1), gp-collect-app(1), gp-display-html(1), gp-display-text(1)
 Functions sorted in lexicographic order
            Address     Size        Name

          Address                     Size        Name

      ---------------------------------------
        template parameter object for   std::basic_string<char, std::char_traits<char>, std::allocator<char> >  std::basic_istream<char, std::char_traits<char> >       std::basic_ostream<char, std::char_traits<char> >       std::basic_iostream<char, std::char_traits<char> >      IIIIIII JIIIIIIIIIIIIIIHIHHSSSSSSSSSSSSSSSSSSSSSSSSSe6f1fe1feee6fjeff
fjejepejejejeolmnlnXnlllll8pl(nolnl@opooooooooooooo*pooooooooooooqoJqr`rroqQtooootosoos*pdsr!}|6}|/}(}4\4.}iU;!B̛̛̛̛̛̛̛̛̛̛̛̛̛̛̛̛̛̛̛̛̛̠ĜĜ\\ܠ̛̛̛̛\̛̛̛̛̛̛̛̛̛̛̛̛̛̛̛̛̛̛̛̛̛̛̛̛̛̛̛̛̛̛̛̛̛<̛ܥ@@ 	Hq p0(xxx       88  ?T-	qo00?Sxa    K<[ LLsLgLL        6VectorIP8HistableE     6er_src         CBBBB                  Q0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 00 0 0 0 0                                                                                                                                                                                                                                                                  str i8 i16 i32 i64 i128 isize u8 u16 u32 u64 u128 usize f32 f64 %lu ' for< 0x %lx \t \r \n \u{ } _GLOBAL_ [ ::{ closure shim  as  C mut  const  ;  unsafe  extern " fn(  ->  dyn   +   =  __ctor __dtor __initZ initializer for  __vtblZ __ClassZ ClassInfo for  __postblitMFZ __InterfaceZ Interface for  __ModuleInfoZ ModuleInfo for  NINF   rrrrrrqrpr`rqPr@r0r rrqq rqqqqqqq 3FXBLnX0000000000ȜȜppWx``pȧī{{ī{{{{{{ī8ȸȸؿxxxxxȸȸxxxxxxxxp`0`h@X(ȽpH2XXXXXXXXXXXXXp<XpHp8     h@                  h@
%s%sout of memory allocating %lu bytes after a total of %lu bytes
     extern(Windows) extern(Objective;t  m      $  $  ^+  0  4  4  4  4  5  5   45  D50  5   5  7   9<  P;  @<   `<4  `>(  >  >  ?  ?  p@  @   `AT  Bh  D|  0Ed  E  F  G	  @JT	  W	  0X	  X	  X	  Y	  PZ
  \4
  p]l
   ^
   i   jd  k  l  l$  rh  z   }@
  }h
  P~
  
  $  @l  @     PP       4  0  <  XX  Z   a  eh   f|  f  Pg  @k  l  m  m,  n  p  q,  qT  u  v  x$  ~X   |  @  8  t      ЖH    0     P`  С  `    P    0     @  (  t  0  @4    p@             zR x      7"                  zR x  $         FJw ?;*3$"       D                  \   88              zPLR x>    L   $   $8    BBB B(D0H8Dp
8C0A(B BBBA 4   t   $     p8xEGF[p 0     2Y   BBB B(D0C8Gp  4   L  f&0   p
8D0A(B BBBA     094    A     3(   BBB B(A0A8D@]
8A0A(B BBBA6
8C0A(B BBBEzHEPCXF`V@dHEPCXF`V@       *0   @A
8A0A(B BBBEf
8C0A(B BBBEf
8C0A(B BBBE
8A0A(B BBBEM
8A0A(B BBBB
8D0A(B BBBE
8C0A(B BBBE      8!    HT        .            -          ,  7          @  8\          T  8          h  \9b       0   |  9}    ACG i
AAJzAA      :x           p;      D     <    KEH K(H0P
(A BBBF`         ,          4  ,1          H  -	          \  -    AU      x  -       0     -]    ADE |
FHEAAA 4     <    BBA G(G0(A ABB8     L=    BED A(G0|
(A ABBK  4   4  =    BMA D(DP(A ABB@   l  >   BBB D(A0GP
0A(A BBBD T     @   BDE B(A0D8I
8D0A(B BBBAga       \M           hN]          0  NC          D  N          X  O           l  8P   P
GDD4     Rz    AAG q
LAIV
CAF        R    Ai
FM
C l     hS
   BBB A(A0GP
0I(A BBBJ
0D(A BBBAo
0A(D BBBF    \  *    P   @   |  ]   AAG 
AAEu
AAIQ
AAA(     4_    AAD0
AAC P     _    NDG w
FAIZ
DAIK
CAI`H   <   @  `k    BDD D0w
 KABMD CAB  @     `   BBB D(A0GP
0D(A BBBG      `f   BBB A(A0j
(D BBBD
(A BBBJ 
(D BBBF
(A BBBHA
(A BBBH  H   P	  m`   BDB B(A0D8GPp
8D0A(B BBBE$   	  o|    eH uAEP   L   	  0p    BAA G0^
 CABAU
 AABGU AAB  ,   
  p   BDC 
ABF   8   D
  q   BBD A(GP
(D ABBI D   
  v   AAG0
CAK
DAN
HAJ  8   
  |   BAA 
ABEK
ABJ  X     ~    BBD A(G@h
(C ABBHQ
(A ABBAU(A ABBH   `  ~J   JNL C
AAG{
AAA^
AABy   0         ADD0j
AAKNAAp     d   BBD D(G0d
(G ABBM
(A ABBHm
(A ABBEf
(A ABBD8   T  @   BHD D(G0
(A ABBC         KBL E(A0D8GpV
8A0A(B BBBFu
8A0A(B BBBAY
8A0A(B BBBAY
8A0A(B BBBAr
8A0A(B BBBABAp <   X
  ,   BEE N(D0
(A BBBF     
     BBB B(A0A8J]
8A0A(B BBBA"
8D0A(B BBBE|
8G0A(B BBBEv
8D0A(B BBBEh
8A0A(B BBBE
8J0A(B BBBEg
8D0A(B BBBE.
8G0A(B BBBE
8H0A(B BBBEL     pF   BBD D(G@y
(A ABBFs
(A ABBG   \     Gx   VBB B(A0C8G@K8F0A(B BBBGH@ \   d  M   RBB A(A0S
(C BBBD(A DBBCH0      0R{            R       4     S    AMD(Q
AAKJ
CAB    $  S         8  \W          L  Xh      $   `  tYH    AML@kAA P     Y    BAD G0W
 AABGV
 GABHS
 FHBE   h     (Z4   RBB B(A0A8G@N
8A0A(B BBBG
8F0H(B BBBI  <   H  [    AAG0J
DAHP
AAFIDA$     L\H    AML@kAA 8     t\   BBA A(G@x
(A ABBE  H     X`    BBA A(G0I
(A ABBL(A ABB  D   8  `   BFD B
ABGb
FBNm
ABH 0     db   AC
Iu
Ah
A       ht    AK0y
AJ  8     |h1   BGA d
AQX7
HBO  |     k   BBB B(A0A8D
8A0A(B BBBJ
8A0A(B BBBE
8A0A(B BBBB8     v    HDD ZAADA bAA (     4w7    BGD fAB   h     Hw   BBB B(A0C8Gpx
8A0A(B BBBKdpapep]dp8   h  |   BAA E
ABDQ
ABD        ~   BBB B(A0A8G`K
8A0A(B BBBJC
8D0D(B BBBE
8A0A(B BBBHa`      ,  a    @ W   D  @D    A  \   \  x    BBA A(G0\
(A ABBA}
(A ABBEs
(A ABBA  (     v    RAG Q
ABB8     <   FDD o
ABHM
ABH   @   $  3   BDH D(A0G`
0D(A BBBB   h     BBA D(G0~
(A ABBDH
(D ABBGA
(A ABBIx
(C DBBEg
(A ABBK   4     /   AAD 
DACp
AAF `   (     BEB B(D0D8G
8D0A(B BBBB,8C0A(B BBB l     H
   BBB A(A0DPz
0D(A BBBAB
0J(A BBBK
0F(A BBBO H     x   BFE B(D0A8D`
8D0A(B BBBF 8   H  L   BIA D(M
(D ABBEH         BBB B(A0D8DP
8D0A(B BBBI $     4q    AP@W
AGA        BBB B(A0A8D`H
8D0A(B BBBEK
8D0A(B BBBH
8E0A(B BBBF"
8J0A(B BBBK L        BEE B(H0G8Jb
8D0A(B BBBJ   l     S   BEI D(D0D@t
0J(A BBBO
0D(A BBBL
0D(A BBBGH   P  
   BBE E(D0A8D`8A0A(B BBB        (V             *   O                                                                                                                              p[      0[      t                                               a                                    	       b                                           s                   0     F                   i                   x     1            
       o                        1            
       d            
            2                                           R            R            !            &           Y            .            8            8           3            3           ?            ?           E     
       E     
      P     
       P     
       g            g           ^            k                                           }            }           t     
       t     
                                                                                                                                                                                                                                                          	               Y                 	       }                                  m            m                 	            	            	            	            
            
                                                                                                                                                                                                             !     $           P     %           +     %           8     '           0     3     	      =     '           @     C     
      6     N           Q     T           V     Y           [     ^           a     d           k     n     	      x     {           J     U                                                                 o                |                 h                                           
                     m                m                m                m           !     B                                4           9                                                                                                                                                     U                                                                                                                                                                                +                 #           '     *           -     +           0     3           <     6           8     ;           >     A           E     H           Y     \           ^     a           d     g     	      o     g     	      q     t                                                                                                                            {                                                                  H     I                                                                                 ^                              4           B     $     +     )          3     %     ;     U     E     |      M     T                             @]     NT      XT      S      T              P]     tT      ]      ]       W              `             x                                                                         @      
                   0N                          8N                   o                                     
       8                                          _                                       (/                                	              o           o          o           o    X      o    !                                                                                                                                                                                                      h]                     6@      F@      V@      f@      v@      @      @      @      @      @      @      @      @      A      A      &A      6A      FA      VA      fA      vA      A      A      A      A      A      A      A      A      B      B      &B      6B      FB      VB      fB      vB      B      B      B      B      B      B      B      B      C      C      &C      6C      FC      VC      fC      vC      C      C      C      C      C      C              a             /usr/lib/debug/.dwz/x86_64-linux-gnu/binutils-x86-64-linux-gnu.debug |:́XR75h .shstrtab .interp .note.gnu.property .note.gnu.build-id .note.ABI-tag .gnu.hash .dynsym .dynstr .gnu.version .gnu.version_r .rela.dyn .rela.plt .init .plt.got .text .fini .rodata .eh_frame_hdr .eh_frame .gcc_except_table .init_array .fini_array .data.rel.ro .dynamic .got.plt .data .bss .gnu_debugaltlink                                                                                                                                          8      8                                     &             X      X      $                              9             |      |                                     G   o                   0                             Q                         P                          Y                           8                             a   o       X      X                                  n   o                                               }                                                          B       (/      (/                                              @       @                                                  @       @                                               C      C                                                C      C                                                         	                                                         @                                           @     @     t                                          "     "                                               =     =                                                0N     0>                                               8N     8>                                               @N     @>     (                                          h]     hM                                              _     O     X                                         _     O                                             a     Q                                               a     Q                                                         Q     Y                                                    IR     2                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                             (     H[]A\1111Ð      H{`ٿHC`    M   Ch   HtH{X1HH5 8~L=     11Ҿ   LHH<$ uH~H{X1HH5 g87LW'Lc`   Hi H5m H0D  1Hk   LVHtHH$    fD  ;H '  H= 1Ҿ 1=   P H<$1   uH<$H<$11H5AWAVAUATUSHH  HIALcDEt-      H{pL=   LrHCp    Mt  LLHCpH   DsxEx:       H         H[]A\A]A^A_1111E1 H       H    H=x s1Ҿ 1=   1H[]A\A]A^A_1111E1@ 1)mLb蛽H    H= 11Ҿ =   1ff.     AUATIUHSHHHtHHE1Z+HHtHLHE1AAH購HD[]A\A]1111ff.     fAWAVAUATUSHHdH%(   HD$81HD$(    H  HX Hr  H g  H  \  LgL5/ HǇ       D$    D$         _    S    IcL H   H      H{`Ht11Ҿ       H{11Ҿ   	        LcZsx  SH{ LQHcH	  HsH{X-HH95    {  Ll$ !  u\H{X1L   IH~gHT$ HJHL$ :0	  zO@9  HQ      H{X11Ҿ   Hx
H;     Lc]H{X   H5Ͻ ,    H{XH   1Ҿ   蕿  H   Hb  H   H{},0  HLcH   H)   f.     8H{XL1Ҿ   %HH  H|$ H¾
   HcSH  H{XLf  ;C}  ;  :   L$H   HCHD$ t,Hf.     
t	
ZHD$ Hu⋃   D$u  =     H{p tT$3	    Cx     fD    Hh    H}    Fh  u
   H5#HD$(H    H|$( m    H5 Ll  H5 LlHt$(
   HaHHD$(H9  8   Hf.     1HT$8dH+%(     HH[]A\A]A^A_1111E1FSH{ LHcP  {ANfD  L   H5  A<$uR1A|$0LD$@t;   f  u$  f        f    H} @uMIl$<&       f  uA IL9,  A?L@u  =H   H= L~   1HV =   J       H{p )H53 LFjH{pH2j  D$   D  
SH{ LHc@ H5i HD$i  D$        H5 Li=  uf;H   H= 1Ҿ 1=   P 
   H; HD$(H/     HG<5  H@1HHT$ BHHH	H9u@H4y}H@@ E H   HL$d  HL$  9  Ht$0
   HHL$g^HD$HD$08 HL$yHAI@udD  xHI@tO   d  LuA? t8LIDfHD$0  HD$0HHD$08   c  uHD$=     --    Kh   @  ,@ H5 HgT$ET$T$HcSH9T   HH{X11Ҿ     SHsH{` JHH&  LcH   L   XǳH   H=D ?1Ҿ 1=   GAHfH{X   5D  [H   H= 1Ҿq   1=   p&H   H= 1Ҿt   1=   ;   f.     ǃ       `ȲH   H=E @1Ҿ   1=   H     1|$  A? DiD$   lH   H= t$H1Hk =   z+H{        H{    fuH 0  H=j e1Ҿ   1=   m踱Hq   H=5 0Hw   1H =   0{H   H= t$MHH =   17<H   H= 1Ҿn   1=   QH   H   H=x sHKpI1H- v   =   oH{`   !褰H] b  莰HG (  H= 1Ҿm   1=     DOH   H=̽ 1Ҿo   1=   d*'H   H= HKpy   1Hz =   !ff.     AUATIUHSHHdH%(   HD$1H    1t,HT$dH+%(   uPH[]A\A]1111f     H}XI1Ҿ   LZ1LLHHHG&    SHHu    fH   H{ d   KT~7Htڅt;  t.HCX[111H    t$     1[111fD  HC [111H    ~k襮H   H=" 11Ҿf   =   1qHʿ   H= 11Ҿ =   1q:H   H= 11Ҿg   =   O1:     1Ht
   111    AWAVIAUIHATEULSHHXH$   L$   H$   HD$dH%(   HD$H1EAMu	EN  H%  H  M  H	HL$  ;$   Ht$HHH  @    H@(    HD$De8HE0Mt!  H5 LHEHH  Mt!  H5m LHEPH  $   M1H   HD$HdH+%(   !  HXH[]A\A]A^A_1111E1E1E1     1[HHc$   Hf     HW  H	t:=H~   H= 1Ҿ 1=   R1\ D\$~:$   H   Hl$D\$M  H|$Ht$A˺   AHH  H@ŋ$   @HD$NHHtJD$L}(De8EHD$HE0HQ  H5 HqHE@H0H,41+Hl   1H= 1Ҿk   1=   >Jf     HD$0    HD$8    M  Mt	A}  LDHDLD\$dVD\$HHt:D\$HL$0H1j E11Hj j LD$X~OH D\$ZLD$0HL$8M   HHL$   LD\$/讼HD$HH HD$4  D\$/HL$ H|$   d   D\$  D\$ Ht$H|$0  D\$ 	^Ht$H|$8  ]H|$ D\$ D\$18H|$$   ;D\$H|$BfD  sH   1fLME_  D\$/Hܷ H
ط LD$HDH HHD$HL$ @]H|$~HL$ D\$/HHD$D  H\$H|$0  1H\H|$8  H\H{%fHH|$@    11LD\$HT$@LD$HD$@    HLD$D\$   H|$@HHܵ _  D\$ HLD$HD$X\H|$薺D\$ HHD$"Ht$H|$0  D\$ !\Ht$H|$8  
\D\$ էH   1H=P K1Ҿ 1=   LD\$ D\$ HD$H HD$D  AWAVAUATUSH(HL$HL$hLL$HJ  H@ HHIMt'W8u HWHH  H   HOPfD  H   HKP11MIH@u#1H([]A\A]A^A_1111E1E1@ HCHE1HD$Ht
E18 A1#f     IGIwHHtLn9}2LIEtHpH= E1YAD  Eu{DD$xL$pHߋT$`Ht$Y6Ht$LH1@ H$   H=x s1Ҿ 1=    HT$H5c Hi    蛥HĶ   H= 1Ҿ 1=   ff.     ATUSH   dH%(   H$   1H  HIHtH    HHHtGHtaH$   dH+%(   J  H   H[]A\1111E1E1    H   HtdMt6  H5C I$1fD  蛤H 3  1H= 1Ҿt   1=   ^f     KHé   uH<t	=  LEHMP  HEPL
 Hc  U8H
 I   LHY HEHH P1L   1xOLHU@HtH5    1YOHE8HH
; H H߾   H7 HE1 H޿   1O1_f.     [Hd (  1H=ְ 1Ҿ 1=   n% =   gt	 :TLLEHM@ HU@H)H5    11^NH ID  USHHHt"HG(HtHHs011Ht	HC   HSH[]1111fAWAVE1AUATUSHH   H$   D$  Ht$HT$ HD$8H$   HL$HD$@H$   LD$(LL$0HD$HD|$dH%(   H$   1E~
1McJQIH  L%G Hߺ  LHHb  H$   E1HD$`HD$xHD$XHD$tHD$PH$   HD$hf.     HE11Hj j $   L$   HL$xHt$p2FH   HD$P$   Pt$Pt$Pt$PH$   LL$8D$   HL$PHT$HH$   H$   H0HHǄ$       H  j HE11jH$  $  PLL$hHT$`|H   HhH$     LT1L$   M  AA2*  A?/t4   H5, Hu   H5 Lx  1OMt I9+  LH)¸H9HNHD$H|$11Ҿ   ɤHߺ  LSH$   ;/   Hߺ  LH$   HHH|$x  LSH$     LS   H`1  LHaSE1     LKSfD  H|$xL溲  .SH$   L溳  S   H    H$   HH$     LIRMFA   H|$x  LRH$   L溻  RDH    LHRH$   dH+%(   M  HĨ   L[]A\A]A^A_1111E1E1D  H `  L菽1Ҿs   1=   ,  LE1E1H$   Q+@ ÝL  H ?1Ҿ   1=   ܾf.     苝Lg  Hl 1Ҿp   1=   褾s    LE1     E1     E1#H   H= 蛼1Ҿ 1=   8ff.      ATIUHHHSLʋ$   H   H] H   $   LHRP$   $   PL$   L$   HL$xHT$pcH u;1E1H1l   HtH] L[]A\1111E1E1D  1HIHtHV%u    HPD$XPt$Xt$Xt$XLL$XHL$PH0HøHE1wfD  HPD$XPt$Xt$Xt$XLL$XHL$PH0HøHE13fD  LE1
     AWL= AVI    AUIպ!  ATMcUSH(H4$LHL$LD$OHHHD$    HE~1zJLHD$MtH<$ tH|$` tvH|$h unњH +  LM1Ҿ 1=   E1H  LHﺦ  NH(D[]A\A]A^A_1111E1E1fD  M  A}  H LDH  H  LH2H$LHH5X 1H5۩ H1HD$H=  HHL$L`H1  HF  LIMl$LMIH  LD$HL$1LH`\ L7D9t"R  LLL_  f.     $LHIHHHHH)ֺ
  HLHHHxHD$MIHt$LHu  HH9D$  LH5ި H1LO  LLHR  LLLH5ƛ H1]    Ht11Ҿ   H膝tHt$d   H=A      HH(LcA~ͺ   H5 H  }1Lm    H٨   L蜷1Ҿj   1=   9HT$hM1H|$`   H5 f     E111Ҿ   H輜H1HL	    L-7 E@ HT$hH|$`H5 1( A}.@} Lmu5A}2u.@     HHA   cI   B|%   VF  uIA$ L  H 聶L1d   H =   HT$hL1H|$`H5( kfD  LhF  LL|JIHH HD$    sLw  H$ 11~   =   茷HT$hH|$`1H5A _IH# HT$hH
! H|$`HDH5T 1(  LLJQ Hl "Ht
   H1ÐH=  d   H1     AVAUATUSH  dH%(   H$  1H   IHHGHXIH      M   HL_HHu?   f{   bD  u+{,t%     H{H$HH   I9uN4+A>@t   D  uA>,u1H$  dH+%(      H  []A\A]A^111 } [C|]8HuHHIHV!H=ة Z  IHH=ɩ Z  IH   fAAWAVAUATIUHSHH   H$   H|$L$L$   LL$0L$   HD$dH%(   H$   1HtH    MtI$    HtH    H$HtH     HD$0Ht     HD$HtH     MtIE     MtI    H|$   H|$H5- lIH  H9D$  H@HD$8H|$8@   ]HD$HH  HHD$ HD$ 8[  H|$ :   )IH  H A9:LL$(HD$  H|$1H$   H5
 LL$@R  $       LD$LL$@A D$P0<	wA@I0<	vHD$(HL$H9IDHD$( <?W  :L5    H HLHD$觱1Ҿ}   1=   DHT$   L}1Ҿe   1=   HtH} 0   LEHE     MtI,$0   LHEI$    HtL#0   LLEH    H<$ t"H$H0   LHEH$H     H\$HtH;0   LaEH    MtI?0   LEEI    MtI} 0   L(EIE     1H$   dH+%(     HĘ   []A\A]A^A_1111E1E1E1E1f     IAHD$(HD$D  蓐L5
    Hx LHL${   1H =   蛱|fD  HD$HD$8IfD  Hx]   jLHH@H L5 HD$D  HD$8HD$ HD$H@ H    HH|$(LD$PLL$@H|$(?   HHD$XLL$@LD$PHI  M  #   HLD$`LL$PHD$@LT$@LL$PILD$`IBMHD$po  ICHD$xHtWH|$L*   L5 LL\$hH)LD$`LT$PLL$@9*LL$@LT$PHHE LD$`HL\$hHtIH|$ Lι*   L5M LL\$PH)LD$@LT$)LT$LD$@HHL\$P  H<$ tCH|$Lƹ*   L5 LL\$ H)LT$)H$LT$HL\$ HO  MtBHt$HH|$8*   L5 LL\$H)LT$M)LT$L\$HI$r  Mt5H|$pL޹*   L5n LLT$H)
)LT$HIMt8Ht$XH|$x*   L52 LLT$H)(LT$HIE H|$0 t$   HL$0HD$(8/J  H|$ tTHL$(L5آ    LI)MBLLD$AHHD$H8HMHL$(Ht$H 1   D  H|$ /   1IHH|$ ?   IHH|$ #   IHH|$ HL$ L    LT$(L׾#   LD$PLL$@LL$@LD$PHIuRLT$XLT$pMLT$x
 CH4 M   H= 軫1Ҿ 1=   X HD$XMHD$pH M   I<$0   L@I$    H4PD  HtNH} 0   L?HE     MHH} 0   L?HE     MI<$0   L{?I$    HH;0   LU?H    H|$ H|$(Lֹ*   L5 LH)&&HL$HHL\$XL\$xff.     AWAVAUATIUHSLHHHT$L$   LL$L$   L$   dH%(   HD$81MtI     HtE     Ht$(HLAWAVAULL$0HT$(LD$P+H e  H|$(H5 H|$_?H|$J  HtE    H-x    H>H|$0?0]   S     H=H=\ 1HT$$H|$0H5 VuAHL$HtD$$H  H|$0   H薾HH   f.     H\$HtH;0   Hn=H    MtI<$0   HQ=I$    MtI} 0   H3=IE     MtI>0   H=I    MtI?0   H<I     1R@ ? tH5U H|$=H|$   H-    H<H|$0?0t?HtZH;   HT$8dH+%(      HH[]A\A]A^A_1111E1E1Ð u   HU<H= c   H;<뚐H-    H؝ H耧11|   =   H|$(H   ;H|$0   H;Tff.     @ ATIUHSHHt.; tUHLtFH[]A\1111f.     t<H= M  HHuH= M  HHu1H[]A\1111fH= M  H= HHsf.     D     f.     U1HSHH5֜ HHW8HoUH1H5Ԝ [UH1H5ܜ GHH5 16HH5 1%HH5 1HH5 1HH5 1HH5 1HH5% 1HH5/ 1HH59 1HH5C 1HH5M 1HH5W 1{1HHH5[ []d@ ATIUHSH虵Ht4HL1Ҿj   HHHH[]A\     []A\11111ÐGtjAUIATL% UHS1HIU 1HHt    H@HuLH1A;]rH[]A\A]1111111111@ ATIUHSH蹴Ht4HL1Ҿj   H蟉HHH[]A\(     []A\11111ÐAUIATIUSH   Iu 11H    HHt!1fD  HRHHuHtHHHH9uΉHH5Λ L11HLH5ϛ HthH1AuHHHI1HHHHH1HLHHHH1HAHHH5 []A\A]H1'H[]A\A]11111E1E1L1H5 11HL1[H5 ]1A\A]f.     ATIUHS!H	Ht4HL1Ҿj   HHH}H[]A\x     []A\11111ÐAVAUIATIUSHHSK$1I$HHC H9sKH1HHLsHcL$I$Ht H9ku
H;LAօt
LcH[Hu[L]A\A]A^1111ff.     Ht{1tt1A   A    @ HIHL	I   HH1HID)HA	L1HƄuHH11111E1E1E1D  11111E1E1E1ff.     AUL- 3   ATILUHH   SHwH   ;   L   HYHHtiMtDLcHtKHd fod HkC$   HCC(HH[]A\A]111D  L%Q6% LcHuH-I4%     G   L14H   LH4f     1ff.     H   AVIAUATUSGt^HE1H-      EIJ"HHt%D  HH[b   Hl4HuIJ"H     AE;nrIF8    []A\A]A^11111111D  Ht;UH- SHHH;HR   3HHHߺS   []3111f     AW1AVAUATIUSHHwdH%(   HD$1HG8G@    HHH;G(   Do Dw$oHAUD9   W HECT5 J<LЉKI     HHt=HAHI HAIHHtHA1HI9uHyHHuD  HLHHH H   HL HD$dH+%(      HH[]A\A]A^A_1111E1E1Ðt-    H HIH2Ht|HD1)H<HKHk$D{C     f.     x   H5?    1Ht%H$L H@    HP1HE HC8-fC@1 AUATUSHHdH%(   HD$1G@    HH8H   HWL% LH   H/1HC8KHHC8w.HD$dH+%(      HH[]A\A]1111@ H1HH9C0rC s$H;T0HL*H    tHC HHǉKHHtffD  HH@HuLjm 1cf     4      LL0HHt$HC$KkC$C  L*C@H;fHdH%(   HD$1G@tG@    HH HtH HT$dH+%(   uH111;ff.     HtaAVIAUATUSDgAx=EHI@ IJ(Ht@ HH[H8HuAIAu[]A\A]A^111111 HttAWIAVAUATUSHDoAxBEHII IJ0Ht@ HH[LH8HuAIAuH[]A\A]A^A_11111111ff.      H   AU1ATUHSH?@t]A   E1    f*  L}HHL	I   HH1HH)ID	H1I@uHL1H[]A\A]111111111D  1HtHG81fHG01f     Hw011    G@1f.     H     UHSHHH   w>Hv      	  t=   HH~  H[]111ú      ~     uH1[]111f     1111    AUATUHHSHHdH%(   HD$1t,1HT$dH+%(      H[]A\A]111D  HHA%~  t      H~  tEAD$HDHAAMcLtHLHWz  kH跀  [H4$   HKDH	A92ff.     @ AVAUIATIUSHHPdH%(   HD$H1  H߉L}  t8udLt$1LEv  t!LL   L  fD  1HT$HdH+%(      HP[]A\A]A^111    LHEtLH6tHt$Hw  t   0   H|  tHt$H^vu&LH_LHLHD  9    LLHt$L@w  L0  Wff.      HHHHHt1H0LIDLFLHL Ey6A   t]A      1҉1111E1E1E1f.     M9rLMLWL)PL    1111E1E1E1ÐMtVHH9rHH)LHHL H7HW 1IvDFHfAEL9[HL)JHHHH7LGqff.     SH dH%(   HD$HGHtHHHHGHt*1HT$dH+%(   u[H [1111f.     HHtHt$H<$Ht? xuHt yHHX     AUATUSH8dH%(   HD$(HHx'H$HL$tHHHH$HL$0t)1HT$(dH+%(   ufH8[]A\A]1111@ Ll$IHHLtLLtHLtH|$ uH$HH+Hf.     fAWAVAUATUSH(H|$Ht$DL$   AAMĽ    {f     t~AoA9~8A.H|$HD$AAHcHHAԅyEA9ȅt9D$   H(H[]A\A]A^A_1111E1E11E1f     D$tAODALcHD$HcH HH|$AoLAԅuAEDH\$AHcHu 1kf     HAaf     AUATUHSHޟHE H   ̟1H  Hu/@ HH   襟H   Ǆ   HuLmH   L   H;H L9uH   H}  LHE     1Hǅ      HH)  H1H[]A\A]1111fHLm+  s1L   HJ1  tH> t   H+  =fD  H1H=Q% ^ruQ% H111f     H=Q% Q% H111ff.     AUHAATMUHSH7  HHAT$HtH;ImuH[]A\A]11111E1fD  HLDH;H[]A\A](     ATUHSH  H  Ht&L%Q HHH[   L%HuHU1   #HH   L  |*  @ H;HL9uH  H} HE     []A\111ff.     @ HH=P% @H=]P% HUH-      SHHAHt4HHtHH[]111D     HH $1HH[]111fD  H11H1111ff.      HH5H=O% Yyt%O%     HO% HDH111f1H111 UH5XSHH=UO% HytX:O% tNH=3O% HHt:Ht"H6O% H=O% H9ø    HDHHH[]11D  H-O% ff.     @ USHO% uH[]1111H-N% HxH HH[1]D  HHt11 HH5eH=fN% xt%ON% tH=HN% Ht
H11ÐHIN%     HH8H{jff.     HwH8H鋒ff.     HWH8Hff.     H7Ht  H1Ð1H1    HtkSH5HH=M% 4wt0jM% t&H=cM% HtH9[11fD  HYM% H9[11f.        11fD  HtKSHru.  uEHH[   H5-  !     [1111fD  1111    H  fD  UHSHB}Ht-HHHtHH[]11D  H@1ff.     ATIUHSHt4LHHH  t  H[]A\111fH1@ HwHL% H9H11ff.      AVAUATIUHcS=H   H8HI   L4H;E   AthH H<   H;   H{DuH;ILH<C[L]A\A]A^1111E1E1f     Lm J<gtOH;wg  A   tCH{*uH;IJ<@ H<    E1u     H(IHtxA$L1E1L   LPH=Pw%  ZYxIA   H;Lc]1L   A   G'  u;E1H   3fD  H; H   NfD  H;蠎tA   L-tH;IJ<fHGHHPHEH11 ATAUHS!Ht|H  H-tiDH    L`hu`kH  et;BucHB   H  BD3[]A\111fD  1[]A\111ÐBl[]A\111f     H  Blff.     fU  HH5 SH   HHt)H  H(HPH  H   []111fH1[]111ÐSHgHހ t
[11@ HH [H׀ HD11f.     @ AWAVAUATIUSHH8ndH%(   HD$(1l$u
D$      HD$ D$   HD$HD$$HD$sfD  LD$DLЅ  D$$HK8   D$$   HS(Dl$$LL  E       ED$D$D$9   HT$LD$       Dl$ Hs8D$$    IDS   HCHK8HID$$   Mt&I> t M LI DLS I? HK8uHC0H0LD$DLЅtHK8D  D$$HK8LL
  f.     D$    HD$(dH+%(   uD$H8[]A\A]A^A_1111E1UD  ATUSHHPdH%(   HD$H1HD$pD$    H<$HD$(HD$xt$HD$0H$   HL$LD$LL$ HD$8HthHHu  HIJLH?H9t*HD$HdH+%(   uCHP[]A\11111E1E1ÐHHL$$a    HH5N  rfUSHHH   :   HHH)Ht.H-}    HHO Ht"H[]1111 HH dH}    Ho1Ҿ  1   1     SHH~HFHv tSuHtH@[    HHCHHtHCHs D  1[111fD  HGHWHw H@Hff.     AVIAUAATIHULSHAHHQ P(HtFHHCLK 1MD$I$H@ EtH{HLHCHs H[]H@0A\A]A^f[]A\A]A^11111E1E1    HMtOA    u$HcD  H1111E1@ Q   uH1111E1@ ScH| [   H=?| ˂11Ҿ    h1@ SMtRA     LÅt$Iu      [1111E1@ HcH  tA1fD  bH{ @   H={ ;1Ҿ 1   ؃1[1111E1f     ATMULSH1H0dH%(   HD$(1HtHL$HL
LHD$    H
Hl$ Ld$(HD$PHhPHPH|$(H Ht<LHUHt.HT$(dH+%(   u+H0[]A\1111E1E1    LH1Uf.     @ UH-{ SHHHtH?9   HHHHߺ:   []D  UH-z    SHHHHH(dH%(   HD$1]H$Ht4H{HD$    `sH<$   HH$HtCf1HT$dH+%(   uH([]1111f.     H6H?D  H?     HHtHH111f.     H~ t	111fH~111D  9Gt11111fD  HcFHHVx~H11111     AWIAVIֺ  AUL-y ATALUH   SHHHtp  LLLHHtEEt}DcH}HEZH}u CH[]A\A]A^A_1111fD  H9   LHLHߺ:   H1[]A\A]A^A_1111@ A   DeAn    HtG1     AUATUSH(dH%(   HD$14$D$    HtHHHItu01HT$dH+%(      H([]A\A]1111    H{'H   L-x H<       LRHD$Ht`H{HH5%H{LD$~1fHD$LH<H9\$H|$   L>   >@ H{*D  H(dH%(   HD$1HH$H.HD$    t,HD$HT$dH+%(   uH(1111f.     1    AWAVAUATUSHL$H  IHAHAYQ  }    AHD$!t	D9  LIGMHE؀; tgt$HDIII)H   LHL   :T$   EuAD  D9  IHkHID}    t$HIHI)HtELHLuLHDLBEuA     H(INHI +\H$v L  H=u {1Ҿu   1   @}I}H1[]A\A]A^A_1111E1E1     [Hu 7  H=<u C{1Ҿ 1   |fD  I}HD[]A\A]A^A_1111E1E1    D$_[HXu R  H=t zH1IUDL$Ht Lv      _|XZD$[Hu f  H=t zL$E1Ht     | AWHK     AVAUATUSH8dH%(   HD$(1HtLHHax=t@HD$(dH+%(   N  H8H[]A\A]A^A_1111E1E1@ 1@ 1   ܴHڿ   H5}  (Hڿ   H5)  迅Ņ~HD$E1L|$ HD$Lt$Ll$+      HT$ H1  AD98DH|$LMI1LD$    D$    D$    HD$     ot$tD$tHT$ Hف  t|$  D  1	  w@ HHED 1  t$J1ATIUHSHHtNH{}u1[]A\111fLHHH{[]A\111f.     1HHuff.     @ Ht+UHHSHHgHHH[H]S 1111    HAVHAUAATIUH	SAH   HEu
H{Tu E1[]DA\A]A^1111f     LHHAƅt#H{[D]A\A]A^1111fD  HLHDH{Af     1HH[h     Ht+ATAUHHSHFHD[HH]A\11111D  AVAUIATIUSH@dH%(   HD$81   ufMt1HD$8dH+%(      H@LL[]A\A]A^\@ HD$8dH+%(      H@[]A\A]A^11111D  LHKdLHeH^H   H¾2   H>HL*     蛢1LHAcDLH
f.     SH7HHtH_H11[D  [11111@ SH7HAHtHԣH11[ED  [11111@ Ht[SHt[111f.     HH5SH{藼H{.H[  H5n A	f     111f     Ht' 1ff.     fS      H5Rn HHt9|HCHt+H5H=pHCHtH[111@ H1H[111 HHtHf.     Hu 蒺Ht
   H1ÐH=D  a   H1     AVAUA
   ATUHS?0tbE1Ef0D9s-MHcI] H?  u۾     u[L]A\A]A^11 A  X@ /  xtHA   HA   uff.     @ B5% t111    AUH=n ATUSH5%    HH   (1@~@HI@~   L-_% :   uaSHtT:uk1@~H|@~   IEDLH AU AEH[]A\A]111@ IE    fD  L-)_% LA  I@ L-_% L)  LHH!A   tOII!;fA~MfHnffAE\fD  L  ID  If.      H   Ht$(HT$0HL$8LD$@LL$Ht7)D$P)L$`)T$p)$   )$   )$   )$   )$   dH%(   HD$1H$   HHHD$HD$    HD$HT% $   H D$0   HHD$dH+%(   uH   11111E1E1D  1ff.     fHHH=l 1v[fD  1wHcHl x11ff.      01	1fA11fa11fO B111f     O B111f     01	1f 0f.        f.     1ff.     f   f.     HR      HR      	   Hm HcHD  Hl 11@ Hl 11@ Hm 11@ H  "HHl HtH<1% H11 H	l 11@ HYm 11@ HYl 11@ Hl 11@ Hl 11Hk 11     USH(dH%(   HD$1   ~#1HT$dH+%(   upH([]111@ Ht$H[N  tHOV  tHt$H>N  tHD$H9D$tˠ   HHc;S  눐   4@ t21     HAuDHɋ   HEщR  @    R  ff.     AUIATIUHSHdH%(   HD$1D$    x8~*1HT$dH+%(      H[]A\A]1111Ð[R  tHOR  tHT$LHAԅtD$t1   H3R  tHU  t      HR  oH/Zff.     fAUIATIHUHSHdH%(   HD$1H$    MUHXILHHcHKHHȃHHHH%   AE M  tH4$HtHt   HT$dH+%(   uH[]A\A]11112fAUIATIUHSHx(~H1[]A\A]1111D  P  tLLH1U  tˉHH[]A\A]1111     ATAUHSx!~1[]A\111fD  cP  tHWP  tEu>H6S  uǺ      H@P  uHb           HP  uzD  AUIATIUHSHx(~1H[]A\A]1111D  O  tLO  tHLLT  tLyR  t      LO  tLff.     HdH%(   HD$1D$    tHD$ HPuHT$   HT$dH+%(   u
H1111ff.     HT$HL$HH1111f.     HtSATIHUSH7t[1]A\1111@ Hhu,Hى[L]HA\@ 11111D  [L]1A\X     UHSHx"~1H[]111D  N  tHM  tHP  t˺      HM  tHff.     fSHx~1[11 M  tHM  [11f     USHH(dH%(   HD$1Ht$;H  u'1HT$dH+%(      H([]111@ HP  tHt$HG  tHD$H9D$t/   0   HL  tHD     HG  l̾f.     fff.     @    f.     HHH9t-Ht8HtKq19pt
ҍT1111@ 1҉1111    1111     1111ú7   H5f 7ff.     @ USHcHw*HH?HtORCtFHHD[]111@ FHg #   H=kf ;f1Ҿ 1   gH1[]111f     ff.     @ SH1HtsHH[1ff.     AUATUSHaHtIIHXL   H-    H;HH|HC    L9uI} IE     H[]A\A]111fATAUSHtEDHHIHt/xH8=9|71H;[]A\1111fD  1[]A\1111    I<$eHtH
H   HH(H
fHnfHnfl@ff.      15D  AWAAVIAUATULSHH$LD$H  DHHIHx  H8    L=bd    0   LuIH1  L0H$1Il$(I} ID$HD$ID$HD$PID$ D$XAD$tDI} 3<I} LhzH;*H[]A\A]A^A_1111E1E1 DH<d    Lc1Ҿ  1   e   LLD  ;IE HHt1hI} 'IE     CHc    H=2c c1Ҿ  1   dD  SCHc    LffD  Hj AQMIHH1H1111E1E1AVIAUAATAUHSH:HtgDHHHtTH8DѐH;I趾IEHt5MMME DHL1[   ]A\A]A^1111E1E1@ [1]A\A]A^1111E1E1ff.     @ AUIATAUHSHHH   :D9~bfA9|XH}1͏uBHa   H=a |a1Ҿ  1   cH1[]A\A]111fD  H}LD1xI9uLH   []A\A]111fD  HEHHKvAHOa   mD  [AH4a   H=a `1Ҿ 1   pbRff.     USHHHHt89~H{H[]fH1[]11 AWAVAAUATIUHSH   HT$dH%(   HD$x1HS  DHHIH9  I,$H8ID$    d8T  	   Hl$ HHl$HD$E1    I} DMIJD M~L9|$uH;1D  HHD Ht.Hx t'L:JL\ LH|$HMKMASHCI9uHD$H9      q    HL5j_    H<    LHD$uHH   H;聻|?H_    L^1Ҿ  1   `D  1HT$xdH+%(   uXHĈ   []A\A]A^A_1111E1E1E1 H;1   H5^ H"/HD$ HD$HH1AWAVAUAATUSH   H:dH%(   H$   1Hz H>p  IHHD$IH  DHqHH  H8M6H{AA6A9ANŉD$Aƅ[  |$	  HD$0Lc|$HD$IE1 H} DKIM9uHD$1H8Dl$LADHDLH>HL$(HL$,  @ HAGHD$(HIHt-LP(Mt$LHL HHT$LA҅   HT$(DLHΔL9u   HL$I9t'O  H5\ LD$ZD$	@    H$   dH+%(      HĘ   []A\A]A^A_1111E1E1E1f     I?ظH\ IEt<H\ 7  L@\1Ҿ  1   ]D  1n15f     Lc|$H/\ -  HIJ<    <IHuHD$H8GyfHD$0HD$<ff.     AWAVAUATAUSHH   H:Ht$dH%(   H$   1H   DHHIH  H83D$  HcL$HL$HHL$0HL$ HL$	  L|$E1MfI} DI耉EgAIGD$A9uH} RLd$L|$H
   LLI]Mf.     I.Ht-H}  t&AvHEEANLMHLE H|$HU IM9uHT$ H9T$tH5Z H|$  H{GfH$   dH+%(      H   []A\A]A^A_11111E1E1    H|$H5Z   Ht$(H1HD$HH} :Ht$(HD$    X    H} H5Y f     AUIATAHUSHH!DHtH   []A\A]1111@ HHL[D]A\A]fD  H1f.     tf.     UHY    SHH'F% H-`% HL@H1H=T æHt(HHu   HHY H)H<(1趐=%  H% u6Hߺ   H5Y Hs% H[]11111E1       H5' Hlf.     SH5(H=% ZB   HdY HcH H) [111f     H,Y [111ÐHI% 1: tHB	[111fD  H)Y [111ÐH% [111ÐHX [111ÐHq [111ÐHE [1111[111    %    D  %    D  r%    D  Z%    D  B%    D  H%    H     H@%    H     H7t%       % H1    HH=% 0% H11ÐH1% H11fD  Hgi%    H     HY%    H     HGA%    H     HWz-% H1f.     HH=$  % H11f     HbH% HHt_bH% HtG  t91H=% K6t'%       % H111    H=% H=% H%     1Hx%     ^% H111ff.     @ 
B% t
h% t11111ÐUSHH%    H,% Ht*H-V      HH[w  H"HuH=% H%     H=% H%     H=% H%     >I% ua, G}'- 
  qij /aw54p  >%     H[]11111D  f     AVAUATUSHHdH%(   HD$1#% t   k  1  @ IL-% I1LLŅtH$   H!H9  H5H=% h=t% t   f  .       H5H=L% '=d5% VH5H=% <;-% -W           B     f  Àu  @    R  x    H
% LHLnn2HS   H=zS R11Ҿ    S19@ HQ% LLvCH$H!H9fD     HT$dH+%(     H[]A\A]A^1111E1E1E1E1fD  H5H=% ;nH5H=% u;Dr% E~1sfD  H5H=R% =;zD:% EO1;fD  H5H=% ;BD
% E 1fD  H5H=% :
D% E1fD  H5QH=% :=% 1     H5H=b% ]:5K% 1]  1I@ H5H=% :R
% b1     H5H=% 9=%  =1H-% HaHHHM   H=% /,H5H=a% L%R% ]9   H=% 1H5% 耫1Vf     H5	H=% 9Z=%  1H5H=% 8+=%  `1-<XH=% 1-% H% 1H5H=% 8-d% fD  UH-O   SHH   HnHt)H% HH% HP   H[]111f[.HtO   HM11Ҿ     tO1UH-lO ;      SHH!H2% H   HyHH% ZHCH% H8Ht'Hx    t% H[]1111fD  ;H% Hx蛻H=% D   HH%     1҉% H[]1111D  ATH5'IH=q% US7t%\% tH-Y% HtH}1)u []A\111fH} {I9t H} $9|H}[]A\ H} H}[]A\Ȩ     AWAVAUIH5ATUSHH=% HY6te% t[L=% MtOI(tBMu 1@ MtI~HtJH9tELMvMuIH[]A\A]A^A_2fH[]A\A]A^A_1111f     AVIVHt+HUMfLY  H50M Mw    IU fSHHt
H1HUH[   H5L AWAVAUATAH5^UHH=% SH95$  %   L=% M  E  Hg%     I?D$    #9D$   D  I?t$$yHH   L0E1MtGIVEuI9.tHtMMIHRI9.uLMu{HMv  H5L MuEt  H5K HI?D$"9D$fIEu\xH   []A\A]A^A_1111@ IUEtOH1[]A\A]A^A_1111I&I?褩  H5LK L(I HH5H=$ I*H11     H   1H=y$ ԮHi$ H111ff.      H=H$ u1111D  UH-0$ SHHÜ1HHVHt
H1wHHHߺ   [H5_J ]=D  H=$ u111    SHH=$ XHHtH[    [111     H7HHff.     AWL=I AVL5^$ AUIATIUHLSHHHtS  L    9H   L`H(HLhHPHH   []A\A]A^A_1111    d   L   HHtkHL   H5H=
% 1t'% tH% HtHzH$!$u=1L賾o   LH1H[]A\A]A^A_1111f.     H$HH:HT$uHT$$HzK$fD  h   LHP1@ 1yf     H$ H;$ tfD  a H$ H;$ tfD  Ht#$ t
$     Ff.     1111    L$ L;
$ HHt
HA@ Ht3HtHfD  H1H1111E1 Hff.      $ t6HtH=
$ HtH5$ HtH$    111fD  111f     Ht
H$ HHt
H$ HHt
H$ H1111f.     SHwHHtH1H2'HH[1111fHtCATAUHHHuHDH]A\o    H|$FDH|$    1111ff.     @ AVAUEATIUHHSH   HHt{H9rNDHIHtqHHH%DLHH~[L]A\A]A^1111E1D  H)IHHC[L]A\A]A^1111E1DLHB~E1D  [D]HA\A]A^%D  HL	% 1H={	% IH)I   HHH	% IHID1D΃Is,Lk	% AHrHHHHL!IHH1111E1E1E1ÐH   HHHcH;% }sH5% H+% HHVH   A   LHH1HHtTH;
% sKHȃHH0HHrJID	H11111E1ún  H5lD H=D Pq  H5TD H=
E mPr  H5<D H=*E UPo  H5$D H=D =Pff.     fHH% H9   H% HH9   H% H9rbH
% HH9sSHHHt2H9rsH9snH~H9xu|HpH7H11111     H~H7H11111ú{  H5iC H=D Oz  H5QC H=gD jO  H59C H=D RO  H5!C H=D :Of.     H   IHcH;% }tH5% HH+% HHVH      HHH1HHtSH;
% sJHȃHL0HsLH!@8H11111E1úb  H5nB H=B Ne  H5VB H=C oNf  H5>B H=$D WNc  H5&B H=B ?Nff.     @ HxsIHcH;% }bH5% HH+% HHVHuu   HHH1HHtEH;
% s<HȃHHA H!1111E1úW  H5A H=A MZ  H5lA H="B MX  H5TA H=A mMff.     fHHtHWHPHWHHHt(H@H% H9s)H% H9r8H% H9s,11111fD  H
% HH9s11111P  H5@ H=B L@ H% H5% 1H=% H+=% HHHHH9r6HH=% H u+HHHtH4HsH1111HL  H5,@ H=B ELD  H	% ATUSH9rDL%% HLH9s2IH
% H߉Ht-L[]HA\1111ú  H5? H=@ K  H5? H=)B Kff.     H  AUATUSHHHc% H9  H[% H9  Hf% H߉I1  HR% DHH % HJ<       DH]H9   H
% DHE  H% DHHH% DH   H% DHIHHH9HfHCHGD H% HQ   Hj% DH7H@% HJ,H!H9] uNDHE}HH	H[]A\A]11111111ú  H5= H=@ I  H5= H=@ I  H5= H=@ I  H5= H=@ I  H5= H=z@ I  H5l= H=? I  H5T= H=> mIff.     fSH=8% H,= D  HH=5% E  HH=)% F  HH= % HtH5 % Hu3f[) % ) % ) % ) % ) % 1111f苣f      % ATUSt1ۉ[]A\1111E1E1 HHGH % Htf)6 % )? % )H % )Q % )Z % H  HKH!  H  HEH  1HH$ HH- % HHH % H  HHHuH; H=$   HHeH$ Hl  H=$   HH=H$ H0  H=$   HHH~$ H     FHHW  L$ E1A"   1H5$    LH5$ H$ H   H$ H<(1H=$ H5$ H=$ H=$ 1Hb1HH$ I|HHH!H=y$ 4   E  H{$ H5j$    H1dH   H5S$ H=D$    zx$       H؉[]A\1111E1E1Ð   	fD  H=4$ 蟦H$$     ]    A            ;H5$ H=$ 8&t
   ZqH5$ H=$ ?ٺ  H59 H=9 E  H5h9 H=< E  HH=j= mE  HH=.= YE  HH=< EE  H59 H=< -Eff.     fH=8$  t11ÐHH=$ $     q   H$     H1f.     $ f     AWAVAUATUSHH$ A  H=$ M  H9^$ 3  Ha$ LpH^$ H9sf     HIH9rM  L=$$ L    H  IHt  IH$ L$    H  H$ HHH$ H;
  HH$ H߉  H$ HIoL=x$ HMLZI;]  HR$ Hq$ HHH1M  HJ$ HL=!$ HMLI;$5  H$ IۉHHI)MI9(  L9IH$ HJ  H$ HHeH$ H99  H$ H9)  fHVH=$ H$ HH[]A\A]A^A_1111E1fD  H[]A\A]A^A_11    1빺  H56 H=I: $B  H55 H=: B  H55 H=: A  H55 H=q: A  H55 H=: A  H55 H=: A  H5{5 H=9 A  H5c5 H=: |A  H5K5 H=: dA@ r$ uSff.     R$ tH$ 1H9rH$ 1H911@ H   ATAUHSHլtIH=$ tQHHHH[2H)-$ HH=$ []A\,@ DHH[]A\>fD  []A\1111 1111    H   AUIATAUHSHH,tPH=Q$ ,thHHHH1H)-;$ HcH=$ H[]A\A]}D  LH}1HDHH[]A\A]}D  H[]A\A]11111 11111ff.     fSH=$ 16tH=$ H$ H[1 U1SHHH=n$ ItH
H=V$ H辍HH[]1fAUATUHSHHHAHA	[IE        HHtAH8iXHt|HpH  Hx_HHH[]A\A]111         јHIHt@H~PIE HH8HuA,$HKH    A,$1@     1A$   1f.     USHHt+HHHt H8BH;xKt   t
U    1H[]1@ Kf.     f.     D  IIDHE   K@H   HDMtIHthI9   NH
7 MuJ HHI9t2G@tH@wHI9uAH    1111E1E1E1E1@ KD WfD  HH7    H=b6 .11Ҿt      01H1111E1E1E1E1f     Ht[ATAUHSHJDHHxHt%HH誎[]HA\H111f     1[]HA\1111111    H   USHHHw]HHHuHHtHHH[]ܸ@ sHD6 <   H=V5 -1Ҿ  1   /H1[]1111    11111D  H7HHu
/fHH9t8 uH)111     HH)1111111f.     Ht{AUIATAUSHH}DLHxHHt,HHH( HH[H]A\A]1111ÐH1[H]A\A]1111     11111D  HSHHv\Hr1 HHHHHH9t!uHuHH[1111H  HHH[11111 S1HHu3 HHH9t#? uHHH)谅H[111D  1虅H[111ff.      0@6w@Hw3 81AWIAVAUE1ATUASHH4$HT$teHq9   yLq@   AD	   IMtL9,$   ID	AGLuH|$ tHD$L(H   []A\A]A^A_1111E1@ HY     {H<3    H=^2 *11Ҿg      ,1H[]A\A]A^A_1111E1@ +H2    H=2 *11Ҿf      @,1@ 
H2    H=1 k*11Ҿt      ,1sEg    AWAVAUIATIUSHdH%(   HD$1eFH   HL=g1    LHH>IH   DMtaHLHHI$    H$    tYH$I$HD$dH+%(      HL[]A\A]A^A_1111E1 HLHHH$    u   LLE1fD  	HT1    H=0 #)1Ҿy   1   *fD  s	L   H1 (1Ҿ  1   *UD  :   fD  E    H   AWAVAUIATAUSHHudL|6L5/   LLHHtx1EILLHqt-HH[]A\A]A^A_1111E1E1D  L<vfH  L1覼@   H5b/    rf[  L1H/ '1Ҿ  1   r)pff.     f:   fD  H藑H111@ ATIUHS@ H} t} IiA|$\)t؉[]A\11ff.     fAUATUSHHtQHIL,D  H} t6I9t1} IA|$)tH[]A\A]111H1ۉ[]A\A]111f.     HW)QΠELcHIHHSH?H
H)iG  iʀLkw<=Q    H-Q DWD_AJHcHi*H!)΍    )A3,  i۵  ETEio  IcAHiɫ*H!D)хDSDIADE3  IcAHiQH%D)DvEArAI)O1K}  HcHxI	   A [1111E1E1E1E1f.     HQ f.     SHYHHE[11f.     SHH dH%(   HD$1HL$LD$iu5HT$dH+%(     H [1111E1E1E1E1    HD$H Hbȼk9H    HHH?HHH)Hiѱ: HBHHIHH)Hn[|H~Hi  HH?HH)IHiҵ  HHBHIH1kdHH)HtZzHDLIIM1I?HHL)ߍ9  H[ALcL$KIIiɉNIkH LLDL)EˍTSDMių)Dk<AI ADE)Lc)MifAnfnI AAE)Ek<D)Li	  HgffffffffnfbII?   HI)AfAnfbflzff.      ATIUHH1SH1H dH%(   HD$1HL$I;u/1HT$dH+%(      H []A\1111E1D  11HL$LLD$tHD$H+D$T$+$H~(y$HQ HtE Ht   |Hy~HQ yfD  HtcHt^UfH-* SHHO0HwHHW k   H    G(   y   HC(Ht#H[]111@ 1111    3HL* l   H!1Ҿ  1   L#1     UfHVHSHHHw       HHЀc0fH-) k   HC H(   C贙   HC(HtH[]1111D  {H) l   H 1Ҿ  1   "1UfH-*) k   SHHHO0HG G(   '   HC(HtH[]111f.      H) l   Hg 1Ҿ  1   "1HG(Htp    11f.     111f     HG(HtWHH HuHJHQHv1H;wr	Hw    1111f   HH1H9r1H;wsԐ1҉1111 HtHGH   11f.     111f     HW(HtHtHGH+BH   111 1111ff.     @ HGHt'HWG0u
H11D  H)HG 11@ HHtH@Hu11f.     H(    ATUHSH   HG IHWHH)H9rH?Ht;HHH)H9s-H9HBHHxH4    H9HB=Ht<Mt'H/I$HtC0tH)I$f        f     1[]A\1111Ð11111D  UHSHHtoMfHnø   flfEH[]111 ATfL%)& k   UHLSHHdH%(   HD$1G(   !HC(Ht`Hu+   HT$dH+%(      H[]A\111 fHnHHHfl@-tIHC(H@     H% l   L11Ҿ     1wD  H{(w   L臱HC(    1R[tff.     LIIHHIw       HLMt*Ht%H9LGHGЀg0H    HW fD  11111E1E1    HHHtEHRHHHG    Hw       HHЀg0HG :f.     11111D  1f     ATUSHdH%(   HD$1H(   HHH   G0  L%$ b  (   LH   HS(fHnHHHHSHC(HL fHnHHHfl@:HT$dH+%(      H[]A\1111D  L%w# b  (   L菓Ht*HS(HHSHC(HPH@    H@       KHD# c  L1Ҿ  1   d@ 1W$r@ 1f     USHdH%(   HD$1Hv$1HT$dH+%(   uiH[]111D  HHHHtH$Ht2HD*HtH@ HHH9u1H       tq@ AUATASHHHGHH+sutS   tcE   HWHH+KH;KuoKfHnfHnflfmfGfCH   H5! HG(HGD  HSHtWHGH   HKHHDHH)@0HHH9uHuiEuH   [A\A]1111    G0tH; tH   HHt`A   @ IHuLH<$2H<$ujH1[A\A]1111fD  HHqH@Hd8   Ht$H<$tHt$H<$H5A   fL@΀   H<$H<$pf.     C tD  USHH_(Ht"H@ HHt 1HHuH1[]111H   []111ff.      Hw(HtH> t       1111    Hw(HtH> t1111     S   HH^u
1+fD  H{(N  H5 D$迫HC(    D$H[111ff.     @ ATIUHHSHu[1]A\1111     LHHtH[]A\1111ÐUSHdH%(   HD$1Hu%   HT$dH+%(   u9H[]111 HӉHH0tH<$HtHډYmfUSHdH%(   HD$1Hu%   HT$dH+%(   u;H[]111 HHHHtH<$HtHH藠@mATIUHHSHu[1]A\1111     LHHRtH[]A\1111ÐUHSHHHtG0u9HHNt*HE HtHHE H   []1111fD  H1[]1111ff.     @ 1H? t1D  1H 1 ATIUSH_(Ht(H- f     HH  H5HuID$(    []A\111@ AWAVIH5 AUEATEUH8   SHcں7   HHL$ȌH   L0H|$IDhHX,  EgIGEu:HE H}L:B~:HL[]A\A]A^A_1111E1E1fD  HEH}L BƺF   H5h LPE1 H :   H=@ 1Ҿ  1   0ff.      UH- ]      SHHыHt<H4eHCHtHH[]111 b   HH谧     1ff.     HtsAUL- ATUHSHH>Aą~(1D  H}>n   LHLA9uH}rHLH[w   ]A\A]$@ 1111ff.     @ SE1ɉA         Ht X0   [1111E1E1     1[1111E1E1ff.      SE1ɉA         uHt X0   [1111E1E1     1[1111E1E1ff.      SE1HA         HtHX0   [1111E1E1fD  1[1111E1E1ff.      SE1HA         HtHX0   [1111E1E1fD  1[1111E1E1ff.      SE1ɉA         UHt X0   [1111E1E1     1[1111E1E1ff.      SE1ɉA         Ht X0   [1111E1E1     1[1111E1E1ff.      SE1HA         HtHX0   [1111E1E1fD  1[1111E1E1ff.      SE1HA         4HtHX0   [1111E1E1fD  1[1111E1E1ff.      SE1HA         HtHX0   [1111E1E1fD  1[1111E1E1ff.      SE1HA         tHtHX0   [1111E1E1fD  1[1111E1E1ff.      SE1A         fH~HtHX0   [1111E1E1@ 1[1111E1E1ff.      AUIATIUHSHHH   H)+   H)PI  HcH9      HE1Ƀ   AHHDA   HىLL=Ht]Hh    H[]A\A]1111E1E1fD  HT    H=  s
H,  1   1    E1u     H    H= #
11Ҿt      1Zf     kH    H= 11Ҿs      1f     AT1IUHSHHtHHIHcHL[H]A\S] AUIATIUHSHHHuH(HHwQHHKLAA   LHtZHh(H   []A\A]1111E1E1     kH    H= 1Ҿp   1   
H1[]A\A]1111E1E1D  ATIUHSHHHuH'HHw?E1A   LH   HtQHX(   []A\1111E1E1D  H   H= +1Ҿp   1   [1]A\1111E1E1 AUATUSHHw]IHHIH詄A   HىALL@Ht[Hh(H   []A\A]1111E1E1f     H   H=  s
1Ҿp   1   H1[]A\A]1111E1E1D  SHw>HE1HA      HtPHX(   [1111E1E1    cH *  H= 	1Ҿp   1   x1[1111E1E1fD  AWAVAUATUHSHxHdH%(   HD$h1HH<HT!  HHE L$    HEHHD$ J  L= p  HL)HD$H  v  LLmHD$HQ  H}Ld$aM,܉D$)  Lt$19     LM4I|$LI MtlHLP7I(9\$   H}$7HH HQI$AIT$AD$qID$ HquLMl I|$LI Mup    HM  HtHq0I(9\$kf.     Lcd$H\$KHH|$0T>oL$0HT$ HHt$oT$@SHD$PHC &!  fH}E Å~)E1@ H}A3n   LH#D9uHD$hdH+%(   .  HD$Hx[]A\A]A^A_1111E1 HA(H@ Hq(HL$(HtRHL$(Hǃy[HA NfD  HD$    L=  1	$@ 1HL$(H    H\$)H x  L1Ҿ  1   BH|$y  L HD$    Lr  Hn Y1Ҿo   1   ]f.     D  SHHHt[zf.     HHu   [1111@ H[D  SHHHHtH[{     H8Hu   [1111@ HH[@ SHHHHtH1[ffD  HHu   [1111@ HH[2@ UHLHSHHHtHHL[]h     HHuH   []1111E1@ HHHH[]$z@ UHHHSLHHtHHL[]xU     HHHt 1H9_s8H[]1111E1fD  H   []1111E1f     H_HH[]nff.      SHHHHtH[(     HHǸ   Hu[1111ÐHn[1111fD  AWAVIAUIHATIUHSHMtiLc1ۅ6>fD  L2HtHt HL   HI9t
H|  uH   []A\A]A^A_1111@ Lc1ۅAD  L1Ht LIHtMtLHmtHI9tH|  uf.     H1[]A\A]A^A_1111    ATIUHSHH9rvH9t9H2DH
@ HH9t:t1[]A\1111E1E1fD  Et	1D2D5xHLH$[   ]A\1111E1E1@ H)H<HAEHHLD  USHHHW HHtZCHA   t,t$1Hk H[]1111E1E1f     E1HHsE1HtHk뿐H   []1111E1E1fD  GIHփt"tE11111E1E1E1f     HOHWA   LDD
AEl@ HOHWA   E1LOff.     @ USHHHW HHtZCHՃtot"1Hk H[]1111E1E1    | xHHHsE1E1tHkfH   []1111E1E1fD  DDHHHsA   AEff.     HHH֋Ptt:11111E1E1f     HHHP|
 xE1E16fD  HHHPE1E1ff.     fHt[UHSHHt=H7HHuHs(H(HtHSuHHH[]11fD  H1H[]11111f     ff.     1Ht
1H 1ff.     Huf     HG H(H? u1ff.     fo	 H7HG   HWG111ff.     fo H7HG   HWG111ff.     fo H7HG   HWG111ff.     fo H7HG   HWG111ff.     Ht[HtVGt   1҃tn1111 HGH   Ht,   rfHG    f1҉1111 HG   1H HH u]    HuHG f/ u
 f/c,f*f.zt1f     HG    0fD  HGHJH4HG1H H=f     ff.     Ht$HtGHG     t#t^   1H1111fD  HGHG    Ht$HWH   HuEHcT$HG    H   @ HcD$xHWHG    HtHOHt|HtfHt$   GH1111f.     HGHG    HtH?f*D$ vT$jD  HG    HUNf     ff.     fo H7HG   HWG111ff.     H   H   Gt   1҃tF1111 HGH   HutHG1H HH ủ   f     HuHGf f/r
? f/rH,fɉЉH*f.zt1҉1111f   fD  HG      HGHXHG1ҋ `'ff.     f{ff.     Ht$HtGHG     t#tf   1H1111fD  HGHG    HtoHWH   H   Ht$   H1111 HWHG    Ht'HGHt}HuD$HG    H        cfD  HGHG    HtH?T$fH* L$HG    H    T$렋D$+ff.     fo8 H7HG   HWG111ff.     Ht{HtvGttA1҃~   111D  HGH   HuLHGH H    HGH   Hu$HGH Hy     1҉111D     fD  HwHG f/ a
 f/OH,fH*f.z^1    HGHc G@ HG 8ff.     fKff.     HHt$HtGHG     t"tU   1H1111D  HWHG    HtHGH   HuFHD$H   @ HD$HxHOHG    HtHWH   H   Ht$   H1111f     HGHG    HtH@HL$HHHHH5'fH* Vf     HL$   HH HG    
'f.     H     H9HG     ff.     foX  H7HG   HWG111ff.     H   H   Gt   1҃t61111 HGH   Hu|HGH H    HuHGf f/r
_ f/v
Y f/   H,H   fH*f.zt1҉1111    fD  HG pD  HGHtHuHG1H HIHG1Hc 2f(\H,H?aHHfHH	H*XRf5ff.     HHt$HtGHG     t"t]   1H1111D  HWHG    Ht HGH   H   HD$H        HWHG    HtHGH   Hu[HD$HyH     HHG    YHD$HH5GfHWH*vD  Ht$   H1111@ HD$HH HG    0    HD$H=D  kff.     foH H7HG   HWG111ff.     3ff.     ff.     fo H7HG   HWG111ff.     ff.     Kff.     fo H7HG   HWG111ff.     HtHtt1111    SHGHHwHZ)HtH   [111D  1[111fD  H   UHSHHHG     Htt1H[]111f     HuHHs@Iº   HHHDHC Ht3HSH9rHS H    1111       pfD  H7HG   HWHOHG 1111f.     HHt@Ht;Wt   1Ƀt311111HuHWMD  1ɉ1111 HWH   HuHWH2HHHHH5ufH*@     D  HWHt.HuHW1HHH5_fH*    HWfH*    HWf*fH   GHG     tw      H,fH*f.      HOHG    HtRHWH   Huf/ ru
h f/vg   D  HGHG    HtHuE    111     
  f/szH,H   fH*f.zt1111f.     HOHG    HtHWH   Huff/r
 f/vHg f(\H,H?tHHfHH	H*Xd    f/ W
 f/E,HG    D  ff/
z f/
H,HG    ff.     fo( H7HG   HWG111ff.     H   AUATUHSHHt	HtH1[]A\A]111f     H LotH> ItlM9rHsH} LGxHsL9s.HE 0 H   []A\A]1111111    H{w=HL9of     Mec  H5 LXHCHE jfD  HH	txAUATUSHHHtt1H[]A\A]1111 LoHIHtL)H{ tHtH}  t3M9rH} HsLNw       11111D  IMc  I H5D L葀HhHE fHt{ATUHSHHG     Ht$H\H{HC IHt6{uH9Cs[1]A\111 HHvL;cs	HCB  [   ]A\111fD  1111    HtHt&HGHW HtQuH9Ws%1111@ HG     1111    HHv   H111@    111ff.     ATIUHSHHtHuHQHL#HC   HkHKHC []A\1111@ H7HG   HWHOHG 1111f.     1HtHtt11f     HGH H   11ff.     1Ht1Ht,u&HtHGHHGH H   111@ 111ÐHtKU1HSHHHG     HtHHHC 1{uHCHtH(   H[]11111f     Ht+HW u!HGHtH0   111f     1111    H7HG   HWHOHG 1111f.     H7HG   HWHOHG 1111f.     fH    HG    HG    G1ff.     UHSHHt   H[]11 HtHt{uHCHE ff.      ATIUHSHt   []A\111f.     HtHt{uMtHCI$HCHE f     HH0HH8|ff.     @ HGH1D  AWAVAUIATUSHH? 5  IIIH   @ AoHHE AoOIH{MIW H}HU AG   IWIwHT$arAHT$   HzXHHCH(MtA$I(I?    IaMbAWJvVHIHIuRHHC@ IGH H   f.     Hk H   HIf.     HHH[]A\A]A^A_1111 H    HWHwG   111 AWAVAUATUSHhdH%(   HD$X1D$   H=  Lt$fHL$1L)D$HL= )D$ )D$0)D$@HcD$H<HLl$ '   LIIILj^HD$HH   JLl$(HD$HD$@HuQLHH1HT$HHt$0HHD$XdH+%(      HhH[]A\A]A^A_1111ÐL$    '   LLHD$0HtFLd$HHD$8fH )   L'1Ҿ  1   1nD  sH )   L1Ҿo   1   Hߺ   Ldy1&@<AVAUATUSH   dH%(   H$  HH	  H  1H? Iu   H   tHI|H(H? uH    H;  H> 1  1L$  D  H   .  HItH(H> uHǄ      L-H޺   LL6L   HLw6HD+   H H<HH6\IH  H$LHu3{@ IIIoSoX[H@ HCI$HtJIH   H2H8H((wt~jIIo0sox{H@ HCI$HuIHtyf     o IH(CoHKH@ HCIHuED  I$Io0sox{H@ HCFf.     H$    Hu{E1H$  dH+%(      H   L[]A\A]A^1111fD  I$Ht    o IH(cohkH@ HCI$Hu@ 1H> Iq@ HǄ$      1L$  HǄ$      OH߾   H@ 1Ҿ  1   h.9ff.      HtKUHSHHH? tf     H(H8 uxH- t)HHHߺ   []u 11111D  HpHx   H@f     AWAVAUATUSHH8dH%(   HD$(1HD$    H   HH   D"ILMAhuDbAeO  HIMt1MAM   AG       H|$LEs  f	H|$tbHt]AG    MAHcu
HJHDIoHL  H   HHEH`fD  H|$v1HT$(dH+%(   *  H8[]A\A]A^A_1111E1E1    EtbH   HEL5D    LXIHv  HL$HH"     DbHBAxHDf.     L   HHHEt蠿H |   H=    11g   H|$  fD  L5       LOWIH  H|$1AoLKHkHC ?u   D  E  LHhL5    HLVHL$IHC  AG  wD  LHωLL$H$AH$LL$   H|$H@   E   LHT$ LHA:   L$HD$     LH|$L$RtH<$   L9r@ z  H|$?{  AGH|$D  LHL"hI<HL$>L$$I)L HH9u
     {H    L   11  H|$f.     H    H9D*H h   H=L    11t   ?H|$D  HD r   H=
 c   11  H|$KfD  H|     LHLHnIH|$IUH|$   H|$[H >   H=}    11z   pH|$13SHHw(   H H HC     [1111ÐHt+S?Ht2HfCC [1111Ð1111    HwH   H: wD  AUATUSHH}   IHtuHHz   Hu?L- -      L&oHCHtuHk   H[]A\A]1111ÐL- ,   HLL6@ H &   H= s11Ҿ    1@ úHl /   L?11Ҿ     1aD  ATUSHt7HHt/HI      HkLc[]A\111fD  KH :   H= 11Ҿ    `[1]A\111 ATUSHt7HHt/HI      HkLc[]A\111fD  ˹H4 H   H=V C11Ҿ    [1]A\111 ATUSHt7HHt/HI      HkLc[]A\111fD  KH V   H= 11Ҿ    `[1]A\111 O   1@ g   1@ AWAVMAUEATIUHSHH8A   AAtPIq HtGIA(H9LHGHcH+   H8[]A\A]A^A_1111E1E1f.        HMFHLAVŅ   AFtI~ HIv(HtH9s,L- HA(  LHH>  IF HL\bHIV  HIF(LD  IqH  H5 H$IHt
xuVLxA~  }   蘷H   H=# H.  1   1[H    1H= H"  1   i@ IFIvHD$    HD$HdHHt$Hx  Mo  Ht$HH$X  H<$HD$HtH<$HH<$LH5m HMHD$ HL$HW  H|$L=    LvNHD$H  HL$Ht$ E1AH<$   hD$,  E\  E1H<$xO  &  t$,H<$9  HcHt$L   H9`f     Ht$LL   Ht$H|$L   H|$    LiH<$i\H|$&f.     kHt    H= 1Ҿ    11~H|$    I~DHIFHt$HD$HH&   H= u1Ҿ  1   12 H|$   LLIH  HH   At$ Ht$0E1H|$UZYZvH    f.     L11Ҿ(  1   nfD  IA|    #L=    H  L1E11Ҿ  1   0HD$    f۳H    jf.     軳   L1H 51Ҿ	 1   D  胳H    bfkHt    H= 1Ҿ      ;   L1H: E11Ҿ(  1   O:f.        L1H u1Ҿ(  1   H3L轲H .  L褲   L1H 1Ҿ  1   fD  HxAIHcdH%(   HD$h1HL$HT$fo H[ HD$    HD$H D$(fD$   HD$8    D$@    HD$H    HD$ )D$Pt'D$HT$hdH+%(   uHx1111E1E1ø(@ HxAIHcdH%(   HD$h1HL$HT$foQ H HD$    HD$H
 D$(fD$   HD$8    D$@    HD$H    HD$ )D$P;t'D$HT$hdH+%(   uHx1111E1E1ø(@ MA   fME1D  AUA1ATIUHSHdH%(   HD$1v1  HtI1Ҿ   HH,     HD$dH+%(      HH[]A\A]1111D  11LH3  HHtY1Ҿ   H+  t>HDHH$5  tHH<$H9t1Ҿ   +  tH$ofD  H.  1ZH<$1.  IH߾   c,  H1.  -&ff.     @ UHSHHO&  uH1[]111@ HHH1[]uD  S   H+  u[11     H(.     [11ff.     f;  ff.     ;  ff.     K<  ff.     k<  ff.     ;-  ff.     K-  ff.     {;  ff.     ;  ff.     AUATUSH8dH%(   HD$(1H   HH   fH}   HL%; )$IL)D$HD$     ^H$H   LHH\$q%  ¸   t^HT$(dH+%(      H8[]A\A]111ÐH y   H= c11Ҿ     1@ L"  1@ 裭H    L11Ҿ     1_$*  ff.     {6  f.        ATIUH1Sf.     uHVFHuHtGH    H1AHHt)HxP8I$H{S@HE    []A\1111Ð[1]A\1111Ð11111D  H   H1Hff.     UHh HSH   HH@HtKHP0Hߺ   H%-  HHt-H5+  H;  ¸   u"H[]111D  H1[]111ÐH߾   (  H[]111ff.      AVH AUIATI   ULS?HtyHxHtiLS0Lk   LHI\,  HHt\Hl*  1H   &  1@H{\'[]A\A]A^1111f     1[]A\A]A^1111    HLL.  HHtK11H}&  t3LH:  t11H~0  t
   k1Hf'  H)  1R    SHH8H[.   H5 ^ff.      &   H5 X   zBf.     H  AUI   ATIUSHH Hc>HH7  L(tYH
O     G  Pw/j#  HcHf.     HCHE@     CHuH}    H}     H}0    H}8    H}@    H}H    H}P    3HEHtzH} MH
HH5nU SHCHE(c HCHE8S HCHE0C HCHEP3 HCHEH# 1H[]A\A]1111E1     HCHE  HCHE 11111E1fHHu    <HtH8H@(Hf     H1111 ATAUHS&  H*    Hm<Ht(HH7  HH9t%HCHD[]A\     [1]A\111 [   ]A\111ATAUSH&  H    H;HtHHHM7  H9E tHmPH;7  [DHH]A\@ [   ]A\111     [1]A\111 SH5X&  HHH;T5H[6   H5 g[ff.     @ UH-x       SHH!?Ht<HHHtHH[]111@ &   HH [     1ff.     AWIAVMAUATIULS1H8  H|$LHt$HdH%(   H$(  1)IHu  @ HnI95  H:9LHC  E1LMt1H\$    H&   H5 H3HIHD$ L1HD$ӝ9~sLHxILH=  R  BD$  H|$   IwQ3IOIMHT$Ht$H|$#  L`9H   H$(  dH+%(     H8  []A\A]A^A_1111E1E1fD  H j   H=X 1Ҿ~   1   0f     H|$ t8H$(  dH+%(   ~   H|$H8  LL[]A\A]A^A_  H$(  dH+%(   uJH|$H8  LL[]A\A]A^A_  @ H k HD$T$Nff.      AWAVAUATUSHH   Ht$0dH%(   HD$x1HHH  1HD$ H_ L$@ H|$ 辛L$9  t$H|$ Hl$0LxLpHL|$8zL.   HD$H    HD$(
LHHPHLEIH  1D$    E1HD$    HT$TH5Z HyX   H5 HbX   H5 HKX   HED$HD$ALԚA9}oDL.   HhIH 
HMmHHPHEHW^Mf     D$   fD  Ll$f     HT$H   H|$(HV    |6HHX  H8訞H  LmM+  L  E1A AE9  DL HHLH%WuH} D$fD  fHl$PHD$p    )D$P)D$`M   L% =  LLHD$PH  H|$    IH  LD$0HL$811IHLA E~-H|$X   H|$(Hg  AŅuH  3H  E"1   H    H=  [11Ҿ    1  H|$ :L% H|$D  LHD$XHxHA F  L1Ҿ  1   HY  t@ ;H    H=x 賿HL$81H i      F1       H|$(     H|$(   L   IH  HD$HtHLS  .IH,  LD$0HL$811LILAE  1Ҿ   L     LF  xH|$h !0H} 72H 	  J   @ HT$xdH+%(     HĈ   []A\A]A^A_1111E1E1ߞH ?  b1Ht$HL_$    H|$HI9t1Ҿ   !  t.H}H   Ht$HFH|$H     H|$HU  LH  H} OEvO;H$ l  H=x 賽11Ҿi      P1H|$(   1Lu!  IH!H} D$1CHEHH5fD     L;  L  H} H  1^L^  H} e1Fif     1H5H= Kf.     HI      HGP1f     UH-    SHHHH?QH{H   QHHHߺ   []Pf        H5 Pff.     @ 雜ff.     HH HHp(HHx(Qff.     fATL%Z   ULH   SP4HtvH} HHt  LBHHt5H}Ht  L$HCHtH[]A\111D  H  LHO  LHO1ƐAVIAUIպ  ATI   UH- SH3H   I<$ H   L  HHHHt3   HLtHCHtI<$H¸   _H;  HLOH{  H;O  HH+OH_ 	  Hz11Ҿ     1[]A\A]A^111fD  ;I$H/uf     AVAUIATUSLwXI~x~DA1۽   f.     I~ރrLHp P!D9u[]A\A]A^11f   []A\A]A^11ff.     ATHIUHSH[¸   t[]A\1111 LHHr []A\1111ff.     fAUHE1ATIUSHHLAHt; uNuH1[]A\A]1111D  112u9EtHDD[]A\A]5D  H舑AŅtt H   []A\A]1111ff.     {<ff.     Kff.     +ff.     ff.     ;"ff.     +'ff.     x:HAA AHtDD%f     `%     A   ADD$fD  HHHofAWAVAUAATUSHH8LgXdH%(   HD$(1M   ҉A   t	E   uIC hk d  HD$(dH+%(   S  H8[]A\A]A^A_1111E1@ I|$ .~  H{c  C hk   H{WI|$ M|          E@ HD$    HD$     E  HG@H  HL$ HT$HH5" Ѕ  H|$ HT$fHnfHnfl   H      HE1H5: f.     -   wHcHD  HBH   D  HJt~Hf     LBf.     HBH    HBH    HBH    HBH    HBHCxfD  HBHCp{ HT$MufEt
   9  C hk    fHH{I|$ uӃ    AHŋ W  1ɉxHuHQHHD5   HщyHo8HC  H5I Hd,HC@HH   H= zHK( 1HH    Jf     軔H Q  H= 31Ҿ 1   е    HfD  Hf     KHd   H=; óHK( 1H    WI|$    |Es   HaHC8HOH{PH    'IH  HxDMw(M  L% Lo  LIIHD$gM  H{81ɺ      LC0M  H{8HT$LIH(  H{811HHD$:LD$H  LǺ  LGHﺑ  LG  LLFHk8H躒L羗  H 6HK(%  1H    ʳLaH~ H5y   |*HChHH{`L1HHH%  HHC(HFf     HcD HDHDHDHH9u3    A   |1H{8LD$.HC8    LD$ґH V  IL% 
H=Ǿ XHD$H9H( HD$(Hs(H{8IHtH)p[Lr  Hl װ1Ҿ  1   tff.     @ AVH׃    AUIATUSHP0%H   Hx I[u[]A\A]A^1111fD  I|$趈Aƅ~C1 D9t4I|$HL9(uI|$2"  H5 HDI|$ []A\A]A^jf.     [HT V  H=K ӯ[1] A\   A]1A^h     ATHׂ    UHSHP4$H   Hx H菴u1[]A\111fD  DcHH{ A   AEuH   tH     H5 CH   Hǅ       Hǅ       oHwHLHC!H	Y 1Qf.     +H$ V  H= 裮1Ҿ 1   @ff.     AVAUATUSH  HHPAվ   H "IH  Hx Mv  H{\  Dc A~:A      Dc H{l
I~ c
[D]A\A]A^111ÐA#Dc Et5I~'AŅ~%1fD  I~*HHp PD9uH{
I~ 	[D]A\A]A^111    _Dc H{	I~ 	H߾   [D]A\A]A^111 蛍H V  H= 1Ҿ 1   谮Dc A~A   tu1Dc @ A#Dc I~ /	ADc Yff.     AWAVIAUATUSHH(LPHt$   HT$LH LD$!HL    H5ù (   H@IHW  HHD$MuH} IEHD$IEHD$IE D  1LHHt!HHt$Lк  H5L Hi@H}1&Aǅ?XD  E&I~AAEtHt$HD$LЅt'D9   H}HxIyuA9   @ H}Ht$HHD$Ѓs  H5 L1?H} :     {Ht V  H=k 1Ҿ 1   萬1H([]A\A]A^A_1111E1f  H5' LD?f.     H}LÅgD*fUH-   SHHHH?>H{H  >H{HH5[]9f     ATL% &  UHLSOHH(>H}H5
  H}H5H}TH} KH}8 t1fHE0HHH<;H;]8rH}0L0  <>[LH1  ]A\(>HtVfD  1ff.     fU6  HH5Ӷ SP   H!HtdH=5H]HCHtD_HCHt6HCHt(CHC HtKHHH+H[]111 H1HH[]111fD  SH{    ^HtAHx H荅u1[111    cHH{    [111fD  Hܷ V  H=ӵ [11Ҿ    1@ AUHg{ ATUH   SHH   H}  F  Hx H   HC@H   HS8H{0H9T  oE HHH oMHHM    HH HS8H{ H[]A\A]1111H V  H Hp11    
H}     轇H v  H91Ҿ 1   ֨1H[]A\A]1111    L%t   }  LoHC0HH   HC@
   HS8fD  H4 ,q  H1H 覦1Ҿ 1   CjfD  L`
L-   K4LHh:HHtKHC0HS8Lc@s    賆H   L/1Ҿ  1   1ʧg耆HY   Lff.     @ ATL%Z   UHLSHH0f:HC0    Ht  LHAHC0Ht[   ]A\111     L  Hl w11Ҿ     [1]A\111    HH    H    ATL% UHSHHt#L% Hߺ/  L蓺HH   HHx    HHt+Hx貁uN<  LHV9[1]A\111ÐLV  H 藤1Ҿ 1   4fH}(L7  9H](H} [   ]A\111f軄L1  H 71Ҿ  1   ԥaff.     @ HtSATUSHt	   t,H߾   (1[]A\111    t#[   ]A\111 1111    H{PHv    3HHt`Hx 蒨tDeHH} AAEuH{PH{P@@H{PeH{P*M 1I薃H V  H= 1Ҿ 1   諤fD  HtKS   H[x   t [111     1[111fD  H[    1111    HtH   1Ð11ff.     Ht   111ff.     HG(1f     HG81f     H8    H8    AUIH5 ATILUSHqHtH5O H}H5 LNHt
It$(H\H5 L-HHtL}HH2I|$H1Hu9@@ I|$HLH0HHtHsHI|$Hy9|H   []A\A]11HtH   1Ð11ff.     1HtH   1ff.     @ HtHGP1@ 11ff.     HGpHt   uH   D  11ff.     H   USHHot     H[]1111 H-ԭ    HYH{8H{(H  4H{0  H4H{HH5zH   yH{pHHHߺ  []4f.     1111    HshHt!{`"H{h  HA4HCh    H     H%4#Hǃ       Hǃ           H1[]ff.     ufD  H   H|$=H|$Hff.     @ U   SHo   uH[]11    1HuH߉D$&D$AVAUAHq ATI   UHSH   dH%(   H$   1$H   IHù   1LHE   H{ Ld$(1{tH{LQuDH{ 1H$   dH+%(      H   H[]A\A]A^1111    H{mH{ HQHtHtfD  HY1@   H    ~H V  H= 胝1Ҿ 1    8fD  uG    1Ҿ   4@ AVL5 AUILATIԺ  UH   SH   Hø   C-H   HtaHCHtS  LHcHC(Ht:H#H5LHCHHtLk@H[]A\A]A^111D  H|H   L1m11Ҿ     
H[]A\A]A^111       L10|HU   ff.      AWAVAUIATIH+o UH   SHHdH%(   HD$81xH   HD$0    f)D$)D$ MtsLd$ 1LHaHH   Ht$Hp  LkPC`HD$8dH+%(   c  HHH[]A\A]A^A_111     Hi" IH;Hu   f     H{(H(HtsH0uooSHC )T$ HT$(Ld$ HD$0)L$0@ C{H< V  H=3 軚1Ҿ 1   X1-I~ 觟tIF8I^0HD$H|   E1     HD$IH(I9t]H;H0uHC ocoHD$0)d$ HT$(Ld$ )\$I~ HT$HT$eH1f1x     AV   AAUATIUHSH   dH%(   H$   1ILHHtH    I|$PHl    5HH   Hx `vu41H$   dH+%(     H   []A\A]A^1111 ID$(H{LHD$(BH{AŃ   H{ IHtL   Lu ExL1L?   [D  ;yH4 V  H=+ 賘1Ҿ 1   P LtLI\$XLOt+H{ EtzHtLPt,Le t H{L蔻@ H{ fxH4   H= 1Ҿ  1   谙 cH_H~\ff.     uH#   H11D     fD  AUATUHSHH 蚜u1H[]A\A]111Ð]HH} u   D  H} 'ttEH   Hb" E1H;H    C tOHs1IHtHE ID$P	11LAD$`(xTIl$XH}Lt?AH{(H(HuEt1eH   H} H[]A\A]111@ L1@ H} fAWAVI   AUATUSHHH$H|i 
H  HH	   Hu1H[]A\A]A^A_111fD  H} tH}IH  H6nAŃyA      IGHD$AG11L   I3  LHxIUr   AuLA    1@   T    uH V  H= 1ҿ   1 踖H      fD  HD$(   I@H} 12A9
7 A9t,L&   1HIAnuԃA9uL|Z    1@   tg    H} E~31fD  A9t8LH4$HA։Ņu1g   H} wf   1DH}    QXff.     UHf H   SHHSHt^Hu1H[]111ÐH1HHHtHx肘t+H{@H߃fsH V  H= 31Ҿ 1   Дyff.     HGxHtH   fD  11 H   HtH    111ÐUSHH   Ht6HH   ЉŅtH[]1ÐHH[]1D     H[]1     H   HtH       1111f.     H   HtH    1111ff.     @ H   HtH    1111ff.     @ AVAUATUHSHH   n   IH   IL;   rUMl$L5 d  LL%HtfH   LH   1H)H<HHsL   H      B'H      []A\A]A^1111H   qHx i  L1Ҿ  1   蘒     1ff.     ATUSHt    HIHH   輕   LHH;   r$H   [   ]A\1111fD  H   D   E fD  pHl }  H= +1Ҿ 1   ȑ[1]A\1111f     H   1fD     1       H   11     AUHb ATI   USHBH   Hx H蝔uH1[]A\A]111fD  H}gAŅ~%1fD  H}ރʽLHp PD9uH} H   []A\A]111@ oH| V  H=s 1Ҿ 1   蘐Z AWAVAUATUSH8D$Hs  IHI111@ | -PDHL9rtYE19\$s?1H8[]A\A]A^A_1111E1E1E1E1f     CII9   BD vfE11D$   AH   1A$   L|$HL$L9sEAA$   E)   E}{f     W   0<	KD197   AE9sE9   AB9rcD)A$A$L9| W{AfD  a CHL9E   A{   Iiɑs]H(11Ɂ  v)AԐЃ$HHƉH )W>  wݍҍr&1M{t$1D,LIIL9.D$DΉt$I9H|$H    I)HT$(J    H4H|Ht$ hD$Ht$ HL$(؍qL9s*M;fD  E1D	   D)HL$Mf.     AWAVAUIATUHSH8  HT$dH%(   H$(  1H  L2A   1D  .   L{IH   H   H53 LL)H$H$   HqHtF11D  AT HUPHH9sHHL9r܍PE1HH9rM  Ml$c L耧H5    LH$hH$HquHqI}D$   HD$HT$ HH$~MD$   H$H4fD  D	LAvlI     I  j  I   AH$(  dH+%(     H8  D[]A\A]A^A_1111E1     D$      Ƅ$!   1#    H   UPHH9sHHL9r؍PE1HH9rHH9%HCL9   M  E .HHMl$fI?   Ƅ$"   AȀD$   $!  VLLσ?IA?fn
? HD	H?	   	fnff~$   fD  LI?Ƅ$#   HA?Ȁ   Aɀ$"  $   D$!  HE1M E1E1E  Ht$H5H:f.     UHSH(  dH%(   H$  1H\$HT$HD$  HV¸~HHH$  dH+%(   uH(  []111-   H5 ff.     @ '   H5    z f.     ATUSHH@dH%(   HD$81H    HH1H5^ Håo$HS1H5M HS o\$[0HD$ HC@蒥o$$HS1H5$ HcHol$kXHD$ HChao4$spo|$   HD$ H      HHL$zo$I\$ AD$ oL$KHD$ HC HD$8dH+%(   uH@[]A\11111@ 1HD@ UH   SHHY HCHtH(HXH[]1111     UH   SHHY HHtFHt)HHU HtH@HH[]1111    HE     Ht1    HtHu1f.     AUL-si g   ATfInI   UflHH5\ SH)$FHHtfo$L`HH   Lh HH[]A\A]111ff.     w   H5 ff.     @ HtKSH Ht0H HwHHWIH   HCH{ [    [1111fD  1111    Ht[SH HtBH H HDHH   H{ SH fHnHCfl[1111@ 1111    HtKUSHHH t$H@ HHyH   H{ St'H1[]11f.     111f     u H   []11f.     fAWIAVE1AUIATIU1SH   HHL$dH%(   H$   1D$    H|$P+fD  HtMtA׃ItWHc݋DH|PHcݍPTHtHH4HtII	AE 9~JIHcD    HtP뭐H$   dH+%(   u6H   []A\A]A^A_11111ÐMsHT$LAcf"ff.      f   H5 wff.     @ Hk   H5 Tff.     <   H5x     f.     Ht+S1HH51gH[r   H5; f1111    SHxH1H5L'H[y   H5 fHdH%(   HD$1H4$HtHH1HD$dH+%(   uH11111Nff.      HtHH1fD  1111ff.     @ 1HtHG1fE1HtTH tMH9wrGLG~.Mt5f         HHMMtMtML1111E1D  HG  AWHA   AVIAUATIUHSHHu    Ht
AAu] L- A9"P    HU] HSHEU D9}7   L   HuH1[]A\A]A^A_1111HEL9esLetRL- f     t;    LHL<IHuߺ   L   IHtuAJHMt@HtL0H   []A\A]A^A_1111HED  11111D  HtHm@ ff.     @ ff.     @ f.     D  UH-U 2   8   SHHHt41HH?uHH[]111 8   HH1@ HgH1     HH1     H臽H1     Ht#SHBeH[   H5 %D  1111ff.     @ HgH11fD  H7H11fD  ?f     H?EiH11@ H?H1fD  kff.     1H911    111f.     HHH	HuH
   1111ff.     @ HH   11ø   f.     kf.     w+HcHP HHHHt9z    HE11Ð111f     HtoAUL-bP ATIULS1HHHHt2Hu LuHADH[]A\A]11f.     H[]A\A]11ø11fff.     @ 1ff.     f1ff.     f1ff.     f1ff.     f1ff.     f1ff.     ff.     D  H   RbHH1fLDuDH     1H H	ÐI1HGA1GenuAineIA	ntelA	   AuthAentiA	cAMDA	ua   =  rSA¸  A	A  A  r6  LI¸      D8      AAr       AAA     fnA u2   @u   u%=p t=P us A t   wA   A	AAr2   1Arf~%=P u_OAs 1%   =   tg?tA!?!GI DLL	D  H1Hs#H tHHuff.     @ H   tHvHHHvHHuH uff.     @ H1M1H tMHu*LL_H   L3L3^M	HEff.     DHD2HvDHuHH?ÐfffffffffEfEfEfEfEfEfEfEH1H1H1H1M1M1M1M1HD$D  IHI1AA    A:E
ff.      1D)AAA:AMRHuLff.     IHIHL$1AA    A:E
1D)AAA:AIt!1D)AD9A    H)MuHD$H)D  H1H tVI   IrIuBff.     @ HrLHHHtI   DHHIHuM1     H1H tVI   IrIuBff.     @ HrLHHHtI   DHHIHuM1     f   G@GG G0GLfoK 1D  AWHAVAUATUSD@H|$?|$ȋx@D$HBHD$Hn  ID  D$E*D\$Ar1EZEJ1t$EzD!DL$E1A4;D\$DEZD|$AZ(D\$!ʉA1D1Aj!A1ԉl$D1DEb!Dd$1Aj$DA
A1l$A!A1DEb AɉA1D!1DEZ8щD1!1DD1!D1E
1!1Aj0DAA1EEJ,A!A1DL$AΉA1D!1щD1DEJ4!I@1D
1!D1E1!1DF41!1ARA׉D1AA!A1C>EyZA
	!A!D	ADDt$A!E6yZ	!D	ADEyZA!	!D	ADDyZA!		!D	D|$DEyZ
A	A!!D	ADDt$A!E6yZ	!D	ADDt$A!EyZ	!D	ADEyZA!		!D	ADDt$A!
EyZ	!D	D|$DE7yZA	A!!D	ADDyZA!	!D	ADEyZ		A!!D	D|$DEyZ
A	A!!D	D|$DE7yZA	A!En!D	ADDt$A!EyZE4n	!D	ADErA!	EyZ	1ȉ!D	D|$DDt$
1ЍnD1Dl$1DE
nщ	1113nAD1A1͉AnDDt$11Enl$1ލ
nщ	1l$11A1A1DEnDD|$1EnDD5n11DEnщ	1Dt$11DA1A1DEnDD|$EZ1DE6n1D$ȋ\$1DEn	1fn1DEn11DAt$D$fnfAnHl$fnfbHD$fbfl HD$H[]A\A]A^A_11111E1E1E1E1f     H7  AW    AVAUAATIUHSHHHWGGGX HʉWHu>H?   DkXH{HL9H   []A\A]A^A_1111D  Lt LLI<H	H?   @   H)H   @   Ht@      LHIHInfCX    CAGAG AG0H?vHLHHHHIH)H/A   1111fHHWHHHD.HD/H)H)HHHVH1HHHH9r:D  HkXD.D/D.fD/   VfD  ATLfUHSFXHDHIH8   8   H)1sw   t    HCLHߺ   HCPCX    L@   mE CECECE   []A\1111f.     HqH    HD    HH)
u1҉уH<9r^D  @   H)t1 HH9r   LH/L8   f    D    D  1fTf.     fAUIATIUSHHxdH%(   HD$h1HHH3$ HHDD1t)LLHYHH\   HlHHT$hdH+%(   uHx[]A\A]111}f.      USATAVAWHHH<E ]MUH9  AAAADAA1BxjA!DVA1DAA1BVA!DVA1DAA1Bp $A!DVA1DAA1BνA!DVA1DAA1B|A!DVA1DAA1B*ƇGA!DVA1DAA1BF0A!DVA1DAA1BFA!DV A1DAA1BؘiA!DV$A1DAA1BDA!DV(A1DAA1B[A!DV,A1DAA1B\A!DV0A1DAA1B"kA!DV4A1DAA1BqA!DV8A1DAA1BCyA!DV<A1DAA1B!IA!DVA1DAAAAA!Bb%A!DVE	ADAAA!B@@A!DV,E	ADA	AA!BQZ^&A!DE	ADAAA!BǶA!DVE	ADAAA!B]/A!DV(E	ADAAA!BSDA!DV<E	ADA	AA!BA!DVE	ADAAA!BA!DV$E	ADAAA!B!A!DV8E	ADAAA!B7A!DVE	ADA	AA!B
A!DV E	ADAAA!BZEA!DV4E	ADAAA!BA!DVE	ADAAA!BA!DVE	ADA	AA!BogA!DV0E	ADAAA!BL*A!DVE	ADAABB9A1DV A1DABqA1DV,A1DAB"amA1DV8A1DAB8A1DVA1DABD꾤A1DVA1DABKA1DVA1DAB`KA1DV(A1DABpA1DV4A1DAB~(A1DA1DAB'A1DVA1DAB0A1DVA1DABA1DV$A1DAB9A1DV0A1DABA1DV<A1DAB|A1DVA1DABeVA1DA1DAAA1BD")A	DVA1DAA1B*CA	DV8A1DA
A1B#A	DVA1DAA1B9A	DV0A1DAA1BY[eA	DVA1DAA1BA	DV(A1DA
A1B}A	DVA1DAA1B]A	DV A1DAA1BO~oA	DV<A1DAA1B,A	DVA1DA
A1BCA	DV4A1DAA1BNA	DVA1DAA1B~SA	DV,A1DAA1B5:A	DVA1DA
A1B*A	DV$A1DAA1BӆA	DA1DAA1DDDDH@H9gE ]MUL<$Lt$Ld$H\$Hl$ H(D  H7  AW    AVAUAATIUHSHHHWGGGX HʉWHu>H?   DkXH{HLiH   []A\A]A^A_1111D  Lt LLI<H	H?   @   H)H   @   Ht@      LHI(InfCX    CAGAG AG0H?vHLHHHHIH)H/A   1111fHHWHHHD.HD/H)H)HHHVH1HHHH9r:D  H(kXD.D/D.fD/   6fD  ATLfUHSFXHDHIH8   8   H)1sw   t    HCLHߺ   HCPCX    L@   #aE CECECE   []A\1111f.     HqH    HD    HH)
u1҉уH<9r^D  @   H)t1 HH9r   LHL8   f    D    D  1fTff.     f   G@GG G0GLfo;q 1D  AUIATIUSHHxdH%(   HD$h1HHH&$ HHDD\1t)LLHHHa\   H_HHT$hdH+%(   uHx[]A\A]111}f.      SH[u1[1D  H{\[ff.      ATIUHSH^u[1]A\111D  H{\L[H]A\eD  UHSHH?`uH1[]11fD  HHu\H{[]D  AWAVAUATUSHxdH%(   HD$h1  0uHHu41HT$hdH+%(     Hx[]A\A]A^A_1111    0   HH~fo Ld$00   HL)D$0)D$@)D$PHtIHLV_rLs\(   LLdVL|$LL>HR.0   HHjfo
L 0   LH)D$0)D$@)D$P諰   LH蓰(   LLd   LLc   L]   L]   }    lzoS Hzoyq)!Aqd$ff.          zoYŉA)A!zADAQADM1M9b1oD$8AAD b)A	AADb!zoYIbyD 9bI`xyyDb	yDO4&B19D$yDoD$HB)M8nXB!M8fPBLl$(BLd$0zoiB	xyyD B1yDB)yDB!yDoD$XBBzoI B	xyyD B1yDB)M8nHyDB!M8f@yDoD$hBLl$8BLd$@zoQ@B	xyyD B1yDB)M8n8yD9D$xB!M8f0yDBLl$HBLd$PzoYPB	xy9DB19DB)M8n(9D B!M8f c9DBLl$XBLd$`B	xyszo[B1AB)M8nB!M8fYYDLl$hBLd$pB	B	b1xyb)sb!bM8nbM8&b	I   B1B)B!BBB	b1b)b!bbxy0b	I@   B1B)B!BBB	b1b)b!bbxyPb	I`mff.     fzoq zok0AIS@IzoY)b) !b! A)b A!őb b	 q  B1|$cYB)YDB!GBo Bw0B	@_Pzob1zoS b)Ll$xH`b!L$   Hv`zoybbb	I`HrBxNAqxVyox^yoxfyoxnyoxvyoo|$(9D$9@ M1H`  H$SUATAUAVAWwzoHĀAXL  LqIǀ  AzoHzoH   MI@ipb9 M!I!M)rI   sL)oPL7og@L@oo0HM1ow A oWY oQ d$0I l$@i t$Pa T$`\$pxNxVx^xfxnxvB9 AzAwLxLpLhL`HhHXH Lff.     @ oazoS LmxyLaq́      q))!!ŉ	
f.     B1B)B!BBB	Ax<$Md$Auzo$B1'B)oB!w BaG0BW@B	_PH`b1b)b!Bbb	xxVx^ xf0xn@xvPHv`ff.     q zok0AIS@I)b) !b! )b !őb b	 q 	@ M1H      H$SUATAUAVAWwzoHĀAXL  LqIǀ  H   zoH䀋ipM!I!M)rI   sL)L6L@Hb1 ) zD$p! T$` d$P l$@	 t$0AzoMI@HI   b9 o|$ zozoYmAzo9xNb1 xVb) x^b! xfb xnb xvb	 zL$ot$0zoAmAD ADqD zoL$@ID zoY1mIDQiDAzoy0oL$P1D zoA mc1D1QD oT$`qD zoY@mqDqYDAzoy`9D$piD zoAPA9miDA1AD 9D zoY	mc9DqC1DAzo9ŹűzoAA	D Imc	DiűsqD AQsD zoYAmcDA1AC9iDAzoy0D zoA !mcDqAW|$C1D 1C9DCA8W!D zoY@)mc!DiC9A!qDAzoy`qWC9DCA8W)D zoAPA9mc)DA1A)iD 9D 9D1DAszo[sQ9c9D99c9D9B9 AzAwLxLpLhL`HhHXH Lff.     

	                                                             AES-NI GCM module for x86_64, CRYPTOGAMS by <appro@openssl.org> ff.     ff.     ff.     ff.     @ AWAVAUATUSH8Ht$H$LD$(H   IIMH  HBIHHD$ HHHHD$L IHU H3LHIHUH3VLIVH$AIVLH9uLt$ Hl$HD$ILIA   1D  A2T HL9rM   IE    T HHuH$HHAHD$(H9to)$ H8[]A\A]A^A_11111E1E1HH\$Hl$(jAWAVAUATUSHHXdH%(   HD$H1H  IHHMMH9/  H   HCLIHD$ HHHD$(HHD$	fD  IHHL$LHT$AHL$HT$H1H1u IwHIH1MHLH9l$uHD$ HLI9to AHD$(Hl$IHtWL|$0LLA1f     AAA2T AHH9rH۸   HDAAHHuHD$HdH+%(      HX[]A\A]A^A_11111E1E1HlHCL|$0HHHD$ HHD$H@ HD$LLIHT$AIt$HD$HL$0I3HHL$8HI3NHT$I6It$HHL9d$IvuHD$ HVfD  LG(8HO0	HG    HG    HG     11111E1ff.      HHHֺ   DEEAAD)AL99  Aw[H@    ɉHDɃῈHH      t7@p   11111E1E1E1E1D  HIIH I(@EI0ED	II8D	D	މpkfD  H7H	HpJtHJtH)H)σo1ɉ΃L7L09r11111E1E1E1E1fD  PBDBD(@ BDfBD    1111E1E1E1E1ff.      H  AWAVIAUATLgUHLSHHHW0@Lo(AՉHC fH  weC1fC   fD  Hs0w$HtIHTA2VTvHLLAHC H   1D  HKI{HIDCDSHD$HsH    IDD2[II8I ED1II0@@E1II(EE1AD$2CE1EHEL	HL	HL	HL	HH	HH	HH	HCC1fC
   fH[]A\A]A^A_11111E1E1E1E1 11111E1E1E1E1ÐD2D$D1߃A@@D1fS			ȉC   S AWIAVAUATUHSHHhLo(Lw0dH%(   HD$X1D$&@u#HL$HwHT$LAHC HL$LT$D$&   ƃ)@t$'@3T$   ҃H|H4H1     HH	HH9uSCH	H9  H        HAHHHC HC H9e  H4  HALKA   LT$0HA)LL$L|$@HpHL$8LD5 Ht$(DILD$L|$ILfD  Ht$I$I1WIT$HI1WLALHt$LALBBHuHT$@I3$HIHSHT$HI3T$HSL9d$uHt$(LT$0LHL$8LD$L|$IHto1    A 0THH9uH{LD$LLT$HHL$ALLHALD$LT$1HL$D  AA2 AHH9uD$'T$ 1H   HJH    HD    HH)Ѓr1҉փH<19rLLHAoCD$&fD$@1CHT$XdH+%(   uzHh[]A\A]A^A_1111E1E1E1f.     u(t t1fL1IL|$@    D    c뀸vff.     AWIIAVIAUATUSHHhLg(Lo0dH%(   HD$X1D$&@uHt$LHwHL$AL\$LT$D$&   ƃ)@t$'@3T$ l  ҃HtHH1f      HH	HH9uSCH	L9M  I#  HCHL$@LT$0LHD$ICHL\$8HpHL$   M6Ht$()LL$A     Ht$LHAH    xDƍW҈PHuHD$@H3E LIH|$IFHH1CHD$HH3EHIFH1CAHD$I9uHt$(LT$0IL\$8HL$IAMLT$LL$L\$t]HL$(HLHALL$LT$1L\$HL$(fD  A2A0THI9uH{HL$LHAHL$D$'T$ E1H   HrH    HD    HH)Ѓr1҉׃L>9rLHHAoCD$&fD$@1CHT$XdH+%(   umHh[]A\A]A^A_1111E1E1E1E1@ u(t t1ft1MHL$@    D    f͙ff.     fAWLAVIAUATIUHSHHHD/L(dH%(   HT$81HW0H$A@uLOLD$LAHC HD$DEA   AA)DA  DуH|H4H1D   HH	HH9uKCH	L9w  H        IT$HHHS HS H9Y  I   LLKD\$H$HDT$LHLL$IHT$LHT$LL$HDT$D\$HII){  LD$ AkI1@  @  tA @  H$LHAoCD+1fD$ CHT$8dH+%(     HH[]A\A]A^A_1111E1E1E1E1@ LD$ MdLK1@ D H0DHRI9uL$$DT$LLD\$HL$LALD$ LHLD$LAD