pax_global_header00006660000000000000000000000064126037735600014523gustar00rootroot0000000000000052 comment=fc5e75a2a16a80e958c2d030eb04bdbd51e4436e plsense-0.3.4/000077500000000000000000000000001260377356000132005ustar00rootroot00000000000000plsense-0.3.4/.gitignore000066400000000000000000000000711260377356000151660ustar00rootroot00000000000000Makefile* META.yml MYMETA.* blib/ inc/ pm_to_blib local/ plsense-0.3.4/.plsense000066400000000000000000000000321260377356000146450ustar00rootroot00000000000000name=plsense lib-path=lib plsense-0.3.4/.travis.yml000066400000000000000000000010131260377356000153040ustar00rootroot00000000000000language: perl perl: - 5.22 - 5.20 - 5.18 - 5.16 - 5.14 - 5.12 - 5.10 - 5.8 before_install: - git clone git://github.com/travis-perl/helpers ~/travis-perl-helpers - source ~/travis-perl-helpers/init --auto install: - cpanm -n CPAN - (echo y; echo y; echo o conf commit) | cpan - (cpanm --with-develop --installdeps --notest .) || cat ~/.cpanm/build.log before_script: - perl Makefile.PL - make script: - prove -bv t - prove -bv xt notifications: on_success: change on_failure: change plsense-0.3.4/Changes000066400000000000000000000001531260377356000144720ustar00rootroot00000000000000Revision history for PlSense 0.01 Date/time First version, released on an unsuspecting world. plsense-0.3.4/MANIFEST.SKIP000066400000000000000000000001141260377356000150720ustar00rootroot00000000000000.gitignore blib/ pm_to_blib README-ja.md README.md image/ #!include_default plsense-0.3.4/Makefile.PL000066400000000000000000000007331260377356000151550ustar00rootroot00000000000000use strict; use inc::Module::Install; all_from 'lib/PlSense.pm'; repository 'https://github.com/aki2o/plsense'; bugtracker 'https://github.com/aki2o/plsense/issues'; auto_include_deps(); install_script 'bin/plsense'; install_script 'bin/plsense-server-main'; install_script 'bin/plsense-server-resolve'; install_script 'bin/plsense-server-work'; install_script 'bin/plsense-worker-build'; install_script 'bin/plsense-worker-find'; tests_recursive; cpanfile; WriteAll; plsense-0.3.4/README000066400000000000000000000030651260377356000140640ustar00rootroot00000000000000PlSense The README is used to introduce the module and provide instructions on how to install the module, any machine dependencies it may have (for example C compilers and installed libraries) and any other information that should be provided before the module is installed. A README file is required for CPAN modules since CPAN extracts the README file from a module distribution so that people browsing the archive can use it to get an idea of the module's uses. It is usually a good idea to provide version information here so that people can decide whether fixes for the module are worth downloading. INSTALLATION To install this module, run the following commands: perl Makefile.PL make make test make install SUPPORT AND DOCUMENTATION After installing, you can find documentation for this module with the perldoc command. perldoc PlSense You can also look for information at: GitHub https://github.com/aki2o/plsense RT, CPAN's request tracker (report bugs here) http://rt.cpan.org/NoAuth/Bugs.html?Dist=PlSense AnnoCPAN, Annotated CPAN documentation http://annocpan.org/dist/PlSense CPAN Ratings http://cpanratings.perl.org/d/PlSense Search CPAN http://search.cpan.org/dist/PlSense/ LICENSE AND COPYRIGHT Copyright (C) 2013 Hiroaki Otsu This program is free software; you can redistribute it and/or modify it under the terms of either: the GNU General Public License as published by the Free Software Foundation; or the Artistic License. See http://dev.perl.org/licenses/ for more information. plsense-0.3.4/README-ja.md000066400000000000000000000065071260377356000150570ustar00rootroot00000000000000[![Build Status](https://travis-ci.org/aki2o/plsense.svg?branch=master)](https://travis-ci.org/aki2o/plsense) # これは何? ソースコード解析による型推論を用いて、Perl開発をサポートするツールです。 EmacsやVimなどの高機能エディタから利用されることを前提に設計しています。 # 特徴 本ツールを利用することで、以下が実現可能です。 ### オムニ補完 以下のプログラミング要素について、コンテキストに合わせた補完、いわゆるオムニ補完ができます。 - 変数 - インスタンスメソッド - クラスのイニシャライザ - use/requireモジュール - use/requireするモジュールに渡すLIST要素 - ハッシュキー ![demo1](image/demo1.png) ### 適切なヘルプ ![demo2](image/demo2.png) ### メソッドシグネチャ ![demo3](image/demo3.png) ### 定義元ジャンプ # デモ 本ツールをEmacsで利用した場合に可能になる、コーディングのデモです。 ![demo](image/demo.gif) 長いバージョンはこちら -> Emacsでの利用に関して、詳しくは以下を参照して下さい。 # インストール 本ツールはPerlモジュールです。 ### CPANからインストール 2013/07/24 CPANにアップロードするための申請中ですが、一向に申請が通る気配がありません。 ### cpanmでインストール [こちら](https://github.com/aki2o/plsense/releases) から最新のPlSense-\*.tar.gzをダウンロードして、cpanmコマンドに、そのファイルパスを渡して下さい。 ### 手動でインストール [こちら](https://github.com/aki2o/plsense/releases) から最新のPlSense-\*.tar.gzをダウンロードして解凍、できたディレクトリに移動後、以下を実行して下さい。 ``` $ perl Makefile.PL $ make $ make test $ make install ``` 手動の場合、依存モジュールがインストールされていないとエラーになると思います。 都度、インストールして頂くか、Makefile.PLを参照して下さい。 ### インストール確認 本ツールのインストールにより、plsenseコマンドが提供されます。 ターミナルから\`plsense -v\`を実行してみて下さい。 本ツールのバージョン情報が表示されるはずです。 ### インストール後やること 本ツールを利用するには設定ファイルを用意するのが簡単です。 ターミナルから\`plsense\`と実行して下さい。設定ファイルを作成するか聞かれるので、作成して下さい。 - 再作成するには\`plsense config\`と実行して下さい。 - 設定ファイルを作らず利用することも可能です。 を参照して下さい。 # 使い方 エンドユーザの方は、本ツールの使い方は意識する必要はないのではと思います。 本ツールの仕様や使い方などを知りたい場合は、 を参照して下さい。 # 動作確認 - WindowsXP Pro SP3 32bit - Cygwin 1.7.20-1 - Perl 5.14.2 **Enjoy!!!** plsense-0.3.4/README-ja.org000066400000000000000000000066301260377356000152430ustar00rootroot00000000000000#+OPTIONS: toc:nil travis-build:aki2o/plsense#master * これは何? ソースコード解析による型推論を用いて、Perl開発をサポートするツールです。 EmacsやVimなどの高機能エディタから利用されることを前提に設計しています。 * 特徴 本ツールを利用することで、以下が実現可能です。 *** オムニ補完 以下のプログラミング要素について、コンテキストに合わせた補完、いわゆるオムニ補完ができます。 - 変数 - インスタンスメソッド - クラスのイニシャライザ - use/requireモジュール - use/requireするモジュールに渡すLIST要素 - ハッシュキー [[file:image/demo1.png][demo1]] *** 適切なヘルプ [[file:image/demo2.png][demo2]] *** メソッドシグネチャ [[file:image/demo3.png][demo3]] *** 定義元ジャンプ * デモ 本ツールをEmacsで利用した場合に可能になる、コーディングのデモです。 [[file:image/demo.gif][demo]] 長いバージョンはこちら -> https://www.youtube.com/watch?v=qurNSQjOyK4 Emacsでの利用に関して、詳しくは以下を参照して下さい。 https://github.com/aki2o/emacs-plsense/blob/master/README-ja.md * インストール 本ツールはPerlモジュールです。 *** CPANからインストール 2013/07/24 CPANにアップロードするための申請中ですが、一向に申請が通る気配がありません。 *** cpanmでインストール [[https://github.com/aki2o/plsense/releases][こちら]] から最新のPlSense-*.tar.gzをダウンロードして、cpanmコマンドに、そのファイルパスを渡して下さい。 *** 手動でインストール [[https://github.com/aki2o/plsense/releases][こちら]] から最新のPlSense-*.tar.gzをダウンロードして解凍、できたディレクトリに移動後、以下を実行して下さい。 #+begin_src $ perl Makefile.PL $ make $ make test $ make install #+end_src 手動の場合、依存モジュールがインストールされていないとエラーになると思います。 都度、インストールして頂くか、Makefile.PLを参照して下さい。 *** インストール確認 本ツールのインストールにより、plsenseコマンドが提供されます。 ターミナルから`plsense -v`を実行してみて下さい。 本ツールのバージョン情報が表示されるはずです。 *** インストール後やること 本ツールを利用するには設定ファイルを用意するのが簡単です。 ターミナルから`plsense`と実行して下さい。設定ファイルを作成するか聞かれるので、作成して下さい。 - 再作成するには`plsense config`と実行して下さい。 - 設定ファイルを作らず利用することも可能です。 https://github.com/aki2o/plsense/wiki/Config-@ja を参照して下さい。 * 使い方 エンドユーザの方は、本ツールの使い方は意識する必要はないのではと思います。 本ツールの仕様や使い方などを知りたい場合は、 https://github.com/aki2o/plsense/wiki/Home-@ja を参照して下さい。 * 動作確認 - WindowsXP Pro SP3 32bit - Cygwin 1.7.20-1 - Perl 5.14.2 *Enjoy!!!* plsense-0.3.4/README.md000066400000000000000000000045111260377356000144600ustar00rootroot00000000000000[![Build Status](https://travis-ci.org/aki2o/plsense.svg?branch=master)](https://travis-ci.org/aki2o/plsense) [Japanese](https://github.com/aki2o/plsense/blob/master/README-ja.md) # What's this? This is a development tool for Perl using the type inference by analyzing source code. This tool is for highly functional editor like Emacs/Vim. # Feature You can do the following function by using this tool. ### Omni Completion About the following programming element, you can do the optimized completion for context. It's Omni completion what is called. - Variable - Method - Module - Initializer of Class - LIST of Use/Require statement - Key of Hash ![demo1](image/demo1.png) ### Smart Help ![demo2](image/demo2.png) ### Sub Signature ![demo3](image/demo3.png) ### Jump To Definition # Demo This is a coding demo when this tool is used on Emacs. ![demo](image/demo.gif) Here is a long version -> For using on Emacs, see # Install This tool is a Perl module. ### From CPAN 2013/07/24 Not yet available. ### Using cpanm Download latest PlSense-\*.tar.gz from [here](https://github.com/aki2o/plsense/releases) and execute cpanm to the downloaded file path. ### Manually Download latest PlSense-\*.tar.gz from [here](https://github.com/aki2o/plsense/releases) and extract the file, move the maked directory, execute the following. ``` $ perl Makefile.PL $ make $ make test $ make install ``` If the module is not yet installed that this module depends on, error maybe happen. In the case, install the module and retry. About the module, see Makefile.PL. ### Verify Installation execute `plsense -v` on shell. If show the PlSense version, installation is finished. ### After Installation Making config file is easy way for using this tool. Do `plsense` on terminal. plsense confirm whether make config file. - For remake config file, do `plsense config`. - You can use this tool without config file. see . # Usage Perhaps end user don't need to know the usage of this tool. About the usage/specification of this tool, see . # Tested On - WindowsXP Pro SP3 32bit - Cygwin 1.7.20-1 - Perl 5.14.2 **Enjoy!!!** plsense-0.3.4/README.org000066400000000000000000000047601260377356000146550ustar00rootroot00000000000000#+OPTIONS: toc:nil [[travis-build:aki2o/plsense#master]] [[https://github.com/aki2o/plsense/blob/master/README-ja.md][Japanese]] * What's this? This is a development tool for Perl using the type inference by analyzing source code. This tool is for highly functional editor like Emacs/Vim. * Feature You can do the following function by using this tool. *** Omni Completion About the following programming element, you can do the optimized completion for context. It's Omni completion what is called. - Variable - Method - Module - Initializer of Class - LIST of Use/Require statement - Key of Hash [[file:image/demo1.png][demo1]] *** Smart Help [[file:image/demo2.png][demo2]] *** Sub Signature [[file:image/demo3.png][demo3]] *** Jump To Definition * Demo This is a coding demo when this tool is used on Emacs. [[file:image/demo.gif][demo]] Here is a long version -> https://www.youtube.com/watch?v=qurNSQjOyK4 For using on Emacs, see https://github.com/aki2o/emacs-plsense/blob/master/README.md * Install This tool is a Perl module. *** From CPAN 2013/07/24 Not yet available. *** Using cpanm Download latest PlSense-*.tar.gz from [[https://github.com/aki2o/plsense/releases][here]] and execute cpanm to the downloaded file path. *** Manually Download latest PlSense-*.tar.gz from [[https://github.com/aki2o/plsense/releases][here]] and extract the file, move the maked directory, execute the following. #+begin_src $ perl Makefile.PL $ make $ make test $ make install #+end_src If the module is not yet installed that this module depends on, error maybe happen. In the case, install the module and retry. About the module, see Makefile.PL. *** Verify Installation execute =plsense -v= on shell. If show the PlSense version, installation is finished. *** After Installation Making config file is easy way for using this tool. Do =plsense= on terminal. plsense confirm whether make config file. - For remake config file, do =plsense config=. - You can use this tool without config file. see https://github.com/aki2o/plsense/wiki/Config. * Usage Perhaps end user don't need to know the usage of this tool. About the usage/specification of this tool, see https://github.com/aki2o/plsense/wiki/Home. * Tested On - WindowsXP Pro SP3 32bit - Cygwin 1.7.20-1 - Perl 5.14.2 *Enjoy!!!* plsense-0.3.4/bin/000077500000000000000000000000001260377356000137505ustar00rootroot00000000000000plsense-0.3.4/bin/plsense000077500000000000000000000655351260377356000153650ustar00rootroot00000000000000#!/usr/bin/perl use strict; use warnings; use Getopt::Long qw{:config posix_default no_ignore_case gnu_compat}; use IO::Socket; use Try::Tiny; use PlSense; use PlSense::Logger; use PlSense::Configure; use PlSense::Util; use PlSense::SocketClient; my %opthelp_of = ("-h, --help" => "Show this message.", "-v, --version" => "Show vertion.", "-i, --interactive" => "Run interactively.", "-c, --cachedir" => "Path of directory caching information for Completion/Help.", "--port1" => "Port number for listening by main server process. Default is 33333.", "--port2" => "Port number for listening by work server process. Default is 33334.", "--port3" => "Port number for listening by resolve server process. Default is 33335.", "--maxtasks" => "Limit count of task that run on server process.", "--loglevel" => "Level of logging. Its value is for Log::Handler.", "--logfile" => "Path of log file.", ); my %fnchelp_of = ("help [Command]" => [ "Show detail help about Command." ], "svstat, serverstatus" => [ "Show server process status." ], "svstart, serverstart" => [ "Start server process." ], "svstop, serverstop" => [ "Stop server process." ], "refresh" => [ "Refresh server process." ], "o, open [File/Module]" => [ "Open File/Module.", <<'EOF' Build information about File/Module if not yet build it. The included modules (ex. 'use ...;') of File/Module are built too if not yet build it. And exec onfile for given file path or module name. For detail, see help of location command. The build task is run on server process, and requires a few minutes until finish. For checking the status, use ready/ps/queue commands. EOF ], "u, update [File/Module]" => [ "Update File/Module.", <<'EOF' Build information about File/Module forcely. The included modules (ex. 'use ...;') of File/Module are built only if not yet build it. EOF ], "remove [File/Module]" => [ "Remove the cached information about File/Module." ], "removeall" => [ "Remove all cached information." ], "mhelp, modhelp [Module]" => [ "Show help about Module." ], "fhelp, subhelp [Sub] [Module]" => [ "Show help about Sub of Module." ], "vhelp, varhelp [Var] [Module]" => [ "Show help about Var of Module." ], "ahelp, assisthelp [Cand]" => [ "Show help about Cand of last assist.", <<'EOF' Cand is a one of the result of last assist command. For detail, see help of assist command. EOF ], "chelp, codehelp [Code]" => [ "Show help about Code.", << 'EOF' Code is a incomplete source code of Perl like the following line. IO::File my $io = IO::File->new $io EOF ], "subinfo [Code]" => [ "Show signature of the method detected by Code.", <<'EOF' Code is a incomplete source code of Perl like the following line. &AnyModule::do_something grep my $io = IO::File->new The result format is the following. NAME: Method-name ARG1: Var-name As Unknown/Module-name/Var-type ARG2: ... RETURN: Var-name/Literal/NoIdent As Unknown/Module-name/Var-type FILE: File-path LINE: Line-number COL: Column-number Var-type is a one of SCALAR, ARRAY, HASH, REFERENCE. Literal means return value is literal (ex. return "hoge";). NoIdent means return value is not variable/literal (ex. return grep ...;). Unknown means still not clear. EOF ], "onfile [File]" => [ "Set current location by File for assist.", <<'EOF' Set File to current filepath. And set 'main' to current module automatically. And set '' to current function automatically. EOF ], "onmod [Module]" => [ "Set current location by Module for assist.", <<'EOF' Set Module to current module. And set '' to current function automatically. EOF ], "onf, onsub [Sub]" => [ "Set current location by Sub for assist.", <<'EOF' Set Sub to current function. EOF ], "loc, location" => [ "Show current location.", <<'EOF' Current location is where you are now. The result format is the following. Project: Project-name File: File-path Module: Module-name Sub: Function-name Project-name is detected by the config file that is named '.plsense' and put in the root of project tree. The file is found in following order. If not found, the project value is 'default'. If the file of current location is /home/user1/MyProj/src/lib/MyModule.pm, /home/user1/MyProj/src/lib/.plsense /home/user1/MyProj/src/.plsense ... Use the first value that the file exists. But, '~/.plsense' is ignored because it's a config file for plsense. For setting location, see help of open/onfile/onmod/onsub command. .plsense format is the following. name=Project-name lib-path=Library-path Project-name need to match '[a-zA-Z0-9_]+'. Library-path is a relative path to root of library for the project. About '~/.plsense', see help of config command. EOF ], "c, codeadd [Code]" => [ "Add source to current location.", <<'EOF' Add information that is built from Code to current location. This command is a substitute for open/update command and lighter than them. Code is a incomplete source code of Perl like the following line. use List::AllUtils qw{ :al for $i ( 0.. 10 ) { print $i; } sub hoge { my $self = shift; if ( $self ) { do_anything(); } return "hog Abount current location, see help of location command. EOF ], "a, assist [Code]" => [ "Do assist about Code.", <<'EOF' Provide the optimized completion that is the available words after Code. Code is a incomplete source code of Perl like the following line. use Use IO::F $ $self-> This command needs where you are. For more information, see help of location command. EOF ], "ps" => [ "Show task list that is running on server process." ], "queue" => [ "Show stack of task that is not yet running on server process." ], "ready [File/Module]" => [ "Show status of File/Module.", <<'EOF' Kind of status is 'Yes'/'No'/'Not Found'. 'Yes' means the File/Module information have been built already. 'No' means the File/Module information is not built yet. 'Not Found' means File/Module is not opened yet. If File/Module is not given, show the list of the 'Yes' modules. EOF ], "debugstk" => [ "Show quantity of stocked on server process for debugging." ], "debugmod [File/Module]" => [ "Show detail of File/Module for debugging." ], "debugrt [Regexp]" => [ "Show routing matched by Regexp for debugging." ], "debugsubst [Regexp]" => [ "Show substitute matched by Regexp for debugging." ], "debuglex [Code/File]" => [ "Show the PPI::Lexer layout as result of parsing Code/File for debugging." ], "config" => [ "Update configuration about plsense.", <<'EOF' Configuration is saved into '~/.plsense'. The format is the following. Option-name=Option-value ... About Option-name, exec 'plsense --help'. The config of '~/.plsense' means giving '--Option-name=Option-value' when execut plsense. You can override the config of '~/.plsense' by executing 'plsense --Option-name=Option-value'. EOF ], "loglevel [Level] [Server]" => [ "Update the log level to Level about the logging of Server.", <<'EOF' Level is the level of logging by Log::Handler. Server is the target server. This value is one of the following value. main ... only Main server work ... only Work server resolve ... only Resolve server all ... all server If Server is not given, The target is local process. EOF ], "explore [Regexp]" => [ "Show the packages matched by Regexp and their methods.", <<'EOF' Regexp is the regular expression matches the packages to explore. The one format of result is like the following. Package-name Package-filepath Package-line:Package-column &Method-name Method-line:Method-column ... Package-line/Package-column is the line/column number that the package is defined on. Method-line/Method-column is the line/column number that the method is defined on. EOF ], ); my %function_of = (help => \&show_help, serverstatus => \&show_server_status, svstat => \&show_server_status, serverstop => \&stop_server, svstop => \&stop_server, serverstart => \&start_server, svstart => \&start_server, refresh => \&refresh_server, open => \&open_file, o => \&open_file, update => \&update_file, u => \&update_file, remove => \&remove_file, removeall => \&remove_all, modhelp => \&help_module, mhelp => \&help_module, subhelp => \&help_method, fhelp => \&help_method, varhelp => \&help_variable, vhelp => \&help_variable, assisthelp => \&help_last_assist, ahelp => \&help_last_assist, codehelp => \&help_code, chelp => \&help_code, subinfo => \&get_method_information, onfile => \&set_currentfile, onmod => \&set_currentmodule, onsub => \&set_currentmethod, onf => \&set_currentmethod, location => \&get_current_location, loc => \&get_current_location, codeadd => \&add_source, c => \&add_source, assist => \&assist_coding, a => \&assist_coding, ps => \&get_process_list, queue => \&get_task_queue, ready => \&is_ready, debugstk => \&debug_stocked, debugmod => \&debug_module, debugrt => \&debug_routing, debugsubst => \&debug_substitute, debuglex => \&debug_lexer, config => \&update_config, loglevel => \&update_loglevel, explore => \&explore_package, ); my ($cachedir, $port1, $port2, $port3, $maxtasks, $loglvl, $logfile); my $interactive = 0; GetOptions ('help|h' => sub { show_usage(); exit 0; }, 'version|v' => sub { print "PlSense version is $PlSense::VERSION\n"; exit 0; }, 'cachedir|c=s' => \$cachedir, 'port1=i' => \$port1, 'port2=i' => \$port2, 'port3=i' => \$port3, 'maxtasks=i' => \$maxtasks, 'loglevel=s' => \$loglvl, 'logfile=s' => \$logfile, 'interactive|i' => \$interactive, ); setup_logger($loglvl, $logfile); if ( ! $loglvl ) { $loglvl = ''; } if ( ! $logfile ) { $logfile = ''; } if ( ! $cachedir ) { logger->info("Read option from config file."); setup_config("", 0, 1) or exit 1; $cachedir = get_config("cachedir"); $port1 ||= get_config("port1"); $port2 ||= get_config("port2"); $port3 ||= get_config("port3"); $maxtasks ||= get_config("maxtasks"); $loglvl ||= get_config("loglevel") || ""; $logfile ||= get_config("logfile") || ""; setup_logger($loglvl, $logfile); } set_primary_config( cachedir => $cachedir, port1 => $port1, port2 => $port2, port3 => $port3, maxtasks => $maxtasks, loglevel => $loglvl, logfile => $logfile, ); setup_config() or exit 1; my $scli = PlSense::SocketClient->new({ retryinterval => 0.2, maxretry => 10 }); my %pid_of; $SIG{INT} = sub { logger->notice("Receive SIGINT"); exit 0; }; $SIG{TERM} = sub { logger->notice("Receive SIGTERM"); exit 0; }; if ( $interactive ) { print "> "; *STDOUT->autoflush(); CMD: while ( my $line = ) { chomp $line; my $cmdnm = $line =~ s{ ^ \s* ([a-z]+) }{}xms ? $1 : ""; if ( $cmdnm eq "quit" ) { last CMD; } elsif ( $cmdnm eq "exit" ) { last CMD; } elsif ( exists $function_of{$cmdnm} ) { logger->notice("Do $cmdnm : $line"); my $fnc = $function_of{$cmdnm}; print &$fnc($line); } elsif ( $cmdnm ) { print STDERR "Unknown command : $cmdnm\n"; } print "> "; } } else { my @cmdarg = @ARGV; my $cmdnm = shift @cmdarg || ""; if ( ! $cmdnm ) { show_usage(); exit 1; } elsif ( ! exists $function_of{$cmdnm} ) { print STDERR "Unknown command : $cmdnm\n"; exit 1; } my $line = join(" ", @cmdarg); logger->notice("Do $cmdnm : $line"); my $fnc = $function_of{$cmdnm}; print &$fnc($line); } exit 0; sub show_usage { my $optstr = ""; OPTHELP: foreach my $key ( sort keys %opthelp_of ) { $optstr .= sprintf(" %-25s %s\n", $key, $opthelp_of{$key}); } my $comstr = ""; FUNCTION_HELP: foreach my $key ( sort keys %fnchelp_of ) { $comstr .= sprintf(" %-35s %s\n", $key, @{$fnchelp_of{$key}}[0]); } print <<"EOF"; PlSense is a development tool for Perl. PlSense provides Completion/Help about Module/Function/Variable optimized for context. Usage: plsense [Option] [Command] argument... plsense [Option] -i Option: $optstr Command: $comstr EOF return; } sub show_help { my $cmdnm = shift || ""; $cmdnm =~ s{ ^\s+ }{}xms; $cmdnm =~ s{ \s+$ }{}xms; if ( $cmdnm =~ m{ \A[a-z]+\z }xms ) { FHELP: foreach my $key ( keys %fnchelp_of ) { if ( $key =~ m{ \b $cmdnm \b }xms ) { print "Usage: ".$key."\n\n"; print @{$fnchelp_of{$key}}[0]."\n"; if ( $#{$fnchelp_of{$key}} == 1 ) { print @{$fnchelp_of{$key}}[1]; } return; } } } print "Unknown command : $cmdnm\n"; print "Command name list at the following.\n"; print join("\n", sort keys %function_of)."\n"; return; } sub start_main_server { my $immediately = shift || 0; return start_server_sentinel("main", $immediately); } sub start_work_server { my $immediately = shift || 0; return start_server_sentinel("work", $immediately); } sub start_resolve_server { my $immediately = shift || 0; return start_server_sentinel("resolve", $immediately); } sub start_server_sentinel { my $svtype = shift || ""; my $immediately = shift || 0; my $pid = $pid_of{$svtype}; if ( $pid && kill(0, $pid) ) { return 1; } if ( ! $immediately ) { $pid = $svtype eq "main" ? $scli->get_main_server_response("pid", { ignore_error => 1, maxretry => 5 }) : $svtype eq "work" ? $scli->get_work_server_response("pid", { ignore_error => 1, maxretry => 5 }) : $svtype eq "resolve" ? $scli->get_resolve_server_response("pid", { ignore_error => 1, maxretry => 5 }) : 0; if ( $pid ) { $pid_of{$svtype} = $pid; return 1; } } my $cmdnm = "plsense-server-".$svtype; my $cmdstr = $cmdnm.get_common_option_string(); if ( $svtype eq "work" ) { $cmdstr .= " --maxtasks '".( get_config("maxtasks") || "" )."'"; } logger->info("Start server : $cmdstr"); system "$cmdstr &"; $pid = $svtype eq "main" ? $scli->get_main_server_response("pid", { ignore_error => 1, maxretry => 10 }) : $svtype eq "work" ? $scli->get_work_server_response("pid", { ignore_error => 1, maxretry => 10 }) : $svtype eq "resolve" ? $scli->get_resolve_server_response("pid", { ignore_error => 1, maxretry => 10 }) : 0; if ( ! $pid || ! kill(0, $pid) ) { return 0; } $pid_of{$svtype} = $pid; logger->info("Got pid of $svtype : $pid"); return 1; } sub stop_main_server { return stop_server_sentinel("main"); } sub stop_work_server { return stop_server_sentinel("work"); } sub stop_resolve_server { return stop_server_sentinel("resolve"); } sub stop_server_sentinel { my $svtype = shift || ""; my $pid = $pid_of{$svtype}; if ( $pid && ! kill(0, $pid) ) { $pid_of{$svtype} = undef; return 1; } my $ret = $svtype eq "main" ? $scli->request_main_server("stop", { ignore_error => 1, maxretry => 15 }) : $svtype eq "work" ? $scli->request_work_server("stop", { ignore_error => 1, maxretry => 15 }) : $svtype eq "resolve" ? $scli->request_resolve_server("stop", { ignore_error => 1, maxretry => 15 }) : undef; if ( $ret ) { logger->info("Request stop to $svtype"); $pid_of{$svtype} = undef; return 1; } elsif ( $pid ) { logger->info("Send SIGTERM to $svtype"); kill 'TERM', $pid or logger->error("Failed kill $svtype server"); $pid_of{$svtype} = undef; return 1; } return 1; } sub show_server_status { my $mainstat = $scli->get_main_server_response("status", { ignore_error => 1, maxretry => 5 }); my $workstat = $scli->get_work_server_response("status", { ignore_error => 1, maxretry => 5 }); my $resolvestat = $scli->get_resolve_server_response("status", { ignore_error => 1, maxretry => 5 }); chomp $mainstat; chomp $workstat; chomp $resolvestat; if ( ! $mainstat ) { $mainstat = $pid_of{main} && kill(0, $pid_of{main}) ? "Busy" : "Not running"; } if ( ! $workstat ) { $workstat = $pid_of{work} && kill(0, $pid_of{work}) ? "Busy" : "Not running"; } if ( ! $resolvestat ) { $resolvestat = $pid_of{resolve} && kill(0, $pid_of{resolve}) ? "Busy" : "Not running"; } my $ret = "Main Server is $mainstat.\n"; $ret .= "Work Server is $workstat.\n"; $ret .= "Resolve Server is $resolvestat.\n"; return $ret; } sub start_server { my $cachedir = get_config("cachedir"); if ( ! $cachedir ) { logger->fatal("Required information for cachedir. For more information, run 'plsense --help'"); return; } if ( ! -d $cachedir && ! mkdir($cachedir) ) { logger->fatal("Failed create cache directory [$cachedir]"); return; } if ( ! verify_commands() ) { return; } my $mainret = start_main_server(); my $workret = start_work_server(); my $resolveret = start_resolve_server(); return $mainret && $workret && $resolveret ? "Done\n" : "Failed\n"; } sub stop_server { my $mainret = stop_main_server(); my $workret = stop_work_server(); my $resolveret = stop_resolve_server(); return $mainret && $workret && $resolveret ? "Done\n" : "Failed\n"; } sub refresh_server { my $loc = get_current_location() or return "Failed\n"; my $currfilepath = $loc =~ m{ ^ File: \s+ ([^\n]*?) $ }xms ? $1 : ""; my $currmdlnm = $loc =~ m{ ^ Module: \s+ ([^\n]*?) $ }xms ? $1 : ""; my $currmtdnm = $loc =~ m{ ^ Sub: \s+ ([^\n]*?) $ }xms ? $1 : ""; my @reqsvrs; SVTYPE: foreach my $svtype ( "main", "work", "resolve" ) { my $pid = $pid_of{$svtype}; if ( ! $pid ) { $pid = $svtype eq "main" ? $scli->get_main_server_response("pid", { maxretry => 20 }) : $svtype eq "work" ? $scli->get_work_server_response("pid", { maxretry => 20 }) : $svtype eq "resolve" ? $scli->get_resolve_server_response("pid", { maxretry => 20 }) : 0; $pid_of{$svtype} = $pid; logger->info("Got pid of $svtype : $pid"); } if ( ! $pid ) { logger->error("Can't restart $svtype server cause failed to get pid"); next SVTYPE; } logger->info("Send SIGUSR1 to $svtype"); kill 'USR1', $pid or logger->error("Failed kill $svtype server"); push @reqsvrs, $svtype; } my $reqopt = { ignore_error => 1, retryinterval => 3, maxretry => 100 }; SVTYPE: foreach my $svtype ( @reqsvrs ) { my $pid = $svtype eq "main" ? $scli->get_main_server_response("pid", $reqopt) : $svtype eq "work" ? $scli->get_work_server_response("pid", $reqopt) : $svtype eq "resolve" ? $scli->get_resolve_server_response("pid", $reqopt) : 0; if ( ! $pid ) { logger->error("Can't check $svtype server alive cause failed to get pid"); } $pid_of{$svtype} = $pid; logger->info("Got pid of $svtype : $pid"); } if ( ! $pid_of{main} || ! $pid_of{work} ) { return; } set_currentfile($currfilepath); set_currentmodule($currmdlnm); set_currentmethod($currmtdnm); return "Done\n"; } sub open_file { my $filepath = shift || ""; return $scli->get_work_server_response("open $filepath"); } sub update_file { my $filepath = shift || ""; $scli->request_work_server("buildrf $filepath"); return; } sub remove_file { my $filepath = shift || ""; $scli->request_main_server("remove $filepath"); $scli->request_resolve_server("remove $filepath"); return; } sub remove_all { $scli->get_main_server_response("removeall"); $scli->get_work_server_response("removeall"); $scli->get_resolve_server_response("removeall"); return "Done\n"; } sub help_module { my $mdlnm = shift || ""; return $scli->get_main_server_response("modhelp $mdlnm"); } sub help_method { my $arg = shift || ""; $arg =~ s{ ^\s+ }{}xms; my @e = split m{ \s+ }xms, $arg; my $mtdnm = shift @e || ""; my $mdlnm = shift @e || ""; return $scli->get_main_server_response("subhelp $mtdnm $mdlnm"); } sub help_variable { my $arg = shift || ""; $arg =~ s{ ^\s+ }{}xms; my @e = split m{ \s+ }xms, $arg; my $varnm = shift @e || ""; my $mdlnm = shift @e || ""; return $scli->get_main_server_response("varhelp $varnm $mdlnm"); } sub help_last_assist { my $candidate = shift || ""; return $scli->get_main_server_response("assisthelp $candidate"); } sub help_code { my $code = shift || ""; return $scli->get_main_server_response("codehelp $code"); } sub get_method_information { my $code = shift || ""; return $scli->get_main_server_response("subinfo $code"); } sub set_currentfile { my $filepath = shift || ""; return $scli->get_work_server_response("current $filepath"); } sub set_currentmodule { my $mdlnm = shift || ""; return $scli->get_main_server_response("onmod $mdlnm"); } sub set_currentmethod { my $mtdnm = shift || ""; return $scli->get_main_server_response("onsub $mtdnm"); } sub get_current_location { return $scli->get_main_server_response("location"); } sub add_source { my $code = shift || ""; $scli->request_resolve_server("codeadd $code"); return; } sub assist_coding { my $code = shift || ""; return $scli->get_main_server_response("codeassist $code"); } sub get_process_list { return $scli->get_work_server_response("ps"); } sub get_task_queue { return $scli->get_work_server_response("queue"); } sub is_ready { my $mdl_or_file = shift || ""; return $scli->get_main_server_response("ready $mdl_or_file"); } sub debug_stocked { my $ret = "[MainServer]\n"; $ret .= $scli->get_main_server_response("debugstk"); $ret .= "[ResolveServer]\n"; $ret .= $scli->get_resolve_server_response("debugstk"); return $ret; } sub debug_module { my $mdl_or_file = shift || ""; return $scli->get_main_server_response("debugmod $mdl_or_file"); } sub debug_routing { my $regexp = shift || ""; return $scli->get_main_server_response("debugrt $regexp"); } sub debug_substitute { my $regexp = shift || ""; return $scli->get_resolve_server_response("debugsubst $regexp"); } sub debug_lexer { my $code = shift || ""; return $scli->get_main_server_response("debuglex $code"); } sub update_config { create_global_config() or return; set_primary_config( cachedir => undef, port1 => undef, port2 => undef, port3 => undef, maxtasks => undef, ); setup_config("", 1) or return; return "Finished update config\n"; } sub update_loglevel { my $arg = shift || ""; $arg =~ s{ ^\s+ }{}xms; $arg =~ s{ \s+$ }{}xms; my @e = split m{ \s+ }xms, $arg; my $loglvl = shift @e || ""; my $svtype = lc( shift @e || "" ); if ( $svtype eq "all" || $svtype eq "main" ) { $scli->request_main_server("loglvl $loglvl"); } if ( $svtype eq "all" || $svtype eq "work" ) { $scli->request_work_server("loglvl $loglvl"); } if ( $svtype eq "all" || $svtype eq "resolve" ) { $scli->request_resolve_server("loglvl $loglvl"); } if ( ! $svtype ) { update_logger_level($loglvl); } return; } sub explore_package { my $pkg_regexp = shift || ""; return $scli->get_main_server_response("explore $pkg_regexp"); } sub verify_commands { my @chkcommands = ("which", "perldoc"); CHK_COMMAND: foreach my $command ( @chkcommands ) { my $ret = qx{ which $command 2>/dev/null }; if ( ! $ret ) { logger->fatal("Can't execute '$command'."); return 0; } } return 1; } plsense-0.3.4/bin/plsense-server-main000077500000000000000000000440741260377356000176060ustar00rootroot00000000000000#!/usr/bin/perl use strict; use warnings; use Getopt::Long qw{:config posix_default no_ignore_case gnu_compat}; use IO::Socket; use File::Spec; use PPI::Document; use PPI::Lexer; use PPI::Dumper; use Try::Tiny; use POSIX (); use PlSense::Logger; use PlSense::Configure; use PlSense::SocketClient; use PlSense::Util; use PlSense::Builtin; use PlSense::ModuleKeeper; use PlSense::AddressRouter; use PlSense::AddressFinder; use PlSense::CodeAssist; use PlSense::Helper; my %opthelp_of = ("-h, --help" => "Show this message.", "-c, --cachedir" => "Path of directory caching information for Completion/Help.", "--port1" => "Port number for listening by main server process. Default is 33333.", "--port2" => "Port number for listening by work server process. Default is 33334.", "--port3" => "Port number for listening by resolve server process. Default is 33335.", "--loglevel" => "Level of logging. Its value is for Log::Handler.", "--logfile" => "Path of log file.", "--never-give-up" => "Never give up to listen port", ); my %function_of = (status => \&get_status, pid => \&get_own_pid, init => \&initialize, remove => \&remove, removeall => \&remove_all, removeprojall => \&remove_project_all, modhelp => \&help_module, subhelp => \&help_method, varhelp => \&help_variable, assisthelp => \&help_last_assist, codehelp => \&help_code, subinfo => \&get_method_information, onfile => \&set_currentfile, onmod => \&set_currentmodule, onsub => \&set_currentmethod, location => \&get_current_location, codeassist => \&assist_coding, ready => \&is_ready, debugstk => \&debug_stocked, debugmod => \&debug_module, debugrt => \&debug_routing, debuglex => \&debug_lexer, uninit => \&uninitialize_module, builtin => \&setup_builtin, found => \&setup_found_module, foundp => \&setup_found_project_module, built => \&setup_built_module, resolved => \&setup_resolved, loglvl => \&update_loglevel, explore => \&explore_package, ); my ($cachedir, $port1, $port2, $port3, $loglvl, $logfile, $never_give_up); GetOptions ('help|h' => sub { show_usage(); exit 0; }, 'cachedir|c=s' => \$cachedir, 'port1=i' => \$port1, 'port2=i' => \$port2, 'port3=i' => \$port3, 'loglevel=s' => \$loglvl, 'logfile=s' => \$logfile, 'never-give-up' => \$never_give_up, ); setup_logger($loglvl, $logfile); if ( ! $cachedir || ! -d $cachedir ) { logger->fatal("Not exist cache directory [$cachedir]"); exit 1; } set_primary_config( cachedir => $cachedir, port1 => $port1, port2 => $port2, port3 => $port3, loglevel => $loglvl, logfile => $logfile, ); setup_config() or exit 1; my $scli = PlSense::SocketClient->new({ retryinterval => 0.2, maxretry => 5 }); my ($assist, $helper, $currfilepath, $currmdlnm, $currmtdnm); set_builtin( PlSense::Builtin->new() ); set_mdlkeeper( PlSense::ModuleKeeper->new() ); set_addrrouter( PlSense::AddressRouter->new({ with_build => 0, }) ); set_addrfinder( PlSense::AddressFinder->new({ with_build => 0, }) ); $assist = PlSense::CodeAssist->new(); $helper = PlSense::Helper->new(); my $sock; my $myport = get_config("port1"); SOCK_OPEN: until ( $sock = IO::Socket::INET->new( LocalAddr => "localhost", LocalPort => $myport, Proto => "tcp", Listen => 1, ReUse => 1, ) ) { if ( ! $never_give_up ) { last SOCK_OPEN; } logger->debug("Wait for releasing port : $myport"); sleep 5; } if ( ! $sock ) { logger->fatal("Can't create socket : $!"); exit 1; } if ( ! $sock->listen ) { logger->fatal("Can't listening port [$myport] : $!"); exit 1; } set_signal_handler(); if ( ! initialize() ) { logger->fatal("Failed initialize"); exit 1; } accept_client(); exit 0; sub show_usage { my $optstr = ""; OPTHELP: foreach my $key ( sort keys %opthelp_of ) { $optstr .= sprintf(" %-25s %s\n", $key, $opthelp_of{$key}); } print <<"EOF"; Run PlSense Main Server. Main Server handles request about Completion/Help. Usage: plsense-server-main [Option] Option: $optstr EOF return; } sub set_signal_handler { logger->debug("Start set signal handler"); my $set_stop = POSIX::SigSet->new( &POSIX::SIGINT, &POSIX::SIGTERM ); my $act_stop = POSIX::SigAction->new( sub { logger->notice("Receive SIGINT/SIGTERM"); exit 0; }, $set_stop, &POSIX::SA_NODEFER); my $set_restart = POSIX::SigSet->new( &POSIX::SIGUSR1, &POSIX::SIGHUP ); my $act_restart = POSIX::SigAction->new( sub { logger->notice("Receive SIGUSR1/SIGHUP"); exec $0, get_common_options(), "--never-give-up"; exit 0; }, $set_restart, &POSIX::SA_NODEFER); POSIX::sigprocmask( &POSIX::SIG_UNBLOCK, $set_stop ); POSIX::sigprocmask( &POSIX::SIG_UNBLOCK, $set_restart ); POSIX::sigaction( &POSIX::SIGINT, $act_stop ); POSIX::sigaction( &POSIX::SIGTERM, $act_stop ); POSIX::sigaction( &POSIX::SIGUSR1, $act_restart ); POSIX::sigaction( &POSIX::SIGHUP, $act_restart ); } sub initialize { logger->debug("Start initialize"); setup_config() or return; $currfilepath = ""; $currmdlnm = ""; $currmtdnm = ""; builtin->reset; mdlkeeper->reset; addrrouter->reset; builtin->setup_without_reload(); mdlkeeper->setup_without_reload(); addrrouter->setup_without_reload(); addrrouter->load_current_project; return 1; } sub accept_client { logger->info("Starting main server"); ACCEPT_CLIENT: while ( my $cli = $sock->accept ) { logger->debug("Waiting client ..."); my $line = $cli->getline || ""; chomp $line; logger->info("Receive request : $line"); my $cmdnm = $line =~ s{ ^ \s* ([a-z]+) }{}xms ? $1 : ""; if ( $cmdnm eq "quit" ) { $cli->close; next ACCEPT_CLIENT; } elsif ( $cmdnm eq "stop" ) { $cli->close; last ACCEPT_CLIENT; } elsif ( exists $function_of{$cmdnm} ) { try { my $fnc = $function_of{$cmdnm}; my $ret = &$fnc($line) || ""; $cli->print($ret); $cli->flush; } catch { my $e = shift; logger->error("Failed do $cmdnm : $e"); }; } else { logger->error("Unknown command [$cmdnm]"); } $cli->close; } $sock->close; logger->info("Stopping main server"); } sub update_instance_condition { my $force = shift; my $currmdl = addrfinder->get_currentmodule; if ( $force || ! $currmdl || $currmdl->get_name ne $currmdlnm || $currmdl->get_filepath ne $currfilepath ) { my $mdl = mdlkeeper->get_module($currmdlnm, $currfilepath); if ( ! $mdl ) { if ( ! $currmdlnm ) { logger->error("Not yet set current file/module by onfile/onmod command"); } else { logger->error("Not yet exist [$currmdlnm] of [$currfilepath]"); logger->error("Check the module status is not 'Nothing' by ready command."); } return 0; } addrfinder->set_currentmodule($mdl); $currmdl = $mdl; } my $currmtd = addrfinder->get_currentmethod; if ( $currmtdnm ) { if ( $force || ! $currmtd || $currmtd->get_name ne $currmtdnm ) { my $mtd = $currmdl->get_method($currmtdnm); if ( ! $mtd ) { logger->error("Not found [$currmtdnm] in [$currmdlnm] of [$currfilepath]"); logger->error("Check the module status is 'Yes' by ready command."); return 0; } addrfinder->set_currentmethod($mtd); } } elsif ( $currmtd ) { addrfinder->init_currentmethod; } return 1; } sub get_status { return "Running\n"; } sub get_own_pid { return $$."\n"; } sub remove { my $mdl_or_files = shift || ""; my @mdl_or_files = split m{ \| }xms, $mdl_or_files; ENTRY: foreach my $mdl_or_file ( @mdl_or_files ) { $mdl_or_file =~ s{ ^\s+ }{}xms; $mdl_or_file =~ s{ \s+$ }{}xms; if ( ! $mdl_or_file ) { next ENTRY; } my ($mdlnm, $filepath) = -f $mdl_or_file ? ("main", File::Spec->rel2abs($mdl_or_file)) : ($mdl_or_file, ""); my $mdl = mdlkeeper->get_module($mdlnm, $filepath) or next ENTRY; if ( $filepath ) { foreach my $m ( mdlkeeper->get_bundle_modules($filepath) ) { mdlkeeper->remove_module($m->get_name, $m->get_filepath, $m->get_projectnm); } } else { mdlkeeper->remove_module($mdlnm, $filepath, $mdl->get_projectnm); } } return "Done\n"; } sub remove_all { mdlkeeper->remove_all_module; return "Done\n"; } sub remove_project_all { mdlkeeper->remove_project_all_module; return "Done\n"; } sub help_module { my $mdlnm = shift || ""; $mdlnm =~ s{ ^\s+ }{}xms; $mdlnm =~ s{ \s+$ }{}xms; my $mdl = mdlkeeper->get_module($mdlnm); if ( ! $mdl ) { logger->error("Not found module[$mdlnm]"); return; } return $helper->get_symbol_help_text($mdl); } sub help_method { my $arg = shift || ""; $arg =~ s{ ^\s+ }{}xms; my @e = split m{ \s+ }xms, $arg; my $mtdnm = shift @e || ""; my $mdlnm = shift @e || ""; my $mdl = mdlkeeper->get_module($mdlnm); my $mtd = $mdl ? $mdl->get_any_method($mtdnm) : undef; if ( $mtd ) { return $helper->get_symbol_help_text($mtd); } if ( builtin->exist_method($mtdnm) ) { my $mtd = builtin->get_method($mtdnm); return $helper->get_symbol_help_text($mtd); } my $fullnm = $mdlnm ? $mdlnm."::".$mtdnm : $mtdnm; logger->error("Not found method[$fullnm]"); return; } sub help_variable { my $arg = shift || ""; $arg =~ s{ ^\s+ }{}xms; my @e = split m{ \s+ }xms, $arg; my $varnm = shift @e || ""; my $mdlnm = shift @e || ""; my $mdl = mdlkeeper->get_module($mdlnm); my $var = $mdl && $mdl->exist_member($varnm) ? $mdl->get_member($varnm) : undef; if ( $var ) { return $helper->get_symbol_help_text($var); } if ( builtin->exist_variable($varnm) ) { my $var = builtin->get_variable($varnm); return $helper->get_symbol_help_text($var); } my $fullnm = $mdlnm ? $mdlnm."::".$varnm : $varnm; logger->error("Not found variable[$fullnm]"); return; } sub help_last_assist { my $candidate = shift || ""; $candidate =~ s{ ^\s+ }{}xms; $candidate =~ s{ \s+$ }{}xms; my $any = $assist->get_last_candidate_instance($candidate); return $helper->get_any_help_text($any); } sub help_code { my $code = shift || ""; update_instance_condition() or return; return $helper->get_help_text_by_code($code); } sub get_method_information { my $code = shift || ""; update_instance_condition() or return; return $helper->get_method_info_by_code($code); } sub set_currentfile { my $filepath = shift || ""; $filepath =~ s{ ^\s+ }{}xms; $filepath =~ s{ \s+$ }{}xms; if ( ! -f $filepath ) { logger->error("Not exist file[$filepath]"); return "Failed\n"; } $currfilepath = File::Spec->rel2abs($filepath); $currmdlnm = "main"; $currmtdnm = ""; logger->notice("Set current file is [$currfilepath]"); setup_config($currfilepath); builtin->setup(); mdlkeeper->setup(); addrrouter->setup(); return "Done\n"; } sub set_currentmodule { my $mdlnm = shift || ""; $mdlnm =~ s{ ^\s+ }{}xms; $mdlnm =~ s{ \s+$ }{}xms; $currmdlnm = $mdlnm; $currmtdnm = ""; logger->notice("Set current module is [$currmdlnm]"); return "Done\n"; } sub set_currentmethod { my $mtdnm = shift || ""; $mtdnm =~ s{ ^\s+ }{}xms; $mtdnm =~ s{ \s+$ }{}xms; $currmtdnm = $mtdnm; logger->notice("Set current method is [$currmtdnm]"); return "Done\n"; } sub get_current_location { my $ret = "Project: ".get_config("name")."\n"; $ret .= "File: $currfilepath\n"; $ret .= "Module: $currmdlnm\n"; $ret .= "Sub: $currmtdnm\n"; return $ret; } sub assist_coding { my $code = shift || ""; update_instance_condition() or return; return join("\n", $assist->get_assist($code))."\n"; } sub is_ready { my $mdl_or_file = shift || ""; $mdl_or_file =~ s{ ^\s+ }{}xms; $mdl_or_file =~ s{ \s+$ }{}xms; if ( ! $mdl_or_file ) { return join("\n", map { $_->get_name } mdlkeeper->get_built_modules)."\n"; } my ($mdlnm, $filepath) = -f $mdl_or_file ? ("main", File::Spec->rel2abs($mdl_or_file)) : ($mdl_or_file, ""); my $mdl = mdlkeeper->get_module($mdlnm, $filepath) or return "Not Found\n"; if ( ! $mdl->is_initialized ) { return "No\n"; } return "Yes\n"; } sub debug_stocked { my $ret = mdlkeeper->describe_keep_value; $ret .= addrrouter->describe_keep_value; return $ret; } sub debug_module { my $mdl_or_file = shift || ""; $mdl_or_file =~ s{ ^\s+ }{}xms; $mdl_or_file =~ s{ \s+$ }{}xms; my ($mdlnm, $filepath) = -f $mdl_or_file ? ("main", File::Spec->rel2abs($mdl_or_file)) : ($mdl_or_file, ""); my $mdl = mdlkeeper->get_module($mdlnm, $filepath) or return; return $mdl->to_detail_string; } sub debug_routing { my $regexp = shift || ""; return addrrouter->to_string_by_regexp($regexp); } sub debug_lexer { my $code_or_file = shift || ""; $code_or_file =~ s{ \A\s+ }{}xms; my $doc = -f $code_or_file ? PPI::Document->new( $code_or_file, readonly => 1 ) : PPI::Lexer->new()->lex_source($code_or_file) or return; my $dumper = PPI::Dumper->new($doc) or return; return $dumper->string; } sub uninitialize_module { my $mdl_or_file = shift || ""; $mdl_or_file =~ s{ ^\s+ }{}xms; $mdl_or_file =~ s{ \s+$ }{}xms; my ($mdlnm, $filepath) = -f $mdl_or_file ? ("main", File::Spec->rel2abs($mdl_or_file)) : ($mdl_or_file, ""); my $mdl = mdlkeeper->get_module($mdlnm, $filepath) or return; if ( $filepath ) { foreach my $m ( mdlkeeper->get_bundle_modules($filepath) ) { $m->uninitialized; } } else { $mdl->uninitialized; } return; } sub setup_builtin { builtin->load; return; } sub setup_found_module { my $mdl_or_files = shift || ""; my $is_project = shift || 0; my @mdl_or_files = split m{ \| }xms, $mdl_or_files; ENTRY: foreach my $mdl_or_file ( @mdl_or_files ) { $mdl_or_file =~ s{ ^\s+ }{}xms; $mdl_or_file =~ s{ \s+$ }{}xms; if ( ! $mdl_or_file ) { next ENTRY; } my ($mdlnm, $filepath) = -f $mdl_or_file ? ("main", File::Spec->rel2abs($mdl_or_file)) : ($mdl_or_file, ""); $is_project ? mdlkeeper->get_project_module($mdlnm, $filepath) : mdlkeeper->get_module($mdlnm, $filepath); } $is_project ? logger->info("Finished setup found project module") : logger->info("Finished setup found module"); return; } sub setup_found_project_module { my $mdl_or_files = shift || ""; setup_found_module($mdl_or_files, 1); } sub setup_built_module { my $mdl_or_files = shift || ""; my @mdl_or_files = split m{ \| }xms, $mdl_or_files; ENTRY: foreach my $mdl_or_file ( @mdl_or_files ) { $mdl_or_file =~ s{ ^\s+ }{}xms; $mdl_or_file =~ s{ \s+$ }{}xms; if ( ! $mdl_or_file ) { next ENTRY; } my ($mdlnm, $filepath) = -f $mdl_or_file ? ("main", File::Spec->rel2abs($mdl_or_file)) : ($mdl_or_file, ""); my $mdl = mdlkeeper->load_module($mdlnm, $filepath) or next ENTRY; logger->notice("Finished reload module of '$mdl_or_file'"); } update_instance_condition(1); return; } sub setup_resolved { addrrouter->load_current_project; return; } sub update_loglevel { my $loglvl = shift || ""; $loglvl =~ s{ ^\s+ }{}xms; $loglvl =~ s{ \s+$ }{}xms; update_logger_level($loglvl); set_primary_config(loglevel => $loglvl); return; } sub explore_package { my $pkg_regexp = shift || ""; $pkg_regexp =~ s{ ^\s+ }{}xms; $pkg_regexp =~ s{ \s+$ }{}xms; my $ret = ""; PKG: foreach my $pkg ( grep { ! $pkg_regexp || $_->get_fullnm =~ m{ $pkg_regexp }xms } mdlkeeper->get_packages(1) ) { $ret .= $pkg->get_name." ".$pkg->get_filepath." ".$pkg->get_linenumber.":".$pkg->get_colnumber."\n"; PARENT: for my $i ( 1..$pkg->count_parent ) { $ret .= " > ".$pkg->get_parent($i)->get_name."\n"; } USINGMDL: for my $i ( 1..$pkg->count_usingmdl ) { $ret .= " < ".$pkg->get_usingmdl($i)->get_name."\n"; } MTD: foreach my $mtd ( $pkg->get_own_methods ) { $ret .= " &".$mtd->get_name." ".$mtd->get_linenumber.":".$mtd->get_colnumber."\n"; } $ret .= "\n"; } return $ret; } plsense-0.3.4/bin/plsense-server-resolve000077500000000000000000000302301260377356000203260ustar00rootroot00000000000000#!/usr/bin/perl use strict; use warnings; use Getopt::Long qw{:config posix_default no_ignore_case gnu_compat}; use IO::Socket; use File::Spec; use Try::Tiny; use POSIX (); use PlSense::Logger; use PlSense::Configure; use PlSense::SocketClient; use PlSense::Util; use PlSense::Builtin; use PlSense::ModuleKeeper; use PlSense::AddressRouter; use PlSense::SubstituteKeeper; use PlSense::SubstituteBuilder; use PlSense::ModuleBuilder::PPIBuilder; my %opthelp_of = ("-h, --help" => "Show this message.", "-c, --cachedir" => "Path of directory caching information for Completion/Help.", "--port1" => "Port number for listening by main server process. Default is 33333.", "--port2" => "Port number for listening by work server process. Default is 33334.", "--port3" => "Port number for listening by resolve server process. Default is 33335.", "--loglevel" => "Level of logging. Its value is for Log::Handler.", "--logfile" => "Path of log file.", "--never-give-up" => "Never give up to listen port", ); my %function_of = (status => \&get_status, pid => \&get_own_pid, debugstk => \&debug_stocked, debugsubst => \&debug_substitute, remove => \&remove, removeall => \&remove_all, removeprojall => \&remove_project_all, codeadd => \&add_source, resolve => \&resolve, built => \&setup_built_module, loglvl => \&update_loglevel, ); my ($cachedir, $port1, $port2, $port3, $loglvl, $logfile, $never_give_up); GetOptions ('help|h' => sub { show_usage(); exit 0; }, 'cachedir|c=s' => \$cachedir, 'port1=i' => \$port1, 'port2=i' => \$port2, 'port3=i' => \$port3, 'loglevel=s' => \$loglvl, 'logfile=s' => \$logfile, 'never-give-up' => \$never_give_up, ); setup_logger($loglvl, $logfile); if ( ! $cachedir || ! -d $cachedir ) { logger->fatal("Not exist cache directory [$cachedir]"); exit 1; } set_primary_config( cachedir => $cachedir, port1 => $port1, port2 => $port2, port3 => $port3, loglevel => $loglvl, logfile => $logfile, ); setup_config() or exit 1; my $scli = PlSense::SocketClient->new({ retryinterval => 0.2, maxretry => 100 }); my ($ppibuilder, $currprojnm, $currfilepath, $currmdlnm, $currmtdnm, $nowstoringmdl, $nowresolving); set_builtin( PlSense::Builtin->new() ); set_mdlkeeper( PlSense::ModuleKeeper->new() ); set_addrrouter( PlSense::AddressRouter->new({ with_build => 1 }) ); set_substkeeper( PlSense::SubstituteKeeper->new({ max_entry => 500 }) ); set_substbuilder( PlSense::SubstituteBuilder->new() ); $ppibuilder = PlSense::ModuleBuilder::PPIBuilder->new(); my $sock; my $myport = get_config("port3"); SOCK_OPEN: until ( $sock = IO::Socket::INET->new( LocalAddr => "localhost", LocalPort => $myport, Proto => "tcp", Listen => 1, ReUse => 1, ) ) { if ( ! $never_give_up ) { last SOCK_OPEN; } logger->debug("Wait for releasing port : $myport"); sleep 5; } if ( ! $sock ) { logger->fatal("Can't create socket : $!"); exit 1; } if ( ! $sock->listen ) { logger->fatal("Can't listening port [$myport] : $!"); exit 1; } set_signal_handler(); if ( ! initialize() ) { logger->fatal("Failed initialize"); exit 1; } accept_client(); exit 0; sub show_usage { my $optstr = ""; OPTHELP: foreach my $key ( sort keys %opthelp_of ) { $optstr .= sprintf(" %-25s %s\n", $key, $opthelp_of{$key}); } print <<"EOF"; Run PlSense Resolve Server. Resolve Server resolve information of Substitute/Argument got from module source. Usage: plsense-server-resolve [Option] Option: $optstr EOF return; } sub set_signal_handler { logger->debug("Start set signal handler"); my $set_stop = POSIX::SigSet->new( &POSIX::SIGINT, &POSIX::SIGTERM ); my $act_stop = POSIX::SigAction->new( sub { logger->notice("Receive SIGINT/SIGTERM"); resume_store(); exit 0; }, $set_stop, &POSIX::SA_NODEFER); my $set_restart = POSIX::SigSet->new( &POSIX::SIGUSR1, &POSIX::SIGHUP ); my $act_restart = POSIX::SigAction->new( sub { logger->notice("Receive SIGUSR1/SIGHUP"); resume_store(); exec $0, get_common_options(), "--never-give-up"; exit 0; }, $set_restart, &POSIX::SA_NODEFER); POSIX::sigprocmask( &POSIX::SIG_UNBLOCK, $set_stop ); POSIX::sigprocmask( &POSIX::SIG_UNBLOCK, $set_restart ); POSIX::sigaction( &POSIX::SIGINT, $act_stop ); POSIX::sigaction( &POSIX::SIGTERM, $act_stop ); POSIX::sigaction( &POSIX::SIGUSR1, $act_restart ); POSIX::sigaction( &POSIX::SIGHUP, $act_restart ); } sub initialize { logger->debug("Start initialize"); setup_config() or return; $currprojnm = ""; $currfilepath = ""; $currmdlnm = ""; $currmtdnm = ""; $nowstoringmdl = undef; $nowresolving = undef; builtin->reset; mdlkeeper->reset; substkeeper->reset; builtin->setup_without_reload(); mdlkeeper->setup_without_reload(); substkeeper->setup_without_reload(); builtin->load; substkeeper->load_all; return 1; } sub accept_client { logger->info("Starting resolve server"); ACCEPT_CLIENT: while ( my $cli = $sock->accept ) { logger->debug("Waiting client ..."); my $line = $cli->getline || ""; chomp $line; logger->info("Receive request : $line"); my $cmdnm = $line =~ s{ ^ \s* ([a-z]+) }{}xms ? $1 : ""; if ( $cmdnm eq "quit" ) { $cli->close; next ACCEPT_CLIENT; } elsif ( $cmdnm eq "stop" ) { $cli->close; last ACCEPT_CLIENT; } elsif ( exists $function_of{$cmdnm} ) { try { my $fnc = $function_of{$cmdnm}; my $ret = &$fnc($line) || ""; $cli->print($ret); $cli->flush; } catch { my $e = shift; logger->error("Failed do $cmdnm : $e"); }; } else { logger->error("Unknown command [$cmdnm]"); } $cli->close; } $sock->close; logger->info("Stopping resolve server"); } sub get_needbuild_extmodules { my $mdl = shift; my @ret; PARENT: for my $i ( 1..$mdl->count_parent ) { my $parent = $mdl->get_parent($i); my $m = mdlkeeper->get_module($parent->get_name); if ( $m->is_initialized ) { next PARENT; } push @ret, $parent->get_name; } USINGMODULE: for my $i ( 1..$mdl->count_usingmdl ) { my $usingmdl = $mdl->get_usingmdl($i); my $m = mdlkeeper->get_module($usingmdl->get_name); if ( $m->is_initialized ) { next USINGMODULE; } push @ret, $usingmdl->get_name; } return @ret; } sub update_project_info { # TODO: Location is needed to sync with other server correctly my $loc = $scli->get_main_server_response("location") or return; $currprojnm = $loc =~ m{ ^ Project: \s+ ([^\n]*?) $ }xms ? $1 : ""; $currfilepath = $loc =~ m{ ^ File: \s+ ([^\n]*?) $ }xms ? $1 : ""; $currmdlnm = $loc =~ m{ ^ Module: \s+ ([^\n]*?) $ }xms ? $1 : ""; $currmtdnm = $loc =~ m{ ^ Sub: \s+ ([^\n]*?) $ }xms ? $1 : ""; setup_config($currfilepath); builtin->setup() || ! builtin->is_loaded and builtin->load(); mdlkeeper->setup(); substkeeper->setup(); return 1; } sub resume_store { my $mdl = $nowstoringmdl; if ( $mdl && $mdl->isa("PlSense::Symbol::Module") ) { logger->notice("Resume store module : ".$mdl->get_fullnm); mdlkeeper->store_module($mdl); addrrouter->store_current_project; $nowstoringmdl = undef; } if ( $nowresolving ) { logger->notice("Resume resolve subst/arg"); substkeeper->resolve_substitute; substkeeper->resolve_unknown_argument; addrrouter->store_current_project; $nowresolving = 0; } } sub get_status { return "Running\n"; } sub get_own_pid { return $$."\n"; } sub debug_stocked { my $ret = mdlkeeper->describe_keep_value; $ret .= addrrouter->describe_keep_value; $ret .= substkeeper->describe_keep_value; return $ret; } sub debug_substitute { my $regexp = shift || ""; return substkeeper->to_string_by_regexp($regexp); } sub remove { my $mdl_or_files = shift || ""; my @mdl_or_files = split m{ \| }xms, $mdl_or_files; update_project_info(); ENTRY: foreach my $mdl_or_file ( @mdl_or_files ) { $mdl_or_file =~ s{ ^\s+ }{}xms; $mdl_or_file =~ s{ \s+$ }{}xms; if ( ! $mdl_or_file ) { next ENTRY; } my ($mdlnm, $filepath) = -f $mdl_or_file ? ("main", File::Spec->rel2abs($mdl_or_file)) : ($mdl_or_file, ""); my $mdl = mdlkeeper->get_module($mdlnm, $filepath) or next ENTRY; substkeeper->remove($mdl->get_name, $mdl->get_filepath, $mdl->get_projectnm); } return "Done\n"; } sub remove_all { # Deleting mdlkeeper is entrusted to plsense-server-main # mdlkeeper->remove_all_module; substkeeper->remove_all; return "Done\n"; } sub remove_project_all { # Deleting mdlkeeper is entrusted to plsense-server-main # mdlkeeper->remove_project_all_module; substkeeper->remove_project_all; return "Done\n"; } sub add_source { my $code = shift || ""; if ( update_project_info() ) { substkeeper->resolve_substitute; substkeeper->resolve_unknown_argument; } my $mdl = mdlkeeper->get_module($currmdlnm, $currfilepath); if ( ! $mdl ) { if ( ! $currmdlnm ) { logger->error("Not yet set current file/module by onfile/onmod command"); } else { logger->error("Not yet exist [$currmdlnm] of [$currfilepath]"); logger->error("Check the module status is not 'Nothing' by ready command."); } return; } my $mtd = $currmtdnm ? $mdl->get_method($currmtdnm) : undef; $ppibuilder->build_source($mdl, $mtd, $code); $nowstoringmdl = $mdl; mdlkeeper->store_module($mdl); addrrouter->store_current_project; $nowstoringmdl = undef; my $mdlkey = $mdl->get_name eq "main" ? $mdl->get_filepath : $mdl->get_name; $scli->request_main_server("built $mdlkey"); $scli->request_main_server("resolved"); my @extmdls = get_needbuild_extmodules($mdl); if ( $#extmdls >= 0 ) { $scli->request_work_server("buildr ".join("|", @extmdls)); } return; } sub resolve { $nowresolving = 1; substkeeper->resolve_substitute; substkeeper->resolve_unknown_argument; addrrouter->store_current_project; $nowresolving = 0; $scli->request_main_server("resolved"); return; } sub setup_built_module { my $mdl_or_files = shift || ""; my @mdl_or_files = split m{ \| }xms, $mdl_or_files; update_project_info(); ENTRY: foreach my $mdl_or_file ( @mdl_or_files ) { $mdl_or_file =~ s{ ^\s+ }{}xms; $mdl_or_file =~ s{ \s+$ }{}xms; if ( ! $mdl_or_file ) { next ENTRY; } my ($mdlnm, $filepath) = -f $mdl_or_file ? ("main", $mdl_or_file) : ($mdl_or_file, ""); my $mdl = mdlkeeper->load_module($mdlnm, $filepath) or next ENTRY; substkeeper->load($mdl->get_name, $mdl->get_filepath, $mdl->get_projectnm); logger->notice("Finished reload module of '$mdl_or_file'"); } resolve(); return; } sub update_loglevel { my $loglvl = shift || ""; $loglvl =~ s{ ^\s+ }{}xms; $loglvl =~ s{ \s+$ }{}xms; update_logger_level($loglvl); set_primary_config(loglevel => $loglvl); return; } plsense-0.3.4/bin/plsense-server-work000077500000000000000000000333401260377356000176360ustar00rootroot00000000000000#!/usr/bin/perl use strict; use warnings; use Getopt::Long qw{:config posix_default no_ignore_case gnu_compat}; use IO::Socket; use File::Spec; use File::Basename; use Time::Piece; use Try::Tiny; use POSIX (); use PlSense::Logger; use PlSense::Configure; use PlSense::SocketClient; use PlSense::Util; use PlSense::Builtin; my %opthelp_of = ("-h, --help" => "Show this message.", "-c, --cachedir" => "Path of directory caching information for Completion/Help.", "--port1" => "Port number for listening by main server process. Default is 33333.", "--port2" => "Port number for listening by work server process. Default is 33334.", "--port3" => "Port number for listening by resolve server process. Default is 33335.", "--maxtasks" => "Limit count of task that run on server process.", "--loglevel" => "Level of logging. Its value is for Log::Handler.", "--logfile" => "Path of log file.", "--never-give-up" => "Never give up to listen port", ); my %function_of = (status => \&get_status, pid => \&get_own_pid, removeall => \&remove_all, build => \&build, buildr => \&build_recursive, buildf => \&build_force, buildrf => \&build_recursive_force, buildfr => \&build_recursive_force, open => \&open_file, current => \¤t_file, ps => \&get_process_list, queue => \&get_task_queue, finfind => \&finish_find, finbuild => \&finish_build, loglvl => \&update_loglevel, ); my ($cachedir, $port1, $port2, $port3, $maxtasks, $loglvl, $logfile, $never_give_up); GetOptions ('help|h' => sub { show_usage(); exit 0; }, 'cachedir|c=s' => \$cachedir, 'port1=i' => \$port1, 'port2=i' => \$port2, 'port3=i' => \$port3, 'maxtasks=i' => \$maxtasks, 'loglevel=s' => \$loglvl, 'logfile=s' => \$logfile, 'never-give-up' => \$never_give_up, ); setup_logger($loglvl, $logfile); if ( ! $cachedir || ! -d $cachedir ) { logger->fatal("Not exist cache directory [$cachedir]"); exit 1; } set_primary_config( cachedir => $cachedir, port1 => $port1, port2 => $port2, port3 => $port3, maxtasks => $maxtasks, loglevel => $loglvl, logfile => $logfile, ); setup_config() or exit 1; my $scli = PlSense::SocketClient->new({ retryinterval => 0.2, maxretry => 10 }); my (%taskinfo_of, @taskqueue, $local); set_builtin( PlSense::Builtin->new() ); my $sock; my $myport = get_config("port2"); SOCK_OPEN: until ( $sock = IO::Socket::INET->new( LocalAddr => "localhost", LocalPort => $myport, Proto => "tcp", Listen => 1, ReUse => 1, ) ) { if ( ! $never_give_up ) { last SOCK_OPEN; } logger->debug("Wait for releasing port : $myport"); sleep 5; } if ( ! $sock ) { logger->fatal("Can't create socket : $!"); exit 1; } if ( ! $sock->listen ) { logger->fatal("Can't listening port [$myport] : $!"); exit 1; } set_signal_handler(); if ( ! initialize() ) { logger->fatal("Failed initialize"); exit 1; } accept_client(); exit 0; sub show_usage { my $optstr = ""; OPTHELP: foreach my $key ( sort keys %opthelp_of ) { $optstr .= sprintf(" %-25s %s\n", $key, $opthelp_of{$key}); } print <<"EOF"; Run PlSense Work Server. Work Server manages task that find/build module. Usage: plsense-server-work [Option] Option: $optstr EOF return; } sub set_signal_handler { logger->debug("Start set signal handler"); my $set_stop = POSIX::SigSet->new( &POSIX::SIGINT, &POSIX::SIGTERM ); my $act_stop = POSIX::SigAction->new( sub { logger->notice("Receive SIGINT/SIGTERM"); kill_all_task(); exit 0; }, $set_stop, &POSIX::SA_NODEFER); my $set_restart = POSIX::SigSet->new( &POSIX::SIGUSR1, &POSIX::SIGHUP ); my $act_restart = POSIX::SigAction->new( sub { logger->notice("Receive SIGUSR1/SIGHUP"); kill_all_task(); exec $0, get_common_options(), "--maxtasks", get_config("maxtasks"), "--never-give-up"; exit 0; }, $set_restart, &POSIX::SA_NODEFER); POSIX::sigprocmask( &POSIX::SIG_UNBLOCK, $set_stop ); POSIX::sigprocmask( &POSIX::SIG_UNBLOCK, $set_restart ); POSIX::sigaction( &POSIX::SIGINT, $act_stop ); POSIX::sigaction( &POSIX::SIGTERM, $act_stop ); POSIX::sigaction( &POSIX::SIGUSR1, $act_restart ); POSIX::sigaction( &POSIX::SIGHUP, $act_restart ); } sub initialize { logger->debug("Start initialize"); setup_config() or return; %taskinfo_of = (); @taskqueue = (); $local = 0; add_find_installed_task(); run_task(); builtin->reset; builtin->setup_without_reload(); builtin->build; $scli->request_main_server("builtin", { ignore_error => 1, retryinterval => 0.5, maxretry => 200 }) or return; return 1; } sub accept_client { logger->info("Starting work server"); ACCEPT_CLIENT: while ( my $cli = $sock->accept ) { logger->debug("Waiting client ..."); my $line = $cli->getline || ""; chomp $line; logger->info("Receive request : $line"); my $cmdnm = $line =~ s{ ^ \s* ([a-z]+) }{}xms ? $1 : ""; if ( $cmdnm eq "quit" ) { $cli->close; next ACCEPT_CLIENT; } elsif ( $cmdnm eq "stop" ) { $cli->close; last ACCEPT_CLIENT; } elsif ( exists $function_of{$cmdnm} ) { try { my $fnc = $function_of{$cmdnm}; my $ret = &$fnc($line) || ""; $cli->print($ret); $cli->flush; run_task(); } catch { my $e = shift; logger->error("Failed do $cmdnm : $e"); }; } else { logger->error("Unknown command [$cmdnm]"); } $cli->close; } $sock->close; logger->info("Stopping work server"); } sub run_task { logger->notice("Start run task"); my $now = localtime; my $taskcount = 0; CHK_TIMEOUT: foreach my $key ( keys %taskinfo_of ) { my $task = $taskinfo_of{$key}; if ( $now > $task->{limit} ) { logger->notice("Timeout task : $key"); my $pid = $task->{pid}; if ( $pid && kill(0, $pid) ) { kill 'INT', $pid; } elsif ( $key =~ m{ \A build \s+ (.+) \z }xms ) { my $mdl_or_file = $1; logger->notice("Request reload module of zombie task : $key"); $scli->request_main_server("built $mdl_or_file"); } delete $taskinfo_of{$key}; } else { $taskcount++; } } # do not run task while doing find task my @findtasks = grep { $_ =~ m{ \A find \s+ }xms } keys %taskinfo_of; if ( $#findtasks >= 0 ) { logger->notice("Exit run task cause find task is running"); return; } my $limit = $now + 60 * 10; RUN_TASK: while ( $taskcount < get_config("maxtasks") ) { my $nexttask = shift @taskqueue or last RUN_TASK; my $taskkey = $nexttask->{key}; logger->debug("Next task : $taskkey"); if ( is_running($taskkey) ) { next RUN_TASK; } my $cmd = $nexttask->{cmd}; logger->info("Run task : $cmd"); system "$cmd &"; # TODO: get pid of task $taskinfo_of{$taskkey} = { pid => undef, limit => $limit }; $taskcount++; if ( $taskkey =~ m{ \A find \s+ }xms ) { last RUN_TASK; } } logger->debug("Finish run task"); } sub add_task { my ($taskkey, $cmdstr) = @_; if ( ! $taskkey || ! $cmdstr ) { return; } QUEUE: foreach my $task ( @taskqueue ) { if ( $taskkey eq $task->{key} ) { return; } } push @taskqueue, { key => $taskkey, cmd => $cmdstr }; } sub finish_task { my $taskkey = shift || ""; if ( ! $taskkey ) { return; } logger->info("Finished task : $taskkey"); delete $taskinfo_of{$taskkey}; } sub is_running { my $taskkey = shift || ""; exists $taskinfo_of{$taskkey}; } sub kill_all_task { KILL_TASK: foreach my $key ( keys %taskinfo_of ) { my $task = $taskinfo_of{$key}; my $pid = $task->{pid}; if ( ! $pid ) { next KILL_TASK; } logger->notice("Kill task : $key"); if ( kill(0, $pid) ) { kill 'INT', $pid; } delete $taskinfo_of{$key}; } } sub get_worker_common_option { my $is_project = shift || 0; my $ret = get_common_option_string(); $ret .= " --confpath '".( get_config("confpath") || "" )."'"; if ( $is_project ) { $ret .= " --project"; } return $ret; } sub add_find_task { my ($global, $tasknm, @rootdirs) = @_; logger->notice("Add task find module of $tasknm"); my $cmdstr = "plsense-worker-find".get_worker_common_option($global ? 0 : 1); $cmdstr .= " --tasknm '$tasknm'"; ROOTDIR: foreach my $dir ( @rootdirs ) { $cmdstr .= " --rootdir '$dir'"; } add_task("find $tasknm", $cmdstr); return; } sub add_find_installed_task { my @dirs; my $perl = get_config("perl"); LIBPATH: foreach my $dir ( qx{ $perl -e 'pop \@INC; print join("\\n", \@INC);' } ) { chomp $dir; if ( ! -d $dir ) { next LIBPATH; } push @dirs, $dir; } add_find_task(1, "installed", @dirs); } sub update_location { my $filepath = shift || ""; if ( ! -f $filepath ) { return; } $scli->request_main_server("onfile ".$filepath); my $oldconfpath = get_config("confpath") || ""; setup_config($filepath) or return; my $newconfpath = get_config("confpath") || ""; if ( $oldconfpath eq $newconfpath ) { return; } if ( builtin->setup() ) { builtin->build; $scli->request_main_server("builtin"); } my $newlocal = get_config("local"); if ( $local || $newlocal ) { add_find_installed_task(); } $local = $newlocal; my $newlibpath = get_config("lib-path") || ""; if ( -d $newlibpath ) { add_find_task(0, get_config("name"), $newlibpath); } return 1; } sub build_sentinel { my $mdl_or_files = shift || ""; my $recursive = shift || 0; my $force = shift || 0; my @mdl_or_files = split m{ \| }xms, $mdl_or_files; ENTRY: foreach my $mdl_or_file ( @mdl_or_files ) { $mdl_or_file =~ s{ ^\s+ }{}xms; $mdl_or_file =~ s{ \s+$ }{}xms; if ( ! $mdl_or_file ) { next ENTRY; } my $target = -f $mdl_or_file ? File::Spec->rel2abs($mdl_or_file) : $mdl_or_file; my $taskkey = "build ".$target; if ( is_running($taskkey) ) { logger->info("Quit build '$mdl_or_file'. It's now building or build already"); next ENTRY; } logger->notice("Add task build '$mdl_or_file'. recursive[$recursive]"); my $cmdstr = "plsense-worker-build".get_worker_common_option(); $cmdstr .= " --target '$target'"; if ( $recursive ) { $cmdstr .= " --recursive"; } if ( $force ) { $cmdstr .= " --force"; } add_task($taskkey, $cmdstr); } return; } sub get_status { return "Running\n"; } sub get_own_pid { return $$."\n"; } sub remove_all { kill_all_task(); builtin->remove; return "Done\n"; } sub build { my $mdl_or_files = shift || ""; build_sentinel($mdl_or_files, 0); } sub build_recursive { my $mdl_or_files = shift || ""; build_sentinel($mdl_or_files, 1); } sub build_force { my $mdl_or_files = shift || ""; build_sentinel($mdl_or_files, 0, 1); } sub build_recursive_force { my $mdl_or_files = shift || ""; build_sentinel($mdl_or_files, 1, 1); } sub open_file { my $filepath = shift || ""; $filepath =~ s{ ^\s+ }{}xms; $filepath =~ s{ \s+$ }{}xms; if ( ! -f $filepath ) { logger->error("Not exist file[$filepath]"); return "Failed\n"; } update_location($filepath); build_sentinel($filepath, 1, 0); return "Done\n"; } sub current_file { my $filepath = shift || ""; $filepath =~ s{ ^\s+ }{}xms; $filepath =~ s{ \s+$ }{}xms; if ( ! -f $filepath ) { logger->error("Not exist file[$filepath]"); return "Failed\n"; } update_location($filepath); return "Done\n"; } sub get_process_list { return join("\n", sort keys %taskinfo_of)."\n"; } sub get_task_queue { my @ret; QUEUE: for my $i ( 0..$#taskqueue ) { push @ret, $taskqueue[$i]->{key}; } return join("\n", @ret)."\n"; } sub finish_find { my $tasknm = shift || ""; $tasknm =~ s{ ^\s+ }{}xms; $tasknm =~ s{ \s+$ }{}xms; if ( ! $tasknm ) { return; } finish_task("find $tasknm"); return; } sub finish_build { my $mdl_or_file = shift || ""; $mdl_or_file =~ s{ ^\s+ }{}xms; $mdl_or_file =~ s{ \s+$ }{}xms; if ( ! $mdl_or_file ) { return; } my $taskkey = "build ".$mdl_or_file; finish_task($taskkey); return; } sub update_loglevel { my $loglvl = shift || ""; $loglvl =~ s{ ^\s+ }{}xms; $loglvl =~ s{ \s+$ }{}xms; update_logger_level($loglvl); set_primary_config(loglevel => $loglvl); return; } plsense-0.3.4/bin/plsense-worker-build000077500000000000000000000152751260377356000177650ustar00rootroot00000000000000#!/usr/bin/perl use strict; use warnings; use Getopt::Long qw{:config posix_default no_ignore_case gnu_compat}; use IO::Socket; use List::AllUtils qw{ uniq }; use Try::Tiny; use PlSense::Logger; use PlSense::Configure; use PlSense::SocketClient; use PlSense::Util; use PlSense::Builtin; use PlSense::ModuleKeeper; use PlSense::AddressRouter; use PlSense::SubstituteKeeper; use PlSense::SubstituteBuilder; use PlSense::ModuleSrcUpdater; use PlSense::ModuleBuilder::XrefBuilder; use PlSense::ModuleBuilder::InheritBuilder; use PlSense::ModuleBuilder::DocBuilder; use PlSense::ModuleBuilder::PPIBuilder; my ($cachedir, $port1, $port2, $port3, $confpath, $mdl_or_file, $recursive, $force, $loglvl, $logfile); GetOptions ('cachedir=s' => \$cachedir, 'port1=i' => \$port1, 'port2=i' => \$port2, 'port3=i' => \$port3, 'confpath=s' => \$confpath, 'target=s' => \$mdl_or_file, 'recursive' => \$recursive, 'force' => \$force, 'loglevel=s' => \$loglvl, 'logfile=s' => \$logfile, ); setup_logger($loglvl, $logfile); if ( ! -d $cachedir ) { logger->crit("Not exist cache directory [$cachedir]"); exit 1; } set_primary_config( cachedir => $cachedir, port1 => $port1, port2 => $port2, port3 => $port3, loglevel => $loglvl, logfile => $logfile, ); setup_config($confpath) or exit 1; set_builtin( PlSense::Builtin->new() ); set_mdlkeeper( PlSense::ModuleKeeper->new() ); set_addrrouter( PlSense::AddressRouter->new({ with_build => 1, }) ); set_substkeeper( PlSense::SubstituteKeeper->new() ); set_substbuilder( PlSense::SubstituteBuilder->new() ); my $scli = PlSense::SocketClient->new({ retryinterval => 0.5, maxretry => 300 }); my $srcupdater = PlSense::ModuleSrcUpdater->new(); my $xrefbuilder = PlSense::ModuleBuilder::XrefBuilder->new(); my $inheritbuilder = PlSense::ModuleBuilder::InheritBuilder->new(); my $docbuilder = PlSense::ModuleBuilder::DocBuilder->new(); my $ppibuilder = PlSense::ModuleBuilder::PPIBuilder->new(); my (@builtmdls, @builtmdlkeys, @extmdls); $SIG{INT} = sub { logger->notice("Receive SIGINT"); interrupt_build(); exit 0; }; $SIG{TERM} = sub { logger->notice("Receive SIGTERM"); interrupt_build(); exit 0; }; try { builtin->setup_without_reload(); builtin->build(); mdlkeeper->setup_without_reload(); addrrouter->setup_without_reload(); substkeeper->setup_without_reload(); my ($filepath, $mdl); if ( -f $mdl_or_file ) { $filepath = $mdl_or_file; $mdl = mdlkeeper->get_module("main", $filepath); } else { $mdl = mdlkeeper->get_module($mdl_or_file); if ( ! $mdl ) { logger->warn("Not found module named [$mdl_or_file]"); finish_build(); exit 1; } $filepath = $mdl->get_filepath; if ( ! $filepath || ! -f $filepath ) { mdlkeeper->remove_module($mdl->get_name, $mdl->get_filepath, $mdl->get_projectnm); finish_build(); exit 1; } } my @attr = stat $filepath; my $lastmodified = $attr[9]; if ( ! $force && $mdl && $mdl->is_initialized && $lastmodified == $mdl->get_lastmodified ) { logger->info("Already build [$mdl_or_file]"); finish_build(get_extmodules($mdl)); exit 0; } my $perl = get_config("perl"); my $libopt = get_config("lib-path") ? "-I'".get_config("lib-path")."'" : ""; if ( system("$perl $libopt -c '$filepath' 2>/dev/null") ) { logger->error("Failed compile '$filepath'"); finish_build(); exit 1; } my @mdls = $srcupdater->update_or_create_modules($filepath, $mdl ? $mdl->get_projectnm : get_config("name")); if ( ! -f $mdl_or_file ) { @mdls = ($mdl); } MDL: foreach my $mdl ( @mdls ) { my $mdlkey = $mdl->get_name eq "main" ? $mdl->get_filepath : $mdl->get_name; substkeeper->reset; logger->notice("Start build [".$mdl->get_name."] : XRef part"); $xrefbuilder->build($mdl); logger->notice("Start build [".$mdl->get_name."] : Inherit part"); $inheritbuilder->build($mdl); logger->notice("Start build [".$mdl->get_name."] : Perldoc part"); $docbuilder->build($mdl); logger->notice("Start build [".$mdl->get_name."] : PPI part"); $ppibuilder->build($mdl); if ( ! $scli->get_resolve_server_response("remove $mdlkey") ) { next MDL; } $mdl->set_source(undef); $mdl->initialized; mdlkeeper->store_module($mdl); substkeeper->resolve_unknown_argument; substkeeper->store($mdl->get_name, $mdl->get_filepath, $mdl->get_projectnm); push @builtmdls, $mdl; push @builtmdlkeys, $mdlkey; push @extmdls, get_extmodules($mdl); logger->notice("Finished build [".$mdl->get_name."]\n".$mdl->to_detail_string); } } catch { my $e = shift; logger->error("Failed build '$mdl_or_file' : $e"); }; @extmdls = uniq(sort @extmdls); if ( $#builtmdlkeys >= 0 ) { logger->notice("Request reload modules : ".join(", ", @builtmdlkeys)); $scli->request_main_server("built ".join("|", @builtmdlkeys)); if ( ! $scli->request_resolve_server("built ".join("|", @builtmdlkeys)) ) { interrupt_build(); } } finish_build(@extmdls); exit 0; sub finish_build { my @extmdls = @_; if ( $#extmdls >= 0 ) { logger->notice("Request build extmodules : ".join(", ", @extmdls)); $scli->request_work_server("buildr ".join("|", @extmdls)); } $scli->request_work_server("finbuild $mdl_or_file"); } sub get_extmodules { my ($mdl, $found_is) = @_; my @ret; if ( ! $recursive ) { return @ret; } if ( ! $found_is ) { $found_is = {}; } if ( $found_is->{$mdl->get_name} ) { return @ret; } $found_is->{$mdl->get_name} = 1; PARENT: for my $i ( 1..$mdl->count_parent ) { my $parent = $mdl->get_parent($i); my $m = mdlkeeper->get_module($parent->get_name); if ( $m->is_initialized ) { push @ret, get_extmodules($m, $found_is); } else { push @ret, $parent->get_name; } } USINGMODULE: for my $i ( 1..$mdl->count_usingmdl ) { my $usingmdl = $mdl->get_usingmdl($i); my $m = mdlkeeper->get_module($usingmdl->get_name); if ( $m->is_initialized ) { push @ret, get_extmodules($m, $found_is); } else { push @ret, $usingmdl->get_name; } } return uniq(sort @ret); } sub interrupt_build { BUILTMDL: foreach my $mdl ( @builtmdls ) { $mdl->uninitialized; mdlkeeper->store_module($mdl); } } plsense-0.3.4/bin/plsense-worker-find000077500000000000000000000141021260377356000175720ustar00rootroot00000000000000#!/usr/bin/perl use strict; use warnings; use Getopt::Long qw{:config posix_default no_ignore_case gnu_compat}; use IO::Socket; use Try::Tiny; use PlSense::Logger; use PlSense::Configure; use PlSense::SocketClient; use PlSense::Util; use PlSense::ModuleKeeper; use PlSense::Symbol::Module; my ($cachedir, $port1, $port2, $port3, $confpath, $is_project, $tasknm, $loglvl, $logfile, @dirs); GetOptions ('cachedir=s' => \$cachedir, 'port1=i' => \$port1, 'port2=i' => \$port2, 'port3=i' => \$port3, 'confpath=s' => \$confpath, 'project' => \$is_project, 'tasknm=s' => \$tasknm, 'rootdir=s' => \@dirs, 'loglevel=s' => \$loglvl, 'logfile=s' => \$logfile, ); setup_logger($loglvl, $logfile); if ( ! -d $cachedir ) { logger->crit("Not exist cache directory [$cachedir]"); exit 1; } set_primary_config( cachedir => $cachedir, port1 => $port1, port2 => $port2, port3 => $port3, loglevel => $loglvl, logfile => $logfile, ); setup_config($confpath) or exit 1; set_mdlkeeper( PlSense::ModuleKeeper->new() ); my $scli = PlSense::SocketClient->new({ retryinterval => 0.5, maxretry => 200 }); my $projectnm = get_config("name"); my $nowstoringmdl = undef; my (@mdl_or_files, @needbuild, @firstbuild, %found_is, %lastmodified_of); $SIG{INT} = sub { logger->notice("Receive SIGINT"); resume_store(); exit 0; }; $SIG{TERM} = sub { logger->notice("Receive SIGTERM"); resume_store(); exit 0; }; mdlkeeper->setup_without_reload(); LIBPATH: foreach my $dir ( @dirs ) { chomp $dir; if ( ! $dir || ! -d $dir ) { logger->error("Not given or not exist directory : $dir"); next LIBPATH; } $dir = File::Spec->rel2abs($dir); logger->debug("Start find module in [$dir]"); LINE: foreach my $line ( qx{ find "$dir" -follow -name '*.pm' -type f -print0 | xargs -0 egrep -H -o '^package\\s+[a-zA-Z0-9_:]+\\s*;' } ) { if ( $line !~ m{ \A ( .. [^:]* \.pm ) : package \s+ ([a-zA-Z0-9:]+) \s* ; }xms ) { next LINE; } my ($filepath, $mdlnm) = ($1, $2); try { my $lastmodified = $lastmodified_of{$filepath}; if ( ! $lastmodified ) { my @attr = stat $filepath; $lastmodified = $attr[9]; $lastmodified_of{$filepath} = $lastmodified; } MDL: foreach my $mdlnm ( "main", $mdlnm ) { my $mdl = $is_project ? mdlkeeper->get_project_module($mdlnm, $filepath) : mdlkeeper->get_module($mdlnm, $filepath); if ( ! $mdl ) { logger->info("Found not yet stored module [$mdlnm] in [$filepath]"); $mdl = PlSense::Symbol::Module->new({ name => $mdlnm, filepath => $filepath, projectnm => $is_project ? $projectnm : "", lastmodified => $lastmodified }); logger->notice("New module [".$mdl->get_name."] in [".$mdl->get_filepath."] belong [".$mdl->get_projectnm."]"); $nowstoringmdl = $mdl; mdlkeeper->store_module($mdl); $nowstoringmdl = undef; if ( $is_project ) { my $mdlkey = $mdl->get_name eq "main" ? $mdl->get_filepath : $mdl->get_name; push @firstbuild, $mdlkey; } } my $mdlkey = $mdl->get_name eq "main" ? $mdl->get_filepath : $mdl->get_name; if ( $found_is{$mdlkey} ) { next MDL; } $found_is{$mdlkey} = 1; if ( $mdl->get_name ne "main" ) { push @mdl_or_files, $mdlkey; } # The not yet built module don't need to be built in find process. my $needbuild = $mdl->is_initialized; if ( $lastmodified != $mdl->get_lastmodified && $mdl->get_filepath eq $filepath && $needbuild ) { push @needbuild, $mdlkey; } elsif ( $mdl->get_filepath ne $filepath && $mdl->get_projectnm eq $projectnm ) { logger->info("Found moved module [$mdlnm] from [".$mdl->get_filepath."] to [$filepath]"); $mdl = PlSense::Symbol::Module->new({ name => $mdlnm, filepath => $filepath, projectnm => $is_project ? $projectnm : "", lastmodified => $lastmodified }); logger->notice("New module [".$mdl->get_name."] in [".$mdl->get_filepath."] belong [".$mdl->get_projectnm."]"); $nowstoringmdl = $mdl; mdlkeeper->store_module($mdl); $nowstoringmdl = undef; if ( $needbuild ) { push @needbuild, $mdlkey; } } } } catch { my $e = shift; logger->error("Failed find module from line : $e"); }; } logger->notice("Finished find modules in $dir"); } if ( $#mdl_or_files >= 0 ) { $is_project ? $scli->request_main_server("foundp ".join("|", @mdl_or_files)) : $scli->request_main_server("found ".join("|", @mdl_or_files)); } if ( $#needbuild >= 0 ) { logger->notice("Request build updated/moved modules : ".join(", ", @needbuild)); $scli->request_work_server("buildrf ".join("|", @needbuild)); } if ( $#firstbuild >= 0 ) { logger->notice("Request build project modules : ".join(", ", @firstbuild)); $scli->request_work_server("buildr ".join("|", @firstbuild)); } $scli->request_work_server("finfind $tasknm"); exit 0; sub resume_store { my $mdl = $nowstoringmdl; if ( $mdl && $mdl->isa("PlSense::Symbol::Module") ) { mdlkeeper->store_module($mdl); $nowstoringmdl = undef; } } plsense-0.3.4/cpanfile000066400000000000000000000012321260377356000147020ustar00rootroot00000000000000on 'develop' => sub { requires 'Module::Install'; requires 'Module::Install::CPANfile'; requires 'Module::Install::AuthorTests'; requires 'Module::Install::Repository'; }; on 'test' => sub { requires 'Test::More', '>= 0.98, < 2.0'; requires 'Carton'; }; requires 'Cache::FileCache'; requires 'Class::Std' => 0.011; requires 'Class::Std::Storable'; requires 'Config::Tiny' => 2.14; requires 'List::AllUtils' => 0.03; requires 'Log::Handler' => 0.76; requires 'Module::Pluggable' => 3.9; requires 'PPI::Document' => 1.215; requires 'PPI::Dumper' => 1.215; requires 'PPI::Lexer' => 1.215; requires 'Time::Piece' => 1.20_01; requires 'Try::Tiny' => 0.11; plsense-0.3.4/ignore.txt000066400000000000000000000002301260377356000152170ustar00rootroot00000000000000blib* Makefile Makefile.old Build Build.bat _build* pm_to_blib* *.tar.gz .lwpcookies cover_db pod2htm*.tmp PlSense-* README.* README-ja.* plsense-0.3.4/image/000077500000000000000000000000001260377356000142625ustar00rootroot00000000000000plsense-0.3.4/image/demo.gif000066400000000000000000034614201260377356000157070ustar00rootroot00000000000000GIF89a{:'$4$ +#2$/,/06GU5DTH5+Mop*1,  @b~SG ƪnE/G?U R# ! M[`xTc~!Q`@"pX!y1$'IJZ/ +pLz5÷,*q 1!KMU=юfTjt;1*s2F=9dFX+A`4a Cd0ak8[L:v+$QNQPYspǕ(ICᜢ0 W;_XJ`q| xK>[ BmYEO 0i tVa(He@ Pxrғp(wCyO s?!PgqLh'[0cL=@-3J4w¯rDAw|eܪ=$AbrnMa@P}m>w.oOsV@<*A;LvGڮGLT*dUPL Ѐ >e-q @9pDc I,rЀ"[׈܀ 4A!@iY7s2`rQbPD܄p,؅4>~9Qf#>8&P 8S&7! =C(eҘδb֓,f3jݧF4Ա^`":fhc9tjHC.ebJc'΅9$Bj)4UGWzO 8pr=Mot:jҢ+U} #b7o8^c樷7+]- V^Yeuԣ[ݗq@:Uoiy.~ Ze?OI>u^b` bB,xY-pƖN]Cwxt/> G0RGVAr[9qts`gOOԴz#gdu+okfUcG;.?}[Oy%t=q{`f,$g)wK4Œ¬Hx3O}I~ Oao}$G}G ~ yWrxh'6tT)vG7yX&xǁ]DG"|(28i&G<؃><?XFx2[#NP&JȄ0VxXSvM^`q6XxKȅUjlIcȂjwgmXv[8w|؇P~8ȃtXxC؅HD8Wp(tof&BewZon`fȑ @Q܀Q ` 0%,SaevfZA4h@f;aj@* Ja=7"ܘz. `(怋h 0_Ј@ ڡИu bШ ԑ` +ӆ xfGQW) q"vaR u}A  GÍ Q-%6 ^FAf$^&] BՐ) Q *:Yw% Bx9AP wwx %ljgFh Ǡ hfqo98Іhgu.ҌHѨrSxa~JiyJA.(PA0H' ؏3 @h#w 99m hFɑ'XQ Ѡ,0Q&Yؙ+9H$#A&aCԛQ"A Q)HDQg!])EQ2 qh)jm)  NGўx$ 'A$z#9 á J PD C :8zW 8L k陌I%i~Iz#7Q(@njrwzka!%}5E2ȁѠG'B&APD)\0M%$181 %K:GIIyk`5XE GYJ.RGzY E$p@` ᰤQej0R{8]yɑdjGsҷ22?s:pZm0 #6aNz"3zC0JT EjH L 0UWwAf(–ajfcZ%f{h*) YW%svxZI"[t3^&Zƺ* BP#$>UQ Z 2 (RWpް/S%}:6ʠ P#5$ *=u:pv96"araت z,PT?%82h zeD`]zX\vS(Ho'3zO c0 9b$x{OPK#,=ʯifˑ W ' 3A5 7rs:Gq"@= +@rqtD\{)5ai$9:B:(PDrqdQ+[#9Xe {{{Q{"tqt`=S ׷D%q2%P5ZTO> 2#RAc0+5@ ;?Nuarc=*"t7J#1k#e KkANeKA% U ?AM'cAE`@" tA #Ҹ2U+q?S@3@p)ZRy@sA{C0r- lAsɂ_ dfVG0,#T@>0gL@2()[L0?߰þl$8AdyIRZ9.0J\ - #EGva`0[ERS\G # ^H(*}'M} [_=WpL&dF+2m ׇE+HV@֊ ]R p]ڭbP)JM0WDYp_ݖt D>z ЉJ2 x]ǔͩݱ)ҦW-ЉҭKLrٱbg5 P'B&@Cʠ:c0а A#[E*`ˊUV_mt 8hM JrS,R# 4G!(UV 5Q} ]-7O<%VFP @ ² W1 3 oL2MMܱ ΰ nRPE=K9m=^(m-'7^AϠ:QНmT< g ((0Nm`@(N~v# kN,qZ9SG¡U*@Bte[`*0{ 1Sױ[.Lٰ#0"ܩ\Su[?tiߠ͇**0;G а$e9W(\.ZnRnB-  pn-EY N?SgM5uTRM7QT66UաKa8D P))QIs IӭTgU }gzh6h#\'JC V2rjZ*f%0 HQ&&0;EEW&.^1GY~ \T(Y _z!B vÄ9fhdiZ)+Ϧv d&u>,8Y eq)S8{BzqF20Za<(BzQGYj ]hcjEvpfg!`8}(8'sT#ِ և(7xA `BÅ4NkT| !jx !j!>4.0ț:¡ m *6BB,-~ hB-|Ǻh*X(H4;H8 x٘ SH7@~〲 p jHM"b79BD081Bb` "PR$e)MyJTHiBb$'AIJTZea_^+3n!yCyxF9Ʊsd8Rvo`F;!q /հ\/ bp7'mfJ6_̢!D>It4f\&:a9Ɏv5qbO5'pAQ PހؠqpJΡ9c(f8rHm#kq $k8F; c(@i (9\8]"p)sU4a`f6(Gk܊c)3A]=eu#S◷ ^Uh"u(@!_d(_Bi ?Ua8aIbLkJc19 j`.܎b@9!vD2dTbϨ(A7rhtV7)| 7M^\EF;ao(:a] f>GCz C:)DŽku&01MՈh57r>@TqksCK0mp[nutWBMS[w[Cp&r_^7v==v1o5XpO*wa\0 nL5x01( [li;hqlSDLbŲP^:x7‰PF촌 ڗ@ C#8SC&-GrxH- O\0Y;Pe %5B ne\GWΊ\57n~炱b۷.}VԢL~q)y ZѪ =~IxP7Q Cá/PjV>_Bf-)&$ :x͔N9I_8=_zKe e 6}g_127ʧRjT: Hl5ET ?_2P9^DN%K\3>@9 r2a@@ @ @>t ?b;-??껾;@@SAQ6A96A  t#/y; A$LB%\.u?;Ah{DIɯ˾D$3DztB&BB!9C>C?4'ltZ*D?< +.|/TA1lA+SJãYChC8L?| dlJdCT,%L4MA{DflEARC#ChFl |E($DEB\BFLA^H?9:ƢIF\FOdvݪij,F|G AYpL,SGdGPA%x$yg\gQB~d?kH,I,@YB!Eq\H]lDyD FMHQȡMI|; |ɓLJ\JIXUčdJJJJTr(,DJ KK,K\ƃqpQTw%F*Bpl"^Tf0?{Aݷi7 r"i@:d2)o X@a .ySKV4sk%hv`Y`r t!QiZ_ W=JA069 O0X tX@D Bx AzO0z͈ 15O/e\@ E`h0뀉OxZy܌]uPMOɅUԍb`s݊HM]]\Ӂ% yЕQw ȈF εPHȋĕϕᆗE[-_tLATywأkX u^菄x e xeTQ닗% ^r .uĀp(wlE:WPX fwK FhN:IpSA`P`0y`zЅad]^_Ox޽ aA`^aFma+.Ӷ( O_-2V[ PJFDv҅XHpa'BGH B/pر@XED ,pЕ* "(ո@@EpehN!aKdVBɘ1 ?cH YQDX,`@_>E\@dEM+]{YcѠgH^ +8 [et > 젧q&rH` |2c|F[4cw#=8~׾8;<c˸OI_rc- .H w`m)z^Rhjh(evfaE hsd jن" ƪКf`ln4nfNcZ!D9,[Ah{gV4&ƥ2Ef8mv = (o8 pfOl&)xX C=(Ykx=t9aI6>hiyD;jqH\FT WcqFnxHw4 D학Ƌ@{Њ@Np<9kR4&`sЅnb0RjVhxH op~`0lwҊ>Dʞz<zi(p0u ݙ `ڟm{٦2ҭlqpmF+n{b떆0]6`NjqI-S4(VnrEcy) _@ЏƖ m+e>ŋE oSx0 y`lq&ƛ{t4 vvyl_x䖦bs<I= ryh8@wzt HF +9M#ur_ϴ- IqN,i o1Yx=iwE cpaUjhvXq[)My=yFƸ6AwtVAwnYIygztuiYƐ'  r> cbiWuqcZ@Zuϴ*ӻpa-&pP,G ;HډiXІ_1(andABPXx(E7Lj&R0#N#>8U@F1 =H6R4Qq*JH{= !kʅ,@zDgZWs BrpVE!ρ>~}DciXu6C -s@9ؚ밯RSmZ8Σ_5t[`hS$ԖBF\bfV-@$ֶϼz/.l0Ċ3n1Ȓ'SV\2̕±:r-4ǍQ;"{U_=k r `=v8evxlgL vS*4A1| #(A<2K5&-IUm1Ϛ| ␆7Q.nzJfA`Cp7>!(Vp3Aח%&wj{v~NgH UxÅdh@Ćo75n|#"^0`~6 %^p1>ͩSz [u:јFʱ$&3M G\h9͘C$Oxʊ #%9D.2yUoFP%0)a˓] +W.H A,Ā qc3AiiG/QH'%/}_iQ<$Hs$>7$1A"p袜-T2h.HÞ$@c*әҴB((GH"DD@9"yGF|! :PS=\)ZӪֵUJ8E ItS(A &!M{K-AS!.(aG M}H%;{m,f3v,(1CWhzpDd݀*^ A 9 ʶ8S~Y,r ӳ%yIO2Z ׺RI *Aio >9d.|+ѹTfWuK تG3 D(Bmy[]wG'poK s}u*WբD"Tp8%l[F6 l ư?,!L q\C{p誵2B+1#J<<)zHqP.(e.GUA}F\3eĚ5ISE2h5rK$1>ӯ~áJ?_T `. 6 F V f v r V 2   j 6!>^߭!6!F!bV!f!v!^!!!!V!!!v! "!* ""j!&"#"6"$#F"%$V"&Nݸ)e"( %")("*b)"+*",+"-,".-"/>."02/#10#21r26#4Z3F#5F4V#6&YE'f#86"a7#: 9^:#]<֣aУ=c`>#_?֍ $B @&?.$CC>=FD#EVd:^$FFnd6vGV#Hd4$I6Id2J#Kd0$LLd.֤M"Nd,$OOd*P"Qe(%RfR.e%6SF"TFe#N%U&U^e!fV"Wve~%XXeY!Ze%[[eƥ\!]e%^f^e_F!`f&aaf&b c6f>&d֠dNf Ve fff n&gg~fhv if&jVjfk6 l&mmnof&pZ A`p֣p&'-'sj`q!ssVg]'vz`t&'.vfdwv7gxrxv9y~dz;c{bvէ}^~ A "~( ( u(1(> &qʧ$N^(Mf6~'(0F(gNz('{(,dh&.h*:''h"Vi])Nn.zSi>)q#|A')#v)杝婞)J!R%Za*_F*VN*n^Wf%v)!jΥɽ**ʪ^\*ڥj^%_+ .ka6"&FbN+:^kdfR&ve~+jkg&h+kjƫ&k+ʦkm&n,lp& t~(6l>,N,«F"r웦i;jlŎ,ʊiV˾vlͪ,zj,B 1ђ_&r--&>m!'V~^-'l`Ԇm[-ٮٞmZJֶ-Δέ%_?-jbג*͂Bgಬ.nĒ*.w2.f,.b>nn.0u"ކn.j鞮*^n%."ή֮R8^)j /^"~6&ʩJ, j.~.)//>֬^/f]0/*op0/6G0L0{_3BW\w0|0K# O 50 𷭰 7 װ0 d1Þ137z/W1JR1;wo`1c1辰sq_1q}q1Son]!""'2r ;CKS[2{RA` F `.2'' ,o?pr| Ȁ 0A*@r,)!в*2!r/\*d(.r.2$P'@+/4c'+!PA'S!B)1s8['39,9;4dz>ӳ;B*3?s?@t@=tB<3;3>3DG.@=sFkr4C[7G3BtMtCs.IOJtA[4LLjMSt7tL N3I34=55OQ4RRsO7QtTaQ5HUK5SSuUsuWKSVXcTSqZpV;U5uSPӵB]u5ٵV56 `ϵap\b/v \5dtcS4agne{d;6eou6f?6hǙh5Zvd_6jj1bOvj66>g(v6^'n#ql{lm6qo6&woCs6t3+O-7rcWvs7}ig(zxh7zwzowz5XG[|,X÷twvp|w Ѿq 8}w?"6x|S8#}5C~vgx#C8i8fx7{x7`Ȍ]ȣKWL>W_>gSAā@{槾S>¯>Ǿ>׾>~ȇ8@ٳ>??GLkQTҬ@ڵ5_Ub%riڊĵ~ $BFlQ&-@,0v#qCAf[Y܎p}NG=c^ [Z@k-HXr|[KV#.C0-s^I DaaycS T"gK$<6sf +x{@ǂ  b=§.,x'AeB7#QlV@,tѹ PTWXzx0lӟsH;UqMt"tAhpІ0aL@3dM 4 НtxOjUi?BИzu@KdlNpYH`8PTB0d/d »* w{NZ2e\Xr+d;Φ`!{ y#Plssgr.>!bV*!*U`\F3p1/j|Օ\(D\̐kv 0K Flfbxo p]0 2!ˣ^l)e)/t^#@hLG( g)O'tF$f$ή<\ʹ"f6! Fnk8` D)H(/t` xN`B(rBFAV 66R c-,hJM؎&`t-@d9ZI%Z@#OtPT+B\~>/"<^&{DojPB,mX@]HC_0@`bFN "OB'?tM T~M`5mhbXt b H"(¬x:OȬ="tL ^F]e~D 2zTQ7/ :$@ $Bd@ Tmq{`&!)Xg ' g!nN^ x & p8E  `ϥ@wR E%eNG^ ʀJbo1p kA@t l18;тg `]΢;dO>\/&p&#=@C+@FD' p& >'GՅ@6^$a J ?1K"P4SV*H2nJ1],8.[QyL֢q )?xz (+036dn`k 6A-Տ$30 :* p@$L` .$3!CG<pDαƀ'<1i 9;R؎B$#I N @{)&Fcô7ˉ؆ uQ xGn*.¬;E7M+i",i-͆wT-߲nD`.8Ƥ6/S&(,@#ƤQ =UCc UX+˺`v55"^,>%2 L'`+;ꇙB,ʶ L%knoX80 @j>&UYUYy ʺ+X {(,X() @=Ư8)L cX-! 6d̮ĥ0>Z ,֎C`J5E< \IT ‰L[]T̂ [`@^(,#l^B> VZU3o U^ `0d'5n$xR` x nj&xMB0&mB c  "E\Z^][Lz5(*\`nex0CE܀^[U6d68hgf {@ Xe>3UrO;B73 Pg6sQ;3L%`,4* 5SC%&hAL%CB&j "&kD']>`(&>  L&s=xLĠ*m# %>}^xcuTG& DBvf 6U 5FVOt=>|'ԥ_o)`zxW^BJ<@mV' c #*`5נIz@1*~F\ [:iKf>@%%@X`>L n+*`"*`LgГG}*fxxGW6v f*F2.f}I}5damTv(klщ5xݒ VvW(" `XI KN]w;&WP` \XĔu ` ^(` &b `Wp`y}}fqeB8s kyy/=-b?h `@v9JC U.@MEX_' bnuUDgj#!#b1X$R[ƕ #5J<7H r/ O' q|Fx2*H7cosE&Pep$Zpcb H2@|>A[ B/ 2e@\VyF` G486bJ|D`F?ؼ*K)Fj{}@Y$k"\ԮS~h]h&|AQ-Cvk .}tr\(Jx",߂'t9gb< 2 fs2&ZD}&Y&҂ O/VMiFy62O~;bEks}s 潨E@߹ W,#^ DCY-1}'Ώ5}"+m-FB <d;5EFBEo A Udг~ꪎ)L' ovs6c?"N9{+f֬9ĉmΨ9cFF5mxx/nh<&O4&/ZeHhBrN/#vdsG?'ʜэ:paY# (%+ț\z 6رd˚=r֖dKtڽ7޽| 8 cP8Ō;~ 9ɔ+[n͜;{.ѕ"1c6]p5SYqk۾;ݸѩGNdʚUkf 0k֤[Np9vn]fɠŖ-N\Ӳi~?=^Ye u׈s900ӌwlN5'25sZ-3_Y8 u\S 9wyd4Ӭ\8UC1W0"0Tk9z,!tO7 6sZ5٨# m 6Tc/|/p1Gt5p8'L3*pyuHxNtBsZcf5$q2c8&a8hJcXǢ@ls3Xg}(0дL1njrG]#2\5h5=8 iɌKl Z \ iz S 8\˙i㦈Lp%p8G _qoq 2ĆLr9(r. s2Ls/<_7WRq> tBl5ŋ3jȱǏ CIɓ(S\ɲ˗0cʜIM%0گ_@JѣH*]ʴӧPQԫXjʵׯ`Ê㸱hӪ]˶۷pӆjngܻx˷ߵ )È+^!|Cظ˘3klqcu sMӨ(hclb˞6K`Ըsͻȓ+_ְ+65n@%fwk#價ӫ lذ`Р1[&MBx޾{ϖNV4vVL-h84;(!̴L3 f`1UN8̀ -(t >^d9S;촣48樣[ f3 B>0f 0|"0?h"#9;f\6% 0ՌK6Ӎ7Mv3K7Lt#< #:VCESNIicj(}/,RM4T ri'>xb Ej%_5H-N:L2VC+:ňM6S88D;Ω^fZCʫ#4,d6;R{ku+k5|S8Vӌ2O9S!>oJ/ghʯ'sp%ð@,V l͆\5$9s:@:+38gju=r >#1]--1ɴC8S]5W*|U'T DCCQ 4^B,"I %`'$4N0<.E8() +HStޤ/)=+54Hp3% H'sE$"%@.꩐X_d<0+|@:<B*N18xbF0@9g"L:[M>:zdC H"H" a^XptlP/3 K\Qy A챎YL;. e(X 3g,׈m n V;,@;̑6ָتHC-"AF1B)H8) xzaNzUR6ŀsȂ.08 `aP9 r 0 s4% V a/! _81xA#_җ'IrL2KҲvxsP9IO"zRg:Mb4sM zXς47ሧ/̓h!ElDЃZ1GB|0DQ?(Me>O7b:aJӚhKmӞeOJԢHMRԦ:PTJժZXͪVծz` XJֲhMZֶp\J׺xͫ^׾ `KMb:d'KZͬf7z hGKҚMjWֺlgKͭnw pKMr:ЍtKZͮvz xKMz|Kͯ~LN;'L [ΰ7{ GL(NW0gL8αw@L"HN&;PL*[Xβ.{`L2hN6pL:xγ>πMBЈNF;ѐ'MJ[Ҙδ7N{ӠGMRԨNWVհgMZָεw^MbNf;ЎMj[ζn{MrNvMzη~NO;'N[ϸ7{ GN(OW0gN8Ϲw@ЇNHOҗ;PԧN[XϺַ{`NhOpM a}NB@tb|I(058B(xstHȂ+JQ BPR D*RЇ(,XAT~@jz +A{_{'_Gn?;_Y_姂7B!2,j[{ HP`pUfZ6|4rY̥nW CIɓ(S\ɲ˗0cʜI͛8sɳϟ<*hQ̩ӧPJJիXjRiAi`\*M׳hӪ]˶۷pL8p5kcA\ ,KÈ+^̸cuVip_ر6ӨS^ͺ똑'W,Zn~9/vl.-ȓ+_5kز'I'{6on=x1#^ӫ_yb0\bI $I4`{h&8S8tM Ԡ:3K|:F 8 ($& ]x!3N;ă$ y%<]M" ؙ (0@ ,hXfJ@ ~%=` "Sp)#2 ednjdH.&&袯ىg6zJ='#/ 觠*[#/{"iO6*2 㨴j?zjcꪆJk&1>\"=<# )Dv*g Z|$=܂+b8S :#O: 48c01 #i6!ޛܠ9˴208`lDžA,KD8X lHs,r8Htj Xg.D~Ddmhlp-tmx|߀.n'7G.Wngw砇.褗n騧ꬷ.n/o'7G/Wogw/o觯/o HL:'H Z̠7z GH(L W0 gH8̡w@ H"HL&:PH*ZX̢.z` H2hL6pH:x̣> IBL"F:򑐌$'IJZ̤&7Nz (GIRL*WV򕰌,gIZ̥.w^ 0IbL2f:Ќ4IjZ̦6nz 8IrL:v~ @JЂMBІ:D'JъZͨF7юz HGJҒ(MJWҖ0LgJӚ8ͩNwӞ@ PJԢHMRԦ:PTJժZXͪVծz` XJֲhMZֶp\J׺xͫ^׾ `KMb:d'KZͬf7z hGKҚ-B@ 5`BaPKBmd? t[B̖" V+ .Id,<o*$(E)1\ HHu[V`zSW$z[7$}W U/!e,[ YvհY,>i#JHŋ3jȱ/`ǎElK(S\ɲ'T͛8sfSZq¡6.ΣHjT7.kAKƌYP_)ʕO_Jj5V]ӪI^7[9sլkEYܹu˞KpEzd ]x K., <5(bL\z^t-wU޺sЍ Y67m{06TXslW[S[Vsݽy|`: W;]ź>-q]+Ɲ|%h e } ԠD-x >Ffv ($h(,0(4h8<@)DiH&L6PF)TViXf\v`)dihlp)tix|矀*蠄j衈&袌6裐F*餔Vj饘f馜v駠*ꨤjꩨꪬ꫰*무j뭸뮼+k&6F+Vkfv+k覫+k,l' 7G,Wlgw ,$l(,0,4lsyn\!^FS漳4@HKyE] 0>8jqƔWgE[h 1vg'Gk|,BmbPy7zcaUg-%hB\_^!:nC WfXFWpeK$O1PDFiHM>,x>ƓAF-tб>wa^P_i·^RO=@p;1g E!-,oy1DP*\/|׮Y./q;1cÏ CIɓ(S\ɲ˗0cʜI͛8sɳO ;kØP\ǟPJJիXjʵ׮{;YK~]˶۷pʝKݐay{os LÈ+^HDE[ӗ\}nT˸ϠCM:H4Mt9s*F;p۸sͻbLE HyX|УK^2R"<ËOy $TP'O$ D_'{ ޷u+Mw˝ 6*G " $%' <}h 7Ҹb4h8&|^a `B %D0) "!7 60:X\v`##A _)ȒgB pS 02K,w0栄jJ"zũ ܜI Pa DS9˴ 0d9#\2px'i *"},R+bꖬ&N A1j $ɛN''N#.ȃl%.ccⵃ;9b<'mk'=bN(2DTb/0ń\N;,SL;`SꟖ=0,O{!$˹eK;<4N6"9괃 6PGXlX#K|*v ̳hvs8;cs.=2>#ڀ.843O3G.9…Nw2#2 }ͨ,z{)zɥ=j;ȯ/o'7G/Wogw/o觯/o HL:'H Z̠7z GH(L W0 gH8̡w@ H"HL&:PH*ZX̢.z` H2hL6pH:x̣> IBL"F:򑐌$'IJZ̤&7Nz (GIRL*WV򕰌,gIZ̥.w^ 0IbL2f:Ќ4IjZ̦6nz 8IrL:v~ @JЂMBІ:D'JъZͨF7юz HGJҒ(MJWҖ0LgJӚ8ͩNwӞ@ PJԢHMRԦ:PTJժZXͪVծz` XJֲhMZֶp\J׺xͫ^׾ `KMb:d'KZͬf7z hGKҚMjWֺlgKͭnw pKMr:ЍtKZͮvz xKMz|Kͯ~LN;㙅" ,6 ćo * BJ&@5 +JQ BR D*R0Yr*<&e!'[r/hN6pL:xγ>πMBЈNF;ѐ'MJ[Ҙδ7N{ӠGMjvFd"9׺RH9hF5QZdT0q^H^#rOoa61І-{L/xA {؃Nk yCLn7a//{֐=g~8H@m4h!+@o~B9A nȃĿa < vr,|Ѷ_a poym#A}A f/}{ >ij` ~ΰ5pAy8B> :h 8nޅ.p b QBDZD 9  C7_aF7@ЅQP4 h",-X!6@ \B y4 F8/t1 :{ySh_Etj@eomZpW0UD0qr0mՆx| | 0yx0uSr+}[t7y ` Im]'@_{`tm3aEGP0/`d\:w&gwhPkP*pp%0F$pYhPWnwnp\P{Fp!pnqpwm׆CjFK3\8s0+q{`jW{UDph+w0WtBȉЊWPh0EgZt_{fq3TnpWtxD WttƧyxhf_}!p5[X r,ۘ:WAqܦgnPm3w ^~3Zwn `'vy0sBЊW)sH_a #y%9QHy Y0mwg7~7WГxnlЏ?I6sD@ @z(WY{inX` tAtp0r tVnrWZrl`Gy{׊A@D0i׎U`7sJ%Ȅ'{HEh{803@{ yY[@Hmyx9 a1P~@yrxȈ,xpJv~{Ziǜ tЉ9_<`mn@ pIq 3gUoX0ea0^~jw01Z[P[`ֶcx/qF0Y0P ygƟ\9kS gv6|@^7f}l` ܖV|t rjZ|;sJt~Hyַs v6lʄ-vuܦ+Wb P y]`}VnmTǍxtyV܆v_nT5wgPZzQm{ _m:zzp `׫9xmj'Hz +*WZܚz *vKp&+-˲ q3A 6_ʠ 0="P p 0  R+ p  ^ E "U" P  D{ 0 հk ` @ :ɠ 0 0 Րk\!-,!oZdvݵp18gΐ9;N3hʚ 7`;sCIɓ(S\ɲ˗0cʜI͛8sɳϟ@ JQKÈםGjʵׯ`ÊKٳh&]8`В1E-pݻWiڿ LÈ+FZPoέ+\^|.̹ϠCM̚%Ůu[Рc 3ߏsͻM4vhЛNسoܸb$ I$A<=׫Y˟O%w(a~]}h&x3D3~& &) (, 2F8&@a >7 4h8VN6FB'L6Yc3yB`)/- 7# 6ǵ#P…&H$xL#Ok)I "X$ڹ^|6裐NFXcMkJ;yg*ꨣBȦ**t*무u>ήBc (4ɆZ6lMKԞSL1/l+nHCms/ϻ*;˧9F{RL8;xk'侺k;W!8&k L-K4T#0܎`M9,@-DmH'L7PG-TWmXg\w`-dmhlp-tmx|߀.n'7G.Wngw砇.褗n騧ꬷ.n/o'7G/Wogw/o觯/o HL:'H Z̠7z GH(L W0 gH8̡w@ H"HL&:PH*ZX̢.z` H2hL6pH:x̣> IBL"F:򑐌$'IJZ̤&7Nz (GIRL*WV򕰌,gIZ̥.w^ 0IbL2f:Ќ4IjZ̦6nz 8IrL:v~ @JЂMBІ:D'JъZͨF7юz HGJҒ(MJWҖ0LgJӚ8ͩNwӞ@ PJԢHMRԦ:PTJժZXͪVծz` XJֲhMZֶp\J׺xͫ^׾ `K f!l 0A !CŇ Yτ EH{Pt3a i7ÊR.T̶3++[Y"Mr\!^,1oJcs lġCkkh3+bB| CI$gȡ+ɲ˗0cʜI͛8sɳϟ@ JѣH*]jS A2$;pVvb!0#,H2H "'x$b9"88πMBЈNF;ѐ'MJ[Ҙδ7N{ӠGMRԨNWVհgMZָεw^MbNf;ЎMj[ζn{MrNvMzη~NO;'N[ϸ7{ GN(OW0gN8Ϲw@ЇNHOҗ;PԧN[XϺַ{`NhOpNxϻOO;񐏼"<HjYL~<‡oBAByF<B&@▶ +JQ B]LE*ݰ"+KAˢ>OnO~/_/Ϗۨo?ho3~*oSGaP~!],oy+DP *\p!bU{vnq#p8|̘%Ǣеv(- 2> UFsZ }c/`@ 9g%vSbJJիXjʵׯ`ÊKٳhӪ]˶۷14aĉ/fcdP nK gּP'OB5T)ӧO̹ϠCMӨCe;.1|Ϟ9+VHfĉwkDIkl_ȓjH9 .f͚G.u5ËOǮ^uٵo;eJÈ-f9$t]WTvqTE(Vhf\2tl@'Ϧx**4U'+p pb\1SM:p (Hv:6F^덅 '|G*57٪'LZCBܺ;t :,,֖p=r0D)J  6S!*jÞ~!AEi:;: '4'(HN3T:7y$5NWmXg(*-0ó.,ƍ"-Aߢ4SKwmI~, c R h)~R aC1|ǷŽ.n˳~z#~@DE,7rAx *"C##$'4 4eN5/c%:_*xN1@ ~6Ov۝y!(ۼ ro"!&P qv6|ih8 ,`}cW8T/=EP,pX`$B`? q AbbeWݲU>nol@$ao"4A wC& 3Ld*5Kh4F6NQ:R 'BQ xAwT=J)Ff=I/W6z U! _@r4T2fR 0.XTŎbx;qbМ[vAOxƱ1fBuxbCԩrЙMB-EmV>oӜE,YqչPZ<{ۓ YSXMA( {AaB2HMR\a@\a@+X *d PD.&@̘3pbc`.Jq@4@E;p |صXF6z34,Bрh,$  /*\k.ֺm9ڱvdAX؈!93 [ e8!lxņt oDcc(KY|0f70g؄4#PI E.ݚc0bz-$a3zSaTXs60wv/1m.ANS! iĢ`,e 8α;Ru ;a/iYa Tkp,(3ȴ2neَr܎: B(B0PjlxsjabxK8c>`C8|q]|ѐtX f,RVW$9,~F ޘ>^:$gt5iOZ 5f>Y:$ubF3n{> :fcP+0kc:iD3 m{wZ]su-;lwI [˔{889QQ*gN[(Ӷw@;HKѓ;=&KԧSX׹ճ|^+.;;pNxϻOO;񐏼'O[ϼ7{GOқOWֻgOϽwOO;ЏO[Ͼ{OOOϿ8Xx ؀8Xx؁ "8$X&x(*,؂.0284X6x8:<؃>@B8DXFxHJL؄NPR8TXVxXZ\؅^`b8dXfxhjl؆npr8tXvxxz|؇~8Xx؈8Xx؉8Xx؊8Xx؋8XxȘʸ،8Xxؘڸ؍8Xx蘎긎؎8Xx؏9Yy ِ9Yyّ "9$Y&y(*,ْ.0294Y6y8:<ٓ>@B9DYFyHJLٔNPR9TYVyXZ\ٕ^`b9dYfyhjlٖnpr9tYvyxz|ٗ~fyG<:p2V36i0 9G@a5pY0YI 909S=iYLCYI:P6@0@EP?@yP# M 3R @ R@ 驞В Pteҟ) z ڠ:Zzڡ ":$Z&z(*,ڢ.02:4Z6z8:<ڣ>@B:DZFzHJ>) pbAa'N RTj`EmeSI p 4B#Lff\fqzK^~z^ʧI00Wtrr0ZgZypyy0kfhj{pWXЩX~zmoW`E aZV*zl0@:W^z蚮FJ Z rnZ@ 0WW  ۰_jW QaЬ Z@DP ]:r!p@vZ 4[^ T1zh_zi+pU@@W, ۰[:9!6@Kp qqx{F` C`r=DPy; h`a{9KFPZ^0E Gjk`-Rv[m0yG۸qq[pYF{zJj/@n _k~0;Kn{+_fpc0mp{0U``F0Zb%0GGnY,lFp+J@g"<$\&ܰ֋kcj{0ss/08p`U`1-sp\pʺZW ` XPTW|Q`!+nL7;0f;~j: ‘گX@~@Pĺ+pakS/0rjJ`y3Ɗ+kuz,igl(jނ+x#^ຌj! Y.+Kl`ʛʾ'||-z l@q`l˩7@+PWpХ n{`~ -hе< W0xLZpZෆL!,-cPz_`90@\p_`~^\M|άl@n ʺ UM;XP˓| +vư|Ac@ 0Y~^[UUpct2p־\ݫb@EAn 0pGl[[c=\ sO+e@ p\mqr0E} *ڪhPقJj`[xۇ],J{iJڥ-v0h_yPqwq0Z-e sݫvkphƬ|:1z*~m@̪n ϜjܝZwm 4. ՛Nκ"Һ&30]-n ^㽚4J|loq Pmsנ6 U~!^oq հmp@ ߰ p  q"0 Bp`C"4!H 4\C. D`Ͱ[[Z'N?!0, qͱjo|b0B)|+_3jȱǏ CIɓ(S\ɲ˗0cʜI͛8sɳ9sjG4OFjhϧPJJիXjʵW@'1>!NO_ʝKݻxץhN"Նkǐ#KL(+NWc̠CMӨ]԰c˞M۪Y NS7볯+_μ痍Nسk)=hBËOjy_ϾOW~ h&X 6`VhᅏMv!U~($R&%0蠋2hш<>)䐾IH&9L6aJF)唕9i%TftY$\)RydBd3$l) t橧v矀r'j蔃s袌hFj㣒Vj^f駠*iߨj{iajkuv⋢+q"ˬ6lm>+EKJfmv׶ކ+nWkSnһk/Iޫ L*: JLZƶjǫz ȤL(,0,4l8<@-DmH'L7PG-TWmXg\w`-dmhlp-tmx|߀.n'7G.Wngw砇.褗n騧ꬷ.n/o'7G/Wogw/o觯/o HL:'H Z̠7z GH(L W0 gH8̡w@ H"HL&:PH*ZX̢.z` H2hL6pH:x̣> IBL"F:򑐌$'IJZ̤&7Nz (GIRL*WV򕰌,gIZ̥.w^ 0IbL2f:Ќ4IjZ̦6nzY(BE~ L7C#CA B" FeͨC |\TبHGJR+LgJӚ8ͩNwӞ@ PJԢHMRԦ:PTJժZXͪVծz` XJֲhMZֶp\J׺xUP5Qf4)GS׿WJ9ةT5I#Z5_Ђq|| 0es $qHmw1|"y@HذY`!#jhn0 g5 cm=Զ#BEZ!Wh3!$o t6vzAn}mFf ]n=Alqՠ4"{ӞnG@<[p]p# >-hɋ!tv bHWb1׵ؐ0A4d-m6A I>0 Fl#d=| F 3+>B4HxB#3+r8kXmPna#[9e|ā9C6 t Bd(=n/V D,@ 3-G\. 6+,ZgpFH,9j8pPS:իƈ#[fVd3dy`uE`m/.<Ё   '5Ռc$avϫaӢt=gCC @H L1,"mխ7*|au I ]‡8!nQ&{_[wUxʇ[[FQ'Gp %\_b(b{&\w\r976ڶ]\\gp]n<[nåxPq@|]x@jl[pfHxBvIVq7j8`hf&a'6!7cgAC,hdkX\i[҅ߥzuep$q`džat(df{~8Uhp#ሣć8 ؀ x(&4ЀӀ H  ʐ 0  A! A 0H鰍ِ ` # 0 P p˨ "!,, " H 3ܴ%HC3jȱǏ CIɓ(Q30cyF33Sɳϟ@c8l)sR1JJի鐡f -_Ĉ˥,1dȈE۷pjlW^5eϗ^laGÈkK*T担*\EϠ?A#pO[r:5>C˞M*ѥ E/_ݼ-\p砉 3PN5@*$-m5ht_Ͼ-|q\#ܩ'B!~&(RR_FN;-Ehr&ǐf)98 48ہ5֜9s50ި$T 3|1TM6Y23͌H8&CN\3N:8N-#8(>B,:茓M|̘(M6(u&L3S>7.07['6ؘZ3&.'D:-D#M; >)$F"$2>)cHR 7XjYd点Fc# 6i3%g{gٔm;\hŋbHJj)6**瘊~꫱ښʫN&̲>H2#έ>N3Ҩs&+.垛7 ֙H 4vF I3- w7,N5q% D;8̔dԊ 0tS͍.;ϬL2$J<40ZSMdy< >? 6%n͛{Cy5HW$9ތ˟NyMʀ2 3 wzHҳF.sp/^ Up _ާ)-g=>hr 2>ye$Qٝ.uX]6Y"fE8^ xhGayЋ ȎS08ףS }VW叇(@}H$?9S ª#"QAI@vޘ (P PFٹ !;YȲ03hQuh/|;h"; {cوF4qZ0#PF$pm18ܑ iDF/yj3IJY,MwR>J4ؑCBftAiboH8`CbaZF0dsCՈda+#*9iJ唅/ю)lqz #7lC&/a,nGJeOX= itc (4^`\PG/1iD,ڑLp,j4Ԣ$ o:2US~k5)I]/Z \kx$*^EС^ph:_BE}{*H!Pr|S::{[>5n`-4ڎj#; 4(|O(G;؀ER(8!XB*7!\n ސZˀ~OFemW BjpLP|@PNa1[@Z`;k7WkC,l! V5? 8Ej zO # C`;H4'/R+@! D%[i\Bx1$,%cpY&'N!dT8 bh9:;S gN1W 1"@Ht3!\ l #4@~(ArZ `1 XX^w]miH0P4QXi!ql*+泳gG ~BF!oz{~B%@@ n&g0!Ȯ+s2nw;Ai =Z!  0WztWx7!(Z*]B4'!=bȈ)NfIЖ$p@`$.uqd"*\Xe ^!W82Ѣɾ7(YdxF@$PFD pGiSH+_!F7;z @^y/>ܑ3:|$@ zF\% d Q4 h>*# c!"(~uv u`ziM CJ{#@{ {{"H~f7|w~f炲+SwT z7~Pco(D` 'FPd}pgEA&; X dTc恲eyci(bLVeޤҶJ-FqH@V EHu@ ^0 >MDP(J $pu waM3 gX|fvFԠP L_nj` h㇈njP *)`DDrvȐAD pl+fA D${ s'Cyy&=f3Y! E0YB `P^4"WY TVh F x]" {`f+ؕ؎̧eF| Ő>7FR 5 v]#%DA E 2Kă=7rpz);  xM(u| 凜5)vR{p,PC@f!` 0 0%NQ0+֜Ui I p p uשSZafMW : y`ghQF$+~ `rٝ y!@u:>'; \p 8 )hɝZ0PcNРQN2 qGK PDCSg *IK)%:Ly Y ڠ5 MbogGyA pp {6+iu #)@鹞`DzʁY}J9 0I6%w%Ju:gFԧ`w}Z!7FvG>ׄ, zJZgzT@ F:0ygppwiVZA ig[#, $Š L@ y;Ɣ Ri3)`@0mxR{# ir>Li 5@>< :|6@) tN'J0Р `"pp B0@"Qg*M@8r pV`" b. 쐱 @0 V Դ0 Pf A+P *p iHNE@"( `g'UJE+u ae " P 0 0 0  Q ` P: иIsʍWA W + ^ ) k܀x ߰]sp 0% @@ Р p#LP  d[ 4h Z4˸V@pVEZ p ?" Sr+ \  yU՘T)=L~PD閷 u$$:$ ``'aIC\G\ H,P T,}T Sf(GCrʕ-Add͓7STbϟ=C!-, r H*\ȰÇ#JHŋ3jȱǏ CIɓ(S\ ˗0cʜI͛8sɳϖ? JѣH*]Ԥ˦PJJիX|ׯ`ÊK@fӪ]˶۷p Kݻxݺ߿ 0eʞ= /| Lr3k̹s‡/nʨM{^ͺcAwN@_ )mȹ%{УK(I(I@vh>YKjPAJg?/AHxYxˑ߂ 6T „ A ݧv5e @,",$(_|Ec(*< I)<)"L6dRX$uߓXfyBP$p"`"j[暮aWP;͔9>W|I(T!6bJ碌6$L1J覜vn9EJP. j+MiyRgVA[.F+mDxm;r[m em{뷈"$nn^k,l' 7G,Wlgw ,$l(,0,4l8<@-DmH'L7PG-TWmXg\w`-dmhlp-tmx|߀.n'7G.Wngw砇.褗n騧ꬷ.n/o'7G/Wogw/o觯/o HL:'H Z̠7z GH(L W0 gH8̡w@ H"HL&:PH*ZX̢.z` H2hL6pH:x̣> IBL"F:򑐌$'IJZ̤&7Nz (GIRL*WV򕰌,gIZ̥.w^ 0IbL2f:Ќ4IjZ̦6nz 8IrL:v`4Bp8ᎄX _@7 Um`8Ը!Z(@H`Xβ.{ ir$1@ r\.$Um |7l1>+ gxn#f|d (KsBf($H,J[Ҙδ7iNye͐H#U-AZ!3Ap` _ $I5D!d np>d@-E, ^^ -a H@5XU 0| B"0I58m8Oln2atp.0xŲCx08A s@[>7~6]0xhjamg{Fä-φe1ְ3a a I\ Nn|!cBl^-Z$;19e}}-ylZjlI=H-OG]TCs](pg0> h|>}srlCGH  PG8 |B:3qs4uߌfT4f5 f EG2f/{h@hbQc? X\9 ?@w/q0g` H0   р{P@` 8{W& p &((),Ђ0-Xɐ &~o!Q2z+H, /H&NN*b4h:|уC 7 ؄+(0W `^ȇgg؂^L؈v/X'9{ Րn'thH(h z聈Ȃ(H8hu8؉>F@ `p hhȊx, 8uP&hh18pFɸX`ȅzxH~(P8gzh(wɄI{؆( ȉ P * qCh ~X B P )|\8DY,hHyux .P 8%(^Y{-ً/i98~P?y |Rvyxz|ٗyzHiVzP)؀ii X))^GٙK8 x?٘(Gɀɚ邵 s ٛFY ĉYəc؜وyә¹Y94.!Y:њ$A28Y*9 G!3,3Af̒%c&Nܳg"H3jȱǏ CIɓ(S\ɲ˗0cʜI͛8_ $xB!JX1ѣH*]ʴӧPJJ3MvM9gʠ%hQhӪ]˶۷pgg֭][Ĺ LÈ?Z시v$I<J̹ϠC6Ks;q *!BD@1kM۸s8@J!T9)7УKGWxJdqe3Nc=m X܁l3Ͽ?\= N5sf5F=bd< b;h ~($WP;GB!%(4(Q] 2X@)$`6kL691L3CH 40A`)GRL6S ,8_c)?ZGUVV%*~Xˡg9裐F[8XAiNKJ駠rA|h8f4m꫰آ18sъЭ+Pj+&3 ,F+Vkfv+k覫+k,l' 7G,Wlgw ,$l(,0,4l8<@-DmH'L7PG-TWmXg\w`-dmhlp-tmx|߀.n'7G.Wngw砇.褗n騧ꬷ.n/o'7G/Wogw/o觯/o HL:'H Z̠7z GH(L W0 gH8̡w@ H"HL&:PH*ZX̢.z` H2hL6pH:x̣> IBL"F:򑐌$'IJZ̤&7Nz (GIRL*WV򕰌,gIZ̥.w^ 0IbL2f:Ќ4IjZ̦6nz 8IrL:v~rJЁ]Aqx D'J"aQE-a HtjF<\8tH\9LR>Ȱюa @5 |Hp?t ji 6"Ԏa$[0HT?1P2 i5 nhL7T$Kѐ=A t3l$_`/8#-F7Aͬf7{*m}>+7#y@W6ubu +z5H_Ǜ4W#fP̐+m&X#+Ub"_$J9[ !vf3f5`⃦ڰ[A0! jPmj$p!_H`hA u}#-4 / RI¡ 0Lj6 3p1l8h9|0w-|!2un.rS9a ZeT~d6k|Xg@k .0MjgC{2 m- `X̑b}{Tw[sEnط:H&^\|ȹI2˱\:0jdW䌇T#Cqt@9a @حpAz^A_cRG6av\nH!-,!Z=Ço;wƅ 'ΙgB{ ŋ jȱǏ CIɓ(S\ɲ˗0cʜI͛8sɳϟ \.2v#-œ/z.N\kȾl T)AkG#"-LFKG5n$l2nd'0,4l8<@-DmH'L7PG-TWmXg\w`-dmhlp-tmx|߀.n'7G.Wngw砇.褗n騧ꬷ.n/o'7G/Wogw/o觯/o HL:'H Z̠7z GH(L W0 gH8̡w@ H"HL&:PH*ZX̢.z` H2hL6pH:x̣> IBL"F:򑐌$'IJZ̤&7Nz (GIRL*WV򕰌,gIZ̥.w^ 0IbL2f:Ќ4IjZ̦6nz 8IrL:v~ @JЂMBІ:D'JъZͨF7юz HGJҒ(MJWҖ0LgJӚ8ͩNwӞB% Ex`Ԁ q|:*>l@Z)T(6R#ªU$ @UMDR $V*@TU,XTխxm+>XBz `WUd'KZͬf7z hGKҚMjWֺlgKͭnw pKMr:ЍtKZͮviۊ8!_PD_-x7޺E]W/Ր|iW/@L`o7'G+a#~0Uİ9X7vpU` D {P>5 =Qx*[찑= n-\[!iCG{$.Vqذ7x  x mG@tD y phCӢxI*@8yK&:"| \A0#aH>g" zf6v A2T#B-h!{l`#l  gX$u9ǚ htS e!n5']T[2G XT #yPC!|a rHn*) 2AF4 iÒ g/ ^BGFpv@^I "p{)F:!P(hDjP :%_3>͋Rsah q̍'80;`)+s,΀}s!^| oW]awyshWg{Zhft=VqhhyyxGqg`b&okkwXVqLWw*oq_f f%abuf "jf&I,(pw0lQhgfЃA~!!ĕhH \ʠ B@  e "Ai ߠ`*g+,p  ̠P` (!+!),1wq9[!8ใ ;k׬a˖0`ղqFcď!G3hО=6;>S 7Wx|}_/ -V{e.W8s/;ѻ^|LSzXg V-g D Za aa@!,,15;ݷl[ȰaC|<СE{ >n笤3c,fcȑ&K\~cLclܼ;wqv9w3bmJ˚hӲ#Fjl$+)lEcvTJmoֳdք( -}&m4Zx-[Ϡ&-a2o餕fs)yh }ٔc툇πX kRުҖ!8qx ]j2*hg8a6րB8΂O<45ml}k];/Njb/>xf( Z8D9:5169P2&,`1d@Hs4Xg}/,*h]4|M65w 0S9#M Bv9+ŀy:^FZnT~Ը@ĵw>c@$ >" -0g2⨧zP/>P#O.3[KoAH4Q'R2l.[H'S@"L; d>$$-8 +/k|A^AJH3> +Ѿ%#~%LKFECBBBvL҇U Nr Ƀ4.H9 z ;юf8ټ2ZAࡋ0[á:w"@W Ҍ&1cM>*Y>{si(/ f "D1v$H:G?Z܊<ዹIoz_;1sLS;0m8o`6 [<8(Eb,ԁObK;jyG<6(I䰥J^>㗩j[3np${L< t|ԩ2b#"d>.eRx@|%_ l]ffE凞ͨh)M3L?Ip4QBP0ԟj&*ەͩNo:F;X'Z00Dk^ CJjSq%k` k`zPT0*@r1 #PjSCU|XuHYeZehQ˸S i\)OуQE2(^\U%K`4q'+;`AJyָFx\ySэ|2݂W ]  @Kz;PoBګxH(<g8ƑlR@"!)7c'F{ֿwcP~BN|B rAVlJunew!Df(v#Ɨp 0ƓBC1AraB7 :3MyH"wXrfv"Z]@x ->"U@\)"g+<ehP0Шv5/$ /9?(F '9:% n/Ϛ2Iq9Qok+hq,3r;؈F3 )oKi|X!D; .qh[bE*0 .O" KqLt*DS-jʢY RT` Ya df>B!GB!9rQ<\A& ix/rq^a6|ǢBRgH0Q .rAohcʖnfi/&i uyWOχ!I}WgO![9QƧ&ml5ߩl3Kv nP0l* hF{c,]:JKRJW|~fVM/IJ+_$$%@K$ g4}`4{=GC$1.t,Q(NՁ  Fn@.Mej؂~$RãbK"<؃$ pܐp`2HhC0X2$O.D/0}Mߐ$&BbEKH#ᄢӒSX.U!11Y]8&6zX?eXC{}xXxH1ȈL(x88؂xzr(m8hhxca¸Z T׀O@ F ɠ QE ʐ% / ՠ!x͠(B@W!EJp舎øXSC$H7%ֈ䠍((A 明Ȏ 2@B-< 8.d$p `*HF>!pN0 ׀ .Y0 V!ٌ([rّ%!9) ),y/ܒAog$! ހ U-eS ΰ u }KtN^ )Y$T e /-) 5|7:A`ӑ R ]gv|P+"ĺ}a*xznQv j'V̊QrPpCl:!A{6"JzYE5d k;[; {{:,ۭ!{ڬ )K0+۲:<۳>@B;D[F{HJL۴NPR;T[V{XZ\۵^hB`;Z!d{UahPlIp;D!t{?ax3|.᷀;)!{۷۸/a[ f;[{ۺ;;{w;ۻo;g[;ț_۵[қ[W{[ڻS۽O;۴{K꛴۾G[;C[?۳;ܲ\{<  :L|` |"<)Z&,(,l.2\4\Õy8L:L>@ 9D̎F|ØJLĻP|R<ųXVXū\|^ţbd\ƛxh|jƒn pNj8t|v|Džz |{ǀ<fhό̬aU&#!.Nn . Nn ga5`P[DEPW]8DG`: 2 `}7T Fg< 6`GP t-vnCP F'nL 8 P @ P $꒎b'鬀4 靎 .둞 uC#Ann~$NcRڎ^ξ.~c.?>S:侀85_Xs2 (03-ے+ ("?R&&(g,_&.<2#4_r8o!:>@1DF͑JLP?R?QVX\^bd_qhjnOp1tv~z|z?uQnBOHVVFD R 3|o_/꫾z_\(M h?Wȟ*r.pB5؟ڿz_.*|_ _B %Ӻw{ $XA .dC%NTxE5nG!EF=H[CHlS\=Ht>ȍTV*4Z.z6e*Ůf 0 jq!d|.r [)U*ȁ.͈V|>Q.5{Ƽ-|Kto%5x+%U1#Hpre6ś!..>~&5!:F(@A°5 !ȃ@lGC$bxD$&QK,QRxb !棂8`ZA %r(5N%R9וԐ' )B2EiLl,-"" x9HH 4!>.N=z /27 izPl s%>8]Ql$€ pj[549ty~F"ь&Ҵ`!%A5# g_cp6$m/1ς$WB@ɂ́Ag @T—A!5Iar#3ȁd=g؂"L9 ]yA"EK䈐+{D1gGR|= \TӜ\"E@HI$oXF@dĉV_X7EǪt(B4;rj$IJ%Y~ֽ sEIm ˙RʤA! ־Fuҿ3v T"֠p`I搐 $ EJ;2r@ڗ 6;3|laIh1EB BC<!"HE  5T8ZPxي n,DVa|\!\@ e[dҳX!!fA@$ fLiež" A D5:nÕȿodh@te KX!eoڧ!w *68epya "^ R҄ I"" Ԩ4 %WC<aXH>> [ >`H%0,0i| [f\decW@ ߁Gp'J*7ۑAAX(AxP0k`vDa$G[Oq_=sص>R9P3QLzթ3;e V} : =^iAXwE ($1nyעL b(@(}mj0VAbZќa O Eq {.$?!r61л!B̐ `#2ԭkly@!>~][  ԟ!)A @&!j ‰Ó i$@,\l¿PAR;B>!dB8ZhAGZ ;x * 5Ȗӗ | Oӗ+ɠUtSlľ Y 谻:7 Š Q\&=vB_*ӢM? TATB-T@-TDMTE]=TF}THTIUCGTKTLvTMTOTPE N UR-US=UUT]UVmRUUWUYUFUZU\U1U]U_ !-,A97MN\jΜ'.2`hܸǏ CIɓ(S\ɲ˗0cʜI͛8sɳϟ@ jR A2t1`1rJիXjʵׯ`Ê3ܸq-kV ZtU ={Iڑ߿ LÈE[tp ^pjL̹ϠCM0 IV7P@A{'OsL NdzسkVoȳkν+IN%]"EyI܁?,P sW %P ߃F(nG 4$"<$3Om`,0xG*3|∶}t*Di͈Om(c`SB \vD)ɤ@JmX`p#1'#'rj衈BHHS4 B k-8v駠'>x,M#4Ѐ p@D뮼*5D#,$3 4HÍ4@1Q6T0v[>θk>sG+IQ^K,梫.Hי/G,qK {Ԏ/Q.N,$hoJ?\,\(4|'l<,&DmH'L7PG-TWmXg\w`-dmhlp-tmx|߀.n'7G.Wngw砇.褗n騧ꬷ.n/o'7G/Wogw/o觯/o HL:'H Z̠7z GH(L W0 gH8̡w@ H"HL&:PH*ZX̢.z` H2hL6pH:x̣> IBL"F:򑐌$'IJZ̤&7Nz (GIRL*WV򕰌,gIZ̥.w^ 0IbL2f:Ќ4IjZ̦6nz 8IrL:v~ @JЂMBІ:D'JъZͨF7юz HGJҒ(MJWҖ0LgJӚ8ͩNwӞ@ PJԢ GlPF}02!."~@ V[T *A^=B)"VT¬t&@lP*XQ BLR D)d B`aY׽GX|b^& hّ!1,Q)[w׸Հ5f;wN>|MƌiMxqٲXɒ7/ʜI͛8sɳϟ@ JѣH*]ʴӧPJJjbDCa^̸ǐ#)ćRe˖/+ZKݻx˷߿DP5=F-%f%T6oժ}mLS^ͺװcVJa;,9ek1kN3hѤYͼУKN! :pԎ"43 ݄ب;9--W.Ֆƨ77ȊL;17<,HK4<"6಴7'dSg%!9g_9ļ󘎠'܅g9h+}NfyeM4Ӿ9/NHj~ 5ސF9Gz7HM6ată(L ?=E$ć Q e%8 >i&:PH*ZX̢.z` H2hL6pH:x̣> IBL"F:򑐌$'IJZ̤&7Nz (GIRL*WV򕰌,gIZ̥.w^ 0IbL2f:Ќ4IjZ̦6nz 8IrL:v~ @JЂMBІ:D'JъZͨF7юz HGJҒ(MJWҖ0LgJӚ8ͩNwӞ@ PJԢHMRԦ:PTJժZXͪVծz` XJֲhMZֶp\J׺xͫ^׾ `KMb:d'KZͬf7z hGKҚMjWֺlgKͭnw pKMr:ЍtKZͮvz xKMz|Kͯ~LN;'L [ΰ7{ GL(NW0gL 6Fs4j>ӂ,d+B~d57 ,@2@p 5Eep Km |0e+ f5L+RT[`E*,?+ZчU'MIGW/+MWӝA+QԔ2uQ])UoՒr5S-YOjϵuVU׺E~M`n5}e3ώMj[ζn{MrNvMzη~NO;'N[hf)Ǜ l|L)y3N,L1.Iq+xHѹL~6x [Ђ6|!wȃ^-a |C.l b А 7 j{M԰p^og…3A&7H/4pAk(.`a'L;!FGW|DCCpu> 2 gG+5!q]&P.O+}mo|"Y9%O.d ̧1΋OϏJ3 l@` h~p]Ryr@v[GyZsf^f`}PW[`[uw 9fgyws7~4zr gP)Z3awB8wJ{0Cy:WT8+q Ql|ix50y6xg{ x {wՇ, -|w8qA͇{tx~}dto]LQ,y`, -[H[^h0}33|hj0kP.{4qx>\p0lpw7~A{7GzĈ舐P|Z@~Q` pUp@FP `jŊH\x07ap}Wuk3h2skzv׌48x2Q{0ǸĀGj`s{@z!Z@xy`5ד`@g+8y2A]7vhpsX=PhM["y`@z9Mxs_#Yv%y)^В(4)y@:9u$xwj9Q; ej WJ)^הO {R9^7ل(421!:|zwG|WtWt z@y\~V R0X~vy |w8\YA@y/b 410=&yEKlP%X0!szIwh>x:svrw2џ5y~Hy .s))wLu[I% 8  {\`b@RrwT@t{(2p2q[t:Xv2AfБzhP[[p@seKrpgxrpve|`Xp `s׉^P uO7W*r[p{g GX` ب ̘}w7Ǖ8dd ZsqǠ8yWZ؄'m{gwj^^pJR/ww;xw*%~j kך(2ǖ4*sMKJwj "ȫ :Zښzyz @:LCR[[#K@#7-r 0A m 0 AaR%wΠ͐  &@ـ  l0+`& ۰ p $!0 p H  2[ R i+CA!Y,q s3wyZ7nΝ.ܸq2j8Ǐ CIɓ(S\ɲ˗0cʜI͛8sɳϟ@ (A :(E7vJիXjʵׯ`Ê ǬYpٮkٹkײUڸpn˷߿ Lad͢U-\tի˘3k̹g|S7lfYU`3G9#3fsͻg37vIƎkm1]سkνw<~8^޼Im,yj,c||DOz#M<"|\߃F(NIH 0:ESM$h(f9ŔO9{ل8b8q,ӎ4 褔Vj_6$<3wM;3楬;8`ͅIB<蠃//&,ILc"9#8%Wmv6G"|dNE$.9 >4GK;R9j0@#hlƻ>LSj;҆/4@s>r ,2wtՑ7t[2h|#,̼l>(r/L@}]M%80L2jPG-uWD4HH+ʹSw`-dmhlp-tmx|߀.n'7G.Wngw砇.褗n騧ꬷ.n/o'7G/Wogw/o觯/o HL:'H Z̠7z GH(L W0 gH8̡w@ H"HL&:PH*ZX̢.z` H2hL6pH:x̣> IBL"F:򑐌$'IJZ̤&7Nz (GIRL*WV򕰌,gIZ̥.w^ 0IbL2f:Ќ4IjZ̦6nz 8IrL:v~ @JЂMBІ:D'JъZͨF7юz HGJҒ(MJWҖ0LgJӚ8ͩNw G>it T8:*RQԥJ@SKt#D0~~5GV$c%}:)VՊpG JWխ:^W+_ kX],csviB Y N66UCB0= Z E]*0$p[؀ mQ BW n*T7]tz xKMz|Kͯ~LN;'L [ΰ7{ GL(NW016 hȱ@`~0 Ap m8,e 8ֱ|| {BVP$ XA Ѐ*x!Ti 3+P"w ` hVp?:nB6.}ߪƀK C7@np$縄װ|\hs7,Pd`Ku90/ā nc. V2.#h<+i͠A r̐8`\w݀O 8UVBt>o3Cg@#X8.eؐi@!0,~ $߹s};(.\lެ0eVc 3f͜t,G\˗0cʜI͛8sɳϟ@ JѣH*]ʴӧ6 DC)ZĨG"ϑ4 %˳PӪ]˶۷pʝKݧЁ#Y3g-RS'N>gM8|o3`β˹ϠCMiy*70CK1Ǒ'Wvv9f Nȓu Xځ D"'{.bŮ7:vhf IBL"F:򑐌$'IJZ̤&7Nz (GIRL*WV򕰌,gIZ̥.w^ 0IbL2f:Ќ4IjZ̦6nz 8IrL:v~ @JЂMBІ:D'JъZͨF7юz HGJҒ(MJWҖ0LgJӚ8ͩNwӞ@ PJԢHMRԦ:PTJժZXͪVծz` XJֲhMZֶp\J׺xͫ^׾ `KMb:d'KZͬf7z hGKҚMjWֺlgKͭnw pKMr:ЍtKZͮvz xKMz|K_fKj`|K"`J* 2J$ v0>H'*+JA K"NM VBIJ]8qIx"qd! 2򑑼%q򏡜)SF~>,d|LYy2Lf0hN6pL:xγ>πMBЈNF;ѐ'MJ[Ҙδ7N{ӠGMRԨNWVհgMZָεm< ^`| qC2l kꀏ/ v6A kX8ɰ%[G4 w؍`_%~ 7D _{+hJ0<C`.lBq%dxI|d.mlH &F\l0$/BNx,/Ѐ 9%Z-BW`vn4@ڰ= nPd ېn|88{XMWqEBЀ5p,,յpẏ`lpN< q%ֶ 6d ;JZ(yH=v`r%C `,( fhs :)ׯ-_ ExK&_G#a]WPpWFP }'~wNpg0~0!/10|pxTpyDkZ|W{p!0uZ@YU0uwljN#{~*m/w0AWV8{F*k-'4͇TP_AzNA<mud`KȄN7nq(wFtf_%y6@u \R`({uNWv(qc0bn.\x{aegf0t&zp8Exf0HuA8 )%nl'Dg;xz./jGz71|phEsFPgTp}_X'd0!NжDXZPHYY@t7x.6U`(qZDU{{Pv\~_0rw 'w_uz-rPxw/zelj@6׊[pkjrrP_uqb]TN(]x 1un$hpnDnƨpulOqkk~ujbWxfxf )EyTkh p9MmhImOǂ_:њ9l^0YdyTEs P yys8 !N 10#@ 0;y /ఞ@VװsQǢ@!0,'.8qٰa&ٳgʚ ŋiȱǏ CIɓ(S\ɲ˗0cʜI͛8ss.l0Ċ1\ʴӧPJJիXR:.۴i1ŤJ]˶۷pʝK7V]ˬY LÈ+>㷁@"Ȟk̹ϠA?ő,|"A2fc˞M)}I I>Fȓ+_S Uسk,I!— ,% p˟O0v7 IBL"F:򑐌$'IJZ̤&7Nz (GIRL*=s#A U*FjiKĴ@]ʀ4/9LLa)LȔ`k2$ 7p5iκsl\P`6+IB0!ݴ&4O EA0)0 $P؀ \ Z BPT h*4:T@4"HIҖ0LgJӚ8ͩNwӞ@ PJԢHMRԦ:PTJժZXͪVծz` XJֲhMZֶp\J׺xͫ^׾Z6h@@`~0 >pp m8hG{ԕ_F΀Ԣ%WC 1aB?#nG`5t$ Hp98Ѝ56fDv[ Yɶ ;P/5->j_P}G nF0! QK@ [[`[Ʈ8@x$eqTi[4 ԰B3́ ɄǨBa5r)mRy$a!x^-h#9 qP1Z·ϬpX/\$aH,1dZ#KG/\΢4M j;\-_0\!X-g̾:ڥo\A ^5Id#6&_Nc[h !,Al kYä MIFNd4|V2>~k,X#Šo2|µ^ĻW8m+nϮ֦0Įl,r')GĀ߆Dl ~.4 ^@C+`$.g@κݮ썼=1@}#Il5rhĚʋFtDM=hW0 !䡱 r 9A/F l!7o^޺;|`#8rmp`4 A.a m(44:9$Vrpr1[`[PZd@ELv^`1bu ,[cT-\קMR}%[D{^8}ck_/Y0d\f`nneeF0| ag`Am `\tQYvmpZ^~hQi\hxRfpm<Z}]*_ronp:jZyAo)}ۗXۇZ_pXg}_{;6X@Ч~uhEX]|XnjZ[p{'Z(Xh\ʼnX_%j@hX+gy !=q0 pp p ` 0 ۀ P P 0 p  p 0Y )x(`0# ~ |bP @ ܰ  !.,9[9gʠ)LƌY3 t f̦MLd{IR\ɲ˗0cʜI͛8sɳϟ@ JѣH*M*A 1tĊ3n8֭ZH<ٳhӪ]˶۷pdp IBL"F:򑐌$'IJZ̤&7Nz (GIRL*WV򕰌,gIZ̥.w^ 0IbL2f:Ќ4IjZ̦6nz 8IrL:v~ @JЂMBІ:D'JъZͨF7юz HGJҒ(MJWҖ0LgJӚ8ͩNwӞ@ PJԢHMRԦ:PTJժZXͪVծz` XJֲhMZֶp\J׺xͫ^׾ `KMb:d'KZlP|`%5> -AJQZ̔ gm 0 + [6`$X[ݖ!JT2e,XT4!.+⃸ͮvK^Mz|Kͯ~LN;'L [ΰ7{ GL(NW0gL8αW܆/ b ؀6 )CNp&; DVp-A>4{P2>@ *L6=蠆"<e $,BJY'yda @<$mpŰ-o @%WV 3+qfMZe@Ā8&~sP[J̐UBK@k @LaӼNIWRe VVIe@)qTы~aBt&oNIi2|D *Ap 6BJZ/0%woZ'oVI,#.a`kr 1aIENr\ \0JA Ƈ8$3Ƀ\1AWBg@]r^Y c@C^ |4 )QWu+6\wɞ?6~wkm)Q xd_e1# ր P aa ,(|a P<!-,+knܸp̘-8qٲ;whܸQǏ CIɓ(S\ɲ˗0cʜI͛8sɳO "T!D-ȱϧPJJիXj_dϞ hE4Hܹf5صݻx˷ߜ_Òg6ٵھ;ǐ#KL֢Ipre]8s뾙֮ZCs5^M۸ssMBEtoVnغKNكD%{O]wz\_ϾoN "J7{ " HB x IBL"F:򑐌$'IJZ̤&7Nz (GIRL*WV򕰌,gIZ̥.w^ 0IbL2f:Ќ4IjZ̦6nz 8IrB8:B&A !GyFT(NL(? H#6`$XЧ D@ B\4 ESqQY` )C)R|4 !^, (9q̒%kq"JHA :8qbŁeg`q:z/ȒNT߹b93v7Y@ Yƌ)/PX JUI# @*>zUS1D@>yJQ"!A_bZ5`޶y*QB\do@ź)udc­['@%ʞ˪]˶۷^ѦKݻxj'W߿ صX֬Mvǐ#K0`/n<ϠC.vs,E^ͺ[Y _;ڵ۸sϝpf1欻O g ҎKNzCWرûn7ū_~S˟/[}TPh& 6F(Vhfv ($h(,0(4h8<@)DiH&L6PF)TViXf\v`)dihlp)tix|矀*蠄j衈&袌6裐F*餔Vj饘f馜v駠*ꨤjꩨꪬ꫰*무j뭸뮼+k&6F+Vkfv+k覫+k,l' 7G,Wlgw ,$l(,0,4l8<@-DmH'L7PG-TWmXg\w`-dmhlp-tmx|߀.n'7G.Wngw砇.褗n騧ꬷ.n/o'7G/gQ>?(T AG0 P>}Q)T >L>G@ҾB60 +H)XQ BR S@0YG-z GH(L W0 gH8̡w@ H"HL&:PH*ZX̢.z` H2hL6Xypڀ--B \4Aq8 ]` A B/(@H-h`%P0-t2!> Rja 8@T`r/ ̃@T/0@:pw6\B 0<_8$.PN7` ~ \!y@ '2NpJ0|G N/a ЩXS/!d'8\8ڰ8 <* 8/| nW5alW*Vo|8ec1H8Ёt5!1,  ,N]9s|%ǰÇ 1C_ 1ZG )ZHrF$=ܘR%>[v\9R/) &Dy|P 4Σ?2t*Q-欚)>PrM5)֔ a~=K2aSҢ¢f'!-,x H >w|笡AwǘHŋ3jȱǏ CIɓ(S\ɲ˗0cʜIʆ6fϟ@ JѣH*]4IG]/t0(IXb5Bb6ӅcuYڊDhH& %8(I(;N8%3$**\vcLI">Yzp b"Ecć]y̰j`ibT0Σ4s -`c/ *3)z8/Ԋ T, (`B)xҋlɟM W, IBL"F:򑐌$'IJZ̤&7Nz (GIRL*WV򕰌,gIZ̥.w^ 0IbL2f:Ќ4IjZ̦6nz 8IrL:v~ @JЂMBІ:D'JъZͨF7юz HGJҒ(MJWҖ0LgJӚ8ͩNwӞ@ PJԢHMRԦ:PTJժZXͪVծz` XJֲhMZֶp\J׺xͫ^׾ `KMb:d'KZͬf7z hGKҚMjWֺlgKͭnw p" qL0"T(\L(u HdX. (!+B7%+X "o~ǵ; f'ahMvօa oՇ]w qW0gL8αw@L"HN&;PL*[Xβ.{`L2hN6pL:xγ>πMBЈNO\ְF5q`<' hHKҖtkFёF3j&tWWDΰ9 *1.!39䰅];!iC5ae_?{"6!P{hCέ#lB?ػ ^P|| \@. jX*3c [з F{Po?\ l氇1[@bw!6M-l &pɽA b׭v K)P]; e;N{W8%|A kP78@ nػ+ _X`@H.pA dXK0(^XP>`90] T0@$[0$uO h@wN` PqB6 hz#q-|{0V0C~d_nqD P00llsjXq7`6lqggxV+| rvd1@|uPsD0~[0T}ytkpmZ7y!pFwX~7Iw`% |~p!@S` AX&t@g0p6^q vWxns"Hv5xPy1(ZP ` Gv5g/||@$Hk~lTtm&{4w%|.`rm`fxnD8W[ZFGQp|yk}jn@U hAmwhz'{@{G%F`P0yƉXP nn`v·h(pU$mW]WPpWFȨ(IFЊw@lG 騁OP)*E~)hC>&XAHB"B!S—*RE@} IѣHOR4i!0,i 70p+\;` #JHŋ3jȱǏ CIɓ(S\ɲ˗0cʜIM|"ě@ JѣH*]ʴӧe 0`Wr 0T14,O" >sմ:00lL7PG-TWmXg\w`-dmhlp-tmx|߀.n'7G.Wngw砇.褗n騧ꬷ.n/o'7G/Wogw/o觯/o HL:'H Z̠7z GH(L W0 gH8̡w@ H"HL&:PH*ZX̢.z` H2hL6pH:x̣> IBL"F:򑐌$'IJZ̤&7Nz (GIRL*WV򕰌,gIZ̥.w^ 0IbL2f:Ќ4IjZ̦6nz 8IrL:v~ @JЂMBІ:D'JъZͨF7юG"bH'b4s)C-KaZ&Ԧ:G tS9:PwZT1I-)Q:FuTfTN5PW &e4j l I`Wԡ O*T5`B)$Hկ6 AX' 81T4ͬf7z hGKҚMjWֺlgKͭnw pKMr:ЍtKZͮvz xKMz|Kͯ~? l`C4Z+|/YІ3xgJ Za 9XA(6`a10@"Nab0( 1, .2|!8 Z \_H+ `-h;×e. `T @5S8mÔ`e.E3I=A /TІF?!H(]`O zԋ6A,U Nt5|jHZ$hC4@b@ցP|r{A 1m/$vm `yH0dB`n-@`>. ր7H 0=,v`@ l8J\ nrER:T\- 0P.|! n] ԖN.Xv`3[S{Nz0uj{Xֻ>u6la @/ߴDH2 ($~9)88Ayf|3?[@2e0Cg3<6π!2,` (Z<| ȰÇ#JHŋ3jȱǏ CIɓ(S\ɲ˗0bH/͛8sɳϟ@ JѣH*]ʴӧPJJիXjʵ+΄^ÊKٳhM˶۷p}KD9VL˷߿Kz÷p^̸ǐ'[vivl 4Gt8ґS^ͺɮ̙3:ft;~MÎƜomڴl〛+ËOvd9.u ȟ?_v\L;2t< 0dS AE/Uh_0 ;2K :aQ,[x($" =3 s"LDiT13K<`B 8ʳc?(Xf8 -π2H &B |bOnHM:H|\ixz%0HBf;Έ:9g6h2e ,( )B'䣤jN:H؃4$#*꩸k~ (%`3 f ҉'sF+K6bvZf #' Rk% .3"2G $p 9 B  l73Pj%H2ϭAMdj¾j;s ̢{77K;AU\w/o觯/o HL:'H Z̠7z GH(L W0 gH8̡w@ H"HL&:PH*ZX̢.z` H2hL6pH:x̣> IBL"F:򑐌$'IJZ̤&7Nz (GIRL*WV򕰌,gIZ̥.w^ 0IbL2f:Ќ4IjZ̦6nz 8IrL:v~ @JЂMBІ:D'JъZͨF7юz HGJҒ(MJWҖ0LgJӚ8ͩNwӞ@ PJԢHMRԦ:PTJժZXͪVծz` XJֲhMZֶp\J׺xͫ^׾ `KMb:d'KZͬf7z hGKҚMjWֺlgK[N3 ER!DpT *@ح d&bYb$K0.JR¹@!ț ) ,ˊ# ![,x HDTvɛ v@ g3q=æ“(S\ɲ˗0cʜI͛8sɳϟ@ JN{a&۬n]6ocǏ!GН3`ÊKٳhӪ]˶۳jRn,ykƬ@y+_$ Ԉf̽L˘3k̹|ec ^w2X0ׁ\ϸsͻ 4-vb: Nm|I+8AUνËYֳ˲^AcϿ GEɢ38L51縗@H >$ 1MXt$h(RĚs: `;NcN8(x >l/@/Ԣ:!8*ViXfMTb5bO;L;x8-yۙL35S5׌83J"9J9l裐F*iw]~9 0 0( 3'HB&0vy'(A:鮼cI"4!84KEcl:d;䌓*>s5 XC9,@ + KL;(ˬJ{:#ϸ tnK`Bw]Vr%]FRSESM;ZTLը38ss@5޴S/JaPG-߅l4K58 ;/Ռcs;3ߺ4t;KԴS|]+1נ$^σ *5,q]ھH 5D9v2hw~.t@LOx %H¸3[,ŜSy=g3>{^Ygznq/'l:򤃎r3:ňK9`4ZA $ "I ! T@B  ' BPH>XР63" `(!@@Hh@$h)h]E:lTz0IL,KT F`=ܑH΢K0w$cx1AB9X X"[9J  C|٠r(y7|OO;ЏO[Ͼ{OOOϿ8Xx ؀8Xx؁ "8$X&x(*,؂.0284X6x8:<؃>@B8DXFxHJL؄NPR8TXVxXZ\؅^`b8dXfxhjl؆npr8tXvxxz|؇~8Xx؈8Xx؉8Xx؊8Xx؋8XxȘʸ،8Xxؘڸ؍8Xx蘎긎؎8Xx؏9Yy ِ9Yyّ "9$Y&y(*,ْ.0294Y6y8:<ٓ>@B9DYFyHJLٔNPR9TYVyXZ\ٕ^`b9dYfyhjlٖnpr9tYvyxz|ٗ~9Yy٘9Yyٙ3E?@5`pX!X@ i2PLP T `6 )@)P TI ԙ yKŜy虞깞ٞ9Yyٟ:Zz ڠ:Zzڡ ":$Z&z(*,ڢ.02:4Z6z8:<ڣ>@B:DZF"rW r53P3G:I:Kڤ6QS*U*ФKj[ ]_jBbKdZ1scp ff\:q|ڧsZ__pW_j`2ѧ:CPڨjmh_tZX0iZ0EZ~my\h_WЪW@!lpa:F`v ڭ޺kj@  {X@ `1ym%1W![_S`Z@~:P0y,۲Jjʡ^8+pU@pP+\xJ7 6p\pyPj@jj` Cpb D+O+m+0{v{mpb0gb𡂊* @*tN)[V۵qq_k Wpb:۶CUkwkmlph롈[rZU`]@~@[^%0HzѼy_ nyX` êFyl\{x pv/08p`UӻLy?K;j?q 盾 {{-K;zZ63ۡe|\Z k10|\+\` z I Gn4 mD*}nbh#.$˜/|I)4. S朚j7v\"|Za._5k®"[+\ȝ;S>}km{"LFpahn{аcĊ@8Z5rYvSɓ|9Ο%43hЀUFW֯c\{j|^1SGN렽&YSݸp˜97nPۅ];wﶣor!;W{Ѥw?ŔZ4EOTOQ59zQM "Մ>!.,y H L2q]#(lġV سg.\Fi($wkȁKڴk&[֭>`USYIHa#ڴif{ 3ƖF[4$Kg`9*֮Yh5}cZ-[Gfx5[ _fD:V1KFŠN˘3k̹ϠCMӨS^ͺװa3tQ"k1jH&I2KJgּΞ?-z4ROzUZ5~3˺E6ҵ5^7ec8 dMFRl 6F(VhfZD@3MZVe_Vk3@m%qxMF%i01ӌ2 )ӌHe@W5?6dTTHT\4>%QLVFX2c]59VWs10AWI@XdU᠄j衈&袌"ʡ H">dFfV,"A3>T#R8&Ύ=6ؐw$>IU z>RSdەd9Ж] D]&3guޙ| (fv1 :X 7À04>4 (NQ;OK6(cN8.bN144N1u-!2!NI3J9 L5>@$-,=2 .c13c4Hf#dmh]vQ"IA/3˰L:N3Q.. s 2Ô7=3RI@@s 43c9Lm;bWogo'7pZC;/T<u===~P/tź@s>Ĉ H޶kG;΁'!'<|oX`A(L 'Id^Hr> RP{/^L 1*`f @}p >&AN9a 2hV6p\,cD X8t*d;jT, $(H3 E(xe- Ds r1C(F<8Ic=F.|Q>vY2b׌N>qaK`9Ť1$XD }y{C1'IZ>1ҕƇgO4jY%yGNSQ)@ G_M  t<[}oU oM5<1OCx@iTz|Q xq*ҳ` bNFdhjxBCX\E(&ib0<<~N8Ph VogNZB҅` sk8 ؀ ~xBgsL؄q#GgQp }7HWoa0  (Hf[cOXuȘʸ،Hg lj30B~H&&r5ЊXxRq _I 39q  c#&% Da  uP1tQ!"~5@ @.  0x.a9 T ``] ) Z`P t2c|8Y ` 6HhjI/E2ǒ U13yI,x3sX@ 712i4 ^P?! B7!N: u4/P9 @V y'%@ # bIqkYImy3t21fߴu #6@RQ`QaF-9,#y^P      p Z PUCP0 pP S@y T`D0C w*kAPL7 `R^Pم1FrP)0⩇W#5@ p   0а/PF`j @zJIz` Ȣڨ=袘a 61~ 0g)\[!T<| 5 P 9M*~ P VPmJP 0:) P0_PJ ^! `zAjetcQ7%_!(Y(%PP)^A*Y: - + ?I$PWp`ZQ`GPGW0 劮@ q@{3>Y E$efP))|Q n{^:Y7U x< <ə  *TYW  Np}Pc!B;hD;p@  IOtV_@g28h0aji+@p `I )u:ZTMг~` 1;U˙k"3$-D0*i>~_Ov;EK\1?J Y Z+W0 aZNm o ~  09[ { 0F F`=#v!D\D}E;b#(|H ]-R]!FfG38M[ \:<^ " + YpS8p0G ByF|ɘBZ *n竾!!# P`pu7BM;pP;p0|5+:#| ր ::P @ zIput ~ ` @a<@&sؐ77G(=a+_"03UЇX11S9@ bO50& `: 1B oجb1Mjo @ T^V~XZ\^`b>d^f~hjlnpr>t^v~xz|~>^~芾>^~阞难>^~ꨞꪾ>^~븞뺾>^~Ȟʾ>^~؞ھ>^~>^~?_ ?_ "?$_&(*,.02?4_68:<>@B?D_FHJLNPR?T_VXZ\^`b?d_fhjlnpr?t_vxz|~?_?_?_?_?_ȟʿ?_؟ڿ?_?_$XA .dC%NXE5nG!E$YI)UdK1eΤYM9uOA%ZQI.eSQNZUYnWaŎ%[Yiծe[qΥ[]y_&\aĉ/fcȑ%O\e̙5ogЅiԩ.kر[]mi7ݿ'9xqɕ7>s|G^uظw ڨyI$/#{q'Xý|̢~"B*TpA * b+0T 5j8 /qRa%B()aEYHqX91YR1FcG y To,ErJ؈J*+deK0üK,4ȴM6,LM"ݔsN഑N< N=s/? 5T;tCu4DUQJ+*RE tSNTNCO'TTSUuUV[uUXcuVZkV\suW^{W`vXb5XdUvYfuYhvZjZlv[n[pw\r5\tUw]vu]xw^z^|w_~_x` 6`Vxava#xb+b3xc;cCydK6dSVye[vecyfkfsyg{gzh6hVzivizjjzkk{lpfmqIl~i{nW{pnyo;pkV$qآ 48 \fh2 #(qPsC( } mJ*!@ Pn{@*  \//Q`@uS&рq K$1M^,MrSD9CD92 D 䡃(@ j&|Bh1ԡABCXmjD |lH:pR!H1.tt 4#͂ jB|A@.$Ukek[Tr-0!\!Z;pس#`_JWx*$(/wT}"nރSqW#V@ <BH!>{e,gY}NwP佂y0 S0@ ZXr`WQ+/?a!0>ؠ: iEk$gZz%' NY^B_%qbڔƝT|(A >7 4>c5M=VKN6d2(30Y0Ff;ۇi֠_3cꩅ W85wPgX@kpdKG{Iyao+Qx-]/ Uh]1 eX :1P-.>pwvDHB'2Fbqa%tp)wuC4ȾHj |xh0*Ȁ<9h A {*<!R‚xd6H.ĵ+&Sq2D4E18WrC*0/.p\J+.x1Lz--`{0͛PC<@z .|8B.5*!.#TRقX)5X䒝/.|Fh 3rG~GG H\+ǂ++RMHE:073qTL4:fZ :9&زGbHd< a&21S2'8y|J˻8ڴ#S60˳r:: JQ*KtEotC31Ȟ#LRGv.۱l8-p+=xăI,Ra"PE44@%'V͠&HWZL+1UL+D[/7M5Z%Z*-tE}\+k0H4T2 djR%4N̶1<0Dl4ʞ"DzBC&1ÈD͌]_`lHVr dxVhd͆jd8Sj_jYeqOug8KV>-o}m 7^%QX\_~ׁWUsU>HTIMiX5׆ݏXa-A-_ TA-Y=YMY]YmY}YYYYYYYYYHZZHY!X0،ESqXڔiZڒڧ!\,:A H*\ȰAI9Hŋ3jȱǏ CIɓ(S\ɲ˃ :)l/sɳϟ@ Jѣ AtGhJJիXj5'́L b3׵ٳhӪ]˶۷pʝKݻ<ݽ3߿ LX*|7G*L˘3_^g.W1|Ŋm]oM̺װc4._}3V kMvjEVУK/l­WËN`觫_Ͼ {\pɁ)d֬Ylˀށ&+E(}0Ӌ4Մ "$h},&׎m䐳P5W>"y`ɼ brC A!xO p !!Բ,ȅ+|s7# ;Z2@ zڪ;$+H'4^( 7 à$ҲeG/-d5@ L8TL@څ7"װ`'ZN DT7נ];tM-F n褗0@DCQ| DQź^΢3RNئo U @3+D (Z} ^ X9ȗoZ 3(M;͘, 28#0 N9X81 vȅ8ȇ:x.юԨ/6q*zuoi5|q>0f(#8 h$̸oB3bMcw PjL!&:kCbhΉQLegc⩆5!sWbc1jTpc6uҸc:F:[|cXGE1Y)HB㐲$IRL*WV򕰌,gIZ̥.w^ 0IbL2f:Ќ4IjZ̦6nz 8IrL:v~ @JЂMBІ:D'JъZͨF7юz HGJҒ(MJWҖ0LgJӚ8ͩNwӞ@ PJԢHMRԦ:PTJժZXͪVծz` XJֲhMZֶp\J׺xͫ^׾ `KMb:d'KZͬf7z hGKҚMjWֺlgKͭnw pKMr:ЍtKZͮvz xKMz|Kͯ~LN;'L [ΰ7{ GL(NW0gL8αw@L"HN&;PL*[Xβ.{At`0LA ̌2@l&ٚley3|+B s&oU *aB)mT@`9$hZ )4XT"e!G]zժf5>dEH,pmj\zQq=l_NN6}f;ЎMj[ζn{MrNvMzη~NO;'N[ϸ7{ GN(DOW0gN8Ϲw@@]*1ё18Ng:J@S]' !',y H*\ȰÇ#J$hϝqH97n% 'NZiB7h৉0cʜI͛8sɳϟ@ JѣHe ,_2hOV4y̆mڬ sٳhӪ]˶۷pʝ+0 E-@zـW|V6˸ǐ#KLv ^vnNӨS^ͺ׮4O6Ax)v(@YH 4/+ȓ+_μ- (H5 ËOyKb:5k.d"MZ5j <ʠbИr@46% 6 55Ҭ;T/C/HM/x#:Sa9;@K;לsN: )D9&3L:L3C8Td4D3( ec 2r0|yВΈ5׈ti'c9O.c/i䡈&xH*٤PJI8Vb%^R&'̓jĦpy穧g;g*무^֨M0 0k2&M 44cY24N8sM6fζWFz+ {I"rnIZS:[*[>AҼ꩸fN'>D,kg$@"$C2LQ)9S0_R*5S LY8ňmCS.rmGÉ.7 PG-5| ǒ5%h4*s`33:5W,Y8rJC=(8|ݷKCܴOOm X=93~3$" AYxC,fʡ{&]UЁtE5@uxÊ昇D yŠF2s:'! )Q8|Z@)F;l_Lg0?\ (GIRL*WVR,@8"^h4j`HȽ@;~#R 2_آ'}!1Z( "E{Rb8@43SG4 s h22F/0( uDch'Oy74dIvҙ8`E2cx` h( 7It8i[j04!P-@L= 2P<(Jb  Oħ`TǚSA@aʹqTE6 t/D cPS @ (^"8*C cL0`U|D^YImb>8O8V=aOlSaR )ڃImF;ԭC(c]lc{Չ[b cm^%NF#@ĥ~E>0fA >m\%=Y']. wt̀@0 퀀zv0Wp7 :<؃݀@8  'H>:HHFNLȄSP3T Ô"2p ׁE_y7#~?5X&P\xXFN"A`q׆hb3'9Eyx ~w'0b{aq# dvUy[x]0W% 'f 0h2Xo5(8XKx@ qȃx؃  ̘`Rp5QC4v\ n3`ـDSP .@ t6 ф "P p *Q( `St."\ր P agO& w "fr +C( GPi;cS! !A5 )#yH g ܠ68E2S+QxB\i 1W\Y(ҸFB}b|BFߠ%(xtd,!Pr gC'S ՘p! w;.r6a(3 \vEՐ (x#uG w4  l`I)1 0 2 94 0LfB@`pRN)tS/e(^`9jId9bqNY(ɖy(TsPY v%) :BoB2,La*`"6pC1'Ԡ xs 60ՔI]", !dHА#5S r `I> ڢ2 H> d@)މ9]_acZe%ҦYҟhd+i&J M5 #Z5#& 'O`DТN3 4!؀ 8 :ʣpDX3 )+JAM IG: ºTjrUS:g iɞO]IaB[Iv:CR3% 34 ؒ!- 7jpsRG,NTR1 arM6%P MdF + 'nB b` P R3!P6p@Lb-sUlq# ?BACk@AKJCP۴R;T[U X{V\˵Y]Sz b QR |!C z;%JG Z6ڨ[6R-t {` %Fnn۱w [n#QI֐L. "@Ld;)=O[Q@RX+;Vۻ aK߉țA)R6> ˴ F+{؛ڻ۽{˴Q{2ϛ[N;;[{+BDKӊ-Ӿ[+ *|jA΋I "<$|<*ia{[89 @Wۿ)B؁#Ʉ1 Ƀܸm X0 sz@{p 0 ȁ M`7@CN l-p-P0{9@ C~~0⁀k^X@=0,Xޘ</Nw^8 Ɂ+jN >a `Rҝۄp#~P`.Pق߽t PUۈMB=رݴim,%P^> ue-U.žFp 낌+08e^샀ݞ,N[^۝n+^oP=}%> , >1NpRPƮ W/0W7U؁@-P A@}ۄ~N> N݃1}9@P@ #@0`@ f 2bBp"Y@ s 0s$5>`D ȃPvXb5v*T Bz`0 (: S-!DREUr3 !A%X k 83`>"5Z'$ "x8HRO X~ǧ&2~5~zW)y쳟zҚǵWw' ]\]$`@&!d`FPz`-xALP`=Al.vBP,1aõ0d+a mv(ڲt&VzQ$ yiB +%nxE,0!U2@rAK7N@b(d jn0%( y1 |  (,RP15!0 Z !f5JT@jd+]B.@RqQ9ۊ@!0),085} kМ,V' @ڟ)VR۬p%? Pg@űM 0ԧT'RR9%  H@f<6ͪj%yPZ2f-'( Y.)O <ᑓ:UOMOJ:xAkKhK]ʲ.H[PD02- HdF 6(M3W%Dn&=iP"`a4KzbmѐjeN3WLV}MIB3Ղsb2DJ&` M([T! /h (! ,kiMˣrziP#+w}iؿIEAVP"6}yA/`VPl:\*ӥ.؀%qCt[]W1@ЕBWeW^W= | W:o{_8&%D|` ~H$VH ^یeo a#9ZO%܇H1}J]d諤_7]ҶtA1qdsHڋ `3+f󱛮E/U%<XE2Ys,EIL. ({rK)C<$mV !-@bFba3B jrt'a4` A,`Le:'k@P&] g 'B0ĉV\\w]c!p#z1mDPҾZ%ĵk\iT]1 G52Rʓ6}oVϣ6>4;I U@Wl u DP}x518W1wN fMVAJ3 I ,r֥ \XH=9o yѭ:!Dsp%9YQ! ,$L~:(Ԫz֦:t{] eHjY@LX9HC~ "'6]3C&ÿJr8̿?䞄7dtI@N!@tq"PX= 9Âc#7CP%A3#;_3QQ4= a PK(ȓH;j @QH!:,ѷY2#))r9~"dҨ5")2y:Yy) 3LDAñ5BAXIpæ#8Bc(k3BCl5E\ůYAF49mLk)9CBYDtH3Aq9{*Ђъ;V|FqEL̶.[j<"5dۃӠdl*FvFHnjƱ`β~ .`}G, `P;(Ht-uLvH}1yYJŦ I43H0+ HȁH쯚Ib*(&($II(/;|J!iJJ|JJP AJJ4D&/>t% ElKh]?񩓜I9T/LL ~'l 8RLt 1(Ƴ܏{@T fLA(K. >ysͰ 0 砒Jɦ!j|RҠx:04 GPɔK  +cI<ϱP M4+L:`&q"'c@b?pB0N?+5 T U#C ѨPM9#:*6-GkS`pA [42Rl!0DQ#e 895ԣh NY7[EpI;88 E"=R8=K蓈@ 6~#I,R!C5ӢYSiS"8T+풘~ڃPsQ2ʹGSL99i;L1ZFRS -BhFT_ " ᴳBhOt@SB{D4pEsU(r[-ŗ TUvքtkK0/3BHX *=-Fp&.CQ_`xT*DDنUA(^Q=C݃x Q6 aZj!U^%d) 01H X,kݵ>hpB胅\"xHOBzcpnՀpW8^Z)mc_Md?GWYIh:4I[FL9⒜J_Pf׺%b.a&ILf#Jiclvmnop6水>2%KK_r6gtL=2q^wԬ&+W,}et+ [Q#@d 1ѰĶѤM!tMp SMr8,h[ְS<3Z]ԂߔN1{jtj kNNčh=.SXOԝ]`,~c,4 ȁ]ő[\* H^ ۿ521M T[TOkŤ A^՝cE_uQ1~hW8GI NB])!fLX%mR=~[`@R f 1_ ESaW96 $1{l"A;GRFU`TBnW0]mbG*3Yogoza}>lM9ٹO QD2Ֆ=%YUYM9H\&c[ r$>]MbUdOábmP0JV)'eg%imjk kVYor 5gaqu5o_˄U H AW}dfmU'x5-/O $sY$ʁ%qrg"QYaYltн6>OtJנRSߠTGUVWXnj)oLҬM>QZ~~1u3HLĉ0bWc޵k I@HlEl~ZY߸ F?Vlvow8=4]`D <P\ƅjj1ΐw( shx.9%5|/ @H$ }Ut~H!]A*cI]#h}.Ns0 ^#fÞEk@^0˜6kZ.b ʦ^ɚC)9m L)`ñ _0?+@>i9E_y43۔䮨H_a N2FT<|ʰwqA4oʹ_Ѧm6|4O,Cn("h?c4TԞտ`'K̋7Ʃzq/[pwQ/X7~t)a.?HA? 4HK  Ȁ1Ka #*W$A{4XPWZ1 @A YyBB@ RRju˝}j+ذbǒ-k,ڴjײm-ܸrҭk.޼z/d*Q"GX0@B,@A!LOE QP`,r b@d)l"-ɓkLZT:q<GگfTǓ/o<׳oZ BA}L{`@QF0PV}~ 6DJn 2 uH `AF8v1ʨRw}K#=#A 9z3y$I* M1ْQ*I$UZy%YjRz SeiǗA 8PTq%uy'yꙥ}jׇ VP_}J{:(J:)b1z)jzdz)ئzꦣ*Z):kz+ _MR+*,mJF1F2AAe,;."$ `OMrMF/KaǨ .5ob;1[UBLJPK51L6 l  ^ G=T fF7ꪳޤTP<σ F!VMtT.@ yJ?EL[ D`Yg7 I @hh[e,r&%IE2.@`^X`( (W n` JjW^% c `(Ħ5)`V '`#J6 }1Dx p@ pB萉Ʈ30Pd!@D(X&h}{@ 808BdrZl#.PMRVT`@1UBk!Q9ARU.@eN T`!p=j2r F[+ZP9l@U u T*jSZdn{-lҶP%E0ئ-AnǶ}nj8IQP'sIm.t+^_~xӫ!z+_ν=|ߊݷTG+YxDjՋB܍9O0B^m$($ ĮҰwL^qL, řpPhy%V1(L`!@ȦI+u3yzm05 'Ay:ҁ6ApyE/ѓƫŽY!Qʫb(#7+@XX/B'1‡mB8-z$(Q:.-x#Kn!6oj35}=ZY(pP333'lI%b(GX 2P"D z_V|]t3^Gs6k`ӑBS7rpT$c/ebQeq;9pa\$!M0 X@R߄D]HX~X ^%\ YdU6ନ > , AAQr` &!If p}=!wI! *!E  !le!v!X|!!zKaYa֡!~ آF Fav"!>! H P`m˄!")"2#!$2 B, =QLŌԡ'~X؀ %v/bU a-aXԀ `Xp[Hθ͔ S5Z#dc D ˌ  T< ^# ! M| =N @D[@:]3*aɇހ | )\ ܈R  MdȜUdV-ċd OAHZZX@$fW@cڀ le) NYHED[ImP@LUTZ Blς8AZ P0,9G5I@ȉHPf!!0XW.je Q[iXl^[uRD_ɑDIFxZ )a L JԒ2Bdba)P34"%>0A)d& %bv+bؔT,A iQȕi'ݑd@8˱٭mb`֎,,eۋg%r*!+@sBg#N'$u vv)w'$$D%%nk"FR}Il`~nA(|R h% +BaH!i*Lhh S39D4hѽF6I@D^P@9ELS Sđbܓ̀,D3)DKx J(>, )+¢2JPB1hNE_]mMF T <9J^T )L 4Q*KTO9OrreLXN Aj *+>0k.%0V5XX UZ [AULL\UȀ^iZ-@VXQ+Ab̫rA0ؙnTA (Jg}VZɕ2ʡli+ʟ6+.6f&'vlLlJŊljuo`˾,BS fK{N vXmmy2 6j--NUE~ fmA]-׎~-/yK~ h)^K4<D& 7ƭ -g|X/JOl- Qь*vKSplݞ #͈j4-P)9H0A\1jr }m,gGn`-Q.Oq/dLA@l2uԞdjIeqƹhH]a _(0 HFfPgF @GipBkFܿ%49H.%;tPR`/=$IH~4 ɴ]5ZGJG6QDNh'NSDH`/` QQ JOt kKwHu-'z5YXnEAW`w5^4aPuY{ij@yaX'v6cSb?v4dG dWM6fIݾie6i JFtl%ȵdKh"6msIRsl6p_mjm67s[0mL&"9b<8j\cOgr5"vH@\ |w !G])s[FVmjV3i]H Pi+Ԓ .ݹf2؞snfgqӑq$i{Q|zq&\+*I3W2qG{yԸs͝ :FTκCE pr(;h$s( a:9/K_d 쏛δ,)0TiB\:mS{LG.RD ;T<Ӝ߿ DcuJC;|_3< `4/@MH" +@,1ԅXZ*)E O| ṶYӼsV`EUk@Z5! hWUkv2ZATkL@W  DYH_5[aY,A͡dkUZxIh9,Aٷ]Zv>Y,}ŬZI(}J?\xɺtj,0{y -w'"ןg]?rvX?F,- pw7! ,x`   aƉb QcH#53yeJ+YtfL3iִygN;yhPC5zJK2HAM|`AՊh8ȉTn\sֵ{o^{ȧQfJVAR xPKvthѣI6ieB$A@H d tLb@w8 BPZ§Cl9"Rtq@w ˱RlnQ};2Mڈ#b"(:(J: 5ܐ= `m1@2_`A ܃p@ d`A3Ya [h`aA ` Gх*>"Fq X@ @o 1Z*4d%V^P ?tl=*ۼcH%J-4DTs@?A1 ߣ+) *>H@( 0WLV&;kTWBZ"u|"`,ʚSBn "ڼb A#X`h L块zߔR;SB<%l,hUmR!- mp0ݾ """"?=:8`#87&Dk]j=Nm2ᔵn9_i,uh x餕^馑ʨ;ӝ#`a`U#VX0^V~ P`H:Sg18"Cn ;Œ +\ "=hFNStl^ dVOy]B Le~`[ޘg=uHvPDQʰ`mj_'רr4^?" aVo ZH S8O9VR@ n @` A~4/pDR Qmm9Jǫ'A SxafK Z ?4@D `s`ɧ>#ITL42٣N*U' |g0D`bf<#@ P'r)x"mlGݬ@1DTFL9#" AXIK^ IO~[2YJSU2AP<0<Bd)K>R0YLRjn Yf3uӁh~Ҙ6k~'`YNsӜPg/ vX9d0c3 >ьv0< `dF5q |D$84Y |D09c6 q88r0F;ʡk=a x0rc4ԥ#9a#03j f%/v<8 eԔ>i l3Oe8 dK p8zb 4|f8AዯtcC;¡72z {h/r[cF4!b'-/koXj5~xaT[Pn4:_p9#5:JvC'j;k ʕ0qoEsN _åF5! Cka\P)VYb1i\c9ycA\d#IVd'?Q\e+_Ye/a\f3iVf7q\g;yg?Ё ]hCщVhG?ґ)]iK_ә9iOԡI]jSթVYjWֱ5+j kTcXyֹ޵]۴n5lg N]mT;ֶJڰ`|$w8ʰ3`>.n5O谇/ġyIqaZE@ Y4 _hCq :0+l ]@5H] TJs,X +p? л u[] F0@t/A k8TA wIpq> q>܀/ npû%# 7b ~7t FXd=m`wnZ B w!n8Cu>W8bW^%kw"[0<]M.x5:9 r/a*  -%@ ^tnn`MWN .2Jo` Bn V t*&` fp. IBlA%oD@l)ހ ."` {ޮ:PO րdNۀ P %:N oLZn ` N0%Rpk0 P% lI!<P ``c.ަ^ gN$l / o o Q"P` NbL s^0p Jn  4,`^Uގ P $($z$ p2ؠ `"B$FA:ZM @< 'vO"Q" L $#"W3PN :M \ N"%o Q t^`p " -%F #'%`2 R%i!݀%ObZ R 0'`v#B *r 1%N‘C/Mrj@ @ X`c%. = 2C37W.1cb/r $S$$(S"а9-e@4N2 SMX@<ALVbS VsĖ H77mGp8߭8/kqF `5s'FNRBR @ %-C^`&NBr~.,  % b.@N m =@ER ʎݰ2AuШBM&Fq6&~$-oHM;+A.E- t.ƖΏH\L'0`{` b`64(f (c@JTc7`&0Z} u9 4Og"D `%OD W9 M Ѐ d``%` N1` .OX"F@>r ` 0 GQ` ` X1%f "`` &8">tk4u.[ Zmbv1[*$]51ߠ ZC4 U#w"` 0oBN ݼ U"%*o 5 @ C ~TԀ VݰQ  t@.[fe"1ɍV52YHIV4264rqAG$(m%Jn*$z* 1qO%X3jig% -.w[pcq@qw4^r!u-tQt)uq5W%Dtux=uWNgvSvGw#Fe?%0f"8_2?gSB؀eBVڡaa**3AaAJjTN!Ёje؟8*Xl*쪦" +AJTA!a!H셱*  Y 8+&-Y x?:y!*,@ H`hي9;dʐ9s֬];_2jȱǏ CIɓ(SrtȲeAoւ20gƌYdfΥϟ@ JѣH t C"IOPwbœ%RC`ÊKX$YhB| Wf˷( dd@"'H3#KLrd&&NX $"]qկװc A2rJ>M؀WP% 0d)4ؗ@\ )H% {ŧQj(rǠ'hȁq;"P6C@@SaJ~xRCS >tvsK8Ȓ:HK;xM$HCTdK':C>д-H-r9-ExM;Cgt$Hk~A`S 08CM624䉏:͡-,ᨣGh5mzTi?ifAqYyً/vx. 5qfCiBJFhK5;̲ϴ#,0 4x+LSM5ҔL; M$n3h覻@,2Rk0 K4#-,#kϰ 7pWl wxw ,S(Lq' 4(s8,:3 ,M>5+.; "KM[ K*۞ Dݜ޹n 8n>wᆿxk/َ?>vMy[_՚o>u? zKNѦ>tz={β޴g{.z—N|/z}OO~_?|}>|K~կ>v/t?L ߏ?opKxf;` %]{  Vԏ3x0 r2'j 1~.b>0lC䰇!;!FaKh?$213| (u1"٤-0^`1`On[@W0nU\AP5q C6QE%[F'w*nl\GRTwllcޮR'ZL{Җƭ6sR>Y*#e<*RHԥmNuR:SUxSEU55}*Xe(ֱf*Tֵn}Y*Wzp+^׽!~+`W9,Њ׮2ͱcl]!4ʆOr,4K>̾{)A{>ϲImQ>Ӧ:m\kV٣̶+aqK3̷0˄5*Cnʔ2̸r.kGѺz.Gһ/!kH"ҼD/#HBҽ/%kIbҾ/'Iҿ0)lJD0+J0-%lK,ﳳdm[l/ d-A!T, HA|)/>Hŋ3jȱǏ CIɓ(S\ɲ˗0 v+0͛8sɳϟ@ Q^ AXѧPJJիXy'&AI`fKٳhӪM;o޻YD x˷_tAͪPি+^̸cE0ã_3k̹ pj\8|>˞Mm2Ǜ7>߽hWȓ+_@#9M .r 4be[柀JC 9< % X 6)覜v=ͣ(*JI jB )H*jfT+>t W'(+k v2,]&ʥA&I)G 'I݂kアC.>`'ۀ.Ѫ0ož&%@" "q Ћ (<{ `¤ ",3N1ҵ 0s7|,d 3'ts1/4s9H#!` 3,#5"K. .W"7.K.}|7gf㓚4͌9N;娣8‗}Wnl\&IJ̄38\S7x Awg\텇>zՐ {o'7G/Wogw/o觯/o HL:'H Z̠7z GH(L W0 gH8̡w@ H"HL&:PH*ZX̢.z` H2hL6pH:x̣> IBL"F:򑐌$'IJZ̤&7Nz (GIRL*WV򕰌,gIZ̥.w^ 0IbL2f:Ќ4IjZ̦6nz 8IrL:v~ @JЂMBІ:D'JъZͨF7юz HGJҒ(MJWҖ0LgJӚ8ͩNwӞ@ PJԢHMRԦ:PTJUڠȹ*VmխF^ XUլ9V ڪ⃭A 1W"Ʈj_ꗷ<*WŰ@@bQ:/E[^V/fjςV-gKkZ4U^k% fuP !V.^JA" A P ͅ lHXw--!+BT7]K*+ |M|Kͯ~LN;'L [ΰ7{ GL(NW0gL8αw@L"HN&;PL* m`ڀ4 B ?\ D`/YІ3\0e/A XP>>`=l!+(, h@P;92@8@@$f*җƴ5]3thAp||A̦nsHƳ+|/+[ F0@` ^6І8 amk 7 ~pp ֶUyܰ𹽜eUC@XX`fyƷ}ZP}wN5< ^@ +` lWB+a 22 f ⁀*\ @>*:ր7x 01,P_Ws܆-hu΅At؂ʐ _`ܿ-^ DZLnhϠۺ[LJ/>`r җ~=_o{5^ _}E5Ȟ=5 $1}pFka;jGeґnp䨆5p}fCp,`<3:r97Ր ؀` p  :&h(:hc'!-, q H*\ȰÇ#JHa 3Ǐ CIɓ(S\ɲ˗0cʜIf̋˶Ail JѣH*]ʴӧPN:tDʵׯ`ÊKlTyTMٷpʝKݻx o:n KÈ+^ #KLˉ dlp|HӨS^͚qdj9_~͚ŎY Nxvǎ3g֊&9_kν5kVZs繭歜˟Oi`n%=;v\3/b߁&^Y2д,Th0vICM4D#9]">~0ax<N.*^Ȣ@)2 (B @!(0-iXfyX. )td"Zlzu )'S!@0%68m*蠄 "I7XH {ϟVj饘.$0 ,0(%TBL*kIp'Jj8J k1: IBL"F:򑐌$'IJZ̤&7Nz (GIRL*WV򕰌,gIZ̥.w^ 0IbL2f:Ќ4IjZ̦6nz 8IrL:v~ @JЂMBІ:D'JъZͨF7юz HGJҒ(MJWҖ0LgJӚ8ͩNwӞ@ PJԢHMRԦ:PTJժZXͪVծz` XJֲhMZֶp\J׺xͫ^, dp"L##5V)PJYc% VtX`E)AY HMigeTVelgYpKMr:ЍtKZͮvz xKMz|Kͯ~LN;'L [ΰ7{ GL(NW0gL8αw@y,eGFD kPF3oP;tF5A)c)򑓼dj4ވl cdy]r\g x\lHs1#E$",C3Ĝ qtRC'zэO<1PҘ4= jH_mjȑ8!`81Y@ȅx,'Z/DF5! `rp3;F#Є;f0rmkJ@ivg0&r<!B7E6!fP#0@~p,$a=`D$f1@(P80"Í4L㎒d#;, !QE#MGHJ/`aCA!R4Tji4d馜v駠)0ׄiꩨZ7X3K<91 ((E2#M"Dˮ8aH$"M5ըͶzη+kS6j"I *P'S+ 0@  ~3VP:8 &I^ 믭psH!HC,10ch1sܱDme3P*x 1#;Ҽs+KQ͓>_xn;<EU,vǎͶEN{1R9Z69czKYCH&BGVsCH4q`#@jdC{j9tq kXX f!H"FG< RLd̈udc(F  $*hG60)`7ġCfB4HG#F)~@ẐE"ЀlaȈ/bPj 9G"!6y`--FIRL*WJdw83HZ(㙪v];r k9 Z2 f02cd3ɦ6nz 8NO*-vd7t#@~S @JtgAІ:C*|fȝͨFxγgB9~RT =hIWҖ0miA-ꎍ75sϒ)KZрHMRБ8TשS>SZTJ XЊ:ZZĪ gmY*Բ4FXTl `V]Ur']ɪҁF"e*_';QBͬfVX2Ȁђ`+n ZR)j*`Zbv:{X! =͐,O@dh-oaK]ԹkִMo}zdž{\}FOujuAxo]4S @(]@ |U}_HDbAEkMGX] wv/q%{bNőnP%z8]{eo@{1I? P&Ύ\~"ukWHSU:9hNjLQapdC u!+05sBz2l&s-\bj~~mhР5^].ǧ%j}3jX԰uXH-vefRUTZUhcךǫ>u}Y^]\x62 Z x;Mnow&vv=j<1!~Nj 'N#\*ϸUq{ 1񒛼!7tJ@"g~I؃ @8Ouo Gҷp>yťN ` :no `gB@r7 !PhWpWjgv\!x @ܩ-h< /ݍ N zC>% 2(!?K` 0D | P4{ #<  "U?|f~٫/r pP,}7}A vtSP~f'~g~W>gudW~ Xvc@}؂Vy~—vw' '+900/=fW: P3up,R^0(w!xrZr_7> VW{ `xbS/rxQv(X08zxtw؇{W~X7+h؈8Xx؉8Xx؊8Xx؋8XxȘʸ،8Xxؘڸ؍8Xx蘎긎؎8Xx؏9Yy ِ9Yyّ "9$Y&y(*,ْ.0294Y6y8:<ٓ>@B9DYFyHJLٔNPR9TYVyXZ\ٕ^`b9dYfyhjlٖnpr9tYvyxz|ٗ~9Yy٘9Yyٙ9Yyٚ9Yyٛ9Yyșʹٜ9Yyؙڹٝ9Yy虞깞ٞ9Yyٟ)YPQ6GQFL`: PV TP?j2LP d pL 9V P 0R@, *c Т85zc7B?aCz)ZCKʤDQ*E7jS Z_)ʤ] ^Yazcjlڦnpr:tZvzxz|ڧ~:Zzڨ:Zzک:Zzڪ:Zzګ:ZzȚʺڬ:Zzؚںڭޚhy^Z`FlqpyZ[pk`Pnn@^j0:z`8yPg@|efJJKghyT9p',A@ZP~pZ`Wy:f_!;^hk{`0WPZwx! Z0T;۳?X *K۴W4kzp^`,P 0.nl^`+KLhK~Q` pUppl`x|۷Wqy"kZ0W{zt& `T[{ `1z{[k~K{UKyz۵90W p@,`%[w%`2k F}\ \R}>{]q{lprp[ X0% ~hqp`q˖`Q! \ :<>@B<<K2yt'[&?X8p[S1@, U@l`@[{{qlspdf k3Lg`[fL2w,Qkq7wsp;"$l`0D\t,u cx,`qxqYcȌcbKtt[^lxw{P`[0cA:;ei0ty@X` ٬,h\P_! "=mлp|o|0mmum0hɕLdЖ\,̼ԍLb;] Z+l!u"_{j;˳1+.|+`mp\},ʷb!;Kjp͖n0<]JM RMajkoM`M̿?k_moMr]x{ 4=QqH+̊Mvمm/`z,pm #b0 Π 0"=AT vޠB0sP A+Cΐ !M4!t^v.,B^^ 0˰%>L>^:F: rQo8;o0 F8P6 ݐFj4VZ{a;+DB` p LJwN AƑM)IS=!^ q陾.kmDC #ca Ͱ #þp(_.^ А ġ-.B:2~Eq CCmQ@ߤC^  n3`bp P 2K6  1HO E ^, ^n4c#&*FY KQ !1 45à @ äMFs1A$1K("蘁Vn C!ق  ) p`1 )nol) !¡ `E{" ^ ͠n/<$!>KA$>- o푮-~aV A ׬jfΛ4rY5!E$YI)UdK1eΤYM9u$)IR (C0#R$Cp`Y$ ;bʮ&#[63f"jֺ1%}*okV{mY !/,M X[d!>\ΡCe2ZdFѢÌ̠#["AhaJ [w`ʘ&ɫ9G&I0fbg3`d}GUQŵ8| e*ܵɐScMAʑ! !f bRJGLz4$n q5ű$'UB=rڬ̛;&a|NZ-#M R(+mk '"b ߒaAșaàޮCOҝTA>V;`Vr!DHbŮzz-[5f8C 1(sKC4B ʄ >TX!>!2,  H*\ȰÇ#JH@]ι;Qŏ CIɓ(St(sWʜI͛8stQܵt JѣE=t(ҧPJJ'LAjʵW<5ٳh:WlcǴpʝKҭ[tWFbn3ǎ.uҊ9 Yǐ#ՈfM6nŖKMtJcŤ&)ShӸsך]ȑKf.lKzӪylҢ^=\v "P'Oͧ({@bD"Py'cP 0~DJ ]"$H:N;mt0(4h(ULSK;(+7DPB'Öj"3-sXf:v6M3pM;HRB@3 >`B#8埀j KhS<BDj '~ 4**Nč<@$7b # ;dЀ#M/k,>pN4}! &*O;Lc 4ʄ KK;S|r_8rL1Ď[Ҍ3e2jpJ"Lj|$ɯ+,'I1SEF3󥀠'|1K18 YcI2phpK#!/o?><#~ H@ڌ+9R:`r)ᐠ7ARǺ2 k.J~a[!=;J$AB∄8 >%I&;ԠׇDЇ?G8@H >8>3@l@" EJQe E0z ^qFZP!FXABP'䡏$b |J_! #D 1 H` B L"L҄R Q˜,i ![OD_ P8)H1?iRA4!.Imv_ 83Y3| 3hz|P<7b$= oŀ " Єge>@ uɌsXHc Xz~PBʞJ&Jk,h_&̠}H@T:Nգ&b`"S~x -s17N·kH6mlU]0On WX.#1;1ΌO,H ͐` CWri!,0f>9Ƈ[ZLV0 >=mk63r%r*I|*[lFZhSZ@kzj3P'gwkC kV֠;`ᢺԠ2al? -BA x;æ1!MwI˙4qmEÍ/طս̙NWD<7'>Cḉ8~)~/#ٸ yi fT##_r\75y5djy96 l=^щ 4Bgwl}Ewӷ{`NhOpNxϻOO;񐏼'O[ϼ7{GOқOWֻgOϽwOO;ЏO[Ͼ{OOOϿ8Xx ؀8Xx؁ "8$X&x(*,؂.0284X6x8:<؃>@B8DXFxHJL؄NPR8TXVxXZ\؅^`b8dXfxhjl؆npr8tXvxxz|؇~8Xx؈8Xx؉8Xx؊8XhZ@`[hmljQ!Wr0X(eы}1hYPZ~(c[_d d a*q؏g ܈ߘwpj"8ȈYn0b@Ehyq_c'j5_`j H;)\mpb t8h0m{0yyqah0jP&`\sr+{PnnEX؎鋿ngWigPm@(lX@)B-9qPqP=|xQYَ9^"9Oiwa) 0 q ! Π Q%% А P ՠրdQ( !5qA,Q5Ġ  p 0 s0 sQ";)  < 頤P=.Ԑ ! t ް9s3Aap"` ߹YQ A ؀.2@砝w:s. 5  YI?q?rj xQ?A pg  |*=Vߩ'Aj|'s.! `s1z z ڠ٠ @ZMߩ Q ̠r`'Ր(~P|.C8FAL*Q:Uz\ 1fjʦnqjt v: *QqQS 1 : 1 "Ƞ :ڞ <`ـZt  Ɗձ-q$)Ӻs*aP! Hj̀ߐࠝ^#Jt &P )`cQ ; r09 `  '@0 P<8:`p'31 B{R 0#Z'Z̰ aJ*Y3› Nz  y:  X А}r :S}I%z2) bqz j7 ;0 >pO {F `G|˸A Kz {+ ` > 05U"QD<p +c0/a˴|2i* &~ @@z+Vg Żf& M{1Pba m  ,02h Dl > q§., 6,9 ;> E|3@FoP s퐭 /;k) H m5 ǰP$R s "  ހ 0 ;-b  Ck o!Fnj-'ɒ 2 0 /Q'%Q?! ;L` J 9@V0l)Q 倻a <r r:9 _K˿>p=)0`  "  `Յ 0` Bm '`P ԓŹQ +Һ:#0| 2;  Mi6  [P P m!pF} ֠"'R @mBE0@/7Փ :j[ /Մ  `R" Fzy}m р . 2#' +ٯ@Ӣ}2 *@ &ϷspmH~!Y )%0Jyp>-P"C } s a>ɳ 5 M!Y! r= +@/Nd:pmbtdyd&+F7P&`{ ) 2c)F} G؞YCf2 / ` `#JA p ++ 5: xװ1:] P- 0_7 p30 `0ϖ~ P p DpBoƫBY &% E UR .0U--:GO;a%/gM6ecPP= ϐ s ds= hn9}gu9}Pse|~Ȋ$:s6 DBsV( oI(`w CI%-A)B_y X_Ϛ4gB\3qz;@@0BdHr[/ 3/IPH  *?p#L|ˀyF' YbIPX+Neb%WPhxs'j. Y ͝qjg{`|2t Bf)A3&şQ 1 x$>w,<{H$HLez&)!bn%fnof2,NlWtD5qi@-lSI7# ZCnvzB]vz(Pr>'E/hJTT :. `0` o%DkD#[c&(ER=1>PiIDk ʚn-)sJAOs@hInD#?X@ cSzH ȧr4)c碚m/ꒆUWaVl]$BװƵpĹfY1@J_Uf2!$sapXpgrU`rG-vOdj;'5_?Ip Ќ>8ظ_OwafYtefe5-6w|'g}!Q,*f"5i,1idIOw\wq:JalaF3Ą2B)nc$w#hG7Ph!aЙ`p&P@ܱ@@4H ꒍VqH53=9F;|!wl2 ;,9q0 ]5bs4CyBqEpFق!^xFRgR8J&5Y!]O|0u}/|! H0 ɯ8f? 3nI7W&($J`bv+>BW[)ʂXhY7x-#HX7ɴlNSImͦO0[ղ4r;1-7z .}HXs07ۤ^K6P 3K v4ޱ++bq ^d^(܇y;>#P0oFs07Qvp7Yc291t]8 va%h4bq*-F6Ɏ_آ=и!g$E#P,`/tŪ{ 4!~ЀF.amYB%q40nA wɀF2# gHi6p`g; wTP:fXǹ vxɀEM5gq ZhG 1: ǹdlэv"HǸHP9i O|Q FՁ_0Rdıw;n%~(0|Qvܢ5dqi! i4!Yc#.]rKC,_ýkݘop$[4q qcøv:Qbxye}nꓺѾ3SoX9u"Z`h-IhlC e0?ۓk3*999}Uq`;+7ccpph?cQn[sp`P:cApo(f:;~aH X!;t0;\87Z`8uqȺeao`S|㒴w(o#yb8c<3Y7ZA/<dof(>QpcvP@z;7`s0p@q+m+j[(?rtg c@̺AYth?uGj ?s3p,kƟ(*f.X[FrFDhiAhrlGw|GxGy$dK `YȅyG~G/> <},*_yFidn qDH#_sHHGH,ɎI H\ɀ!0, HKȰÇ#JHŋ3jȱǏ CIɓ-Dɲ˗0cʜI͛8sɳϟ@ Jgȡˆ͛jJQ8|̠ƭ\v`A˚5l՜{ XѷpʝK݊nөS^ Mj)6 ;hղu{˘3kl\;qQ Q3gn+Ve犝sW,mӮqͻc. '8TKN eN+wسk~i=B."0n S=vرÖϳcvG^yc3@0AL9L_}Uhfh' 3 D3<@N87ρ2H tQmi<'0 3CH"I,Y# bD1 d 7N\v%\0#"2:L;2:#M;"M4ȃ<2 H! (%<0%=$֎Ηf$"˘ez49 ;|#,|Nyެ7H' @*B S x /6&/c` (a a cB Hb& s" 'xL1@Aqc\wn9!,֞$C&Ӄ@-3ˈ:՜'.10~+R'87ɮHyh΀3Βؘ.M$d6y®R« K $=P6g'xӸЈ`fitז 7|97|9 G4G>-njw,`[޷+=~j'1>5 G(xȢ7lE[up91_,F4`L@~!o \CSHH*fO(G5o#p/fr|C8" vi!@Q1j<oDZ<Iȁ}C B05D#tX2UbjM*'35BM0s~A B85 EĂL|7qF$1IT$6:ɨRh*dr@L:{p02q"1Xm F7 e(G6X`-jd**:h06 HG:u7,ޙZո'05ß @ zЄ.tϸEEaQ13]t!TJRZ%Ag/ծz`*VJVh5hMZ׊9+[J׺xAj׾z l`֫M,\ {:H,VVV*e-YflgGkWК%jz2-X]K[Vjmw "p[w4M{jUskZWv{@ o[KހWey۬W/o}rIm#N0 |*bpq G7 gXu<ъľ!q9sF+g|ر4qoLa.< ˖H.5& <= )T2NBej2r 2hN6pL:xγ>πMBЈNF;ѐ'MJ[Ҙδ7N{ӠGMRԨNWVհgMZָεw^MbNf;ЎMj[ζn{MrNvMzη~NO;'N[ϸ7{ GN(OW0gN8Ϲw@ЇNHOҗ;PԧN[XϺַ{`NhOpNxϻOO;񐏼'O[ϼ7{s#A @Zz@ˀs{폀{3|C?ӿO{20}C&41~ EA{/0$?؀ ہ@' ۑ K  ȀXx؁ "8$X&x(*,؂.0284X6x8:<؃>@B8DXFxHJL؄NPR8TXVxXZ\؅^`b8dXfxhjl؆npr8tXvxxz|؇~pmlmhfZX~p_@J`ϱ\mp8xfX[+Pm;UNbPy@ @lp P苿L(xW_XZpڸgpF`pyp^mшWP)~@ yXy#% #W 8LxnmD+=@+\ 9 WPWU8ȉ0hC,l0Ukp[@I,,jEJ0[kD`Ied pH`|f@|{ycT^^ Hf0$9]h@)Zɛm8lPǹɗY`ΐ ⰠL  ܐ ِ W lQ *7IK@a p πџBA @ (` @ 4%z` 4aх9Z[ Z1 0K#PB:0CW!/,i  7.\d*\P!kݺu̝; 2qCIɓ(S\ɲ˗0cʜI͛8sɳO LذCsCq:~IիXjʵׯ`!2X-Jrq㾉(>͆˷߿ YeײǏ2ˌ˘3k̹pK&A^\tzM۸sC ' -pO.z䥓УK< g8b x jP@ξ/cv"rxǠb ߁&9 ;\S9d2x:"M5тO;H#<ADR(ȲN1Ɯ:U:DinLo჈G,;<oal`;NEc,J5:bFдsxpFXG_HCdıYTpG-Aco/1g(2v ^IΠ5,n$ Q:1c;.cH"ifѥ/IrL:v~ @JЂMBІ:D'JъZͨF7юz HGJҒ(MJWҖ0LgJӚ8ͩNwӞ@ PJԢHMRԦ:PTJժZXͪVծz` XJֲhMZֶp\J׺xͫ^׾ `KMb:d'KZͬf7z hGKҚMjWֺlgKͭnw pKMr:ЍtKZͮvz xKMz|Kͯ~LN;'L [ΰ7{ GL(NW0gL8αw@L"HN&;PL*[Xβ.{`L2hN6upL:xγdAHj`|[!BVJA" RH:+DCb&@J)XQ BTR ĪSꫠ:YAZ!_,1, 8ݺڵ;wfղ6">fɒ1cǏvD8g͘-sD1j&VM\tY0%q7nYrJJQdѩ8p릊u:i}գWb=]ڵX: lQ jP@<#DZb^{ ],#!"bGٶ[_ < @?@ lV ΈK7ucL:t:˚ϋE  fI\BZy&-pƑ_֪4`Ӻe 7݁uځX`gxMZ$XBrJ;It8w[ (`(NtD9,p#T D`, p$҄ $4/s5wu/M,S8]f͎( :BB̘H*]/5ȳ03bDRL<# &rހ"I ) <7\d! lR맓tc8Fy!E.È"!‘/i)'0\00DOM\RL2 GS 03>3\8$'/J-.ҌG0ɴ#p( 4AJ$\3OȣN % .0S p36,ӎ% PDCS+^̸ǐ#KLrAq]/[6qB;-N[^k`"%lɓ# 5`ILȓ+_μs5c Z4iӧT][‹/ܻ|˟ORcڮn"3Nh:I#J 3,3ބ̈N1˴~"6d~$h(-,L1(#:*-B&L;8߄3M0촣ӏ,ViXf_} ("H H" 8Վ;u0)' )=6裐FZb5ꀙ 0 `§'#͔oƙL-t~J D"|~)ij꧁ KU5-/ "d:B'RB & I}Í7娆Ohs MLꪭ(5 |bOB 3j1;}JF^j*85 Ekܚg:PbB8B6Ä&K ggIC0u& Ca;;ႈF$_1g&Jx̣1R>! v!)x쐲"7YHbnF7lE3xۈG0e=LGrܧT VP""'YgfG;5I)of:3G+[B$6~obhG1t!9C0j-')HrkB~hӤ8C5F;z klfG01,04/OcG}(M*šy:|i̢zK3Qj$!$@TdX!oDcHҪZYbiKEkT7pQc=ihx lDc4gB`*H kBӠ*VKg#|PJk‘ NGkQ  n/nljS F]r%4V㲍4! YHce3c8㳟mJ;ܺy πMBЈNF;ѐ'MJ[Ҙδ7N{ӠGMRԨNWVհgMZָεw^MbNf;ЎMj[ζn{MrNvMzη~NO;'N[ϸ7{ GN(OW0gN8Ϲw@ЇNHOҗ;PԧN[XϺַ{`NhOpNxϻOO;񐏼'O[ϼ7{GOқOWֻgOϽw,? H l#>`At AB~@`B)_V@B Vp߾`E)~)"8}YT_O_۟ExH ŀ (H h텁Ł8!旂'؂.0284X6x8:<؃>@B8DXFxHJL؄NPR8TXVxXZ\؅^`b8dXfxhjl؆npr8tXvxxz|؇~8Xx؈8Xx؉8Xjy^F`_w~peg|u_\nh`Ȋ!CepaPj`\`8Ȍ^qh@90,A@Z~pZЊWpyf_Ȏ^hk{`0WZ!0y \x(yW,0:-[p%lm].y0iID0]WPpWFP PGJΘnylPy^ `T]Y{ `GYgip)sY~@yI\yU)yGI ²kpI)lr`^ShW UpXrq`\  Ƀb)Z)ePil 0AA9 -zglY0/ ȉvc+ \i@?y``s>ڈb 稍chx(ϙ_HcqPxjТ \[\Ф.IYʨʸ]Џ]٥^`fhSUjj\h9ZP^jikڦZ"**J` `(!2@ P$@A[Z{1 Z ׀0" 3A@U 01 dRA  30{(A JKa00t*Z:ʪ'0@@U&M@"$-pX"P A! ސ MD a!^*ݚڪʬR ;+Q  a?pu @"z(EZj0@  31 Ы` ʐ?ڪ T,{ @\թ +C 1 ѯ15'ӷ !AAqa\^`+AIg "0<0<(A "AЪ qjW ذPᴹkFPKKN:дA ( ߠP :` !#  q ѼܕW ހ3k,p [ r0";0. p  Ppd[-! !4  吻  T[;Kb1\rݫY۪Q048"0"G\T\2gGpѶ `2kŠkpb\X{ūA8Pˠ A0p5,!t0m; |C  )>{tlKW@,~vT EApLs  j |g,m,RW1Q ΀ۂĀנ˼({A+b \,P! x(^u| ΰ),(l>sˠ!A{Up @`1ˑqʒBA W >a !0һ0ޜ=w @ k" `W !ڂPӰ$;5 -/=Iq=+y >&ԻA  ǂ b #BJ ,}!*,Y! (Yfgv"Rm4kȝ;7qBCɓ(S\ɲ˗0cʜI͛8sɳϟ@ ]IA Ņ4۸q٤Eu1ƎC:9ׯ`ÊKٳh[0آrKس_ֲ9}ӧ LÈ+vV۷Ӱe˿w\ŠCM鰍UK\v.˖5NSIm:q NWgk]0ٗō3k>_ֻËOx٬s)۶śŮݲb@ Jiה'h`W牓39,$Re2.:"$h$;S -,vcM~1  P;H4SL8|B-+N5̴L2\vg10Ƹh-K;p@>(<#K1G$+PD.XO袌6'  2aeCFPQ;bL<'sN9j뭸 (LjXy!2!c;'*鴲Қv{3Є *xrHh$F2,3X & <|#I !8К 7iB +[F,q\૯~zpo}Wˆ0<=-n D $@3 t;h+XgͲt$ ² b #O9؂z~$JZ8IBV DrH C{(H#~bO3 ؂c€n&E: !۠,LD~D6 `zD:'|,vWY;K1-# O Aa #8~%M/HKF7rƼb#‡JTIBRMZ_7 ZPQ٨F8ZS ` 0;^q ZE.t"H8B RS Y(h7QѹHLb2Ar l3w&J`3J!e-::J`cE468]g44ap9G- A>d#C,GvbJ 3?7Z򒧁!boXopK1QBVp# ($1^ 0IbL2f:Ќ4IjZ̦6nz 8IrL:v~ @JЂMBІ:D'JъZͨF7юz HGJҒ(MJWҖ0LgJӚ8ͩNwӞ@ PJԢHMRԦ:PTJժZXͪVծz` XJֲhMZֶp\J׺xͫ^׾ `KMb:d'KZͬf7z hGKҚMjWֺlgKͭnw pKMr:ЍtKZͮvz xKMz|Kͯ~LN;'L [ΰ7{ GL(NW0>n6b<B0@8jAX&B~@`B)V@B' *ä(! )̩K 0"%̬H Vt3>πZ! |L9ͩ!),aBáK5k9klĉCǭb6|j;\Z특s]5`Iƒ3|0cʜq` 60Ċ.c _f̀3F$JXBsIjLqΑR ql67oNv ,Xʲ. 9|DZU+Wf^%kI'66eݻyymگ :uE7e.\)S8YzƎ:i߾MZ23_} .[;kؤ*G֊Wدg~InwUjP@yݬYɓGXd^$O"$H'x7xᑷ  <K,":A$}((')HB/H#1,USK %`ߴ3 0#K7ބÑ(%/@2*5/bɊL9P08 [(O6N<'P3d/M4sDBD$Rй*xM/״#ɣ%tBlb6g5UyB'H"4&) DR~ 6 ><>%x -`pNVXuꏒNy:¬d;jd8ŀN"I;аzBkyJS t ϋ)9y4<I x4VdUӦ:e{ D0bL3$2 r':-g\4{'<W C'>'!T f3z&HO,s<)J׉ϯFSLyWʸu4(z2ȉ b )>LӍ<%=gy(̴^vBB',z -O쎠bb):2ɂN;i63\j8>$1AI:bx5_81I#8sLx8-˧>^ ^VNIx؄^hn(h14 @$@AM)Z@f8# "\ᜳe FÀ 0A60y΀P u(i:α|0+F-PB ,/f8#7(Fxc"`l1Q <ę6ы3P:R9,"Lı f<ȅh% 0 0&(dLKn4l >1]Zc5ĒbB|# !),y H 2HḆ!/D\8.<r``/{U^4\9( .i 1` ‚v+ s $CN3 451X\r#@ DO,A(N{M(TViXfXӤ@_c8SaA#5TdXMFP$O;|9^RЃ5ؗl[Vj饘flA8d)CdBkYЛ1φ}XBIP SC:RdQ ;HЌ8iq6F+HXt@K>@"sL5+34S :"P >|s3(2s-Y$4 , NcssD-Ǵ# ˙ǒ >LX L 4A Mk8"N^=+>cNTa/A}u7b"ǔӎ8#/ /B 7T8& 3B:CN.:!;LMh6:376x8d19 #M;y32Č5/IM5 `B*f0YLO?IptSf MVѴV2+9;Huӝ'4:թ0@S/)Aծ2%PŨ]1&vK6Â"qB %$lIͫ^WVF U`:ŰpmAkd'KZ6$r]jBpqeP{ X{xBw5߀&U ~Fs'&PD ,Vak|dQ,bp1҆k *ߐ  ~Xt}6:..R" H%0p:fz]t (pznnLJU8kzx8!."Ձ) &UhV(7Xr+t {ÉX3'#]Q7 u#x g q $h؋Y z@ Pp2XA@)Ѝn8 (dPYP Qp@6 p x~R PmJQ6L:A! DR0цI0 rֆe A Q%k PseS 0rّP"aD#K @[jI(## dx цI `0pz w&% 0 {p7 E?Qi?3BqrceidhIP t PtPt9I(ǗfXjCS ,#3Ig!TAQ US?e\ v P9 o _Yvf  L @YP#dVz^; /kh~a{# wS ߀ a :ȅ5X7: YqB", a<C *jjijQfҐ@#' @p SWqD45D&a" & ? p w#0  Y@Lhz?w  #aشad fJ LAڦ TA aYs 1z|z JQ d x!&kJy['pYgB۠*Xpr PfT)L*ryQ q  ɵx0 p0YzKz'PO9`Rk a n4+A9~j fk"2(w† RP ivAchl3$cFN0jrW 0! 1A PI9qpzWVՠ7:6 JY +\;X1 ъvJ6#mZ*&Q!&g-  Qa C(i'uOUұzr7AK ! A (Qpt?y kx &Ƌͺ> ; @Uo")y'PSI6Ga[MVJ" XPp!aԹ=T27!oC ZW G + 94rg2H\QY烁p dſ0!1:CG@!bA=l l )ԝ& 8AW=]KX] !Bq >4&zn86wMR&O=U+đP XAĔj5U|X<\/A*[su!NR?Ʈc ?3sPQ"?` @ q 1QrF6dxYX"dJ7uu׎u7WImI>(H6}L@BeD#39%Y6Q}5@h'jc8a{V;R.p.P01lndlk8?!k fPΈ kPM l)b)@w})MQ'4OV=fZNFQSE M }3003P}VsY`9ϨtVbL~ea1;ƙrKt_2y8k ]&(M u>`JfS?fOAQReUD bAdP=R ? nW p Ѐ c;@;kݔh {] [Y˕V,AK)ٕ7ԏ`ڀXwXڃT >}`@{qە*J:J7ܱeGHC]8Kݏ$T P!H` POQhS4SSPR4ߨd` Z [hǐ s p ;ģzS !~6[XD&3sHO Qg8]IJmd" QV@5S:x<* ԍR -QXCۯTdjR;!$cC}4RUdH (Qߐ974͐ A"ӄ=3Th e"Fa.갆YU6c_AC=R@LT TXSXM/4B!&Є pܠ3#O~=LpxFĄ`-뼞ҾH1=Îf>9N /)ԃt`-LA$u)>+ -ߴ 23u*m:T Ԁ2#,dAC{؟ڿ?_?_$XA .dC%NXE5nG!E$YI)UdK1eΤYM9uOA%ZQI.eSQNZUYnWaŎ%[Yiծe[qΥ[]y_&\aĉ/fcȑ%O\e̙5ogСE&]iԩUfkرeϦ]mܹuo'^qɕ/gsѥO^uٵowŏ'_yկg{ϧ_}p@ 4@TpAtA#pB +B 3pC;CCqDK4DSTqE[tEcqFkFsqG{G rH"4H$TrI&tI(rJ*J,rK.K0sL24L4TsM6tM8sN:NO@tPB 5PDUtQFuQH#tRJ+RL3tSN;SPCuTRK5TTSUuUV[uUXcuVZkV\suW^{W`vXb5XdUvYfuYhvZjZlv[n[pw\r5\tUw]vu]xw^z^|w_~_x` 6`Vxava#xb+b3xc;cCydK6dSVye[vecyfkfsyg{gzh6hVzivizjjzkk{l6lV{ml"~ (n&>ۿTp~@S + (Y:/IGu|J)t^=@gv=v=?/xcsVdA΋xg~z#=o{?'.\(Yɸ\o&IOL(IyS,TXXʰ_,RK[n.yy_*TY̨OQ2Lg.L4yk^(P͠|?8{RNs:yw-FkS_@7=y}T/+RѼY#8 DiQ2c/I plx'fҗr hhC1 - L} Ӌ ZCxӟ4>`' $4 7PT7AD b؁ l0\A Sm[|AbBaZ @[z pDذ\|4^@ Dj@D݄@5_p-f3a %TjՈ̔ x䰇2| a-i?C8|!Yl W*6AT kʀ6=  mMi/ ̓dgza"^p01 r8vaX6Ƀt[8%H4_|ළlMπ僼 B)xW2Aa|T\i|{$3x@`XU5V/N&H{@d ä[|t!WXIF<` nZ|!&R8h He-]4 y1*jzG bd56! |PcBMRFY3kY`pU7`pVw}o|[ֱp mhCh| ε Acb "O$Po]@(>{ ~E⅐gcn7/9d !3M . ]| G e:n(xnk#ioWMbu@ꘝqug^7d:s {܀My$#4ǐv(H#@ED,XS4X?k+|hp<[J 뫍8|̓ 5Bjw4 :h=H<9X:8J-+>X+ C)r!,KB%\B&lB'|B(B)#/6P3p9,.C7/X+80*.l1;rC xs; 4,تd9CR‡ÃB|H8t+2J84="<<C-2`?R=?J+.%,Bh26 V,BMCsh<,5(4 ,.S6F$ E ۨd#\Պ801{]?92 ?n<6@ZKS»r$Yd+,SHc{NjӄX.^LK=IW[>FbSQ&3E.Y3A)k˵=ЬU{..b Xt*g8tԴ- 7d/s3ĩĚ)A,\B6+/CW[`YM*Yk3Jc~-02E/P3L䟊cTbcXSJBjR7jcNy3cMb2u %)_F,Sxb4[$d+3@&dJ)3f<T.DKcT 16ED(,䈨/ヸaYaa6Z JGsN0-%&v1(b5k.媩={YC>c036"e)1@1+Y*ădd3g;kNE";R8ˌ8梾gmqPoخq`s'ΆFqm|h0q|x`r0ΌvX|xqqXmlnfh|p~'e)Wfhpxmn7O.pqpo8m:|_}:'ors|0uhvȆpdnq`vnާ:O2_(('SoVGJpmئ|_pp9fPPpPet_mjokvxfXnFtqrjȧܮ_:t288y|qf۾'/&elnrvOm/yHiw^Oop4mZo'mXbKGro0p0"~^4Ǩo[by[oZ8bHy6{(~(_x|>'1gelbp`lkjx?6sXi`wh`잆ii0; V*7 zW/IXsZu\(]uv`aj pem]rohvk`vjqmφnkw7mru>k8susnzwy}zmmq}t'fbsNoxFxqg`[mxgboOwj@Vn\wy|y`t1L\8_~p &KL8`I#Hf͜9׌ٲs JF2`efZjUgT>ƉslT-4u}Q +ذb}H_ʂl-ܸrҭk.޼z/` !>j!f0ȒW6lր]&䖎#4GfHmgk gtHg,[v} س䨫S48IbNJM52em~tfJ!5k?y#4AIR%K/FrP<֖m̂;I/LW=nkq-i<;%d)8Y55{pu4QSciU 9T#M6L5`S͌5} >C>4s}> . ~LiUVof&m&|瑚j}dc)'}UYFiƙgFiQj H Uu84x톜r1$E^u_wif[[8 _Ke~مw( G~׀OTHT)X^RdNrdێ94V cpZM/%#u#i:^@[9gs3DM9Q&͹#n9^F,- n;n8'%|2)2-21<35.g%֎D(l3A\ E]pI2/T9< 4SSKAe8ŜU.w/ 9L]ZɈUtMEN9s\1;n]}^ ~W3@S.4}M.8SJŸxAEz~$EϭHV1nΠ4#.d#M5PT~:cL3|t>FxyS҈C[C჋:ߨ\F$8st5 yF;#F@"p%&E2 r<Ӝ &h=iа^AØs!4i+.(5_YY;iE BpY>*RiY9P 1Feqr9x7adF՜<|fE/pqGn ve:\P$ ">2|($4>ݦ T#KFC0PdmAbBƂnr^`BX' f "!N- 04QE.Nu *Q.!#zGA;\gDo!]qD䘼QjtRn)G\8 Q@GЖFÜϏÙ~ A"ւ@$1׷ `q=$X[Զ۸`|+Y+Z3u*ȫ޷w '4sq\$Q@$u~ 8^6x&zn[%45\}*݈$VgCZC&`璧I:fPB\h=@c:ᰤ1DEqaƂٖW #JƇ.!&#jzej-鑌׫5n>"n+]F1R$~A\4AiG9QIF@\A<k08ŏbq4it4$‡k `DjBmV#Å*n(wxmF- 0RA󛳭mst,'bLJnʐa Y˦-$Hy:D0&~[q#@4쮗ժs[]ٞ[H=<e-tͅF\} ŵIB!\|8WhȆ,D)^,0S[V}+EAHd ę99IPn(@[; 3H\ 3QFh(]`~}5[[<[EQȹQB. E e^L ܽ{m C1H,{Eɟ۸UyS\ >!HpM !))b8B-l^-8.d6x7t H ǭXYCB4EC$GBE;ED9XmpľE윃48N30MPm@úTL$C-dODzqDW89[vАJ0;#>Ję`YC2530EI88&=/}d Yp3b%amY4I7dCi BF bӰU kTP8|CFW:H,6P8,D9 E8P3r@Cم)ƥ\%mC.pe4xCgJ/2/~05#&݂XDJ42LO[dC/|ch`RAC09C894C2ޙC;#-ģ۬YׅLCI8O337D:܋DDV1p0UFӛEqҤOP W_̔AKv0`=}LdBT5`;TnRVuO_ 3x}ƬV8reS7X[|*&]dem,`;lԠ@у/$Oe"P'OI$bhLG"P VSفz[g"ͣhe@,"%-֭"l nm/ք@$E H" g+>C$\8C/# .w (  DRjuN4ڈc:] (љ&:G&$o B7|)k83 &;(I x4|c" )7H9g}2.]()͌7 #CU֌ ܆54U _zK-I`~_#LN5zSM':Zc⣥;mc߳fzW3#IF .(B3F7$2C2 0c9⬊kH& ,"I )T8Ls2OTӚz"r ;c <!., H*\ȰÇ#J](Ǐ CIɓ(S\ɲ˗0cDhF3sɳϟ@ JT$kH[ʴS|% 7.3|ekw]rʁfsΔALٳg:KݻxhRBJ*>Z5[5d͢U-\|3k̹Ϡ .T]ˌ[wk]eЍ=N :95WC+_μ.}:5`׫[v' \8lƑG_ϾM;{#Gw[u/',묳7V ,'Vhrf9GUU 3cF$ >N-v8/#IA4ÌManj? $ ic _H $pB9I,S;枮 8L6za~OoD-OP&ԝz !%|]"(,@!MC_/Uַuz'UzyiU q+u`k71bY~ X.L>X)t/Df+{^ܱCR f"H2E5ځpF1A.\dC㐆gLŨ,Q_*)ВaF4!rPs-:8ȑkT7V閙Ԏ183ul+8 ̤iN;o;9V:-}6!S90xl"AUʧ5aC62pMb:d'KZͬf7z hGKҚMjWֺlgKͭnw pKMr:ЍtKZͮvz xKMz|Kͯ~LN;'L [ΰ7{ GL(NW0gL8αw@L"HN&;PL*[Xβ.{`L2hN6pL:xγ>πMBЈNF;ѐ'MJ[Ҙδ7N{ӠGMRԨNWVհgMZָεw^MbNf;ЎMj[ζn{MrNvMzη~NO;'N[ϸ7{ ȹz|A [%/ rSAm.! 59'C·:Ёʅt4Eӣ^`UOpAgBC&RG;!TPf P '֡w&@)E*BA*M DϞTOES YP>:,BRxOWֻgOϽwOO;ЏO[Ͼ{OOOϿ8Xx ؀8Xmlmh~WD0%&_`\mp6xm}Z `{9'X1` P^P7h9}7"`Py@ lU@Uh:[(`-Ap"X-ZpPPW}g8Z`PW`W}ȂyqX\0Ux}/08p`Up؉j(x}Xw&8艠׋hZ (1WHȋ6n@X1@ p&%xs_ Wf`nh}["X0IX,0! n 3܇yx h [qb[[/ 1ɉy[]yqtpb0_xp0Oh}jk<SfЕhЕkP~]Eb^Pgilnyַ0 0 `E@SNÁHa}!/,2H *\Ȱa‚9H!gπ#76t.&sl\n]v`A˚5l՜Ō;~ ldɓ)͕S0`ʠ &N<}^6fƉ7o$VVر̘-;W윻bOҜvM+Wk%kZǚX̘,Oٌr^u 2f7%i`Zv"$F .>n֬.Ӎ6-u$I@$u,6pxƠɓ [x"Q6@@)~O0]1sYHS~DJ CK H8N: AO c1,ls%L9yҠ0'&J JRB 0̈8N,JI6װ,B3|9Xji90hE3HHc]*- ;#M-\Q9() #d! Ʌ!6>j/g™MILՋv ,(/DM9Ҏ+MX4@/C/( :TC)c~Sl/D Z1<̳0s< _N؋ 0T0jH:LCK;X3sK23e#z6)AcFt;=̀_"$>\t H/>C~II-# !4, H*\ȰÇ#JH`8lӦL3p 2h̝URZ6nN>͛8sɳϟ@ JѣHqcǏ!͵2fĝeLh3k*KٳhӪ]˶[br8q6;ܷs[=Ko7ro+^̸ǐ#C;W\]h޼`†KMӨS:pck=Wmn N:u {6ۜ-سk.׬%y8wpԠ<كߐYGy;Q@{`B ߄Vhᅒ9$U :.ADR{J "<(0M3#<@Rކ~b1Ŕ@DB'tb`РT;`)dihlB:fNl!SL8}ΓIM4 B {(< =o6裐'>sx.'HM4 B ڠ 2骬YdS5LsM8޹Y2@˔%tB3DAxF+mNK暩IJb<2 "{,eδфke~$ $' 7G,G g̓Vfc/ /?F4 3 4(;^l&!1vrPbCr:X3&70?ǸY. h&k-sbc EmP5vAbDH:)3X"hx^Ԣ(2`Lx6ptG~:403`*ъf"F2kLFQﻣ$')U"!H0rie'GIR2] F J򕉱d!1IS~R<.w\x 0"KLҐ]$.SIA:Ќ3 yU6q&Qc6ske$EPzS9iKVj 7x t@b8E dYl+np2%e2?P2ӓle<'Jщs~,ırv1&AG?XpG0t30 A >TNw^DG3*kJF:#QC!V*j"XX-ʬ.] oL'M+XʬrjHգF Izn)49W4]Jw| #aU iHǘɫ*d'kV¼QÊٰ5(ZY$ lX}lQ sGش1EA4 \^WUB9JכF?w;ZvWo[++i)HMM(3k\w' 0mo)_\"N0LMkHpV$\Nu6uX 0sȱS@,!HN832&BXXβ.{`Ǭe)l566c>cFe|xγ<>ˌ˃4@uψN2@ s ^@$yf/hHyOr.GM]^@ Ҥ5OMhu9 ،``iQ@=p@؃5Ѧ ˵ζn 1+`@D ,P a~v!&Š![{F`ie7 (@Z+Z FV+" NFZ҂h5@V3m^rɇ&/[yE=,h^9D*HA Y8##]<+]sy @%0 &w Jr9ZTߝxA >.W~6fpmrb b-@`A8fe?뢽yo'O~ _Wt/Gx{OOOϿ8Xx ؀8Xx؁ "8$X&x(*,؂.0284X6x8:<؃>@B8DXFxHJL؄NPR8TXVxXZ\؅^`b8dXfxhjl؆npr8tXvxxz|؇~8Xx؈8Xx؉8Xx؊8Xx؋8XxȘʸ،8Xxؘڸ؍8Xx蘎긎؎8Xx؏9Yy ِ9YE`5 *E?@50(M"I6pB*I.&QPo 0i6pn @!)- D& @T?P O& Z ]fykii $[9 tɕq#wYw?vI~ws9=<[ɘv) ☇ٙ9Yyٚ9Yyٛ9Yyșʹٜ9Yyؙڹٝ9Yy虞깞ٞ9Yyٟ:Zz ڠy^F`_w~eg|u_\0n2**j+zCep#aPj`\3ghyT9n,A@Z0~pZWyhf_N .hk{`oSXn`~gkڦH*wWbjn^m%_lm0ʨ/xo$]nwUppl Z4yPkZW{T2GY`U3wm05Z ʬ~ ZP_P3q0ڦhaz[yzX` P[n'\ PzʦjdzZlЩy:/-p1c )g`_yaG@[0{Z@W[0k㩲k%Jtcj\ƊmN[t]ʲ_@ ijzgꉦk۶m /*s[w| !0A 5,` `+4 @y" 4 ՝!., H*\ȰÇ#JHѠp3jȱF̘%KݹlsϞ5sj1c;wN\ş@ JѣH*]ʴӧPZH#A$i/ff [NJռΞRʝKݻxFb '֑ɆA l9|!ݺ X]c-8r}CMӨS+[x0#T۸q_gЪ N VcBh+g#6bXИY~,ӫ_ϞyVͭ>}zZ׳&lXwY{h&X254e#<rR($|Le*h("r 6܃"$XNDJ &= C"y+&L6TM]:SM6p#4,7朣N6|c3DŽyY"I " <ADN M< 'l:\5xM5NVj饘.f3QNYe5dM6^v .| 8lyJY'y[CD<Ϗ& A +B 3N;p+=p'#Wlxuͷ NOrn l2I馐 ;4o  @G<1H'AO9ӌe4L+Ȓ))HLt )hc< n Dtǣ4? =EAxЂ&ӄne#K/QEXk#R'Ě@*@M,P܂:j7ރP,L; mH|V5Wlօ]@kk,C,Ȏ Ly4.ࠃNS?\O^9)Kg3؟HXۻEހf%LH3&H ےotCxA ~rG̣P1~us ]E9f1 2F| 2DYHL@0tY#ͦ#PḄC1X$reĂXJG5.:Ï jȆ/ cc 3$Y#M(ƍB0HPɜQ fpr&*L:-fp#4Hl PD,5lhF54AB CN0n! "O0a EUW+bub>|wsY;fC0:A hg **mD.#h1oq$+QծhƠ2 rC3.3 # 3c>xC44zt\n8KBYX:d!uCp*1ѢsZ60^ͬf#p3FYkX+y:ƕsF]Wg蕯7%,W)Yd4^٬t@.Ǻ xk}/yޒzKZ+ͯSk7 N)R;X [ΰC {Xq+WK(0M]qglD2sS7;ޱ<] DNrf|+&m*5S,g`#0d.ל4Ϙp>:o,ׇgϷsM ÅNaE;b'H[ҘN[jaPxԨNQMTZAf}_MkZw^MbNf;ЎMj[ζn{MrNvMzη~NO;'N[ϸ7{ GN(OW0gN8Ϲw@ЇNHOҗ;PԧN[XϺַ{`NhOpNxϻOO;񐏼'O[ϼ7{GOқOWֻgOϽwOO;ЏO[Ͼ{OOO?AlP3a 0I AH 8wx1 xxHȁsE5 !(R%?:5,/3X5H8-T26EBL`HJ-0@6`GP S- T2L ]- @TpM@\xג P q \ r)zzX |؇x؈8Xx؉8Xx؊8Xx؋8XxȘʸ،8Xxؘڸ؍8Xx蘎긎؎8Xxmlh`~W( _F \g ȏiZ {9 X1` P^ٌȏY`Py@ lp P:ؓ8y@ W_`I Zp5 YVg nF`pyp^@mMP7IZqsWP|~9yT )ؔX^ i9ٖ:  ,qWɚə9ɏ^0}D+=+pdٜ{$[pa)f`noHY0C ,{X`~@иye`[@g0\0tc_[@:\)y[[g heth _lst@g 0ffnÉm]pjhh jA:EGgM P*Tjhֈ1L#Z=L { R^!0,enᬵݹvР1Vmڬn.Iɓ(S\ɲ˗0cʜI͛8st9Ag %sf\}}qcǏ!wJJիXjݺX2hɚ-]qE=f̘;p9rCn\˷߿Iz+YX̘1܉ֽ,˘3k|agwepȊkV;fqMۀ=MfN.߲LfY=ͼW :n򲣓.@04(E IqFڵ˟xzldݝ@bD"9Ұ}F(6eSM;RJ;39G$ ' 34/V6NFe 0<3KgX3Hr` KB#^7\r&,";"ϑ(ߌO . (`4 >8v矀f$t36cƳ 7h*7Ҽb YJ&P}駠,x,2,0@$/r 'H 9DA\r9jȚN4v":M7t"H'8$N&0K 0@9k+~D' q$L=&*o+ y)<\*BL2x,ͥSL;< ;Ƽ3q)3ЕטI 8;5]8 H"HHH͂ 1 ߀:s,m0݅0ĵIEY wz}X9s{K](!"J s:l3-2j)_nz]2\v<ܰc-/w{׈#N8143 As 0͏D˜3hV/< E> >?Z 0-`o [1?1 GH(L W0 gH8̡w@ H"HL&:PH*ZX̢.z` H2hL6pH:x̣> IBL"F:򑐌$'IJZ̤&7Nz (GIRL*WV򕰌,gIZ̥.w^ 0IbL2f:Ќ4IjZ̦6nz 8IrL:v~ @JЂMBІ:D'JъZͨF7юz HGJҒ(MJWҖ0LgJӚ8ͩNwӞ@ PJԢHMRԦ:PTJժZXͪVծz` XJֲhMPlHRMH |J@2+O |5 OSAG(O!A^dL+|ZTT@Rlv(iY Ӧ"ka |)+v[Yv!.,<U /A&,h5k%K,uڵk;g2S(S Dx— FN,t1k !,˗Ga&D\lپkƌi=9EU,hӦukׯ`OZ8V8tUN_hɘ.ݸr*w4jAkg.aS*VZ-6o~v8gD3 zi5l[ǫ0eδ֮4w箵Θ;^q8HJL@]N:O9tB85;č7٠0PB|Q'8T xBN5`2H2H 0( .$#c@iy (' &Oc(( &d i$T$%$('() k#^'ӎ4,sUgCx h3+0 >)IZ Di,p'|c$4rxd z'0 4 #GϕIZzlOڳ/42\zR,|S5y^MLfy _H $B5= @ 57)¦ܴ y79,V ̵Xj)z> A;@eUW >/l̓Ԁn:%3UmmM;c1SK;xN 3ie|(_':`0C}Ui4w`43`! #0KWȱ W!G@!/, (0eV 3]Š2nݺsitƱc3fCIɓ(S\ɲ˗0cʜI͛N!C StvӧPJJի(us}'V4ϑHn-ַpʝKnU\_辥u֮È+^LSArFёE24hj+ϠCMձA$r;u8G۸q6Xm!7wԠ<ٳУK~uw~ }A2a"ϩ_Ͼ}v d صp격kg]\#,D$^9Prw:{fb\N1B_;#M6rM60C-"A$D,x" =:΅iu "P:p#6D7g ృ 7 B q( =HP07"ȲX%7 B a9 )x&&(I4R % 0(,TW2Lc %t 8@A}8諰"7dS0tf;д,_8q"J;ӌ20Tff,8<0~H ,z昒"H'j,pCn_~ח4tg;H`ڛ >J4:ʳ˒7gU∳@C:H:pN5W @&Ĝ;H߀?c>,' p!ǂO -#$'m.Kf#P8858#N(20x"2K7Ռ'~W k~Ck 7 IBL"F:򑐌$'IJZ̤&7Nz (GIRL*WV򕰌,gIZ̥.w^ 0IbL2f:Ќ4IjZ̦6nz 8IrL:v~ @JЂMBІ:D'JъZͨF7юz HGJҒ(MJWҖ0LgJӚ8ͩNwӞ@ PJԢHMRԦ:PTJժZXͪVծz` XJֲhMZX@;m+>~9mIlS*2\oJ&u!r * v 68B)t *U |e$XR"~BeE)NˊT6NaTlNYʢ !1,*Hk׀)KƮ[7vՂ欢8|3j4hP ݲ6$.`͂UtvQK02F51c-N@cdQ{QjG6Nvft4vdϜ֭\ FA Jbg1U+;PFBĈ@wϖ#wli$Ba O T d!"'z̖S9q]k,I+W@&pNU#W̘8nܲe֎ʒ$(;E年'fRF,+t`^SF7 S >4,F fF5 oЎ2 b &4 F(ڙ }v!q; >հ MЗB' p;%$HbW5L/"~dDV) 8" i@,R`] #  "bݟEE#ϐ >̴3\@c32M,ZlMˠ_F&H50(Y #>/*4#9xfQ5\*n:Ӌ7 .@!"!7TsM"DN5ʂ;,.6K6ҎWF91  6:N1< 4@C.S :߀U 0<#>o:TMc2-sN⠳p<-L@!6,* (dɘSvtGQ83jG[IY`hqKK0kزUXMΗ@9 gѣGY-ˡyCJ5$:YtTH۵%\1Bu.@5(E O]L+4&[܁2"(@&Lʻ7'Iu+D ܕ( Şغ;N:p%5)$!2) a'B%Mjլ]{ $BD IUx:!nˎ'{&>f~M\DSL7Z:bpIZ{x&Py魷s%@XpG% q 3xVeI  0dw[ul6a̍1ΰ3-\ Hr2X3,~Gw}tS" H]"HwfDhx)ɤYb#HQVX;E<08Lؚ'ZW4s$t~'~ޢLŜC/lӬPF&`Lo: <ߜs8ĺ 4}9lflf>hKgDy+>c5Hk1 M,RpT;@;C 0L;θL3`4 ;Q/22/RKb/,S--a00S:1#NTS;N1˴L9 { 4O| ,(!1,xIH0dɀ)ƌ#F-5kӦaf횸èwMI.vw9nܼM5kZj'sɳp@:t=9)Ln|Jj4k㾍̙s63>҉ʶ-υnbڳgaVMhЩ#h5ҥ*NQt1o8wΠLY& 4ZgEՙBЃ}&pոsͻ I JhFA$\ǖ/cά)yn@E:MmM=ꝧUZz+lֳҮm\W_&m!cNUvYfYj6iLhMZh#]-,0ƸSqB 9VJu> )SJ2Rޑ-i 52ߠ$9-S7єD7efURv/eF3ٴTqy2 UӜM7|Z%#V㧚ȶ<")U8RC̐騤j()$$U<.mAAɜWIOzՔVU3Xj)^ri7hV比f̹ww8|: ZM(g=XYj y ,z >`I%r4e턓 KƜ#mNi-/VsiCc6L9N4|UCw63>#K>,B0l-@ӎBӎ/``K9#N1|x-PB@wRg9@Urw T35A&]5|#4q #4&H ZaCXG P(EҘ;1 ID > wةm97y@32J %*Dш>Jw(=aeFii17O|b [(VP H! |CH1[ 0`1 wE vƳi52rfx;\p$P@$` |F0Ʒx0l5vf$K;aI0 =tebTήhz:_^}. -Pd n0hF٩ჲpG\% @pVpL#$faf(.,`k3p Ac8S cꈠ/ơ wC[0,A PyBa AntQ _6oh;7@q hD_Όo )jaqbkߖ2spᲦ\fYWRu_11Ɓ !^q(;ь^HfG `JcT,Gz7e"77ٸ@eKPN%d?Xc{ ob8@a YS )r-Ԩ O;,³ʨ/ġ PfYS+lHU‡guXkabxElu1|̵"Bv~5PqX`!歙x;~(BK1 9ٸ/Z-CFP3)KÑzmxװYHc$GbP](c!:|agYq)+d rbn N QrU S4DPpUR@UńuUBPL`F%XYP 4 {\GAPP <~L%NLX4rXNZz +6 o@ 9D'-Ki 4kY7{;P: fAEF@@x@\*@p@ ustZu\a*`q KPq:O dj Z0ſZb,w 0A7U WgR 3am/ɟ l @`l{Nࡺ0 0+ DžP5Dfl 0TP@f`[O0RKCԛzm<;){"  @ ` 4CgQ7[j {R7EVLD`?QmT ۼ^Qm+`ň4^k#sFLj]0K!p*[sL` 0q#@Y/ STđ9LJ@00 `*` P Xxfi=Z {PFDd  ^q   ݼ Ig-- M;ߐ.?xxv0, r~lQxŒ&s }PZ J    L5ˢ ][fwy * P֤ oI֫--8q %䱤 X M LuA޳0f.,ϞСN05Pi < 5ѕs5XwAZ:$PVX`%!6MjŸ_q{}VoPo5c7kV~`=+IŖVĉ/fcȑ%O\e̙5o\I$P>s;hJZwm⁲,wm(q,kKĊwnX;pM>/s2k'\mpPD6;X@PI*1LjpIH Y:A 0@, ݳrG:EW'biWfd᭾qg X"(ĢwުȝanF(IxSP'"F &rऺg deM6}Q_e0 ccsAFZLY<ђ˚ΑG-?+(&$OIܯ+yA4&wdԦpp'v 0҈#@iG&A I'y$Lh*ꨫp̩V\Fq >K@ԆqFli$d/@!0_x` 3I: vvqp"1fGbSQXA:ƙbiE_4uyv%vjI:L&3gc)e`q3dH?)gih%eqhΡ9ycnra|Qof1GsQfi ǗNs qsw@l|b>gđKĢl\besnux9[xAk9qGe噪3{yzf |9b'&;> h/cl6q92bhc[;vT6cp,{;^h/4: `@C, }naG|9 +F3D9k# I 'D0uuŋ`!|yq2* 0c3> L$d! yHDR&Y$BQ5Z\#bp;6Au82yHXV EsE.v! U3laFiPF!<$7_ܢA5i&dglaF!9c뛚7l:cp!9ʡ sE%v~>愦Dfkkޱ"Ҙ; `>V>ZV \C13PFld۝,W1 ̙eD;2>g_$75c/!gkI.>%b\CP2'F6q<ᨆ  / kx'l692I6;0G1x]EEY.&C18юlD;qk邥hD"z+F2Z<̏JLds\FWAg{ $d#&0WhH8؜c5Ёpt,#䘫< ?9h0p"le[={7q̓}&>scN@_|tF3:r#>uB1#q({sπY8qF5B6{2C8G %.&=<¯"LGB4>E+9 0 8Ӫ{ȈWd8܌pԵ\*udip17`/f]2r^w ^pC-Bnʼn4H14T7gȆQ׺C:r/b}A3>>6A=^.do{[G) p(&X40u&t}o|[ߑu%1SR0yГ!:i^dh{MzX/{f_e܁Lg:ŀFa XÞ1-bųPb{n[sA2s#?uUɕCN.+qn-]2 iv>&ʠQC4ыnt Iw6iO{&40jU -#`ox#XGk_;&l>mZt<65rO}@S1fb,re7 \țf~|C{a~}!dQo\pj~vEr2Dy (_sr1oBr0d i()i#4 y3P 2)|l@i㞓&%o(+%`mBq hjX'"ĩóslxl )/ܩꈖZǩdt# kH9h rXlhc()<+,-eB/ Cc쯪)3LC bgpC8_C۫Cgt? Dp1BC4Dt:/yXh$ZDq#aOP 8SGSiԃE45 * (#4ۯ g)xYqiu`D{F{F|Mؔl>'z'B یMMMM NNM@ MlN|NNNNNNN OƸNNM\OlO|OA2O͎`NOOO|N,P=PMP-TP P mOPPPmN }P Q=QMQu ]QQQePQQQQPR"-R#O #]R&mR'$'R*R+(-+R.R/Ռ,}/S2-21S5]S6eSlS8S9R9S<M)=S@ TATB-TC=TDMTE]TFmTG}THTITJTKTLTMTNTOTP UQUR-US=UTMUU]UVmUW}UXUYUZU[U\U]U^U_U` VaVb-Vc=VdMVe]VfmVg}VhViVjVkVlVmVnVoVp WqWr-Ws=WtMWu]WvmWw}WxWyWzW{W|W}W~WW XX-X=XMX]XmX}XXXXXXXXX YY-Y=YMY]YmY}YYYYYYYYY ZZ-Z=ZMZ]ZmZ}ZZZZZZZZZ [[-[=[M[][m[}[[[[[[[[[ \\-\=\M\]\m\}\ȍ\ɝ\ʭ\˽\\\\\ ]]-]=]M]]]m]}]؍]ٝ]ڭ]۽]]]]] ^^-^=^M^]^m^}^^^^^^^^^ __-_=_M_]_m_}_________``.`>`N`^`n`~`` ` ` ` ` ```aa.a>aNa^ana~aaaaaaac-`&` (ZİVY%&  )T( 8RY*Hb&V X-TP *hB(6vcXMV(eTNeU^eVneW~eXeYeZe[e\e]e^e_e`fafb.fc>fdNfe^ffnfg~fhfifjfkflfmfnfofpgqgr.gs>gtNgu^gvngw~gxgygzg{g|g}g~gghh.h>hNh^hnh~hhhhˆ~ᩋ͌hM5h /lʒ͓6 Xiji\O38p.h~9jT=+/P ~3 4jfj5pj}6j--@0|pm675X5,@4؃<?n6k-x/΃/@5)0l 9. @@1p=.1oooo傎",x?.ȃ5PY3/m>^08 -؂&ƃ<k-(0#83o"-5jv-Ђ(0oEmym wx#uuoGx-<H/ sn8؁F5 Pj66/oVnje/{7NW.u0^>{.k#~$ލEbXOf{rqA[dy[b[|Fe||EZH@ ~t=BPK )Ey$ؙ"nXtlIZy%Y"B&Z a6lg]Ej;b4 aWiWkut=6e}6iYcԶq=7u}w|m5x7 >8a}xo8;8D v}G~9k9oc}x硋>:饟驫:c>;!`,  Hݧ*\@a #J$̗Ȇ5qp: `}3V K_kre˗51ϟ@(S(УE %4(>O6U өTjŚTԩF~mvQe{UZm^EW\U"Mn޷{ڑa K a@!), ;3h)\ȰC=\E!G9zWI|Thnœ&Sd"L*ySJ5IɘD=SgС3sԣ8ZIRZbmZ*Ӥ[?E+lؚpO e}(߸w!3, qe an[P`8||Ks 3jȱǏ CIɓ(S\ɲ˗0cʜI͛8sɓg;s[xk4b MhqhϧPJJիXjʵדĝ;wl\9۷o}Kݻx˷ߔ+/Yi3k ǐ#KL˘KBb Xq9C֌YFs\װc˞Mɐ~=fnܸvHnZ[֮o+_μЙ'IҼy<+}:jËO3*1HR@ۇ3,nxϿ"B <ɢQ}߃F($I "dTC W$hI{* RB 0 8<>{W=2Ҹ`}"L6M Hݑ%\v%ja|Ȑ}l)$. z Ře|UWP'裐F*)_2p,2Q8dN.{Njꩨ$M37Ҝc;Fwiꮼ+I븳:҄L2д#H:F˫,co`v}θ;nF֧ 뮓i:B1DEQ6/>.drp6{C #Z@ !l"G2,rd#4U6T@-Bm!LtPGRWmT_ g`udmhlp-tmx|߀.n'7G.Wngw砇.褗n騧ꬷ.n/o'7G/Wogw/o觯/o HL:'H Z̠7z GH(L W0 gH8̡w@ H"HL&:PH*ZX̢.z` H2hL6pH:x̣> IBL"F:򑐌$'IJZ̤&7Nz (GIRL*WV򕰌,gIZ̥.w^ 0IbL2f:Ќ4IjZ̦6nz 8IrL:vjGlϵQa#6 PcO BFjPB3m?3b#i~z2JP @AQjl`E)JʊT4XIӘ0CgJ6VO!0,l (/|W eIf3jȱǏ CIɓ(S\ɲ˗0cʜI͛!g9s6IѣH*]ʴӧP.U_WRÊKٳhӪM Uj+ڻx˷߿9Z6`60`u  ˘3kެW0a?"{=Hװc˞Mg|I%$Oʺȓ+_^v݃JQ"řkνǀw %j+v˟O> דTD'x9}& L3 $108 (w^t< ;d 64heshҀ 3OtߍH&bWX6P= YB12\v,`N<Fl@\$ P] hf|I#20cU8sN1pCH 40礔VJ2:r#7t8ti驨J0a0ň3N99뮼V:մs0jj6]UE[9SfmXNۆ+Ju;P.nB EO,l' 7G,Wlgw ,$l(,0,4l8<@-DmH'L7PG-TWmXg\w`-dmhlp-tmx|߀.n'7G.Wngw砇.褗n騧ꬷ.n/o'7G/Wogw/o觯/o HL:'H Z̠7z GH(L W0 gH8̡w@ H"HL&:PH*ZX̢.z` H2hL6pH:x̣> IBL"F:򑐌$'IJZ̤&7Nz (GIRL*WV򕰌,gIZ̥.w^ 0IbL2f:Ќ4IjZ̦6nz 8IrL:v~ @*;T"H P("Q| \G| 0F1 !%6a ^/p gBh- d8a yXH <ajpZX=C*І8 n)+4;Iڐ,l_P*F2J-`#CվZuy44yLl>8Z" q"c @ ځ䁭@0X,d!hBb 7%,J;rm#׾2_ ,>p+@W#Dh]\Ѐ6#Fm3tt 5./=؁ f2|u /#izaSH\>7슶$6O XV$%*+ _p 8hjLXΤ 3j|8MF$jx@t*kh@(C5#UH`ac._6Ԁ2dH[|lAλ4,[#``$5,lϬF*ˆ/a N,AЀ"2&ۆa kC$_jPR%r5>^[3@ E4RH@C>$k̻f5,;#jHHɠ>toU:!k3 >01 d pg< &ȵt^Pd-{ьL Nuylx`-2w#<4j0 ~!ax1_C]qv I\*gJkŬƫ tc~o@#.e0#hF21q8bÑ ndco׺8vb8#Y8vg 3 ~$ !.,!Yp HYCȰÇ#JHŋ3jȱǏ CIɓ(S\0|ZʜI͛8sɳϟ@fN,H*]ʴӧPJ/ijʵׯ`ÊEU\v|m۷pʝKϬˀ-M4c``+^̸͜#W2g Fg>MӨS<&\/`Æ,ۡUͻ=z7o ֳi̵C'-Հkν?e8r̡=~N7;gOb-3q`v<"f|5F9 f '$h-"ɋ|;(xB"@-L+ B 8"D9B ;.أXfvA,B X#$"(h%tiRAs 0 <}`=fߕx6裐@lBBP,!J3 jꩨj&/ʍ79ٌ:gk$+1*HC6, T;Ѐd ">+B(D+ 4"dS-[,[4ϴ -r3\/TF-Lk7VL1L3M7K1@N6,aS8 7s 0M9& 4װ\ӬL3N8<-b.Mg<=M9jCZjqmhDD6AntmSP.`7`fn'7G.Wngw砇.褗n騧ꬷ.n/o'7G/Wogw/o觯/o HL:'H Z̠7z GH(L W0 gH8̡w@ H"HL&:PH*ZX̢.z` H2hL6pH:x̣> IBL"F:򑐌$'IJZ̤&7Nz (GIRL*WV򕰌,gIZ̥.w^ 0IbL2f:Ќ4IjZ̦6nz 8IrL:v~ @JЂMBІ:D'JъZͨF7юz HGJҒ(Mip@EP| 5!dTP!JSA ? H+E*BA*M D) ť*+RT(]UYϚ |DMkXA׺ʢt^׾ `KMb:d'KZͬf7z hGKҚMjWֺlgKͭnw pKMr:ЍtKZͮvz xKMz|Kͯ~7p qGq/ l`a _8х X#2,/86IA x#n< b8"|` Wȱh+48"VLedu"#Ҁ/p! @6\9!_0-3E-h9q2Q+c >>`0fh=А$qCNk {5>93 QF  Z4>p!9Cǰ/a d9 &r "|A >80 q 1HgCG#$t1@2d8H؂,*f FAvA@Az yC}a g5|T[ 6Ƞ}.!x 09 gP0#vհ]C j85 <6qm{a k l.X@N)} ߬o L]i7ww?>ԃw虒kX fVg<hC` Lq4k: 5~˜h@ >W!/,3 _;W1cЀ! 3||}6D|> ieK\G~&/`+]xN>8˙k׮W6.NP`BERsΜ537Q ĪԯT LYp̀M[pEtX坛!fթ۬iײ 6,Bǐ%E.Bxpܹ@Т'WV VD^W#l,Y; dZq| ^\V\G7'JK`\jly.sÛ]@!/,2Ho H!\ȰÇ#JHŋ3jȱǏ CIɓ(S\9P9|XʜI͛8sɳϟ@g2WYУH*]ʴӧP"=wa /`ÊKٳhSxaʝKݻx֮2}az+^̸iZ1c{ ϠC}0ڬY~Y6oą=ٱ͇Iͻ;fj֮a˦6nKNu|[ƌ8nӦulٸq˟/טvF#B闙j5:L2h D~N >Ψ(3;Tc6쳠3@BCl~s/,K*+]L 3XjfN8̎+mKL17/{l+%@ '\G,1M1N櫱w ,$l(,0,4l8<@-DmH'L7PG-TWmXg\w`-dmhlp-tmx|߀.n'7G.Wngw砇.褗n騧ꬷ.n/o'7G/Wogw/o觯/o HL:'H Z̠7z GH(L W0 gH8̡w@ H"HL&:PH*ZX̢.z` H2hL6pH:x̣> IBL"F:򑐌$'IJZ̤&7Nz (GIRL*WV򕰌,gIZ̥.w^D f0MF&A LbJQMA  H$+E*BA*M D)ΉΑ'+R1TB?e | hXІʢ UD'JъZͨF7юz HGJҒ(MJWҖ0LgJӚ8ͩNwӞ@ PJԢHMRԦ:PTJժZXͪVծz` XJֲhMZֶp\J׺xͫ^׾ `KMb:e1D-8.{pf60gvgq"J j 4Dk=6=>1얷{Bc 28`| B ?ahKA Dw=hA Xnw:l/]7!>C/aGwC0iwXqxk^_ c86 pU0~@ai`d_7Gppg 89 ֶn_gzdDfm^86Z6 bi y6^2J6vf0Ձ88i#s8dPnShof1&[e/s `/`V^idЦklow& @zq`,,0\4pp6.vm@n$Hv\Hs _{,\zn`j@wY2@dnv`W0wemX^({ []zpp /eaxzolq ha s-fuxt1)gk c`jGbcciy] n0y%v]cru{X0@XXLWQy c  %V)2vxٓ)&#i&iaV^X.m[ ]y\1 gr/ P% ܀#܀ ]  q u IՀ,AB` `P!1,A9x HƑvᵃ#JHŋ3jȱǏ CIɓ(S\ɲ˗03NKØ8sɳϟ@ JQ[9qGJJիXjݚ5R`MJٳhӪ]˶-nKݻx W!| È+^6ر#KL`̹Ϡ&MEHPS^ͺI g׸s;o8_~nȓ+ _KNrgi]:;N󌡵1|K}]A`ϿY\H SPA> J߃F(N,4 0с 2$h93 4@'S = ;| 0L3̠P9,4H 9(:N5 "$QˁTلW83$%;M#@0 LhM)餔&9t z'!36hV꫰Vf:') =$zb;)=l%,I$k $ B [2&F쒵-=|FPD % =94ʞjl@3л**~"ϱoFw<k-ۧ=xRB S{l8sr>l۲2(& L7-IADϞz" }£N#,Htdq [¶%l ZB܁Lvf)84`x\ !X35(Q7w<#RL3Ր#䔻2״In#;߀:dӎ9cL1 3NPEM6sb%8 9|C|6՘8ƜK/.K@%O4Hc}2 UAL z!~$<l Zp:tGlS6 y#`ra\0 gH8̡w@ H"HL&:PH*ZX̢.z` H2hL6pH:x̣> IBL"F:򑐌$'IJZ̤&7Nz (GIRL*WV򕰌,gIZ̥.w^ 0IbL2f:Ќ4IjZ̦6nz 8IrL:v~ @JЂMBІ:D'JъZͨF7юz HGJҒ(MJWҖ0LgJӚ8ͩNwӞ@ PJԢHMRԦ:PTJժZXͪVծz` XJֲhMZֶp\J׺xͫ^׾ `KMb:d'KZͬf7z hGKҚMjWֺlgKͭnw[,RAAdg`>PԀ0ǵY*~k$ \L+kR"~BbX*XQ"ME*ߍw~rN,`;'L [ΰ7{ GL(NW0gL8αw@L"HN&;PL*[Xβ.{`L2hN6pL:xγ>πMBЈN]jRdT] HK*X#}dtU(BD1. 5Q-/hW|5Pl!ױ>C . mh5І.ZlЂ? i@||;~ȃ砆=l;Z6h;{6A klsaC+y؃ @ \rPƕlC ڠk/`[ XP*= +;yB]W_a Hn)'BAl=q [N/ ^ p* PL3@o` ف;[^ No@ p !g(BV n Agf4 [CsͅmC-@z?=Ā'>Cx _[ׂڿr54 0!Y! c_f`POU`]@k|h0dw~2KqqX`^kJzm`k,l`k}m;jllkq6lWP8 |8vs }@Gd"hXWs{t[[Fy@yO&k7fvk6Y`oZ k1[] o7}mi,Piwk}0Hǂ/`z n(w p(xfA < ꖋgoV KhxȈ]Hm) ilhrD`0|jhzm#]jmVomD 8@+p)gNu}_`A@D }hxt@'u^ږkXP{fGgwg6c@jx77w@6cnn}wчw} jhOrzX%0pl~' qr `Tm,, [  jeb_g\yh0m di k_`T~[Ѓ 0 jghsepgVcjl&r{^xgtF[{GxMvb`$k[PyPj[xx Z f}_avȀʶMHfƝK'pjqͧq&|66nV8gٹk mA` ȟgǞqzI|y29Z-*jp @9y 8S v Bp9jNz 0 h08*0#0 8J ࣢ ء" ͓$8 %!*,M 4nxiCP`:=ALP<Ȧ#|G|[6nrE3n(POF|_ yrLΝ8| !.,y H HaA!D8N8.&V$|~'-REʜ9P͛8sɳϟ@ JѣH*]ʴ)҇f5GP"AiBi#M3X[6`3yN~;(.ݻx˷߿ nzA`h «Z/r!z - 10d w:r= ^ͺװc˞M[g:'x Xr2D;8О<O5سkνw(_oҗ,( 21.ᄣC5S VyVႏrF+VT%f+[dM5tM8T8"ߞKN6GcRn%L3̐՗2M2g 8\s80J9(CNn 4nӯ5ք'3,%Rz$_p:8csMYހHn58 W#%3@~3·13:P%@^`2d3tO3lfh#pk.0Ev;7ehFiLwX 3̑KL=eq5!\).KxM3|9伳7= Q ]I/}MOGoU_ Xr5bmv7nL߆+R6}J?C,Ć 2ΰs ӳC9ŇK'=# KL*VFm{'p[2KXoG91lppvK2)| nЌfc$=iz]Eӕ/nٌc R$V;stO(.AB`>w&$>)c/i9/T"v.tE4:OE-ʗk笔{tJUA*# ez( ØT)=}qd5XuC!7I01ADd@li1zP9YF?ϹH"]B⎇y+".9-(pK9)>n"/9G1s*Ngۼ&>Q-EسP}=A FrVcB9J<~4tp3G<b /]5]8?Vo{JDf9Qy 4MD 5fOF<1l|sm/pDwPC@#31 yCt3n08)5Oi@'B;;kb%z˟dZ n(΅P€lie_vBaXX1.{`!I4^g 9L.5|(k,Sol6Ƈ= 0CH&2ϋp\|l]LlwX{aj51F/֑NHcT8r!?b>H6(;\j`RbGӀAE&>`$,vGi 0l !ŘaȰU;n v mTQ@KZ;^Ko1 18Y8`[ZuZ `"8VR~7 b@ʡJC$2Q6гU8ù92;3iL $1*縗Ƈ0bqވAh;1Ru+F9w>CaG,A%qfvjB%a5BLiZFHo9 )D>s-ҰGx}y d#֨i%sio " HAq RuOWP#M/ТCnu8~}XdD Ӎbj*%ڸPG5.wz!Y 4m8V1p <'oV7Kcp1Fp0/0,?2ŰN;F~@`oE~X80l sQ 87Z0 @G4+EmGC' "MH+Du2! _ws ߰# N @!n"F@ ܀=b$)GL* oL &X$  L fbd *06g5-`)4z7zԦ8F@x2W[Pt'q C|̘ ;+ ;A' 0x !0:C {pPPh3Ͱ#.W $gJpg !Fd@0qVcC.DKrC Ȁ  J1AgF g4hW 1&|P Ѡ-ёͱ9 (0@{ёgpA ,p1 ɠG=F/qy@=`F˸=w@r/uT58Cd1)&, 0\\x81 q7xaYх+@( t⠎;/`Tp l s.(pD u, K  1{  P5 ^‘6! Qf(6 A. 0~+"38˅pJ+ (Pv& 1 ( !{I 2E#q.ڑyJ)pz;|75(AaP њ H?i\X|%[٦!c@Ɛ*wI(c u>*l&|>J0 dY` @@ P Iiana`[i4{- ׆P0 E Pe xdAQ(aВ B驵18̀wl 民 ! Gm +!w-`hZgr5}[j<"vkw,?;.]6i1aP { CSP}+;t( @0L0 !pAq<Ck54Z2[Dҽjt[7Q P?3_P܄ yp^IzEOE>!IL:{u-o ‹t`А,(QQM[` N&b'QP}{겞"5mw1P0ah|VGN @=nv51qM .<˷W~:(bR>!5<*p dk.|\XRFy T)q'W ހ 0(F, p [ 3# UfWLˊK)AvY naB4"FCJHtp;ߐ.YaQE-WX "q >Jkx!c6)qv754}Ξ*fWCCyT cOP/)@L, 6#~ޞW`O&?FX(`Oj -4@ոHDm| sU)ޒ_ > p,.l,8I ,Y2hɘg-`ˊN]6i] >|A@r+>@ f_+b犅5ݸlV˖/s=!.H|E.\RJ+Tfa׎v״jxW f 7oι;׷ҫN}U͙s׮U-u:;3`;''[` ׮4 f8qצEќ4u *[BCN`l*/Iͅ_.on+)>}[kG\EuHˆ#HДp@ 4@TpAtA# +$rA*fç| +eIFOpk|8qBp;"Hn*Haii5l"92fꋜjɆF!f89HF oQ,,16<ӗ-l"JFF10 (9a n@:D0:I}:ь1;siS, ]f*H(x [n%dH 8ƸjV@Z8PG9Uʩ[HJTB}v'MEa$ vHJ z\gEQDzvt! #xb+b3f %vCVs&k‡DQT]Ծ sOyH! 4*#JRXӞF`%k~JyT2L14SddM*㜳ƹg==?낳3*Gnt%mR61-sӦ$@w;qL5N^Cs&Yê\__%Mb5]ꄠE.iǘfjv;_8…r?n*ܘ{]xOUJ&kf:f\'/JvM{|9qi )Fd!>y:aKtf׸T=1l&E8؝S i|#“Έ i,x CFPX x0ьi4(Fāq1sZSt#HZs r a5d?e$$UcG?Oab ĐcXC)ɲ |0c}7tϐG q j<)9CC)(Na tt 4z8??IӐ3e\`a@ɁP$HA FT'A('Є( [p!p56HgWIb2&NeSt"_$&ȉE)/0c|ѨF6#A*P#K g+ ;=:ҫ^ +fq]bX3v8rl< g 8l|5hvTP} 4zL aw̒)SLNYkfsf8ƃ Utx]Bfr|C\d8y'3qTl# GöbV)afՠ9Σ&uM}jTZB =B ǂ򟏴'* x =tt*$1@|J<@! lcUmp[&7#XKC ]G^SюwX qUmlʎ31A@*v\@u-~qg\w (? Aur;4o"l+̳v FP1b h+q']Kgq$WArDr>"6>d,,ιgq\t]{{љX_cpҀwFvR0"u?n/13ob Cz^btk` :#d~6abyP>&}ۀ^9=]@Ѓt=}! [8оic D"B|!v^G%3O{x;O@yHI8y{>@ @ 3Çs0;XK࿨0@9!<?p?|uȷ @XL843o@#a>2 HS =L\EȀh%:\ (hY@%DIDJJer  +B[(^\𼹐tPor56dvPv )+C9c_ؑ8rfp_HDiFjFቂ_(06ŰH@qhi腬 e 6Ӏo_`ia8rXq( $1#ŠFHLB\ [xF KeH_ 1ÐǨضzdkŎ\ņjP9Z]jrhH|J=I3耎n#JJv4 lK|o˪lC3KLh`KKKw y DLKlL|LLLʬL˄JɤLL#L MM=S@? TBB=T5ETEA]TGF}TIUHTKJTMLTONTQPUS}R=UUT]UWuV}UYXU[ZU]U\U_^Ua`Vcb=Ve}d]Vgͻf}ViUhVkոjVm-lVonVq=pWsr=Wuet]Wwv}WyuxW{zW}|Wm~WXE=X]X}XXX}XUX-Y=YE˕mYxuY}ّYXٍYXىY}Xڅ-Z=XMځ]ZW}}ZWyZ}WuZ=W q[V=mM[Vmi}[}Ve[=Va[U] \U-Y=\}U]Um\=UȍQ\T˽M\ͽTI\}TE-]ETMB]] T}>]Sڭ:]܍S6]MS 2^ S=.M^Rm*}^R&^MR"^R _uZ=_M_eZ}_Z__Y `Y>` M`nY~` 6 >Y `` N&Ff&>Vn !&"#F$%f&'(&|)~M*(|bb|8.b_%# BHc5R1 (/D9U_HY c &T>fDfR 0.* R`DEfdYV`MNƇML~\@dTNV Y R\UdYPvWKU&[V?]&/efbLceQe\ dhffEfMmfj~foTpfqof|f[FgUgvkv,u>gzx6|}yghKfكԄ~fh|~ImhK[艎h^T6ʏGih>iB5i>TnNiӗ>iS:iS6 jNS.2=jS^.mjR*jR&jNR"jR-kQN]kQ~k~Qk>QkQlP> MlŞPn}lnPɞl>PlO mO.LoVMno|o&MoѬoLooL pL/p+3>yH׳oqOZ6…l>\&@w *`Q8EQo A^mFt> !t@iǝwy5TiCa7tQD0TǎMGnZ;Q1dB [MaAT]ClxDqPd<@NJDBx.B$q}ay|q(GK/@lġE\v)S]UЅHlEƇ%e.4 `Ԉ ;,kst@S f|R ` @w:@e jP(R |*BIDmDDtStCY Eh%[kAQzBu] %8{ U0P\Ta`(M5U!Fgߵggj?^dFiC3Fk!5#oQj7aȗ`u 4G "#_@rӓѲvp#d3a[Umm FB:HbhZ7Hul #*@ G c L!Vh,9@)G>Z81p!JqhLFA p箰2!Hˢ\AXv $vGLDH:xLfʌ6)΃)cV2-2 6 _LS68yaNvN)iNW3EhBLtO_8ɘEt.3Hq&A%͡P3; 6F|pF) EcJsw;wx.Ql=sNd'|"E(R#:Q6`ZZ^*X*ք@A2P։"m+\*`8q䵮8AjX 9ΑpF5 H8XȆzd o$$8m1[/`HCUm/j+o`kY{c`->|Z["@rZ8-v__DCpnj}[ p7_؂tcۋvF1ZbH1\aьe|aZl\,Qo 3l5,X kF]jTõXk7 f8> h꘭]Qٹfȇdyӎv64qsŮ B±5n~3ͱ!s[nG|gwؙ鳛ĪG1A\ࣰ(0d ҕ2>z HC-QڸErUl6,,kdSBo9w6|6ci3ƂD吴A!*Āƭ ;i$[4-y׳7-._CU0NP@Fj__~{Zڼqֿ-2,wĵurUr*)~5>ZŸ[BW$'k *K"^H{ lW=-oFc!hH;0.q^o;T?G 8cq3B܌fV 2q hG@,m6 }%rhؐB遐??y~>T݆0XogY|ჴߖC4_B(ZPiD9A3Z: >AD0BĞ@CT +5x%D9_8<B00}~u5F1 (FC$k1 zIA DD}< Ķy%@!QCBP4aCԂv N!""ɁymBlB C -QPء@ PCKBHBT C@B8P"Ƣ,"-֢@@"9"00=3>#4ވE# Q6nױ^hT6r#6H#::#;;#<Ɩ#=֣=#D 1cAYJ3z B,^c/1Z4xC998U>|!$Gv$RԂ/6ׅ^8-GB ou/ۻ0N$Eֽq"O^T.YP%ROP&o SǏ CIɓ(S\ɲ˗0cʜI3/`n _ςj JѣH*]ʴӧ1cΗqWhݺ_;`ÊKٳh*Ek]ԍJ׫ڻx˷_Լe 3h .נ#KLˑ.LbƎBLӨS^hsU84ѫsͻ={qи+_μSϾl~νN~}qvë_Ͼ{\p.iފ;^;4cN}凝v FX42\518(8h(%4H!"Hb80L8!zh#H& #BH$5Xf)!RȂ ;յcch9Vjlz:|N4~bi矀65XK4L1xXPT褔V:8LOY*Yj/]O T94JPjȊdkγ TlVkfv+k覫+k,l' 7G,Wlgw ,$l(,0,4l8<@-DmH'L7PG-TWmXg\w`-dmhlp-tmx|߀.n'7G.Wngw砇.褗n騧ꬷ.n/o'7G/Wogw/o觯/o HL:'H Z̠7z GH(L W0 gH8̡w@ H"HL&:PH*ZX̢.z` H2hL6pH:x̣> IBL"F:򑐌$'IJZ̤&7Nz (GIRL*WV򕰌,gIZ̥.w^ 0IbL2f:Ќ4IjZ̦6nz 89jdb9EbNt6C 3 xʓ紧HO fώ|A PЇt ~qF6A 5.!\BRp yABR rXI 6 1@< 8uJ[* t@-L4A5ELdA9iAC-d TBQ@׺t}d bS- 4n`;lh@@,0 [@HIQDCPb!Ht lgKI6`5 7<+$" DHNJ drrئAnpq"R ,B` *5d k@*>J%쁯@b< ( @6x ,%H8 Ne[ \pƀ⣬W 1o5mpApd{/>_~2aΰ$0.t*> ky -r\d.X `(rH_nY H`9|P+dieRY CJ-hp/A<M i6/`GN{Ӡ;MXX>v- `GMZ֡v~$F(>PԘrA - v͛P9%b(UЁh~ HLP^`fx @V Wr!>IE Ѿ1mguѾB@c 8R1V${Dj˲W|mnB:m0o b3tf`e68h/ xԧ>Zt|VArr Y@0p3Dߍ67HkڄrCM)KS |FaTH|ْ@5P| Hp7ͿV$wzrxO 5J`9P/la`Ww{T h@o' 7AA;?'nA9Aa{GH@ya i|v1|_ Thsb_ v57 y]5T@_Εi/oxWAR\ _/Teano"8"]6jt^d@{@naR[Qck*i]YhW5]UxAjQ,U\(Y|_NR|P\hupqaU~'a!yW}\E(5x}/py0PcP`xqs[0ZRR"l%P^ P%rR^nxvfم|fxQS]pg vYcS|@%Ud_qrpj@W,q"NYyd~t-Lx=H1\'5XY(X8ygQŖhQ%f^f&1\JS7X+^@5ymϖpU%_U92Eb2%Q%Ȅĵ[ŵT3Ey'|Y(}Ճ'qe\`xR،>y8XqHX[ Uj8eȎ%5HRUh1vQX YXqLy!Z3p9Q&ie9IP!8|oq'aU~ 5lWq0! !N0d 00 ր Od!N q¹I ِ @yy ߀p̰ I `++ #- p8 p 1 ؐOq *`*4!` א $3O9 p@S@Z 8 ݐ ܰ ۀ "0 i P !`ԙ 1&P SQ 0p 8 p `!߹lw,pR+qj+pJ"`!@P    03ɞuJtZr+Q`N؀Щ* *j 8` @P$ \ ^ b djЦʦos˂zʧ~ JI ʨ :jڪʮ Jp:!yP @P,ᩂ# rƀp ?i  9 ` Ұ р p @'P @ в@ V/.+B+KO*JV+W˴a!`'.`b;d[fKҐ i p b 琶pdk8{ kۚ9"#k% ڪQ*z Ԁ @ / NĚ*ꯌKv[jSF|zڰqI "9t+S !+ yŰ 0 0 ߻ -˺¶@N`   pP `Рyڻ*Z  1)J(ˮ  P pཿ 0 a l+c7}*& "+ ! D\F|iJibN0-Ol0 QP  K [ ij F_{PKqU;{1,L|( L5 0 ް #7 @ p  0 | YO\pjƫp!/' P p\Ǹ 1,ȁ ˝  ` ޫ ؀͌! A|ɱ |`, `̥l <]M8qtkJ[Ώ[' 0 Ġ *|̵"ݯQ\B:ͮ 0' @ @ " 8aB̡*LNmjOҗ7A"ҥbԌJ}d]f |UgՎ7[=^~bMə||M}ւ7swז\e-Ր}=ՄmP}x،Qx}aN٦}ڞ,٪7MԦ_Mڭڸ ٕۨjM}#Ԋmۚ< ȹz鋺-M+=ӽj؏]mͩ |Cܟ=̀lիϽ,l=Tk{Mmރ3 as'qV}ɗ1a N!q^ˑ A!\Ѝ-|!-,q  H .k~&-8|ŋIUQ [;bIɓ(S\ɲ˗0cʜI͛8sɳϟ@MbǮ7uꤙ%L݂ӠXjʵׯ`ÊKlOu}K#0hÚl'Ҭݻx˷߿Q[5kۋ7C L˘3k9%04hΝ[FZi>WڴYʞtոq˖>tUCnu:KNس(iԪYs [l۸e$ËO窳Ͽt5W T0T7diМl7I'`c ('(44)L;ESW4h8Հs`,IHaJ H!Xb3'Hl-:v`٥$Ʌ5 ›$lImJ <"B l~I)'lzB498b6裐Fhf %PB # ;H "K<*ª"g"t)8 J0*+9ч@p@#nLbJ%x"jUB "H&)B E9$3:k8)ˬ6  (" 3"~-|[B 3H DNk(2$["@`%Nze b$Sk %98#8PGTWm{M]. 0)!HcK"CqLB|tôK 5|@уO:Cw2-C~ @JЂMBІ:D'JъZͨF7юz HGJҒ(MJWҖ0LgJӚ8ͩNwӞ@ PJԢHMRԦ:PTJժZXͪVծz` XJֲhMZֶp\J׺xͫ^׾ `KMb:d'KZͬf7z hGKҚMjWֺlgKͭnw pKMr:ЍtKZͮvz xKMz|Kͯ~LN;'L [ΰ7{ GL(NW0gL8αw@L"HN&;PL*[Xβ.{ٱMR_n&18BI6 6>#E% f HTXs@RBғF,XAR:ǔGmjVը&Rj:־lk^MbNkeӒ' !0,2l 8_)˗C#JHŋ3jȱǏ CIɓ(S\yA\,cʜI͛8sɳ'DvJϣH*]ʴӧ2-JիXj5qU6+;OQ-ڵ۷p5l5ifI""Iڡs L፳U ,P ˘3kެ4bfG\ӨS^ǒb_ָsm"Dm{-ȓ+_*蓤^سk?)@ K.^u :+O~n$'־ 6F b("x5h̆A L@Peh(͆ :L.T8X88N8ҨK8$ަHc#4SqIVi㋍Wv傾dɠ9il狖Y)gtix|矀*蠄j衈&袌6裐F*餔Vj饘f馜v駠*ꨤjꩨꪬ꫰*무j뭸뮼+k&6F+Vkfv+k覫+k,l' 7G,Wlgw ,$l(,0,4l8<@-DmH'L7PG-TWmXg\w`-dmhlp-tmx|߀.n'7G.Wngw砇.褗n騧ꬷ.n/o'7G/Wogw/o觯/o HL:'H Z̠7z GH(L W0 gH8̡w@ Hƅc? Xx$.J KpL1PD13 [ 9ÌTΘ6_/dyx#> # ]AР ]y98rP@|aZȤ@+ jP62Z8SRh>°H6| {%M)?ABe'd1RB"HH:R T@>p5aX bn kX֙ 4Cq@+w̃؀[`TA FP@QB+ &@B` , 0+ bHI 8$>@V@@6X \>L+xr dC$fD" %@  HBT`x@"p [ Yh:T| nC(㸅hbԦCh]8s+]=-@ఞLi(AJ[d}ƚV}ζ 1 Zp'XC,I4 p@BpR؀ m$06uk!c -}w=nr1DXA}ߥ2gC[^ C (`[B6 _hA}sc Fò8Ai變*CƱmqp60ubY2HRZxiS&çz 4l_T,6yV7ܸ9Ũ ࣣ^BƪPlӣX/@C@il@EaZjLh0 B\Om (`JN~2uζrmp0h1 9 3uJ+ ;-T/> P\$>to5nv@` 0R(p\؃;i8`-a nx`* , H)f*֐VHybY^5U,XgnK3a  y~ 13F8@38<,g8R'_"`gTӽ.!(xԡ#\{ٷe}KB~<_ '7F҇K_@S\}\h;:! ؐ@ P c `E$(ِ # pp4X 0! ̐ @=  砃4 !#װ`p!,,x֎ִiذYYj Hŋ3jȱǏ CIɓ(S\ɲ˗0cʜIˁL9$JѣH*]ʴӧPmrw*@W(ׯ`ÊKٳh7jִpʝKݻxCZc[LKÈ+>E`ϞA[L˘3k-[cTӨS^:jj99sG̴ָs͛'Y^μq#/~[Cν+N:귎 3ubR3T4%͂"̓|N;VhY!X݂дEHXL(-L3dS9묳Lu䨣Ҭs@)4ڈ;x"PF)e}#2K;س,L8ds 8N:)t3D#O79pX砄 wV6c/ VjY%Vt*'襤jS "P'HzꬴJ %BH _Rk #I %H4ш3VkDC H'{䖚)>J %ɴp+43BB KK+=b "/70 .?D@!˛ ?"2.H9ȃ7ൣ<.cL:,w @7:ؓM;-Ӭ#Sc/MC֗xEL6d^SdDkۊQ-wؾXmp|߀.n'7G.Wngw砇.褗n騧ꬷ.n/o'7G/Wogw/o觯/o HL:'H Z̠7z GH(L W0 gH8̡w@ H"HL&:PH*ZX̢.z` H2hL6pH:x̣> IBL"F:򑐌$'IJZ̤&7Nz (GIRL*WV򕰌,gIZ̥.w^ 0IbL2f:Ќ4IjZ̦6nz 8I&L Qrb EH; ?BEl |*}/R!JdA?DT$4@`E)"P`E$ Y(=)>D:Җ0LgJӚ8ͩNwӞ@ PJԢHMRԦ:PTJժZXͪVծz` XJֲhMZֶp\J׺xͫ^׾ `KMb:d'KZͬf7z hGKҚ}a""mmRˌv푪*bQi3p m8D\~A / hni!L=v2"t-!lЂ? i8D|! _i ^}ah8֐$6A d_#(9z->-T^ ++;:ps44D0ҝ>}Ѕ6VЀ3wA8@+p=fN ]VaWafekA@D`gwevhVg~ _WZPs0_F p^vtUc0b.cnP!@o\Pa'devz.XNn "He_lX1.rh0g+se{VUh0[@ǵ,*p[ #(Y`Ext`[vXhm-,qh0fkTj[u0@mwWugUxj%^b p|jwn|p\\rhm%vյcPaup|7n|Xe._gQuk^G\&cgV|u|`Ũ9v|hafm׎m8k`6]PbRŎu|hgmYIɑ ^>>yi @UަdCW@R#є[͐ (T#p Z P 50 i)  ĀR @{P !7E(!2, l H*\ȰÇ#J۹3jȱǏ CIɓ(S\ɲd0F[Eq.sɳϟ@ JhJɘ4upJիXjU筯f~4j׳hӪ]˶[yN\8kӮ1ۻtܸpLÈ{7^~˘3kެi1'yr`ΨS^ͺu@ f!J%BOB8L^nh(PCA!xM*h N-@EV!e8ir 0K6PJ3N;BXf[9BK9#f6ꠃOSc~Z曇3T 7Oe# >蠩&p*TD$92(Aݶ裐R9DJdv)Ozn驨jvڨ*FR*P :魼+l&{j*쳁2KVZ)bbm䖫߸榫v &oؽo[+ZLep 7G,Wlgw ,$l(,0,4l8<@-DmH'L7PG-TWmXg\w`-dmhlp-tmx|߀.n'7G.Wngw砇.褗n騧ꬷ.n/o'7G/Wogw/o觯/o HL:'H Z̠7z GH(L W0 gH8̡w@ H"HL&:PH*ZX̢.z` H2hL6pH:x̣> IBL"F:򑐌$'IJZ̤&7Nz (GIRL*WV򕰌,gIZ̥.w^ 0IbL2f:Ќ4IjZ̦6nz 8IrL:v,-"Zȃ@< ;@  2P-*AP h(A;x K` % Nn C0O/u@&ġeB- eHH H` 6hA OUrhې0 +%ȶ Up| IZߔ ^u_PŠY6=C` P0(G1x qۆ=h-@` !F.hT[X|X@MgG7h 1OÁуܮw:1A 'Jr:ήEY0P\m<94t drBX|pA >HBo C`60ݭB l;}S m @:y _x~qCB P4A -d! |o*V0a>pd _pde0H3:h<ޑ jeS tHoC1ރ]-!^Cx9 hXw ]7goU@-q"gnWCd 0_na/4 0Pp5 fhc-> PrF.fyw#s>y}*ў" yN5Dcq4\s >Î5x9 :Ì2<,0,4l831"@ۤpN,41y $Xg\wuA-% p$;C5\@H!6X,M1 sL/{/n'7G.7٘gِ 085ܾ3Nxw6 ]/oo/ڗ H}Xz`Z̠'?zir((~W{ g#{ˡ?P Hf:`bH&:C6a&8)n,h#P^!H2'JĞ2 !bH:o_ch>:ha X"d$ D DIv̤&g2{GIrSFZoKQXb 0+sJAre/eKD BsI:Bۋ4az9% GfӜbBVAՌJB̧>"NA;t1w*x#)φc }Z_!xIf3:!N dP1b0Fr$i6C,Ҝ  œ=mz;hJ <c&Z6 jp>囓+]KW@:Ea 9QNM/̗^0{'gtXԷ~gwucO~XpN {`Pz«)h&DVM'ճ@\]@||r{JT>n s'`:c!ƊyQ6P`}P9 xX\J@`b`8zc4/^h@GjDk!hIFl7C0NPa~Ќxa*kȈk}0p]|i4 *9 a|@xc.'( 7,)t-96+I#y<99ؓB? 8HEi:NKɔTO2 'Y\ QוbWYs7b`b0z 7G7ciybqf{3oP1w&!*$ `hYUwFIGQ0D^M9y7z}dC'i'qHF`JdT}HHp^mVFfAQ[0X}1``nerym*g98`}y hwٝDk^fkX Hh禌]fj-Wx~b iXlpq VP0tX77vpAct mYoXP rbfd8pd g/`p ilPr0 uЃ 6i wL֐7xk]kQ jFhh pOF 57IbT`2zt9aF A` pb8grHipaHkAPդTe ^FVlzإ/ ]KMwbq*fVHl7p{Zj*wZpțȆٵJm>ۖy#H1`}Wl8f:oBF*trI.,xYn؊5 8m/ڞ%]q%pٺo?lh!0Pgfqz_7zpߚ:+G'7q;]}9h,yYϺ,kO$`ilf&jpbzffn JZ{&z:Whfs^[ڪYltР:h%P+[ڶ,0 FʫY+_ɫ`^`Sp EP^Q`ED`[۸Y^ #+{v:9Z uKX׻[˒[bjxf˛wu3mXGy+p]YevyT;Ƽ yۼ*ż UK灮wbnfηXq*zgc*vz֖`bgsX] Npd1+IlvszX ֿzqGk(}/P}'qH{{DhCPq4h~~GG5|Ak'_ytGhH)1ϧ_>C_dUқA& I%3@/VJ!" V3pCEVBqD94D5[,1Ec?lQgqGsqH"G IP>#tɤL2D!J,m% K0|,J1TsMh<6sΉN<3O> sO?I@5P EtQF3TQH#EQI+T9J/t2SPO4TRKlTSSU1TWuUZuVZ咵V\s5V]{U+^vX%Xd26YfiYgv* ڟv[n/Ҷ[påIq57oUwtuWvߕ7xWz7|~8Հ6ԂV҄v҆Ј'ϊ/Xj7֌?Y̐G6˒OVɔWvyȖ_yƘgŚoYÜwz6Vںvڸڶ:[6{V۱vߖ[{ۭ7\W|wܪ'\/\7?G7}OW}Ww}_gow}+x7ygះw߽zo>ٷu_=|O'Gs߼}/?q_<V@ 6>pm(X]_A^ !I5r0a qpKшF9#׸5Q pnR0ۚa oC? hf0#`/nC8(EͨF6q,n81zPbGx5'"fD ^B@Y [ 3 m#m8!~ gX>A@ɇ1mp4aqF 3 t0>!XG GA XAB= X96` q򠅅a ! >ə|tn8ְ@h ^BQ,t `R @j ~h|Ȅh|kM#kZ0XAEt[M*{6B~0sz)@׻1z}WЀ$wmʀz$\sܝGC۵uyppWcyKێKi-Ju }5mo{8 ]`y驅{ajt`)Xt H\fqj#/W_'g/!&fSnt{/4xޖ [BZp '5HK63``*]ӂ3(uֻ:F␴ܓvkHG;[{>,բ7 3A33 %Z20A,B8 h84-j*7Xy(@ڂ;ӂڮ?hk"0- T l.,5.P41,x4c+(.p))@Dyz.T@x˃,`BsB/XE  <8{*5=գ/04#2mB8 PS]%(򃣺D,`;6(#sٳ2f\ 4e|&o'D2%D*HE>uFڃAƀO#C$Oԧ-X>y P=%yre:> }9r$ =ݩG22wuP{:Q5XQRt$>,h H.w$ ?5 ԉT Ԇ0TGeԡtHqj |`l@t"|pg8pHo"f!fhXePp(jiN7b5bNlq:V`pgqpo V|!jnp#XfM=k!r8spxpXi@fp*o@pPuu`q8Rvii5jk`vW|Wql"VcXhWXX_|X(#lXؐXo\f8؂sHٕY!Mlhk!=&k(Z< !^,w` H`3A)_,c>`6NZ^hV˗0cʜI͛8sɳϟ@ JѣH*]ʴӧP*L(1!D <F5@lv,]˶۷pʝKݻx<'pW >(g\2eqz#KL˘3kyo߅Zp6. rװc˞M۷]W" z[Z]KУKN띁 $B˙˟O=oоoxa\kg& uUv~g=#z ($$`Št$ĭȢ' #BX@)DK3 2(MBcy)';c\v`*K H )Ȣ~뮼)(r O:5'GVk%zRR2 <m +.y&Hik+7'b<$d䉫 k'kUO%WIb0@|w 8 ,p #,0,48TG m̧8IP@SY,BtPFqRCĈZHh/Q eT9HGQp(PIMz”TA+ei _Ja~kSTPS qHNQz:5:KeJDUVesUo`LW*Ű3c%VʤUk\#VqxMI0K]-%؆5ic'FvͬR,{YiGlg3:-MڟVklZGVM^{@2moDíq;&wjes;wԝu[ۀfW-.v w yuln_k>涽}erc ` x)i`/XD`Rg<` o¶İg=Y%3ƚ8-6-dWܿv4Ƭ5xǙEn2$HV"Ifd)CeX61۲<&_cNs^lf5Zlܫ8μ3)=ρ3&A\24$E3#r4' IS47=Ms)AMjxԨΩSj0հΪcM)ָͬs˯M f˱,VʳMLʵlɷM&ȹӝu~w-nӻپ7}Gn6?x^3~8k-Ǻo53s8C.rN>9)C.g4cӜ69ss>x9,FW3ғ>3}N.$S@:m^'1î᱓f?l  5 `vlw@l v/m]w,@7ȭrV]<Ё@yuO2d^px=Xs;긎ӎ937x\5؏:39 S0 I/-YrI-u ;8$&yA*I,ْG029MX6 8SYBɅDY_xH)JeؔNPk8TVyZ\ٕ^`b9dgphjyeJmlmti~WD0 _FP \kyhЖq9uX|[+Pٗ;U oh+pU } y P\ٚ)Iig9W_IpjHhZ`PW`W9yq^i9TZWP9~P\韒Tt  k A H eW9%*k4yУ=F@=@+y]p WPq=^0F0yC0 !]0\Z*IePWڣ\@mbhy@ fq h0k[pm\ _\ʥm@ t^ڣn^_`n@g`j`^j`ol0gk jF*ƊʬnYo*ךJG OP<簯0 p P 0 p 0 S *KGwѱ{Ms+ #{MY𒲹 ܀ 2ಹ8`<;!2+ 5{8 1 ` 3ِ F!/,1z,/f!d,ZÊ}6W\ƍ{p̀c!(Qӈo4|ʦn\8r\O|ׂfxٹu;Sb9ٯi:yŜ%E&O>UesfɕGכj,Ybɓܷ?)V,7\֤qbEN>{ Ԡ@ SFH*q%"`Ŋ6NZ.BIɓ(S\ɲ˗0cʜI͛8sɳϟ@ JQY./ s;' Ehݺׯ`ÊKٳhӪ]˶,3fnMLVqN[[Ð9JÈ+^̸ǐ#|[r2fwoڝ#UӨS^ͺճرV˾ƭX 4`LZȓ+_μŒfME[-devNӫo=-j )oɫ'h-T ;",:H( g ($2>| 0N3 B t=d%3%@)J&Ӊ=|N;͸#L-" & = Cv`ٜ$ $K+00%l)tif.-# Tx&袌6 =(2R 8H ) /"*^~.ht3Ũ% T )牀ωHc . $$ L@E(<᭼F+6&I/b7M;l7V[+g8͒w:,l'0g#G,c K8* ,2 (YM3(֒K^Bxx 34e5tSDmtP. ܎Mᬳ<B\DeS 6Tlp-tmk;8L׀.8>_[&6f6ތ7ӭ7~n+n2d2/褗n:}ꬻye{:inˍz;ʡM{l/|7G/ϫ0?mC ߶Է/篿O@x3g=wU燽bA^ ?Dӗ/D$bB  1Gw9mPt1T[A?C8b$Hυ3ڜ pA .zH? q &<#!8kX7:1N/ C6Q\c87وG9 7 d4iFF6tdXFjP o>q 6RYg>-_Iim?CP=:{ eBaϡɌcf`4}\hHһ@[$ g,HM*QdCqk(N?*񴪌)ŢU` kOdZhh@HZ pi}kZϊֹxͫ^WukGЁ5!k;A:d'KZͬf#"uB6KҚ,>|ֺ%MlgKB6$:|n_v !Xw |+[,g{\@`#fhH!y1$y&.*ؒ/Y24i<8췓=9@~BIJFy KQȥNR7a 68bW Pd_+:Yl7Mj9mYnX]f}FXdPW~yeEvSɕ5Klh2pDC;GsYsFs)g`hTm bkX㗃f\F@b 0pnٕsm9i! asDpCWtZ]ԹcXfg!aViH)`-pb%:m8x@ל׏ z_F}Wz}[ɏV*ZM95+%.0*8:-Zu9;ʣ?ZFzHJLڤNPR:TZVzXZ\ڥ^`b:dZfzhjlڦnpr:tZvzxz|ڧ~:Zzڨ:Zzک:Zzڪ:Zzګ:ZzȚʺڬ:Zzؚںڭ:Zz蚮꺮ڮ:ZzگCE?05GI[2 X Tа#aEP k P Y?! [ P E@P )+ <۳>{8;D :;D F[H?۴: L+oرVX[۳]Lkpa{<{꘶j[\۶pr;t[v{xz|۷~;[{۸;[{۹;[{ۺ;[{ۻ;[{țʻۼ;[{؛ڻ۽;[{蛾껾۾;[{ۿ<\| Cb hy^Z`Flqpy0g~P[pk`Pnn^8sȽ aۙܘ= ӽ ` M ʝ P#!1,1X H@uڵ]'Πŋ3jȱǏDžc!ȓ(S\RH|icI͛eIU&Ο@ 7LH*x(̅GJZH=j rBPQ>za G-Wx^d붮݋sG|S,0Kz^ B)ٺM1٣ -˘M4o%jհc˞M۸s6ǻm|Nzﵺ+_μ9m_} GuҲK#mosa 8ۻ~ɟOϿ5h/ F(!}ᣛfU2$_l(,"G 'X|3R# 4rb+W~m|HP|GbD ɢO١J H 7I"@!4lf|o.@ D X %!}4@ +G *!B^yߋm7H2Bi P\*k xAi] )l1:Re+` 8`yl[0 +* F G 1:/\+ !q}^7 -P)-lk@UGs@ t{`J1PiIP!AC >PPPQ[$@AH0 9 F[DH 5A@k#2id]A|0FDX=  h@fA!>6 # +8 vD ^ Rq@@x8n}5 /?b ( *B󾀏d0>k I@t8!@!F6!cFCxC0G5ԑ v: ȧ0b"ȋx#wr >X>$3d22H\RsE>4hF0sDjė`F;r&0a l0;Ŕ<$&6 g `Pf6 b15xjdF$>~ (@)ЂH?τt 5C'JшV5hC-ЀNEOg@ը@1:ѕ*4 iA+RʔhKe:S4i4A g*MRR"40GaԦ4=;1kuE=TJVz;ݩN_Jֵ^u(WEjTg\֛bu)u*D{i4~!Ey}a ׳T-VVOՋ((T?P hlيӾֶM,EPwp䴩uNwD D$;!ˍD8ZWWq |p; DBrrH׽n=KJ}+Y:cp5ƕDs?#7'PCob} `OE?#Quǃk5Ko[kawp8:f|8ļpw!e0b8ŮMk4.0BG5,&O嶘Yr)[w->S{zh^#wfY5:-a)m_>y~wI}Tԣ`/ꂤP,!i;{g$n h&0T?IL{j[;0Ƭ;odTF2 ΀p<(p3/77x5ppw3}p.9趷CMgC'7L5qW0`Y@ЇNkDFOҗc' !+,10 (0A\HH` UYxE .<cȎ$ Xdȃvl@34I0˙>O tN0a 0$ K@< OA, (T,MzpiSO.$ rV.yWY˶-S 5-\x4! +6G_66qܓDl @TrF5a.Y "mZj휽ν;wq5cF=j͠mξ=m♅Μ˗?@P٤@`Mс 6hCFF B_Dnm\FуBB*8a"R!>jL|Lߏ@ǟ^ЀAbF$8N&(P3ux=dF>fd:bOlVyҐZuM7݄}I`!yY`͘H3ݙg3{haVIfi&e"I/ ~(6#)G\%O fk.Ȳib j,dn*P$s@cG&+2޴rFmGn*YS+o M\&(~`k0r+$ξ&ޘ`}RܯF)!mCn"XCGaz"mËG<YF3p'(>!η^xb!=4qASޛz4$A!-a>gs)^YА&餬b"=j!ƍ9KfVqRkνËO)lPjݰaVu6v{\pčcr)ǜsE'NPfeH"ayVhfV9N1(Qm\I( x9p# H F6裐F*iW!v$-q̴V5SN %`B ; B s525Ig L3ʹӝeeN6ޅ>b2pf}K5/r'( Ij+g{t>, 3$0*x&# #c #B>30; œ#tB;'p |2%H /w 8/DmHw;ppœzRB2,t!;9lB+l )-><35=:I߀Y ɛ'ʋ18 Z1ƒ3-> 3 {$t#:¯\/ >cbˈ3́P5 zz//P<'Hs;qBl ,y){rywv袣[:= 3SO{68Nh?0Gd'\o2r4(3#hxs,!  la? #È=0r;:2i,IrL:vϨ3ͨF7x HGPD(Micّr8iHӞTB[7T3hMӦ:TJժJ5M̜8 X` XZUh YzQH\*[J׺N5xͫ^bױFWьd&0aF_ػ,Tտv=GKU md=KҚ֪Mjzֳֺloږͭny pMrwvЍK]JMZu[z(wX/yY[R/{KV/} \/,U0;x4 ^L %ޯ7`8Gx$N-3x0@Lb*qwX;\a YDN|*er} *WS~^,g\ye%s͌6'Wk<\8tγn|gϪ3 BUm1@ h6njSECڹδN}ikt RvMq25Utg=Uε,m}ou{ bPö\Z:flhv^l{piMn[٫.vn*jMoh;7}nߒ w ?jl6¹p/^j8!NKx.q{|CG$OxLJabaNȼ59o[|{w˥Kq#sZ3e46>hOqE 7.ƫ fDZ7rIPܷqU\˶۷pʝKݻx˷߿ L K"F];BA }0 `mA#,H^;w@V@n73!0@Aj~l 7VS 7+!c;5-nVP@RA"0l(e Z@0'C0@1@"  B" PFvbCiH<$`*f!lp;$a- CKwb}cF,x*@X @bxG +XH ? BFA ZdvBu P$BA$0;j:g pQ tvEQ& 7 X ݖw^Pr0\aB@cD,EdBIc)-a _@ D2na/0@ ! @CߑJCeb >XtP ~AjRt1D ܮuִ2YᥤB^Z_uMtFd ! AY|Y٪˨l,yXЯA@9-F;s?TSsOP@6 q@C#iߞdnbg7tIpkϸ*QczGM0;x<1xC"FW3/d&ϹwNJcGGO+~Gy+>zOOϿ8Xx ؀8Xx؁ "8$X&x(*,؂.0284X6x8:<؃>@B8DXFxHJL؄NPR8TXVxXZ\؅^`b8dXfxhjl؆npr8tXvxxz|؇~8Xx؈8Xx؉8Xx؊8Xx؋8XxȘʸ،8Xxؘڸ؍8Xx蘎긎؎8Xx؏9Yy ِ9Yyّ "9$Y&y(*,ْ.0294Y6y8:<ٓ>@B9DYFyHJLٔNPR9TYVyXZ\ٕ^`b9dYfyhjlٖnpr9tYvyxz|ٗ~9Yy٘9Yyٙ9Yyٚ9Yyٛ9Yyșʹٜ9Yyؙڹٝ9Yy虞깞ٞ9Yy֨83z}ɟy<8{AZ4Y| `b_`\mgСJwZWp^_fpڢ u!/0&*ʢ.ڢhkr"{`Ey~9lZppNq0D*q@j{IMVNTza@APy xz|ڧ{k*ɣ> i XI fDPDW RjEjWѨtBaZ0jp:rj4[Ы jBmq`m`E+pU@pmࡖ* 6`L.!j^{j Fp%Z9@yn{x` ۰ (*c`  ;`-P]`EyQ Fm dfWJFuҚ@W,+in9ڴNPzRg fЫ_tjP]MEM,;HGMy0P0&c@Kll"+P]uSJBq᧖ۧnpzڛ_Zf/GWP[M\e0o/;3 W_0~Z 'dj+SʪZ;[ ^W˛`|Y%X0P]~кWJj!<Х.q[]["ʪ=t \kE/ Xp p_;<^ɺkS:Ѻh;۲vl`k{ًjP @[ jp!]Fmp{rKVDapjNE9j:>xZȊ۪y`~`κ+,ZJq||Ļ(P+.;{V@^`bDLDP#k_HXPyCyP{ǰ)=*[@g2p%g5ՋzHKUK_0qT`[ 0Ԛ nfFW\ı˿Ihߜ^*r^xN_ϼ_v0ό_ g`h:Ђt{pnm`X@L.΂Ln0)R,ݡ,ja»kѣW붙\ҵ<Кz3nhC=Dɵ+IQ]”9YVֳOpʝKݻx dw߿ L0spsaV#˘3W6ϠCl.39ծM۸s-t ^8ō?6>WK>ԪlgM+5˟OϿ( [Uނ 6K7Vhfx`GA($(,袊̢ h8x/+ +b lըPF)%P{5OǀPۧd=/Ϛ'5]Wqupurw}gh<ހॾ"5L's8.PGi~Bqt}))|殺 ^}\)D[J %/<{60ر~:z}5_H0?KO?>^ƻs4#Nx9Օv+'eߌǥKyߖFu\u DTm!7£%~IHHFM )d+!Ż@ϒ$9oRim~ `| P79DĿ;^4^h6'C @JU)tM! { 5ZqH]@X #|)v\TJMmLWE.u*KU! u56N$)l$,Z8ۚvX@~JY4V~n4'ҽbo;w[.tëL؊SR\tK]RMGTU2QF XPx~O;X7O o W7a Kf=`>(K39Ms017Z'Mw@q`F񱐗&+ FL%'[X.3DYǼe/%pL:wqγl>GxֳQ?OVpѐJђδ E[UGMjPԨޥKL:հ[MC:ָ&ݬkk;:e_5ec#ىR6dgCO6 dkc66 co'"lnt뎷zGwm~t+be c$6 F'[|zO"g<T3d+$F䮊G=|#gr#ب6t:y TmR84N@>{~G#W s~=nvy%*TT$ 8Z2~U509%9a83Y!ED [E>C@&8^b{A{>ww7AIT4w%1:#/eA}2D|)C}dgOcuFsb_EHV2tP[rV4QZP9R*#=p4 H/uW1/cVUYJXxvCY3jVTW'MݨMy5$A~Pi1Yj9XHx: P6cWk7DWiEYeXCY[~X[Nt4^EO\^Х]ĥ^WS]~$RbB]˥+\|=B<Ƀy%=e]#_4_E0B9Up)c=IňpٜM(Yiܩؙ9y{I yg<Ig9ǟɝ &Zj ڜ ʠj*F*pߦo!*o#Jf'n)Ƣ-Jn/ &3m5j9Jm;ʣ?lA*FEJlGKkMꤕQZkSJfWZlЩ٥K`gJXvpbdZq6kLNsaE}kmhvmu(a4vx1|j{~1xR,w-Q2H's' 0r̢y- .c.0{^{tΗ}V8UW@c@'95&3kc}gYhIhv7>.(6=ICYك< 'kQHX=I># >s:*gYCRl(~;T|D E[Ү"&R9TCMz@نSHN X<$v`I^B'Y\*>3۱׺ m)$&˄ȒOefrcJ@RtpgOWi3**S4R%(|`z-! C"84X=b%1802Ev,Ra%)HiVC @l@%Dqծ%!muigz-zobֹ0g j۔[/lƋ+?NrBcʝKݻxݫرҮǷÈ+^̸JAF ! 3k̹Ϡ G>ZvS^ͺ׫É -_ Eͻ )[\^pY#OУKN&TBk$p fNawUm|WUf\>P/' 6EU52W x v1$0S6X"6GK@$*Z͎"Zj8hH& Z8xb.^ZP%3 >62YC$@Tr<yn\y1>Pt>ԭo5  OOT@9߮S>8z7l^ԻCB=<,O#Y6qF;"4䧖}B pB pƩ7Zɀwm +y@ B8BC~+0 !aAx;!Zk@fr[F4RHcL H#~ntuM).` 3A$;4 נ>)8@'II%,_6-_XbQ2bRC(!&(9(+uԋ&5IQ=d%̚YI7,cF9"b<X: X~됓99|*X0ڱMuY$Q8A2 ̂UIIgOE6p`xF9qYH!w<{ވ\j;9Ay*TqO㊥<1nG,;Np H [(?BnF-Z0C~B̌fjoAX"& 3Y,8\DHB0P 9aҀ)hI3pӀ22 qșʹȩ 3=aqYyؙڹٝIK2VR-WŜ虞y@.,ҏi3 _ 'ǹ/s=Teҙj٠ 3"Yvj U&5Jp-سqqjI9Oy=1 Drb6¢@F ^, S}ᙱwU7Nܛ}29)5A ")L4㚽aζ,a !M^9H~J+*m9AG.`0^Mh~g8Ұ qnW @uںjTRv[n>> Ac䦊(f$~!&Ks~w&YMTT`>n. !%l~~ʮή>Ԏ~톞^k^>]ýӝ^Mﵦč _  ?y]?ma"$_U}(*I.?0==4?6:<@B?I\F?H=LN1RT_%|XZ^?` /.$XA .dC%NXE5& ʣdž I)UdK1eΤYM9uQ$ɝA%ZQI.eԩĞ+UYnW;t8jXiծe[B~ 9j\y_Q\aĉ/*ݳ%O\egСEV!aҩUfڵ¹!]m~]:o7jlɕ/gޜqO^:n _wn_yi${7^}k_~po@Tм:pA#0zpB 3p lCC/DSD[tŽXqFkJFsqǣpG G!4HDrI&9'r'?J,T2K. qK/sA04DsM6SM8M9s8:sOO@E3PB lPCU0DuѸtRJÒRL3RM;G(?uTKC%TT755UV[JWcU'NgVuW^MW`e5XbSXdE=6Yf3]Yh!}6ZjZl6[nܶ[p6\r\t<7]v\]x|7^zԵ^|7_~uܷ_g7`U`E<8a3\a!|8bb8c۸c8dd;9e[e{9ffk9gY۹gG9h=hW7i=^iE~:jMjU:k]޺ke:lmlu>;m}^m~;nn5o޻o;pp/;:qaZqWz 3DQՆ- ehRP԰|!n@RI1 KHB`7 jp(3 l D6Z>A7tQ ~r6AaA'jC | L\H3!qF"* r\A tư(\8 r D􈆂l sAr H/pjH"}:!|!<db0, TGZ#C2h $^p"kxNtq8\IW:爀"A 6`!0AI|,,fiE49C8 r/|aQc bHcC\A]9P0!f *N>a dCт ghiA1DTBVL/ sD\qdjA6pay )0T!&>( 6D m+ mit5 Rcs$⣇|NSlDbAh.ر_Zm:ēM'Cp҄aC)eҁ<"_īقH b`-PDт_І"tXB c\h-pX|@ G6`94a[ @) mmy{^ Zd]yN#uL<(fjP"@*qՈ8 ]PkTGr$A!$$2$AUՁ4Q|nt]< ry@@ ^1JH:9Ӊ`6R i$-KXڑUdJ싐/&( kȆ9 X&oHBHmD4/ [ItC> >T|Tj$iAQ %HEa L4Š5 0]3iJ /YC˘Z7|Q\"E;f\؂Oprqʌ>\ .t&C%pL!"IKs)i8H4 *fRk:1kmkNp od,H< ٌ(kOt6 r)BjĂ" ͷ/,O" vԗ \HItJҒ QgCGesFyX5up~.-H `B^ ^ ^\&6y9}̦oZ{lIS@*>n}?$\+rx" e2v$*'$,|p@һ 4‚ "\C21,ā<<6. $=< #A|Í\cÇ ` /ćCS\+p{EXEYEZ:@(5Gc/C323"5pP0؃hzrL e!hEL<*4`‘C=8Ђ&/ȀGK,30RT.pAP¥HJ*h>-v*‡1`?+ć?lvcBDEdDi3WSLMTNW$ %m<ɇP"2ć ;1)@.L{ |CȴպC,24*]%#[CP`*U4Ht #γ31@Vϟz%1PP7# +W2r8 ;CYs؁1YM/t%7!"rQ,P5h6 Jm!Z ܶ$Z41333 1H58<-rEd*\wBRjDN% 5n ``iftps`fPd`pp@q`dPfkgiqpa|( dfgascH[%%fa!f `xg_YɆkk3Άj@agpqȞiarp5s8=NhbshfXB !lvj5^?&p d%d4i5j M b`c10_qNb `dedjl ul8f|_oefQc+֞kn@q gNV.~f|ba/3.b?>fXeypPVVdf빟TebBv9ghb/ePbbheqjxbF~gq8cvNi|her롆tjeXva9v@hΆrHjfjj k>kpjkCfk8kk ȅf!1kh.>Qnp,k뚨j6Al mm.m>mFmy&fAg6Ԇl sm˾ ͖m~ 6F )jh|~mV _lݖe~nnnnnnnoo.o>oNo^onoonN PkmÀNglmN삈p p ޖ 1pApGfݾwdOk瀎pg?p p Wqgqp3va?'Nr(_k`(r Q+,*.O/31234g5_78:/gr=/>m4t !4,  O2ą֎p5P"A>LÈ+^Ĩ1G#J(ȂS2d˗ $K|.GꔩG6ℹ(MI=rF=R7HP%O$wà5;R@=%Jbp`U6Ef Ҭ@][gЋHⴌiaÕC, 1hc}ztc#aE.:h̤a (ʗ:۹Oӫ_~)P!), H08q;wNֹbHŋ3jȱǏ CIɓ(S\ɲ˗0cʜ͛73'ϟ@ JѣH*]SJJիXjʵSyvKٳhӪ]sdKݻxݫѭMr LÈO7pKLU7~ϠC]q;w%ͺװњ>:۸s떩Yj Ne.μc8سkwzËOb˫_Ͼ/Lᄒ!׿bs=߀ m4 >& 6!!K gay _`1с(#JYK^v 2Ì|!D4h8x"Z9&"H&$x֒$)esTie@L4pM7X#\s hlpwYna)n矀d"44Ӝ)裐F*jm&hv駠x騮)XM608-4"O,2ʫ1ǔ-HRL6PC7ܠ:lŹd[[3Ũ67# ,L0B-ǜ4ټ K-,nl`3 0<1#44.P^\-_mhݧlp/Om5ҭXx{߄^We'TG~'%oWyQw>[n:M.ä.;츣d;Iă$7cFo=Eg7~v=)ѫC=/?m@ *@)p `; F`1XA "A:%4Q:s`C揆 q9⏇=9!3D%s8)U"8-n"F1j{3H75fmt879ΑlG="f5A4d5E.Fs$ IIڎ1%11M֎@1Q3PJUr+a9-Yep)-]%LaJ21y)eFti)iN2#m>@&s" YNs @JЂMBІ:D'JъZͨF7юz HGJҒ(MJWҖ0LgJӚ8ͩNwӞ@ PJԢHMRԦ:PTJժZXͪVծz` XJֲhMZֶp\J׺xͫ^׾ `KMb#XDؠAd:Y2fN$%c M>' v@lle{#Ձ.[d~\2,r㙅έOB0wۙ,…J1^uT(]H,![*b /8bk G@!5, HsuX1s#JHŋ3jȱǏ CIɓ(S\ɲ˗0c^ 'N\8 ܹB2 JѣH*]ʴS4mDȳχOjʵׯ`Ê+1Mq9lx(ٷpʝKݻ3kMBqn LÈzοKL˘1.FKձ@43MJ7U\h԰c˞M{x ɝ; sP\ȓ+_V(I }okνwʀa,XЀwF X-b`|\;'h-M4R pwqVh0Do>R(LJtU4%h8Q FL5hHXM62U3#YXfwK#ΔTzfhq7 !Hup xMӎ8u硈&8~CN64pc7`cͦ^s*jV(HzrZ騴jLC'0H鬷k)+찟"+f$7)6x 7p7є+:Tb{d IBL"F:򑐌$'IJZ̤&7Nz (GIRL*WV򕰌,gIZ̥.w^/ 5 l0̠e@jP&4hL|-KE lS 28B)2Y@ E&QMH+c+JA$x '+dϋ+>qOVb@!1, X H*\ȰÇ!;v2f"0`Éɓ(S\ɲ˗0cʜI͛8s܉rbŋmcȑ"y*]ʴӧPJJ՝>-b#kH^KٳhӪ]˖iV\ݻx˷߷[v-5l8+^̸Āz˘3k̹sq)(p"iϨS^ͺ[Z%6:\iӮsͻ7Y .lXȓ+_6Aw+fNaVn`pN׫71rGO&4|˄Wqh%R6!Pt Vh><'($|%"}3ˊ@~0 (a0#v@>@0E:PF8|c7Ht'##@MR(h&Kس8x H#diY|yY%p~CcS8xzn磐8 N&*Ң駠$88;#$‰51bֺ֨%*j;VRmɪi-cF1M,m[:t@kﻼ8o6H&pW|-gqo#2" uz0ǜľT8 IBL"F:򑐌$'IJZ̤&7Nz (GIRL*WV򕰌,gIZ̥.w^ 0IbL2f:Ќ4IjZ̦6nz 8IrL:v~ @JЂMBІ:D'JъZͨF7юz HGJҒ(MJWҖ0LgJӚ8ͩNwӞ@ PJԢHMRԦ:PT]XlT`TRիfuUaV Vd-kUV f֨|A PWu |%^-@W o@@6 mPd = y6lV \8CX|xh5 C0+#v8,h8>V k0C(K]ƺH= WmҾ!ζBA݂dw~r-n` ^f+ְuk|WYo-a EbLB4Y&DCPc!H\ @\r Z0(Ѐ{ dA£no N g1B+ dM/ b|jH e;.LXh@* jnmA@+w j@ְEKj vyX.+Y,ʘei =>k!W^ 0+49n 3/ \Bi hC iO@o0.b=|$yB!$0{-t U5yQa@-l <ra I.A`|7;Hhl q@FȆ`䡻{x64=WD%?yvߴr@`AxpAߞ6h2"mhpmćǿ@"0j,рkİ<w/4ٷՠ1a @0|C o,-͒x x̆Xcyˆ.e $B-WWgtq*k ;*v | ІYeWF;ve6c[gA*&k}cuYdr0X^i@V^϶uq6rvgh#W^5^wb`"FY[0tib@Wv(V1HdavQ(D h "H ڈ@)DiH&L6PF)TViXf\v`)dihlp)tix|矀*蠄j衈&袌6裐F*餔Vj饘f馜v駠*ꨤjꩨꪬ꫰*무j뭸뮼+k&6F+Vkfv+k覫+k,l' 7G,Wlgw ,$l(,0,4l8<@-DmH'L7PG-TWmXg\w`-dmhlp-tmx|߀.n'7G.Wngw砇.褗n騧ꬷ.n/o~BhFl|q|DNb|}KdAmwoFyg!~ңp}S@4c@8&XT# 3![, r H[x0Ç#JHŋ3jȱǏ CIɓ(S\ɲ˗Fd(͛8sɳϟ@ J̉4*]ʴӧPJJjƚZʵׯ`ÊK"V 2eWڲpʝKݻb&lK/޿ L_nְǐ#KLY%b|2k,ϠCU\gϚ`ͰI˞M#MVk7N-C.ݹs)|<3سk^U9sХ.X:ӫ_ҒyH T"퀗gϿ)_ $yFH$/@0"0@uVyH($$( %0,lE&h8N% (B_~hH&yӎ@ Vg Xf%FB$2VܖhfX Hg)k"H'*:'&(w)≊P .j饘N8K4ٴ#8ŜS/fjꩨ:&I438#Ψj뭸Ƶ AXk+T%6O _ZK.׳vIC@}QU֛k/E+;Q' 7G,Wlgw ,$l(,0,4l8<@-DmH'L7PG-TWmXg\w`-dmhlp-tmx|߀.n'7G.Wngw砇.褗n騧ꬷ.n/o'7G/Wogw/o觯/o HL:'H Z̠7z GH(L W0 gH8̡#S`cpzH@6P D58BI">AE" (], A"`"$RF D@Bܑcd!TwY!Ƚa$>!-,j8 Hp\ȰÇ#JHŋ3jȱǏ CIɓ(S\ɲ%DŽ ]ʜI͛8sɳϟ@^)ѣH*]ʴӧP;JիXjʵD`Ni9_Κ5ϗ׷pʝK]c?e,Zw L>/ۿKL˅+rm.CLӨSwkqU&Nq}-q]5ZZ-k׎4lՀ1[z.vLwËO4k׭a˦m;n޼\8_ט1OsQw890h5FXU:轆:L3M6㈳ 0'#>"@4H `3VS'P,[L+I)HK%7tIB rIWZ).1H vcN ,4{3X9KKBs9L!@36*H6pcOwp`,6>A6:3 {tҼ243ǐo,p33Њm'lI83P5݀);bv+t2N/$3䐺#N/̇K12^Z6lc> (3yݐ|CZL5yF)$%)ø/Fe09[1 ТD(x_6DŽt-cIB#= Y ia] IJZr#nI$X8Mr-p@ab<e*WJd3aA8ɑxU;Q[h^b2RGL2 L #,1Ij>yEIiZ6Mps :v~ @JЂMBІ:D'JъZͨF7юz HGJҒ(MJWҖ0LgJӚ8ͩNwӞ@ PJԢHMRԦ:PTJժZXͪVծz` XJֲhMZֶp\J׺xͫ^׾ `KMb:d'KZͬf7z hGKҚMjWֺlgKͭnw pKMr:ЍtKZͮvz xKMz|Kͯ~LN;'L [ΰ7dA ? H l #t` C'&k)P!$J㱲41>lcHb-+JA KJN VBɲXπMBЈNF;ѐ'MJ[Ҙδ7N{ӠGMRԨNWVհgMZָεw^MbNf;ЎMj[ζn{MrNvMzη~NO;'N[ϸ76 lhFn`a _`@.pAd؃@@2ā [G@+ yxd. <7^N7 D >wq@ѷ| mH |xjȐ [HAҰ* npCR 8?ta"^; c$97Hy~r0=tH5 _A.x oB2/ &r~!D /Wɇ eg [B ByCЅ.!@{ D_E.u;QQx7ZD}y1rw}m`ۧc| ggYyקсy7znyQxX8P3u#'z wGx:'/v~|DŽQ0vgh~k}7`T@*!fxhc僖'l &(fYA<=p}jzrypXy^8P4cy@ WpPa@gv8Y>zlxhķt'~ 0kjPrAw5xtF7xy'Dwawm(YJn c0bv~70`z_@HXPvkpHy,hP_r_bzKrtgy0wsqtЇaQY}~[7+~|Ŏcfyw7/r 2)h{0.爎s qkcP_{t_0x\t~8IّrP?XizW=YdP5'lr_&/t.G#wmwJȎ#g(Jg ^x}~k`7|Z(frW~p9`#GWu*9s[P,E |I1jPiǚaj QW 8`˙W)ΐ2 *R r L0, 0 !Y̠#ހ i !)t Y&@ C߰&3=!0,><4 e| Hŋ3jȱǏ CIɓ(S\ɲ˗0cʜI͕Зϛ@ JѣH*]ʴSzϫjʵׯ`ÊKv,³]۷pʝK] R '.6lcKÈ+^̸cy`k ?̹ϠC׽v -sΚsfѰc˞MmMVzko N[K#jnb8سkν{v2gG0_ξ:O D]q(Z2H % hVh20b-H"$,v8L2< 0 RŜ3ѯiZFٱ✃յlJڥm1dPEPbEEQk:%D<Ӿ+'|G,Wlgw ,$l(,0,4l8<@-DmH'L7PG-TWmXg\w`-dmhlp-tmx|߀.n'7G.Wngw砇.褗n騧ꬷ.n/o'7G/Wogw/o觯/o HL:'H Z̠7z GH(L W0 gH8̡wCeDj`|#V *@ d&b}c$80#JRŠ@!ؘ 5-`,Ȋ:1i $>BL"F:򑐌$'IJZ̤&7Nz (GIRL*WV򕰌,gIZ̥.w^ 0IbL2f:Ќ4IjZ̦6nz 8IrL:v~ @JЂMBІ:D'JъZͨF7юz HGJҒ(MJWҖ0LgJӚ!<>/ hBv5#WZT|H"maCX־jJ@/^Ԡd HT)` b%& Ĭ1Dt*"nQ& dz6խQY/"ơ!lEnV rHr\վd_r n+#p"hBW7b]A @\A eݮ^6H&R\ \@ @- R->Z[w(\>@/H"0li8T<@Ĵ}0Ip  kP蠆9,U`ځ\ R^b7@Cs8mkj>@d6!C|P h F[="ݩI5 @rE4dgh,h phC d PIj CE4LEo iJتYL5\@bA vs0!uC]]ꚨS^ 5x{ pN3x۬ek[|Ag {=T&VLn;܄iS5q}Ѽy_V < h 6i2T88*t*Hyʳ?_Qnt`6md/%OG:h!-,Q)4H0@|*\\.|":4!Ë3jȱǏ CIɓ(S\ɲ˗0cʜI͛ ,髧/|=q JѣH*]ʴӧP;ϫAFʵׯ`ÊKLA>m[YfʝKݻx] jҁ捛`gʘ`pΜ{̭e3k̹2,aȉ7~yremA˞M۸7Ƭ8>reY5u`MسwË+F3Хξ{]gh٧.S5x#M1@5F-s-~fK5`12$DI,"X"I %@`c 36B=Hb#%< bL6*H *b$ DX$#%@l2Ûl);,($=h袌6]syg;yg:# "`(9*ꨤt34ٜ8s8HRB~Jg+lSֹj)k1 BB#䡉kf IBL"F:򑐌$'IJZ̤&7Nz (GIRL*WV򕰌,gIKfBj`|#0W *@Х d&bc$0fJR™@!ș q/ ,Ɋv3'>y~ @JЂMBІ:D'JъZͨF7юz HGJҒ(MJWҖ0LgJӚ8ͩNwӞ@ PJԢHMRԦ:PTJժZXͪVծz` XJֲhMZֶp\J׺xͫ^׾ `KMb:d'KZͬf7z hGKҚMjWֺ> |Z`ڀ=DM-a G98Ѝ` ٚAEny{"І-!/uAh8>ݗ܀ †j$ .` ҍsk7u`趽Up5R# .rha!zA` nr[61 4~eG3 npݎAHrQb~$ >' -{5|#],Um, ?NaMG#}Fpȃ+ax< !FH3M/X:$Whsr-j|qdj[=X*\-uQА"7_7T nP xP \2 b`E*lҖ %oa!ð6`80- qC: կ05uƀn~Iנ{ 6p^f3WexvgAkr<ٹ{6CKMg}&H2NsDFڭlT8F2p('89>|pe!.,a* H_p*{f@<}J(RyJ:ujU[ܹk֦*J-[jfn;hgkǶ۸sս޾)Ӣ^s:ikw 4gjuhԁ,[/vF+3fOPx |'iD I$(aOVxKlAoH};A%ؓ]޴Y-9sӬ'P  s!,4'9! X(' 32%C#(<#7 944 $$P%|#;P'b9lS "I%ig# 37b"3 ;ðx:7<, ~"`_e>1Zul)h@.t}7cLMzQ|h|ߑC'~*WMyE4H3_tN15!.(MQ, -\O?=E:4!2δ3̌sRJ4c92m3D\/KIC3D$3F$SKj!,,q  H`,ȰÇ#JHŋ3jȱǏ CIɓ(S\—ZʜI͛8sɳϟ@+0ѣH*]ʴӧPO%իXjʵͩ/ 27֜ٳf]˶۷pZ9w˷߿UM8nܷo  ̸ǐ#oau̙ϠCM!g9#3V:yaMK NSnee.ݾw>νWVSF̙3w5kz` ɝ1gЌi8^y祷P1K=' 1YfᆟL;<2D9TB ./Z4h^S 0H"{ :4&#L6@~ylT348"', h&IASKXj< H %HRk矀N1$&P4 059`<@Ȟ馜92P,LhFHb)=fv*무v7M;T ; 8g-j&첑]#,S 3k '^,+.[Nj6W *9k808H̻K/ U7t9r8\s9L0Ę,m(IÜmAƜc7k|N8N+-傏8@c4PG-X,(=@f9m`M4Yh5d-lA$CVxݰBdeMހ/Yk '.B}G)-gw砇.褗n騧ꬷ.n/o'7G/Wogw/o觯/o HL:'H Z̠7z GH(L W0 gH8̡w@ H"HL&:PH*ZX̢.z` H2hL6pH:x̣> IBL"F:򑐌$'IJZ̤&7Nz (GIRL*WV򕰌,G" qYzLC^)P6>Pdr`&AlHš++JAfA g*oB'+k~g@!3," Hp`8_|[>_!8E WP#>C8|ƙ,I90I[-ʙܹ%iٓ'b  _I'Йܶ[wP\aД2u*՝˜9S<}CN,YqeyZn-['M,xq~[W'3hy:y KES7_xyreqō.Yy q ,1PxJ@`P"'{ob'|I/QB ɑSw(轷D^R ξ{wJ!?h|ҝiPwH ~@GO=``_L8I=J J7„gU̅蜶a7%蠓:x >Ƭb 00dfh8d3 .KR䕷yL!C%%a~D Sy 0%PAR@!\, H [h.Ç#JHŋ3jȱǏ CIɓ(SDɰʗ0cʜI͛8s3g˞@ JѣH*sӧPJJjpXjZќ/|-syjٳhӪ][6@}5%ۻx˷oAr[nKXB~+^̸㗁#k˗e=̹ύ9 ۹͞= 9Sv b>8A NqIFÈͮ};~|{vYp҇c-8rf(<۾r޽{;w(Ǒgz|IRB uef 0PS0$N;栓M;@,@,H9#W\@@)Ee6h"3H"4\<#78V9H`)I @$*%x#Y}8M<嘀* # Ϝ$K xOC 0H)rF@S%0P$8BFk42 6DMi3AJ}w[ Ӯ;+oiL/WlQ%(+ "̳;2 c,7 <@"i|+pn1LL7, -",蠃#K:p# 7Ŗ-=^pm,됷 >"Yq 7:& mJK6CȀY4,yVwnN^X`CAt촧E^c\{o2'w|Wogw/o觯/o HL:'H Z̠7z GH(L W0 gH8̡w@ H"HL&:PH*ZX̢.z` H2hL6pH:x̣> IBL"F:򑐌$'IJZ̤&7Nz (GIRL*WV򕰌,gIZ̥.w^ 0IbL2f:Ќ4IjZ̦6nz 8IrLgRP| 5> AtPJ|, 2J% V4`E)1P HMEhTdTeHGP. !d,8 H0p '8gΠA#&Z;f 3jȱǏ CIɓ(S\ɲ˗0cʜIMrdD/JѣH*]ʴӧPO )9rimgn:pXKٳhӪ]u*ȪWn5,ۻx˷߽tqai5s;c9k˘3kwIc7>Gװc˞M[gϠ ׮YuM2j+_μ414|h߾XËO $ " f+x D:3M5"«HR ˯f- vа )2 J "Z;[6x 4%6K4)" 2kE:o) IBL"F:򑐌$'IJZ̤&7Nz (GIRL*WV򕰌,gIZ̥.w^ 0IbL2f:Ќ4IjZ̦6nz 8IrL:v~ @JЂMBІ:D'JъZͨF7юz HGJҒ(MJWҖ0Lgʻ,? H l#4`>@)KA"9 R(DS b&@Wub)XQ B4R XS&p+\ֶtk]׾ `KMb:d'KZͬf7z hGKҚMjWֺlgKͭnw pKMr:ЍtKZͮvz xKMz|Kͯ~LN;'L [ΰ7{ GLxt>ؠwdy@g0԰bڈ@S"' 9MA҆ _fH n.+ ^3B#H& 9$>91 @/l -(05$:#h(ɡ ch\sF@萨8V0flA N5$<f Ͳ'C ^4PN4$l@ g&V!)B0D\G]#\hN4A#u +{OHZN{57A 0뜻C&>>WwRG}zh3|ݼa0 R@kX_@7R/ 0P ==ޣN` H  8 ? @ Zs q:p ` !1, 80\8*4HÇ#JHŋ3jȱǏ CIɓ(S\ɒ# I͛8sɳϟ@A*3aУH*]ʴӧP-2իXjʵWTlhYrʶ۷p)\|˷߿Zļ+^̸㐄 7@rkk̹ȹ;5պyvٲu~j.\pղew8fLM]4nլ]K.:su ܲË4e̘=lަ%$Oۙ2`tw>Ñg&8yǞ{J %0B _k( )($9c D7ָ7 $@![kӎ4|!hH&Ri=r 0D<<Mn9L;NHWk-ܿxwzbM9+݄Φz'~7a- e䔳idYw.xw.稧^^z^}WnP0Nf+7v 7<0.Wogw/o觯/o HL:'H Z̠7z GH(L W0 gH8̡w@ H"HL&:PH*ZX̢.z` H2hL6pH:x̣> IBL"F:򑐌$'IJZ̤&7Nz (GIRL*WV򕰌,gIZ̥.w^ 0IbL2f:Ќ4IjZ̦6nZ1 ER! D5ǪyRP?8m 1|0+ qO؀ `E@W VT,~ eF7Q|" !,, rj H*\ȰÇ^cF0E1cW8|Hɓ(S\ɲ˗0cʜI͛8sɳO+^ qcǏ!G\ʴӧPJJիXF :p(Q=%ֳhӪ]˶۷pf*kѰH*˷߿ Lx0]C[ǐ#KLrv.NjֲϠCM3Ěr.ͺװcˆybz;ͻ8_μU^0:qË:,iEڭZ[);O8Srh&8"W9M7rKw*v3, {t9 d!y0(^vx]A,ʨ&䒅E2`4LVi啁E {aa)dN/Lc͚ y Ecei?/̴S8硈&$1iH3XFѩ覜vB*)R^Qjbp܆0wj3)Ѱ&9F.+V܂v->v;طj춋ٺ+.2ݫ.,CR:'<BDOp$wz\"*L,s]$WC!1;Ωlp?V3A/#(H+3s4,IWm54\Z#E/ cGiVj2(L3%0HS":34.ňN5tL5G9! Vt/5ٌc9߈ތ2$3CwFU7ՄSڌ(L8L72F}9 /ވs5ӄ,-ӎ/d3gMlF;9?dfs2v~C7J7ةCyF/? r32g9s JgexȃhGN.nBMxփqM^;Ѿo~%s#[J8Ul#3|C  <j]!9 7f 9MkPE l nغd  =pQJ,HN eˠ@9eM`yd$Y5866ZSGnH3:ixqG܂)dYE2r#ʔ*OT_jid6:I-D3N7T,eI-թ| I# 15 -xf4IM\/7b\:%-nըi$sF1r|H*9q|c lj8r#b@n c"8i15a v[c(nР9ѨyEiMy<8Q1ܱZcN8cdh/J [;a^ሪ/)ƵM%PZU G.cUFЉC3xS#[.T R1\d+lBr#E}ɚhZAV&nFE ZHcS-ׁXM;ma-bBt:>4Y|øqG5{9#/!GqmTj[Kb@ #! &,A)OBVj@c>pz Ωd|` ȍVPxb)(mBs  wĈ.1 0)Ba$\wM I@C!MT$U&lA9*$IA@!Mb"!.H bPb* !X"$D R A wǽ"sihhOc\AA\/cw,a e3zYs8nj 5W"laȪ ң8G^rAq:zA#ǝE@mIH*ġMTỜ Ȃqܻ \‘LÃ: YrWo<;\)"{8y D}E} F,V]=*K߭Ǣ5Yc>s_` p9(d)0&EQnpT<Ft"'""Р Gp;[d+CK J

B[BFeJ۴W´NJR[;BV/Z۵µ^b[Afぶj۶nr[Avz۷~[A۸[qAl۹gV[QA갪ۺ 뺲;K{[;{ʛɻ΋;.ѼԻ{Ǜ;۽໻;[;蛾쫺+[{ۿ+;| , ~@B<6[F,H.LN&R,T\{XZ^ ` ;d|f|jlp|rBBD]:{HmJ2NP*;TmV}"Z\`]b=[fhl=nrt]zx=z~:؄=}ߚ؊ؐ==ZٖݬȺٜ--ڦmoڬ+۲]y۸M۾:8]~}ܑMtЍh=$VZ؝'mMk @]gs]5H3,3]2}10>S>0 /^/^r.n. 2$-&~ے*^-,0,2>R6+8㫲<*>B)D^rH~(JwN^'Pd2T.&V~WZ^%\K`$b>=Rf#h2l#,2撱EQ$J)Fu~=b,<,Q%ڰw#s؞ޝr.g.yghgm6U,rd_Pyk0\a A!mPaA  1b a:xil^Z^rnk_]m{ ~!ﳭ~N m'VA@9 ypdc 9aRA#m3bRoAq.aaOH̞#Ϟ|nW_?[UP0eb=+^h`qb/Q\n d/N2 m a@o[0 1 ȯdq>/&Z`\0y\0P Aț_ٟ[0 Ex`?R_g$XA C%NXE5nc3hМ'2-'4 5jґĠ5UhdbN4i~Yn:,Rps3╈nn5}Ap@8NK37@M(!/ؓX#% 2N1( >|к(6+E%Ï#;*x 50J-ccPUchr:ۥWYf"<( 0B$B JrB+f"0h[7+|H\/&h10c`sϨ+(YC 3עa ԡ*i.opL+!ordh ƚy7$b봫H|9!B+)'|_n%Q ih.фdW$<[IN"墴;MJ= 1O jPmae dH >ء0!B-dvډF@#@$[pˆPAa^EP"|Ȱ{ؠ4` L0ƴ Ct$U HÞC쀏PD9QB CɃڇLZv`%@ *8n]ч_D:|i0Id%BJXsADjY*J'iCpg5D-z`9|!wsȁP 1`5yMl։tP1 xH34HXYL8ߤ*kȣCF,4ԅb N4.RK|!NKaC PSb?堚tRqtĢ?E5$x)ī]bU:9#{ j=-HhZʣubDk>@-<$uICCfCrCI) c4OKȂlAeM S|,YΥlV%la ]FdM|FY~BqH%ɓmHӳ_Ȧ!!:d f HdIڮm0=lU6Fq^q[(K; I40luiN6#!f! IѭmGr'\k[D[}e V knn9jHlf?Wql_;(3tv ,~y > !o+.q, p5=IHO>h\0=ml[$iTL6%$cZd$ (޽ljB;r#r;ZfJd$#:|f`IFQ$yN38,vc7Fr|!c6 x|h|GDtW L4E"K;&ӎt=JZIC1ꎬ4 g<#Gq_bFa k\C88n^Wp3-lqc#֘4 r`ưAqH[ʆ:*S7.F1q[C/ iHE|C7oqbƇ/m [;߽pHzhHo/}a [<徠x{v(1Mp>!q3˸7dl|PF21qؐ78ґ lLcXFAlŁZ{9 gddƲq #ٵ.aZA|8G^#bS^xw^'DzC/}]z-}!}mi^}Wd_#E#bF\ȕEO]m|^99lWg-oa6\P:=߀kXm]퉣u7~i)嘟AS噇.:U wD謷.n/o'7G/Wogw/o觯/o HL:'H Z̠7z GH(L W0 gH8̡w@ H"HL&:PH*ZX̢.z` H2hL6pH:x̣> IBL"F:򑐌$'IJZ̤&7Nz (GIR9i>*w"%f;B !xTP JAA , V4vHE(A (5iTdE*ęTȂl,Rv⃙+OYs @JЂMBІ:D'JъZͨF7юz HGJҒ(MJWҖ0LgJӚ8ͩNwӞ@ PJԢHMRԦ:PTJժZXͪVծz` XJֲhMZֶp\J׺xͫ^׾ `KMb:d'KZͬf7zz8~ `@* hK{ZʤuJ`K8D-Iİ8 %=D jۑ-Pa |Hqa .wv6 [`40 y^|w ^C6 C`/hd0z m8w uˆxlA֛.W %X} 2-l!XCE z8pL ^ pA*p= s FL?tW _\DHy h,D 9v Ѐ1A@4ph@=`Y q09Xz y>Ɯ }5h x8 @ΠAG1\ ^FȀ@ \@$fʤ4 1S<$Y rCD_ `[dQ\rXpq ||@ ¹guxe- ^a|q w7]p; (C'6( 7k]7 Hq|7aOn@ GY eز@H;\Lqcb8U,+`9sDT,%8C61S[҄S>7\`R;dӎLpɍ )0!xYQv*矀jg:QR (.hV_Zƹ駠*ꨤjꩨꪬ꫰*무j뭸뮼+k&6F+Vkfv+k覫+k,l' 7G,Wlgw ,$l(,0,4l8<@-DmH'L7PG-TWmXg\w`-dmhlp-tmx|߀.n'7G.Wngw砇.褗n騧ꬷ.n/o'7G/Wogw/o觯/o HL`0@ nCA+<6tD [CHh+ЄAbDž nЈ Ra![F$ ) A~X/P#wx"΀ 6 N !`, ( *\ȰÇ#JHŋ3jȱǏ C<`(S\ɲ˗0cʜ͛8sHΟ@ޔ4-,uf%ӧ!F&m֬vj5$`e0sv]VװƖ=˴ݻ?ߊ%k-޿e˗nÈS{Zǐ=.8'gMZp^tjְ1Kuۈgn۽-pԴ_ޔ8͑No^W~O^;O˟OϿ(h& 6F(Vhfv ($h(,0(4h8<@)DiH&L6PF)TViXf\v`)dihlp)tix|矀*蠄j衈&袌6裐F*餔Vj饘f馜v駠*ꨤjꩨꪬ꫰*무j뭸뮼+k&6F+Vkfv+k覫+kRX>{䁏~\Eu^{B ߙG<D:PAFyQ\lGdFh$Z1dy5ti@_E{dA!v~tYlQ\QZAWuE-un<1yAw~Gqih}^F 9ᄃ7Τ.>!2,x  ĄI`%_B…̙Hŋ3jȱǏ CIɓ(S\ɲ˗0cʜI͛8sH p  ΣH*]ʴӧPJJU{L/`Æ7ٳhӪ]˶۷pZpCb˷߿ LK ҥAϨ˘3k̹g%Ijl+`+^ͺװc-BґáNmY N%$ڶGCУKNzaђjc4(@:k^ֺӫ_/v+Lȗ"'ϿuI(Ԗ|߂ 6݁0B *v9܄&Tx i,2hZ V<(w R馜F9D.ij*"Ke꫰-h뮼+k&6F+Vkfv+k覫+k,l' 7G,Wlgw ,$l(,0,4l8<@-DmH'L7PG-TWmXg\w`-dmhlp-tmx|߀.n'7G.Wngw砇.褗n騧ꬷ.n/o'7nCE5؀O ;E@aLd8![d} x*Tq G>P1@3 ++^J* &_RR @`*R*"nL>&Ype!~(L W0 gH8̡w@ H"HL&:PH*ZX̢.z` H2hL6pH:x̣> IBL"F:򑐌$'IJZ̤&7Nz (GIRL*WV򕰌,gIZ̥.w^ 0IbL2f:Ќ4IjZ̦6nz 8IrL:ב5AOk\''=shy4(? PIG5&ѧ5ьfLD%JQ"4GҐPKu%!p6!mX6p!3l/ ^G̠ӓjդJi g(8dR5>jz!/Z1dX(6p qէZ |$6ZXp.la oW-"F}0+a hjS ڦVD d4\q(mb0.A Z47 ZX  h;\ 8nw17t \/> Z r\A yjJ 5q<m@H8Hlk*\ lXns ]j~@CSjH {@PuZ0"A,@/!\B`7pقg1p!@0b>!pm@T|ضr1B{-c0@ a|a{o F, _ *@9!_/@0@>T = Bn`<9nA;3Xg`L R\B0t1`.yB aOGyF^-8T.@ |z= h2)P|L@Ų𩷀>! hBm!zlN[* vfN`,ѐ4w!^np"* lOF4mζ 6B 4C䰇}Gi@|q8 =7e ¡7< =;ЅFÜ*ӛ>d! Nuǰ|퉝 ݰn_:բhݫ@/6;aW`FP-K/9#qye=eV[y|wb`qwga @ Sm}}^m\7~j~^@g/@uWdمoF[Wd&m } pzP@"GiKEZ`hPU>ETʖEX8@+hmPE~[ȅ%0mBe``'i^ĵd/ZZ8 vz+.@[s u\y^Wl`0yEfSXfkfh_avj(iZ%0hG[ȧXjsHfDE *i0 YUSY0`a-`[d \;&]TS[4`a8TS~Wt bh0[`,놁,wm X\(rkxS]D5exg`t]%S HE) IH@BClP|$'IJZ̤&7Nz (GIRL*WV򕰌,gIZ̥.w^ 0IbL2f:Ќ4IjZ̦6nz 8IrL:v~ @JЂMBІ:D'JъZͨF7юz HGJҒ(MJWҖ0LgJӚ8ͩNwӞ@ PJԢHMRԦ:PTJժZXͪVծz` XJֲu/mh4 C/!\Yֵ @ i@b {EPZӊ3  BW6Ckd 4YZ]C F{ Z ->*p!yG<Ҷ@=@ڠۇ@!yhpz]%@wGn{[VW=mK肗!=o~АTB $X j5 nhb7@ tX- {C/5%qvP9cB n^! yr԰9 ӆַV5jj\fE pŔV4lٲF.p[4\ԭ[gka6sf5in4gVJ. 7\m`; 8ď \f|uY9蕕alP鑕{0Ĥ?ibW3 kgmZsřMX‘lkޤ37z!2,x( H*L_Ӯ[Hŋ3jȱǏ CIɓ(S\ɲ˗0cD0ܵi ɳϟ@ JѣH*]pܸo1JիXjʵאNE׳hӪ]˶۷Evڹs{DAxp LÈaʚ[n]`'L˘3&M hdƬ8cąS7W;v۸s̙hٮt8qRk_MسìTIdj}3e\G_şoN5gz'F'߂Է߃F(gIb!eSMzX3 6a](H,.]!Hr!"GG#@)D]%`r$HT g3ϰ)_8 䠏))dYwIǤٰX@ i } f矀fHL 7񀢨L88 3 m%>z覜vR3zhK93KyC37,驯ުg`pw%w]sٜԌ iY(n!@(ݸ7:T?:ΡmL`VWe;3{,նmoDJ' Oz x=0 !& |#|@$fGMp&yP[8DV! K(Qi9rB8ApP! sG1 \NS &7ƵDHLT KI@$LHdC.bYRADߐƴF@ъ4dqR|0U*򕰌%E1p-;aYDC7nbu؅S!A'AYtM)1Վ,a6M.]MOA8!gˌ{anc99rP'; |3N*!3 *NF-Adޠ5ЄnD2iC#Җfo}E3ю!iI1OBʋ. PJԢHMRԦ:PTJժZXͪVծz` XJֲhMZֶp\J׺xͫ^׾ `KMb:d'KZͬf7z hGKҚMjWֺlgKͭnw pKMr:ЍtKZͮvz xKMz|Kͯ~LN;'L [ΰ7{ GL(NW0gL8αw@L"HI` I/!\|SA&Wв|!A L+ R"~Bbl~o*XQ;"wNE*$ zЩB," iG[Ҙδ7N{ӠGMRԨNWVհgMZָεw^MbNf;ЎMj[ζn{MrNvMzη~NO;'N[ϸ7{ GN(OW0gN8Ϲw@ЇNHOҗ;PԧN[XϺ?$ 5cRCFþ^u_7NC>W:MkmΑR"3 g0. !Ox@E p|| jG  'o>q`6A =hUZȃȋ_=߀+,?_ ҆!k`=ca]8~ y| @89Ͽ5A j`W{L٧{m}  {`|DW|bymz )P7([{}S`P~DP ]0!}azyDXFxH(GK~^nx`PDP0xǁ['8`:هD@~g\ŧ Fp0rЁE+ohZx`؉wzzNX{ x|`-Axn@hx׊!C[{zqWFxǷ0~xHyb0GH[zrWU`]@~h%0E׏_0|(w^xzX,k؎lhyf|;g^Xzg|GgzWP[hP'#uHPy^Pi@W {Ǒ0h|18(dPK\g |X~Bi׆ox6[P\яS& @8{ Xp p]*)ɒhلjͷnbPq)"ȏ|^i2xy.j @ AZy|ك؀iډyyYdp`H8@+]X}yYT؎W{@qQ~_7WPAwq9-y|F mڹjIy^{p_C0[X!@a`yi'_U0,0q Vz>LhW@\Yr2[8TrlOPIs0q} ȋT[[?x" jqס:zZJhqfO٩bdr -{+x d`ona^G}*x[pxu|0Y@jЁt"Wꝛ ْ jx k ѩ'é:mi٭B 9  PTP3H SpZ ̀3!P !bNt!#%!ဴ $ ˀdc'D~wKv!T,B   >I&d0INńһ(0\8&x#<𙛈/̥NZ8|O|=J4hB=*婴QM 4QPRZժEyZ |6W|fY| tn^|SN 4f FiS &ة@_Tn,6rѤ=# ў!0,A9 8k֯w Ç#JHŋ3jȱǏ CIɓ(S\ɲ˗0͚@"Ɋɳϟ@ JѣH*M-9rKJJիXjU`ӧ]ÊKٳhӚfNpʝKݻFlo÷x LYv 9aN3Ę3k̹,o2Yl̺װcOe\ ܹf͜+櫷o_|-ȓmnqs س'5oި]@|y洫_Ͼ{ܽo?5v-K} ^ 6]34AS/ vx,6x!y0h0" lÍ4+Т@)%%;sc 8/=)TVICm ty<Eid9dAؤ,ipƉ_"7,:m(砄Z]δ r㦡Vjf* `4~B**t9$3b\ [ 7l0u(W*譫1w ,$l(,0,4l8<@-DmH'L7PG-TWmXg\w`-dmhlp-tmx|߀.n'7G.Wngw砇.褗n騧ꬷ.n/o'7G/Wogw/o觯/o HL:'H Z0Y(Cj &\t`Cl⃣K48#~02aJP @A.Qt`E)ȊT1;(P 9Vx!4,Q  H/۵~KȰ Ä \8ήIXbBg6$GƐ"} @A6.Yŀ鬖-jjkX5t&\f&$7UҤ]5gR իW*ЗkҪ ۷oD6m[p5aÂmǏgȒ)?H @3v$Iǝљ3&O|`[FZm|ݎwl|Ύ[:wkgN7pG'.AC@u]j:ˉ((O04Ì,)b6-32Տ? !/,' H*\0a#JHŋ3jȱǏ CIɓ(S471`*cʜI͛8sɳό-IѣH*]ʴӧPJJիXjʵׯ`^OسhӪ]˶mrsKݻx*w`pz Lpa^̸NJ X1˘3k2e|9Mb[ ^m pL˞MX Oz\Ɠ=K=屣kjI8ϓ_)Tq0C$TVi%B״ORw`V ) ̍^0ӎ-(R3&xٖ.kE%zjhV$} L ١VբۙRwZ QiN29jh&*kcXl!;+F JkUQ:mKԷkM䞫&rn+Ѽ櫯Ao+0l' 7G,Wlgw ,$l(,0,4l8<@-DmH'L7PG-TWmXg\w`-dmhlp-tmx|߀.n'7G.Wngw砇.褗n騧ꬷ.n/o'7G/Wogw/o觯/o HL:'H Z̠7z GH(L W0 gH8̡w@ H"HL&:PH*ZX̢.z` H2hL6pH:x̣> IBL".5 Zr| q@A Z؀RFy@e0| ^pC< 9>N90IbRbt@A%35C m$Ɋ DԀ Ă@> -pa tdC z h,|YP  mp,9ˉ\!\h0b@ 7 P|@XH`* r A:J+ ƌ0'N|.|n[ЈxC>瀆W^T q`*K A&u(>: TƤ'*}i7?d_PPTs@#5>"/lՑhxiB6 $)U:b `Ġ!@:7*p! | kX/|1,9.Ovٙ`h f8+\abO9 nЂ0)>ֱ"jX."aqiU,HU\9-. [Ȳ*LPf3 )2K] 捃 230v ?-0 BR&.́CB+R8Cl1AWud1lAh8T~@`|p2Ǽp. TH5M=nDڀOk\m+JO\ŧa}#y0o;/87(" G^N#KLv0̲ϠCh.pͺ׊Õ6]հs͛bNqNNxsǣKN=#f_Y[ӫ_{˟O?{'V_| X 6ԁ:(af] (Ah,b08ߋ2hcu4ި㎽@cD)ِF&d_H.PF)TViXf\v`)dihlp)tix|矀*蠄j衈&袌6裐F*餔Vj饘f馜v駠*ꨤjꩨꪬ꫰*무j뭸뮼+k&6F+Vkfv+k覫+k,l' 7G,Wlgw ,$l(,0,4l8<@-DmH'L7PG-TWmXg\w`-dmhlp-tmx|߀.n'7G.Wngw砇.褗n騧ꬷ.n/o'7G/Wogw/>t(>]a`UQBWW ]lЏUk_B?|d3 4KA BBp Be lB!0,  Z %`A_™3h0p :@]cG|6z$J-_J(q'Ks.kPAoU4'Ѐ!/,x H_*,(Ka#JHŋ3jȱǏ CIɓ(S\ɲ˗õ30d,|)˜/@ JѣH*]ʴӢh+)MaԞOjʵׯ`ÊKVaSEBjSpʝKݻxF3c7xΎZhBi$hl^T" BF'I&8 xHgc&>袌6) |Y|9'#H"(ᙎjꩨiFW i ڞaɡ* ת] *ɞnz ȳ+v2@% ̞`)~B;@'r-)(먈%@B su>'" %@m˭w@"и2)JŃzr#ro,8s -Z-F{2sڼPGhx7pX566 z1L5Ԉ74m,p!Vc5^[69bivNm'ɸtm `,Xv5 6 ^3/⹝褗:B㐛_ٛwy腛/o'7G/Wogw/o觯/o HL:'H Z̠7z GH(L W0 gH8̡w@ H"HL&:PH*ZX̢.z` H2hL6pH:x̣> IBL"F:򑐌$'IJZ̤&7Im Ad &t/!DPJJA.O HԒ 58$rb!4`+I͏&+RT- gFMYӛ8Iix4IO>rxs-H?Ђ APӟl(@P|>ZQz HGJҒ(MJWҖ0LgJӚ8ͩNwӞ@ PJԢHMRԦ:PTJժZXͪVծz` XJֲhMZֶp\J׺xͫ^׾ `KMb:d'KZͬf7z hGKҚMjWֺlgKͭnw pKMr:ЍtKZͮvz xKMz| #׸תs՝} |ߎqhF0`1Sa); 1$f`68qg x#mh=a^x1Dlb#9q_0+ yȃ`# _.kꀏ/ ;ve5y9|pA كr9+@@`! ]C8#ʄNHаCn|5Z,-]P'Xr + @p/X9"d*>P9 ePym~ ۰<\ P _s ?+ k-B@5ˁ|[ @j-PP XP hBUW  hvA` @-קݝA $e|!bP@< `P @Jr[`r@A&`/lbg 6hyA?4 F8 -@]MqIc >ׯs-`L!Oz A[ v(]; c Pa lη@w<3`n90`!lk0tVg pK{" ghn*{we^ZFX{ʱ:j=?Df(y8; @fW;D q   [KI`_Ր @5"p %ʰ ``6A {!0 0_ * U *r[(|P_+ cT_ 蠼7@" @9a`  &"!0,.L (0]<!\ȰÇ#JHŋ3jȱǏ CIɓ(S\ɲet$ ,8sɳϟ@ JѣPҧPJJիXjx@\ᓹٳhӪ]˶mx~l5x˷߿YʥkÈ+^Xo |f '1k̹Ϡ3F\2̡S^ͺk:\sͻog ڿ+_μbsc+\.γkνQ_n-0xtӫ_#O ?/`qhj~"%(VhւY S8L(,G$bh8O84 33D >5Pv8頓a8LF\6eWfd=(ÌhpƩjrWsx)蠄w Y袌6<ϜfVjA*ib駠T7q aʨ8gΫЉꬴ*ke9+j&6F+Vkfv+k覫+k,l' 7G,Wlgw ,$l(,0,4l8<@-DmH'L7PG-TWmXg\w`-dmhlp-tmx|߀.n'7GGA6S~9s^8 e.9B6pz?{n;~{L^2ބRDP}Pw)T5~CCr>{J(!O*KE*n P8KA:'H Z̠7z GH(L W0 gH8̡w@ H"HL&:PH*ZX̢.z` H2hL6pH:x̣> IBL"F:򑐌$'IJZ̤&7Nz (GIRL*WV򕰌,gIZ̥.w^ 0IbL2f:Ќ4IjZ̦6nz 8IrTU6h@@`~0 >p m8Bt"h|g<͠,(lv4 ^HBPh\(=UA| ZP-u}`3hAp||< (;MehRJ3SZ0*pD WV6X*RzT@fEZ_0\!B\ꇺ޵zQ xƓ@!u,^#VR>l;(W]GkPt/x i%B>"m `|V "Up\r;iŀzJ Cm |  0 l@ ̓`]a pv`,{xX7p!P/@- ]۞:!4cނP<9 h- 8Ƈo]LbuÑS6A VrD/r7ENϒdQn2媅/l!M[fh@ɀ@0:; g88q kXc:j4 ckZ2Čp!-,2  L' JJ(/Ä"% ŃhpCE729…3I|'WtnK*g wsgΟ:}Ui.МEUpiP@.zPQ:kNLN[3#uUlʬGf !-,.L HAE*\ȰÇ#JHŋ3jȱǏ CIɓ(S& `@  q.h%X Z̠7z F[ b@PHà1{fTCYЀ2p xD":PH*ZX̢.zG@d iTchdQ BpH:x̣>񏀔73BU3@:򑐌$'II@ކmdJz ('yIM@kT(WV``NIK̥.wK9r f{zIbӓ^2sf:zlG2I@ b "?AsLpvJrZ8@r,:OŽ INw`@9ϊu"4 @@ D-ҋޑ 7AҚ>Q9ޢH`KJ6Տ PPJUXhӀ1p_U*f'8Ud+^ֺ̊bS^BWxݫ`׿bz4V lU(k S8ҺjBZӺV]lY2QZkF O8AHm~{stuB\ɭHYC"ctKޚTwͮv@]xK_7um~`aojK`p @ @V`T+c `  CM{AxGH`pj[8_#0^AgL;#x *\7DcT{r0b&r6CkALgYxG%߾`{@P |@"dvG_~іoW~nT @SA C0Xia (I#UR_}}HO k`U1%3I'6O9r>up,T `|z@OH6V9}gdwz'YftTznTd|@'7poHGd}vCX؁'GG@/@ninD 5teEem~NhW;׋hL8XzugEL̘UX5hJֈTؘGՍxHv`Y`i]TpeЈI8hdGZ@M"| lF@-@XtC0jOHal } GM]dk-f;uJI~$l0ig$yo~-P | 5N5Ue=~WC xml ֔N;)$-0KD@7qTb9~`qOgi puTVv9VaPOjd;0P.-Zi[Gl)Wǖ`Wk-MHdS5f#䐴>Nϳ9)LM9Stȉ9yMٜ6Ly`c`uPW\i\ vٙ}ɝߘQ~xO@xQx^M8QUGzRAzw]TiGz%:V|ǷR|,(zdDٚ7}0:w١w~$IS~_nOtOH8x# @eqi(E/,:{DpɤM G60%(p`0aoyf8fLwBDh!KHn_ I:g G\8Pbh)jhFP phY0oEp:j8^PPWOx8Ox`DId L֞@t$F?, HP 8JjLyꪬ>ZL2TJ-Kү+K[r [* {[JEk)[ʱK)v 0:f$7HxGZّuX&dG;@ d 7hɴNxQ`5e %䝄PXZqY1JI?˵Ji υfh\ ^)o F)Zu[t )vG.1M}ȂevF𢋛V KTgG;o;G~W+@-0c{dC@Pp qkQ!ak" V뻾Ի+>J{Г;J9T+J껾پ J[o@2y{]I+qNZvZFehaunI2iu4JxI~肞/.IRXFbg pj1φsM/lR!PߊV8y0l؃ %bpR$ޢL Ҁ7Q2PFB]oŖ׽'R5+i/qf?y`tʂϖ|O_ΓSgzy $XA *ኀGE5nG!E$YI)UdK1eΤY͘T"By ‰# H8(K t犟xȀCDYԪZ)T "p[N8hk֡ED!`)1kU%K$@+gСE&]iԣu `Ƒ!C-Kc j{ko (PŇpҵS7o!Y8P&bǓ?@)ZLp@ 40z`A0@K;*+`A.smh:O("X˩B'a@Br+ 0Hx` +hrJ*J,Q[ I.K0sLL4TsM6TL$`:`<Cgfƚiizŗbx[ewfiz``&iv%h)ؼl`p`1f_&1ƘoYyyxu@ۗŹŖ_iA^\UbY'fk~IwpxrgVi穖~z꫷z~{{|7|W}w}~~P$` x@&P d`@FP`-xA fP`=AP#$a MxBP+da ]BP3a mxCP;a}C QC$bxD$&QKdbD(FQSbxE,fQ[bE0Qc$cxF4QkdcF8QscxG8!~dp5 uD #pJB~ tB q?a ̞!HFAP3`a(Q&4%*iɽUbap g^ h@C2* Kb -|ӚZh"@\ S0@sv~a .ΨܵpK,L B\ ]jBk+6a1XA'U0!6  a7T ؀ 0{na cC\+6l!e%98%y6 rm؂o4a 6Uo6aT6y6A gH$aH7L Bް/@9S*e5O|"lsL0qVچ/ o37:Txֳ#%M d#>2 \zqjT4 odm^*[Y2A^Ԣl#Y !2,1 H xA50>nHŋ3jȱǏ ;!AC\ɲ˗03:HV.Geɳϟ@WJ rOgЧPJuHdvSpک˵ոsD.dIlmȓW5ї̍U :gs‹<õ=s<\ ;||S 0 L2 }U߃syӎM/ ,0<:b\$#:댳/H]&hBU @2 "ЍLB% > HDB 4`Mvӓ" ?R lt@Oc*myhS 0%P'U)uz6j~SAvP“)jg:@@L3@ $Hix~hZ x(9<-3M;̂ Xثy+C;ִ˲4z)98[ >};M4 .m.HCZY  4L0Ɯ6K4לl s_A$4Lz,0,/s&<4-Dh,r$csEWm-qJw4=M@cmC{hбl uvsv<5|]sGS׀ K!Ls]8, Qco?S~یO$"r$Sx⑀y 5ȕc:G1~7ED~DzUc8 2Ᾱ`+wIwvȭ#=ABϵ';t.Ϭ{ y1zP7r˔ F:7=|/z3C8I/o_W؝l|=ѽo!i*d! ]@q3gÒs{ǂ(D f:@)ssp;ygS[5qwrSk"3Q. ?nj d|TG,$h0AhaKi@:7AH1$Bxx 1pvj! @+bF X `+ q!?ɑvRDF  {Sh@™Xjf1ا@Qt+ @,u@e< C 0@ 1S8 5QzSC s`Ryptv@JPUM P=BO Vͭr=@]WgH_+.L@0c+RYn#lOaAK U\|~T@ ʝ,emTCpB*לf(h\& mLyH `+t BR܀z*ݟNaVh)et]N"UCۿ&*m@(\lřsalM5qGp|[s񏁌5!i䠹&._$Se=٭!N"Qb;&-SSZ.;Yn=gx S L <^7Jgؙf_ވX@0@pp*p@ xP"X} BԉjlOՎ~ _"Yœ3zǡ?a{3HsVtHc6mT[P {Ͼ)]qN.& #½X`v*+\ s ^p  QA)uS x-3,)B{&x#2|nz H}E 266ƶ>kfL.|pg{pNxϻ6]oͱv]-n1a,8I{o~׶ɔ.ޛb>o<0v^-S >xR5^h| ˞ixFD '~?4n jqO/97/')FXN h_ XHx؁h ~8W&H",8|.2h|+Xԇ87G>=DXCxvfJI؄MƄPO8@&VxU4\؅[b8aXEhgHnmtXsxdzy؇ć8k$xChE:XlEH?ӉPI5~x~J؊e88XFVx58X^vȈiʸ֌8Ԩt x(؍8hM8 q9OXH;񸏱x؋Ydy 9ؐÐie9g&W"Y3Y#(i!ג.9'/I4yv):2_דب@n@3y?YXgHyMɔO)CIsJDY5ɓXyX)PIIYA]9i6hG8$֖uEb8oqMJFu[9Yy٘9Yyٙ9Yyٚ9Yyٛ9wc b@/:mgpenf]0j)Y,0 0+!,,y8 H*\ȰÇ#JH"Br2 Ǭ3gΑ.ܵkְi'.i֘}lf͛8sɳϟ@ JѣH*] F=I$JƱt S3MÊKٳhӪ]˶[)KFٲ![tqU È+^̸ǐ~[.^%xpȠCMӨfp̵Ʈs7.vIꂫȓ+_|}.`7\b‡7OgP>x$ 0AR( |!A%F(F@V5'L8t(8NHAΌ#@$4 6%$@0LH&M#]w'%NK/&*}8<tA8 5ЏA&4lix.A 4]lIP M3@*##UdscC@Ђyy^i^4RI Ad:Т4IHC^OjfB YK5䐓Vky$N88P/@XFŸ@$A%D;^{Py¢cA(Аbn`̬0$72,3@  лI#,X LSUw%}9X- C3ôceľ4P2̹HQ1 MmČx7간O; l2j# S$3|7:swp*/./ig:~KWQ1nND'd$0dN3̈́ӛEW V^ jo?Bؓ4xu_6*KBw:'i!H]0jͨD,eD pL W RЂsH?8etPTF-BB`PZ:A! H"G !opg!As0Ni~j(0l e4 CuX1#A% 첗U }l"иJ m5xl qŃI :4HR򔨤 8FD#+Q8f/ d8faA ;iHa*U򓱌4ioT#lšFn##,H<Ypc@fCvo@ ρp並7i5њqd:XĜ53@ϊZLg= R$YƸ! Bd -/ BZ@BKوa8iO H0|CR( Y¡آ\ 9NծBd ġ" d C!8T 4z:|k"`{Q*xYkR+>Vdu%䑍r0k` KJ0a-X1V"D7<n%՘:*Mrw Ԋ[ aD=dOֶꖷp p#Er^"zQ @>a||||#&%H;b ^H-2cn`I*و6ST"Y/( -U~Eř"LS5 Kp֑fP@||#$xknV/no:+.131y_l.P1wfӉ$ o7~П4%RD+.c^8B"|ؘ_}3 85"hW3NHw5QYı #zШNu ]Cg#ыiIS/Bv\ԦMl $a5a*yi4h^sږaFGb{:v]f'жCmMr s_6ρFK=%bXJI>!TʯP4AE(oD,Ɇd*ݾV"|{7A &/8J;`$ұCHqdƌqFg|[ЇNK$ሾfХ8o` a5~dHH8,eGgh/ - Ӝpz2.q-ֹN= oڑ[t|C^PX8q7y,(/jrT|W|!6"\Q{07P{׀-v_qz| X%"f7'#$> p܀؀"%1uc3 g>>؀ #XsCk+؂/b>vG`W ;nZ| rW|A1QovCjDVT"`M@  ϐ vy v!>$eh)g<l#Bmh)p z i{؇=8yb.#@8Xx؋i( ʸ،ȋ(2ĸ8_ڸ؍?S?蘎ꨋ(h-{ H0 8x؎︐>1ɏ`yC Fw!" ɐ&'Q0 `8Z0,p0F #9 xY%yL$)+y1CZ D!I9#+_ɏ`~PM99;pX9XX0i Z0~e9rI!vDfHP 2)ZP@yn)y x)}08 CP'  p0ٝћ8ȏ yY`0;Iө~ IyCQ V1pI9~؟ gṙXZ[9(z@`,pJ<9ID# Z ?/J@p7;z DCZdiIڥjcZnZgZ%@հvs@|zqJsp}@ :Zzj0 { *:zZʫʪZȺJ٠ :ZЊɺѬz:Zz*qڮl@ଭz:j Jk ;f1aڪ~   _ mת˲- J6 *kڪ`!);A~ (. S밬Z7dCO KJT˲C[٫Q{+۴O˳W Z{Mᵯ& l-+k۲j) o{Z)[x[J A O봃{Ne+;c+K-@[XkKkr;L *J)+k{ ˸2;;xA ۱k{TmKлK+vK K;Pc*s ˺*[+}; «03@ ? "̫ J q$\gkG몑ۺ `:<#B,};,2;1u{Fljk'l2̾S`KNPS,}{X\Y,V;żv܃ In{U+r<Ą\Ȫ4 |XwȚ=}$\ņ|ɘ [Ȟa)z '0w !ʣ'ivw'Fˎlˁy˼cq'wüľ-pɜi /aR,G aa\8\,l &;@ εu-p8P|-{ &&!1$a .}ӎ,+U8=nq!g %W@P}FTHG@`!Q`]'Sd}c]h_$nk훯i88*&Gdׅ~׀؂]HvgoM:2a~BHL6إ`Fi^8vHSOVY؞3Ԧ!={}} omMjۅۻ=]ܷܼgME?(q}=սlq}bmޝ=mDڝA}]=-]:` 0a5kn N.QQ$Y[=Y-]0G1aLP :> .NL^` RTAM F^ UZ~Ab>VVA'h`P0`oq|~߀h>NpYW>~nn>䗞9yNN䤎͡~%~0>X蛮뻾Ӿl.뽎>ƎϮ>^>ٮnߞ ~n^M.. O _} i=$_&a*,P0?2?7]68BD_|HJwNPL:RF :sUP 9EBC [ 7b5"v #CkPT4唢^qa@ HY9MWs L>C4PcI$+XW+ dZ|̀UX|z'F /Nbd1C#b W Y5f H"NhÌ5H4R ӄ41TV /axF5ZߟOTMKwfڌi!~˛2ccPx0@ІN 5໠UCi385b}"/Rc1ՒTC]<.&MF6h+'"ea$6 5yȌX;8/*-#zOV#ͻr9l|0 }?~hۈtۂܾm\V78#\p0zC{ f#4$e!H2A T+hA ؛k  A.a v[Ӯ$@d WؠB [h M9q ^4=9sΒ)"Wvj9^$I Y"@2 HFЀ!!C/pxc0f l6ػ.ZhGDAˁw17D ָ:x7 ?Re/}K`Sd3M 2@@ !  >P3 +H 6=J1!l&Hx} Y-s:'Di$0#+e.ag1r"ț W/O ;"&/4)Z:bKZWq+A{eR*AV>]5*6>SL mB2d!N5I%Eh8R)}R@UJU l]'B*t RG<+4wWOC:(ddAD:I-@C2ZO'ֆ4idh($>V sCB2QFn!8Gj𡀘@d+*0 \FWӥnu{]6%jC:͝V[@U Ҽ~^Yr^Lmj [7 Rd e9n YP)H ˩"~݇ pIH\D4N* 2 Y^kЂxҨhpB_:[KOd/.KLc +RK} ՜AʐaHI+<_/CZ7x!m!2޼2 dSյ9"VH"r@6%7zPMn6SN{; A +n|5^֍g12>jGO:i\j]kc=X>`.&/ugHӴ,4|LÇjXGv߷& fF+84)Qh=n3Բ hJ/x!nh1d(V}" Ok"x Unh1#5 #N` B&V&bs X'eR[Z,N%Բ=;>s@\<靊L0VvAza@A3L\ !ۄũ!P2pHL+;| #ȿ9)p$j ,g(->L%%a 62#o bo E /nS}Ou-\ i6gPY({*b+ eH8E2aAp-K{Upgۋ,@`&3H|>@%A #Pi.8@#y6Rقe!ҭ0=PA<z'+J=+7WٽAhiqy:5XiRA#<8ۓSi,0a:9|x VD>1@9@2B|3k?+?c.A+: ; zyEat#0UƒQYa A: #J4c˔5H6Xtۃ/P:8žI5Hhi%a;hY6<`L-X4<@<-_c.RJ7F!68CzFhgVS_*qq a6rLz!R-tyă0c 45^[ GnMG['%GhFpc:tG3ǂ̾3BAG:;>u+N+3"9>9";ƀFM3G|X2)2dk[ž1ydX>:@AxKC|0*29(EYڂA<0|-h[9𩃨Jz: B磗-)EڃJV8Z;d0Z0#lKA4AD| Gl*EtG\yLȞȆyq0HHό}H ~U IS:ٳ6M N3G,ɀ\ XNPNNp{ΉNPN4*`ekr$qlPnXp_jHt8sp xgppA$q*h_(e`dH$ak`q@jtŇMh`f P̆lqdёkQEdPf`%MgpfNe4OhX Mr8+UeH`(4ol;fh*} "OpSN`+FeFNlI]&-P\SqqӝHkh_Q rp Q݉l`i[U`(b@( b-bŇJU䐷؎1TH9λX舎0 2ցV1o k 0u Vv=W1QOlPBO WgM8Ws5 y yzW9fWր X_0HvxW-W Wءx׉%qVY %Y]Y XyY,ٙYuX!.,1?0 G0*\ȰÇ#J`A)jȱljC$Dɓ(S\ɲ˗0c)R͛8s)rŝ@ :3ϑD*]ڒfHP.uh!X"4Hhh * 0?d /_veidcx`W!` ,0l w6bn) 2`H[->eP wǒ4%lBs $*ױeun4H>@ls6;\NWAT+P^6 TB@4pI%4I|^7Zx0FX R}xW(AY0@ @nKzĦ 6H\K@r]J  (]f"L$^`@ eSPA>hAx͡Ѭ[VVx)[Ś+p ܆z4H'R60L3z(7dI gr`p`jLXA*>:8 +RΞs868cNN^O36|Nd8ܒk.6kM o8\c5D!l'| 3G, WlgL8/l0 q+0,4rwqs,3\DLL7t0W,q`j?4I'dmq ONW&K \vAHc;>6ur_ĵސtp11k~D7Gr:dt q$Cnz0NpR q'p$A0\zw,{ZO ~(s3=lYϵ^^^/:lK:ɩ xC87܉- <75 :ƐnvCx0F+?@T{R;"kyfz #;fP ߇0|=D =@PqSY\!5<OȖ2͊ VF3,ldD1VOq8Qr opvs]ߌGN˛Ԇ1q2 F NrBdwYH5% 򕰌,gIYf̥.w^ f` fP! bC4YjZ̦6nz 8Ir,c*2f;|`F4 ƌg @O{~m31a@0@iL0g4IЎzHHG`8C(B́ iž8ᶑ#E1dTaKa*SHM*GtSF՘4RՎZ4;Y` XJֱę̂NUjViȫ^׾ `K5i]+2!-,1J  HqCȰÇ#JHŋ3jȱǏ CIɓ(S\yr@PI͛8sɳϟ@ ϥ@\9PJJիXjzP>op Gn\Ӫ]˶۷p( p.(Z޹ LSջ(>KL˘J $]iӞ:(+ӨS^ΟC8>YZͻVKKAW+_μ#>ܜ,]{ν'>vl.u+Q8JO8YԎ/K. (VxZx 0\c`D$(oazH/% 8=~5"H&5 >\C/T37p74L5X-7ŰW$Lp$RRi%Zrå`Zc3UT19b&脹3d c,#7:h-c˞t$b B'O^_#xJ7e3N5d 8eM50L|gygc8-8#9c 7,8'Ì8 48̸X *0{ÏS/߼їo~/ yT˟hLD ZP$̠xzp@ "#L w + vp8 wP< bH ,&oPX(ZT"jY2mhL׈4l#ޘF9gtD<Bk]4"ÅH..j!IWIҊd.EMzM'GP.)VhEt,SK"qKY2 s~Ha9j$f,L@\f3gFȘjJ8jf, rJF4:)NliIӇgjQT'$IWZ05K7Ӛd*NA I BF#P[Ծ:EMSJU7SVӜnOJֲ;GVum+Z*׺>vr׾~ lk+¢MeZ@E c RD,A* zV.% :Ҳ%!iWQ-kgk# nb[ U n #?t@\VvwB!˭Ae &wk]&I* AG{ߔ +Bܦ4MIR Y0A'GX0)8ݰ%(NW0gL8αw@L"HN&;PL*[Xβ.{`L2hN6pL:xγ>πMBЈNF;ѐ'MJ[Ҙδ7N{ӠGMRԨNWVհgMZָεw^MbNf;ЎMj[ζn{MrNvMzη~NO6 lh&|h]~C@-H.x gH9>Rp'8ŵ`r<_v4 ^p8Byp B0( C-` S3<ꊒ>~k|epG6 +l<~P rg{;\ /`*\ }y8osmW4ңl1 ~3{gw߃j>B?1>АL@ IBL"F:򑐌$'IJZ̤&7Nz (GIRL*WV򕰌,gIZ̥.w^ 0IbL2f:Ќ4IjZ̦6nz 8IrL:v~ @< ^`| qC@2l kꀏ/ pP/І6!)U΀4 yr . -DWЂ !E-/(U@Lu*Tр5aQ-`8@ª6hMZ%E+paX [8X `uІ 豑-daC`\ 8`4 mk"60W3m8`P.0 5(>/ʽ3ySπ4.ft[]TI'00ꑤ0 ` 8 g#h2o5D8ZuchHvz="XpH-"o&7=iC=m;CNQnwÛ!2,qYd̘[@*dС@1:c })RV8 XɒpRkIDŽ3i 9u8ЕDytKLj(ըM2TVZ kUfrOsoZ)[-!.,jI (0A|\ȰÇ#JHŋ3jȱǏ&<ɓ(S\ɲ%E.cʜI͛aɳϟ8Gi@sHӧPy %:իWjʵƩTJv׳hrKYKnMq={A$cmV_*^#^ϤTBD z qϠCCDۻɁLHH͜=M1iӠVΉk "DD兢jN]qP-߲S2`@U^ݺ˟<)v|p8|CN;$a (h`/v&[R( 1ӌ2pZ~#!Y!(&~ߌ<ʗ@13:LFe#=6IR$LVNv9]-PJɌ28/L;^I[;? dfΛ\)hu|`hh6裐F*餔Vj饘f馜v駠~jh(N3dT行"ꬴj뭸檫(~jJj6쳷ljBv뭭Ҟ ߦB[Rj++^.:/šm'۰k0 WlŹJ F\bl(o( I ϋb24l\Dƛ<|0 2l|L7!DD[4#;BrpLťq]2p,W ⢭nMrr.8GN!Ƭ6߃G.9 Ȋ/u֎76.Pgkޛ'@d5N( , /<|O0"K 448sN:TzOd\2hAw/o觯ǯK HL:p-k"$f\̠7z ` ^0(L Wp5 e(Å8̡w°"3 {H"GaF&:HH(ZXb-z` V0 pV1p8@ g܃6j [ p9N#"\ %E@B Nzr#5"NTBY ,gB=B "iU-C,iIbrp>Nэ K^ ̦68# |"*)m#0B"茧<;7T`=~3,?JPqqMh?: C'Έ>զEюs H? R^ %(A]DLHFqC 5AxLQ=:s`l>P "8*bQo%]b'® {Z9JΆ0=gGݠi>mlX6Y8v3lm[3ȁary\06+tG銡#U@V]vwj W EuaEnzGʫ  c<BwXA||7U4xwB0  ^GqH@L<GB\hMc=6`Z@:*@'u<ϩ!,";,p`BD)a yV2-, t؂Pf}`AáT0-[Ȼy9nC dPl'1U~NdEMj3#(A r0@ bBX%A`@(rpCL@.Ma7 cSmx9ǍfV9}sqlN@ OdFp7@64R@Iiw Ydԫs/<nki/o `G@ L:j) Z̠+8.l GHBz* W*(a^H3@ܡ+"$ۄ&:\=*Z.zi٢2cLt6QptH8B<5| /BeL Ȼ(_#'YHZS&N^r'GP+Le"Oʨl,Zqt-w \R) &ILP,2fqФ3hZ%&Mh48Qrp$9יt#'IOQ>~Bp5?EAІfqtDшNh=1Qi i?Nt!$-IOt-KMS45MqSn=O1kEQ/T.UMSUeNաUU en]-W_՟e%YVUm5[W_Εu]ٙM!{]g_5W֜dayXp&v-HcXC@#fe-fs,`=KMQ%4M#QjY#hD0lIں 6>rKS->`;W&r[A d[F7ӕb\75 X2KlyhWE{y _%Ra׵ ["!w2k`!?(\&Vej6`$WX.!L,B|8 n(_T|X1>p,aq4F%MvUխva>YϚ쳵qk]m&e7 &Mr?&?u{w3L$I2x+!r!! "1OE?AE7}P? կr=Ea $qOFg1F{qϏб_}폔GG1џq?J+? 8xx xHxXrqfсH b1$&x^*,؂P0K8T62<;GBXDXCqHxJ5фN8P1]Ր ؀ ! A=z`DKaX\ ^}1{dh~jhu ^<` 5|QnqH}X(h׀g؉mlhpfZX~p_@0`?\mpg&hX[+Pm;U(H&h+pU x P(Fx`-Ap8ZpȏhF`pyp^mިhZWP$i~*Y(3y8 kPA@)+ْF Hg @?WP)yEIxy^hD1 py] Wl gn rɑC(Y !pWДU  gko `Tn ,,kE`>_{@WЋymfuPr@[ e\lP_[М fmog9ٚf_p\X_  dvy  :͹J ʠ `%q"Jg@  c p#@= uҢ_( N mP;EUJl q؀[l]`*3\Q&vRZ &njOʦX:o!*,(p A_)T _#@bE|%"ȱaFrqh_6lRZÖđKTK9c2k@o̹Ϡ0c7 &}'cI|@bjU:9Af̾V4Y`ιs6)J 'xj2u 5=v‹HŸXR *>EN|*FV7U"FeV'>ep):u֫Vs% !-,V H0#P!B >0"Ň%^q#G3 (Ex"="W E|:L9SKY6)HK:l^n !/,x+ X ߳Y9r]f _6te,P"i6^'.6ozIlNV9S]Ɋ9\5knMi٤UKHUfВ}g,(Pqn3[ .|L'jLܸpͼ*j֦c֌YpV+^̸ǐ#KL˘3k̹ϠCMӨ;haچ#Nx1F>XȧI*YY|έN'O@ %jRg52V-[;gΦU3r_} <(h& 6XjEYjBB4Sq&Dcn+4L8qaM7^I2Ȍ#O. Y͎#M8&ق;B|(3" bJBD/lS;ta5( 0s82Fp%>= 4Y 7x1*蠄j衈&ZLXBb%0&"h3C:bόX*:v4Sڧk X8xacyfk^曠ٗx>')+k.g rn_ nF (ۈ;ĈN5.M|;kcj K,* : g D7dVBB,^ H $0XS %a}HY( G$J+TWmXgX޻"[" v#pJ$qیı"Crd&Y +;!\9+7( H_I@n~S D$-/d 0Jnk7R<$i8Ȥ3j0*<ȲM݇/Ҕ"a!%'(5j Xp;Th,Nf9 (9! ,x@6z lQmWij?,DS!<51T˞7(p,CF6zB tr,g G7{$mQ ,PG9:x̣#0_qoĿvòթ=ΨFJIܰ^vQ<$YHg! c!Ց*_؈ >ڑd)=la5:˽0EV X# yOWC)ވG< 8inx+h/w NB6g=SA,>JҔȤabdr$[E[0Ɉ[1)4wN,Cj$NwӞ44D5C,^9[(T; vz\,n2IDC43Z+R*$",Tq}KY h 1GW ,0F1 `a8 vQf74Cm䚐˅H-BGR5V%wwf4Q':VJi[1j r-zW 6"tH7gb YΊXw ,(pYy|hN(C,F84g0H(:Ƒ[,d"F C]DvQ:f!T vF iL-F,,&%ȅXQZ@}Yi-m!h,HV1b0(> $-,r:.{`.W}_qO闿 l`` 8 UhI"RΑ qHlbWC Cql02>a yF5,c Q]DI0:rrgMZAx uG5(b9p,x%E`>_ ,iHH"ѨkŁWb#!(7Q jxc޸Bj OC*wX-C0/͝jtm2^}]H鲌'!"q(O=Sb/ c;f-E4H`Cј:1rf-o`{!, `CM0Ɲp\+~q^Ty!.F4[LV,hv|O89O[%{󠿣!ЛOFɫzǗ~Ͻwϙ?|OMo|/Џ~/[_>TAO̯b?OHϿ{ xT||X' ؀؁ "8$X&x(*,؂.0284X6x8:<؃>@B8DXFxHJL؄NPR8TXVxXZ\؅^`b8dXfxhjl؆npr8tXvxxz|؇~8Xx؈8Xx؉8Xx؊8Xx8E5 8VQ0،a8Ca2 Hx5U5ЍX5@E@؈LP X UaL `9. @R@ ِ0@y  "9$Y&y(*,ْ.0294Y6y8:<ٓ>@B9DYFyHJLٔNPR9TYVyXZ\ٕ^`b9dYfyhjlٖnpr9tYvyxz|ٗ~9Yy٘9Yyٙ9Yyٚ9Yyٛ9Yyșʹٜ9Yyؙڹٝ9Yy虞깞ٞ9Yyٟ:Zz0`-qǠࠟt$Gg~ʠ #~#h_`\mgp8z.z~__pW_j`Hz;:~=CCZG8:~WУZ@,{lW5ʉm\bk=X@i[Z~ymuoWyTTn_u{@lyPyuT{`@Ay Zzm`lZ`y dmmplZSXZ@~yWpUnlkkУS`PDP ] @!_jObp_ЪZH//@[qЉ0y0ͺ+pUXD P0[!p6`K0ej@{` C bpE+,hZz:|0T[V{XKgpg tZPAz{W `-A[@n0'Oj TT[8 T` ` Jk`,{ڪ0~A[7ʵ*(XB[Z,[^n jpjPyF0 JTz;GP 1TaZ^=ڧlУP~J4+{f뵷b\0 pAkr@g/08pp]@h|ʴ7y@[[p˨jWgڭnZjk[z;qȺcC W\\M̴Z yx10W]m*˲8:UQ/@Wp˫jPAj[ItWm\ȦzlJ\@B{rۉ3˴ yo[\FW jǒK Aw\yǾ7\̉ü8ޛ|^Șˢ{pzP۾7+@y~Ĩl^ U_g2Ly@[F [jC[ }гxœWlЉڶ7a<M@JZphpOJ {UP0/PiTHUjԯ]g0hәذZl[[`T0[gx0 ;(kp Xpj Aʵ7 P_ 0`=0[03GFjImG 7-b0cՓ^h \Zij}b Zmmpot nJt׊qgx~}|sp_Skڪ3jW*\ŜˊgjeJ[^0mQ[{mܭڬݦȝ~}כ}է{n0Jh0,f#Ī}Mm}ߨmj.}^w JtKz|s1㏎1`ʗ-żY^Ο==ZWҧMkEZ\{/fZ6!W, /r8>s [p!&l! Qdhvqbȑ$?܈“#]jQfƌ-U޼SN1u4s(КB5J4O(b/sj֌f!1,/ (P\3hnݢ! 4Gŋ3jȱǏ CIɓ(S\ɲ˗0cʜI͊*d0bĉ7 JѣH*]ʴS0 ̙;pŎO|KٳhӪ]˖dԩUfCm˷߿$I’„+˘3k̹#aÈIZtdx;^ͺװO~>LxPǁ $@ NxوI~5eУKNFa?zm.$&}gNWϿL'= & 瞀ӎ}>fpb_5s,v v!<\b8JA"%I;t_PF)eLN/$NN`y/i斒'l#g$Dx橧p9Cuv砄/Ĺd8s7H3,i襘f"裑3jjeϧJ:ꩰ*Y驣:뮼jTf k-+窸*F+F.찺NV+lr+z{-䦫n;h+I/9.b'/|&'W_gtoDZu $o&r(*Z,,NL8es<>-I@mLtPtTWmXg\w`-dmhlp-tmx|߀.n'7G.Wngw砇.褗n騧ꬷ.n/o'7G/Wogw/o觯/o HL:'H Z̠7z GH(L W0 gH8̡w@ H"HL&:PH*ZX̢.z` H2hL6pH:x̣> IBL"F:򑐌$'IJZ$k\֨8gCQdJ< JQҔ*QJkͨF6'$e.w(): 1%f`6 SGgn>$mh=a^fLo*$g9_0qS,_CА< Z0i3+@a! ~8!{C?=$ F4mx8p5ZB:- Ӟ ZCNo.tW @ HӴ=O+Po< "#H`/ajh8ъa{ z\a ]XҀ`2p>,h;-PP E+.U *թ95x-4 (n@5A l28@>0 |a lK@H@7 P@8@ڰu@ p a^B Үa @p`5|-o+|a kC0zXH \{C ) l  Q:!ѝE,q&b1 7 80@ + 5@4y]@^``1T6C  OڔBB* 6%B>`  otXGbT# b׀48ؠa"O.˾-@P7TԾMh.a{悙R8m<`Ղb-3<^ |̓*Mn4 >DX" WZYʦyWëb#ȚbV6f] ,]3ŰX-@ e֦Ş5jhEܰd6Ή loB@X8 \mT@ %-J4` n;d6rflj9uu6^ m5n:q`9/e!a W0jh#S ]Z|nH69vTICWvn@wDoltl;봳K=G-d:5"7e-drkp߀hw!uo⌃7xxމ7n嘏8Ǒ=9ߙ.mnuy#6鬷V S箻NOR 7<׾W;yw}Do觯/o HL:'H Z̠7z GH(L W0 gH8̡w@ H"HL&:PH*ZX̢"2W/#5 X06 fDm:ƍ qHh>FL8"?ipF 8$ H# Iz2e`E)qI)"*/ V"+]Z%.m|0L]*f.LP)3͌:YL|@SS+Mjf 8IrL:v~ @JЂMBІ:D'JъZͨF7юz HGJҒ(MJWҖ0LgJӚ8ͩNwӞ@ PJԢHMRԦ:PTJժZXͪVծz` XJֲhMZֶp\J׺xͫ^׾ `KMb:d'KZͬf7z hGKҚMjWֺlgKͭnw pKMr:ЍtKZͮvz o ѐ. n8ڀ5X#yKPP3ؗa(׿%Հ`ݝ hpA` -WM { mh3w'N~5ab-`8@r,g9?P# ye)_ Z0 -`@`/fv,`6Gyp&.D Bp+h }DNyp6hWkB8]=1G6ԤCWYִqMM _u |b@6,LnrI; F@( y_5|a ] rVpg|x@f+\ >p#\> T+ X^3 ]8.:9t>Ȁ1]_Zh'zHEӯ~}w$ !],!/Y;]5`-7.4lU-B`Ƒ5`ak X6(SȲ˗0cʜI͛8sɳϟ@ JѣH*]ʴӧP $hB!Jhaƍر6unIS6۷pʝKݻx˷8qM7t) ZGN;P2ˌ)0 Wi03 򧖏Zj뭸kإ A 3v*$8 (fv{7~p`B T 3Ÿ'^ބˈ gpt2Z[kWlœ2ͨezi}1VzB'B\-=c0|7L(6L@#.|}O,XXs,Ί̲BG0ӲXg֩8sN1Hs8HK;͔e9X:|36> 4"Y;Ws-T8+@4Wn459L"@p|'H 9yw@ z N4>(oBB0 mv08afXP@ H"HL&:PH*ZX̢.z` H2hL6pH:x̣> IBL"F:򑐌$'IJZ̤&7Nz (GIRL*WV򕰌,gIZZ/A l@h !%>ɒa 2ɒ]3t2]2L|\3  A dprE Ι,x> yS: d}tkT'!PԞFaV%Jђb  @ b$-!R*B4/RARYNJԢHMRԦ:PTJժZXͪVծz` XJֲhMZֶp\J׺xͫ^׾ `KMb:d'KZͬf7z hGKҚMjWֺlgKͭnw pKMr:ЍtKZͮvz xKMz|Kͯ~LN;'L [ΰ7{ GL(NW0gL8αw@L"HS6h@@`~0 Y>p m83 {r 24uM~r͠,(Znv4 ^Hf5`ap,%/U^ p*% H>- f5A{0<|ɝ4 A>PTZ IO N$`Yfm4yZ0*pD WB6ġX5"MkJ X0B}6[>w 0@=o?}7f ..;Qfr!,Ar/oK:#m6Z f bF8Ѡr-() fnyVԺ5[gC抆< ^ +Pdʾ+^Lm|YCt׮=ƀ*K CX:P:n®3`yS{O+<ApB꺆5 yo݀5,P]BYC -a_x_P{=c؂=A SCta\ƀ8Gkڠ/q{ MtMgO,xY``pm`rKVAW8_PNvv (`Plhuz2hWW ΀<Ǔ r ՠ Ā ʀ P ЃCk1` `܀X<8 IDc8egJ8C qc q@`׀yHhGmhD8 DԈfX!2,B/8 >|z] X;qrL0sȑ#8rCIɓ(S\ɲ˗0cʜI͛8sɳϟ@ J(K`.l0Ċ3vѨիXjʵׯ`ÊKg1f[P9gÒ!V˷߿ Lpehemܹuݨװ˘3k̹¿2.:uQ&yrϰc˞M_хͰ-oFM]kq+_μ{7Sqھ]P'O)Nӫ A0A?O(`W2$  J (Vhah_ r 7ޅ$h(& !6b8 IBL"F:򑐌$'IJZ̤&7Nz (GIRL*WV򕰌,gIZ̥.w^ 0IbL2f:Ќ4IjZ̦6nz 8IrL:v~ @JЂMBІ:D'JъZͨF7юz HGJҒ(MJWҖ0LgJӚ8ͩNwӞ@ P񖬅,dj+Q6mcLmjս9;V{ծ!$rGX꤫h=C6_%kYw֮ق (W i!!a+ n8>=l ?\a ^``AqhGY,a f=1bj ݎ^ @>/}P/h.A iC /Dv ..h  Ϫ uG ԋ$@xPW~pkTFPGCCqG !qAp-!00+Z0CsX" KT `Ap0$` 9xq?_:<Pb/p!7|]6h!q@f G X8H0,q0fjA q=D/g8 yB(q6l ^z X0ЀM_VF4+xY 4ɼ3/Ph5| daP朇647y8.|Ӫ. +ֵ}r`Ww h Zw*l $ 8 4 .@t#1@9&`%/ }@ ?ej=e Zx۰V7P | Z+{ 0+ qcl6j`,u-P풁 {oG\fn:ճIs ]xϞ4` 8uϯ=0hBr\ (p6 -K̅`PS}mB*vw@١]Sy[a//' hiccwj kdYח}&` o 0/pz@~~~bm&7 `Um^[zet[ZeVζThk1p'</@Xhq0XFpps@u'"%x(mh0qxxgpy2~8Hr5Eu^p\P{kPfq@uGwq\pVgCTgu\`(mbV`Vl.YpvCwuUuWw]qjhBlz]VmgY`eȵщh[HfeliŊh^ GTgXXkz8!}!$"r ` p ̐ / ϰp+ @ * , րБ @β F@ 1$S"!+,Q/U-\dϞMM;w߲L2fզa;GBIɓ(S\ɲ˗0cʜI͛8sɳϟ@ )A :(E9~8իXjʵׯ`Ê=)3a8۸qΝnj8r5Ju߿ LC&0W3dÍ7dC7p]"3uB_em-0>^se$2dM5"<908sr4xWy5/9./;ֶq-.SKJ◯/o HL:'H Z̠7z GH(L W0 gH8̡w@ H"HL&:PH*ZX̢.z` H2hL6pH:x̣> IBL"F:򑐌$'IJZ̤&7Nz (GIRL*WV򕰌,gIZ̥.w^ 0IbL2f:Ќ4IjZ̦6nz 8IrL:v~ @JЂMBІ:D'JъZͨF7юz HGJҒ(MJWҖ0LgJӚ8ͩNwӞ@ PJԢHMRԦ:P=8 w@\8ŪX*W;fVʩHZF4$+І6#jאk< _3]lc, Me٠A \!_Ђ?!_mH!sC96Z؂`[?A ZWlk-#``WP֠ܚa-N06 \C^-`Am|;4gm >\Gn`Z6S0" ~؂4Z  Ӯ_xI+_jh/lgkb y PL _7 op(a ]{XZqa`\@"` A`b<־eCvd!r-daZ$…5Ur0< ]B']կlC#0Whbr}A9r+=ā Z0&DDpb g(%<%y+Pk\4.~00W1L`Ȧ C$] f4A.^GH|̀f#B_=._硵h(-qñ_(`,+[fa=궖 dm5Z" DX[7 qP P\ ߕ6.rXTzxoZ[xYzNτT#֢9 7%=No^oZZrC:nI8bzo`guU<ꥆ3lH"I Hf9^(&ThaBT=H8\cQ,x28_"ZC7r-ø#L2#>4(>?]#98@4I73E4͓QN%_4 :Qvaf3fR~ΙCpr&tםC橧T|yfzIhq2蔇J!1, /q  H*\ȰÇ]Nph:WlqB ɓ(S\ɲ˗0cʜI͛8sɳϟ3%R1b<\ ӧPJJիXjJs\kӦY&y$yoHf\ʝKݻxݛ+Xd͢ -!,˷ǐ#KLɔ57ݬi$ J!+wD$a.˞M۸sͼYFH "@lУKNu=-)j'2 ]_Ͼ̳$&SCRBHg&1L5մ(@2 k0($h29ZI;nR<2H<3\ "b H"8TViz I5Ң096Fh8}M7\)Hb4T!矀*(>n9pwg `HF*餔h5G "W驨jnf `v!骼YMD98 1&k2HR*|"=*R;f$8~3~BK+/B[o5P3 8;֮&¼{oC/>7L; >-$l2\/Ă3;83)䲽- 92W;' 8:h 1\4PKMVch=]Yp}-xm߀-'NG9._N9>go9褗n騧ꬷ.n/o'7G/Wogw/o觯/o HL:'H Z̠7z*E0H d,AAj kAl`8R!@! D!DRP? i&X+ Ă0ȢSU VOQT c*( 3p̣> IBL"F:򑐌$'IJZ̤&7Nz (GIRL*WV򕰌,gIZ̥.w^ 0IbL2f:Ќ4IjZ̦6nz 8IrL:v~ @JЂMBІ:D'JъZͨF7юz HGJҒ(MJWҖ0LgJӚ8ͩNwӞ@ PJԢHMRԦ:PTJժZXͪVծz` XJֲhMZֶp\J׺xͫ^׾ `KMb:d'KZͬf7Y c*K5~!j`71d\Lh2 qjx:1$`tvi -9F[Ӧv1![-~H44Q,e #(Vf0c8TQdŮ@]r}7@"Qwjoޫ3ICjG;QZ\(8!`88"2Y@E;r;LF9! `CiAhD)!4A W3Ϩq"]08z $5P;fAH ` nCH6YZp*;f! #  "1ABZr~0m8KEG- !X,y* H*\Ȑ8#JHŋ3jȱǏ CIɓ(S\ɲe@ct貦͛8sɳϟ@ J |Ҫ ‰+JիXjʵׯᓆ[МB ۷pʝK݉'nܸvqÈ+^̸1ݼ{Fxlk̹Ϡ?'thpզśװc˞}rtөW [6 N\)`-УKNJs/WnN4`[O}c]Ow٪oKo`'hP3oF(!F .Of X!($%,n/f34~=9,ȍ7\#2LS4\3 0(L5S5 810cΏ< 03:#N6 2u 0zIuZ8d<0rf6o%3`8NZc (0Н~L|馜b3֨]88ȣ@ 9(DL: 4:0e;p%bhfT״N1ń [٩Y㋟} f (8 S0DiT\ +?UV9(̿j #A8Ci8faT6:27 t 63AEnI P,ࣰr~ 6s+9,߷UJD͒Z/mLP#2//`fvP:LJwq"O/' >)3d8,,1,fT6:SdFnAڑ  {sj$e@9>0-M.rM/dI,Ir <3/D_GBI=\S,nkKLYA$K m$[M/Ps5 > /dJ -24T ssߠ]hm]C9A$8ql |7 #C@:'%ު ?qp)AXvo|cX >_ L < &H:  21\ɂ@N^o0fȂ54iXC #>!:-tJP5%%~8G1hp1HveQO*r2IUhF_녇؈< XT 7X0{G`  AWCm G9W\FюKfr,gU2qGܞBwP  R kIJ̧>5(<Ć5)d[ k.i7ˬѹQ t XhA4O D J0e!IӚJqDBЁ^D }f<,sZ9ю~T ,x:D(UHI" ZzRb[6 ǯ%& b; 8$DOKF5 qG;Ȣ ^J)B9J TDר4 .rK5[/=+WO,>0 ,2bɎG;.0Y| [ж%&Z#>Z6QmsKvT暤5Ʊ/hF# uxEʑ 4 rlGj 8 kH#6٤>qے,j [M3Jc~oYFncDI783zQa,n=XbZh5nD5fƍs``dWCFwJ[z.&.H~)'L#}׿y+a2ɉ#P=ֱLU `ˊ5-'rkT1ӫs( <|:,ŶKu;P+gԥ# jVIL^mf]sJ{:1gF'd#XPd6>xX#XzO".r(K%*!JH9G0|B3TC@_ᛀ[q4sa_h6NF=Hc/'mP2"ޠ <88x`Nw/'̽B_<׹(s ]DѲgK34Nb1&[XTrB b'A[]+պVQG+" Bh1z k9u0%Ά:XCЈdi'#_5FJE`@xp7(Ap{Z{$Y[Ira] |6kΐQRp}}հksd-1I' p0\} -w% ` &`RJB1\QSz  iy WnA%WqˡyZxfW(Ҁ ) aLxxN8'SC %T(*`} 7l^(݃:0% 8,aA| "lÆ}p3ˠMϠ\XTRspAP<}'3ph) ،8^#y`T&"`t(b8X-q1@R 0ʱ98S D'9HC c n 1Qч2&$jʰUAՍ0)@~ P9)AI p"c6W :/a/=@`9yx T=Җэ H Z@V~-ՠ(@%I miH7fɸEhYH2!1 `@E`ٛ  MD1FD 4 rG 9PRgA [0 :%0R 2@>zIIq `4Wco IL@%SZw  @+sm-& P+T~Wap}>% I}I` tf4 ׀5PK)W@t SX nx'zkL2r zg`g7M!b Iϒ(XbP jYА-ac [(b gP秀:!3pm1sqhׄ!:c@+q- ͐  ګl0,ꡪr& Ӑ#4'ںUT('+᪯(v ~@u):^O 1GUtzנeW3:# a ݀  Jb(7v۫ Kx O笎Bf]ұ2%K!986>Q!w@[2+AFLR{JaX۵^;d[f{hjl۶npr;t[v{xz|۷~;[{۸ug;G{s۹ù[C􂺪ۺº+[#Bۻ»[AƛۼL[֛۽[A曾۾Yqa5[G@@62.Q;AqEP |Lj;+L KԻ l$?`.<#%,6L ? ,L{DT  #H E6 TLP Nl5,^Ĭ b@Pj[]p<mvsB||\y{ǂ i<ȈlMȎ,Ə|Nj̳<ɘLɞɤUȥɡʙʒE ˭,ˏLˣl˯|ʹ˓u˪,̻ l Z̓+͎LClq|݌΃<|Δլv j<|QL6=l\ ==]M̵ "=[&-(޻,.2-4]{8:>-@Ծ;DF}ԶJ-LԮPR=զ[V-X՞\^Օb d]֎{h͸j֊np׆;tMv}ׂz |~׀ͷ=z[؆v،Mrْ ]n{٘Ͷjٞf;ڤM}^ڪRڰʹ=F[۶ >ۼ3]{mʽͭ:ݫ}ݠ݂=_Z ޽]g]y-M8~L {>WNw)~r"~i$^v(d*.N_054V6~j:^S<@OB-<!GI.( M޻Oη&mWY7x!rqd)ghmm drm"gpmy0!z}"胮ol0.[m0VPnrlZmnvpjEb`FCb0tmqPv+tc .r.\.!j~dPW@~_@pkqW`>W\ r@q]mp^ ~y0m`k/ N?痮VX` NO_2_8?mlgXOQA 4?վB>Y\{of/k?kP"_ g`pom~Ns>35gVWs*oQ~\ /[On~B9o^6/P_.^?G/EP ѐ>QOP/~` O_4 o.%/Xz/~qAc!x > m8&a+W>waB#l !qAm(dK1eΤYM9uӧ3he+ใ #YdF E7.xic$?rJ1.ܲrcpfdy嗵:Ťւ-z[c}h LJWLA73jUPd˭nș&Ѵ@̘/k@ ׶^ qMrΤD\qȕ/gܠP; P%QpI>>U[3/O5_f'l`sϓNMfĈOE&j|`h)\ 062CH*!(v싢0m;|ؠ Fh *Z,x2R{2"D#ŐQC |./I(W,J*|9HscX*JBOSB8B4Ǥ8iC+gz b%4苸r+|\[/>mRG.;|( .|(ϼ90m+DQ*3@M3#f%㌶ LtZZlsb`%@M‡05TT+krr5+İ hO'^!i>WB8Ƞ4s2!.=Lp1ml2,A髜I3Fvt@&pIwý(5!XAP:p(wIʶ ,yC&g)yD Gf+@"dS`+UWC3СArE(i31{Z*Ld !l Jt*;/&d4bcF8Qs&>X@d7 3>H!$ D2 dW%-'O+]Քqn_a xu7M:1H%8PE$%mpWB@tp$* &b˕4r%ć tbamCDr7i!>R QYl$e 1[T+JJ[H03 (1$91(r3^RSIr"\U09maWY@0 dgP"aBƧ cJO"ȕ!@cMK8wLQ)A[}FC.AC怆qz!h(+><\O^TJMWnnd%QsT^24 B6b/N0҄`y0c% j0`L%#8iPmR'ͨ6S}G W&5N 5qT{\&Wn|HK{& a`!/!Eqф4I|kS|U8=h%-9\x_744<ȁyӗL#P-}3M:$O}*>do4 k htCR)TcR'[R~[g«3iҁ G#:0>*50RPR)hUr1C]eCfRd&nCؐcSY  'ؚ|@H'hf Fb!qv`,5aC^)|8=|C05x feh s6d/MӆMD4  `k(D=-a-.E|'B)bli ze]b$^0]?=nf5UiM8$69hnʽ7B`flc}K`'o;H!Kd:Cj^f%f0UX1d äZ^̑&]ԒCF4&І9̫}m"kL.oqEhMS ޤJf4fM|Y?R3|}!SRL}<) Bٙ™Bjsʶ-͸173]O8};<ݹ틫[*o=&{%7n#YFom_{*e<|'9_;F2|f$#PFN}|90p#5~1YL#>q qh_ fhgp?qxpjH#?|Pceq f``>lihA|x`H?sL#,qqolj ph?ksXl@p?`|flk&k+dP @|o@\q+?jA A|XK@rPC``sPvhld>fAfhkBp_s`DG|A0G JDLD||FOt ,q?i<p 8lks>=?CuE^E_E` FaFb,Fc9ÔlIqIYD|Iq9HfHd< pɒI BIDl`$ȦJ~DGsJGJJpȅqPi^v`epcX\&XPv`kh3ɯ\KL¼<̙,̛iP4ɉTvTbpbXZb8<uEkLM\MlM|Mlr8riMTLrX@mLI^R:]TFmT%-R8RK5RtTMTNvȅ UTRRTS=UT=π!\, /q  H*\ȰÇڳ /_6_\3|ܹ͛8sɳϟ@ JѣH*]ʴӧ McWfM.3fɔ)KYJ,]”I۷pʝKݻx=| +q&nj͚K˘3k̹ib||yװc˞M۱ @I$ /uՎjЎUV%سkνB@еçNbj7Ͽx0B D z Ȃt <K z5cv (N"B bb g‹=CD,1,ن#)Didg4 b>& @" D[<,( [Gl&O3$%QvB,$[v*M/f梌6^%8B $ &`  (+yN38sN[꫰z5VB&\ k *j$F66%O=y#)* >_覫.1y狚b.K k %" 4<,YEVw OSD-W4SWRw`-cL37pS퐼` )߀7,DR-@sKCՀWngOO^mm530ӰN$n/;H7:;2؇}!thoo擯?>OAO5.v=L:3&H  ¯{T3`  0lTc(P>4_"3G qF"}@E!G̢_8lp#С ×=B1 a$06QC#7-D8p~;tH+$qC|Ã"  h!l/!Ai;6v<$ J1 _!J̥.qF`} B" {OV:3% qRk̦6KKS&j$! gno; gK\ntV7/GoЄ=FFsdg;[Hh$t|Z7IeA׷N.Blb0=FIRs$Jȓ5g ҘF< lxCPh | 18 قy"4`]?iZRTEEZ׊2թP5&aH3|HE*35'5вZlMbSlg'  ,':ih mv؞rEdSwB1khgK[ݸ;LK,u1W2ͭLxZ:יqKݾT"vz xKm4QrnsK=o9^o KX`0z[A1MB &D!:]N1)'Dk* @]#0@%|`HVx0`Ђ0(`p , 5rZ@:B *Hh :>{x1@<U3b~8?0:k! Df?yl @j4щV0WbGkYUPi!kIT{n0ޭ0}aGB ! !DyB*kT [ڿN V0wv `=#Ţ4p?XAp<^E /x='D  =Pfo[@(炫(7nxK0+Z XL` `u.oO} Q?/O#F&gw7oG{)o7O}SZ0J?B \*.z?u-}0NXA V+H{%_0Z{΀h}KL:B 4-hBew~զV^K(8@'(* ]*@WЃ`W`i&g# ;GkV,] 76^X  @@eW Ͳtjb2Gh @to0e Ix06oM P Oӎxyy 2YX &Ɏ W#))y)9,w.q(i88k<ٓFi$BGٔA"J(%IX"IYYٕ^`b9dYfyhjlٖnpr9tYvyxz|ٗ~9Yy٘9Yyٙ9Yyٚ9Yyٛ9Yyșʹٜ9Yyؙڹٝ9Yy虞깞ٞ9Yyٟ:Zz ڠ:Zzڡ ":$Z&z(*,ڢ.02:4Z6z8:<ڣ>@B:DZFzHJLڤNPR:TZVzXZ\ڥ^`b:dZfzhjlڦnpr:tZvzxz|ڧ~bm]Z`FlqpyZ[pk`h\m dhyj_:*6yPg |h\xren ^f_loT9,Ay~p] yr𩖪^zl^q{`0W_X3WJ*z^^J\ -\s,J  z#]XwU;k#+%kEj`mZW{tfTp{z=wJ@[\BDkHL~06ZZmgPx9cjI۲ PkhX y@X^K{![;y[c3rй,GZ@@%0c-;\:*kcmM]K9wX{q_\vzg;`bmx |P ~ @_`K{z+Ὲm}EmPgXж^hZ+1 \ZlՕ3p2<ì/>:@ـ@`I`C^  #.= @߀H Ġ*T0 #W9ŊUW[L^ b P`?}nX @P Q\ ۰ 8Smj5ȅ<ȋȏp qʨʘV ` P 0 gߠ 17~L̫V  p c07l|T  7( ĀC78msR"=|k!J?2~\6}Q8};M]4mF}TAJK &$:=Zmۄ8b!\,/ Ho=֭vˊ]m>`Ϟ-2gBI!\ɲ˗0cʜI͛8sɳϟ@ JѣH.l0Ċ3n1乑NjMׯ`ÊKٳhӪY X;qŀAS4oަMƗ/ټUΝ֓ɒcǐ#KL۾;ݼ{Z ,P5b̰c˞M۸aB5.`©뚺l6 ԠA>ٳAHXËO|yX~ծpiek-_WH!}]vnygށ& 6X( Ȅt$N J ga%YIU0(Z p8B=hI I )8L6P>  @ЀTy[BK=Y` Zp)te xK&Hb%K9Ib'ht@$̛uF*餔V*H7` >Z4J7' $3Z*무Z)Ié8t(ʨvj6l7}Zci4)TIkH:ϖk#N6ٖ)HdGKn,a#K P9</R{,4`RR Dh@IV,$lS1+̈c;,20L9E[Δ((%H'Xe8>CJ9\wm8`-㄃D(ppR1mx|K.75UCJ~,JғlHaJSv45ͩ6oQQ@AlP| &=fkw{# 6mau-Bd0ܗȍc|+ۂԀ}+]P>܆jMoY@.qIW,M8B~2|KF^Bb_L.h`[(` B`/L⠤ n lpR8A[gT@ uǤ+E*BA*M } &.(ŒSTBΕ4+[Y^r)l^qhN6pL:xγ>πMBЈNF;ѐ'MJ[Ҙδ7N{ӠGMRԨNWVհgMZָεw^MbNf;ЎMj[ζn{MrNvMzη~NO;'N[ϸ7{ GN(OW0gN8Ϲw@ЇNHOҗ;PԧN[XϺַ{`NhOp6 lhn|h!X" @; `, \h&O6нtvǻ,( ov4 ^<'oˏv<UA| ?ǽ A>w+Z^cΰʷA F0@` ^~І8  7{~4/08p`UxHyxw{ww kp}A0xx~_h Zaw+-G24hy^{`DD@ p}ThWny 0~`|IhyC4s y{F0ywP$oWpm0Fe4kF `Yn,,@iXSܷqdsy@h2b8_`\qqEy\x'aGx[@h82mFňm`jxw_hk (2x{̸wl0{\b؍ t@Ԑ  !< 0m ldfx!b, /q  H*\ȰÇ#B7qҡ6k4\B> شn%l3gbʔYM͛8sɳϟ@ JѣH*]ʴS-b㵐FuK&c,=4#SF8h￘[.. 6ccӎGxNb‡/ފ#磣>:9ӵ5K5%CY '/}k'?~\ҿHzp/G:$?Ȉ1tF}3̤ e(BֻH#/!&:PH*ZX̢.z` H2hL6pH:x̣> IBL"F:򑐌$'IJZ̤&7Nz (GIRL*WV򕰌,gIZ̥.w^ 0IbL2f:Ќ4IjZ̦6nz 8IrMG~@58<"'Obyg ς/T(AlpR)w2FVTT@Rdt(Z*XQ "&ME*dҚJM3M>d3cP* HMRԦ:PTJժZXͪVծz` XJֲhMZֶp\J׺xͫ^׾ `KMb:d'KZͬf7z hGKҚMjWֺlgKͭnw pKMr:ЍtKZͮvz xKMz|Kͯ~LN;'L [ΰ7{ GL(NW0gL8αw@L"HN&;PL*[Xβ.{`L2hNNC'Ç/*|$2a8R @hG9ֱsd I;lC79r3gfyK(dfTUt" itpg; P'X9 u 6TJW.ǤB whu1ia E;QsXF;~<$h,q _$8Ƈ, fBe@70AD4Z8o JftCh2AH" `Qq0l$=@-3W0Ir# YLp!lwBW_0 wzchb6/R^3 {T=r Fuw=g$8܁~I7Qz^`ptwDlvj/`LSnc@m Pr_wwx-1bFMvD' p~_Av0 p@ 8 v '[f&E!/,/x Dp)dVLk׀={EhN|f-7.\5oުUVYĕd֮:Yڱ5[j6 8q N\3g&V Lπf 2bΚiaY3hl ܚMlwNJuKvkm6_#۸jXWr΄ĝ "[6+KPaӨO^ͺװc˞M۸sͻ Ne4X ai!JƉAYdʕ-_fldE([FS)TTNuW`e YטZ-dTi 94>x373Xab=z:~EX}3Lj%g8<@)䐮E -,u8 3␓M6SFSR2|$X:aC H' x-7ܤV33(1>Y:X`P[Pm(D3$LYV3g\3 ; S95t:XTeX 6>HuR603%ш6F+VH*ɤPJIXj)4]~&gd9ji ~p;aɖxR2( -O6P駧:jꪭkJDK\kX~6lǒl8@,ȹ3M20@ *|,΄,Q:l .JzM0ʹL-` #Fܒ>R$l 1U'm1|~{l"I.2M;kW(k5L-qZE.EBI#&8юKSY%!R1/p5n '`xRP$L:qC%( ^ra D uQ J0/b$ϓYdfo 8Ir8qd$&;q#'NwT{ wѳlܖI𢓒( @эY@IVr54E [bs;!bbP< A$t9a $e2Sp9! ̲hJ.9JժZm_%v1 :b#pOE#F! E8IB"h;UBxC12Š(B^ FRREp1 t4JE ! VX0PFV d ;#1J]P+!A7I,SxE- CȂŸ88!hݘDa_ ;qF4bMz#à[VF6aNױ; 3 SeO􋓖x1Jw̴Dx]Z-liI]ts+]*wAې,ṝƢE-+tTw`W J;(2@S-/{L2̱_Bb G1ph6ng6dj",  Ta8; -  $0RO`c1PCרwzA.,Tyuˀb"DΔ#h} t|CTVԦxg n`c:L 5,}RMrjvy_-Nd*S" uq=~ I U ad9bZ`D#F84>$|86.iʖVUe"do,R<20VB eKx]kDVnPsUIcGBX,1 VГc+C˕P}) *oQJ4&Í s(OkH8I@t[ӞF.27Q oy3imVhҟ$g4!Wl"uƩi#{6ԉ>AP"tcYw)*uV8{zNbFh%L,H|R H+ocU6Nsk R7%#p[ 6F0#T{#^= "hZU 0@D H0 `Q.@/U0\,`j@\ p *0\ EM  %c er Ǣ5 2 %P` UOqZP<ՐCsvҠ \v åZ PhWs)$)q.Ue2#xXkB p L DCr Q  r?U0/ubA]Ϡ Nnpl l# vCa#'4Xh`:D d D # ob8P@ Ϡ: p)+K$8MRR8:t@56 7`3 4C#cp}qE:7b@.% `AE`  mP 2ؐ;yxՓ1 q `Xi#a: Qi`:Xo3 Õəc`/ vX0 $tYzYyė 1 %Q6! q 1CQ9 p (փڰ 0މ0Pl! T*QB@lL02Yy= ɟCɜ7 H Sa^ p dɝ 0))TP 8MI ) |96z8,3# bW5aP>铬#5B'Kcq&13 `JP9:dZɱ٣81 B+0 ޠgR qq.9SVzXj)\ ,7`J fڨ ӳ06c*E qz P -XZMW^rlLt& 㨾*:Ei5(\!))9A. iqSҪuU*2bqY蚮ThVBz zf!ڰiKv!S[5ʱ&{(;ɒC0@ː4[6Ɋf2{@`` B۴Nk0I۳T%L\۵fJ d[fk3T+"{npK$icv{xK);[ ,ПCihL{ۊ6X ' ;oۓq uY C;[{ۻ;[{țʻۼ;[{؛ڻ۽;[{蛾껾۾;[{ۿ<\| <P? 5`PE@|—K&\0@E6p:<@, ;\v[  @@M@@F@B=D]F}HJLNPR=T]V}XZ\^`b=d]f}hjlnpr=t]v}xz|~׀؂)t]}؈س'F3t^b5~0h0f_0y `P@|[Nm[-7`5tBbNyP<Zp `Fp0g:Dԓ\ZthlqȞ- 0>0|0]\w`-@= P붍ڙyBAn`Vnn/@=.E^y0v n~Wh``y0-`d@ljZpPy>ǝmTG\Uz_l[ R/y Om tpx`"WP]th1ߟNޟ|l\PH;[j/KZX^ ny`Ck@^hߖX0@10sh2m8; B,wWnPAjPDZSnᘿ/W0|PȿS6n9IWW/\.E/Fl ⅍6m2@"ɣE-^A,q#I)UT%ʁ1eΤYM9u3AYQI.e>-Dp~iWaŎ%[֬WٳGm= \5Dmժ\1KF qsFfD9MP4:BZR"@y22Φ]PcL1]qA4uٵo7Z̞/j*!`@kY(%-\I|qM 2433p-  8`5[*uvj b)ؘcod|L68enՈyl\yD@hOiwq#|r0 r\&mrГ gtGtfiIogqAvܵgf}lFs1|xwg dtЩ?whFer|7|fQ}af&`F q!tᦜvXkMJw LH1%F5 |HCv9¡ gk0 _P+d9"BP3Lmg;␆?`/ v!a h0Æ aD(F+(ŜH"و7:|p6a$0x@,Qs# uC<u8/Qd4#a h c#HH6Uuc3`C:2)\c7a$]JXr;pܣ,o#1jQd7<v†9d-LhFs)&! _“;b1 \BĀE;hsX%Nx3Ԅ<db,XbHF1NvdhCJG=2әP+P>ThGiHQ^hIMzR^ iFSRT:ZiDRwT;iORS iQzT*NTF5K GSG*UfU U1UUXzVƳiek[݊ŀ!0, /q (9q1[qIwm3jȱǏ CIɓ(S\ɲ˗0cʜI͛8sܩ B BEH*]ʴӧPJJի9k X5rNlX2f̰]˶۷pʝKnI\K,Z LÈWvnܷpS̹ϠCxS7s˘AuM.F۸s׻ȓ+_NwF{3N9;H|RËO8Y}`˟O:zsV(}m7P~' 68CG@hf@ҜCE @lh(/SJD 0>ȃ*@6,Ȓ7tΒ:TViUY8Z%f*#cb/Wlz]O82#mAYs DgLhS(&~r_Rj&firR驨JB*Rjjkm9'*+>* +6k):)fII,Z-k.KǺh{ R*B*'˺so*p 7,,[d-:lŋBo 1q(0 gH8̡w@ H"HL&:PHŐ5EAj`|Ԡ`W \LE4^5 HTPFo~ @JЂMBІ:D'JъZͨF7юz HGJҒ(MJWҖ0LgJӚ8ͩNwӞ@ PJԢHMRԦ:PTJժZXͪVծz` XJֲhMZֶp\J׺xͫ^׾ `KMb:d'KZͬf7z hGKҚMjWֺlgKͭnw pKMrܰ X HА34j6 ֽ#ޱ9F H rW QG8|aj`녌\ j~ -60v `DW{34d@<w9! }aM gp@c1q{T@8n!],.? D HP S0B|#J$pC-VQbLj QcI'=RdK c̆#E !+, ?p HMZ3eqZap[4o٪!Iɓ(S\ɲ˗0cʜI͛8sɳϟ@ R!C%RllҢIF5$ѫXjʵׯ`ÊKYBco7r1+۹bWٿ LÈ+&ڶoΕe.̹ϠCM f2v 2qP]ݮ]۸sͻŧSk9z;УK޼8q);uӖ[6gӫ_Ͼuۍ.Ͽѫ=vT@e xw߃F(@}PтU$h]s 0# xL;똳`(<,j@~9p-88>6PF\͜90@/t΂R)diV" p _gti',tM5,qwܝ&袽9͞x@˝sv駄8.@D ~|!_5S^c8Lcꮼz&*@0@ex7C6kV;u蠃vy'8 Z#k覫+k/״SNW UT9$\|}F,Wl_ڿ <$|R.r80,hJ7s/&D=40L/|J9v#RTWSH⬳8x(-dmhlpJ#ӳS|M38s;nᆇ7G.Wngw#Aߨܲ-3.8ᢋ{81팜ȗD7G/=3B3$-?oWo=o={/>oҫ|g6?L`w}` Zx8JA GH6otHU "΃ aDh l HPx4dHDjHL 09X*jys.{" 莁Y¢E/# BC*…4y>&.H|"I3pm(G8J*nˤV铏 )g9JJZc+w)%G2,`A ZP򘒌sI^:G%ጜ D68Ǒ 'NS+ghH:v~#8IP VHBІ:D'JъZͨF7юzt`lp\QeiYӺV夫`K&ԮxM,XWdժ=1d'K٘b 1bGKB0!5 O*ֺ@Xj%n G(jJ|M\cˀmMwK]T@@Hb p#Pجr^>+I)R BP?h!JF}BQ ,;Dl~7TfE*T }/ea*, h9㗔IJqKq;G@)P 0,V=2M eVȢILz56^3L:nIe.΀4GB#~hАw ,/#bn7}e8҅FtRѠN5VLj@ZհJg]W֙glk\&=MwMȖOl2=v&xfmmsVal'<@NwF1o"۪%MkMn#gT&MAH!b۞}_z[% z@SZPm@Ђ*(t{hvg>ܱ/sPt((zN#8 bݝx{`XDC􅮘N(eAPUVxϺCc`+@^v=j_^-X*8w '[ &P~A(ዾv/\N9*@ B牞b# v` !G=E~j}D =XPsE A}/O35_Oޱ|; 1R%x( 7RY`[X7 un[eh0呁xǁ*Q"H&)4hQc.8%x2s5u9<؃HP!1h@ُA3R'C-b! ,|scR^6s Zؕ^^c EeFkb)V{ *aw\/6uZ(QQ`Y+V `7(EW{v4I^/!rGw"ɕe+0$ cqN9_i{]\xCɛ5W\tDe6Z @{m #~^9YW 7YԥuD PpH9Pp!,IP'j6| )i%0p` P % ' :`U}@PY*Mw9=ƣm)@Bڣ\Ez a;D+Nwv}KZm: XY&tzp;4z^`Nej%[zi) \O oKv+cPwʷ~[Ic :}_ԸƝws;D;JGIzhЮ;[ ںHaՇ~鶷;c벿;cgొ[Utȫ˼V2+hD1fċgƽ &K1dPEľ往 2dm!w0;Wyp8?sbڿrU;DuG9fPMՅJY%AwoiT*uL*=wX'­\Ri [/?Ee2prL[<Bw!zHTjaR F A`Y TՊY^aA `okR^s:ZpPG[z,ufèȁ7LY.ő=a李]hh-XpW Y^f$!/%{\+] %yY-/ _@Wq\^n(Ml-Z^׮9VpPuy^>ZJ.#jls_a|/o/cؾb P/n@IKo/XgNĿC\mr',l}ۯUwnbyp%N/{8 35nG!E$YI)UdK1eΤYM9uӧ3A U&5g|ab4_,l_-WaŎ%[YiծeơqMӨ{0z5]&\aĉ/fq O\e̙5o3gП].EpY639kgД-Z'^ܸڀ!/,)?Q (5u;0sՎY.uyM]qCIɓ(S\ɲ˗0cʜI͛8sɳϟ@ JlsiqjNhѰaׯ`ÊKٳhӪ]v,׏߾A5\|dۿ LÈ+v\\P@rqk̹ϠCKnpĉCZڍM۸sF[nsyYkȓ+_μ9wan֬_ܹxes朋O[%nހv޼SNϿ(X3CH s4ٴC8p#~`䗀v 8 B HH RL;rM1p Vm(<㏴% ,3H D؃pL A;`!Xf\%$` O8rb xHti)-̞rR cS/ʫӟY>B3Hw)"AA?8ρ1A.AΛ!u0C N}|@P1Kn-@ ztS@Vc&C h$ƏT"~7!ІZ<;h>|`1h{7A@!#`(E .ṣx;Pz\KSw@R9|xȰpwl$c:yVXhG3Q%1K,,c!OJpfyYr l%M2 'uIbL23Lc:R4ͱBhZ4чn" m&5L'N0`:bNdsILb5 0A B>KROBsU FbȀ(9n0%(!@B&tC%ЌNGB&!VR\ `?BD%;)7wU|  P @ 6}8@@̮Tp@HŸ% @, 0@j-Bկ-E*BA*M D)`Cp2˂+@M j>*h3 VbHjS Y(QTDUp1nWTxռe}.!D:d*uX(@ @QmxūSV[|4 Nun!t5@A_Zx%"h6R R9W 0cLd6αqǘ>,"؜)6$/YA Ïe> e|@%pkJPh*!F;BQ/=@Z[B1|Xf[0@·S!Ϸ>Is:ǎFN4;~C)>GY;C:b|Ȁep(S1M="}mqW ?;S{< pPD5k˻^wW 6{p|ʺɿ?%+#= ^kvQP~C,|ۻM_i>zgwV1P"VaSEyVH"KFC V:+%bDhAP44P  zV0]VpvT#Vg}_^f3{J؄ÄNWRX:CVZ؅…^IҤS`46Ufx@Q6Xfef$pGGm(mФk?gg$x:nu瀁0zf}B[N0uCP0i,0BunP%JϧL w TT\ kur 8UmKuib3bfMxNxCGX0q:jVn0u VSćӨ>ocS@ި @X+ PPu$@Ď>EhNeN-`Zt:((PكyM؃oCmG50(RЀ &qf$4eT&Y<^pf{Ppe  _ SV"aJ>nNPgWڵ0ȕ8-  PHy{hZY?FA'IYL}Ѐ}u (bT 0T}0I'OhNwRQٙv™\Y@B;ٚš JWuTMSf1 uYy"FbmfR)9P 41 Pz"h-9wC7"hJ[+09Fa7%PyAND@UV PSo90HGՠz7(yb %:iAQrj9эFr(f#?}6]ڥ%bP~p!*FJU6<*|;R;x̖ e.J M]Q t^0KyPuK~PNZyJB|jcj)(  s0ovsCPn:8XWWQZ_`_ @M1b|ꟿZFP{8PNCМPjڨ6R&R\Пq/ ]N`D`Ur!ڍ"&Di+ʥ*[ٛժ7"HVPn3!Q~j&ފw(Pju"'r0uz5tȜUPqj nl dJKU9ʥ 8B;-rœ'3VdNGGpE[(&K hSl;k۶pots[x;wPx֜YVo\ʩe7ohYoWG"Ƹrmq(b`f{P⸐;8P %Vz'{˷2}f6gC pWF+5jwW b)b"X'rTW[qjV’ )gMF2}](w+b ~ vx XTȋڐNе;PHYPbnsAo9-%uf-e-_6l`0g|5;ʜI'*SUZ׿4hˀLJم,V7C_rk[VǗLJ[fPjk-jʑVUxHV"3TJ[cl V.pEU,x%WU{| Ƅ{:̖k4[gLK~[ Em%GX.hCSyկ"Fz=ڰ*`S>8:hF zתf=6|n>x\жH (n~x 򧉒5~p%}+T.S}ĄހWĔN m̻O"2TEMp^T4p~zV%0 %%5M`zTX8 k%AJ`:{#2M7R.[ja~p/:PDf;(rxbσ!Gojmb ѾxUI7xE;eB4TY@C_?M_/]_$XA .dC%NXE5nHǏE$YI)UdK1eΤY%H6uOARqAT)҂ !$PҦJ *WW&Z5l[a ۻrǺE UPq \aĉ/NxȀKhhdT"tHgk(,kCMm?K@$@f}EҐAg Ltr!j1=vƊL{$ϴ!M|aj!@>b9b%b/b 0`4a'ȃB=q@&Xo% !V0@*!^P dAI&Yxr泩>|d=04L4T31Bs % p2{7j7.3`4 5@Ax12B mÀ!77 H53`%AZ|uVZk֍J B.ȣ < BUJh1@6oX1-Ҋѥ[ 8^ s8r] ۺ,S#<]rU,F}ZN+TH.qm26`>1 ,4اLMҖ U 05p5nC9(C@n]޴hTA9Q@<|ӾPTfi~t"" c@]Ksp#@j+ŧz!`*e|y~LQ(XnypB@Zb2ET +\5r:s;2ũEU<W,K;UiY(U@d_ *x %6``j5 9AVK|,cAhs7E(m>N}O8u- @PNy$Q/ e4`@5UK >Ɂe+Ms=J)X)| "τ+da $" :kMpRuAHZ# 9@ cvg0E1pQ2`B<3A  B (ݷ,~&_.| xG<0@&c;5 fx\ "Cc:l,b;gq;Jdhׇ/h@B0?` eHa2At`\s?RV-KA >HLhF&f5+bGkfSۤ{ 3@ G8ය D0P# !p܄ 6yO|31ci>tVG:)>EbO&T eh PFTC)zQfTlrF=QtiIMzRZĢ)eiK]ҕT3H,6 4 Di|Pz HQܨ!KWW"YE"۠6DP!pW2l,C`;1I42r^HW 8 3gJxлFi>ቡG$'-v[QXnLC@gFEKhׇ9a{1iO׼7H_';S@R\JW9.-kl7Y  VB)8qny[cb՗ްifykr_SA@$` MT2{RX0`%DV2s쐱AK@yL@33r if4v!oL dZ&T7}NfΐfƙS% @&tMz$g}%B#G`B)aBwS|X"]{dRLdIO3~|?_R !,,)?Q 83_1f9s| 'b0>ܸǏ CIɓ(S\ɲ˗0cʜI͛8sɳϟ@H0>;PVihY0CZ|QI1攩x'^ӄ-hb瞈&;3HR, M-$D2[w %;`Dtjjj:ꭼJZXl|3: 2}Ë/J~Vkfv+5x/+79EtG+,''&pM,xM6e茣ٺ\,+5 DLc^4l8R"=L3b= 7s5xM:Tc5Րqu\w`w c MG'tOG=uWEցmx2|߀.}'xG.?nyga_y.n<.׮߮fow7䧯/o?oBg4h#|58X';ZP4Gp b| a.HBdH?(0d S8Ѕ8\ wɡ"%4! 2&"ΈP2X"gſE^)5 6&pJX3 d8*Tu`,|L$Ȩ U#!HD*k&@A6JaIL`LOR *ьd$>rZRI)R BPM )iib+ȴI*QaH,Jijn+ؔI4)mFԣ5ǩl'L'Νj6p>/s0 a 1= @=31P<s1`cijq;Ǽ1d!ȶ3:%ɮs|:)oUrl:-o˞2f1K̗385W͎s3l89/us\8=|M6A c3hE@s!3I{$0iM#A}8Q 3Q0Uwխvua 9Y{ֵ5p.]w9a/ط2 :eیvv͠m*iOڤ6Ͱmm۞:q 6-э(u_{r'yw ;}1~'i2; w!~&OU0^%Q2y9QrAra>=[@q#W=yޣ%%)g Zl`hġ1qـZܶ5@5Do'tMzԧ^g=[Vדus]Ƌң%Z-ٰ8& k\Cnv=|FVrN7 A: (bGHL,H0@+0(K;x3$% p@$/(D ]@,,AiXfi0 3,1-Ujl9,8SM5и3L$L@968)蠄j衈&袌"M6430楘frV3 1S b~詨ꪏF:i*Me 6tjN;91L3)&.ي+, C} KZۑ8g5SAl 4$#k/0T',.:1Gb^lp7-O~`dw;IO@|  Ax!6 O%:̂ܠ~fxBN"">0 dPD A "ԡP'B3u{k gĶ!Kl6JeU ul(D!AFqc$$qsNt"868b?0=@AzB;I𓠤\! G52򔨴#!; `(=ZҒjؼWkL0UZ1gP:@c&LIjZs$Ɣ#3_>;Dw$LEyHɹӆ{}.z4g0~ @JЂBʻ.DZԟ2!6юz HGJҒ(9*zі^hGJgJӚ(]i;\SbM8 PJTth=MҐu*! 1ˍFuU- **+B~ HWQ:@ @. #G|&\ԫ` 礀fESjRAD k!4 BؙVjbb;[@Dm0[W nF"HH`.!( P!J# i[_K],5 nT Db^8`8nJ@Ll?U# h+%Kp ܠUh X4 aU.]WNU 1`l'\;A y $`W"95 XXšm@50,T@ Ň lH"f'ѫ 6 -0@E51n `,dUȚ%ʁ! o=͙ ``!2GR"o@Rpo]]OlظHEOzuYs zaXrN" VլHS Y٣qwC 02k Wb Y5s=&` X4kϜ4A*qSf,RR;6纇<m8 {I{Ko5#ofln;mk[NɷW{:/"k3eZ`ם3Ʈ<XS@ ` A ]P^JWyZEUhɹy,b7[;;gFPnpٷ=E}cxG꘮ʐ'WlϠC, !i|>p-}ڴԫG.iֳmnm_ d+/HobC@u0 !/,A?P Hu̙ w=#JHŋ3ZdxƏ Cїb#ɲ˗Ȝ9G8sH@h; }ٓϡH~,:S ;PJd*өԫXhWZ~;4,d4Vۖl%wݥTٽ} 7B_ cLkp KL˘3k̹c 3il.nLqdϰc˞M{VݬYP3,˜rp;YQ3:u庶cËOӓ=^tU˶cͿ?(By9ԅCȂ 6F(Vh>@X ($bp,qX4hc0Hٍ+( I>;@0@XP@ T@g.&ID-40 G!:&Ȟ0oZ+ , fCPʢF $gh@4M4@5&CF;񅃢n{MPD`1 6@«B+ndں SR ګĥ쓃\0OB@!k2k̲̾,5@nTzЧN,x{T,Mc _jm75| -yiAA+ cONc>[zZ8 3:eDAZИo2t{^Q 5`@ Q!"QU hA,50;sKAP,?PKLԃ !`EKV A{R΋$|,J1GҿS1|aI@F'B"S5q KW9aA2'M!>Q`.т@l?|`o p+|p {@bà8)AE J G T`J Lh",IP2Z 3#DGhu#AHhq>3;訃ި$S#IJ"D((U"$K'q8t  S1Ҩ*JcҖ|4ԡl`p;"Ќ4IjR|&69mbӚ 8 MlF1otg3)Morg4LlG;M}MBL~C @ zzR-<+͊nԛĨHGJs>T @#AOӞ(L;JҚ"e6=:sYiKO-*NTꓟ?%9ZMoj@U݉ hF]XUoE='Jn>|E WXDbC$`Hc ,9H~*?O򴰑K 8b&ZYkz,W sm&\oF,-,^ An5 X~7uk [þSf$jZTG}GV~0*\ Im+XV 5-3 n'!6p]KΚQ/7; sͮhFok jt,TGjc&Q0x/+Y ;ם)qg [UvIя6d6ƱڴNro X/}d)^3No;S39qApsg 9q3L:ߙMBЈ>>Ù@f7_4!,,A_0 HEIȰÇ#JH!3jȱ` C(ɓIT!|(ӲfCYlɳϟ@ Y-[f"ZʴӧPJJիXFr'% !ٳhӪ]6퇷eۚWܺv{Vu^m& /^ďKF[V`׾%xgCLw+̂7'<;-r׸sޭ{kpîn ugqmdzyK7 /٥B m[y;wvfʹזIsfbo1qy|cZHV &YCXaȠbj ~YN3_õT} YI%x|=xCdžfE$_V0ȡC"cMA Ȗ[ CB?|gY=yUCkfLbYV ,D@&d|Ceyx_$bvh*)Iv6K*:(a.J1H! )VV;\7k)YH!o%t jWR:Mj&mb[+)ZɗA &-dAuqJB @=H)wnKи S:iW s t[MVJoX+)pmE3z{ ̦Y^G6|og\v0tM5 X>]٠U;/w5a7[e5۸H"褗n騧ꬷ릷S9;:״;>\n'o:0#|+/ԯ<9w=s]o@s BSJ0T+HT7(1# ! @ Q@|} ԀG] KP@ (?l{#BB! !>u,@wC9bR~1^0#djW*a ,@-^bH@Q+G@QtTX0|Hoc,!() DE9jrGBl}B4nP Mha ZHܣh?RyA#!>S^AN@tT!I>Pt_@ c1oS hb #(1QІΟd#CJ}ӉOF[B` $ !0,A?9 HpC >r#s̝sռqV̙2ʠ=L 3`f*A3ȬBq4YfjKѣH*]ʴӧPJJիXjʵׯ`Ê`UQiea#H$MU2`bA`}I+V 10_lNvj̹ϠCM^*LXMs;wNivѼY's:_N\tm v% :Ǒ5ËOIUΛs^ZN]h~[Nƥ393Ӝ@QSCQg5R zfv >^B( 0M35L -&wv9#N3/:XQ@ӎ9c;FTViXfeA#"T)IXM6smKB8a .M6AwTT5KFYᖄj衈&S] 6(R (I$@XN2L2=VK54 >Oft--J+Z<i5*U Lʘci i͂N#IY]ڪ:++k/Ad-Ž/d#/;:ߜ708s9 (0;03,1+Ij30Ӛ4\8HN1L6#/ .mH'aT54Ґ#c:\9<$s*;BH$%ӎ/̌,42+4s3"39#J7G, R,0DlzK,3|T/g13D${s$0a6@\ڂ 49HВggO <P4H$*(I(:>s6)A8SبG>P!  H^ -` C(`%0D$׽0 V^e8u;!!,7ISX,X)w{9$8H@Cрb :x a6 b9iah@[H QLtN"E*"3Y1}4KYNNG+thtjL;^ʦGtG&881 L@H$Vo`ǡkT5:$o,@G Hmqdi34o7ܐ4 2MMxs|vms Q ;:vҐ7t|w^g<(YxdL3q[Φַ#$\Nv&}hx_wxNQO< sO|O7ɼ7{3_w˛WwԻbgOXWJ>OkH|$yo_[Ͼ7s}O~gTׯfKX{xw@a\R{G6Pf7xzG2`Ɓ*Hy h&4wR Q2 x2(5sEP/:P5-(Phv?<:p2 `xuT`V6`GP ]nq@Uxg kȆ|l @T?_؇e }V( X xV凊eH~m(`NjWh}X4hx{OJӨzq܈y؍XG8=8|瘎(9x9xX4ȎFӏi/rY, |9G(xّ"% v8(9%%v'.!+9y4!1}3Y:Y7v-@=~9Fy,C9v?yLIIEٔROi~Q9XUIW^[uKd9~aIucYjgոpɖmYuov9sIwUʖ|~ yHyiyuY9'wIٙ9Yyٚ9Yyٛ9Yyșʹٜ9Yyؙڹٝ9Yy虞깞ٞ9Yyٟ:Zz ڠ:Zzڡ ":$Z&z(*,ڢ.02:4Z6z8:<ڣ>@B:DZFzHJLڤNPR:TZVzXZ\ڥ^`b:dZfzhjlڦnZ4mlmhfZX~p_@- _F@! \gzo~q:uzf> {9Z m;U:q z+@=Py@ @lp Pꪯ '*{ t{ګ*ZpЬww qF`pyp^pm*Gh`m/08p`Uj듯wzrXڰ{ Z;Z5!z"[$sهy^yF@AD Y21z[ \pԊyipb7=۳h C{* C[ = jP^K}k=$= bP[]A0=c0j`з\yb{rbdp\^u\pc|m=kpnj`ɊgX\ hkhPk|p;Njɻ{[Yɋ˽ŧ@P{~ 7m6'1, P D+` p^7T}G "!F#%!2,?8 pkO:"Sn:,jȱǏ CIɓ(S\ɲ˗0cʜI͛8snjYqv !fՍN\Dqȁ'p W;jʵׯ`ÊKY\Wp,Y2`xuv߿ Lik09sH<صs.̹ϠC1O,xv֬Q5Ҹsͻ Wn:lʵo_μУ43PsdqDJO车;{8OOk>>TÍ,E[ 6 aN9ŜN/S | փ ($G#d(4HbK;(/蝍DiΑ2P<M4[xH9KňXf%aJ# M4 XlMx,Ν|'IҤ<2D$9䟌6ꨖ2P7 ; #nᣠ*ꃑ`* ?ө*무w 3(M (X9b/&첻rk;"MD! jN;&kR7XF# (q+eZ& 7@W+ ,L1S4ј3->?-E@"[ ,_#3(g4Rrch1vl8$s<3H;,<MHltL7NG-POm3zF T5`bmhlp-tmx|߀.n'7G.WngEElT Gtnzڄـ .{٩PQpD)6$T.L@ŠK]J*BMRWt*2=+LJ*X/߃ >!.,? H*\ȰÇ#v͚_]w.4|$Iɓ(SHѢ59zj͛8s܉Ōͅ6^<*]ʴC/^JQXjݚ,VٳhXkdʝKW'TAb '.\ݿ7+޾+VpB!;^LG˲f1knKEK^*<e;^] 3 qig>ܷp㢏췹uϥO|کSN2ܭe>^}.:Ï_9t5V/h_]TP}x-HW AۄZ(_zqihX"סx"0'cs.H8Ҩ\<2jyܐD&J6NFiRVyVf)Zv^b9"ӚlN~_tӎ/Ԛu '{gf@J%(eF:Фf馜v駠*ꨤjꩨꪬ꫰*무j뭸뮼+k&6F+Vkfv+k覫+k,l' 7G,Wlgw ,$l(,0,4l8<@-DmH'L7PG-TWmXgAy \p0 !>p0Z4(0@\ <6\\pFy|acaAXA y @h'lxD}}zZPEa 8 @Ǿ0\8  ?`y|k{<>j|!xn _ZC8j`2AsG@!/, /r #1Gٯ^)vM3g͘8ܹs]S7nE̖-cF2:teˆX8`0{IKMn\gϪeӸrqϥCcf̈́LH|8Ñ38`¼ Z26RɬÈRT+0jٸ8nƶ̆5i>Ir nL˘3k̹ϠCMӨS^ͺװc˞Yc2T1E9z<Rdc(UtGix̹Ϡ~M鸧QS:0֮ >zS-ȸsīk Ra̤3ddF(Vhfᆡ%>h4FdI]34|24TN#8ceF:EP`S5L`3x\$LT40 VFU7rE, CIcN%0TO]45IDS 9Ő$9+e3f5#`Vj饘f馜vꩆh"#14J5Jtct9أ=>AY$O}dLh%hi ^)&Rwf`AUx}wg=8N50**}.h8F:J,|Y$TL1Ì9x8݉]S /0L.c'0X:\O6(OS/3p(/Hb8YX>IB?< aN̤5t6K4D7QN;TM59fЮ.nxX 4T`G,c:LN5!9TeߔD1x3p9CD?/HO % 4挝47zm23 "w2acv3CNGc~xDcbheݘe4 >nW#A40c 8Ǯ*Q怖H8A]c Ba`|G|8CVr 7  č3,<'yt6c9@ HD82g΁NX d! 4GBjch ; iTAdqB>="+|L )w F<@!=̐2;e Y|qqr<')$'IJZ~eJX&c#?x)4|AYȬ(xe |q>|<20JSVv zDc| 1> Dz{8#֑Kш5`k8V+>ƛ4JCpkwpK<>cZkP$$OXz *)~3<ш)cKTs\} 1(YʈE#< S_ 2jZGx$Xb"[Hol&:u =f et$)\O$MMWb 2">@I0$42Ƈ+2 K1 c$OnŘ;/$~i0AIDL6r,>"$#I-LgИ11#C0FBi,g|x~&>"ʂU,hY 8i] v#:zLR-ȁ+ТkBF44'⸣3AA/ cp!qNxL.ځb2cTܭFMryn8F-ڒ'Adk0qKfҎ}#(F.udp6#:X5j+Q0i@ռF6mwS{2@r,UuLCKC2/4l8ÀBm|@E& rGYu,;_zifdX@1Փ5Ly+쪅/7I*0F4# MF=,]2N1`;>n`D,N$w|cRw7ye>23('g Z3}A/ڑ#ZL1Yo 8ƢHS|z+i,A}qQi\gq5w>yьK="Sx4Fjr}=NN#s# !E'|HWx|asQ y'P "&~$X&)wwm7Nz1K`SN6cr.1W=xR: 8 <xx$xbfFg2Q P?w`b8!)h @TR~3`wQ?d"sa;{u B2#2gt7vu/0x|QvRz%r#Kqy 0(1cXxQqLAY2HL8dzٰ"5Q%9)sqQjL bskx78A"L9r7͆G.mw#*f_P4(Q ʓz P; 焔HS8$G(΂ubCّhHpuJ#n3(2+X Fm1s+eeT 0CTSF) АY$$ Xw2;f%&P=0 р&ӑ.сN2"1x3oYSeT 5$ fq 0r 4y"s2!FDX5p PFp QQ7p!H"pHZٚW LXR !c7ob]Wˠ %'ȈP 9VrGРsV& 9x +M! $2K!:*~\[VF ߱AZiBCpr;{a@cqLС+# O =PXvLP fK K!ނZ; J5ڵ+M5C  %`R Pru1 Ұ@0?|JWiZ:nFH*@P pG1TZ EÀwh,:cu7T!*bi.|fV[pCMT`L,=gVkJ >5 F%{g ڮ*5Qp eQPIX1W%a kbGJ:3-Zze5K V*ɲb;䲜7'E`A pU(iq#JyNc!۹9  ڶjq /& dd{Nfh 90''Q2~J|#5&W qo[1GFmp7xʻC{B ߐ(:2놝 Ic[3. h-9G0 3nq 'c̄ HR1d4 KENRMjs9Ձ|XZ[-ɬb=֪#pHٰP]D0y!GMt]פ! 6 ã98א1v]؆GGDn֖C?]?p]rݫ}٘-@v#AdT})K!s٦mɺ`2'[ڧ]c] XF +8V<ܑܠMgKكֶ ] e@ؐ-MږВR H}ޝsE4KCDb}^3YbI ^Fڲ .DS nI=~̰ᙢ9(s$2 ("T?6u2>4:6)@V6u'>4BNnD=f VQ~2 7INKNW:QP[].l.L<G.LY6zn@`ٔ{: a油3 }N:N @ >N詐P x>ꗮN갞. ~\>N.ĞmH^-־׾ ~~Nt.ޮ_j / _?o?"_# o*$.ߚ-2ߑ1?65:?9>o=B~A?FyEJonINOgMRbQ?V^UZYY^T]b?Oa?fNej?Iin/Dmr?q?v?uzO8y~o0}0?))_)!??! ?o?/?_/ȟ̯/_د/~?v/n?f_/^$XA .dC%NXE5Fdu096$YI)UdK1eΤY͘ ~ OA%ZQI.ݨ ρ"NZUYnSPJZYiծe)؁bu[]y+@t&\aĉXcȑ%O\!cǖ5ogAF]iԩUSskرeFܚ4mܹu='^ƕ/g޼8rΥO^]3tٵo{wŏyտ4{_}߹~p@$@@tApB +DKB 3på0CCCK4DHDqE[dHEcEgFkqGԱG G!4>"TrIdI(s2J*$nJ+Բ@FnK04K14.];sM6U#M8M9s-:sϭO@;L@ 5,?UtљeQHSr4RJ+hRK3tASP%4PK5U#LOU5TWuUV_XgZo\w^v`5bUvduVfvhVjvlVnwp5rUtuvߕx׾z=ƒ*:,`8}OaqaT _ &vn8dGda4, fYFF)rfr I w.gMZh)\|1:jR3ΐC|lآ 48þ.mQ#73l\{OD 5pÍ3{w|3hh *8Hs6\ /m7Z' 7 5;HC 5!x:∃s4w<Cb , 57x<'H|(zw w}5QZǍ7r42ߜ X> @8X>pͩ CW/a x׻ Lx<mx@8hahH ^ l(@NP31dRd'=IPR$e)MyJTt/a?MC<k` A!ۛ]A3*dH⹱!{\ c?|L2f\N'HBR!] Vz@iD&S[Mҷ9!TNgU8AȅC &mP ]>(4Jk@F"$yXgG C@>(U`Sb$ k()qN yT&UKejSTFUS.{d HC|ġɣ܀P҅tD J!..@>9Psu%miM{ZԦV[W҂^ќ-`t`BI z$ -!4Hw ڜPAD#>(wA:0HYW>!@|EWZ{S*m׹2?$B8Ѫ7} AXPY<MP&v BRgoduқѹ |@״Y/C8VǞ-ގ)r-4 mB(QHx JꠅD QAuơ KNW`=|-p% Ͻ^JWq@Bl) 䐠ž/$Q8t7"NHV @:z^ F|x

.-dA92p/#JB.6ClysAZo A i}B+9v/DnvSrg;>EG&@^ ΐ`g[gyMyޏ xa}1S:~ܤ:i-[q8/±<{+86:(/24bћ|=@ jC;La.#Wk M.T]fqNX@lEWkQEn8HvNu fhmMY~m\ eXM6ަ^_~Uojls6PV\fYg⡁m&B(N^ov4jYp6A.Dp^'~pP`>lCP-Nd aq+2*\mX(,pT-i (s'pApPQfjPP!H3.(s,hssu`( s&drOOfH܆f^h8UfU7#bdsfT`)vk0\YuUXOGwH7QTOvi_mMrKsu(vPs^\_@Zf(iau1=b@vpY]P*|klV`*tkoӡi\`er0}rW޸5mDch0[_Xs(z[{wuhꔆ؈ UP'}' OqPٌ)x߈ ^gٮ?) aG{!., S 80\8DȰÇ#JHŋ3jȱǏ CIɓ(S\Ѡ YʜI͛8sɳϟ3] u ѣH*]ʴӧ իXjʵWR~KٳhӪuڷpʝKnƶU˷߿>LÈ N̸ǐ.L˘KN̹Ϙ7Miy/@hO˞MJV#ֶ&P U-h`彣kνDQ޽3GϾF_L9$T ^n $ P Vh&=X URP^(iBSG,8(3Ά46@cDސF&vH.䓾5 T&eXfYٕZva\~){Ihefl՚n)SpiEՉ|ޤgZ@ &(F*G 餘fJQⓨJ⣨fJ*ꪪꬌ*+j멹:箾k'&&K&6%FK%V$fKjm ηnK.,tk,l' 7G,Wlgw ,$l(,0,4l8<@-DmH'L7PG-TWmXg\w`-dmhlp-tmx|߀.n'7G.Wngw砇.褗n騧ꬷ.n/o'7G/Wogw/WM54 iLo?_0 Z~ i`Ѕ\A^ȃ~Cf hH@= f7lI(6 CarXC!" y@pȃ+ "B @@$ ?#hVH5!qAC7 [@*@=@yFP hHd [8Dt@ Lv a~8ǡh G7p d|d <- @)8|a$CIXA g B|@ m hFl$Jn+@F(eˣe &d!l#Y-l! Q HŠ: Ld|93,O#1g`p<|m0IR WʰȪ.)>EL Y"?  4:SQ 9$ϺsRT+MyQeP9haJ378 Ae3 5p!j9(d^XCG|le[/p a]M(ǥ g$C UɅ 66Bpori/a|ϧBwkB?:W-ЂA j ++6+~ }wV4t iH[7zS B;W$*)>|YrI@ 'AY$ M;H8 DC \OS-DpZfQtXB"$D@ր`3 rU3>8x=$s H%3i׺$>@$<R|@ *t: 7J`  `u @މA1 @, ~8"f;Y0@ st@j\@X 5&t4-RofA GhH@-!cHp8' !&\C9rZI*, |dҰ>@2RԏGK0°qplA̟e?QƂ^]3L8d۰p/ PtC0;duH!b0Tt :,LxdPbp.R͛bKgC> І%% 0r ial A9'вyPPV.] 3c BT5,Fz5 Ly,`g6`"84=z4,*>owN wjx|*1'{ʧ 9x>Z0o{>=|{LY|ͷtYw`!5 eFh א /" p#@? 4 ` Cʐ @(P p q ܐ 䰂P 0p T3?4͐ 4 T m @HS8O؅q 7]8 aH ` S` Q( 98 P a( p 8Z((RrRQXm P@t؉XxP 퐆 а>nHA88Sɐ /0 ^rQ ۰ 0` `  ݐ ./H% bbaB ـ ސ Hqa밂YZ8 R .@B9DYFy@"!9%ip1  `p   Ҁ~ H爋98Y[Q)k1 `>] 0?xܰ hؗp)a*‹% PŐ~y`  Tݠ0 P 9 ٍl9ʹxQ @ P @ Ð ? ͩ0 YH gYk)ɜIy @ ɚYRAjII(rʩ"B! ":qI "z#8.Z!J☢g8I5:@:H I4%B_X"ćoD4sU+,!2,ky H*\ȰÇ#JHŋ3jȱǏ CIɓ(S>,*]ʴӧPJJ*&Caׯ`ÊKYT!CгpʝKݻx:>:bÈ+^x +*o )ո˘3k,RڂL LӨSM*!*}b۸s69uRdȓNź5+ÕKNu. ËO&+;^˟OϿ( LcNS 6ؠ@DˀVhx` J$hbA"0(c)r 8ÏrF3QlT#"HF:S&]w3lAb8G6 m 9leE/xA {؃-Ju2EhiK\`Ԡ3lA hȃ4|hB Va0?\!q-H .lAX>ʙ|tn8֠@h ^@@`WAp+BA`ы92 lV: 3! yVPmf rb+xa dΙ/d x | l:Pm G~A(J8D(@#(@fQ [IR`iS |漦ؚܰ Z@P`І-T D@pmA&vna \,Bݼ fЄ{n8>JA mm@8 !@0:ܓ,s1Yh@7|H%pBۙۙ[ZVTi'놃xA n܀6ok]?wh>-5PU Fx^@m(%>p_i^Ղ !^`! LL`V ^`ay@ f4_=QP`;,@ )!а-Y \c_1tLM}+Ccd ` 8@Zp9!UX|D@ 7 f1 fj  W2kI9̅?w[6WqT6Ɛ1EM9@n q @ڜn0r{ np``3 X@Y@DcZWpCizPמm}~lـN60+p#'>v9%-'+3SW( 5@Z݊ώq6=b<`('*+^;|a h@AWoB>XݿŇVQ?ݚQwPWJ@⌷AF@ÌT&k7m}h@ iCz\|8  [P$>slF1?^ lukSW7`-(Dϓb6/|Ԓ on|  U`fX0 b0Ss`Og\0l2p 8ė[k@fsTGp[# `Tc˗QZh,` "{}FYKwdkg*VZww[uS o%X_0cm#|x@obJ5H&c7fcvMnbvUQZgb&v Hg}_ {iEh)g@LXqgXJC7-q`f0Y_HKHfn tfj0f4MN4&L$fȆ5PkLDK򷉟{@zwh(O[Oke#e_nHgbHK8r8r$hȋ拶 @ilɸ-0A3 i)ʠ 0}HK T  ʐ p H pt G Π H"ɐ ߀0 @ x4!p ?` 0 #H7iGT6 ` @2ɠ 7 0 P 0`B)pI ,pmi9qsY9u wI9y){)9}9 }9 9)2!_,{ G`A aC#JHŋ3jȱǏ /B|S\ɲ˗0cbi$)ɳϟihraN@*]5uҀ;\sG  }5Klvפe֮spiWbףy5hNc Y۷$2qB@"J جY$S̺uSI"LB {]v:^,u] S ӱ NE|s3H⍘ˉ(=+b 8&i( 駠*ꨤjꩨꪬ꫰*무j뭸뮼+k&6F+Vkfv+k覫+k,l' 7G,Wlgw ,$l(,0,4l8<@-DmH'L7PG-umma}aDD\ppWguD9S@Dm> U}hP>^ dv} 8EW=VQTpDK>qs~@m>Fd? xԭ@k`鸯{]!;F G^xWz_q_ok 8D_ Pzk_xG5 n4u<0@.|!\pCp55hlpB0|yP|P`mmThPg/pmX(5Ay "E#"QL!  T$9〉.4>N`F8"g@Aր8!e4# !/,!{x'0 ,B  qช/bDƃ?vMd8&i$0`֬]+]×1g̘ȑC$(i^Ք.m4[Tܝk ǁ!.,iy H*\ȰÇ#JHŋ3jȱǏ CIɓ(SB,b 0cʜI͛8sɳϟA>,*]ʴӧPJJ*&aêׯ`ÊKٳ!CKpʝKݻx:2LÈ+&ȊJEZL˘3kɪڂL LӨSM*!*@H!z۸sͻdk֩Jjȓ+_vmċuسk/+5Rn{ӫ)ᯟO( F\c5׈s94L3<783c` U&F8a ]t(4hcJ88 * 3DC8x84L6x͎=$D@`6)8s/\s-]3$N x晧@g.a*ڹ9$ 0kIC̴L23w'J觠zs ;lϪ( 4>:L0ր;bک+,eL;$*]6Ԍ3Hbm𺧯TɸB2$ -,N94L5S 0bkm H7ij4@ 0c9Ɯ93K<,4.0ăЃm +2t־s K2;B<8(pؘg9AdW‰ *. p:۟N-tn| >$8bзx 9cɛ'|ʝ E| *0,6T=M#X!x|G&_篿̓h=@ b{^qipl` y D3Z YH;0P :N#u i A{vA[y,.(8Ix.w&:F) _x#C 0p8Yp}E z"" h1pRȉW zph!E5 7LrV8 qD!/7񒘤Od!@8eA5d {PD1 *|0 KU0%uߐ. h10Ɏ_=(3ZJ3юqPh3ԁuxcarȆvТU71 [Hh[Tw5!pT#@>U5ElEZ\ājP:!1YG `Kԥ6Qq `dsE1)լhU+[M+8 @1ֺv1I[6l0jȣn7XF6jiL#Bh8  o ;%R#p8Q*||#{x[cn-(eF K\"Wuno#`P7 5~%Kpd 'L [ΰ7{ GL(NW0gL8αw@L"HN&;PL*[Xβ.{`L2hN6pL:xγ>πMBЈNF;ѐ'MJ[Ҙδ7N{ӠGMRԨNWVհgMZָεw^MbNf;ЎMj[ζn{MrNvMzη~NO;'N[ϸ7{ GN(OW0gN>uBϲ1Iқ7Yv>Qc}t04D@Ej< j>>o,jd4A f< ~tG/2h ~H}-h ZyA rw=1A DqwrdW @:{M h`=>Z `:h^z"0`pd`{l[z%zԗ{`Z@WF-DPr 284X6x8H9Z`vy+`,`NCpr@mq`}WOX,0@{[p|[0,7PNqNWpz~f[@{ny\9-y^Nm㷈};?vhrЧ @HІml`8Gxw\[`+q^Pw\` yz+.0{pPGwP't/A@{ipvh@Fhwxl~sjgz HzWXxԇȁ )xru`w{͈l T׈9zG0y1Ap87%Ѐ~^+. Lj{HXWx i/* xո\NT`0[py,9] w[b@z_ \,8 P[0zm`w^.(aSvY`>= lzrGgh'hHvzzZ`bP%[ hwn Px|`%\Mf wfOG 6}0{{y藿_G؟l@89 χx#8@b08}Ih h?\|_{ W@/0,`PGbwXg|A`P^r02":Wwwnma7@q,,P4ЉhJgLlxJu`m~hfaї3Px=`}lgvl'r~q{~jn zcvx[0k_txǸd`wI}[d~)_`hhpjB*wrR~~Yrڊj` {l w؟fn@\wX0@ȸ;(:SȊگ ;׊8 Km aZ񚨻X"IH%˕' y*c`Y[%D* !@VWG7>Ԁ"ER߀P$h N GB5]ն0'U0 R0S[ @`ҰO5 `&rGgVtn^{IVGL7TWALgX˺Tcke [ek;eK O'K!2,Qc* H*\ȰÇ#JHŋ3jȱǏ CIɓ!˗0cʜI͛8se?EϣH*]ʴӧP*mT(QRjʵׯ`vR`KbӪ]˶۷pR87ݻx˷++KÈ+VȪ6@b˘3kU*BTB3ͨS^ͺAV;*JlV\ͻoLw}[Vȓ+_,٥p߮ݼس3Ë_ݽӫK<˟=ϿGhnF(Vhfv ($h(,2(c8`7c<#D0c8H&2YG*)+299H\N;޼ (H263;@<3K<,9bN;$bD!l3)Q,\̢\壐j74ȥg)IsK4|Q3S[2,+4,P"pֳ1'b1g c-uTH2f2.df \0ĉmn 5s [<'JъZͨF7юz HGJҒ(MJWҖ0LgJӚ8ͩNwӞ@ PJԢHMRԦ:PTJժZXͪVծz` XJֲhMZֶp\J׺xͫ^׾ `KMb:d'KZͬf7z hGKҚMjWֺlgKͭnw pKMr:ЍtKZͮvz xKMz|Kͯ~LN;'L [ΰ7{ )fCGe1KI<GI,f3Yø2oEC2Oj/ \h%٤_>p/| 0>dFC|2 yȃ-`pO׍Y&> Q %|ɛ<)P i~&jtm褔R67O lY騤% >ߜ@x靡YꬴŎA +XZP&(F+U+ބM,qhalO56[mR4ش3ϰ4:k'/H{8L3T'|QW5<4׋hzy$<sR/x $B>Ѓ8h `.^ᦆTpS|xyR_'m&0@R.4X^4H0@!8|!?+Ѕ8l opV cE:R[F*ɲ`Y0mhh,pM</I$Rfy6p@$芢0觠w5B !S0>󌧡jkz״7+-zdzȂg5}dh@%$ 9clf{/r /I;/j3j;+/.{/׸o;ט#p#ޫюh.bg&m=;$2Wc4א<8$+S_51\<tq" ?G-Q!.,q{N AҩJe[ .:Ҭx&μ͘`*|kνw6>pӫ_Ͼ˟O_8g7083F8X .ؠv M6٠7( 3]5 (H(">/H@^.CN/$#PF/ .Kf٤\vehJ$дl&`He&ـY|V.L$p 9)餔&h;bJ r@ <ijJh,2 @/J L3{*ZԪ3X,@;dHR@[vk8$"S3r&9 n6>"@梫 [SL3&;.1$$3$cpw  >3q\[70+# 7 $%` iAHG333+ ef38 B:PIwu~ 33H 4J pZt}_cc#&Ժ I~qm{g Tr5L 0Ā(A+K⠇].G>,`;aAInn駇4d38M~N;ǜh̸7g7u$90N0O/d7觯/o HL:'H Z̠7z GH(L W0 gH8̡w@ H"HL&:PH*ZX̢.z` H2hL6pH:x̣> IBL"F:򑐌$'IJZ̤&7Nz (GIRL*WV򕰌,gIZ̥.w^ 0IbL2f:Ќ4IjZ̦6nz 8IrL:v~ @JЂMBІ:D'JъZͨF7юz HGJҒ(MJWҖB8iԠ 7iF5 g,#F AqjC.LeJST9эn4F3zԤ.O*_L04抎[IӘc#װ6ьfhj[ WcPsUV!(1Q c6E4zqc46! yxF;h648 G51Y@9j ..F4 i!Nπ4qaʹЭ(ej!L\gM/fCk$p!r/$=d+@(p' 'L0d1 1bY@1a/cPf|3 Y BSfAdP2lH8@a[4g8e|YHee8IPŬg9y,2<C`~(Fx1*TuZ9Qzɦpev7 fCr7;n"˵\AMr:1 57lې痊4:f`@!*,qw! (Ab16kĝKn CC)ZHfR\[5ĉ WI+[sfM֍څ w鵟S'M]sܵ3)ԟ{KkKlv~%.EeM[Zlئp$ e}6[źwH ,PO. Ŋ{hH.l3YA3\d%~@lM4E# >ȂN4$ 3D{B$X6x#7:ؔ; j!,/'%iӎ21K K;#+(Zj,2xN;dMR5Դ.|:ވ#Hd;dT4b:ਣN;G'.,rq/, 07dux v ~L_|uGD7+#4K\uMcMM2S7e!b8 #bd"qC9i0L p=3 F#n >(P%93d3/@L1#@T RlaC&bAXR"8 eM3M67S JCSL;#j-f-3]K!3, w H*\ȰÃ": \:jӮ'iIɓ(S\ɲ˗0cʜI͛8sŊ3n1ΣH*]ʴӧPJ*fղUx8]RKٳhӪ]˶UXr nۻx˷߿ ‡ [j[\1#GL˘3k\ 7oѰ!vx9ɨ7^ͺװGF-^_|sZ Nx!g7P6N؁g͆mh ذ[n5 R$ "3WM.yzοJ64K; 3@ 4@@$08eY6 (H4A772 + R@|{0̈DiՕxA-.”+b#d ^| ➐Hih8p3KA׈,"b/MH|3J C袌6ԚmIPS 3xHv>+hI:ꪬV $@te ; 4^  R^NǤ6,> @c/D {8 0<잙L23l/ 2@H,`$D,DBŰ\s Dm_& ;DN/HN~RXBdL 0C-d > AL3,ݤ L/ (H,<<0,ClلnNgˍO IBL"F:򑐌$'IJZ̤&7Nz (GIRL*WV򕰌,gIZ̥.w^ 0IbL2f:Ќ4IjZ̦6nz 8IrL:v~ @JЂMBІ:D'JъZͨF7юz  8x  0=N.C "BJhjlA HMRʿ4-   l@ y` BVP6DwL.E+@ڀ|U WBjVUX6ԨiW g`-DxjN쀏$ @ar|ᴨMj?tc!3h!+\/ -PbChPW4rψVJ51 hX qC]Qq WC hRo]W;Q@+YG;>r `K^b|tǷՁuH9g3*H;ގs|ܭֱr gF1pc 0s|#hNsqv8rC(;s+|VY6ԁ cCGntrc7ρN}h{sk;ؐѻa#tq.cwXbqy3R6q.W>l$S3Ѐ1;f;kYx bAhFqXG5v-NOddh3܍`#WvGx= k0vXEBrQup:@7guWopH~ix_Q:| g=   YiQ"7 |ifx av |& P ƀ% ݐnmiji`:Pw Wv90  EXQko!plQl& p ~Ǘwk˰ Rcn08 ~ Ұ6XQ ?qA7  gp ﲁDe06 ;{}0#7k7 m+dbҰjPn ~^ q3 h3 El {rp s` (xb+m?!Ӱ;x~ (9oqxxw}>'x'wx xx 9ـ zy c zz{灴g{{{{{_1 P @|Ƿ7k} }@}և}W6 W 5`z0=ilrЂ:aq &u|w*虳)23CxJ{* U :S:tʀZ#ZyHf :~ :p!P `,ܩȠ *צ-s ǀ ppz~`m' g  "W pB +g  ο  ͌Ԡ̊O ͵hq0 16kg q 6  1޹j*'I6"k, ;# 6` (2n"lpѼBs--س!ҰGwǀ PD`e z CʹVMYm@^I'0,e MR'r:cT Œ@_m[K=X7@ ОWƒlO zK1m. ZPj#@Q ^P ׾ՐpPPM<^Gm/}K%Ύq3 ZX` p :S.I = A M,@'qU b{ĠL[O" Ն L`(`LMb0 0 Q/ ?:7 S+M A"~Գ O<ς: E>!/_'?aD0P\qp1u>' Up9 .O!מ ֧|ԦOX L}P60,_P @`. + 0";P(A|%2kv6\@ $ 4 XA ǝtA _1ci f<)T<'Mc Aꎜ9v@50`H` AR;4=۠%AD!D蠳b3 _;sJ4ve̙5oWM2(jӚH0u.;'Ə#1H!Bhɕ!~"4XТœ# BXb++|6+&BV֫J9tŲI"GdYlb!!$`p "gƆ[+# #P 0 -G+ lFS`Fw*s 2wf)0 aR9b@T)DB`!pi&aa'Zº!"ͷ+(D@x`<0V˥Y✓(vg|(4R*3"? % 0g@aJ)ݙps P( k, B5U<+-Q"fIpI##C A <0Yc_Y騫1"oo:xm^P!R6cZXj,%+3I&1GgqAo+se Iun&kQ` _mnLn&`:NAuI`%$ a@1YrŰ{rŏ}xⶡ-jy:F$&kC)p !J>I*[o"/x g IA!khT\؜юY8To= qd%P#qY8uI2E`$)&׃xELܡ6&fxE-_XCox; !2 %TW)NEs;DW)@\PhQ%M~z B1M#88 inT~Z"2pGH5#UcW,8yʻ̇ pQ#$61PRAA-d ЊoB(2r¨uYu5#ypʧjdt šck\3:iknC# O& Xb5L y?B/f=j訸qaodBEQ~e%2D6`р3h!H+( *7kT9ĥy$pMFwP,v1%TE v#syl`1:䡎}Hŋ3y`,׸tZ("Ҏ^p2$OC/]1xL.Ƙb9_Ƴ}@2pHoϢ@ i`MA"L_xh0ѝwhf8`-㘅G魽`*@)g@ =uXyP@aHrEa `q;4 s%cpD8QeY8x2b3c:oB0 !@;0B   hbnq`dYFtPbМo1@?1,;. 9fP0g"Zs8)P"AY-ثJ`(2-^aj#26`X(x 3#jY"E! `D&DopB`'Fwh KЅPh fhFtPy*Ea .lHЊB8hHFTT~am @ -Ddn *8W6LadooM,Nl:t'jxG"\2 P!H? IAwɸIu ʃI"IȈRHGi NƝAf_@08̢"ihƜTTJPF+ ،ɽ \"` +!f +B( ᫤钫j ,̖@,NXr!F2^S\)IDKLҮ'tR+Tc1aWTX,h"GFĊFYO@Ʃ8AوbkL: ќ@ДJlY"A@5ю%{>K 4T)rl)]H@ {d,ZO?JR 5I02mPS-!R/"J4]=2J",!RaPw*S< l.󐫼rqr~R-PL5"ӕRx-Rox0"8pv[l8 +>F"(ѠQRwHB.]ShME5p W%WZ,OSjfn Q}TPqk4o#Ixv(i ii_vXsțuXl6kt:F Big ͨunPhcF iF?x'!kdfi(\Xr82PP"E|غYu u(s`%bڸ8mY -ll/ر!vxxx ʘ-e0:^uoMy؆Çk lPvn.vhjoZ`k _r8ge[x)\ [N nY@f{jbEsl`Zw'`ņqep`|jl`pra = |:Y9u歆ŅcPZsȅir)QKLsv'f(i_Zx\)JXvp`(_lPepP&E| o^$ФfpSZZvЅsHuPt@pАْl3w(h(qsH3s'h(Kq@t8uQRY&>Xi0]9Inb,D2pѥ)ZhADXͨ?uiPa թ~m]uvP{bž)v8HQ,fuFZtPKvXH1:Zu[usYn@ܨ͆q%.1݁i`l9^yЈdV,AXP/fq 5'ٞ tț5X5YVH;&hjFHqxv@{nn0^{>wehi`d@^pZ`dlӥ_y\_g``j`rfnZ(o)"dv`ZPuP)7>olpe_sX)Yx;im^W2L Pź(-r\ KnNgx_"X.ﵩ2o!\dgav(|A筦fBl_P~SfNV.9Hsdt;0|hx0Zx  t뭳PmqqhTH(q'džhA _&Hq$Or%_r|E &r)r*נ{r.r/Oυ//s2H 0 s6q7€7s;Wvs=s>vאJJիXjʵE&k@_Ӣz]˶۷pʝKc{0\ݿ LR$ڈǐ#KL2Eŗ(e+MӨMC3BBCM۸喺]&3ƹ+_μs ]H /ËP҄PT7gʼ>g& L-(VhaC :w (brj z8,ba%:|h8蕉 m@)9O-t5PFщGV4(\veGHe(h1p)'lN䦙s)ѝ*)蠄V'cYY袌6ء8#Nq#5C8@ÌENz32:j!BQjqrzJjqzK~ъ)VQ 9ő.-IkڇmCr-Bނezi8RFۮ&0n( BDN/ f;cL@LR8|s(k,2B,,̃5<"X;\6TN9U:N1˦K'nD.W 3Xge431Rq-4r:|8s, 0x <5d<^6TL;3- ;0:R4zI,>3;>L3M5 +N #$L-ˤ (00D$49xK4?DBhY3Fj y"lD@JJ.mf;#" ^a<)y(>F(=ꅣ@D׽o|"c[2q [b ?oxP)/Xv@ ",[ BʡMht (sj81w8 :2DKy$x ď8+L#~ܛ/X@ @D"$'7 …rG$2D"H 3w|Rni̥.IF؃!/9BRG!33 iE2Z$3$XT|dANqG)xs{. ! KH`.O-"; FZ!g(8 y- q5Gj84n%;+}4dss@O@1KhI?JԈs"d;ֈCށ B䄇Df="dv^!$Qz!!)>@P|Bh(+ +H-! ,A-b>-Ռf#4HvEp `b}H" ]@ BpD %>n1׺`C9:e$BыvCbdtX@!ЀF-S.#ae<H"6DphE+\ |Ȃ8-f—ْp ћi؊5iז T.|v4 s.񡗴$9 V$!yfr|!hk!6 DhB[x2.^*L@ 7W"rXFcmҊ CPgFDs3BLX |A>[­yC(L&7e 8A ˲#ȵJ8d 5g h@ ` Y h3B8X<X ;Re!/Ak΃}F6a@&`&ވ/ L x XPJHP `Y@lHO|4-EbSFuJA6_ u`0+ NB2Ga0X;~_İR葶#,8:Qϙ)3nqZCx,#O;*vx)g}vϊ0,=Uwޛ]qajh;h5fƻ*GfHV|ҐF1Tg#|7\?gx~v2Lu`8e \?pw/3]XpU.ﲢSY.U 7 YCw|# Xa7C=Mԫ{=h0{aX;]F)3$.s+pIv D7P Q. >) 0/a4~*<âH<0`y7 ϐ] ASYڦDx2߰M - Wax3 08 w(y5&R'؆"0@71T :C=@( E/@ty @ @ 5'x+յ08щx؊S8x1Qx؋X8xʸ8(xhظ8R(xg踎8%xdi85y 0 9ՐYB|ّr‘h"Y[B&N*ْ@’.62Ykb8+4ɨ /20yЧahx\ {Pڪ Q  0:ڱЭ hk`Z1+dpbq+ۭn0|+|k{k jxy*sP AQ_nK*W`tA?ۼK+ۻloT9S,AZ~p]yrzj^Ⱥj{KʺZ`; g{ !+ZPotmp`GP ~j qN_@۽DzLNPM l{R6WZ:Wb Feh^Wy)[r+֪Qa@۬1&Q#_`jn`naaj7|mq7=V^]| -\p+h- ^q۸j r \l0,<[= !1N ѿ|Q`̫q ,a\ qrtƻj<LQߊj{)dp\O~Q` pUp*k-jĮZ |%{q& af$1 1@vyPц;@JW@K81j;vk,fdK֫kۼ=ɾl{`!Z@G} `\ i _]Q (鼭+Am !!a-{JL%AdpxK O0\٥ݻ ,dm`:z{ZgaHݻmʵ}۹ ͺ H[ܚ* _leN'!J<ںkd]! F,82̱`g*Ai< 3Pqpɥ |8M˟ ,ژUr,K} ANjܽQ>=;_p>jy \X` (NNy [͢z.Ѩn`Ahe |Ҫ<ͣ=<$uy_ ,lk%  Q 1qzLb^ 8|u bʳe캋4jt#21댎!dOѳy.WL> 0ثP[0 q7Ί70Nw'jk@ M1*aՁ= [{- _*>zx>h\mc-:㾱!^ am(|/Fɼ. `[0c`&<9{ڞ]]c}0Үʏ|!1Am%0ms\R /Vg1b5$yf2̲4g/tIaui23Wgn1E6Up/y%Nk7b /xBd"9k,j 9hDh)B$-0KL V&m|gVeΣpU:Cnv'G|ć)3gcåh7#v/rC9{:Uoz#)n4:|:2QG7jƇyWC_7UjڤB6S[$/}"6̨# > B0"A**HF†.|&sRYĹ%LЫTs>ʎ{$ Hh7a++ TćMH)dHB/DmkNVO @J: Kdb6 5Bk[Цnrn+H'/sQbGaHr&6ls2\JD}D%E a,1n7ݹwHGo}SLg5P]U&hs\qsXSf|1f4CF5V|7fU3< qLe e`mO! pgŁyȣ`2 `BG5 x>b(c*Nq]ux5 3;_<6ᨆJ;@4 \PAlX7qU|dhF[f7hSexּ==;+]#Ѐ2qbu f5/3;r5wlw*kU09Uvɰ*>*٪V#Fmԡ^v: ehY7d6Vm5 \ס6L&0:*#m]2>aYvLŪ5ku>暗L6Sr &Ktk\MMp\fs2_X7Qdt¬E/!Y,4"lלKfvGXk6pSVu͎eq-`| 9[&w}ntܙPljэF0p g5/0 Uu\f4`imQu|Wb7d(m,0Tը94W|Lwx5QkT7q]Osw:q8/ =q/X! K.h7T.)Gu1tSIexV`q &|aָ:~XG3QlkO5m1Xێ)w}Bg6{v;%Fu:oZTߓ;cwJZphcxe~';9.ph8E|ܪ'Wrǜ49Α9K8qXs`1c-21d@:< @ 4vЪkpSuX ,A<+ +3?.Z;򣫷s{6=;,`; 1<8+<$|SJl؆m+c0o*bvxvʆS=yYpXe Z|˫pispg8Z@,C#>%;éphs2b1*39{+C4jvXCB#pA>s;ú=r[xE`i^Ph긯*D*dXXEi_E`ŰŪ^(bpŤ[lFlFbFnF_Ъ-b"-t;f;kDppfиҩc8={8-s,fePb;q.`CʉL\k`-sPbD.L$Yi')Q+-.dXB*jK/ƔF_ʆX6hз9C Y`XhCdKRDCs=FtG$HľI\iATEjlw@*,pl@F|KqJdҲr:>gP8+-qSz*+{3GbКA̯d2 Gs$jSD7uvtGxT,`zȶSj8FJ*<``_F|K:L*KFiъlN|NN|VNWćYvp\Yhs`cxvXisn-i9S{eYx-S:c brXbhSosĥdͤil8Y8ZpZh[8slaȾ,7+79[2*8DZcZo+5\ Q_v0`+vvo˒ZC*YuXfv:7tqn0ba@ :Ǫ^P_cv`L>)TrѫXPg|Ȇr(l<:pHo#quq whs]KJ#exh`=b8SRHZ}Y!ղʅdђiPbPnyx1L5ū:u[vhA+\(XP-uf;@TOm u6P)A=vW.Y4Zv0va=WTf.v[*FUhRvx- EDVa}=C/EnU&CuCZgcYRh___冄{ EK7*Y 21NulInƷVx+7 anP XZafsSCmtc_&.FI-_Q8#g&T2_`}Kܥ Nh=^CQU[hk觌h~hh¹gFC5BJ.ב^i}hhiSivihiVEݙ&iS->iiNH~jjii^l~l.Ǿk[q X>k†sfkF.m6쩖lƦ읶l}j kvVm&>fFm>̗.nCmhnJ&l>~dnlh^&ꨮn">o n6BZoj"~.oopȶ=:hUp.op#IJ  7!1,za H*\ȰÇ#JHŋ3jȱǏ CIɇGʀq˗0cʜI͛8siQϟ@ JѣH~LҧPJJի-!hCS`ÊKٳ:+hʝKݻ%0k x Lj XÐ#KL2F)GCG߿n-MT2칱"c˞M6PBE6ᚐ ^ͬm4fRУf8}@j.MJ%+˟OϿ(h& 6F(Vhfv ($h(Ί,(P8c4X/)樣~-b3h#;i$|=@2 9PF)].#A6`DJuA 0I;<2@C7|L;ܒ 0b 0@#:2M1(p( 4`M54 3`**Ub981jr><眲̭ ;L; ,h0x L @;bx fk4 (D >| 3@θL3Ѽ;@8sNDBt(Χ4*$3Ҙ@SB%`ɳl+#,%tC38D,H<@~\,rH 82> ` qM6 *ɖ]m2@ ]|t4ұ@`!Ž6# Vu 2C2Hg65 ,Xp`4w}.;Fy#  .\ h1@Ϛs./o~qh; 1|Z/Cy d;4<7oKo㣤pڶ1 Yk|LA u#W cq@Y N A!x4F5/AaK8~Cx rx6*̂ ǀlfC;.&!F% shG3t6"ʠ nfB/y4!  l }XA n@<^PvR-0uB@,ZP4ڱ \B0- Qpd! u਒is˻W;DR[Aґt\3vkh9q0"!CH@ d(#U@y#p`;q(iNu3H;y^0eJOxbhbC (њ7ƑiLO`F8pCLGtHt؉WŢtNqj14Qc0Z$ ԧ@*QTb 7hq:k$c8GU |0ŭ XBh91h]f7z hGKҚMjWֺlgKͭnw pKMr:ЍtKZͮvz xKMz|Kͯ~LN;'L [ΰ7{ GL(NW0gL8αw@L"HN&;PL*[Xβ.{`L2hN6pL:xγ>πMBЈNF;ѐ'MJ[Ҙδ7N{ӠGMRԨN܆6 m@͐@`M+| F6>WzZa 9XAz6`a10@c'˖R[l4h!+P<D󵫣}TVvns݁\ v||pq8tp4 Z0*pD WW6ā vqoHx 0@Rr?1э\ֲv5!,aLBяs,[OtK] bQN5__zɾ#4!^@|1X4 G-^ 6ְZ=GvǻC !Pv >yo/ٻ\R3 o|n.h'vƷ uGb l70?\p4d(jC j0Ca-˚mx'jpw"l'}v\px x"@&rP&p @ erP- 'd B@+Ϡ eQ!;+"u-D84+OIXM7FQX4S8UP %؀ ` _(րY%z 0 mX8zs!-,e* H*\ȰÇ#JHŋ3jȱǏ CIC& k0ɲ˗0cʜI͛8s<Ο@ JѣH>P PJJիX-RX` YÊKٳh  pʝK݈Rw Lᜬ H#KL催BRHBRɺLӨǪשc˞M۸sͻ Nȓ+_μУKNسkνËOӫ_Ͼ}O|/\g߀~h V؀Nh v0 >`c5ׄ.# :L ̐8,#NL6y8"K+^c8(75xM;p Μs(tZ&eX3,;D9p0S&D~(7LsMv*,4P%4zBzh8. @p@@0b2i vAE2 D+ 3#fE,AēfK,ⳟ0̂E x lR  42>w(d 5p#3HDM;#KC%44< bs!b1s_ ,_1(7E:`&>3 14L5d#2A DX:7TptAR>81 ]=~ /}*vܐG4sA\ @HGN8a':@>˯n;E M4H5S 3@ 4ZNz| #;F pEoz/̴) 3|43d3%M~~: Έv@G>}s`~;w8FA]m YL#H3)BƐ=P3:C} " #MBЅ,vi)pF0ѯ=P=!,yd+ H*\ȰÇ#JHŋ3jȱǏ CIIL֐q˗0cʜI͛8sB< JѣH*]QJB6JJիXj}IE`5nKٳhӪH돃ʝKݻx] d`T|LJLÈDzWL %L˘? EJ MJ%+ӨSΛ װcM۸sͻ Nȓ+_μУKNسkνËOA0f˟OϿk7>߁&H | F(cVؐ9R(ah q$y&bB*/cv1fO8v@H&9: 8Ȃ0$<,P;?0,#N8蠣4ȓ" 4 S >dC730#3_8䐓M{/2*L- -!4#8sN1(I1:pL-ܒ;(23Ŝ74+K8rH tsg 3j(‡2C/HJW 4$ 2픣:sN,pN\6 G 7%3j4XS 7ܸG,L5{r@ : @L<I$f:X1#I #0'%H*P1`)D4L'|+H D%> 63rC!?=4>,H{;H"U騋$AaE)t\fw %E hb$*8D DD =ࣷ=ϰ5 TA ,@ P83;00XLM5>4[̇ x#IE;aY4A3lw.mНaAaxZ$ *Z!0fA@1 r&C ?K#\v#KqXt]QH)>A 4 IP;vlFğv!{_`6+5IJ 7,أoLhB:%w|"G4\Bx,d!hJ!ơlHY8b!2:HJTӔ\Azz"KYR=.(2Rt OmyJ {8D((=!&rTFч|Q !x;^QZUA jxN !$% {an gnQ]>J!E3QT}8+!@P>C)6Q w#0՜$yM;ֹZШ$ HpDvb7р,,h @Ձ8bqA_iG.Ƒ c=`g(Ce FೌvT@ ?'P0 H8fpғܱ=1q0G8َ^|cN"б`d,1x9K[ۮ'Y e3QbТ 4UUIcQP4p4;=kJ!3@_t/>bKU= ʆײ*DP{tKF6aD%@0 -#ؘF5`b+Ә/<PDވh(BN@ED$61ϡb'0"9Q-ql ȭbPdC=9S>,SA@< i >Lj9T4o0ƒ:d}U9Ր:^aHGĞkdfābk=j{3iϩlf8Kf5:\ tȚub^sST7hc#[emm 4i(gh?vqBfqQ ފ Ǻr !Z, H*\P!JHE/jȱǏ CIɓ(S\a˕0II͛8sɳψgO(ѣH*]ʴӎFF}s*իXjʵ@z )vٳhӪ]+UbYKݻ*7N _ɁGB+^^'pc/kl:puÆ0[΁[;`ڵ5<=c6[5|96;[k,i(ˆm4Ӻv ln,ι[N1М'7.ܵk֬M5k}f8x .s=t08X/` 0831>$2T7 2-3834N6#4 vΐ爃7([6dS1#,0#4Ph/dS_8EҎ1EVM63ːt&tzYh3"j.[oHv]; 9EGt]gq,wyWz{7_}_8`M3$8 Z!6s/xb+((6#hD0lxSMl9lM)fŜKhfY'0֍#0Ӟ8# >, % 3 7c3ij᠃ΘӌH=+K@@/1S2C3 >(L8yp B|أ q  |#F5 _HcP7xy Gćy ;$iG4\HA 43aOPhG8o| '(G{ A(aT'΁|-l3ƌZs0@phB KhzP/8"DH% RI!)S0-2xŨeƂq $;t_CxcB!C cA@zlI@DCdɀ@u$02nQT WD؆:j]" P" A\ Eѐ daH@c->,*$(F~ n|#3xy 7d & 񱀁0;$P ,  Ĝ @|̓4C T|9HYT(E(VlU E;Iāb;|b&4^q ~=J i#)B1Yt:EGO RT7܊Y,uQlRMxb%34U#S_dA.f$}1 p4x:҄pAt.Vܦ̧<ap0->BUJCG7l$E d*>P: [(x"AQ ]¢sGk">`rV|8bX*|;brC8A zYp| '[_ktrFl9HK|7w,XD EvA~`| @ЅLC1uRAv ‚딱k[Gc@1[~ ͓o6НH j >Ba6./ `"P|CK@ -pLȢi)s4vEک"4(!19f czR*W D A[(dE-Q 0δ[@cTp@ПG%|t||:cYG 7*,H1u\XC|/qרbqa~ 'H/`sdPF\H5""N(B1^ h0>Q4IXVt'kjߐ.Q l}™\Q4 P%g7 15R `x `PAz `XS w @r !`x(Bt `2DP% D p$ n8AP `ԀC w. X ( 8up#̀; ߰ w|BˇC" }wx0CF{)Q t g  $8/x S$> FP  @D ` /`C? Q Qk3=wKŠw tFS No8`U1H$Qp(' PpXQP 0+V%!#7}`ssc(G8 @ 8Ctywȇ=B2(Q b 85$Pr"P>#z`46lT#PP#s3J] b ״?@ Q 6)$Qѐ )Dv Ƕ2p # VJ-f2  P'{+.x RX# 2X# @$  p6 !745GbyI7y i)yi96RʹL)'Ùi)ɜٝ8ᜲIISٛMVٞ yI九q)y"9))搜艝I iy٠ 1IZ'ę: ,ڢ.02:4Z6z8:<ڣ>@B:DZFzHJ h @8KRMRP:XK52;Zb\cj.Hk:t݁;P'uڧ~*`QZ _'daNQ >%AfF )GP fؘ:|uQ:L%z*v.wvd()0 P ^yzݩ70j M7mVc aJlڮ g SD"L`gi6p#|[mVwj2Ė"QcaQ4E Q% b[CV ([Fpdht V:r(:۹U6p $\3q c;[SeBbZg⺴gV4chSkn;[Z) : a(% uhoL?po{CR& OVW vWxS5:#PsK?M7-Q # 40SOvJ cap ۼdGz/bmj li*R)B p BFH#P '~$9!G2d+ # 1P ]*!.R$2;O2G"f \|8п +2c G}0A)2O PWe:/@lP( "YAܳA$)dȀ |a-A H) @ !!V@AƗAD<$n3Q%T0.r6[pưa<Ƶ Ġ "9h<(l<ɔ\ɖ|ɘɚɜɞɠʢ<ʤ\ʦ|ʨʪʬʮʰ˲<˴\˶|˸˺˼˾<\|Ȝʼ<\|؜ڼ<\|<\|=]} G!5b%ɰP 95)_.yk;Т$mpő!#ң#3R؈21 2h$.Z-2=CRƇӢ%=Cx$`e1סK +bR͈{bxWmxϠ"*_ɛ;djFds=4ouyv}FT@1ɏr\ؗsm(.T86-ٙ[ ]E,qB-*ja56a.B1ҥ+N^&<ư&N} ŰAzp]*4?i;"&3R"^aAxN.#xn1>>(̮Ϟ)p) S`$H3$”a j<>3(`xgx> 0~ /6Fi#"P3 w45gp`}FP#c3AXW 7sM"|-)0?~0@5ρ2 [ Co&C@ Y#NNlh|R9`@ 0Aq: L(#jL !* D`wXItsMdϱ4V0DGYH$k2Ϟܱ0 p0GL^oԘ 0d^Ijh%4._ Pn#g .dX0pպ‡۴i ei4$YC| /I1e.Ʈ!9uOA%ZQIC]f튉X ]PQ%O]oM+gn\;he՘x#d7 \|ΜCٱbEL:yʪ5טA ^CwY;l㾩Æ ^dKn\va5^w+\C`ٚ5-ڹsܢbNq.uk7k;`5Yq!g;vKY >.|̅+Xb!GŊ3| !_d(10v hR fnYa(B@jE[tEcqFԑOt@YFL\k+rEnqI[hFs9> wڹfasʡyd)˛.lY6!4fIup&vYu"%sQ漑Y*vaflGFɐ_ԉZF)I" kh=qi_&kh_cJfe];g Ppp( PofnPϱDOG "&Ihx` 6`GR'w'hjG?hd 8Xfpghq :f,L$'|:P`>"qJ"1Di AA h8#/] ]Bp'/pJIP!p2qmzaBdAq YF8 nCs<|F> 2Vfg(C0w d7ΡNÇ96a$u>,HMr0C3 )f< q Q"\A7 Ǜ&dƆMC~yը">@38Wx myK\tZI^PoL#3^'w(X]A8!: Y"0Y3Q,bS}1!b pf2a3~BюqN#IdZL$FFiHF8GB6IAO i *^tC#a,QH ]T;iQNs yBj̳aHg$]Ecn᣶!x^J. 5 4י̱ ʨF6!w27] k|e6``6\ CXrD%Юm '>f@  '1lSEQSG:^ m XJO}[w!E7b .nG"! I>Cg0g$T:z $M /D HhZgYí Y)>aC՘iA"v7i#_daߊuH&Xdž6h,{g%̐>贩I`юuG^QOɲ!4{cF`0͗,@gQ5屵"hg0XP$ ` zmeA3 a۱3s3Une .=H[UKj0H!Ip*7˅}A\¸B6/qM}j@!`ÇY lp7 A|03r$&4Lv̀sA+OY#y^LG|c}nǟOG@{cQQ-ԕ/MsisTpù|!#9,*BTG\ 3!i,X(/ \J01B cD72 k F)_P XRa>x)B^ǂD0+YǯmdhHRŀN1EpA g#ʂ7aCAA]*Q4XE$?b2T1o8=&AF;xͶļ(uq r'gK\<0p1D@1j6RS\~彑e(89ʁ_ĨR>pY4  #R`F3 "X !iJ5׿E먟XKc,ickh<*׈x#:kw0H,kYv gX"! O;PhJ\bkP 4kD|8C\ߺCZ=&?DAeC9uiT;/t7HKD~ NPlQ,EBEU4SqiXlEd[E?LqjFb4FBFeLf$^xhF`ka? n̆o$bA_7:ulwyzt{ ;}TGqG`HH1'\@#Lԩl4`NhZq@uohBEõPC nFRK^tp@;|pq Ȇְ}cuDw(^LɆl4bHiX9IŨqih,#IeGrH kxk`D(jl[d(_eQ$YHUysG ]:O`O DoPnmУZ QY 'PITJԝBTNTOTP% L݌ US=UTMUU]UVmUW}UXUYUZU[U\U]U^U_U` VaVb-Vc=VdMVe]VfmVg}VhViVjVkVlVmVnVoVp WqWr-Ws=WtMWu]WvmWw}WxWyWzW{W|W}W~W]Z7XK-X؁=XmX}XXXXXXXXX YY-Y=YMY]YmY}YYYYYYYYY ZZ-Z=ZMZ]ZmZ}ZZZZZZZZZ [[z-AXtXb0tX$J<b~ 7ɰy@}SO_H#[{o/a[`AMeN(՝e w tĜ \B-=\= g`A+bDJq4`4`xQ;YI:]]ݱRG \H]Gpyp ^%-^ قR/v ǾoX siꐆƧr(f8(e ujxWi^ h:&Y]h_sP<*\U^(Z೾] ub'{]8Nna؃Ab";Z!  蛒H!ph !bc x謂Y>,`C vc,Z^^hHc5nagPGHj 5GX/^ӱB*@Dp>6 0bPݰ#dOa]5 [ir(6J^cc 0`u`kY/{uhe6Nx-|觅e(e|\+U#a>ݺz]`Kf軚1 vDQ&t Y`IJ[x5`(K_ e(7u#k6\(#Mk?dAr`MX!`lPĭ$~ih& jjjjkk.k>kNk^knk~kkkkkkkkkll.l>lNl^lnl~lȎlɞlʮlˮx{zˮvdl} t &>V @؞ڎ1ڶEZ]R&n(Fng8funnႨnFZFo}!om2|C `Ht c\oeso~|ل_lp p p p p pppqq/q?qOq_qoqqqqqqqqqq #( r0('gr%((%*Rpr (%&-WV/'&27P *( hB(Th7TVs@=tB/tC?tDOtE_tFotGtHkN2pMtgtR}SMoVNMSeu(u!=TWc/ ͕,^^_YUZou[T]u_`a'v`NyLe_:jvgvJ i" xdoPvfvWŇ6Py,a v8 A* wGf?^ﺫewSűx |*Pp K~NKyQ_8yExOAx^ xPUCxy'C +x2AzP{{Owzzywu?xPxHw@cT?'`f Iy'MYGtzz{/^CHw8x!{{KhAxI {txD >/,Gzw >}EpXA {t OTaȄoOxzXZg_zw@_@XY07|,h „ 2l`pf>%Hݡ%V ҝ\Ӡ9;,I"eX Pv튝kzNèRRj*֬Zr+ذbǒ-kaĉ-** ,]Q$%k2Lw˹s;X΂ hdǚ2}z2̚7s3Тf5kNj=w繖(@KsEzL- y d(;D"Er͛js;o/-_щ4̷ ""aPKL3M6EH@2c,bO:,#i{.隺ꚨL;ڎ5ʫ:l&5>->%M !7;[|1{vlQ/sN1i9p30c,69`3/<3,6 :T.cA1J< 0)S1M;4 q8NE9L*22l3:sȂ 0Œ8#G'ry7}7 >8~8+8;8K>9[~9k9{9衋>:饛~:ꩫ:뭻:>;~;;; ?<<+<;>髿>>?????(< 2| #( R 3 r C(&!(!F<"%2N|"()RV"-r^"(1f<#Ө5n|#(9ұv#=~# )A<$"E2|$$#)IR$&3Mr$(C)Q<%*SU|%,c)YҲ%.s]򲗾%0)a<&2e2|&4)iRּ&60 !y…+#\76d3{~0 . D'unѣBܠA h@$u!A'6@9a C-h[DiN4x E3h@CA P~ `>а3x=CL7Ӛ9ݩ@0dA t QۀԤr2FҘn`cf7Yc}8dQ\XZW'dW,aCd2c b'F$ml2( YnORYh90h!/,w" 8Pܹs[̙3q׀={ŋ "T!D1H۸R6SLൗF,yr\Jn+[Sp@af' ѣG4qJU_ӅRZ;>m+zk1\1sfC7.[jC(p| Lp_ҵP@ \#gW#_GDZ1(x@E.7h3h>H 4( {[7X;&R|Ԁ$Fœ;g츳1?`Њ訵|`];>yS|!ZbFβax4_}ܷ~'e#9(hM I F9 CI5X@$$ d8! j,%>1;4 38$ Q) $\K.]2pC YTn`, +1d~v8z!F !|Wvܵ,H#2R)WGc\b6dլ 4HsWM1T-td@!-, dq H*\ȰÇ#JHŋ3jȱǏ CIɓ(S"P 0cʜI͛8sɳϟ,BPH*]ʴӧPJ Qʵׯ`ÊKb)@ǤTٷpʝKݸ Hw LÈ EJ MJ%+˘3k9d*|BݹӨS^ͺװc˞M۸sͻ Nȓ+_μУKNسkνËOӫ_Ͼp˟ό-[Vٹހ|W~(|a(8fs5Ts_5~X(Յe~%^8r(8DL3Lc>,EVydMf=9߇L3TYd}Xrl&|`ic1U|2N9/xS -Y 0:֖ B cW >02 ^{"oi,")x"M5 sw13kq ):,4#N6!"(08ۻs"9S7c#l[-HMusu"C`b,ŬSn'm$< 9c!+xw%o:M&08.IO D>ygPn )w&J90 Zc5cH0o$$x` \L98IO1"j-dN)25`Ѕ@<B3t?F5Ё#h3*j@o40#8AfT =fN-h@1C,$G ĩ(ZH@]C5v5eD0bdH]F<Q:+^#Fgb0G;V Zl\0"F:򑐌$'IJZ̤&7Nz (GIRL*WV򕰌,gIZ̥.w^ 0IbL2f:Ќ4IjZ̦6nz 8IrL:v~ @JЂMBІ:D'JъZͨF7юz HGJҒ(MJWҖ0LgJӚ8ͩNwӞ@ PJԢHMRԦ:PTJժZXͪVծz` XJֲhMZֶp\J׺xͫ^׾ `KMb:d'KZͬf7z hGKҚMjWֺlgKͭnwր6 @z@",$m fvOӆ8yBl[&3 $`w]~4x6030réE<(}\L P24ą@|3_81>ЄAukj8-\7j6la/ 6F^\:|5%3lXvCfP݁am;< h(;1 w :`3t7^Nq' c8hpCFg4C̀g4 j0}Kk9z泟hA˺qFF;Ғ您7ciLk#̧jsU-T*m`ۦoGq6u 8Aט,эY 3p%rP,f<>f_;G0EpCw8G 8R4'tDlq4Qo|CG81"8:ю࠼tqP-7 r8a "h/ \=cޠ7aZ,C|fR,`CLߏ:.ZHJG3qgNje 9(1\{4d \4h)WP8rO}DŃу?8Mj<0t 8qpC|wF_0#ZЯoh "4D85h@Aԑ u`#pG5a yB$50/ F>c,w5x$qِ A !9 cAY$h$~b1H! =,#=5A.u0G1|cAY cu$b@u">  @o  $@x0 gx@JG`GB" ހyQDynA(`(ЂB5H'# ,q7v?H"5a ʀ$U8 X͠ E` `@ őrr-rgjc  à B7 DnGtKtPa1 ['u`'v`# `vW q ٠t+xg{}w (xҰ-xx '|y z rzwz!gz2 g}{ {yP]7>qˇ·W}׷ ~7#ߧ61 ʷ~~:G6yʗ.S|850Sޠv z Ė8=w3"h25a-X ` Q6}us0;Y6s` `uYWPI~ q)yt +9 @ ` vH8n|(_ (Ѣ؈gC@ EXF-" 0 aqH =V Švu~t!276[B .rP *QE r (s ЫPpZ͇ ZX #0p- ` 0 0H рy s0 r 0~*{!8AJ5$R ;T .7G{2s|62gYyMx@`1)J! 6ؕ!R k$Enat[ԣ_H|t`z+S0yw5"%т+2ƑְٟnR(sju A@w* * u> !'σᡒp xH 1@0 ) 7Z9 ;J_@@ DjꐢZ`'`OyjJvc}+)j]Z _jY:Q[h2zlڦ  2[{7:FPPGza+s&0 fr2C ` P B}ٖXs3jI#z"=11IƩn P a + hӹTAzz17[z & x1{*'[б̀ ";Ы f[.snz kJZ Uľ0 Э/ _ `+fV ? +P'DRP,[ 0G(;1b p wp&, PYr'WY  8tɐ J`,P "j"G5G~ٰ⢵i ֠~pyI d4 )* C `ɘ<$ t;K @ y{ B80~ ưtp~p= (`1Rr#9 dA ! jLր P =3eS -v l@ P׀(?m @wB>"P ;) ӴԠ ) )sMW  0ѐ6ð} @ s = <͟/!H6l@s?)], x p*ta P-Y'  )x8 8f!j0$ M+ { # -e˓Ѐ?p؏+ j- ̰S\@EP`tPHp8AD-pPD+8p `k+'򀠁4+00  Q~ӀP0$ 0rʀF~@>}3$7@ ƠFQ K}AY ~B +3!)Z 0qqACb) As B?$.PD _k0@OY0y9MCPB/چ $0!(,"A20d#>i \E;%*Ν$" ȳX/ (I .(P$wܸp;Kz@:iT,PF Y s*"A˖-\2eubdRx x$+(Lk[ lM?BH A &\@`"gJ[Yb5p;u`[۝U|#z7m 1`SN^DII{0&|Y" b*L캊DwN*m!up.~d"Hb9܁&`l&|QpGs*?2J,rK.K03e'ok(hB~ 3wrAgf!%欳Bc )jQs9,3!8XD4^&(C9]tZ|+0dP%RFlb!P@@+aX!Qr|UD;1tf(rHjmCp&"B+نD$`r &P0#Z'4]oHzJޏٝU_-8 aR9b@R BęmY2Y( &@x`.(1A,T C::3JQb5EVڒhThYP%``҄Eu 9iT3M(o|cG" D,R($$i=ϥ(me4C@(#U! NnF7XA"I&ÐvEY̩XXLs&8ATT"US@cJ@,$Uz.m[z1I`6@DF {Xy$/,Q:FlF1Zlg[Z َY7*N0gqdl-'sYx4)l.#SV9N x3E|p , Fx$rKN=\,#,R)_?,mB |% Y)ׅGX%,o8+- \b]z&}E?#WE I0y*`"pCC{[  He[!ߢCȬ>wG>4 E~t+޴xv"'l%"UmRE=Nۖ3ƽRSl0hoYR'E"BN:oci+(YHzg@M;rP2,g8 KkCȂDqʡD*qqHdqxйEx< x44jW4"86|6a$q @sKuvC!Wx") @̺*C # 80t9qivЂ$)Â0y;ztk 90sحh=?9 +sᯚH&%PFpki`ohsR+;aG--C ѺҰDUb%C$V &>T!0Dˢ 9bquB(siiH&[_8JtgJ=:ڼ2w`hFGF)pb@eB S2Q{uXy k|t[qrP- j }dv@[E<2(.Z"IXFQi2 @ <,IB"Y&c'tvHBJ * XaX(,h(o d2†qIK'pB! /ZB0E  Kf f-g8# l(4e8̖i-LZ-K`(ɘÏل*V*PcX(K9, 1*X *bÓXP`ob'1TЅؖP(tP`jBH@܎n,Lhx(1Y=n(*M+"!@>Oqep`@em(kM}qXΪPjxM"ȃPSA !,| e Pr=M % QёRϵoz>iMP"(վbp2tiׄM E3S ]Ѳ@M"/F5G}"mA$"Ny8 /U{q@xY=Xt(`=0 ,Vc"H;s)(˹lmֹ@ɷQV\h3OdLy؄ hJLRPDQ ,11Vt[#;%MTX4taı-r#\p4oQVɚκ넴slVj 'ImEШXVjPz i5Ϥ2}-P@Nzh $Y^SI3Cm-Qg8Lr؝KFUM =rH'KI#[?.UPuxZCR8iM5mӁ>|]@Lc QHw<=[Ps^uo->[E(!l@j] svhjo, IfoZjg(go̺`آnmvh_8a҂olupa"fc0|Rbva0ocsU6cq(`GYvc\n؆n@GS#]̆lgehj`8,rl(`bchs.baY?u{Xv\8e`0\_j04tS]v.f|,;{Z,JhpGv`/p{dlPeh4$o3K[ƅvȅ[\t@_0yUSNU!loPYPh/JnX;(1+NphIv;yhk("n^˶lI.Zi]#Zv8~)ռ_yZNM_&`-lpta~lDÆa"iXt"0g\phu t?qcqhnlo._" -(rY(+uP.Vo8qmt b;l"ҡiC6_omȢUfrXpYbnVJ9svH-ut>aM.n`C4n=lnemewP/deofmZs8.|hg+>awgh[0*Zda0Qk\h g`rm2f uH-1gZ% m0=oi?fq8Po[{܆]6,3aKfHƦ^y>)fk`Z~4_`inڕ7ߨZp?YߕalP‡n,"mQg#Fvo.uh'v_ȋ(qv(eGjZ†[ddd <{Tl\v#[ufhLsly N `Yj.Ἀ|@v܂yEyy ؈?-WyozJsikgdk_{{?ϊzyG{!*, w H*\ȰÇ#JHʼn2j 0`׮wIpJȲ˗0cʜI͛8sɳϟ7 cȑ&O<ӧPJJիXj584㸯`ٳhӪ]˶[]Å ;vۻx˷_n K2<''ǐ#KLr-,KgƎ-MӓfҚkyV۸s}S֯Cڼ+_μy\KG]dZ'-7i%S H $vG7|9ONGn-7ВL;~Í7؀4p 14ꘃ߆v ɵ`2 (ϸ3)D,8ˉ-&f@$,$̌Ӣ; )D&"4ɬO `@ ( < b!,b;J"CDdhx133c+H (O$8,Xj@^/<"acF*N rDC;eb歠^;ăE ͣj뭸J$c8͜vJea:CVk*Nji$ÆڧY:"7䴃K5@;Q!fr3!0X%*(#9Vl5d;  Tp 9 $M~`&lͤ-#NF혓0K8BN)$@ (͌ \F#;%#MH<|6~sb޴:Xw|k5Μ YL3턃:L; ,(N,,Csߠ.N)8ᆷÌ97~M;X xM,,y[T Jd28Tx3ϖ7괓u/@ãd<3|5C/=>Ïx/`456 HL:'H Z̠7z GH(L W0 gH8̡w@ H"HL&:PH*ZX̢.z` H2hL6pH:x̣> IBL"F:򑐌$'IJZ̤&7Nz (GIRL*WV򕰌,gIZ̥.w^ 0IbL2f:Ќ4IjZ̦6nz 8IrL:v~ @JЂMBІ:D'JъZͨF7юz HGJҒ(MJWҖ0LgJӚ8ͩNwӞjR>$0<Ч ^Hj@+@>0* Bذ/.Ѫ։\ 1jʤ U\5d H 7@.W\u*o |W4 s0V6 m+>6li0 r֤ hh} WDeIq!j)\u - D Y]ޢag>x/g?-X6=i=|[l@\|< ^t{0p/47xCs\n .B=]4{6 tF3p }/G^l /^ٻzv5kYcqC0+[4_ 2/qӬf+:汏,cyLFd[ǔ/RcY9Zr0+ 13nѬf6n@CDR@HLm ȄյJu0-$ZG>bnxc$`8AWx3Q eSU ΝC hm@>1pXdzF5 C /bx$"B4⿿0`@(WQrp(Fz `C8F6 ~((w\F|D-Vɻլf"\#?9Rαoci7 |+PG1j<5ֱ~sf@fc8S̭vօsϜh@o/knȵN6>>rCtf0sɼnf#H!mg)ЗkV%$5rkBш׎sq"óhp$˺yj_HH @_xÝfO:[p㻾F_rH5gyOA}tAsss7}$At`tHgJtNGP'u@uȇH u? v;w`vhvy;Grp'wVwww{wxvxx'yހ|ƃy_.Ȁ/?& vZٷbb8;f}w00 @r8t8{ pEy]||ї3Zg}ا}"}uX 䠇܀ ` ؆րv)8  (l\7 06 wXs{ӧZ|B w}AuGȋ[W =Iss7sҀ 0 pX hwx! 10H1ǀ P r# 戉 q ِ 8Yn}xQ ͳ:[WͰ ِ /HrI !y7@u0 "gyp|gz `sHtPv8 !`XY`Yhiٰ6c3 AxkDYk1}[Gv)  ׏p aiIp ܆mqQp 08!=HzPx+'ـ ٛM=ԃKJNݜ8D[Ժxm] ԫO=T̈́R]\<}hlclX͌o]`mDMA Km M}׃]҃-YA~MzL em-HٖMٞ=Ӛ֊=bՈ}ٓ׏-u ѝw݂h)бֹԣM٥Ӳi}ڱ=Մl]8ۡ}Zʤ]م-%)ͮv}ql|{1mv-ِ"ڣށ![,!cY, H*\ȰÇ#JHŋ3jȱǏ CrІȓ(S\ɲ˗0cʜi"kܤɳϟ@ JAB8$dӧPJJb)@ǤTկ`ÊKlDV a $pʝKJVQ) RdLfScŸcĐ#KL˘3k̹ϠCMӨS^ͺװc˞M۸sͻ Nȓ+_μK'̲MËl=fgw`˟ULVA=at VX!fhԃ2$!3$ay U7Ԅha0҉-"&`2G#7մ: 3"M;!4 -!;VL;4s5\s͏t֙PN/#M,XB J bS 9ށx f2f^ ;ި#pi稤A# a;D* bKDOCN:$X>.+$6*A$A"P($$j,2n4-- BDAB#rLJ,mN:k*M%~Y/j ΰXl5HL8gKAԫjXf fC:ܘ̱;1P8,<͙5' Mf7E# 7ʹ5, ]sx*% ԛ'>P9 4, I /H3͍ JA QE$b@MQE$RC(@9?;l9+'N(0PH#.4@M4D+#"Aa^% ۀ~%oq{ 0ʴL8Fq `Xcړ6ځ9Q go[ /\Ec~FF2jdCz8đpd#F6 :CP,e; c(VP8vЀF;ʡlp3 sZPFF`l`nP,h|ʉQ̣nfGa)p(p\c88&CoB5q6uУ(q3 `C&l##9tHc{E;V7`"|7J|rȜM@!*,[ H*\ȰÇ#JHŋ3jȱǏ CIa5d\ɲ˗0cʜI͛8'9` |0XJѣH*]f>hJիXjU UJٳhӪJKݻx+ELJLÈCA&'LvY E+&JӨSLkͪc˞MC֯_ͻɸsM\ gi*-·vËOӫ_Ͼ˟OϿ(h& 6F(VhΆla8(dv!#`'0b4U3ˎ@iDcL<ȤPfeER~dWbd: 0 08 ; 0D>㛠4 ,3ˠќΡoF 44S4d3K<,RJ\1޼ȥN0 ;DZN3@L-2M/Ui}gc3s0Ӏ2H yg;zl#F,4BH8-DS0Ӌ:F$N"N7D" 4\340δx2 (N$v >+8@ J<, ,!4EvR, <01O<8H`ss7":i<3ΡHS1{Rœ$ǡ΀uC1H$C0(XAH H,8Q90Gl,X\= T7H Q7E]+BHHTQ1|G QHK7Y3 ) P 0;S\@ @.b! rpHU"z!|DV4^èȍ;{"24 N ̂OƂ" >{$f >!f[+B g,o䋛!!G00P8:ѮEZ[!=o;>fЀW cHFEsnd_ :p`$Q `<IYp[ -hd CJ/8LYxRGF#v(ABnB AqRt.юsHϚT# LH(F<DgG) N cđG-' At*! ;A # Bh$ Rz3;P (08`@!|aUp,DKP!$%b;!AczQ83B`E77"  @YC`G"#K rT8A SP!pS#A B4G#j@B 8F3\B09. S907 _ߐ9h1vFj |3JU V9׸0!Xf*F_ێvhE3a٪JX2Δ/|㬨5.ψmlb0LhFpjfʌfƙ+jDʷ(zV֨9\/[6m3[lx(JNvmxpr{ kX# fl2j"Ypq&q(T2lLK;-4b璃qn5[5!qe `y v0сpL¿E2 4Q~F9 ;!qOxqmπMBЈNF;ѐ'MJ[Ҙδ7N{ӠGMRԨNWVհgMZָεw^MbNf;ЎMj[ζn{MrNvMzη~NO;'N[ϸ7{ GN(OW0gN8Ϲw@ЇNHOҗ;PԧN[XϺַ{`NhOhC|hF;/ΰ>@w7]`԰5=q{!HCC@x> j0Ow{!s4yrA +hA 6 @R?{^=r,!0~??7Cr~C  -[p%@N.P|m`f8Qw~D0]WPpWFP (m@yykZW{y!P|Z;T'X{ `|{_ A6w9@G&h:_Lq(AzjfS#~ׁwg X Py vxg{1㱆k؆ZW`|FNP^0RAqc0Hz@m[`~?LJ1\\_}Hm`[@_xQ؋Z|w q7nx苿x1}}g]Al هP݈߈8ȍ{p鸎(pG\[ [ pM u [ 9 #) %y*y ,װB1 w Rq !_,[ H*\ȰÇ#JHŋ3jȱǏ CI6j\ɲ˗0cʜI͛8'9 |2`JѣH*]N|= ڴիXjʵQ구ٳhӪ]["e#˶ݻx[/AaKÈl5`TL˘ S91:lȐ7ӨS.JΟuԨ!۸s]S`Rȓ76@*ʒU&Jӫ_Ͼ˟OϿ(h& 6F(Vhfv ($h(830x.h㍖C<>)K>F&YD4餓/)%F2QRYe50l*$GdlfxIP6HK5:߄s;9SM6`M508G$ d;K8,iJꩪHN8D㍢S3.裑NZM 6N;$[*¹;T+K$ .xM|3885sDR-<^dBC p@<2垛N~Hv# -ǹ E gL54ӌ9O< ;>y@$x;YA$t/H'(o"N<0@2̠rO 2,X`;Ells Ф@h3S;Db}NH0]Ab9иӎj;@dNH!ܝw18sK)K._{< 4iF.98!HK$Ĵ9,iN}X6> B؞o'/  gR Bm> p3((ۧA a h@|UubCM[ ֤u %> f0QhT5^IE@qDs7@ u?=ߨ5qJ'2:.i88&ax;bWĒOu6Jd8(Nh h$g4I/AE~Bt"#qx,pcD`IPa8DSLn\HNd1,IZvx;f \Xb. BʵL2f:Ќ4IjZ̦6nz 8IrL:v~ @JЂMBІ:D'JъZͨF7юz HGJҒ(MJWҖ0LgJӚ8ͩNwӞ@ PJԢHMRԦ:PTJժZXͪVծz` XJֲhMZֶp\J׺xͫ^׾ `KMb:d'KZͬf7z hGKҚMjWֺlgKͭnw .B6 @̀- ~p8O%@_.p gx \׸UrN XA Ѐ*x oyC\⊷X p* H>- w<&s!`\ s#jA /B{8?gPx#W0@p/yhC* s>c4 Zxpp E>d:Q&SeP` HWdfC<^1uqЩ' xV(>hC4b@ +6t@.W``7Pѐ4-m `yp0D@.hg . px`]5n4脅9!,0@" 0C \4 6Po.l!c@C4A j5 [8o Ʒ|@iI&5X[ W5-pǫ rIn\߂54 I9Eޠq13 (a\'EޢN"mr;Nu"5/!-,wz H*\Ȱp v EqΉsȱǏ F(E`5\ɲKeVM f͘ɳH2iĩӧѣGFdv ӧO͙CJCՂUկTBWh{ G@]<\8sv Xs箰k$AP@;|(=\IoA}UhfuS1>g93vXbЍkGv vM~}ʌ0+W:p%k w]Ooњ {6/Ђ EWEN7vy=13笃4/3pHs 2s̴\]8$I'x=г"#=x"I'B> >58=CyN<93̂C#Oah-O N<I$Qtb8 R- G Qe #4:gH-Y_E%:S3Xh`C!N$8&( E<7A +YB Ă=(f(T>K8"@N, >+H %@@@;FcH1=fO`E HΜ@ebN5\ L $D (=8ce{#N/am#Ɏ`My2q:6(`@tB +< (Z|@'EՐs>˰JK O<򎸨#z 6 ة01 =hX ET'd SC RHFX83'?mb((:ҡtpC`C!z EQi'hSp B(" h7!qT"ˠ5Rndcۄ]AJ| =f( b@: A`!uR6tj3i9FFȑ,O/2" Xce=+0#+ pNf80~ c}k`[X`@9C8dٌW% 98Cy/ؑ^G1`[!.,qw* (0 *\Ȱ@J0!>32xѢƏ!4gɓ'}T( I0U%̔3i@̌ـ ߹l٪,V @? 8n4iܸyW윸A;fR眙<hTASMs^r{G4/Iiz.;g_AcMR߿eC"궁0`c$3(k"A $AٳgBek`(Z1׳YX8rGXj !sXԍա;⾼?9bi1sF RHȅX0,286M6T(0xRQ-$ Й;Ph!>`SK-s fŌIH '( @$XN:D#.Hy0$#x8cWΐETMR_&Ւ/j( (;DM5Ӟ@_VYI1LS4;pI es@B 0t2bH#4t `=*P1֒- ,rL;S.ti!9,w" (A|㾉ƐÇ LaċUcLƏ5ra(OU ˗/KKreK0e$*$ Z3o\-[j 30$Ap-$`&8qoTfߨ ZrS,֩2w6Q1SK M{vdΜ5c<(#N{:Cb3=5@b jHRK C'N3gbi(9);휘5@^N[jW/O5G( 3A ud2A)%UP=NVK,(O3dtfVlYad.3 ! 0੧i ;Œ:KÐ7ҬsA3SX C ,,L9`ÍB!-, H*\ȰÇ#Jt>dŊ51f xmڬ(5K4k#QʜI͛8sɳϟ@ R0|Μib C,9P,]¼Fׯ`ÊKٳc7ݸpeK4oVL>h͜LÈ+^SLYƅ;7[]io`ƠCM2-kYErw;•Dͻ ke[4~KN2ɡ&N8|NK\6or&x G˟O?ݿO޲yD^}h%:8߼>Um͆%Bd 6pb%SP4 EU 64hR 6WN2@J@2p/s V33\4`(6`Sˆ$3C32I0,|C +C߉l[ 4D߇ >?/>o/ׯ_?cw>/K @*|pʲG ^χ@}  ~%T ?|0l5_'hp:u0q HL&:Px0( VFTH2h$# ŐqpXHl0x̣Gm 9юG"FЄ+_ IJŐu#7N($-IR a'WV"1Ag?I#̥.sJDѕ &' @o]:&Ij|e`ie ByZ~L:o+x/d8IOsa$~S|@$pC[~}=]OUe$ h)jB` }R(%BODf/ҚZr/tKwʖ*6 9-Hj \Ӧ^vCL&I! pd;A|]'@ +|DXeel;zeEFWgP@;S61Y0yР!@v3!0 Mamaé7U7V@VPy/raSF 0+z>ۀo/~0g2gK] @Ý-v}%y; xiNK+f Gn|$O9ZN di e8wN\<:P~NF in;'Eg fuH"@?]OL:ۇ9n>5]xHgpo7 p?p6Hg`9 t6gH7AH)#{O7{gw~{O>ⱟ}y񫝳T0 gtZ7\~uehVf:05pxX_bp by8BY~`FN@~Fjz&t]lZY7x GʬY 0(vOITU5i wDફFZ]Rj t PKKO\ k \ [O ;O\kq+  ]Je0baI+N=9i@hKNYh,&,۲`VٖiwmS Fz`tw5*d{kjn9]p SˈwdzϤ ?:n%0e p ^W00RrVKtkI) v&$!؀ia bWZ@[[JũCM nɜij6Z[I9-.:nuل{@)kb2ٟ˻+\ \LJ\,[ L [ LI ֤Yv}eC@{ka% ^}Q^.;\WYx+LYNrUm\AmÐTPw,LU{y=eY跖 `WiYًͬ\6rfʛͿ9fhжJ^mڥwg!6q`oD@̆ؒFa7idY siž=Z@ Lr +yPضEdjs{@@q ̐y}\oPv9`}]A ~Y)✘- oy&_g;(+fY9`e|l]ysW”UVpYfe[PY,T0wemY*V@4hYf~[@/@YTc fa.]HcnxeD`APEpݶ]}>|`M}ol^쾽^.~ep$Eod\[Z$E?dŜ+t0GR|;+ɔEg݅b Ր֤/9`ovfbYYޚ>&^@<`xL:NcI e+^yY8~E@P@|9@ nUK=a`͐=g>0KyѭiaF-{mfhi ѥ6@U"4 $Xb%4H*p Y 0D  Ê? !BDȉ9) " )Z0! T@(FYUyWYiծe[qΥ[]y_ZX"AhB'01X$1@pr@(A 6 J "!?ȳy̭.ɾ$D8[ N0F `@.rzL>do""bCh+]Qu@v IraGC7㴵4N?{W`֯pVdUvYfuavZjp}D*pc[no w]v?]xw^i7+ADŪ}_ `VxX{ va#ua+_:l˺flg_A9ƙaaOYfsnKc=dFd_PMerfi8ib7glgfBz꺖yf>k&{m={e2鴟{p aigx@qwib!G|QgP`TpK7tY@$A$fxqFA (Ѧ>oQ7x䓏֝]F*qPr<G; A$wW}Do@XyvId)|@($/}c`u_ |@H1BI!,$! Bp} h<(l)%>@PKdb׸y;AI|B ҌcΉc$c sE`^gf3Q{<,`F phfBHbF߃ȇq,d%Dva BHSeIIZRdexHC'kFWHMS82C[+yLdņE3c idc\8˦Q%(&w Lf9yN,F:YF5lbP"&3\N& G$XC'>1 H{M.c@UhIM:I`T2q hFMfl:hBw)9OzT2-Qv$s3MqsҸf/!v"PTUkek[VUsk]zWU{k_WV%la {X&VelcXFVle-{YfVlg=YІV%miM{ZԦVemk]ZVmmm{[Vmo}[W%nq{\&Wens\FWӥnu{]fWnw]W%oy{^Weo{^Wo}{_Wo_X&p |`'X fp`GXp-|a gXp=aX#&qM|bX+fq]bX3qm|cX;q}c YC&r|d$'YKfrd(GYSr|e,gY[re0Yc&s|f4Ykfsf8Yss|gRM/lYu|;LsIۿx[8us958@|H@D Ȁ@A khA!pHdHj[PgP!]Agp?D,q8s(B#DB%lB'|By`(k`YBjW8%-cp/c !., H[(5v #JHN3`26Ǐ}\e-ɲ˗ݴ_0]VƜ@Y[.W)W]ʴ̧2ʼneiǍϠA×L8`#h҄T*Uj bk\c˞7LצȌ`hLY‡#0p 0Y?fƹtBmŅ|l2 ̴ְ{-pRW n:v—0+6q^_3H 7q³ _ӰŃ~ m\OP9F( [ui'w3A|zrlQA~7(2  4N9]sM5%M6wjy>S3sP;02;28#iRN6|MR p)L;7303#5AVP u(eOA6Ocx@Gd18L-tM;ְ5Q23ek#uZeXS.3&:#}5C$)! > -Hs ѠJP3i-?u !IM6sT+=ev 6d0$Yߎ֌3M4t >m*+-(4CA J3~Xз֙YRe{@24Żڋ } L#7c8>LNabzN;2eb50"4> 1()!B#4ׄSL1|j)3 484ļX81> 3˄njFc(Y9j$1 ̋ G0oC0 !d6ڰUo=?bGR{  #8o$;4W噟O9FVI3;)ݞQHL:Q Z *z GHM&L Wh-*D! gH*8eZ< G4"C%25t"B)R& ˜X`d`LHF zeL '6Pdn&:v >~ (BL$ƨFt$"#)IRҏd?ICr$(Qܤ(SFTR|c)K5Ҳe%.è]r"0Ia<&L$2D|&4(i6qL"69jr& )NU&:sxuP')J#"T)ROԥRNiM*RPUZ$*Xձ$f PYǺVoj\:W5wuj^Wj`:X6ibgX6UidO:YV6hf7Y^FKҚݟjWֺlg vTՄ9Sv pKMr*ըFnk &pG$z xK ;QoxCհ.B!ȯ~Lؾp1^q"}'L [ΰ7{ ^|%_D8NW{8$%r 8αw 8F6J|ߗHNcw,B&rA! [8/>k_,^/~#_s,iHo[\a,Wws|d!egwYY!G3e@pG3wMoDiB!DgE#lvfIS ^}gR`˦&LJЋ>[Di=Gb/>Jr#^`FΐBspw6wnjVl~-y~6~xQ=jQSǰf-_k|WoC=u1iLgz[z.+@}܉֯ "ANu$}m;'P,1dZ'ȷ֯# <,vAn/9C\q;py݇3>\sn_Xw#'m{^ﻠs@A;i\n3C]򵗽AEꐆ:vSK_MGdM>LpCSsOUL˜\>| D\~~8 H(  8H+~ P 0A` p8(6X2xx7엁0AE0 `C PW+(7, 7؃ȅ3(7G` @0Pr8j׀;6؅ jxq+!}>JAH*0jX0@aȅ؊:!8eXF U0p~Љ @UF0((`H! `~@rlFK!FA (h$@qXH h('8`z` Q҆9X` 08@Xx؊ȏ~  x ),0J `w( H.FX(, /A%0O~UViQt8D@ * ;XxxQ0 [ }` <.Pm9  E 8.~9)׃A#t9i9)(ٙB$I|!Ǜə I© h hZ`$ PG8Rp>yDAYlimI!˩z-AX h@/`+H8P,08f(}hHȞ ,A.0 _iX|7w8ǃE) [x1@(~ȏi}.ȉbhPؠx7:EHڸpp 8%LʢH؏ Pz:x[LAP8C`ii8sJh虃٧:8  @& z"ɠC$ y hʥȌCE9h=W jx*PbPrWǦ`Wp' 7@_Hi考D9x81i(zɎh کZ[(4Y䙞Z=-9'b;ĩKO] aJByKH@RR;QU;X[)Hǵ9Q'bd{XǶ0ᶏB,!sKcfkYH[- "a9 ! 7P8~;{ S ["=s `;h[,!8  Kл`[۽jA cҎ6  XpN0@XpTk `D ~ K {M1v [pP \0! N` ~K`TлÐ F1<lÒ e$àĆCG0M`p:Jl 5, Kdgpkƀ|)   PDpL _Ț,# *Ӑ" +ȏ !!m +c ր D,b9{r <ñ h GˌHK2a!p/; l| Ѱ 0d.|/|,\,!3, r H*\ȰÇ#JHŋ=ԈǏ9Iɓ(S\ɲ˗0cʜI&> qܩP'ϟ@ JѣH*3aӥ/BJիXj݊TA\? KٳhӪ][r@lKݻxmqĹ~ Ls)xƃL˘ntܘcșCMBtǍ سgSDz\cI 0<@ = E+szIt;CNSlu6XsA[w=P'c'1S Al =G tB\cBP >1T>A1oOcxo'}<I#@ \B~t7R A AcI/Q W xH EA+0<ړz F;#yk IA'|pJǍ皃"ODY1'+HdmQ"Vyh8@((.;xD78H RBH& CZx0$AB ;0F8 s0 u@ISAЇ, m=bET; 9<-zEXE#]Bd-!YT) ^A^Ӟ"o 8ADS_@'wKאNh|sf a, o" ,DB rң|VP|@#xIzDĂ5[rAFPx .InNr8ͩNer>|xb^S=d ;۩4C `#2>;ڱ p S)iB 2QЌw9:z#wFEQyKM KZzn6٨` 4_Zs,naz$G4V_؂mÃ:ѦnT r X}e gn:Q ," DHp䪎ܵ z__5 * ( E.\.yt=Sr/Dq#; DwRM8)_ caah mOwcć3fa@Cy؃җ P._Y zִhfŜ=(+)FFYBP~Yj[O+sgiħjs@ l̶ &#bwāEW£ h|7\1jI-hE7e|lbQ@R~Uʠ8kLb Ǩ/ш4\\݌SL*sXM2@9 / Up>`("h5;|,>rQ R C,1Sd&RF. %8@qHX5>l hG( (Q}iY 0eU=I5XZq jHM((&!|@puB NtB5Pr;-u/^ԎcXK7ajE1q*p3/T8"PޠFtu[= 5jDCPxlC7^RpvHoI{(/~l0܀Q!Ђw߷ p$1v3|o|w+KOq.a$H}`ccbdA L}dc G%'qrJF Aa rFp" Q }(jzc0 {|Gn({ ;4v7vhyޠ Ɔ 48$&83O# kお sI< 9հ+w0Pu%7x (`(!蘎$PfkݑD!$(;b9y莘Hxh]Yx ѐzɏ6'5Y.Ƒ塚!Jђ(I5 @% 5ّ>I&)=y)R9DHa$K);T9dBVհ 8 LȒ?YtY`sX9Hy r)v9Yy٘9Yyٙ9Y08rhٚaсYV7ٛYΰBy0o@Y@Xҩ:^$@epvof3K cELNjHj\ #M? C@D jN:cBC븐K-x() h |)=%3,;{yc5r w+;[{؛ڻ۽;[{蛾껾۾;[{ۿ<\| <\| "<$\&|(*,.02<4\6|8:<>@Bjr$a#c\ƪii̺l,к4 @daQ1лy{l+ǀԢ8P}" _r(-8[ {siIlw a< Јَ-e&ğ@nSjIOLe$VC ۨ up;D@-VY 6`%J"/܌óeMsC ;LpĎ`LYj[N 44E/ &d0 6thK>$<`G!:LR3 (s!=ĂPlP  `N@ D:|4-rrSP p =:DğI!Kbȶ3z!Fq$bQZr(Hh(AКCZk;",G#!Xps/!ǁ!ːE[-&]_ a,T2#򸾀tk=-%!1"r|x-f}h"حKa؊폦[-ْ=tٰٜ]:q3#$c`r 1Afa۷ك,!: }0:@~)WxvM[BM}ݩ)܍# Q #AaYyߨ#A c+ t,8F.8`+t-B{8|2ruc %*.ޓ"!d  %Qס Qr'됁H9s CbL3>&58A"1qgvU-鎃 EYƆbLTNq1OtҎb} -=s `„u$ŀqϙq= "N#|T_.zA \u UE6J|= nT{N վHw2 31 5uf>^> ? 5­qR p k f*r>[.  ;>87@b]08P9…8 ÙBfJR-,32x 0nS\  AK4{Z + a ;$e*@>R 1H{E`%G27Z{1u"9 Ҁъ@? NJѠ P =g̀!0U}:- h++qr*dxNSvB qɅ= Ȑ!|' *? KMh⃥jrӠ@_jN `y \*%yeoP A  -pᤩ;/l|3w صs˘$87nTD0|8v͚kٲ\sdS0hЀdLq[gNDݜzN\pdVc֬J\2F\5|͜9;G.0` w%Zpˑzaĉ/fcȑ%O\e̙5og-$CC׬#$@=7{1c,3qmo6,\qSB|E3ĬWfyמ5c6u , \7;daa &[~ۨ&9L<|(|`['pZƫIofBCg`Q&ʰJ4 rH"4H$TrD됁(?hane.DFX|FZXH .|N8 N砓w¡J\ CA؉Оf|ǝVBDwiQƷdv(IKÚb?iB (p4Q Sp2qbAUF5X]as`8'AEȑArM1[Z90>~l%Y/r *Telc]!/j+whLpY4q+a]jp4Gd ›ePr W-^]҅Ś؃wHVb脉#sJmB! Fi U'A HfL>aLgDceHҊڄT+2H{3sN F1 M8]2s>V&p__Yysoz_ k%[ئ` cp91dqo$!PJ6LԼn ]sWPdqNӒj}"o3c6!c QV eKѐŒB,R qEPwL:`Dpy'q t T4 u0h#I!Lp36>גRF-х8ዢܬ03\ {h,QJfu]j$=~2a%>Q̱9Ba| ,Ň9_. bvFnRŗb\4񇕉0ᖫ\!XrE`3I%7ѐ$"OƓrT#!G3(MD5`:7mPf9깈9p\ZA؉SQ4GTZC>2{kgd*Ҙ5YZ)#@#¨5R kG]SL%\B&0eplЮ.Ks?vdx k oKqə <{;oXc8pHtxkhõpetp6D 0 l `arx1iD(?r2jBnFoT'L()D+<uP-!e C2 ! nPCH6ć7Կ9CCkaNa^ana~aaaaaaaaa b!b".b#>b$Nb%^b&nb'~b(T4()f"'=`.`/N# 1IcS7r!&;v>ΆA.dCvSD6aJ"End~d|GInaK̚cca`,eS>eTNeU^eV>e;)`M~, NLhPRne_e`fa2YełQZȅL#K+-dv,k 8 c 7fZԍY vngw~gxgygzg{g|gXl%rn,sn%zLu^|>hNh^h}&~Fn,0f `%gl00ϻ L "k&lΌ~lèlqkkцOVl@mvmavOkw Ѡ^gNh^]`t-| n쾰m從rXasno>ipF>nc~>1mn&llqp6c V6m܆q.mmor'p Go VTsdjr D.jN*Y^ 5ϻ}󕰁@aN='W;<'Wk=|;LJ @s͂#ptAF?ahC YN'vB`[$BX LQ & 6u)!v['=X>1 &MQI @bdc_,6T`i)g RuGwuTHYw| Fv(0J؏mOz/swa!u>G ww|ww}`GQ/BuK:JuR97Ty"H zS?z Iz=]z;gQp.z RzОzQ`侰guS_WѴ`=ؼ` p]|hK-w->Gvysl 0v'Gsʟ+0_GQ+?u@  gg!ď|WQ'-@  w}|pE: '`x~g'X~|W`B } ہ7?LJ?$ B2l!Ĉ *Hbp7r#Ȑ"G,i$ʔ Yl%̘2G '9|f'Д-j(Ҥ*Y*mњ7sj*֠CrkS`ǒ*N5`Z-\[ҭkػzլ]9YЧ[e߻>kg,N8AZ'=|j 9sgh襶z /@,0 :׵ 0T CSMj̈|3N#@0Y6ΌKIN5\S9XY2ހ@ !6 mb/iU<4JT jss΄8N,S͌dNF,>n+'$&dOڔ D@ !8M5&ͮA2عPgYji8Bi㬳g;V!mOj0fӎaP2O5L0*⋥ِ@4RD;X4L/l6#-̜ >X\:t25><uClN=IA  4Bf#[2(5p0ND_  ^a A4ANNS# C:r]AӀ e=@35SNCC8:e6WV6-nA~>wjAj2QZ@2( $D0btr&8#[>A=& Gd!I >ѻ ‡ "@JC{>IȻH-UZ}bE=Q. @ "BHĂ@B%< %ݠGApW AzF|Db DGa_;B&>a<-1BL8 1> LZ _j aF3p(/y&`j1CJ@H+ m1=Cx17jkuX|HXtfP<8? ,A^QsԨV(>ALs? Q rlrt,epCf1T&2Gn%[Ұ*#|pd7>=ra o@0p$# _H&h-\fXbx= "ff>Z]_< A'> +!Eady|8:&6p>pr(ɬ85-A Y =PKeLcJTr,C)@SdK>6{h ѣ|h >Gt -H6Ig{P4F 6l"pXC,g\#]X2;~f3w d!'lu*8_@H0ra0_t]0%@6՞ 6pC8G<kLv I6ғ.eG9$H/lč#F<$Lehy@di6uA&t={=mڮ> ۦV=~@+B&|1DDp:.kb!Q:򓿘^^ 1#2@r |x Ђ1҈": "hA(hS5 nG1:(Z / D+$ՂF0w!0BԂ) Ă7O(o Eδ;$Jk@@%*BʯL5/}Ce><]ALIBə4K9g@I׏3@C34C.XMþUT .d1""N\@(4@q`>P*ޡG0|q T]_lH.؍:zBY4`59B5VL!IYKd/H_ A:$X%:8 .DC4x.ɀPnzC6E[948C1ڄZeZe .-j\ )8,! Nb0 1"rh@Lɍ$H ;<-b,8N1j @FnzGx97A@ 542Z}Ǝ<@Db$ݤ5XZ,CKBVGMF]$ fx)BTgM͎ 2e^FC ,3LaHr82܇Z$+ ޏ,aEHC%NV˅Ĉ`@ %!1eY>@~@PYljfAt$u|d59pCAY$K9$3x >d]ChqJ"O2OfPFpQNbR"'B5e?U2'V >l3tUA0f8$Z[\~be]So^ ɕ'`Ha ]&fVcg̣xHZtZ|&d`x%2IZ! k(G.:d.C87 N7C:p{ T"99InG cBKKJ]N <eBtڟqbHᄉp0938 [PJ @5D6Pù 3OFI5=R 0P$VC=,iH3dxTCv J4x6O-|i6JT8`C4wVC4&|(4@Ѩ(h譜-Edq*iY2u|&Nܔ6)*.WH<͌)Z$.CÚBC1i9)Ji@ g2j6D2j8I/$&V꥾\7p*xꒀ.C.眨C4`C/p؜F?QҤ9(CuD 1 *>N-VlDfn-ׂv-؆؎L|-ٞ-ڦBٮ۾-rm-֭ݪޭ-&Y-v.:G&.6>N.rEV.fn~.D.閮馮.>.ή-n./>/&F6&>N/SE/^/:f/v/}lob//څ/W֯:ޯ/b/00'D7?#pOo_oooo {o _o ;o o ϰ n ߰nnnngn/Kn?'nO n_wfۂْ1آqֲDZ±ױұ1q1  2!rp2"//)2#? 92$O2R%$_&G&o'G'rv(2l)r2+-*2,+2-E-2./.0+E01E12D2/3D3?4/4WsZ36R4g37w6w38G739383:9s93;;s7dzO>3?/3@14AA/'B2C74.?4DײDOt,WE2Fg*o4GG(H2I&4J_J4%KC2L4#4M#M4!N2Ot4PPQ1R'u/5SS?GT1UW5VgVo5WwW5XX5YYuZ}@AAA\{>A\YZ!Da5aA_c6>eˁC[uAeeg׳gAke#DtJ!kl(6@uA@XWA>A5>uD\?8['6yya76 wq[r37>8wAvAh7wG@8wx̵[AȷoK~#7aCw#vv#D`Ak81+8;x|_[T8A\|A7Wx KlĔSyDoC 8>L;0D3$]]joCA6l7}ěyv2yxP7>\@r/b|6O'āĨ8D?DC8B 8_nv/DGĎ#v:]Wz ,D4ěAG tZ7lF| ,D<C:A CA0Cs9;WA;A@wA9B@A ;By#_bOsgġg|QTB9h8˷˿<̷x]@C:A ĬA0DȁK$t475kA;o}Ax|<>p|A@}pOJ:>`wC|4D3čC;|=X\3C| @hcG=Dzߏ{7B༇B ,eylxdz $C$>T{@X|C@lD9>CC@nD@l3?ADA/D8Ax=k/lw>3gx1xM| JmiCcF ϨQ3b/nиe˗/dlb!|&񝑳c5l9Cq`iyFˆRlab.l!q:_@҆ 1C\P̅Z <ӆK^.R"GΙ"j4膋X耯Qbh ԫZߑ6mΠ1}2)a͈+`YC>ĉ,`UFoQk>B4B'\8[|! >ٷw~|>3ѿp7ڻ >>ʫ /i @9#48c `p#6B|Fp 1L#C:p3N j7ڐ++n4JFόѬ3 @ F*mN#9TǸ.pRCƘc 1)|.1n#19DJ-,"C*jE:B7{4!1L4" .@.8H* +O4*c̴"tυܘ+6 :8QL3Y7h̋bR ;#ʚV5*餕^z=|LC'BiLbZ1z"iU>ն%?X_+5nFjP[m# Bc;oGȳP'({Kn;/1c'5+`92Y<ډ 5B]W&5\H3@cju4]]ãX`DG~N5A/ 5l+ ֕+~ 㭷{"ˍuc`e%}f'3h~2%608{G$x ^XBfK!I(ld2Iu|=<+aDNÐ .ˉ?\a  U.ڃ@X|([w#Y Ó Jp!JG@h w1_1"D|ˍKc@)1TDT+<p.\sk^x!e 7J8KU໢w92"vHe;QYUȐFπp(9Фwh0G WDo~!FnҬT:atd@)Rxƨ>O~ǝ0@{ӟUBfH9 e,$(C~dF2ьjX5q#002S`$H3q89qdb=8B.Cר>ӥ4RMG:đQ4@7`֎Vq,$M`T5Jp$#pF3:u6%l\ĊMe!<+^}*40Җ´u5Ex_:lWs,nwGF0gG/Hy 3>l4[g]W3ܭN)Nkѱ&Սِd]M7y^nu^v;le__8B>ysIW5=fyuD-G]8W[=᥾z{Y 6uy=Q:Ԇ^qS^ 7قVsq=wWt{I?ݞ5W_zqo^Uvu/K.Ϥ~ڗ'|-/wW{ƼċŸ^w[_n_mG9Z+~k޳ƿO_OPP#P'+/ 7;?7PCKDOSpFP[_cP3gosPwP P   !c,? H*\ȰÇ#J80p3ZȱǏ5fIɓ(S\ɲ˗0c|)̛.mjɳϟ@ JhɚH*]ʴӧP.ѨիXjʵkJ`ÊK@^Ӫ]˶۷ʝKSx˷/K 뷰È̸1#KLe3k ϠC;G^ͺӰc캶۸y}b >q;+_\盛KN=4뀓Wν_jNyӏ7#=X~ Je{ȠW Fx׃`[INbV~xՆ$v(E"Q8o:(#Q*(ڨO5/($OdC CdzI69S 1-ETfI -Y$d%A2|YWb^Yp&tu zzt'=i! D(5jQĤ?GJɩDnzYJy+>*oJ@:j RBk ݺzBED)kll֙ $Tl G@m MK-kO*P#,$no񖛊,@Kмe #)L%{wpfgi7Y1(7ic),ʍ,0?6'<<{`=ρ mDgw%mPt]QWMtYvXӷud'vYedmlܫ(R bN;m"݀[g'c8l}V[fwGJ%d]ߍgE9.1#9Ҏ5B 08 >̂(#8π@D<Ҏ3,ՠ.}13 ;;,L, ry";t.iF;*;/䁅[lc<$bkFyHŐFU8G1΁8=zAE6! /5a E8JT8>Kbv(4'MC` KZ6XlcN/A^b!c pKMr:ЍtKZͮvz xKMz|Kͯ~LN;'L [ΰ7{ GL(NW0gL8αw@L"HN&;PL*[Xβ.{`L2hN6pL:xγ>πMBЈNF;ѐ'MJ[Ҙδ7N{ӠGMRԨNWVڼmh4 Ђ<k\^І38~YZ0Q^g 9X/A ;P/A0m5h `T!q@|! f`p\юx|hAFµp dk!6` ȯ8(½U0ppW \8󅗜 B^3 f ,s4TX:ѹ`ld@R5ؿ`sA O4!^@|1Xxm@Wyl!>Ϸ0 !xA~qP!9> |Xznx<`* {xV݀#T; nԠ7=Gcυ9{_s c ~h'~y tr~~u[[0bPܧYs@_0hƀxn6kfy|v|7j`(k (HPF8B*V:pU ɠ Ȑ[p㰆 n9:kHd2 ` ְJ|8#~xP8U+suȈ(z((h"BX![,  H*\ȰÇ#JHŋ3jȱc\Ō;g[7(S\ɲ˗0c|諘;c$ɳϟ@ X,^<| ]ʴӧPtvTիXj9H\ÊK,Kr]˶[ߤIk'ݲx]svÈOt7Kǐ#-A˘Ū.Ϡ⒆N],#kǺ5yc˞1ȅͻo غw b]X;`h߾]rG~͜ee}/˟}{ߏv'bG Je *`fN' Q ((ZDb| h"48%ڨc8!' I *>9>Bi%}Rڕ\e82e]/tp)tix|矀*蠄j衈&袌6裐F*餔Vj饘f馜v駠*ꨤjꩨꪬ꫰*무j뭸뮼+k&6F+Vkfv+k覫+k,l' 7G,Wlgw ,$l(,0,4ܛ]EFhؼ+(!EmV 4A  0yqd%{| XWZhQACpwouFtx|[Q7@[]Fu yFkuA 4s]C0 3p@\!;WTp@nnp_l>qDoUzg7_Wm/lf]aUӍ7眃:!0,  "W (P:_eNaBs (qbD+fxF~aI#MVėɁ-Wʜ)W8_/my3gO;TPD"!0,  #AsG 4e*dvCU{HCs3kDZw͚嫘(OZɲK_@R&ƥɳϟ@ JѣH,ܲcΜ h̢6cfׯ`ÊKٳhӪ]˶۷pʝ6x"T2iLԩtOݴičLyYr5fb;uCMӨS^ͺװc;1bænU+W Nȓ+УKNu進kËOd:oM\N6҇h& H F(a>8Nv (:x0d 6ߋ0(4 "X faj7:"4M !o觯/oo/HL>u Z̠/6AIGHBl(L WX!F gHò8̡w'w4Q"";LAXJ4XbO߱pB2ъZLhA.!Dd4gqN!H>|D @(pa=Z}4Nz~@(GFE2A IU2,̥H^.q/Xe ?,Zм `<+9|E' Їh T|zRCn3q$-~2a @ 8# zq! yAϢ@Q|{BA h(EFW ð01kNw9lӢzHM*@cP1jԪ.LXj<ծv59J{ihE_ΰ1խ[0Zֺ+xEַna +>j:+j[WְUb'ӷZ֭p`#NQ,e3ΚNcA9[IVN el1Vb I ;ts;9&` 8VQ~8^EK[7  |t@ nЂwh@[bux?E2Rv!  _p֧ZBP!*(8egJ;w[\ XF3"+N2UP/cg[?Sd"`@&ˆ5iНHVӇ`,Lgdyhl1^$LI`} 9ɉ  sJ`.>0@`BMk]eH8ֱ'i!F8\dSX=\GWjЎ˲}fk6ؖ6}Ak?;F -b:6 ׍@o7 M@wago|kT_JcgNٗ9Xxx?L|!qB\ [ C@:\M^_WTr_yNWF_$|M"HnUq[gkSRA[rc{Bh'NB$fvٺr`vM뀏?mux'F5BWm{>ۓDou}EWB~%B~zɃ~=k1?zo }KWN}}}Xuo{ϰw.Neӻgzg|a?2%\"E^E^sgegy`za hcߴI j.v~#Y%kPւdNPF5Y7JPPR1ELrF&nsXwhU8L<$Gph:h^s IdH*FDF>us9Ǎ>XTA,y,N6v ,p 3@h@>IIpwnphTP`cPzFM bIEpJ~J%9e)S2g0 Jrk[~4œ=ETLIR` iD}Z6p@w[E(x$GbɇdYz/$vM H~cxMNyubv\g v;[!lC9% -i?)C dPWvY[獝RcHpe _4e d|CوQ䓙bw&_7eYiw-(M-ٟLz:䩠 *K :Y:PXsjIXڍ>0W#L%(*ʢ.:>+ڢ8K H^mɣf6x\&ʙLzIO bA)VJz[ZF]zp`*MnvGWgiG oJJmFMdydh@ KEdЎ計$zz4P^nꩿ4L¶{jhj5ĪHE::CZY$ԫ;ZR Ț%~KbVY@:Tɛm @ʭr9#TJH蚫ʮ ~ZzH\m%}JKRkH)<z- BXd\ry*u/ `C5Zs}rY">Bg~J|>z+Dt=+ UI%m :͔dvc:GKN+AjAAwUm Qxc{jCI}wk2+O[}Kӵ 4{dzǸ9$C{j_cKKM۹CD+Tq 0 >{:|빴;J;` 0@T<ۻ7;P<ɫ+[`[ ຿Kd p{;+(dmо $!OIuYup9Ayy<qYF`vh*dm OMshIN MCz^v<_ ! :i,yFSaV/2 :,up.Si ܐ `LO62pF)A@GvZ\`,c,7}Qʹkp*>I7PO`00PP @y,IJ.[h ɒLɕ 7E x?k3jdˣDQJz7ZRYYVu𓑴?y8ln˳8ɜF^5YTv؜5[)̘|5ڼb`r|4E˃X3WT|RD|+l4-\@|94 r3v !Cx@JdڛʃB; c_W۸rX&0-c& ;\C Z|jCfgH$BvM #t}0ТEyU}N_dL|k #HuM3MԶ[ }Ujm3Ny]\2P@@9Ք ?לm/rPsוTkQv<>4y̥-?ھ}WjP tܛ(ҝ0ԝB}ݬΩ, j-,mA2+7h ր 5S{05`/4>VbXl~@Nq g*5 p&JuhhJr+Yp~JvDZ8'̼)ޘ~>}tZ8>'ˇi'@WbNl ܶ%>Tn#Ď~Hڹn> wT"u [EܘpvN'sўE$gr7Ԛ> b(Fm-^N#VPN>HEv \WĬyUJnh#v/10}w`kL ?T.f-` @Ў߈0U%WJrhM>@o#.f!_%~L·O@,YN O>U]g?@Mo/q?suwlz.AcmS0E.M!>>#CL?X>Xx<_Ín1y4`wCʀ߯~*p aEGv`[_nd.V?_iwrhbp!HP/_cC%NXE5nG!E$YɈdK1eΤYM9uO6\4P!JQNZUYnTWaŎ%[,A ҁL&\]yY&\x0\Jcȑ%O~he̙5F,w1eСE&]f-\ekױv.8iܹuUoݔnoɕ/O>sѓ.|uٵ[^y kZ{e8}ѯ|3@)B@#|@B ! ڒC] K4D)-"!Dc4kqKA 7 C DqH" Iŗ҂@?ܓI({d\p ر H0s"$]Jˀ  6z(.$-⌸jrL@̖5Tta?E@"/t E+B@QRKPI@?9u<])MT^d4)V_DZU9[ IKFuZ( XKH# w\ܚv]*m\dɵ^fҢlԉ^Mf`<>|#/N3a?Ýc)>!Bx86ސcn9Y&ǃyfhg9SVZȇzZ£cz륯:=z&wzm i\Tm3m[bP&6;oɭ:<|rV3WShICj@j 7[lc[rqENxu/xge7>Pk7 ݛQNixM@hysqTIַ72y=|m, 6woZwX@[?P .i,wo#D rJb -?BfDRB$}ak%H aaCPڡI2`DA[bE,dby,G@J÷DE4aRFzq1shDW tcǗVIc!#S@'tܠR J0+,cxIr/hiJ^h6rҎFPRviV &F:+K}ؑRp]FS+3 p '(Xt` :MdˣKf;RI Aܝ %=өKtg?}#`M =w*U- }pY'?В$9Aw`E '!!ѐXɡ e)GDB-)cKm:ƕL`S7L86hPXXOzS=K՚RUL!Q#TH[%WCUU;ӺV9|k\:"ծk+]ǽ*k`:X5U+b9.xReGV:rYVk䡘]Lԭ]ig60 mSN[zZʺ+%!P)Z0-iB#DE);OBF\SM|f{]w$M0!hk0 PnwE4+Z.|Ӳ0@afMPyw3"25 r4aCoQ5,J;'.$▬E싛&Ƣqwc>.$Cc"ȔBqLd:.yrM듡F;JYg,kye\6㐿F17F7юzi& LB`IK^(g>yg='5`ˀVuGEjRNE"hIъ:UVդ3A}3M B=ꎖV,Y+W贈+Y/~Tjq-פk@:ư,;vvMHUWڎ*-Ch-_s$4pZwܜͲ}/n7#q~"[u`?9ʏrNS鴨S Y܇0 [>!:9ϣiNO|r8eh7T!l^r~;}i_!E XV'=4}Ōx0Z.ѝC-;c#bW3㎗M.S>N:_=O9^j?zh;?jCAp}i4$לYx-5%!q]?$! NU7cdTؿ|(Z?P3o6Z@>D粧H.B@.8`@ @oz:bOSJ6w`=9(h5i B! x3' 8=14((B1IBY@PCd0<0C|  C %aP5'6 6Q"hڻ/; z@BS?S@ TATB-TC=TDMTE]TFmTG}THTITJTKTLTMTNTOTP UQUR-US=UTMUU]UVmUW}UXUYUZU[U\U]U^U_U` VaVb-Vc=VdMVe]VfmVg}VhViVjVkUUkp8w\k-lnpkV`hf:/p.8p|.`3P5W(:؃<88-&=@,X+483[#+4ԁUj (0Ђ< S06[\xeF5 `7^|06P[|(a [u`X\uU"4؃"/`/PklmNc(+85t^gm}!gU%znۻdf-hH_0fnNKFX&.`އ~+x*ؑ_Xn\ۡv$vW`ւ`*8*Ya ~닃烎Z_#?6%p[=Pȃh(]~&v`,/AukL6(v徕?n{P^̶lѾxF(:8=nm6PO_-! \2mݎ وh6nae1Ȃ. f-v_pnVl X-6I 5ƂK_]Qvhc Tn=nw3 hK mc\FPÇ`. "Kخr[,8a<07Y;R9a.hil'oF83 wqn&3[3 I=0$-DVf`/Plgn f.@.`,_M_+c|Ps?t9c4XþX4hFo3n;^1p' Z4Gsoeie؈U؝}kf^GEئ P>mr87]v6tu>Ⱦpx=_egRܟ7m?W0`#6dC6_a3jԜ9C 9e-SQcC4yvMD7 a682m)ԨRRj*֨2,ŀa+VYǒ-k,ڴjײm-\`Ű.N^p 0qܑ'Ι3|ɘ+ݺosvpF_l4ԪW[7|Хw.[j5\̗q㾁K5q d*f\bt-> l; ,b5[j- q1cL3|3{4L;ְ,02ZHpᣜz!!8"%x"e8݆˱"18#5x#ɇ53Z9 9$Ey$Ic?^QJ9%UZy%`+>Xz+%a9Z%i&my\9'uyq'}yc@!2,y RKP8эHq\k2jvA` 3 "3`Ϟlgj=T l T@+ :ѣH*]ʴӧPڜJիXjʵׯ`ÊKٳhӪ]˶mZ2(MuD/jx'{'SlVf$s` ?\4˘3k,խϠCMӨS w\I&kWby1S&:tą,&.Ϡ KK  iiV-eËO|ӫ_Ͼӷ;cli˽wtR]r9WIMH`G4xPe>߇ ($hbW6S]N:|3^3ШtMpTM7\L2 tK2眳_eL3J&cXbS\vy')diX׊b3궗4̎cCaH*$NNtPSVVn壐FzVj饘fɴ3M6Hgt~3X/4,@hF! sLM5Me2(J`jF+jvѧZ*52jJfj Z ,JO.,ٴUm}L5tO@2˄W|Yg+̰Kl(,gz,) 4:ܨN3@/Dmѩ) ߜ=+TwXguXJCt4p Umnlu' %x|ېr7SM2̀Jeތ7ߐG.?*xt#O9$㠇䤗n'y !M&s;~^bER{hd7ϸG/=hϻz٭?+o;·o>לܔQ'NoUs\oyKNGH>π7X1z`7A2ޫW,|H8<. w84WD;` hs2E8!)#H;a^DX, X( k`'$^2nu4 $41_* Ϫa_1U 1ґd8(KDv$4< JtH# "gJt4` Y''.^"g&3|9H&@"5yk6и:Nq9 \`\'Eyz 枘%?I+$$ z<+R (< xG$7asc$Nc%1q60HO`"MJ%CT2DVǕ;SPI-(Hw$1,yɑ @r A !k8U%%|$7HlJHUvgYB%P=Pf%AZy"%!.h(|auCg UEAȗD3`KA`o :kh7]$)|IpwonHd\[, 3t 1Һio[7>oz^-Mb{c4+_ZwkX Ӝ; GXtv/,a sxGMi@Eq{g5 YJ0ijPy< 7C@͐Vd${bllEb#8`h7LxCm'>eyǼmt<Mf%rK8Y~cϜ0npps ׷'A 1Yok#=szo (@9K덠{1jD⒠4ܱKB4|rC\%Han0z `1(Nbh¼9lV]HCXfmo$ƟH)'?Iaw  w [1L^#;ng㨐|=!'\ܧ/1vp?O{(,V^k^v<$|A0%v>ɫ@E rYq_Mқ O}S ʏz o}vkd$͐ A7V0a_yyle~4w0R}~,"UkaЁ`gp F%ngpe MH Pk[0 g `p c0k V`a ^>X [ ` gtVW\`zv% &_P ~kVk WDЀ ׶S- [`p 6 }^ 8[L T兞$0[a ? Y*sy0+ЂXag58R i׆Vk%cKuH` :Hg9 %h% 2} V_Ylo8 q v"`[%i0Dh @'uצL&|Tx~%E~$ |%'YEj[ɊА8 c:9 Tg DyF[ŊG}h  v( Da~Y!r0P  'jP yp`Y$ p)s 3 cVfp 0f;@ C^- TlW  V sU 7oTkGPzA`PDxDF%zF Aa T c6[氝Fy)FMCGt_Ib L6_TWk4&F+ ` t [ zwz' `g Mosk) iK0Y*@{?P ٚٓLeDNE|zYZ| s)WZR7#b HӀI։y0 I {*MR4iLs) [_HpTro zn% 5M$x!zv*0}ւu@pa$uws0r S"L`0P DJYDP `  T5b#TI@ ߐG i'_D{>к]ܹy#! Vr`a{VCD|IE0ܩa MJp 8)0 oHuWF@>UY# > yJT$!eYy*V WzV: HET s[GVf AzJDH jv@sT 'zʆȈշn!l'0ݙv ۰v [l2뷩@uX+n+ !K|n֦k6+;J(0K+7T+Q 6@@ v{ @9pyr  M苾P P Q0 }0 W y*m,;N  ê([LfN Bc5 L30$p2r31  Q = R E; 1K p,   Sr'2 :00 T"Q@ ~d m  ~48- 70  P @` s<NS%RNMW ʠ 0,E 7@ }0 XpP., P A]#E {% P '1Tp FT X6R>P"E M+, * NbI^ \DvV0VpPda4$@+ ѰҐ$ R eW 0$ [Ip' X5e#r *Aqb\ /q'V+Fy . s Я 9# ҠNE$4UU ߰w T+f ,!PN" p`: Ncp 0נ3  ZX @FdQ= ʼpc@s`D`fϳap 3 U k7f('Ӡx !@^6- ހ eQ %`3BR eg\ưc0 P -PǼK2Ed$E ˰$F` "E^•0̠ wV0@ɡRa^) e| j!޲ ` ѣ5y @:p} | W_ m M/"% "0LuiЦl @l Ґ ҚqKR  `@8~f}0 B:u9 E ǀ @p]-RK Y !ǰ]pe  a`P UDQ^ xg(m*75ر a q!;O0^eDhq+|#B)  ./Ծ%.ܾ>'x P8P ޵m&?_Ѷ+>q<3#&od?o1t:  ]:<>"O= /'.$/4 b#T ./^`b?d_,e% HrG%xCLP?`SOErrߌ?_?IP t$B{gNA SIc_DLUV d u?+O4t`7?_Lu 0M/wO?<1$XA .dCMXE5nG!E$YI)1K1eΤYM9uOA$ZQI.eڑe8QNZUYnZWaŎ%KiWiծe[2Υ[ݱg_%\a fcȑ'\墋%og11&]tKCf뽧CVڹsUf8dXo䈫V sѥ\ޑmܺy~NxuƑ+_yyտڵj5c{⾷7-nYpo83@ދo&?OCCBsfb9\‘D̮ii¹qsPD rȡhDYnq@#+v1vX15K0E2qtϘw@EϹ D Y<O@LpΔG"q7}P9@Gt3PN;1I&Dyz)ߖFQcx(!zIZE__aJ*fv@$I)_Ib @ܑ6rpfYifQ3 P)u,wm'q¡X [ulqfhiǚrQvI\P$)Ai9yjQcqxguƖgD `>hֽkhx)eqٙfiYfAYZhFbY %On$gWc=^eVzj drݵZ6y25kgu7s~klke[qWU\{kd* ēZ'hy,ƗZa_y`>i9'geb1嚩ձc\Bd\ey2oy`zFe]Ug+BIhGT9p*sܨK:v SV2nbԯ>8F:Q o+da 2gR#'apXc D$ z >4JzǨ!CI GTX=NGG xВ$@PD`1VG:t0ʆGenT.!'>C1&yHzXZ"FСG͗=QъxF{CT,4RQ)Q }K`D)PF@p\ :asbRHĐ EVN$(Ԇ-f"˸r., A 0fgH@u3w IN܍D?'{t#!- 3.⊞9J DFS6 QgmTMjA8<1q)KejSBħ bdpeg lcqcp>$B Hc D!Y" h#lŀn3YrGY< @"B WqFۚr.H"lao5]D$c:"ᬐ0ѣPD"9 ­ AdAXk  w@xO'{4I&"3_.[]:ȑ>CDZӨ& STWNjD6Ti]CXj1 Y7rc页vLc#ю[N\F-S^j4d3nVvd0Ps'˧uA)(KYBuŊ:o s2ߊ; X\"}Ѫ v|8r}=|캊 7vŚʞڣ||gq=Ũf]?DDc>-CX^H A vGYB^ZF/бdշuB0wa>i.ij+ @,Q V 'qY|= GN^jK4+FըF(eC$J큥Ҁ=aTcC T.wu3޺I$npJ*g'Sì$8@z]ᄦE7zĽ4MΆf;jQu#0=Xͬ.^e{+"qpnسlB;Ѥ!"1>VAvR(a@sooP$, ZA"+A>ˈu- 4?@3B.\3w?!\16?1^3C@<"*@ ` _`F,qhh`Çn V hRvx,(eh^8'x,iSLl (wHWX p]\NdeiELli@ `*YcDFGR>sD|0iHC3@F|`@6XtY`cl X>jkq}Wt'[FLdlhcpEY3yٙE_>)y^b%@ J Ih*Qċ_ȅ\sq(q8iȠ bP{f8[a8j*'*9c^Qh)_ii\iuljh0Ul(!>afq) ǔaht\gxMePqXuo(gP"gHkȘpHÅr8fZ^hn񍖌hȆbh +sf*lMJ|Ot~AĆl rx״I Hi,)nQ8hJc9K`txH 7MfFjTa0 fP )%*p@tJY@HGSk$ePytD{0Me*Yqjhm n&7ǤQfQB"8OC=ԿO`O&ό洆' P`P4PfSe}P!r [ oQU'ysQEXbL!ŝ[&}(* Q,u-RqSoS)Si4US6ݖ79S<=}Ͱ|Ԃ+TDW|]HЕyetH=bqӇI6{dx_\fso&M\qI=3Ņh QfXfX `8dRY\,#߆f&hP \PJѨAh(C02ЪY0Z casPΙivS\(3 fQ]u() Qk1o*Y0rQ>iС_CV䮾kF\Ix"Ihs0fB w92 `Ѧi0hһ•lBMPA废Dĉ5{0a⦶"KvӶ^m>TSd)K 9d0J!6d0a8yn{nc+AX"ng* KgahAK`oYpff6o( rT784RZkCѺ1]lgpTGAX,;g޻ozX}MskdX5=n~O?$(55'!O%gr$r)briXF./9ss1`3o4WsN<~bXqH۞t8s˲5p@RG02z`?ΆpIk(DF)mȆT'XuE7]c7+UCmFQL'Mtp3"-AY0m}@wu\ *`_!]cf(ǕX{uxunyvjl7{vlem?now#O7O8uh8=σ'KqZ{1[QZrM#X9# ohՙe5 (ZCzX:4hnmGGxÂwsL{dIp.5q#y$;w"'b*u0 [\yA|zd^zꮿg*!)keP=zsch_vF2*at|]XLV;q#r Wt\U_ؕcpW>^Nq@=)z/|gNiGuпM?1{\nfvpkޠ%['m\#C'8u4W,/q]{8cIHܹeIC :%kvΝs]+v.6kJdlkKFh*֬Zr+ذb+,ڴjײm-ܸrҭk.޼z/.lخD_̅c pAs֬:nҦM-ڴ[f^82|-Y^ͼ8Z8q|)Y ܹvNgWqY=9ҧSڷs;Ǔ/omŧK<̛;=X鈎skaow/o-pq rIӜuz!!]8x")"-bz9dL;Μ:Ҍhdc̴c39bC[3̤Ll 82Eԅ2眈i&`"q9'uy'^1Gc{6#>yD>c$0HF$49)[WcVyee;^)fe.!m:* '*3z5DLND@349c4# cZ2<^U͖;p1t$K͍y\rrX*;Y%..ݚke @; Te;|RbU:#d9%η<ȧ{2)2U7 :|I$P;zr3UM6|IPEc'~ܱ J2]i2a=6eW0T͟, ϧK9mUH48HmOsc^K>y`}9kN&7b7~ , r;0ְC~pp;9~@~P$wvBs pJ Bp^oić;"齭::»V;QΪ歄:Ӟ07O|{! Ѱ6w( sU B Q!YL yЃ $0L \iZ&=i"RD8!:/h:vs{j|ఇ,aJG-~xZBXDvpH#^1Տ#)JӪֵJDBGMnD뼪#;YU:F/Z, B+@jl:;@1!YC{.=-41ŭ~cm ?|SsgW`Ul? HFwn,*wX쨲l!  wh;t=/&LG;rAN R~s L P,7*@8F3G#˅,^PX/P! 7 -0a {@^QP4E)~0ŐE1 @1g|=H%3|ǐ|+f'Q9) kfip+}! \Ja 35E2Ѩ8עQk %0s F*@bd$3:MJv2#-8F=YK]Jn9!YtCT+!@׾^ʜDG Ş>f'op7S4,(/` 5ڕ#盧mȷӯKoZ1UTh:uT,\V;#Fxa#(=]AC Mlu-bC â3nGsG)h q47 D 7W`Ӽ3ʿD! It8!K~f.:8`ۼ7FΝlR@:𑝢Ҹ>&p5v ,w?Vv;Ǒ LS9pH8tB3:6;#oC{koFۙvf}s{Cw|2 #^n<"tӾ(=sߦ۾w/|?~?>WS+Ώ>?s/_ɯ~/}g|& V* f_N=`^ Qb`Hu`  ] ` A•| aS35L,]D5ɗXI6xC5Hݡ7Fnp:2 95LWM6aL8NkH5!ZG7S84IJLKT| !3SIG"6d84Cx9|73H *2Z2C%HD8TD"fp405`C^UѠ-F jaBU`2އ>/^3 !6aDC^C>CF׵h" "43bnD#6,b#>H"%Zd&rC'"0F(b"*F*=,,r--$ES2׉ g\Cac 2FFVEӝp9T;d24ύCEC:T=:Tp45xՍLWa栴C~9#K.S68 6,܆=/NqF6O6D:8t}R*wC2!qb@@%.ŎR,"3 $eIdU\J$4kd8̤MN$]>P~OP(%SS>eTUUNdoR WzX&2%Z:3%Sp[:7jBUg^%?_ZC`}̄a"fb2b6R@G]eAB;$H(̃'x=DD;Mൃvէ$x'C/,34Xf$P ʍO:(=HC4lO @ hW 4/XC4\4-DD.솔IJ--؂5xÙ5S!d§$<B HCoM;@;$.U2QPH<Ȃ$(8Bh4A@$C;TL8Z9,f Q4x)qt(y:ø+^9,()=B)k<77vj+0%.AO.hٙ=*3Qj-^*~\}B i g x'ƒvۂ,l l~-/ҩ;+}JBmlҭ'Cfݬg'\JǂdȞIB *H~M.ă@'C; < .Т}"= j>mz* 5 ȃfYzv o6.=چCJCsB*n|.qU/. -žJh  0Ы >#m (>Ȃ8C0./ oC.04Bzj C#<, Af-/41/q#$73 GB@/)8lB},CxWٝ:<2ns< ;C=5:3.r;$+0hR27[W2$hJJ9-B2e'(DB6r.4jlƱߦH+=/I@O7r1X[t69dC=*#9Ch Db&.`C4CG+0 Cu6@ü$zH2wB 5#W=EO2qȭ;Ow@f Fe>H@ cHS麴i.®ٴ=Nr}$XnT#Rs3?uTk-[C1E#m^Efq 4Dz {B0q4uq&qB^B>zw:܎r}:+zz!&b&ȹ#89:3/{5AB(L@=D7>p@M@-Xd!,Pc"d@! 1|#{(1 8@e>¶75"x@5$<|acD:AicC#@| /Ȃ:8BA$Z+<.30l7,?iʯ| 3؂7d38Ȃϯ+ g@.<Ĭ@;+cHU'r+ۚ9U7x5CWO;!ٯ0ȔN6DD4n:$~6X[3]ʂ1ΟC̬ۄ3'l̙fq*3p00qYyv >rCKk.&j}q3bdYf3q g k`,H re!2<4\%sSPPB C6CrbRDvEoq%1K!4IfdɄ*lKɴd˾ sL6]}Xe֐d(ݺPY:;oکiTKlf0PM5]l&/)Fir t]oY[_9ve'lzi܂JMZl|ֈ%-օrjzQ߀Fk~F\QT/6ɨ k6[n_Fu 蠅ޒoef,!l[YedkgaZnƙ>]͸,+)fnF p"sa'=Lr"q( 2h'h Mgvf[\AǝH"$"rW_8wF_[cAㄻfiK\ -yǭw#?Łi?R3"p4i*ָ!9LՁ] @w …8 0;Vd"jF;cՈ.lx-AE'd3 F3s":cc,!I@ /1 R8X,!P1OL_NJa qL.=VƗbxԸB"L:! n#( !4B 7J~ChG~ю_! lżh cE6[ِƎb^L&A_H#>c_FVyH`!\q"P ˵CHF;l1G9&I?wCF8ӎeJ#)1Sb#+"'Ts8C_Рϊ/bE-~1Y|2}U_X ^iM c*F7fACH,nAjHyA:!xʓg> y"0JCZC t[pB*v Nhv9lX%N"Vwc(tJ  a%PAmAn\ cPc  `$XN P0X@* a[P.Dn+ wШݠ dX|rJ6 *($ B~P)p9e,h_ bT s +yx"X!* I h (! I@@ h@tpX^+̰3^!"hCȅ]+oT$UYj`Wٍv?1^pB*^dxr%8;1}tk>amYA ֒."-keO͠.\YPH[V`by @)Jc#4  Pq$.U/CW/w" @`0"(HA,( `ks$DB-4͙€ƝD` FPA頜:!,%~"aJٴ;:]Oc!O@KWqw5?!n$.' u0~q/vk B@b!`d>@+[Q! A[5_LQְk rGQ$I-# J5q4P/g4Q@pa /f@%@"z:>iѩ@a魲BA)`rh"b ,gA: ἒna}n@Z/-Ps;/bJ $29۬AE.Ɣ!L5UE`ITIe6Kl+!<-T-TlA Kx$AR4",h!arGDK 4]D0`J  ! `:~"`a$ /,@ 8n3} a-aX&m+T  B F'V.J!11W!-0xm!rdV'c"!T__kInrJ "KH aK d -o '6MNpTqPfB]vP}rd  *clr`nGAˆol6H4E'nDoRLգ~6b `)dnF%F`bF`J@w56vpH!.ҥ 0_'r+$W 免0K_dġPFi0ʈ֡(z#j l_\j!JHDZJآ-KAjD `յ֧A|VITKw*Ρ!xrAĭJ3`5x*IJdYzAe~UJ`Ԟa,L,"YT8!:Op!xOy'd)!$r4H/K%s"A4tA Wh7A0Hԡ|]j/"x^VJXaI4EϣȒY?8h^J~a}h!8)YdFWdv)\'ԕyˆXyI#3:lyE'aC`DsipD)Ϋ)Hơ.oa)<Ə) h0/*s0!sz )y}n($}t0e~wdp/ 5A/E08@wXh!2 !@#4DL|g"Zѝ99BJ9ACڡ?#';Do4=6I^*eL}SxTZˑbGqGǦKF+txz}|zR#z !18/!}˺֧B/dڭyΝvؖxƌNJj7cO,BTևI*4¦aheB dx' Ӫa8vϡ1/Eġ3!i$:y'CpXJv)I4M}0-(ơbd7k byh (́BʈC8*֧ŅꃻgƻÛ˻\ƻ{/Tzlajڛ9dQ۠_K l*|"a1*A)/<ãe;>|5AēMůVť \NbFfġoOYǗAȅB)C4Y;d*ɗ(%#˩e˽ٓ aPZ`w aGjz;FAj!h(ʫd"1rTn!I^ᵶw9A{k>(tDNd*xl2`dxd'r,,;Ip!o{Âkbhf!Vŭc*]kHĊ@c|}l*w**sAݲ:̝ãĥ=ڲ`_^֧Eߟ:߹ǹA੄Mă)2D$g58t r{R>DV!^eo3ba ma~x Mܻ{~A˛?>ۻ?$Ih O3e֎5Z |D6$|;ȴc͈ (5='=/=P3K[Tv}V3|o3-b9}c $'xh}>ڳb08'`~A9_'&.weݙgfnIxIgvމgzi$)#H2SMZk%Љ=_$%[:BLd̆# ,1‰ K$D0HcO1P0D)@;J铒\ hT |#_A " 4G%ݚiy @rIoދo$S C/dPs d ,v"4LR#/l-*KɪY[ܠm3㠣>Nx4 Qh50nbh8ERFjHpm!s B,|P*VUԀw0X'(/l<X% BGucӸa|:4 G;e4q8qS2(&¤e¤G7.AhTLG2e+t <^RO- R y*`!D"qUX$DH"O B%JR{FpdD$J4cA2>ySB!^eI'gR% ;D!\4iX͜t< yBX/sjH#ybpظqSt*g0Q?ᇁN<_Y[ mC#K0%#j is$a>L˔Sc2"H/4fjj~=g? ZA"B,8YDP9!n hv mQub m,h0 vCAjI/^ч6mH0ԇs}h@( fHBq3\CѠBqXL(#Bǐlq4׹~;%dBf_gv4 x81B־6(405up0Bf:?sGv4a4رGrHT&]e \xCxX8*LqHc/~+ @#ِ.nƐ&F5rquL1|pM6!蹘}Isd0n2e|Xzִ:ܱuH&kejd./|h :aZ<̵raco|c'VG b#@3giP7.HS >Kc.J[V DM#:s6PLMetDt]7ыlz-lkh[3~b s6ԁmÑnya]|汖g1Ad] 2j!goHely8tАE.bc^n`TcH/](GE;Chfi 3Q"(9j2YC0ť_p0|4,yU ]o gܢ/3V Ā2e҈7ގj;oA8v?؈@8h&ȍ!)#ިWGXDž鸎%dfi%wޑJD0!00 X$ك?xȑ)$ig2DP / ఒh\ K3x|؁X 0s$0]J0鹞eJ i4/(# @22p!~QVpA+ U+QXj0⠡  10W Zs9!05Z 7 9=P @ %0=U@ #J 3,]* pC` P(fm* p:H9d B+(/ D]e~p p-00b8 ! D00Bqw (!z Pp y34p3--: CP ߪh:MsTɳ(% |B,,A퀧! +ŀ t>2Z 0 +ʰa:0@` Zj>[`,Q#K %{%: =;3,IڢA}uʴO ?},!Җ }$ \۹ 9S)(o ! , )?# C0FA@[04I p 0  0 p饠[ au<[!q+쀙Э[+ ~Dr ߠWb:D(D f :/I ҀNCٚ 㽒PJ1R `7 pPD;0 l) {0   XLȅ'RկNP ~ZP[(Ru30 w `_p^v CP HڥZ-xF0 C𝾁/*{!𳅪Q, *QPN dǦ!ٺcl$*%!2ρ հ,|0z%σ@; &!őQ0TC @w+P˾ ,;W|E)SzA1%z \{3 29m=:Ac⇞Nc.n5陮Ε~靮SJNꧾd^s 2P > sWjx 7 0P؀ T}Lq :r  T>``nH}T'{s~dM>pI)ـ+4!^MhJjjР7؁v 20 +Y+?X0|'.]0j1Ď o0 خ"n7 \r[{F/!^{3 pB"|~z&<^}'{ZJo>=#_vnS*?iQIZ^N-@Ŵ1 ^hI+tY&i 3aʠ*uQ| !@"zc.D C@P jQ #>6$Me*n8tަM6N2`@*p԰vfI*QϞ]ؑfj%@r}cX0j֬]jPde s{W'{AWߩ&G.[%ULw9RvvA}538`E(!3`*3,`vAx{È+ _Eǟ_~0@]Dy!a)wGsgY%٢h Yt)&c D0{歸Šhfa62(jhiglG%`l_aYaJox+fvn":B)k@4̆v)z4lڡjlޢ٨as\;AtQ@JG,J ~Fr#`|5p9vi&Y jv9pa:|YgpfӶb0YeeYg6Zf $1@ =QP7CufYбΙK<Fi`lgFjDfgt4.[}rliYGZE7`hr3<0 ƙamGYL7QzFo7̆_)fiL EqAGnDqG_rebfop1G9%7fl1Z1Ƙv.3hPsCGYɅ^~mGa>;ooI aHX L|ʜvk^VF \zI AhGqG";.WJ@  gD"H=,OBAyD̙9B! -!X0UؾO uGme(s}{ݽO w<#0:'a; =$,@9I~ 'HUn7BЄ'Da _bA ".ǶbvT\,9}#4% "q,!8bGD#"F#B%Y|ňq6=pL6_,A''B{ 1TGלPшM H`@" )"`W G+vђh Ǹtbx@0P eЖe.uKHLaK0#sK`y3BңWcD0 d`aZgP ]!Mm#]2P?:^ uuƻ@SAYeFYȊ*e(ip} DNQTʥd#!̚\ (0`DFˆjj!s0KA (83PH nVg}y'l  b ePrV•g"( t oIDqx 7+pg(`G)qN?g2pqsq .rFr!Y $Bjr)O *%,ǣȂs)sDs56W 7?8Ͼ;g<.s/=q@'vEp?P8/HTdwo#@hWeoXl>yCVKE]Em0X F8 vWLC`s!t֐"s xM#*zd>! ȃ`'? `a/cv~XivdAX?po|vpۜTyu"IXx -\{X +<@`VbChY*rpx ,&UxvhHxwvhWi7FhlC -''ԂVr|~XPhV oiHە0? C `"R{PcЅzZ Ią> ֑.E{EHT'ymo'P'|SGխD;e=mA&mە/'IфsB"(o Y(' ؝bP߂I]P^tڿR}'p "Lp!ÆB(q"Ŋ/bԠB"bšC#q\';^9(ɔ+aYxI $gA@%/C1c6 TAf2fxHkk:qes78oSOZ;T}^X C|)JR^yI޹W7yܹsn4ҦONz5֮__8oέ{7޾.|8)?2e͎+[* 6#g@3.6*XL>:լ[U.s pN\㈣]@=$(x" %`qcD HD,m#MH JB ,hآ/iW7☣;أ?"#!>EL&7RQ*$i̒eUH!dTR0,ST_K1x#ك8 KSMN٠W+Rh q0$Fh ,xU 0;" ;,$ڪl4Z zSNH+La9 wC1;^uT7erfkZqvihTD;| H e"Λ,ܛasIT CZcx\Ѐ 3Õ7dY,LTpS5o2/\33.TuH 0͸U\3ϸ;N2<N?34OC2k&p@$@s WqS4!I:hv 6XC`9UMsM6ՌVP50̜:ՄTQS^Q̱s޹+ C#2&<230L8hĉM;G'OG=ug5^2砭6%lN;q]7T9}A!_?ę߿ U: %is1r\C\q|q.H~ oTE$$hd@J+񬡵kTޠ5GW>LٔlxCE1 Y(5̆8vBp7#FmGA$ i~rc;1z㎚i <A 2xFCh!h> iP4(sF%a wFtWXEg?RElq]"ig. `Xp#5 ;1&7Id21ȧ,:wZ3a_@._N]-Ȧ% t>ux \$s_0c':qbdCi4`"[9F(5o9cK1AI4Q =7‹ɃP1,*KaͯΨ6+YjVS4'ЩNv'=n'@v0ጄ.D7l'ŨF9;T$5i3PR4/m3d &47%gN] d@*QuT)\Y:z+U6ͪ*˸R"w4<+sȤϘE2![U]kG3Xݨ-Ƶ5+׵fKM!vR w E0t)?*fc/hƖsHCra^g4 (%pY,&Ⱥ^à 8Zt#*⨩KkV`T׈^iz2r,r9.u+\jew_+׫>כ_Wѣ|/0Ju%ے76 $*t͆I7ļdoO⑱XE&P ǍsB4;u|P>Hik4zY8ఇ,upAŢކ<1@M0. ^2W >@F3 b@i=iHÆS,ȧ?cсi"DGU8`Qv|=3O$ @ҸouC|cv kʹh,<`Y46P"j`Q>٤DG=P#g]W;{DO_/3Ǘo_}{|F@-(x8T" xȚ@'<1dFa:D#}B)Na}E!:C> @ OϼI<K޵5iir^垨 : `̉``F̅Zm '`WQRt_>MPF 靆"P%'C`T ( "mY.989B_h,\HcȏLCNšHH,@>œ\ "I D#B-@d 91 KЙ/xS[?d@ԍ|=R|M(ڃBB3B1H$ bh3,=4$ 5b􍚨} bAr큆9/#GTF 9ÄH!$<4D/A< QQBHǗD, ,1S;*8x <#iZc>Z ?֏? d\\>$C8̍"|`C,eEa~' qC\}cE, b1C/|1X+A LkN 8M30PE%0DOT%QE4E:8DUxI,M9dC3L"C1;x,0<-"L 44dADx":@ f3B54k6-Ă AlhXl$C08CP%4 _h4RQQ10ӌ Xe`B7Cuk#-0ט1E!D6]B))4BxT",dCH[DhbC7tC\3|6,<Ăn8CZ17`í487,З,4d.E;V|:L>!;B-B/k;1-5<[I7!ÛB3Ai~Y ,(C<$BĽ0%C۾m܂OAPfk"P,:;j5B8H)-9 î՟4B.FT9ZPip  4WTHx K !#0 ð 7p;qD 1YB3181K1[q:`q88LW8p;`j15'9x321hqN@ d1@ AKrr"cs6s"qR|CdH}Y\]<7G83Nmht k+%ٗ4E;,@S77@Хi]+MF 1khiS5jHp|30(^89s:H5C͝Ƴ.rh~)l@yLF@8τlgly5^;'±$ +#,r8l'R)L -lv.zjD3!Fi. y XjȮfb#fd8@p/<&H뮼& }if# c-@ PMF\,2a-HlRaU*MVemg)RH$ܒ/2Z/{QGe[eL- @P `-wnD6;Ԁ܁I) S)F AF\\Ƒ0-^j}%Bݑg'w[ـ%ؗayIhiqYgOsZ!@Yb!hlƚH "s?nP(>`e۪1Ƙfj\za~=o#yfC` `B,XHhLM % 6QvYoa+ Yd;%_gkp1NZQv(c= (m=@!"@1FaI[]lRAϯT +/Ż_m]@0͑( `|U-HZ A N5]!kXcNل,zAC2\ ^F;юk&53-=SOKF;!v ɀ3A`#ŖNBr13Q rd#GŠtc<5b芆7 gK8ԑ jx-!€ A X@E.7#!IIN$LRϱ_tŃ/"oHΐ 9A5q 3px>ÈjoC>|"a4_0 G!sCW5.qmP7 ~\ A1 :d=IGR?)i,1WOe5+$U(C QRԢmJ8Wr[iIMobpF3&kHf14qb18Lۀv!>PP?@̈́P$$N,qe'Qr-Gyu95ye,4 Q HBN q <\%c3} ձT6@R"C/,$GcTɩSCK]n/ճw}\p0Ypaw/! 7!@D"wɏ<a/sїnv`={5ý߇<6 շ>HB`$}_Կ$W7Q$q @&l_fA-=8 0D#r -p5p#

s1 Czaa2JͰ Da!&4nvi8]'ޡdTGNAzpvfhs%:0ā)!ZeSڱӖbCQ(@T hxtK"LwJ`A.CHDuEK$gaFw%nGtx!AAJ@^"@쁛h4`Q>I `a9B`(.|'t'f''4v<$cL'&\%(J4Q01JaF(:I/:aTfai6aAF`}U`v}VJ}.wJ@_j]Uk;ކ$~lQ mV2؁+Z-%ã>Xm^55# $@3ʠܶUJU`6a^e!}!mH^.wJawdWdW vvwC4h b7LV'8YvMAHXq!ax%+62/`a< aN^JTv D(J2j; AT f @_6a )Sĉ*DփTbb+ A'AW`x- F%*3V _vU(*zGSA"AbA1̉X>`UweZv˫57M׎ţi'pAiNGemT4gE#;*ߚ/`ʡC{Zu1.y^U~_$!M7kX0l(`Z$n^~cB'nBaK a('7(<5FL^G[Y<9>B+%89M&?PJԠ5`VdaoSzhAi.6wqFc遥d[2M)zAVhaL#*f$A:PA<_Os>c/Q!@A&IYDqhw$a1jIv',С0V@<'L)l'"p`x%L ;#z1FyUa!2{u<:[wwX!][t`}`֑;U7+4 {h^xGU$: EQP cc&{jG\%JL)[ťmҷ#;rs|lj}az1XbC+'X[UE֎bxRӣW%^JE īAȦ<AÉPh鼱t;alwZF*= +]^᭚*6|$(ܡ+}'$@yziģ޲q?m-ҲmšeAPA`=aacJةAz1]H"!浇Wca;yWh˸/VhZvځAm*%ݤW`6/X!!BU9 :5U`F_%-cٸ(4{9d8$`$P8c}q:-*S}>i%A<3! hLU<9﫾'i a9(@ҡB ,hA֫<(8$JQbT!ͭnw@$BwzN"Ĩd&>j kpv%8TMzEp;\H">"smጞTC`$3d~ٝvmceG91#ΰ7{X$&bH(W>GI؃p.e m\2Ci Yce|HN&;>DPrGi L`AZSnx:d!708L:x,)?r!v(7&MhDF-=i4) *=гGMR᳟S|@sX퀁 l#xLx fb8k9[QX!@f;Ў6{UMeV'4MO6;1Y"MHp oC NpZY8-~DC$nq@D E(xw -P!:bsZ(OWrB}jI@qn{B(X4Ȇ$`eh²Ɩ[Xza^pм˒H=ᵄ htH(P4S}×TD nl#m<"J #PB lnQPaͨ.ֻ%BAPސknC^Ua'j vF̎$9U[~01L@>X1>8<!!BTA;A*#H=s}8X} _'m m'~@XH` P|FpK(*x !=ႉG"P ހ IJC4"X"WC B5 ހC ,XVx~ Z @C D! N@B &) 0 PĤ 0р @+X8XVwU[GЈ Xxϖ !bO!SV"mW5S^E RaXxȘUИFXx3ظ؍8x蘎4،X8؏9Yy ِ9Yyّ "9$Y&y(*,ْ.0294Y6y8:<ٓ>@B9DYFyHJLٔNPR9TYVyXZ\ٕ^`b9dYfyhjlٖnpr9tYvyxz|ٗ~9Yy٘9Yyٙ9Yyٚ9Yyٛ9Yyșʹٜ9Yyؙڹٝ9Yy虞깞ٞ9Yyٟ:Zz ڠ:^`:C mʡ[n ! +*jhq& $)p:yg024Z ym^^1:nw1jJʤN%JgTZWfzNgsT ughRKo!7,!VY H*\ȰÇ#JHŋ3jȱǏ CIɓ(5A(Fʗ0cʜI͛8sɳOGV)XѣH*]ʴӧP> o(.jʵׯ`ÊU6$˶۷pʝ+5Y|:˷߿ {HuԐwǐ#KLb"@~ [ CMM0kC紧c˞MTT`c÷ NxdBE~dfmFgBƣKNPT3w$ËR,@xlg*U)B4!TT(h& 6F(Vhfv ($h(,0(4h8<@)DiH&L6PF)TViXf\v`)dihlp)tix|矀*蠄j衈&袌6裐F*餔Vj饘fS;i9묃.DeΪ >Ҡ*kr1͂O;e.+jl >`M68C3L1s:#N8#4Ö;α>ְ2j˭; {nϘ5`M5<34 < 3L35դ2o$8p'p0_[*bÍ,ӎ7dN- =س4 )|B"%FN:,H ҃4=″; T[uZst ItH'HR"TmO18# &wڅ' xyS@ xO/Bx1(;~Kߡ$"i׾ {cH:R IڸK-|H/rW( "#ܹ߻ 7@~K\ F' ;%K%H(F/lD#(9fhpC5~ np# E; GBQ>Ѐ0ay2J'9QBc~L"F:򑐌$'IJZ̤&7Nz (GIRL*WV򕰌,gIZ̥.w^ 0IbL2f:Ќ4IjZ̦6nz 8IrL:v~ @JЂMBІ:D'JъZͨF7юz HGJҒ(MJWҖ0LgJӚ8ͩNwӞ@ PJԢHMRԦ:PTJժZXͪVծz` XZ6 lh>Ѐ3C p/aL]#k\B@žj2+ZV3h 躇-`k]ۀ kX"6Mf5ka::UA|l = gJ-i WvgՂZ8 nšU F0@` ^p^І8 hKZ풉hn 0@Ы^?׽|{X l=+n!,Ak.~0[#V-( š6+xCń< ^@|1 0W tc- Y nC"<06Fx1 !V0dqY\e0a pX0 5/xPcvƳ̅

y ٢FE/ "V)hdǗv'ysL*WJAj!>4B` # Ta 7! ] d _#)Z#Ç"Rlb8Eh@ SXBR})␅@p jH%hBAz2@Au)ZIъZN5[ .WHRӋkr uG1|q`RXUF (dſQN@P7bҐ=yOr"gJ⋔`%%2H*D4eO}0J׺L8.7rIl:1UfTh5qӜN7K e?\c;{&Nqa 9+i] TCEiPȡ`, j;~َPMMMtf،1.W1uv6{Xየca2 fNUxe6kDS WU[Soh-cvHNԱ'fy5bkܪfOzަ#/_NS8|cȐ_ 6 s\wMG}7%| HG9C&;P2d2.{ˬ@\d,{O6FB>$/9nγW3LBs*ѐtME#yВδ7mWJ9Зn9MRԨNWVհgMZָεw^MbNf;ЎMj[ζn{MrNvMzη~NO;'N[ϸ7{ GN(OW0gN8Ϲw@ЇNHOҗ;PԧN[XϺַ{`NhOpNxϻOO;񐏼'O[ϼ7{GOқOWֻgOϽwoQ<&1V81>P:+QQ_$F$ bSA*T5 R! e/Bdj4sQ=|W}H!G~ge\P~G=~Gxqjt!8af1Rhe#?x}/x"2~= 5A52EU'4d,(a#1|3d7(9S;WJBHSTQg3T'OQisb F X  . dX# B; @ѴU"@ "!_5< @9wjW >d`X a!!8~6eaPapLh WeBV X\\4}@ (" 8]bpΐ  .a 3C '0 Ӑ=H @,V3  8X$d%p~ i ! 0YKC& 8 =  @ 6UX  Y QQ^*`*HDd^rux0 !Uߐ T0Ҁ_8T=!u%0 ` Pم%IDt p č<Bcb ?G9 J 7N 5 ߰(- :9(:P-vߐQP+f#U- uY6GDgS{ =W P].1Ű V"QP@, N/3Oـ 劝 u70͐A n9jf sTEP c4 #CY @8<O6<;pA0C{Ð zѤ1>_5F=@tT"-=##x >=q'ЀC JDâ0$$ f\4=0rD)Aj24p@T$j$f?AA62y\ P" ʰ|QUR08*@W2g͐8AadŪ,3`kJxJ:q8Q%bhpq 7 P ! <1C= ǰI43:i!TRp Z5Q` s8Q2A c6:'r"iC=EHyI p O6P߁Z"P$j+ 4r IAfG#B,FS+ưKI۱"":=O28LˆQY Q\:+w4rC4ՠw P; w9<-6aQ2 V  Qq. )#  7 X21 a&ظQ q):P 6E$ WQaIᠬ KYؐKܿq;  V ʂ0 3%@3D @#ȸd5L!+3 IS<< FDq@ú;" ! *P b 0|bX ;P3W!b gxF@- Ы <bPY)4dߔ^bzqB Yp2)F!m RtjT&gq=X'[YOSb }Y%CX ienhՄ=\h):Cq Rd4z)  H'c | (Eֽ}v@0Q ̰ X\Xƺ e=fmUBꊉV%rM$M~-؍TsBp _]ld`< ՠO=Y=R?rߞz5 "  @=B&\LD\?PMp}wHX}XZMSJn*'+XB0 L6 O!o!!٠Ӏ T"'qNƅӀ%(^]<}[{L>#-de@ik8%'@`ynx盥}? -9>b*A鸑nܚ闥#}.rT ><ѠTXpѬ?_ "?$_&(*,.02?4_68:<>@B?D_FHJLNPR?T_VXZ\^`b?d_fhjlnpr?t_vxz|~?_?_?_?_/| B0ï?NrKB;&!(IN AAJ[a! _FM@OE:_$X2(>B JzH >*IG!E$YI)UdK1eΤY+Wt %\g@N JiRQNZUYn底AӮaӲ@/e[qΥ[׮@\V҆>ӯM)<|cȑ%O\롒6 sgСE&]ig*xfʮQϦ]ma}Iw 0WD sѥOQSE/ި*&?ȓ䆒Y_QzsGBYU[ݖ ip?2bFCEbk |U*㦣}-ꥫRk-r^膎clV}[EJ9;*$d2mȞPHVi熊+klB תp 8S\%.G?1=A^ iyv+=Lwwz~xAxwxw-柗~zz}>{;V{>un'=|׊ ~h׸|0I`/}~s~8@`$+N]B co ۝58֔d IetkOAW<BAKgn "J,8p.C_a<^E4!IĤ$o9l"Q O2DqI#> QcCҟ:d-@8D0Eo2*d 6,ߦE7%8f@%ghdTc1H<ؒr"G8qscKVɭV2e/SrkC0^R$ILc"sI3b8G1 j#֌6X6dgAȹ,f<ڱvʊ'0)Y3Ƒ b6Cg8Ёh/qk'5юf: ̂ g;)p3. uӘ4qѓ¡E#𱀕C>a^cG41FCq fC5 uW G5jȩ&t }S8w@#:Q pڨF3!RtR{iA*Lb5U/:u,F, R m}kAlĆk ְ> խp+]뚩:,-5`ISq "Ytb>@1xT;KDH,g w H<2zd8oAߎ| 0>füKdq>js]Tt4~ZgA|! i|5:K,$,A[__pD4bkp$>@ajģaa kI(7iOvgk@iI|#[Q6eGzrX ~H"  \# Ļi|L(F^Pģx2t +>i67hJbj&a b {pA=s 0<Dj8aHF@|d.4R԰F5R NQS @7n,h 62V{ ܄@!pCC9̱ x$ nA-܊ 3a~(1z H8a)7 o! \ /ЁtL bq28! T&pC9kYX6w;m|!D`c83 KXG%;`? ('\t;tmvMIX{?/$9D_D 9|=b lA=Hͺ3o^$ܓO |\u;~q@F}TqC@3#Xpghp0l8Ź:eP8y#.Y,&r,|@&>#-p\;{YC se(G`BVc=F|jE:y"iEZ+VE{^c&W3sadbcdteph33jFlmFrćxǃGsD[GqhG }\;lGG |,G~LE Hl$=[x3YC<,kвe&~ǥoJb&rspjby%0ZkJL`p+n@lCKfа:jSԪjsI{o0eHkJq`JHX:9I!Yʦ|JgJi;*\JbJleKlt+TZbc 1`Ks˟˙˅lI͋DL|8^GrȔLzDFLHDJ%di0#Vj~Ҫ3HlhJ3֛pDsP'fΜ͐D}PP P P d|(rt^D+;GlPL,EP&4m QQ ] -jI!$n;|p4ӥ+8GQ%Q" pRn/*X$Us#'e(ѭ*}Fyb@u7X*>v(l"l*@4Q5 +C-S%|#cR/3bjuZJębvD4]T j+p|" X;K뻟K22bpU FKm[%=EZ+R:G`<"@NVc d'KVwxg>"l2`|!60l}e1 r6mtv#,yPW0B\8X r-xط8WqW=DGUxF'Y{d)PUYI瀆kD=*-Sق-e%Y=Z𤗀5Z`Y"Qp[ƉIY> T "QSR[AZIUX| X )(Z\RXoUܛ`oHv0 Zp̕nKX)4oջe)(U]a])(\Sݢ`4H-,qjf;=%5^DJo.`p_tR|*{ȇř^?&EjTb @w5c,@sT:R Q I^+rhKdhPֆ8E]p~{|fɄ(F뫚QzO*^8,̆kŔaQt )y92)B&:cL4e__þ_0_.ŧǒ`,]l,xߑCYh/r^ ֪b`J`hi;#0JaghE+R JFt(3aj)U2-Wںb#$6W&Oy<[bs,>.'/c 4J5nJfOb92:S3|_0q@bW*ыHTMw70.AasE)\vĪ&bA>>l89[Z.3\g*&,]I]GR&G?b@`g3\]3cyj*Yijjjjjjkj^O,K[f|J?rn:瘢v(r+GYnp0Tah3hp0K3 Ç1>.i"6iij1r*if;i%Õlf(tćnH꥖j6Rk.ano&o.ჂbvPVknnҵW6Vizr82Ϋ %iP>%A^f{>,UvpC .i_`ҳc0`8c*9^u \J^>Fc Y+!7qY%a>*Gk@}p|畜hlX.bXn;:E`jpmg8s99 :ss?t:Ff\KEgKo3ﳆx:_NlbIz*_+*H3kpbJD\pT,/2=ZqNq=|8.fSULQĨ3W6ir*r*m&b&jrҭX"=f3U`^rebrw}Wsml:VPLs]nsts@OxshxxA't U5NL.V缦:v9Ov%36S$+iD6Ir$d82#l}HUO\Va6:fkxbyoC1Prj x1x\ k{{jh,5lE/Kxeg;{z{.PWd)&SyHܻp:av[4{'G/{zw/|ʫ7{@{g7oo~?'v翏؆^zx0ɳ;/8 eE8t(q@yOIc™34}֮D|eў)[>i(Мʖg딑>Pm[8n\8ffewN'@-"=T" ʹs8gΚ<(0ܸv<m3OF*]0C&/.l0Ċ3n1Ȍl2̚7s3ʩ2W-$4"7Sw3H5 |<\m1ͲɵKp5/[6`S+oCvVV-Fu_m|%OBWgG_]I=aYp.V'ŁUYmB$x.lLpI- ]\g/0#-"18㋔v#9#=z4D/ukJ%M (QyYu zCMS6i4ҀU2G-BDFef848$42,\c,k! NoD0#'>L3\S>$L5ScY k>BCN5_~DBDPJ;JS'~J>0L3 "qL[[cL/HI2H$H!#j-z-;.f@"$e` ]ԫzQ+=0CX1A7mdS;u,I@oc*: -;JS " >HTQ2iAz4Y D5RK-AkP0#Gńs3B|P :@~RBǒ5]{5a=h&QjA4H5AJ$':,<r ɍ$y9@c= 7Hl Ė 9MSKDMQ;J%>4j髿>>??o?럿%h kJ*[4!#xLЬʸGVy%C 29tBncG]O"Cyd'&DTIi'[`fZ5Jq/EALafq/v5n|#HmHrәN(P*Hejؙ>f-Q;q8:M*IBɂ A|$?$MAs}iFDn$Έ@V@F3aqi"qə23*I"Q- u9Rּ&6: )Ϥ-| h$&tKÌaDz&Mvq) fɃǨ|!?FF˴l+ci(SJP4`/=i4#beљhdHC͝>)yt%"x iBɃ"U͈ rq-2!j XLTYW[) =DJx- G(l0z"+ >j! DD!i(8oX!9X)Q(,H mEQ8#`l1Xk L)k_Kc\dDR#"T5:Ȉ&e|0&f BH$0sVøaF!L.4 }/|+ߌՎ;3S_4!diM>Rzix`4ї֢CHy-u1JzbjDV |H8R@rؿ$! c" i|c߉F4̚kͅ\NhSw(Fa}q f2hպ0E[p[sʐ3Gq:pCdij8]=w+/E믾D%RlDC)>lR(vNo8iNAq[$yBIw4+Y`I,Dž0 dj< u=u8GBi@'66 h[Vq<'67//#`:m2gC`Ƨ# &dwQw87a{ :Џd43!Ail u8ځD(Cx 1Ab)!aȬlp1CRF/X %n 8kdYvnrK`Nzin;ȸ7ݎݼƺ-o`<̰H7D t_y`,$Ze-C=PXH_8wٌ,JSSnRqc8C/[Q0g#=c/~?/ӿ?ߌυ'=2͞.AH ]9b]9P[fN)MYiE}Y}F_y  _.Aa6LH5XX( {ȣ5MR5@8t`f8P\l]Cᣤ!rNul7C1f ""&"z:a|Θ_\adnt!fa3!!ReDE9~Np5Џ,diB-/0ܵD-"2&2vK#.cO@53N#5V5Q3^5A`6~#88jK6c1 ::#;;#<4#=<>#?#<#@ڣ@A$B&B6C>$DFA(ajDfFn$G*"EEfu$II$1$J$KKZJL$MdǙ}٤N$O$ĤOPM%Q%R&FR6S>%@2%TN%UV3JUfVn%b%W~%X|yXY%5%Z%[ר[ƥ\%%]%^efإ^_%_`f[&a&b~a&&c6S.cFd%dNe^LV&fn&gfv&hC~hiF%NjI&k&l*k&m֦ΦmnnofJ&p'qzp'r&gr6ss>tNgD'u^'v2qf'wvgYwxrxym'z'{rKy'|z{'}^|'~:}'~'((&(6(rF(NV(2f(v(准(刖(剦(劶(r(V(:(()z)&&)6)zF)V)>f)"v)䗆)㘖)㙦)V㚶)))))ޟ*jܠ**ڡ&*ע6*F7EJP]*jQjCf*4e!*$> 5a`6*뎠AlAF|+HAH+WZ+Bh>b)+R|AB䁲A|>ā(vkF|R+fPkF\< +CA"xAkHtG\kF>¬G`BlA︅*+n뾪՚A>-J+f0DGkTflV@AdApݚlA6HҬD  DJ$"- ʁLl ʁZ-&CnD8,>h>4(~-ALpA T .>.>>x r!D *kXm޺EmR+袁AثT"Dn"DHɺ"+/>HBdlFBD,M@oFDzPAAmZmjD,BAdG>A+>kejD 0KDA->(-h-ܺ*+ɒ0> $CW".# A"kLl#pޚ0B@/olllȰ_F& 8@kl@7k+>,.Um_AsnAJD',G1>q,> ߺh,(ADrF0.+pFārA0G +{fD8D0rF dĵ{kJ&i0{0s"3.sD3ĖA-ce2*l3D> HG43T)AA,V_+.AP3ieGLl2B 3ssbu.rVxA3%D?22-^AThk+KK#Vlκ^kUzt{.fKf"+p3>UUT|D`l,'+FtVgDG p7qtF55Bh0>|@ϒ%-TurfT%-8UA`e@6(|,z.k{nnA,+L0A_5[S qԵ׎E6M7,lnLB@s>-p|M+\ 2T@ VD22iAAp8AN-^06:710Z>A2נ3+dAmЁA]7ws[G-0cS0myRs*8xl.t2c6f3)wsx/o9|{67j6>Ċ /0^m/6AjmBdzq/8N3v:02 ?mc{oF[w (ߎ`06w;nAD{nk;m3k_,>0+{p3N߶KSkv6{kR o<ׁ_i ï-9gԗi,8\C5p!7:&b}:C`V+:> R(V7x÷}5a6ThfQ5`a]_} QwVFW Q2(C.!m=3νWC< >>ay\ܱb ?kM[Ka$>K8WM^5Z)??5n)6ӿ5Pc@!',/x H*\ȰÇ#JHŋ3jǏ CIɓ(S\ɲ˗0c ͛8sɳϟ@ JṭH*]ʴSEJJիXjׯ`Ê ٳhӪ]˶[pʝK7ۻx˷ٺ ׯÈ+^lǐ#dL˘3g̹gǚCMϨSkװc\M헲s[M㈅+_У_eN:dسk߮ѺtO<>ӳ6Ͼ{˷߀&U 6FT(fQΧ P$'(fXޥ(#s0hc}3܍<(@#[G$$ C&SL6^2<)%NMVٔfXvy`FVLA6SCcQpUGy@i|*矀IZC2)\FE@@5YD>XEH@:萩 觰~PPDڐ)*h6+P@b+$;g,O !T!"˴nF+LkFҹ+&&ի+Ҿl|&<0갿WZqmv|/$c)r%r,5Ɯ.8h9,@C;m4LǨ4MG PKm}Tze +`a؞6vh?ϵ(t'7u ql|'ሓfx7V:.eG>U^%yLn:^yl$밣庎׾rKtµ#KE)go</}(#a' |E1i/:Ȍ`4[@X0bCC( a8ʡ$*#NQAw3 3!FE;C|Ds#$G ~" t<@yX㧚;t!Qi#_FQI(3d)KZ@c`Aؗv#GD d2) :.P8_\78jHxC(4@! <}´҄U11@H;r fCL #Yw$F* MƂ׸5&TZUh>u"hG3F,5H5p4h0gb~,^1"p)l_"+Z:f&R' ,/~4ti^"aP;j89 mX~=,Xa̰V7e6QZ!nta|}>B)>h,Q\XE# j hb>3!hqU& b NA \䥅-_;,|XxZ_1i6~B`-l 5`8q+ËN/qj4!gu H#v!q[-56] 3j>MV|9<[.}M:՗i}m?J繧7䡎s9 ux]BKj(C3t Ұ ߀P OQ@gB@a ! @Qޠ d2x4C  G` At!p  o'G7 hpU!vGuu>bz̐ ypN$ [IZ @p Y "dz |\ p7~q4~ ~W g']8x  B tK]h? ` $< ސ !8%x ;\0H2Gt:00PGVN(]Px0e#Zø_cXtipsapQ & (VSjP yŋsn.wK P 0@ݣ ? ƃ1 PT\ 3  o0 [ k7C( p Qpq| xq܀&>v0 "7oDy$hi0 rIpb7y%c r$ m0ec րnXp$ Pi6+5I>q琐lI`;unP!_i x0 24)oRQ3dk B D) aTH(?RIyXWZ \ɃaecY=9Tlin)opnr t vՠwٗ(Baty 6RVC O?0 UA߀SAZ5 "d pbhED>( @ 0 LЀt?WҀ XvՐ `gSVŀ` 5  C B'<9?vth'`qd|7ys-yy(*x˩qKI(;Y0 <>(lx#xi8"*%p^124X `VO ڐ zZUq`0 SdZd V cЌ Q΀Π 0r$wC6zQ ܴM ٞKw@D`g U tВ^:QP[x Pe*mBer% _Z w 0(jچa сjJ i00ﰱ/EM6IU W@\^@   * ,CC0Y/`AH 0Ey g(W  M N9L `HK0e&_0LF0Nwnjl;     NcK xq [e3 q5j~EM@* ]\0FT@G0 tP*`I;SPFKak7 ` ga>-v P @а [ GA ۱' ]|i^fl;z5M6 (|ɺ K[0뻿ěIFEO@HA% Š`,ûOpIƒpL Vf ǟ` Pyl3 kyL # z\v lzI`Gc\˫K{ylG 0a cGg kG@ Mo>DAI^y#_)U:x@OdG` Ʊ |$ PI>QI@ORp>=J24 Uj >8>۱If T AmÀAc FA ;vHhL /h<[ܱ63;Ik<, Ҡ]`EP#K- N=YpLJ=\E]LD#ɳ]{%`P͔qY_@ 7PbW` ˻K@t{xE٥OWq08>0 6@R4ձ .%V[ \ʅQ4ڀ ^u@SSǍMH:?10Kv `ПkG @S0å ,PvT' /08{.K?~ ™n Ko KY Ԡ]I PD k`\ P@P~NMl?ǤP>n \uFhAp wOXa: , P W,.  S~{~O 0RCpH@ CF74FŠٔy#'lG0>o~P= @TZNYF Aڣ Q0+  `nІA%xހp  @R>P'% :LI nPp#KI/mŸ SpL^'ε)nGS   ZK +ۻ[@]c Ð]/U>ϐ^~0 Z  Za^0x6? @ >F`FJrn>r\w4?`m\_ L Ph/PJ R[^pǞ @VڅIiӥ.g Р$k~I p8]@[M >PBEMP -[ Q=NcW &z p `GZdJ0 P *P  ^e ;P ) $q3P$p X%l>|J$ B 4P$X@Exv:5!5HDZxtq1cK`.$>s7n|tGޮ(F0g% ]Y<d-^FID=‡7D昱K?7aj঻$(pCA4XЙvsO^uٵowŏ'_): #DTC _FY`d Dq`fyFxnUPJEyY DDpYv .pj[H`E$ɭ1wR@.f6ba=Q;*)wzĈ* hDk*҂vaйE'"# d 1dKDΉѽɄ3g:#cF+© B*xJkd YAd8^ơqig9Vxava#xb+bUPP0#7G@Q@ M6@4

a0<Ǟ+9~ڞ*p]*`*5wl&88BR~E ŝC\Y'lf>_0KCvv`A\ Ppv@aXTrZ ' x%ƝRd1hIv[W$N9>K$"iDqu1-?lj"p+L/Bc`-xA fP~4d aX2a:Pz4-< ,h?["hI=T0^%*D #"1;QT!Q!DAai ݢuk4Q P@6Y!X00@KMp2k018 !-`U1 Ejw;`CA;P`*l V=6! #xC`S "L` EY}ؠ8zQts8jWH,>[" ,g ؃7!tH- _@a{&Uh@a x"iD#Ҡ-.~,HD @o} 0@IJ=Nfv(ʊp8bͅ,0C E.@^ T[:Y$2@G# N_ю p-|a gXyAv1;~Qbcְ/Xl \X!&1F1*cXbN3%Tɀ3Y'(j;ЋsQl8юk\ ~&sOu2Ja%hG/z@ɒ|vp 3Tasd, =7c3>sDL~fL͆C-69Ul&Ys^Ig:=ozX-f$eutPjxoauXv((Ég: K;uyȺ D @耛hP;\c2J_ڸ F5\6;<&S6+s4)23sS<35B5FA;whvw S=-B.B/|H&G‡#8`kmD Yno{qIo@`jHli:d9Bgr4ikqCtlHC`Pe \8{ LEؠ=j q `ȅ;/E]E^0L7#+Cf8CH5lYx8:D;ìWC`@\ACDDt8) GOl7KDMĘNLCPE| E*S UAjXEI[VEH,Hfx g$ q ʿl젏ppjȲTQCIilh{#$tnY$ #;tep# 1Jܾ *J_H|k8dST3HJ@H+ zHfȉ kȏlʲ|1 uu 1v`˷c0o-i &IC|Kdt&h `H>W d 2JLLD(_LF :M\MlM|M1z÷qXS?S@ TATB-TC=TDMTE]TFmTG}THTITJTKTLTMTNTOTP UQUR-US=UTMUU]UVmUW}UXUYUZU[U\U]U^U_U` VaVb-Vc=VdMVe]VfmVg}VhViVjVkVlVmVnVoVp WqWr-Ws=WtMWu]WvmWw}WxWyWzW{W|W}W~WW XX-X=XMX]XmX}XXQjhfʆXXXXمaؐ Ym];;kYŏEY(33.h9-ZY/Ђ/+/500Z=Xکګ-Zdm6`6h4X/-8;?ȃ=@Lm[#(/h5ڀm.p1X5PE ,H4؃ -?۫=Ղ7+<؂0۳:\62<9@<3`=xڀ590a@*p@ 8 Ȁ_1؂-x[ X1@>RĽڨnN:3"p^ <Z-#|pa=&[|\a>h~Ĉ[a-8^E ?-؃.1 B~[Hu6b-P-NH:6xZ5؃-c#`ƸM<8Ň!<=c>յd5^+0P_ D-G^^5b^ڭ*0. F5g~8\-@B ///Z.XZ,^`)ނ6^xea"?.Hޕdd`m>~NLFn-eX78:Rn5+.@g.@2ba֥Hm/b8vn.=^5a|a2^`^e3hf48[61xƐgf4xiopgᵍc< (~h_EbX\B ^΃Z5k(5@ۥ Zv\o.0kV`mk4F=p+`}kf}8Fv-Ђm?@xd~_6@ vm۾Ň.c"0h!m~&5^oob\Un5n:>^g̓U-pZ5W?5]5ȂՃ=W5'pZf8c/x[ P ?9`P8[4af`#(ME`#m$_m(a[lŀ4~qڷ< `.Xb|Pa. X &K=xF!! Fւ;@Z/[,PUSw+9qK9p1uAZ8n9u`׵Ev5cu]5^70[|7:vĥ:P3\q%Z>@9/Pn>;Z;/c}g~aUzfڇn[2HzRp9 4qW`gxh'3Yu=w`oG;_w=\osx۾_%xVn4ZV3rl[{uχ5%ZzwWχ^۹[6۽g3|zwy÷}]σn|fx#8 |lٗq8 l* wJ8hKG!jX vn!%S!x"AW!., H*\ȰÇ#JHŋ3jH0Ǐ ȱɓ(S\ɲ˗0cʜIM!s~ɳϟ@ Jѣ*uDʴӧPJJ*BKjʵׯ`JRٳhӪ]v(YmʝK]d˷߿/L{#^̸HCLϠoӨzװ۸Wͻ w>R%|Ǒ$E 6ģSu.+G Y ϫGyCn@gID7 X`@,Љ3bjh>/\ 2<4bƂy{X| > C#&IVb (F._!>I$A%E 7 -|LG wUL B2p-p|WwCU{Z6:$:/q̧>1lJ>A<>z/{1IS Ďz 0 vk. \#6M|AI4 Y45`n d@5dk Nkh3aY6 qA1kP~0AXB})4g.3lG=PxS b^4A J3հO\QPR !]$ZU ^( `a|܀P`o} ^pA,0Πa? BF|!MK7 $@e8\5Ajp8G3!p;AAoG61 `Q5j7 CS92>? !1,xA Pa*ص3Hŋ3jȱǏ CIɓ(S\ɲ˗0cʜ9w j;k@#6t(>k4*]ʴӧPJJU6o)R(c椵O4IS7pʝKݻx6֭d qfۅOǐ#KLeȑ)KvrLӨS&ysg^M۸shoxȓ+_G/N+Ν;>sұOڻw^vz}'Xh 6TރVh(E݄vjx hڷa{(ש8"0h㍶X8㏕ Did\BxL6IS4:)TeXf%FWnS c$hI$lp&niYwxzY矄_ j袌F*)u9饘W陙v)m~*ꨥJꩨ>fjת*Sj1Պ뮼k㋰&©*lVl6+KZmEKVR۩٫һᅨ L*v: iJL[ZTjLz DL8/& 4l8<@-DmH'L7PG-TWmXg\w`-dmhlp-tmx|߀.n'E EjxTW|anfLl@AyadG|h9T{P>WtE[`< 9PC%;Fl`hp_х75[|kA@axF^!#!obĪ= y T.h_R~9PbyPCӀ6o$H8xXȈ皇1}A Z(ʑpkZ@XPֵ y @ @L`>P2 Qk_hCW3O@,{hCH2lH>F1&!_,  L H0 ",aÄ!FT`1&q#G>f(GCrʕ-Add͓7STbϟ=C!), Iq H*\ȰÇ#JHŋ3jȱǏ CIɓ(S"d 0cʜI͛8sɳϟ(ѣH*]ʴӧP1JI(FԫXjʵׯ`-RX` aӪ]˶۷p* x˷߿K2*>&+^̸ǐC4XL E̹Ϡٲ EJ MJ%+װc˞M2>Vsͻ Nȓ+_μУKNسkνËOӫ_Ͼ˟OϿ(h& 6F(Vhfv ($h(,0(4h8<@)DiH&L6PF)TViXf\v`)dihlp)tix|矀*蠄j衈&袌6裐F*餔Vj饘f馜v駠*ꨤjꩨꪬ꫰*무j뭸뮼+k&6F+Vkfv+k覫+k,ln p> Onqn128#88 4q!\)r/33>5}3L3$2/C E|Iʹ@mT3c5Y$B'Ѓ/W# (o 7=ڹBL=0$%B/2| "9 h^ -@H R!!sn$)`@:>ը0¹͸ P%('<=7xwmo9%xO$3@8bGD_xO H]?x(G*ITx!xDnl[ `3a5qgBM$B3ҔB%>T P䕰\,i3[sU@!2,!HY H*\ȰÇ#JHŋ3jȱǏ CIɓ(32IXCFʗ0cʜI͛8sɳOGIѣH*]ʴӧ $aիXjʵׯ ,BXhӪ]˶۷P qܻx˷Rb I)+^̸㌬ H3k̹筬BRHBR̺װckL۸eͻ Nȓ+_μУKNسkνËOӫ_Ͼ˟OϿ(h& 6F(Vhfv ($h(,0(4h8<@)DiH&L6PF)TViXf\v`)dihlp)tix|矀*蠄j衈&袌6裐F*餔Vj饘f馜v駠*ꨤjꩨꪬ꫰*무j뭸뮼+k&6F+Vkfv+k覫+k,l' 7G0< 0ߠ8tΜs 0$ (5\#q[{ $,xM6ߤ92 3*3Bm4J3@-5+||b=D/"I %H4([}kN;K;t]/ " ( 2$x <`y mC䟺sNw %zN=7#I %N$ˢ${|?3O $4.73K"^</~ӎ%XB:|P/SN1z ~#=@ t4PBq @xDb8+@BLHF2|1oȣn9ˊ0T!|q8c(@9K#Lt8(E.P>EKNF;Q iC:qb@!G:Jc@4uC$(H|P4nt"B| IN$&5IO^AHiJI}9Ѷd\bT%/YZR@v_,41٨!^,1KwN7n)$N !'A 1t1D|ΥCoܷq~=c[GC,y2ʖ/%~ܩ Yby.Ý#>BKƮ[X~5Ή@I铽sF3w;I+D(!^eD@%HT_A}*A%(K/>II"h=1"!)5❆e ţA y_bt;S+uY=yuf{z+0u_~,\sXZ[ws, 48q#NB:dM9 3UJHjȡ\sM8$2_; AlVmZs@E5o|T"=[+ݻ@$RT҅n;oŻM` W0_#|I3]5L8 H %8` 3&*xNlX0#:Ђ7SˍH4,#:T;d؎98G80#48 Cdh>`PJVb%^~I38M;7#9\c5dӤl tzgd;plsense-0.3.4/image/demo1.png000066400000000000000000000601701260377356000160010ustar00rootroot00000000000000PNG  IHDR0J sRGBgAMA a cHRMz&u0`:pQ<_IDATx^O%Kwd/͠l6hc f(-$\w`B% ){᷸5j?y\yeѼ^o4.ӭ77㫌?2"2"O}*OȈ/◿_!xoÿk? O?W~;ovȿoG|_39pJGٿ+n-ՇÓ// W~ =bׇO /~kb_:J;е~|8_ÿyO~M7?O} @h@'?~zzz?[Z}ϟ>|zo|AT񣏾_ۿWW;bm7Wp}A"Nٯ?}Ow?y-}˖[4ZOY(@ Ij/~_(Ͼ>QJӿWv/B|WϬ XkG>׏ϟ맿uu>?XL_\j'UwS;8| @`&}Ͼ?lZwS??=-G_ ڥwZ/^wQw{_XU/@_r?| @XЏ) ;ը^'' * @ P-]bȡo4'C @`*^c lC @i TiB @@=߀ @@3f  @@=߀ @@3f  @@=߀ @@3f  @@=߀ @@3f  @@=߀ @@3f  @@=߀ @@3f  @@=߀ @@3f  @@=߀ @@3f  @@=%CKt   2C @{& },B pFY>Nc>GOl?O>?1s%}c 5ڈמ@f:/-H@ Q g_|J۞W._!hOuBTwVO#N+>?zU{7Ao'B_50( @ą[OGEq;CDi,v <=1gRj,GOxmy#B_{(@ D^ELF?G?z(]:<,J?"HhLSш{LdN2&1R`sw+r& .;t= ~ ՝(OtW2%zoo ^Ji_r vIy=3ڙП{ @@XuөX+"gFe?X-I.]wC5x8s O?G|kq?~6r_"zO~^P~v/G QTGDdݯiDN e!@8UnM&ݿ)6^m坤 <>F{ .% ޵vףHqi`]MMM7z#W}{7;.}۪P}.A'r\*rt&+fx*>,'@j ?7z-o@i3ͷ96#B_r%AX6#|]f8ax'eGF<>_bЯT^h:;_,=&+F#tlLXhvЗ '@ p~BdF#ye.kRnP=NJMo%$J6گH-K-p^gkm{t{Dg4s;>aO{ɴ1ukD\jmW UZTx nqپSu'ᾜUdbӊ{|tyeW/1/X8~ЗA  @'\ҮBcCBG\Q }WSdpcG]:-n~U+ۈLZKntO'nzݏJ<*7ۙП{ @@AMI5q9qk#֩Yvm%A?"5O|NR=BT @BtgFe'\tLvL@Oh _;{2_"zU>@0MYNW9k3B聡Y @w?տr@@ 9A ,< 0$3o (2 􍞶 k@Y=: y@ #7o^<{kS[8-xL L<?HG6p,Z , zGi_gIw3[sXfYS79W%龄ٿ&yL?:>v\jX >S΄;BKp*06jMD ,zT%MB#JFī9ͮSpqBdMh_tЛkqь`zӐ/3\N8BB`ߊ,r f07EB SӦկ#thz)7z>fPC~jݛD=hL#7/mF]0AztL(s*=: O~;}hS|d^Wϟ~w;o~| *zoTyô{'ZȼdTXXg]2$M!ųކEFM:Ͱnt#M'ˡ5iψoB?^2ladEn'H?AŦ+(Wj?c/\  ,jR{F?Qe~u>ԙ_~xGvCE?Fr^ptHX"iXԕt{|qTPɽBG4Ћ.G﵍nǒHwUSB(.9$s臣`A No;Ue ,j^{o{C REeS5VA@/Qrc>[+KOi3e)U8Ve=μGs4&Yt }8fl2EGk{F[KqXHwDAGg!0ЋP}?wR|'I]z?Z& igf$,h_E~]FRy@֖1Y#0Чڙ> ~LG"- }"'W2y8ޕ2QBUJ 7&oBB`j4!s)&54L^]G:VcI2}PJ #ɑ"S&LhS}mzAOEÓ_0_lNi,t=L7RhgC SArjvX=aݛ=a OqC#E5)d"c Ҫ@Y"]8S8}geCoTB?xYfǁP~MK>o'#v:󍬸0KҎU_?8K ˡ`Ub2ݏًyƭM?lX(U*wg,ă^"Bj%cs]5Gg!P# HУ& (B4/$ (B_s9 , %У 0 #%У@qW@= У@Kd2@z@@Y }@= У~_2Ko? G!4JGg!P-vIoDNlBB`Vx gN = F ,je/5/|NB!E>GV uB艜$ @+Qy)Uew77o#%УE n[Gѳ8I@,Bo":OAe|~eY7Dqz@@Y'Zd^Bo j 􍞰 CBH@Y!ww=E95G!BB`Ы`){έiwtu%ȉYB@Y JfB`V#%У@g>*,9I@=: ~Jf%#%У@g>*,9I@=: ~Jf%#%У@g>*,9I@=: YoJGL`Bų7^]^izzdzt u S H k" }u#g_ј&z'lD&d/T ۤ?^=ӥ|q|d^5Su^rUf~ $iF5@k}}8֮c  +)9vr-j Nڕz~)DLi&/xs]Hx (vBlhhz ," @V#嵼?9ݱ(珞.ܼLw7PzƘLl#mjUuB/,z1l{E38a@SGvob 1o&HЯG4AY!]^$(F b.G'%>?BMQ^!_a]޿|UԄATd_`jW; %~$Mԉ?,ﷶJ+GB?xysdNG~Me1}t jW_MBbolB/AGg!0+}V&;'i [u/J^qh?"Yvo ݝ{Paz9mTkJXjFw٬Hv\;*Usto/)'tN}jǛ=qWT1d}0H!5hN=: ^'rrJ Jos;-}ny?us}Q3)ÜB?/O3 }4.Spuw/wIKk )׃k0jBlD'H!У8ЛȽ#Bo4П[[_@AKȯ[ݯ6&ʔ0?NH*"n$~5Y(˞^yE%6.E֫DL _zpS[ BBB|6bE^@> )d%z/"**$ Rn~'л 8.SJE*}eHҹAxiBLF|F^p׾o YoY6)MO%8&q| B҂"W Mg9C;B=oW>QAdw}T֨OBsG~bB],79X4ym0M9 9NK7%OGu-Is}AYLz6~npp9?ͰQztzyB yqit}LޮVAΕ VGSDvfmMl lw10r?׏O{T*1w6;/ʍ^tȝCUn2r/M(9NGg!P/˫- ~b)xm B~5dk$3 (BF'7z"o'FHK  ,!{\# (BF'7z"_*"~!v ,!{\# (BF'7z"o'FHK  ,!{\# (BF'7z"_*"~!v ,& CRՖ BChBBV^bsq|xy'Kl|y{{a6@n/.no0w< ۉ@`)=: *\SKs7BVv{6GvO@r1SutFz@@Y0l?B{W^3N7}ghBBF@`3B o 2Fdo%УDz'-gIxtFOMi  @Ы\I&X{qГrӺ>BCX@<'@gۍb GG_ى0!!У -ȡG!4JGg!!{Ա}}'EhBB߾9 = F ,9d:OoDT@@Y WQz8 (B?Q  S@)=: YRs}[#/)W76Rû+}̞ykJnlDZ<~0;zlH\>^e䬄BBBd^=`[VH`=BcDhиU] LO 5zq~>̯;(#TvBxy7=5HC=jc~A 3@Y\_dڒЬ!bVXJ7Wpnuc͗oR赋Cŋоؖ4; Օ];2=: IBG7!f47kzaƍXש:5h)Đ}}&&{^fg"w-˳wbUͤ^Ϻ\)6ہ3KmSQ-K@YT swo [_%[5Ν7 {wN^\> ]tEMvɂ ÈxF轪(DDŽ^th9~B?RC#~)7z=ih8.9O>1b$^z/ 謋X~\.zyfV\4 jdxl=: *^wΣ3ͻ~cDl+boT$ |{]l0F}TG|+z~*[XRn <@/W<{վ~-"vx,޸*sٸЛ%^.=.ށ&q XbR3 dI"e|1{@nnCeЯPjd1D}p )]gު >QP>2%F& Jv'7[(Ћ`)8qO՟}] }ą_kݖ|:M䱎~Eۨ{2B0E7yKkŨuW粭"AYTY{Oo@l+LoVVk G2S70 9!%p8> z="!)}R.,wnPjzw7w$&u2T vgNJ)pv=: wl7+9 72B9b7}4g j3_uǻ3~?UnOTpͲ&"üNpeƝovK?{pXl&V+[/NztBA`֓CP~j OvFKhy ,})%sޝ_%4B\_Pi0a|_)M9k(=: V(O4[NNGg!SO\N~" @y=: ~.}@!@`a=: ~J"i  ,ĎzI ,}j(§1"s У@;'&У$7zfOcD @Gg!P'w/ո/n^}$ޘ|g?nHOWDV tMr CztUByTȅuHChq*&3]4FdztUB/geL kw7JA虷@hBBJ襙^rg2eкL 67Q A @kz)4#Q 3E 2=:  oqBor_\8c]H`(>wBBJ5n`7"Ya]C Dv@+#УRFDp|m Vv#@`{zt0~ F!PN ,N&zRDI§E Z=: *dFBx! 0󃧿׃=(A`OOص;C!Y[{$BBChBB&&\M~6yO-+AOowK~ɼYUg6q~}xݫwW/.y*/g7/zA.zt x*BpQx! gIq]9+F:UrtoPb.3]'%u^r`U 5fǥƅ^ 8߼g_Yʦs㲒=: ل~f!3XRE(5SΌB;ЗpV#ӛ5 %:81+xBB|,2>= ا2:B_\UrȝrO|zfݭ*DxxrLy$D Yf944n7 LdE'UOE#*i|!:_<M1 r? Hwq!1pLƄ>3w\J۟gW/L1B;.#񠺖z$u#$}?eZ@^˱/\u7h_wU " jH;ov/.m6W\kߕ ˋRHo']̽s\<AH>rդaRdwG9 *6Űtc+w\䔦ʱbo셋c2&66!K AHY1Hm/EgƳmpI"]__IcY4UѾJ^Dk. NZDs# fWLD)ErޙO)8d)nxyW]3?ϳz^qxvV`~-PR'ǽ$egJK:AH3x w~ {D6Pc9{Gg!P)NH^0}D#Bn̰oݧ~ HBOB&M 4< ; uy@xxjS#}Ҩ'ЫqcZUlIn :B)#EYdnI#iasN @VRn|wSkuqHilwڬ^':__/ w@.sߵ>~Ȋ wU1 $;M\z1R*d;ȫv٤I5F6#,zT% $A\~T׃=(@`oz@=k+}O؛_@=+Hk!S@ZrS"sެC_UO0-Yq^SCM+B}(77u֯G ggw*']Tɸ,tx 8fF%)l8S"%Nv{Έ;;wlWB_?qO!p4?w^/t黗֋[6`AkQ'# [57K \$Y#3"=ݽ?I|_ߋ GؗDoTvuSiQ(*s_XHfF;U 8ڻB"x [V;^]#c2ggIJqewdyӥI5oP#oxeWJ땿8ukKdG$1%ƽm]ZE#NfT zrpQwg`^y<+q)_YK|) Ciζ3qOE҂cxOI+riׯ_L큶?9y5TF(zK]:BAKGH+PN(ݪ|_mЋmUo~(ʾtx2U~N0bmgЇT*,$RE-NcBt y=Qu'N~yHp*DiN12>zG/^E)]RƿOq1!,ƎXG$=qT>>&> PJ@܈Y8B?𗪐@G Η)/S8d2IN;1EtdC h_)}ދR.dE=#58lD|+]xe9D28O[& =f:4x3HSv< }&As|qw9{NIf4u\* (]:@R|9A'B_*kj>#| {4B@T/3hF۞ gW/*"*+Uqd# a<.w Gl@6妏^u]lӮvO_Y:m00o4FFb箉HOe|J|unwp]wVε3rKu0B)#`^pSSЉ@g8UMd:ћnb,vuL-b.r(G/r™z`%۟3s#q)kG7hth9 ׼c6 $t+'rGXi։q hl+Iv&*U}L9]k8sK,YcR57&M4iT>=!9=N}8rc /3e籔{'B.?zиO9y85 =BQ /P+&d*RE $Nղ՗o\g l{vR< (]:@&>Xㆤ)M$ך3e1$sbVvǥݏ 6H CoA_i_5~s~!JP׭ Qt4U[ g6uVAm@v?* B`z@ (]:CDFONNh;N BQ ȇ=u6?؀Пxu!UX,h(W94ouSןkm<)s'$Qy&ւ,Zn-s m.M`Ll(B_`Ez᳥ t^O_]{4R Ĩ"~!cTŭ";ْ!2G$p ՉП8B/c>ǟ^4͉O]ZOL'<95*1=i~oUq+9 W*vzڠ%(hdxm8#JMB}ztj]^Z x`/q i( GSHSǫ8yO&<1VY7f^r\F;"Sۻۋ~5z}}9ϟ쓨;/ִ?8[57 T" El.Gw@:kz]@WǬNlO+ #Z.3dԬG 9Wq oZhaJR:ENh$d$vt͎8'mWϋ.IL7'# w|uV_g<ĎW[uc("kNg^0Yߑb#Byɺz's{[wxg~"uKh}{QwKtDm';% q\y&g& N=|/@AثS^w?RĺFGON,=qI4+NuKx X߮?frL RjZLdN0l3,ϤЫ57;wTS{&4Wbǣ 0.v i捪ъ|%-f#$K_= }`=r#xf} f'e"uvΎ&~߹}̶kt#;TZL^Ebr$B'8Fo]snZ]7r 2{/7 6G-Gȵb"igN$!;Lܯ70Wt{dWGjݐ= p8 ;E0tVY,~i<̯cq9aw7*A퉏7uφ[IMBİUqyZ7m{h<9luxړ8^*QB_x Bv-6GD䝈])7MznդXSW:=W/ʍqPJ-cWxg,脢#ֿepB.{ZGmn;.䁸wnBwA_9RBQAL/-*Fm +&K5zgtF4)7nxid^GniףQŖu3pR3<.+{OB#KvkrtOQ9`a8\jƵVtrZIK;C(#X 0$; KO}q?jlAL^AgP%ذp$B#K9@4etV_EMƴ VǠ~JO"ŎG@ ~D!B#K9@:> @;"AjN䵗)lB#K9@ߺwIk3Z>~zg[ݗķ U\pUyKhbՏߞYS}|yԼ]=޼6Δ|ū%Eu$W?qgsC%:nIɜ}QpGF5suNb!r e .(spDR#D)q ム?֊ɾ n{ 3vmO@S~jn'3[U$:w1tp~vcmd@B#KƄ~(CAWxaD^,Z|.!`'f)c }`~{K2.޽^5J%pIt+q XN2h<2]\_B)nJdrg>OyH;1ҜS'vc~'*'֍F4}QpGFSny_ӮnU_& J,E@黚o{9l&Z {e͏{c*Nogl ڱWNr'At"tL2|>h x8Q>ޞ'sL6QA$V B#K>)}mV"и(C By,z5tVGHt֖qX{S,鳲z'KnbVy/)ç@e M⏷J{#1`2(#B/ލB-nYq4'/ |GP MZ9B*kS/H2&aT ;T9%>F=,y&EDNxR0!)5;!=Gc9^+!|&?Nw L(, :n{ihN 4'*]+;> B?:8^=*7izĠ+暻 nNL@goЫVMT7)d&ƭo$=Gv%t=mtOCŴm}QpGvqtYyv섻,h#ץCs-?C  ;TZLV#o;/M xYsj8B56bǣ spUx"K0H)oB#K9@`BIia Z}QpG9@_"Z`,Kߑb #VC/v< eK8B`57.'cOߑbSd "Я&Vw~`bǣK &@z@@wdt@<<nDߙ -,m1}c%Rj1135k&$>0x~8L vˆ; 8(#nz/F%6C_Hb''#VFߑbic37 55m2)7} #'TvPH_ى| ';wD #7~\_/l˖~yGMiR,z ;TZL,N 2ЯxȐ@g#;wD`eEs!p=B@Q,8Bl!@v4K/v< ז/%_ΰǏW7fcn_‪Wq~儩.:"nޗܔSΖ 9#TUߞ#Y{BmȹP)Rj1ݽt_J7g/F(dT)Λ^ܛL2AVO~,O :tjP|W~%?Ͷ?9 ҽtzRYAlIf[#}nIP-iFUe=o3ڞ8yqesWߞDܓTof| 匟1ڵ~+9.S:4/v< @F:uF܅K/)wNO@L97ݿz+[㑼W^ҎS3ł,OG"-{Խ}rzi+xd]OLEcen7GGl'8 igȳ\kG{|09ɏcW<£nOlOqH71>UO~+R.>~Y*]-&PU2ZoiY/ wL1Nަ8:RgP#g5LSHs>+JCsFuGi/4|٤Y"?ޞX~, J#"-ЛzF~wћ"KVbǣeχz_or_\\T>)u!'Yw=RRBԴ_TrjXMܽ:ԯrtTLcDw1bs%gSg}Z[0;LM6os>k~"5B?]S6'.qt,_~GJW d}|kDH NPׄԃ^ pnx^Omu_~ui1ny1XJ"HCt7 qWA=aב&NŶ\=p5Y8W{M]PǎK6?7_쯜!q]4B"uib1</v< FE s7{&^$֮8&|1hW;~*G B#Kt) ͘b~=>$<nܓ S3G;"94H? UU;b24Fx>(- )q5 _B#Kt) ʓ.&@1(# @z@Y*]-&РK$,NoDNB_xjs:_ BzfԂmbN%g)>I80e+wtu&rW# #Ч֡==>)sϠ 3M'+lX{&W7A<[/.IjIt㲨"43\Dg2@%{0|mXNssR@{G7tf&EZ0PG >H~m  o&jΈnGώv!|v1&7;4O^M #B$dZO7-~&MȻP DŽ>U:Y** tdj;oZzž^D?\<]=ɲ>^Jh}\t@WTt=~ⳉWF'Bun]g,B]}ե5*/.(~TGƧ4]-vze~5q3uߔҙdGf˿ s[ZK+z"W((}{mB3h=]gBf8OBHgıRWϭ긧Q\PSd}űZd-D WcaLiȷvJTU)<~&MH{0t|`顑hú/6Fq'5 }Ԣ(#Ez" Ah^/p{yj8&ǧ `1z VV]:7.$4ߔҙ}'3~ ]{]-\$>7r# ެ.B? d^D@ө)Mސ]ʀ|cB'[RR:LjR{OL nɥNM0A3;neuRkwڏdT)gлplH9!}s\31B+t>9z3Лdq{Df5~1DMQlt Fԩ:G?7n Tٴ4ߚNߔҙ$OFIzcwMw4I`V#2jM3PKp R_觶7eoYLfM6S6gYAFdtdVn[q -}:s }0' ǧs`FSnzݮĸ~gK﫩dT)ybUn5Hgjk3 gQ_My(n̍B9/F zjrejߜzѵU{B?RͦT8E!9ݫlqzMy(n BBV7CuCݍ+~&MpB`7 =@B)33؍QT@z@@g2@ ǡ(vCoD^ã$ Uծ9g%ݡ F = F 3 l(V+>.j VG觡[g!7z"jđ~AMy( !zgkY=B@QLH5"0uQ><#=63dyy V P:3f ^NL} Vf託 #Dݭj^ު1y@z@@g2@ z> +1y"[Of1#utF=o5H r%7"K@Wv"dNAUMy(qMgg*{C]/g4CJ=B@`e j6E`F!pbЯ_ޣ0 j޸E5^K);N`B SIˋss'Dy={n~i~q.>Rwyq= 3 ltfDyRl GʞF[ U\JܮyqvZRJCI"8am@7tf&!Gt|̐o" }<&.ݍYvT-| bE9Oc- }3 'I,R"֎BnL6AfSҲ+H~" 9OMD]g& {DnPw_Y5x5}$"u6]:ֱq#6$͛?C 2F$oY/ t~(i|y+W}0a=wC~x[ 3 lF#k&ғZ5%J\>-O, )9!%FmiɖWKWD F~DZǛӤ~!%oCLd,CoRkyyk4>McGOI7~x>U?ro]6ۿaԻ)6N zB=!)^ʰI8hjsMOsr{>j噇 t{ZF:+<ޕ=Sk:{?'ķ j6E`Lkݸ+xo%'WlU,v3v,|~+=) h|{$B里{j,W?텖9byoƐCZ} ~&MXzO )@k%pzZkWh7 0 Q#O u@8Tdw֯^@WfC;!@RsYpg$З % KPg ّr+ʋ'Q,@?Z4 B GNs.M!@m[@<<~eP/O0CSAc.!@QQpҦt˝)4ercOְ\ly;Vsrc{! UCyJ/m6&IENDB`plsense-0.3.4/image/demo2.png000066400000000000000000000556441260377356000160140ustar00rootroot00000000000000PNG  IHDR[W4sRGBgAMA a cHRMz&u0`:pQ<["IDATx^O-[zwAqāғ F`gFɱ9 Nzm ։n&;H;xb%{: yh kZVv޵ksY{Zjկ'>C?џ?/|O>7s?p-W_p;7_>~OBww`J>~WB>?ɟn_g/Ntჯʨ܏|t_=|woW/7{8;gϿ + @@@'o????J5|k}OڏLy>|J~;dU}҇7e^N~uoǗ߳~ޯ ƣ'{|{/a~߂ @WC0K|;k>?77TG㯽*7+mY|߾:+_[s$%_jU.|ڈzfQ@ 0\Aj|~ݏ}C4W+w?(8wNvƛ_`0b*oJqU! @ Q|'{jT~V'`.* @3ŷ^L7[ R{ލ(wC @8?Ŵ @3 3@ #^ޘb@   @@|/oh1 @  h| @ 7f @`w4@ py3Z @ 0;_ @<- @A@ \ƌC  ΀W @.{ycF!@f@|g@+ @G1 @3 3 @w;cAK.{G!@j W3ttMt >xϾe6w;?SW?n_=?;[k\/tlPCk/\g>űkF ^I#+]V|M|Gm|xZ[Et [e=9eK$~GoZ~!jwv_wrX#pP "5U#;_9Zew]팼yK1YO$Nķr~̩ @@E|M,T>`'c*wcGҏ\LKL4%h:ZDˡ5Q&ɬ-1l.Ny-D>TG T(t_ᣙZ \!Zצ~r|Ej,Y엿!a72ZQL_Q;zu;q]{,_|?/J?>v}˿g9_W6Y:|_cXZ4,aػWr#KCnINU{ ?a3W.4ⱭK$8dUO_p#sD+\2 m&ۡSmAjMBhbáp'678īNd>$Q~;y;n=#Np/gH|{_|׿]'F[mүBˍۖ!C]iud[;,DjFHC=SlfG;YWnC#^@5#+[*3|{ ݂ I6ܖ QRoI|xc yD؊lQtcl+Ϭ\舃zk_vS/ J;V\%=qo.t0I#BE鷋BA|#ӦwoFWM+|'oS]sn@7>i 2+!6Lo ^vS*K QX7v撚>yNM׬_R78_L?3=]~Qh ͫp;#X&iJWnԆN+ $e @ cxB5[ӭ>L|Fߵ-\x>h}6V{ZHIk*XWI*F۶-m72|[4[#ZR}B)D|ft'Q\;teZBŒ@vH`qf !Iν #n$$h?%w4;"IķO*Ǎ3_`Qn[xH%:h.GE OH¨:Xv|F8S2.Ztx(@X@sr\#j®"v-<zyf .Hl(.Bmyj pR(_Ku^Ew|;"j螻e6kՐ;@ḁw2 p,(~O@NL`z5( @ L ,A@ (ሯ!P$pA P J`R @ J`9ճ'l!μ=ܖ=<}8n|{?<{EGv0t$J-A|(3ţó8;>޽qF12_lwjؗ~|-Ӊ3C|K=NE'6p;Df ?vb%Y;IZ*QgߣVP"mJP6':U5OiGXMv}l:shY$9~b&fĹ$%!"W 7QHoMQhEqq9!! 4S~:{[W\ȲG@!ӔƷmmE|>A_ķuPXRK_%0C,yI'cƖud/j{Ղ<8\Vx6vKkMw}øf\#ɮOIgK2x32na䡐,KR|:=?QKAS>}/ lRK_%0C@ߠJ!^ Cxų'}^h2ǚ&K-|*[-7moW4.o5+~<59ooEas!wr%iD|UYbx66L>N%Z2Ec FJ-A|(J? o*@CrS#7}W2PZ_ЖUκ͕W9 ci}:&b;w [2)_sYuLĆ % J`J|[mF^y{ mx:,5|/VtWMa'R;߱tw""El4Wn4 D<` Q|]зJE1E1@Z*Q*-%' !!+6 ~X#&"&]Fab1<̡M1TɈor']9nj(G|=3#v2D36cDItTB (U8tko6F>J[؍5!~T(tIh㛧R/d>O6Jz@; W @|wP@ J`⻏^@(U8,tA@%!c J-A|(w %] }Pj Fq X+ 쀀RK_%0CBI @`Z*Q>Jz@; W @|wP@ J`⻏^@(U8,tA@%!c J-A|(w %] }Pj Fq\޿z՛'[%ndT|8/6&LӹMM@%! OQ|q|s_ͶX:ϐj .RljU:]xR N?~Zmhӹe8?J=?O g2韦W9Z_'|ݶ(` J`@FdA%Tb~vйTψ͢3/ .d?f/& QnB􍸵*uNӦ6f;Ĺ* CngR|_\XUͷ~^>}e_8 J`Z^NiU|CdW,o؜D&mQ_!-g.șkgPy5kkl(d;LEFKR|K;OMaRQZ;+Kkη0y"(17E:K@%!0}s[c 36Ӌ8v;);^h_.C`ߴ!MOZ/..D01V|F7i[q:Hw&XDbCzJ-A|(orKoŷpķ_ꐧ&rgg:đQ_om}l^N(#$Z|y}o:ps۞) F@%!0tEqi&$QC{io>6~{CjO0 o)m`:YV A?mDηG3C|& {"W ֟!k>_rH\N_smg(+L "SbEP| qu)=hK !h%sfCnulԳxm?5$ P&W h_w|ůpw룧:bVJw|a~C<59*|y-,vM.oKWy/h*B=;^1k)PyE_T8RK_%0C,3/r} h (U8_Dy@JZ*QJBZ*QvU< @`%J-A|(wŋj!@ZJ-A|(W*Q  J`E - J`](@XRK_%0C]iZ@RK_%0CծJ D@%!xQ- @@K@%!jW%CV"W @|WZ %W @|!@+Pj Fq +-^T @Pj Fq U (U8ߕ/ h (U8_Dy@JZ*QJBZ*QvU< @`%J-A|(wŋj!@ZJ-A|(W*Q  J`E - J`]o_>9؟ۗU577O^y>]~P? ,K@%!p{3^}FU߽[V=}0ݫ.~Q|^xݼ]v!6@8  J`o~zLs15y5T;~o׈p2`%=!@XRK_%0Cט&>ߴ-6݇{'Kŷԅ|u}86bfW4ݯɎS4Z*Q/U~o>ypUM&#WmkE|DS9.߬(Cךo - J`̅Z]B?uBoZR,F|۴BSz3lX pJ-A|(8$#\6!<]ŷ\mHu`jZaܝU7E|MXlXw~Pj Fq\`7e+1)T2GM!睅4x+ئjg_rIKu yZ*Q-c*{YWT(! 1#D|x sPj Fq\tFLS|V"ca7?caQ,8䫻x ۅRK_%0C!=c@c1<?u!-ݜWKupL$۟fTܶrUo:  W  EJ @W@@%!8#+ 5(U85V.  W @|g,L|  J`E Z*Q@ W ؂=<6)b5(nż ^zDd@RK_%0Ck_p8L>LT'&O^՟<6aۃj~ߛ4H@jJ-A|(3a:g6&oG3s5,mƼ/ ( (U8&׿D7{rg/7U+HkԼ8-M9FpK>}ԉ{\S$[R; 앀RK_%0C,V_t6~B44"i^ُR(]y YnAp1 'h1mv @&W 7_%5M "޽0WH9`N{ r/@(_%0C5A\_4`N'FvooI=ASM̠(~9ܼ5s'tdqo:ִ;+/ \5 J`J|G,!^y0g'LL6^EXRǨo1b#S: \ J`J|U}f%8]nEj[f-EgGS5rQ;}UG5 @cJ-A|(ڼ8 = yKrYf!Э?lFK/(}_}`@vJ-A|(vKRMo~w/+A-r{]۟GyZz? mXCDg;̸nATo1KxP 쓀OW (G|[n^wԈ<Ҭ{żv/7nq!r\+N6l"W 8.R Pj Fq ;X( 샀RK_%0CZI/ @`Z*QJ@ W @|V @ J`⻃.@>(U8}v@@%!`  J-A|(wk% Pj Fq ;X( 샀RK_%0CZI/ @`Z*QJ@ W @|V @ J`⻃.@>(U8}v@@%!`  J-A|(wk% Pj Fq ;X( 샀RK_%0CZI/ @`Z*QJ@ W @|V @ J`{ޅGyۣûۗo]@eɫ7k}ssFvܼWϦzXO'ݎsw8 XNA%!p> {xbni=A|FtJFFӨ%-H!K uL~?Ks<.Z_1>_ԯZDm7K|kelWWvYԦW 8QI}p#sߘYUtpf8+8C`Χ$xdr-6.so(0-UG5,a-.U&̺u'I5&kW 8&'.oG/GZuAQ?_< t(\bs!3g .N9&f7>ſOS[YW3uKķu>]᨞5%V])wD=BE:0KןlL\]O+ul}w*U8"ccTwyv0$Eg'|rB=W.k+2F8.(ěkߤqH>Ϥ)sHB g .8\&noo3W!~*UenK!)4ϳ gc,3^Ͼ\4C#S4O\2LFd@v^֓8DnXet+U8&~ ;Azi> $f "zd7/V^Pşk=(~I9$XQ.așuaR_;[,T|3L C&qKC1'S_rwp={w2`}>v/ O]aȍ>(SI!+;Wi]DngyGqfx+U8"ut!IuYvݴ 6VevuӞV|E'*BVNs;bj),şZ|1kΔ\GNe 4?k)t5ٽ飿H}>TjB8:o?F|k&d) KΔ,](/qk<|\?|UaxbŔZ*QgߩT<7}KYkgaAt-T^rm<8y5S)  ,$\|n낾7ib*<>K"7"_cc6W._z`0eu~:кKX|+ߢn_&pXʽS)UzfpڍWj FqE|ԅx)pgӗrY)WGpmS5lfF|e_O">5zo}lC- PjF%n݈@wG"[t1~_iķR^8#mw綶;o)U8#{gO)q}|PL#$!~J9":X]Y|I|sRr\p+qi},ʧe[5'H/G|9SF|d[ =6l"76=..<6yE~$v//jWXD˫ַʉ?ɪeGy(VU]/^COJ-A|(sDo8U80;IuH qz7tHQ!2;^`_nyX:7SRUO5U^{0羧q<աͦ= ,R<6\ \{rt%q+t[ $7EE=Ox)s~ W|o[N,'ַ7i>Q\"[]YCX!A|(3Ϥ"F@6%$A@ (U8+_dY ,lV__B APj Fq g* Drpg_׍%j 0I@%!N.C RK_%0C=ZV @Z*Q2D@i(U8.Z|ÛZtYG96zl$%2=?WU~n('rn;kb)?󛻔q_,37.pWj Fq Z^翱l?ڭeտ8zxbٹJ\v-y*rϝ|hgobKP9~85(U8.Z|bԂev(!51.krBr_M]Nfx[v[_|mZkY~fDGLI"ywrs-W 8/}][ta-hgTGU{,r(Q7)>k?/Ls- eF|QUǥΆ}_e=-ܾBl†^LYeL5O(_M:#S%Qj FqG|mͭMpQj^*: z//z k- 1zk g`vξ쭪U4>|IRVީcyCםۗ7Ɲ_XKR8jWoSSZ5KqPߴ,={i}8/.c!VvKRK_%0C|p IAXRndvDAR!,6\/I#vGZ|z2l>᱀8x /^|6A_钷 (pb#!]!Ӷ_=ʺ8e*8 \ܸTķ0y.GvpUqIg5aoWpgyv@6W7wvLlX%!)Mo7蕷s8Z8'?eT.cS,J;ILA|,8ROFÝf2i^*(oϓao^]5»qĢ<lN{#i4>!IJ4qokp4sj83c qŷZvbSO#Ydr/Z J`^j/ePX+~X%-R| oq}n&FV_>!vc tw7{IGwLm6܂7i#@ns]Frhg* $7wxsh߸/1D=[ L2 |yR;@kq-K~P~R\b=|.͇0 y)ybE;OU,hK!;H5>)׵wi}^>(TMQ"J`"fMI /L6/U-\.]NPzZb{U|zRA<}Nu{6Tp?= ś1!/J_S'cҘ(4<.i\J:?y^܏e8ߵʛi>gsQjj'IJqN I.<\_ߤu`Y[7S^%!p=#JuEk`[ y86??5brChY)Vlro~i )U8+ضCΙ#1R.o,9qSP莘~svOZO& 16?ӤV J`k85a-4.4E:׸,C]_JZ*Q;_Bp k%W @|^@F(U8ߍ,v4 W ߳ޑ=Z/A%Y߰m jkѽl΋G1lZ*Q_՚z[ڳ ی{ gg+kb`F)Kp14| (U8KӸ w\{\jomK|.|:  RK_%0C`'{6 {Eֽ?ywņƌ[+{U}޸`4!h/Πt1..dz .מy+2Ƨ|P= >.xZJ-A|(ox-ֽ=Sx{g{;/V517ue=/onDV[Zm=bFo[E_P8ziqB[|힕"D3Q$8:vݔ/"/J-A|(]KsDϫ7IrfEO_~ͮT~\3HvhO86v{o7ݻ_ JdG*)n!E|KKkerf3ݞhtoJ-A|(MovT"=.UO}N@WEr$o4eF6 }jMNw)(?:3q_?_Z~\g=/8etY_Gi0F6.e(j{WܡJ&*|w<r3w#ߋT}GpSj FqW|G|5G'_wה%n{1~./fcJ[ZC>ntswq"'f2߅qo4F8Sn;_jP^_a2굺˩=bŤ*eA {;BE냜;GP7ύǨ2^žXw5 J`b.պn3pNnVa=!'{tqt+VԂ& ]_w ׫!D-q]mmt{K؞ǥ|ϟi18!hz3y 0)g,?gngw4'{9[_4صi{*W 8e̲9z }E.`\ MVδ%iuͱ=`Wj Fq 3cFQR3j;W2 pq9ofb'$W @|Azi?HxNU믧Wbnsqxٲ|^.b=2Ļ6+U8_\@F(U8ߍ,v4 W @|Yg!@!W @|7 @RK_%0Ce lRK_%0CbG3 @J-A|(ėu J-A|(w#̀ (U8_Y@F(U8ߍ,v4 W @|Yg!@!W @|7 @RK_%0Ce lRK_%0CbG3 @J-A|(ėu J-A|(w#̀ (U8_Y@F(U8ߍ,v4 W @|Yg!@!W @|7 @RK_%0Cx=?ɫ7[W^m.ypxz<{}yLl-ֶeQʭr:d1w!Zg.crb J-A|(oP=y(Vûw%X(b-nW T{cdgح,z!vj`wLKjvG[mJ|`~zsl6it颐?PJ \n7Z*Q_{ lD?>7Y`~\P-$[O`'Ҹw(~xYlOuU⛛P]89 ﴘ}y7 ͎;nԅa}x툅)H8~3"r;I2T;ݞ34 ǡ1'nW/}.qk+~ @ʈ(sKO~^n&d˕Z*Q-\=ʎᦨC#r$iTmee6}=_>Ȼܮl?o%xsCyXWWDS|q[s2 y%3ߍQW?va+6ۺ3w RK_%0C`G.#Fנ]h(}LX0jk<1*=%ǧZJ9.O:D;p")E|ºepn nd#nJ|J9 W6zfF|uMҰm J`Eo[F /0BZξj=>;iO(mp4a+Cے`c1F=qw[E&s+M#ue _/B?JGBQp7Y0䈏UٷS|E/y?e~4+{il u6+U8#҃ՂrCB}}%VA [Qy:1\ݯpu~'ƻmמpĭ3t ⸧<'5/ݺ1tc{¼7}D*MӦCքy_y~s3~ZE?ʹo)-;ܼXnyC']7?u?%p2'QZ*Q ɵ:~  6'Q{&o;N6[9<'kj W @|qN]=m{4VQt+nc\.yQ9~sD1IF%!Ξ2;>qC BszXFS%!^*I!@`7Z*QnK:@N@%!^*I!@`7Z*Q_iem{n8[J-A|(so};scؓP ]MKsI=LpVPU 4"G<nvC@%!p.5/Z⛖|/M$r>&q_n'1V.⻛C>Z*QgA_|ZmR->}_uƥ&l\YyǼ/ˊF>;| fJ-A|(oy>W>ض$\8pYKoyM+kKJߧScW`7ƛb&`i۟k='hȲ+q !J-A|(=b$̜H\5QfҖRJW~I|>boTfR;_N~|8nIw_*B5!F@%! ՟P,†`+Rw&c"F}xKVIu:rʈo>^l#amhcX|7Q t| jǭkJK!# (U8T|{ ^N(CDGFؿV|߸I銼D7zF{]zoj-e%$_ <,$Y?$?eB!I@%!p ;2&w_̈}}EQyoHVȕX,,1ƒ"!qDiD5Eq`]q'RtdCZ*Q!if3; 85Q3”<.-k|3\M_-z|(#Sl6:.)9@Q|9GhSz]k.B`Wy!(U8% "$\H)CuNPx{"`S 婮ay( "==XB|ҬGXzpSzCxJӇ4Ŀ2jy5dQ6\ J`ո,|j? 1J-A|(j-⻱C润p = J`+'ji-@ (U8_D J-A|(w#̀ (U8_Y@F(U8ߍ,v4 W @|Yg!@!W @|7 @RK_%0Ce lRK_%0CbG3 @J-A|(ėu J-A|(w#̀ (U8_Y@F(U8ߍ,v4 W @|Yg!@!W @|7 @RK_%0Ce lRK_%0CbG3 @J-A|(ėu J-A|(w#̀ (U8_Y@F(U8ߍ,v4 W @|[g>>_%Z݋l?㻕q<9ûFwQ7߾|4ݻKi۩W ا޿z,ȓʳҁmbdD!yri{%ړR.?gV w<9Z|7%y[m/Sj FqW|a35oWQ0!=l/q۶lw|W;$ϝ +̶qк]yllQj Fq\~:>.޿-8>{s_591R2Z^* Q;pDb"ja#ȏ3D˧q1ÔGº޷:NW :MG*|I᳛9t_K,|]0|.ֿ겛ozL*p ܾ#_lx?Ŀ_Η}d#nqs#qβASaۘԯۺfgf7מ'rv~]_2<e7]`yr?{~]oނ6 @%!pkNy>Jw3&k<ăqm~bT7#eLg_pRCĿn1q%TcC/?OQ9"[=w-v:n ;Na'bfa4O6y]֧t'"ʺT܏FY}vJ-A|(otTBL9:O{a8G_Ls8@r,7ܘyu7RxtW үbT;K5iP0OejQ{34ßNj[Maݫn+=|.J-A|(o!nG=@?v,*>`)}.׿%#\8K/!^ܬp.Qn'Pq͎ KZylHd_{0 ŞAe?[c{}WVd')HXZCZ*QW%JX,o:G/.cEq>/G| = Qڃ$䤦7~%7O^KMy"܇ 9 54Ҹ׮$W</}E1UgM4)it<:扼H돻3+o9#>s[#[Z_W 2 .9G66RB{ؘC@]`?`N|9pWGSDEβ~ǎoiIpey=O$e/Ǘ/NEY|5>!Xz]S_wp~ۏ"x.uGezv@)mCiISAXamkV:_%0C`_lW<}xXڋmɌ\%!l9cC@<{z*U8 @e@|/sh5 @Fq@ $^j@ %W  @Iq @J!@.{F!@_%0C \&2ǍVC ( J` @Le @P@|(@ p7Z @ $*Q @2 9n @@IU8 @e8O~ @ p{~ @ wGA Xo}|+Ͽ˿8Sc'oT/~]y<9n.Uϼ^ fzL_{x.z@](_j+me>"f?*9:Cqo?^葜뼄# H)kɢ|dӰ+/ %nb9О٦R|oVQCfoy|_YݱS|T=?_#[Gv3z'0Sh2Z14͇k ѧ2㣰H뉋O߶8)4d2u+;I̡kLbַ|.C8)|F}3ķPnL;WPS9ʟRe5tevI>}>FNa>XZ|ܛ׬f?^4zli_߫9:%b '?-=" -6 rkk>.{9oR6D^|6i;/]ڷd8 3}A~ :XOzi=0UOѷƢ͉vS\;9ܔ}E]8J|]n2kJw8}evgߴKGI(FI GAJz5ߴA_ϲAj)H/APNie[!ҼJr?,ktWv>QD<z /xӿH2:7TOcy[OBA DN|]XHؓ>QjlmTCo9L0NJdqA.QlUT[h4Oĝv!{hZ5zCUkVQDvoQD8!߯1Ԯ0)- |`>ᘈ boY|-72](L};ҟ8 Ą!F|>vy|KDLs2u>W_ݹF`"7qɨΓ"xN6w_ '4$f]Ǩz_qŤj@WKXUşVN74wuRw!Uj1V5磰)खķ=1l-q'z&ZߡF}~ӆW?& (/MXpH-=#1Nu^r=<& Z2|̊D!=iD حg>:LwZ[hG {//D.0w Dw涴8 ]d@GX@|ݽ IGQ)ka++-kN%[>7*Ɨң|w ג6j$VV5IrXCN/dN ,[k6Me4pZ |҉+F|Wa%#}AE@l_^9▗gU{=8td\ܡ~ KO-(A8|"<@ @|w4t @@&2; @{L'!@_ @U@|b$ @ @ U 3 @@| @WAa @/s @* W1t @e@ \*NB  @ ^0I@ Wڈ)GIENDB`plsense-0.3.4/image/demo3.png000066400000000000000000000162271260377356000160070ustar00rootroot00000000000000PNG  IHDRo֛sRGBgAMA a cHRMz&u0`:pQ<IDATx^MfWZR,ąt( Qf10`,E..% i]I108n[BA UL*T0m7|{K3ֽ<9>E槞84}?Oi_ńп'?~_o5R<4_ Y`99~_~ZU^i~Nϟmwq3_ha;ͳ_loi[34OG.[?hm.7͝m_h^xV?18|LCK@(ŭ۟f88;Ώ σ7Ofwn|\{ރ<~Kz'2U}9=ڋi(r|8e/iݿݺ5;cog_2Ӄuc=3n -f"}rgi9'7O޼ԪRE2sϬjHz;p^ cUG[2 !Dx}@yXJHi,׭)c:.4S㪦9Ku@LS$mdg^:gŊDw!h:SnPdYd6SA02JU]"q"gd-,#.ZLhtgx(@X"l1nj޵p2Lb8 o @LQ$"DTs] @`NA,vN&[GLFGE@X52E> @IEʨ @EEYEo!@IEʨ @EEYEo!@IEʨ @EEYEo!@IEʨ @EEYEo!@IEʨ @EEYEo!@IEʨ @EEYEo!@IEʨ @EEYEo!@IEʨ @EEYEo!@IEʨgM83a@C@4 P$1H <CÛ'NwN^f.|yݳyID=- RNWzNxCw ).ŕ)Cz:FR"E؉Qr ^mEr~vkE'!EN@S:si)6I$dǧb$ ,Zp$Qtљ2ben:eL%JY@ dc$*wSy$wElLzaH ѓ/WdSG{IW+iucĕ@#NR9B~7n퍿t\I +v}`FA|0ڿ$57@GrD3sx|K`"yvp1ۿ"w^deiɘ*$x0NmH6b@Y&c'N'^ dp#k0\Dn=HxN31ъDX1at! =4VHZxg8H;NID~JX bD Ah}hme[tX1SEGUgfHxI"v4o&}:Mc]Gj BC HNL(1jTdW(tߎ0D>~׭۬Q.) < W}Jv]Ǥ~¶5N1oU7bc*W$''nZ x" ;7k6jѸ BVs?  XIQHDL5'd"wgt[S3pOy&52X5rߧǾQ$cnJGZn"dn0SķI gߊIkzq8Xk86v"E}=f&c$H_ouD+dM۵YPok:ii\bUiht8RHHswmSLCR$>Orz `RVdp|m"薀ȆavuBE0uw<2t#˘ڀ HQ P$Ցb b(bdT @:Iu @ @NER)!@(&")FF@@TGA@ HQ P$Ցb b(bdT @:Iu @ @NER)!@(&")FF@@TGA@ HQ P$Ցb b(bdT @:Iu @ @NER)!@(&")FF@@TGA@ HQ P$Ցb b(bdT @:Iu @ @NER)!@(&")FF@@TGA@ HQ P$Ցb b @&м d3@ *]iϕko-Nk_/}Q s"o7EUdE[δQ,%Vb&PHu{].e_^}j`(Ó!\yf.!DN_H:IyK"OTϩSv'`/%7&ZΧ۲l"5U[(!X(U$=W%_vʵkR47p7gzݜH]`?[}q2Hk*Th5a`2M??nwb;n=JS*d2\% ЇRĩրEyZxu0F/Z4v'(c.:3Q0s!yV)T:FV.t#2H҅ep<F/zq =^ f)HQ !Etd 0\ScY4\(];!9ܐ[t0"q/ʖg( OЕ"Ez<ݺX&ߜ7Mu)aiNCDEvw~M\vKtVuO!y<Nߌ=ݞj9R#ȿD{S5>u E7W6z-` {THX>^N8wŮQcEH|'HˡS3Z#.IbNڿT/7}58?ca k`RK*sp3OkǁT|9H|bǧ+kq\8X K+cDf8.W$]e×J#J2]BJߏLNPPv~S5BkgH~iBEFڟ`m~KyG)m$yw0"Yf\&[ɝwOO57"1{L]}r^ŊD;+G8}Ipo .c#{%!&qb11(PGm"Ȼ;6zݣ=w~ Ock,?K$xwmKq^G.o+V:B!I8.S[ͳ3+J髎x̩H)R1}rS;1C$c[8=Oג;)=1# 'IU3X8xI)}.N,>I15A Bl'ݗ6]gnzzPCrLOŐ"^(V$ojPvٲ9Qv)5&0"YWrњe=keUUvGXrd" B`6k7(:Ϗi\"qaX";mlfϒp{qI1gMi/>N '\>3> @`P$KMS dHX @FY&zy>4 qWc+z4/R0qzĎ6\J^:^O \l=ID镽pNfIO'>:=~ZdHEi][Xo 8S[ǛɄrMLKsu%\Z-L>E@` db$Ec^"Q>.c72@1<:MR$j,LPeb$fN3(d$Mwv?.b Y")Oi@`iӯHf8~QS{VgtlL<8Y,=̄v#rDs|m,zfR꧴|Ϫ3jy.;^.lw HHaQr`:ZGDޗ |ή7wO(KbTN 9H|>V掇ijd~qη3 @X6G^(I5>!K3U$qdžŊD +YX6pL1UŠN81=nqֆ<9~u×.50ԍ]D = :4{ͰKUg:fj0̤PC,brL*`$I$唳M:!iQ>QN$U6CeQd#< Nq3^Z||Ub$%!b$9E"eI*O(_*0Jt)?1HLxC};T|v9Z"Kڧy8 ̀}.+H:/ D"`ZyW ;mW8$I?C7d^|ހsdrOALLkxl1j1N 'v.߽f\HrL 8Q$% S+L&)J0H ^Q=:Hܫ{F(}J" W(j6BꪶGJX'Y? +-5,@dh5>u"b7 $t3BEd}pG)z9QU%) omMᄉN ?;"b9XE#wb$JXϮiڎsybJ&҉1D=2JW"UcH&{h(uR_t*5qC/wUgfzc$:y6wd⼓#]B ,ԮMSco0,iKfq죓ad(F_ޙD̸wmzS߆;bw C$^HO U؎MWڞ_Hk=eh OX>k… XۡHڇ5Ek} ,(IP$Q  P@$@ j@ UoqIENDB`plsense-0.3.4/lib/000077500000000000000000000000001260377356000137465ustar00rootroot00000000000000plsense-0.3.4/lib/PlSense.pm000066400000000000000000000015141260377356000156560ustar00rootroot00000000000000package PlSense; use 5.006; our $VERSION = '0.3.4'; =head1 NAME PlSense - Omni Completion Tool for Perl =head1 SYNOPSIS % plsense --help =head1 DESCRIPTION PlSense is a development tool for Perl. PlSense provides Completion/Help about Module/Function/Variable optimized for context. For more information, see L =head1 AUTHOR Hiroaki Otsu, C<< >> =head1 LICENSE AND COPYRIGHT Copyright 2013 Hiroaki Otsu. This program is free software; you can redistribute it and/or modify it under the terms of either: the GNU General Public License as published by the Free Software Foundation; or the Artistic License. See http://dev.perl.org/licenses/ for more information. =head1 SEE ALSO L =cut plsense-0.3.4/lib/PlSense/000077500000000000000000000000001260377356000153175ustar00rootroot00000000000000plsense-0.3.4/lib/PlSense/AddressFinder.pm000066400000000000000000000600511260377356000203740ustar00rootroot00000000000000package PlSense::AddressFinder; use strict; use warnings; use Class::Std; use PPI::Lexer; use Module::Pluggable instantiate => 'new', search_path => [ 'PlSense::Plugin::AddressFinder::Builtin', 'PlSense::Plugin::AddressFinder::Ext' ]; use PlSense::Logger; use PlSense::Util; use PlSense::Entity::Null; use PlSense::Entity::Scalar; use PlSense::Entity::Array; use PlSense::Entity::Hash; use PlSense::Entity::Reference; { my %bpluginh_of :ATTR(); my %epluginh_of :ATTR(); my %lexer_of :ATTR(); my %with_build_is :ATTR( :init_arg ); sub with_build { my ($self) = @_; return $with_build_is{ident $self} ? 1 : 0; } my %methodindex_of :ATTR( :default(0) ); sub get_methodindex { my ($self) = @_; return $methodindex_of{ident $self}; } sub forward_methodindex { my ($self) = @_; $methodindex_of{ident $self}++; } my %currentmodule_of :ATTR( :default(undef) ); sub set_currentmodule { my ($self, $currentmodule) = @_; if ( ! $currentmodule || ! $currentmodule->isa("PlSense::Symbol::Module") ) { logger->error("Not PlSense::Symbol::Module"); return; } $currentmodule_of{ident $self} = $currentmodule; $self->init_currentmethod; } sub get_currentmodule { my ($self) = @_; return $currentmodule_of{ident $self}; } my %currentmethod_of :ATTR( :default(undef) ); sub set_currentmethod { my ($self, $currentmethod) = @_; if ( ! $currentmethod || ! $currentmethod->isa("PlSense::Symbol::Method") ) { logger->error("Not PlSense::Symbol::Method"); return; } $currentmethod_of{ident $self} = $currentmethod; $methodindex_of{ident $self} = 0; } sub get_currentmethod { my ($self) = @_; return $currentmethod_of{ident $self}; } sub init_currentmethod { my ($self) = @_; undef $currentmethod_of{ident $self}; } sub BUILD { my ($class, $ident, $arg_ref) = @_; $bpluginh_of{$ident} = {}; $epluginh_of{$ident} = {}; $lexer_of{$ident} = PPI::Lexer->new(); } sub START { my ($class, $ident, $arg_ref) = @_; my @plugins = $class->plugins({ mediator => $class, with_build => $class->with_build }); PLUGIN: foreach my $p ( grep { $_->isa("PlSense::Plugin::AddressFinder::Builtin") } @plugins ) { $bpluginh_of{$ident}->{$p->get_builtin_name} = $p; } PLUGIN: foreach my $p ( grep { $_->isa("PlSense::Plugin::AddressFinder::Ext") } @plugins ) { $epluginh_of{$ident}->{$p->get_method_name} = $p; } } sub find_address { my ($self, @tokens) = @_; @tokens = $self->get_valid_tokens(@tokens); return $self->find_address_in_cast(@tokens) || $self->find_address_in_symbol(@tokens) || $self->find_address_in_magic(@tokens) || $self->find_something_in_word(1, @tokens); } sub find_address_or_entity { my ($self, @tokens) = @_; @tokens = $self->get_valid_tokens(@tokens); return $self->find_in_binomial_operator(0, @tokens) || $self->find_in_ternary_operator(0, @tokens) || $self->find_entity_in_literal(@tokens) || $self->find_array_in_list(@tokens) || $self->find_something_in_word(0, @tokens) || $self->find_entity_in_cast(@tokens) || $self->find_address(@tokens); } sub find_addresses { my ($self, @tokens) = @_; my @ret; @tokens = $self->get_valid_tokens(@tokens); @ret = $self->find_somethings_in_list(1, @tokens); if ( $#ret >= 0 ) { return @ret; } my $ret = $self->find_address(@tokens); if ( $ret ) { return ($ret); } return (); } sub find_addresses_or_entities { my ($self, @tokens) = @_; my @ret; @tokens = $self->get_valid_tokens(@tokens); @ret = $self->find_in_binomial_operator(1, @tokens); if ( $#ret >= 0 ) { return @ret; } @ret = $self->find_in_ternary_operator(1, @tokens); if ( $#ret >= 0 ) { return @ret; } @ret = $self->find_somethings_in_list(0, @tokens); if ( $#ret >= 0 ) { return @ret; } my $ret = $self->find_address_or_entity(@tokens); if ( $ret ) { return ($ret); } return (); } sub get_valid_tokens : PRIVATE { my ($self, @tokens) = @_; my @ret = (); ELEMENT: foreach my $e ( @tokens ) { if ( $e->isa("PPI::Token::Structure") && $e->content eq ";" ) { last ELEMENT; } if ( $e->isa("PPI::Token::Operator") && $e->content eq "and" ) { last ELEMENT; } if ( $e->isa("PPI::Token::Operator") && $e->content eq "or" ) { last ELEMENT; } push @ret, $e; } return @ret; } sub find_in_binomial_operator : PRIVATE { my ($self, $is_list, @tokens) = @_; my $lastidx = 0; TOKEN: for my $i ( 0..$#tokens ) { my $e = $tokens[$i]; if ( ! $e->isa("PPI::Token::Operator") ) { next TOKEN; } if ( $e->content eq "&&" ) { $lastidx = $i + 1; } elsif ( $e->content eq "||" ) { logger->info("Found binomial operator : ".join(" ", @tokens[$lastidx..($i-1)])); if ( $i > $lastidx ) { if ( $is_list ) { return $self->find_addresses_or_entities(@tokens[$lastidx..($i-1)]); } else { return $self->find_address_or_entity(@tokens[$lastidx..($i-1)]); } } } } if ( $lastidx > 0 && $lastidx < $#tokens ) { logger->info("Found binomial operator : ".join(" ", @tokens[$lastidx..$#tokens])); if ( $is_list ) { return $self->find_addresses_or_entities(@tokens[$lastidx..$#tokens]); } else { return $self->find_address_or_entity(@tokens[$lastidx..$#tokens]); } } return; } sub find_in_ternary_operator : PRIVATE { my ($self, $is_list, @tokens) = @_; my $lastidx = 0; ELEMENT: for my $i ( 0..$#tokens ) { my $e = $tokens[$i]; if ( $e->isa("PPI::Token::Operator") && $e->content eq "?" ) { $lastidx = $i + 1; } elsif ( $lastidx > 0 && $i > $lastidx && $e->isa("PPI::Token::Operator") && $e->content eq ":" ) { logger->info("Found ternary operator : ".join(" ", @tokens[$lastidx..($i-1)])); if ( $is_list ) { return $self->find_addresses_or_entities(@tokens[$lastidx..($i-1)]); } else { return $self->find_address_or_entity(@tokens[$lastidx..($i-1)]); } } elsif ( $lastidx > 0 && $i >= $lastidx && $e->isa("PPI::Token::Label") ) { my $currvalue = "".$e->content.""; $currvalue =~ s{ \s* : \z }{}xms; logger->info("Found ternary operator : ".join(" ", @tokens[$lastidx..($i-1)])." $currvalue"); my $doc = $lexer_of{ident $self}->lex_source( $currvalue ); if ( ! $doc ) { return; } my $tok = $doc->last_token; my @currtokens = $i > $lastidx ? @tokens[$lastidx..($i-1)] : (); push @currtokens, $tok; if ( $is_list ) { return $self->find_addresses_or_entities(@currtokens); } else { return $self->find_address_or_entity(@currtokens); } } } return; } sub find_array_in_list : PRIVATE { my ($self, @tokens) = @_; my @ret = $self->find_somethings_in_list(0, @tokens); if ( $#ret < 0 ) { return; } my $entity = PlSense::Entity::Array->new(); FOUND: foreach my $any ( @ret ) { if ( eval { $any->isa("PlSense::Entity") } ) { $entity->set_element($any); } else { $entity->push_address($any); } } return $entity; } sub find_somethings_in_list : PRIVATE { my ($self, $is_addr, @tokens) = @_; my (@ret, @parts); my $e = shift @tokens or return @ret; if ( ! $e->isa("PPI::Structure::List") ) { return @ret; } my $lite = $self->find_entity_in_literal($e, @tokens); if ( $lite ) { return $is_addr ? () : ($lite); } logger->info("Found list : ".$e->content); my @children = $e->children; if ( $#children < 0 ) { return @ret; } $e = shift @children or return @ret; if ( ! $e->isa("PPI::Statement") ) { return @ret; } @children = $e->children; SHIFT_CHILD: while ( my $c = shift @children ) { if ( $c->isa("PPI::Token::Operator") && $c->content eq "," ) { push @ret, $is_addr ? $self->find_address(@parts) : $self->find_address_or_entity(@parts); @parts = (); } else { push @parts, $c; } } if ( $#parts >= 0 ) { push @ret, $is_addr ? $self->find_address(@parts) : $self->find_address_or_entity(@parts); } return @ret; } sub find_entity_in_literal : PRIVATE { my ($self, @tokens) = @_; my $e = shift @tokens or return; if ( $e->isa("PPI::Token::Number") ) { my $value = "".$e->content.""; logger->info("Found literal number : ".$value); return PlSense::Entity::Scalar->new({ value => $value }); } elsif ( $e->isa("PPI::Token::Quote") ) { my $value; if ( $e->isa("PPI::Token::Quote::Single") ) { $value = "".$e->literal.""; } else { $value = "".$e->content.""; $value =~ s{ \A ("|') }{}xms; $value =~ s{ ("|') \z }{}xms; } logger->info("Found literal quote : ".$value); return PlSense::Entity::Scalar->new({ value => $value }); } elsif ( $e->isa("PPI::Token::QuoteLike::Words") ) { my @values = $e->literal; my $value = join(" ", @values); logger->info("Found literal quotelike words : ".$value); my $entity = PlSense::Entity::Scalar->new({ value => $value }); return PlSense::Entity::Array->new({ element => $entity }); } elsif ( $e->isa("PPI::Token::QuoteLike") ) { my $value = "".$e->content.""; logger->info("Found literal quotelike : ".$value); return PlSense::Entity::Scalar->new({ value => $value }); } elsif ( $e->isa("PPI::Token::HereDoc") ) { my $value = "".$e->content.""; logger->info("Found literal heredoc : ".$value); return PlSense::Entity::Scalar->new({ value => $value }); } elsif ( $e->isa("PPI::Token::ArrayIndex") ) { my $value = "".$e->content.""; logger->info("Found literal arrayindex : ".$value); return PlSense::Entity::Scalar->new({ value => $value }); } elsif ( $e->isa("PPI::Structure::List") ) { my @children = $e->children; $e = shift @children or return; if ( ! $e->isa("PPI::Statement::Expression") ) { return; } my $constructor = $self->get_hash_constructor($e->children) or return; logger->info("Found literal hash constructor : ".$e->content); my $entity = PlSense::Entity::Hash->new(); KEY: foreach my $key ( keys %$constructor ) { my $value = $constructor->{$key}; $entity->set_membernm($key); $entity->set_member( $value ? $value : PlSense::Entity::Null->new() ); } return $entity; } elsif ( $e->isa("PPI::Structure::Constructor") ) { my $value = "".$e->content.""; if ( $value =~ m{ \A \{ }xms ) { logger->info("Found literal hash ref constructor : ".$value); my $entity = PlSense::Entity::Hash->new(); my @children = $e->children; $e = shift @children; if ( $e && $e->isa("PPI::Statement::Expression") ) { my $constructor = $self->get_hash_constructor($e->children); if ( $constructor ) { KEY: foreach my $key ( keys %$constructor ) { my $value = $constructor->{$key}; $entity->set_membernm($key); $entity->set_member( $value ? $value : PlSense::Entity::Null->new() ); } } } return PlSense::Entity::Reference->new({ entity => $entity }); } elsif ( $value =~ m{ \A \[ }xms ) { logger->info("Found literal array ref constructor : ".$value); my $entity = PlSense::Entity::Array->new({ element => PlSense::Entity::Null->new() }); return PlSense::Entity::Reference->new({ entity => $entity }); } } return; } sub get_hash_constructor : PRIVATE { my ($self, @tokens) = @_; my @parts; my $key = ""; my $pre; my %ret; TOKEN: while ( my $e = shift @tokens ) { if ( $e->isa("PPI::Token::Operator") && $e->content eq "," ) { if ( ! $key ) { return; } $ret{$key} = $self->find_address_or_entity(@parts); $key = ""; } elsif ( $e->isa("PPI::Token::Operator") && $e->content eq '=>' ) { if ( $pre->isa("PPI::Token::Word") ) { $key = "".$pre->literal.""; } @parts = (); } else { push @parts, $e; } $pre = $e; } if ( $key && $#parts >= 0 ) { $ret{$key} = $self->find_address_or_entity(@parts); } my @keys = keys %ret; return $#keys >= 0 ? \%ret : undef; } sub find_address_in_cast : PRIVATE { my ($self, @tokens) = @_; my $e = shift @tokens or return; if ( ! $e->isa("PPI::Token::Cast") || $e->content eq "\\" ) { return; } my $next = shift @tokens; my @casted; if ( $next->isa("PPI::Structure::Block") ) { my $stmt = $next->find_first("PPI::Statement"); @casted = $stmt->children(); } else { @casted = ($next); } my $addr = $self->find_address_in_symbol(@casted) or return; logger->info("Found cast : ".$addr); return $self->build_address_anything("$addr.R", @tokens); } sub find_entity_in_cast : PRIVATE { my ($self, @tokens) = @_; my $e = shift @tokens or return; if ( ! $e->isa("PPI::Token::Cast") || $e->content ne "\\" ) { return; } my $next = shift @tokens; my @casted; if ( $next->isa("PPI::Structure::Block") ) { my $stmt = $next->find_first("PPI::Statement"); @casted = $stmt->children(); } else { @casted = ($next); } my $addr = $self->find_address_in_symbol(@casted) or return; logger->info("Found cast : ".$addr); return PlSense::Entity::Reference->new({ entity => $addr }); } sub find_address_in_magic : PRIVATE { my ($self, @tokens) = @_; my $e = shift @tokens or return; if ( ! $e->isa("PPI::Token::Magic") || $e->content ne '@_' ) { return; }; my $mtd = $self->get_currentmethod or return; return '@'.$mtd->get_fullnm."::_"; } sub find_address_in_symbol : PRIVATE { my ($self, @tokens) = @_; my $e = shift @tokens or return; if ( ! $e->isa("PPI::Token::Symbol") ) { return; } my $varnm = $e->symbol || ""; my $mdl = $self->get_currentmodule; my $mtd = $self->get_currentmethod; if ( builtin->exist_variable($varnm) ) { logger->debug("Found builtin variable : $varnm"); my $p = $bpluginh_of{ident $self}->{$varnm}; if ( $p ) { return $p->find_address(@tokens); } return; } if ( $mtd && $mtd->exist_variable($varnm) ) { logger->info("Found method local variable : ".$varnm); my $var = $mtd->get_variable($varnm); return $self->build_address_anything($var->get_fullnm, @tokens); } if ( $mdl->exist_member($varnm) ) { logger->info("Found own variable : ".$varnm); my $var = $mdl->get_member($varnm); return $self->build_address_anything($var->get_fullnm, @tokens); } if ( $varnm =~ m{ \A (\$|@|%|&) ([a-zA-Z0-9:]+) :: ([a-zA-Z0-9_]+) \z }xms ) { my ($type, $mdlnm, $somenm) = ($1, $2, $3); my $m = mdlkeeper->get_module($mdlnm) or return; my $addr = $type.$mdlnm."::".$somenm; if ( $type eq '&' ) { logger->info("Found used method : ".$addr); return $self->build_address_anything_with_method_arg($addr, @tokens); } else { logger->info("Found used variable : ".$addr); return $self->build_address_anything($addr, @tokens); } } logger->debug($mtd ? "Unknown symbol[$varnm] in module[".$mdl->get_name."] method[".$mtd->get_name."]" : "Unknown symbol[$varnm] in module[".$mdl->get_name."]"); return; } sub find_something_in_word : PRIVATE { my ($self, $is_addr, @tokens) = @_; my $e = shift @tokens or return; if ( ! $e->isa("PPI::Token::Word") ) { return; } my $currwd = "".$e->literal.""; my $mdl = $self->get_currentmodule; if ( $mdl->exist_method($currwd) ) { my $pret; my $p = $epluginh_of{ident $self}->{$currwd}; if ( $p ) { logger->info("Found importive method : $currwd"); $pret = $is_addr ? $p->find_address( $p->get_argument_tokens(@tokens) ) : $p->find_address_or_entity( $p->get_argument_tokens(@tokens) ); } if ( $pret ) { return $pret; } logger->info("Found own method : $currwd"); my $mtd = $mdl->get_method($currwd); return $self->build_address_anything_with_method_arg($mtd->get_fullnm, @tokens); } if ( builtin->exist_method($currwd) ) { logger->debug("Found builtin function : $currwd"); my $p = $bpluginh_of{ident $self}->{$currwd}; if ( $p ) { return $is_addr ? $p->find_address( $p->get_argument_tokens(@tokens) ) : $p->find_address_or_entity( $p->get_argument_tokens(@tokens) ); } return; } my $m = mdlkeeper->get_module($currwd); if ( $m ) { logger->info("Found module : $currwd"); return $self->build_address_literal_method($m, @tokens); } if ( $currwd =~ m{ \A ([a-zA-Z0-9:]+) :: ([a-zA-Z0-9_]+) \z }xms ) { my ($mdlnm, $mtdnm) = ($1, $2); my $m = mdlkeeper->get_module($mdlnm) or return; my $addr = $mdlnm."::".$mtdnm; logger->info("Found used method : $addr"); return $self->build_address_anything_with_method_arg("&".$addr, @tokens); } logger->debug("Unknown word[".$currwd."] in module[".$mdl->get_name."]"); return; } sub build_address_literal_method : PRIVATE { my ($self, $mdl, @tokens) = @_; if ( ! $mdl || ! $mdl->isa("PlSense::Symbol::Module") ) { logger->error("Not PlSense::Symbol::Module"); return; } my $e = shift @tokens or return; if ( ! $e->isa("PPI::Token::Operator") || $e->content ne '->' ) { return; } $e = shift @tokens; if ( ! $e || ! $e->isa("PPI::Token::Word") ) { return; } my $addr = "&".$mdl->get_fullnm."::".$e->content; logger->info("Found called literal method : ".$e->content); return $self->build_address_anything_with_method_arg($addr, @tokens); } sub build_address_anything_with_method_arg : PRIVATE { my ($self, $addr, @tokens) = @_; return $self->with_build ? $self->build_address_anything_with_build_method_arg($addr, @tokens) : $self->build_address_anything_with_skip_method_arg($addr, @tokens); } sub build_address_anything_with_build_method_arg : PRIVATE { my ($self, $addr, @tokens) = @_; my @values = $self->find_addresses_or_entities(@tokens); if ( $#values >= 0 ) { my $e = shift @tokens; $e = $e ? $e->previous_sibling : undef; $e = $e ? $e->previous_sibling : undef; my $objective = $e && $e->isa("PPI::Token::Operator") && $e->content eq '->' ? 1 : 0; my $resolved_addr = $addr =~ m{ \A .+ \.W: [^.]+ \z }xms ? 0 : 1; ARGUMENT: for my $i ( 0..$#values ) { my $idx = $objective ? $i+2 : $i+1; if ( $resolved_addr ) { substkeeper->add_substitute($addr."[".$idx."]", $values[$i]); } else { substkeeper->add_unknown_argument($addr, $idx, $values[$i]); } } } return $self->build_address_anything($addr, @tokens); } sub build_address_anything_with_skip_method_arg : PRIVATE { my ($self, $addr, @tokens) = @_; my $e = shift @tokens; return $e && $e->isa("PPI::Structure::List") ? $self->build_address_anything($addr, @tokens) : $self->build_address_anything($addr, $e, @tokens); } sub build_address_anything : PRIVATE { my ($self, $addr, @tokens) = @_; return $self->build_address_word($addr, @tokens) || $self->build_address_subscript($addr, @tokens) || $self->build_address_referencing_subscript($addr, @tokens) || $addr; } sub build_address_word : PRIVATE { my ($self, $addr, @tokens) = @_; my $ope = shift @tokens or return; if ( ! $ope->isa("PPI::Token::Operator") || $ope->content ne '->' ) { return; } my $word = shift @tokens or return; if ( ! $word->isa("PPI::Token::Word") ) { return; } $addr = $addr.".W:".$word->content; return $self->build_address_anything_with_method_arg($addr, @tokens); } sub build_address_subscript : PRIVATE { my ($self, $addr, @tokens) = @_; my $e = shift @tokens or return; if ( ! $e->isa("PPI::Structure::Subscript") ) { return; } my $brace_s = $e->start; if ( $brace_s eq '{' ) { my $membernm = "".$e->content.""; $membernm =~ s{ \A (\{|\[) \s* }{}xms; $membernm =~ s{ \s* (\}|\]) \z }{}xms; $membernm =~ s{ \A ("|') }{}xms; $membernm =~ s{ ("|') \z }{}xms; if ( $membernm !~ m{ \A [a-zA-Z0-9_\-]+ \z }xms ) { $membernm = '*'; } if ( $membernm ne "*" ) { addrrouter->add_hash_member($addr, $membernm); } return $self->build_address_anything("$addr.H:$membernm", @tokens); } elsif ( $brace_s eq '[' ) { return $self->build_address_anything("$addr.A", @tokens); } logger->debug("Unknown brace : ".$brace_s); return; } sub build_address_referencing_subscript : PRIVATE { my ($self, $addr, @tokens) = @_; my $e = shift @tokens or return; if ( ! $e->isa("PPI::Token::Operator") || $e->content ne '->' ) { return; } $e = shift @tokens or return; if ( ! $e->isa("PPI::Structure::Subscript") ) { return; } return $self->build_address_subscript("$addr.R", $e, @tokens); } } 1; __END__ plsense-0.3.4/lib/PlSense/AddressRouter.pm000066400000000000000000001001241260377356000204410ustar00rootroot00000000000000package PlSense::AddressRouter; use parent qw{ PlSense::Cacheable }; use strict; use warnings; use Class::Std; use List::AllUtils qw{ firstidx lastidx }; use Try::Tiny; use PlSense::Logger; use PlSense::Configure; use PlSense::Util; { my %cache_of :ATTR( :default(undef) ); my %routeh_of :ATTR(); my %rrouteh_of :ATTR(); my %hmemberh_of :ATTR(); my %max_resolve_entry_of :ATTR( :init_arg :default(3) ); my %max_address_entry_of :ATTR( :init_arg :default(2) ); my %max_reverse_address_entry_of :ATTR( :init_arg :default(30) ); my %max_try_routing_of :ATTR( :init_arg :default(50) ); my %commonkeyh_of :ATTR(); my %with_build_is :ATTR( :init_arg ); sub with_build { my ($self) = @_; return $with_build_is{ident $self} ? 1 : 0; } sub START { my ($class, $ident, $arg_ref) = @_; $cache_of{$ident} = $class->new_cache('Resolve'); $class->reset; } sub setup_without_reload { my $self = shift; $self->update_project(); my $projnm = $self->get_project(); $cache_of{ident $self}->set_namespace( get_config("local") ? "Resolve.$projnm" : "Resolve" ); } sub setup { my $self = shift; my $force = shift || 0; my $projnm = get_config("name"); if ( ! $force && $projnm eq $self->get_project() ) { logger->info("No need switch project data from [$projnm]"); return; } $self->setup_without_reload(); $self->load_current_project(); logger->info("Switched project routing to $projnm"); return 1; } sub store_current_project { my $self = shift; my $key = "perl.".$self->get_project; try { $cache_of{ident $self}->set($key, { route => $routeh_of{ident $self}, rroute => $rrouteh_of{ident $self}, hmember => $hmemberh_of{ident $self} }); } catch { $cache_of{ident $self}->set($key, { route => $routeh_of{ident $self}, rroute => $rrouteh_of{ident $self}, hmember => $hmemberh_of{ident $self} }); }; logger->info("Stored project routing of $key"); } sub load_current_project { my $self = shift; my $key = "perl.".$self->get_project(); my $cacheh; try { $cacheh = $cache_of{ident $self}->get($key); } catch { $cacheh = $cache_of{ident $self}->get($key); }; $routeh_of{ident $self} = $cacheh && $cacheh->{"route"} ? $cacheh->{"route"} : {}; $rrouteh_of{ident $self} = $cacheh && $cacheh->{"rroute"} ? $cacheh->{"rroute"} : {}; $hmemberh_of{ident $self} = $cacheh && $cacheh->{"hmember"} ? $cacheh->{"hmember"} : {}; $self->init_common_key_hash; logger->info("Loaded project routing of $key"); } sub store { my $self = shift; my $mdlnm = shift || ""; my $filepath = shift || ""; my $projectnm = shift || ""; my $key = $self->get_cache_key($mdlnm, $filepath, $projectnm); try { $cache_of{ident $self}->set("[R]".$key, $routeh_of{ident $self}); } catch { $cache_of{ident $self}->set("[R]".$key, $routeh_of{ident $self}); }; try { $cache_of{ident $self}->set("[H]".$key, $hmemberh_of{ident $self}); } catch { $cache_of{ident $self}->set("[H]".$key, $hmemberh_of{ident $self}); }; logger->info("Stored routing of $key"); } sub load { my $self = shift; my $mdlnm = shift || ""; my $filepath = shift || ""; my $projectnm = shift || ""; $self->load_by_cache_key( $self->get_cache_key($mdlnm, $filepath, $projectnm) ); } sub load_by_cache_key { my $self = shift; my $key = shift || ""; $self->load_by_route_key("[R]".$key); $self->load_by_hash_member_key("[H]".$key); } sub remove { my $self = shift; my $mdlnm = shift || ""; my $filepath = shift || ""; my $projectnm = shift || ""; $self->remove_by_cache_key( $self->get_cache_key($mdlnm, $filepath, $projectnm) ); } sub remove_by_cache_key { my $self = shift; my $key = shift || ""; $self->remove_by_cache_key_on_memory($key); try { $cache_of{ident $self}->remove("[R]".$key); } catch { $cache_of{ident $self}->remove("[R]".$key); }; try { $cache_of{ident $self}->remove("[H]".$key); } catch { $cache_of{ident $self}->remove("[H]".$key); }; logger->info("Removed routing of $key"); } sub remove_by_cache_key_on_memory { my $self = shift; my $key = shift || ""; $self->remove_by_route_key_on_memory("[R]".$key); $self->remove_by_hash_member_key_on_memory("[H]".$key); } sub remove_all { my $self = shift; $self->reset; try { $cache_of{ident $self}->clear; } catch { $cache_of{ident $self}->clear; }; logger->info("Removed all routing"); } sub reset { my $self = shift; $routeh_of{ident $self} = {}; $rrouteh_of{ident $self} = {}; $hmemberh_of{ident $self} = {}; $self->init_common_key_hash; } sub add_hash_member { my ($self, $addr, @members) = @_; if ( ! $addr || $#members < 0 ) { return; } my $curr_members = $hmemberh_of{ident $self}->{$addr}; if ( ! $curr_members ) { $curr_members = []; $hmemberh_of{ident $self}->{$addr} = $curr_members; } MEMBER: foreach my $m ( @members ) { if ( ! $m ) { next MEMBER; } if ( grep { $_ eq $m } @{$curr_members} ) { next MEMBER; } push @{$curr_members}, $m; } logger->debug("Add hash member : $addr ... ".join(",", @{$curr_members})); } sub add_route { my ($self, $addr, $value) = @_; if ( ! $addr || ! $value ) { return; } my $ret; my $resolves = $routeh_of{ident $self}->{$addr}; if ( ! $resolves ) { $resolves = []; $routeh_of{ident $self}->{$addr} = $resolves; $ret = 1; } my $vtype = eval { $value->get_type } || ""; my $vtext = $vtype ? $value->to_string : $value; if ( ! $vtype ) { # If this value is address, check current resolves. my @addridxs; RESOLVE: for my $i ( 0..$#{$resolves} ) { my $resolve = @{$resolves}[$i]; if ( eval { $resolve->isa("PlSense::Entity") } ) { next RESOLVE; } # If already exist this value, remove it for moving to last. if ( $resolve eq $value ) { splice @{$resolves}, $i, 1; last RESOLVE; } push @addridxs, $i; # If count of address in resolves is max, remove a before last address. if ( $#addridxs + 1 >= $max_address_entry_of{ident $self} ) { my $ridx = $#addridxs > 1 ? $#addridxs - 1 : 0; splice @{$resolves}, $addridxs[$ridx], 1; last RESOLVE; } } } # If count of resolves is max, remove last entity or last anything. if ( $#{$resolves} + 1 >= $max_resolve_entry_of{ident $self} ) { my $entityidx = lastidx { eval { $_->isa("PlSense::Entity") } } @{$resolves}; if ( $entityidx >= 0 ) { splice @{$resolves}, $entityidx, 1; } else { pop @{$resolves}; } } push @{$resolves}, $value; logger->debug("Add routing : $addr -> $vtext"); # Check to need to add reverse route my $need_r = $vtype ? 0 # no need if value is a entity : $addr =~ m{ \[\d+\] \z }xms && $vtext =~ m{ \[\d+\] \z }xms ? 0 # special if both are a argument : $vtext =~ m{ \[\d+\] \z }xms ? 1 # need if value only is a argument : $vtext =~ m{ ::BLESS \z }xms ? 1 # need if value means a class : 0; if ( $need_r ) { $self->add_reverse_route($value, $addr); } my $commonkey = $self->get_address_common_part($addr); if ( $commonkey ) { $commonkeyh_of{ident $self}->{$commonkey} = 1; } return $ret; } sub add_reverse_route { my ($self, $addr, $raddr) = @_; if ( ! $addr || ! $raddr ) { return; } my $raddrs = $rrouteh_of{ident $self}->{$addr}; if ( ! $raddrs ) { $raddrs = []; $rrouteh_of{ident $self}->{$addr} = $raddrs; } if ( $#{$raddrs} >= $max_reverse_address_entry_of{ident $self} ) { return; } my $idx = firstidx { $_ eq $raddr } @{$raddrs}; if ( $idx >= 0 ) { return; } push @{$raddrs}, $raddr; logger->debug("Add reverse routing : $addr -> $raddr"); } sub remove_hash_member { my ($self, $addr, @members) = @_; if ( ! $addr || $#members < 0 ) { return; } my $curr_members = $hmemberh_of{ident $self}->{$addr} or return; my @new_members = grep { my $m = $_; grep { $_ && $_ eq $m } @members ? 0 : 1; } @$curr_members; $hmemberh_of{ident $self}->{$addr} = \@new_members; logger->debug("Removed routing : $addr ... ".join(",", @new_members)); } sub remove_route { my ($self, $addr, $value) = @_; if ( ! $addr ) { return; } if ( ! $value ) { # delete $routeh_of{ident $self}->{$addr}; # my $commonkey = $self->get_address_common_part($addr); # if ( $commonkey ) { delete $commonkeyh_of{ident $self}->{$commonkey}; } return; } my $resolves = $routeh_of{ident $self}->{$addr} or return; my $vtype = eval { $value->get_type } || ""; my $vstr = $vtype ? $value->to_string : ""; my $idx = $vtype ? firstidx { eval { $_->to_string eq $vstr } } @{$resolves} : firstidx { ! eval { $_->get_type } && $_ eq $value } @{$resolves}; if ( $idx < 0 ) { return; } splice @{$resolves}, $idx, 1; if ( $#{$resolves} < 0 ) { delete $routeh_of{ident $self}->{$addr}; } if ( ! $vtype ) { $self->remove_reverse_route($value, $addr); } my $vtext = $vtype ? $value->to_string : $value; logger->debug("Removed routing : $addr -> $vtext"); } sub remove_reverse_route { my ($self, $addr, $raddr) = @_; if ( ! $addr || ! $raddr ) { return; } my $raddrs = $rrouteh_of{ident $self}->{$addr} or return; my $idx = firstidx { $_ eq $raddr } @{$raddrs}; if ( $idx < 0 ) { return; } splice @{$raddrs}, $idx, 1; if ( $#{$raddrs} < 0 ) { delete $rrouteh_of{ident $self}->{$addr}; } } sub exist_route { my ($self, $addr) = @_; if ( ! $addr ) { return; } return exists $routeh_of{ident $self}->{$addr} || exists $commonkeyh_of{ident $self}->{ $self->get_address_common_part($addr) }; } sub get_hash_members { my ($self, $addr) = @_; if ( ! $addr ) { return (); } my $ret = $hmemberh_of{ident $self}->{$addr} || []; return @{$ret}; } sub get_route { my ($self, $addr) = @_; if ( ! $addr ) { return (); } my $ret = $routeh_of{ident $self}->{$addr} || []; return @{$ret}; } sub get_reverse_route { my ($self, $addr) = @_; if ( ! $addr ) { return (); } my $ret = $rrouteh_of{ident $self}->{$addr} || []; return @{$ret}; } sub resolve_address { my ($self, $addr) = @_; logger->debug("Start resolve address : $addr"); my @resolves = $self->resolve_address_1($addr, 0); if ( $#resolves < 0 ) { return; } @resolves = map { eval { $_->clone } } @resolves; my $ret; MERGE: foreach my $value ( @resolves ) { $ret = $self->update_value($ret, $value); } my $rettext = $ret ? $ret->to_string : ""; logger->debug("Resolved address : $rettext"); return $ret; } sub resolve_anything { my ($self, $addr) = @_; logger->debug("Start resolve anything : $addr"); my (@ret, %found_is); RESOLVED: foreach my $resolve ( $self->resolve_address_1($addr, 1) ) { if ( eval { $resolve->isa("PlSense::Entity") } ) { push @ret, $resolve; } elsif ( $resolve && ! $found_is{$resolve} ) { $found_is{$resolve} = 1; push @ret, $resolve; } } return @ret; } sub get_route_list { my ($self) = @_; return keys %{$routeh_of{ident $self}}; } sub get_reverse_route_list { my ($self) = @_; return keys %{$rrouteh_of{ident $self}}; } sub get_matched_route_list { my ($self, $regexp) = @_; return grep { $_ =~ m{ $regexp }xms } keys %{$routeh_of{ident $self}}; } sub to_string_by_regexp { my ($self, $regexp) = @_; my $ret = ""; MATCH: foreach my $addr ( $self->get_matched_route_list($regexp) ) { my $values = $routeh_of{ident $self}->{$addr}; VALUE: foreach my $value ( @{$values} ) { my $valuetext = eval { $value->isa("PlSense::Entity") } ? $value->to_string : $value; $ret .= "$addr -> $valuetext\n"; } } return $ret; } sub describe_keep_value { my ($self) = @_; my @routes = $self->get_route_list; my $valuecount = 0; ROUTE: foreach my $addr ( @routes ) { my $values = $routeh_of{ident $self}->{$addr} or next ROUTE; $valuecount += $#{$values} + 1; } return "Route ... Entrys:".($#routes+1)." Resolves:".$valuecount."\n"; } sub load_by_route_key : PRIVATE { my $self = shift; my $key = shift || ""; my $loadh; try { $loadh = $cache_of{ident $self}->get($key); } catch { $loadh = $cache_of{ident $self}->get($key); }; if ( ! $loadh ) { return; } ADDR: foreach my $addr ( keys %$loadh ) { my $resolves = $loadh->{$addr} or next ADDR; RESOLVE: foreach my $resolve ( @$resolves ) { $self->add_route($addr, $resolve); } } logger->info("Loaded routing of $key"); } sub load_by_hash_member_key : PRIVATE { my $self = shift; my $key = shift || ""; my $loadh; try { $loadh = $cache_of{ident $self}->get($key); } catch { $loadh = $cache_of{ident $self}->get($key); }; if ( ! $loadh ) { return; } ADDR: foreach my $addr ( keys %$loadh ) { my $members = $loadh->{$addr} or next ADDR; $self->add_hash_member($addr, @$members); } logger->info("Loaded hash member of $key"); } sub remove_by_route_key_on_memory : PRIVATE { my $self = shift; my $key = shift || ""; my $loadh; try { $loadh = $cache_of{ident $self}->get($key); } catch { $loadh = $cache_of{ident $self}->get($key); }; if ( ! $loadh ) { return; } ADDR: foreach my $addr ( keys %$loadh ) { my $resolves = $loadh->{$addr} or next ADDR; RESOLVE: foreach my $resolve ( @$resolves ) { $self->remove_route($addr, $resolve); } } logger->info("Removed routing on memory of $key"); } sub remove_by_hash_member_key_on_memory : PRIVATE { my $self = shift; my $key = shift || ""; my $loadh; try { $loadh = $cache_of{ident $self}->get($key); } catch { $loadh = $cache_of{ident $self}->get($key); }; if ( ! $loadh ) { return; } ADDR: foreach my $addr ( keys %$loadh ) { my $members = $loadh->{$addr} or next ADDR; $self->remove_hash_member($addr, @$members); } logger->info("Removed hash member on memory of $key"); } sub get_address_common_part : PRIVATE { my ($self, $addr) = @_; if ( $addr =~ m{ \A [\$@%]? &? main\[ .+? \] :: [^.]+ }xms ) { return $&; } elsif ( $addr =~ m{ \A ([^.]+) }xms ) { return $&; } logger->warn("Failed get address common part from $addr"); return ""; } sub init_common_key_hash : PRIVATE { my ($self) = @_; $commonkeyh_of{ident $self} = {}; if ( ! $self->with_build ) { return; } ADDR: foreach my $addr ( keys %{$routeh_of{ident $self}} ) { my $commonkey = $self->get_address_common_part($addr) or next ADDR; $commonkeyh_of{ident $self}->{$commonkey} = 1; } } my %chkaddress_is :ATTR(); my %trycount_of :ATTR(); sub resolve_address_1 : PRIVATE { my ($self, $addr, $allow_addr) = @_; my (@ret, @othermdls, $followaddr); my $trycount = 0; my $curraddr = $addr; ADDR: while ( $curraddr && $trycount < 3 ) { logger->debug("Start try resolve by $curraddr"); $trycount_of{ident $self} = 0; $chkaddress_is{ident $self} = {}; @ret = $self->resolve_address_sentinel($curraddr, $allow_addr, 1); if ( $#ret >= 0 ) { last ADDR; } if ( ! defined $followaddr ) { logger->debug("Start try get other address from [$addr]"); my $mtdaddr = $addr =~ s{ \A & ( main \[ .+? \] :: [^.]+ ) }{}xms ? $1 : $addr =~ s{ \A & ( [a-zA-Z0-9_:]+ ) }{}xms ? $1 : "" or last ADDR; $followaddr = $addr || ""; if ( $mtdaddr !~ s{ :: ([^:]+) \z }{}xms ) { last ADDR; } my $mtdnm = $1; $followaddr = $mtdnm.$followaddr; my ($mdlnm, $filepath) = $mtdaddr =~ m{ \A main \[ (.+) \] \z }xms ? ("main", $1) : ($mtdaddr, ""); my $mdl = mdlkeeper->get_module($mdlnm, $filepath) or last ADDR; my $mtd = $mdl->get_any_method($mtdnm) or last ADDR; if ( $mtd->is_importive ) { logger->debug("Try get original method of [$mtdnm] in [".$mdl->get_name."]"); USINGMDL: for my $i ( 1..$mdl->count_usingmdl ) { my $extmdl = $mdl->get_usingmdl($i); if ( ! $extmdl->exist_method($mtdnm) ) { next USINGMDL; } my $extmtd = $extmdl->get_method($mtdnm); if ( $extmtd->is_importive ) { next USINGMDL; } push @othermdls, $extmdl->get_name; last USINGMDL; } } else { logger->debug("Try get all parents of [".$mdl->get_name."]"); @othermdls = $mdl->get_all_parents(1); } } if ( $#othermdls < 0 ) { last ADDR; } my $nextmdlnm = shift @othermdls; $curraddr = "&".$nextmdlnm."::".$followaddr; $trycount++; } return @ret; } sub is_valid_address_to_resolve : PRIVATE { my ($self, $addr) = @_; # Allow try to resolve some time for the case that call same method having different follow address. # For example, method for clone. my $trycount = $chkaddress_is{ident $self}->{$addr} || 0; if ( $trycount >= 3 ) { return 0; } $chkaddress_is{ident $self}->{$addr} = $trycount + 1; return 1; } sub is_found_address_while_resolve : PRIVATE { my ($self, $addr) = @_; if ( $chkaddress_is{ident $self}->{$addr} ) { return 1; } $chkaddress_is{ident $self}->{$addr} = 1; return 0; } sub resolve_address_sentinel : PRIVATE { my ($self, $addr, $allow_addr, $not_resolve_reverse) = @_; if ( ! $self->is_valid_address_to_resolve($addr) ) { return (); } if ( $trycount_of{ident $self} >= $max_try_routing_of{ident $self} ) { logger->debug("Exceed max try routing for resolve address"); return (); } $trycount_of{ident $self}++; my (@ret, @follows); my $curraddr = $addr; if ( ! $not_resolve_reverse ) { push @ret, $self->resolve_reverse_address($addr, $allow_addr); } FIND: while ( $curraddr && ! exists $routeh_of{ident $self}->{$curraddr} ) { if ( $curraddr !~ s{ \. ([^.]+) \z }{}xms ) { last FIND; } unshift @follows, $1; } my $resolves = $curraddr ? $routeh_of{ident $self}->{$curraddr} : []; if ( ! $resolves ) { $resolves = []; } my $fstr = join(".", @follows); PUSH_RESOLVED: foreach my $value ( @{$resolves} ) { if ( eval { $value->isa("PlSense::Entity") } ) { logger->debug("Resolved $curraddr -> ".$value->to_string." / $fstr"); push @ret, $self->resolve_entity($allow_addr, $value, @follows); } elsif ( $self->is_valid_address_to_resolve($value) ) { my $naddr = $fstr ? $value.".".$fstr : $value; logger->debug("Resolved $curraddr -> $value / $fstr"); if ( $allow_addr ) { push @ret, $naddr; } push @ret, $self->resolve_address_sentinel($naddr, $allow_addr); } } return @ret; } sub resolve_reverse_address : PRIVATE { my ($self, $addr, $allow_addr) = @_; my (@ret, @follows); # do reverse routing only for a reference address if ( $addr !~ s{ \. ( R \.? .*? ) \z }{}xms ) { return @ret; } @follows = split m{ \. }xms, $1; my $curraddr = $addr; FIND: while ( $curraddr && ! exists $rrouteh_of{ident $self}->{$curraddr} ) { if ( $curraddr !~ s{ \. ([^.]+) \z }{}xms ) { last FIND; } unshift @follows, $1; } my $raddrs = $curraddr ? $rrouteh_of{ident $self}->{$curraddr} : [] or return @ret; logger->debug("Found reverse route of $curraddr"); my $fstr = join(".", @follows); PUSH_RESOLVED: foreach my $raddr ( @{$raddrs} ) { if ( $self->is_found_address_while_resolve($raddr) ) { next PUSH_RESOLVED; } my $naddr = $raddr.".".$fstr; logger->debug("Resolved $curraddr -> $raddr / $fstr"); if ( $allow_addr ) { push @ret, $naddr; } push @ret, $self->resolve_address_sentinel($naddr, $allow_addr); } return @ret; } sub resolve_entity : PRIVATE { my ($self, $allow_addr, $entity, @follows) = @_; if ( ! $entity ) { return (); } my $etype = $entity->get_type; if ( $etype eq 'null' ) { return (); } my $follow = shift @follows or return ( $self->get_correct_entity($entity) ); my @ret; my $ch = substr($follow, 0, 1); my $fstr = join(".", @follows); if ( $ch eq "A" ) { if ( $etype ne 'array' ) { return (); } my $el = $entity->get_element; if ( eval { $el->isa("PlSense::Entity") } ) { logger->debug("Resolved ".$entity->to_string.$follow." -> ".$el->to_string." / $fstr"); return $self->resolve_entity($allow_addr, $el, @follows); } elsif ( $self->is_valid_address_to_resolve($el) ) { my $naddr = $el && $fstr ? $el.".".$fstr : $el; logger->debug("Resolved ".$entity->to_string.$follow." -> $el / $fstr"); if ( $allow_addr ) { push @ret, $naddr; } push @ret, $self->resolve_address_sentinel($naddr, $allow_addr); } } elsif ( $ch eq "H" ) { if ( $etype ne 'hash' ) { return (); } $entity->set_membernm(substr($follow, 2)); my $member = $entity->get_member || return (); if ( eval { $member->isa("PlSense::Entity") } ) { logger->debug("Resolved ".$entity->to_string.$follow." -> ".$member->to_string." / $fstr"); return $self->resolve_entity($allow_addr, $member, @follows); } elsif ( $self->is_valid_address_to_resolve($member) ) { my $naddr = $member && $fstr ? $member.".".$fstr : $member; logger->debug("Resolved ".$entity->to_string.$follow." -> $member / $fstr"); if ( $allow_addr ) { push @ret, $naddr; } push @ret, $self->resolve_address_sentinel($naddr, $allow_addr); } } elsif ( $ch eq "R" ) { if ( $etype eq 'reference' ) { my $e = $entity->get_entity || return (); if ( eval { $e->isa("PlSense::Entity") } ) { logger->debug("Resolved ".$entity->to_string.$follow." -> ".$e->to_string." / $fstr"); return $self->resolve_entity($allow_addr, $e, @follows); } elsif ( $self->is_valid_address_to_resolve($e) ) { my $naddr = $e && $fstr ? $e.".".$fstr : $e; logger->debug("Resolved ".$entity->to_string.$follow." -> $e / $fstr"); if ( $allow_addr ) { push @ret, $naddr; } push @ret, $self->resolve_address_sentinel($naddr, $allow_addr); } } elsif ( $etype eq 'instance' ) { my $mdlnm = $entity->get_modulenm or return (); my $baddr = '&'.$mdlnm.'::BLESS.R'; if ( ! $self->is_valid_address_to_resolve($baddr) ) { return (); } my $naddr = $fstr ? $baddr.".".$fstr : $baddr; logger->debug("Resolved ".$entity->to_string.$follow." -> $baddr / $fstr"); if ( $allow_addr ) { push @ret, $naddr; } push @ret, $self->resolve_address_sentinel($naddr, $allow_addr); } } elsif ( $ch eq "W" ) { if ( $etype ne 'instance' ) { return (); } my $mdl = mdlkeeper->get_module( $entity->get_modulenm ) or return (); my $mtdnm = substr($follow, 2); my $mtd = $mdl->get_any_method($mtdnm) or return (); my $mtdfullnm = $mtd->get_fullnm; if ( ! $self->is_valid_address_to_resolve($mtdfullnm) ) { return (); } my $naddr = $fstr ? $mtdfullnm.".".$fstr : $mtdfullnm; logger->debug("Resolved ".$entity->to_string.$follow." -> ".$mtdfullnm." / ".$fstr); if ( $allow_addr ) { push @ret, $naddr; } push @ret, $self->resolve_address_sentinel($naddr, $allow_addr); } return @ret; } sub get_correct_entity : PRIVATE { my ($self, $entity) = @_; if ( ! $entity ) { return; } if ( $entity->isa("PlSense::Entity::Array") ) { my $e = $entity->get_element; my $etype = eval { $e->get_type } || ''; if ( $etype eq 'instance' ) { return $entity; } my $value = ""; ADDR: for my $i ( 1..$entity->count_address ) { my $resolve; my @resolves = $self->resolve_address_sentinel($entity->get_address($i), 0); if ( $#resolves >= 0 ) { @resolves = map { eval { $_->clone } } @resolves; MERGE: foreach my $value ( @resolves ) { $resolve = $self->update_value($resolve, $value); } } if ( ! $resolve ) { next ADDR; } if ( $resolve->isa("PlSense::Entity::Instance") ) { $entity->set_element($resolve); return $entity; } elsif ( $resolve->isa("PlSense::Entity::Array") ) { my $curre = $resolve->get_element or next ADDR; if ( ! eval { $curre->isa("PlSense::Entity::Scalar") } ) { next ADDR; } my $currvalue = $curre->get_value || ""; $value .= $value ne "" && $currvalue ne "" ? " ".$currvalue : $currvalue; } } if ( $value eq "" ) { return $entity; } if ( $etype ne 'scalar' ) { $entity->set_element( PlSense::Entity::Scalar->new({ value => $value }) ); } else { $e->set_value( $e->get_value ? $e->get_value." ".$value : $value ); } return $entity; } return $entity; } sub update_value : PRIVATE { my ($self, $old, $new) = @_; # The value priority is Entity > Address > Null > Nothing if ( ! $new ) { return $old; } if ( ! $old ) { return $new; } my $oldtype = eval { $old->get_type } || ''; my $newtype = eval { $new->get_type } || ''; if ( ! $oldtype || $oldtype eq 'null' ) { return $new; } if ( ! $newtype || $newtype eq 'null' ) { return $old; } # If both is Entity, try to merge return $self->merge_entity($old, $new, $oldtype, $newtype); } sub merge_entity : PRIVATE { my ($self, $old, $new, $oldtype, $newtype) = @_; if ( $oldtype eq 'instance' ) { if ( $newtype ne 'instance' ) { return $new; } my $oldmdlnm = $old->get_modulenm || ""; my $newmdlnm = $new->get_modulenm || ""; if ( ! $oldmdlnm ) { return $new; } elsif ( $newmdlnm && $oldmdlnm ne $newmdlnm ) { return $new; } # my $oldmdl = mdlkeeper->get_module($old->get_modulenm); # my $newmdl = mdlkeeper->get_module($new->get_modulenm); # if ( ! $oldmdl ) { # $old->set_modulenm($new->get_modulenm); # } # elsif ( $newmdl && $old->get_modulenm ne $new->get_modulenm ) { # # looking for common parent of old and new. # OLDPARENT: # for my $i ( 0..$oldmdl->count_parent ) { # my $currmdl = $i == 0 ? $oldmdl : $oldmdl->get_parent($i); # NEWPARENT: # for my $k ( 0..$newmdl->count_parent ) { # my $chkmdl = $k == 0 ? $newmdl : $newmdl->get_parent($k); # if ( $currmdl->get_name eq $chkmdl->get_name ) { # $old->set_modulenm($currmdl->get_name); # return; # } # } # } # } } elsif ( $oldtype eq 'reference' ) { if ( $newtype ne 'reference' ) { return $new; } my $oldrefs = $old->get_entity; my $newrefs = $new->get_entity; $old->set_entity( $self->update_value($oldrefs, $newrefs) ); } elsif ( $oldtype eq 'hash' ) { if ( $newtype ne 'hash' ) { return $new; } KEY: foreach my $key ( $old->keys_member ) { if ( ! $new->exist_member($key) ) { next KEY; } $old->set_membernm($key); $new->set_membernm($key); my $oldval = $old->get_member; my $newval = $new->get_member; $old->set_member( $self->update_value($oldval, $newval) ); } KEY: foreach my $key ( $new->keys_member ) { if ( $old->exist_member($key) ) { next KEY; } $old->set_membernm($key); $new->set_membernm($key); $old->set_member($new->get_member); } } elsif ( $oldtype eq 'array' ) { if ( $newtype ne 'array' ) { return $new; } my $olde = $old->get_element; my $newe = $new->get_element; $old->set_element( $self->update_value($olde, $newe) ); } elsif ( $oldtype eq 'scalar' ) { if ( $newtype ne 'scalar' ) { return $new; } $old->set_value($old->get_value ? $old->get_value." ".$new->get_value : $new->get_value); } return $old; } } 1; __END__ plsense-0.3.4/lib/PlSense/Builtin.pm000066400000000000000000000223351260377356000172700ustar00rootroot00000000000000package PlSense::Builtin; use parent qw{ PlSense::Cacheable }; use strict; use warnings; use Class::Std; use Try::Tiny; use PlSense::Logger; use PlSense::Configure; use PlSense::Symbol::Method; use PlSense::Symbol::Variable; { my %cache_of :ATTR( :default(undef) ); my %current_local_is :ATTR(); my %variableh_of :ATTR( :default(undef) ); sub set_variable : PRIVATE { my ($self, $variablenm, $variable) = @_; $variableh_of{ident $self}->{$variablenm} = $variable; } sub exist_variable { my $self = shift; my $variablenm = shift || ""; return exists $variableh_of{ident $self}->{$variablenm}; } sub get_variable { my $self = shift; my $variablenm = shift || ""; if ( ! exists $variableh_of{ident $self}->{$variablenm} ) { logger->warn("Not exist builtin variable : $variablenm"); return; } return $variableh_of{ident $self}->{$variablenm}; } sub keys_variable { my ($self) = @_; return keys %{$variableh_of{ident $self}}; } sub get_variables { my ($self) = @_; return values %{$variableh_of{ident $self}}; } my %methodh_of :ATTR( :default(undef) ); sub set_method : PRIVATE { my ($self, $methodnm, $method) = @_; my $methodh = $methodh_of{ident $self}; $methodh->{$methodnm} = $method; } sub exist_method { my ($self, $methodnm) = @_; my $methodh = $methodh_of{ident $self}; return exists $methodh->{$methodnm}; } sub get_method { my ($self, $methodnm) = @_; my $methodh = $methodh_of{ident $self}; if ( ! exists $methodh->{$methodnm} ) { logger->warn("Not exist builtin method : $methodnm"); return; } return $methodh->{$methodnm}; } sub keys_method { my ($self) = @_; return keys %{$methodh_of{ident $self}}; } sub get_methods { my ($self) = @_; return values %{$methodh_of{ident $self}}; } sub START { my ($class, $ident, $arg_ref) = @_; $cache_of{$ident} = $class->new_cache('Builtin'); $class->reset; } sub setup_without_reload { my $self = shift; $self->update_project(); my $projnm = $self->get_project(); my $local = get_config("local"); $cache_of{ident $self}->set_namespace( $local ? "Builtin.$projnm" : "Builtin" ); $current_local_is{ident $self} = $local; } sub setup { my $self = shift; my $force = shift || 0; my $projnm = get_config("name"); my $local = get_config("local"); if ( ( ! $force && $projnm eq $self->get_project() ) || ( ! $current_local_is{ident $self} && ! $local ) ) { logger->info("No need switch project data from [$projnm]"); return; } logger->info("Switch project data to [$projnm]"); $self->reset; $self->setup_without_reload(); # Loading is entrusted to server process return 1; } sub build { my ($self, $force) = @_; if ( ! $force && $self->load ) { return; } $self->build_builtin_variables(); $self->build_builtin_functions(); my $c = { variable => $variableh_of{ident $self}, method => $methodh_of{ident $self}, }; try { $cache_of{ident $self}->set("perl", $c); } catch { $cache_of{ident $self}->set("perl", $c); }; } sub load { my ($self) = @_; logger->debug("Start load"); my $c = {}; try { $c = $cache_of{ident $self}->get("perl"); } catch { $c = $cache_of{ident $self}->get("perl"); }; if ( ! exists $c->{variable} || ! exists $c->{method} ) { return; } $variableh_of{ident $self} = $c->{variable}; $methodh_of{ident $self} = $c->{method}; return 1; } sub is_loaded { my ($self) = @_; my @vars = keys %{$variableh_of{ident $self}}; my @mtds = keys %{$methodh_of{ident $self}}; return $#vars > 0 && $#mtds > 0; } sub reset { my ($self) = @_; $variableh_of{ident $self} = {}; $methodh_of{ident $self} = {}; } sub remove { my ($self) = @_; $self->reset; try { $cache_of{ident $self}->clear; } catch { $cache_of{ident $self}->clear; }; logger->info("Removed all builtin info"); } sub build_builtin_variables : PRIVATE { my $self = shift; logger->debug("Start build builtin variables"); $variableh_of{ident $self} = {}; my $perldoc = get_config("perldoc"); my @perldocret = qx{ $perldoc -t perlvar }; my $validline = 0; my $helptext = ""; my $foundvar = 1; my $indentlvl = 0; my @foundvars = (); LINE: foreach my $line ( @perldocret ) { chomp $line; # Start region of builtin variables if ( $line =~ m{ ^ (\s+) \$ARG $ }xms ) { $validline = 1; $indentlvl = length $1; logger->debug("Found region start of build builtin variables"); } # End region of builtin variables elsif ( $validline && $line =~ m{ ^ \s+ Error \s Indicators $ }xms ) { $validline = 0; logger->debug("Found region end of build builtin variables"); if ( $#foundvars >= 0 ) { $self->set_variable_helptext($helptext, @foundvars); @foundvars = (); $helptext = ""; } } if ( ! $validline ) { next LINE; } # Defined variable if ( $line =~ m{ ^ \s{$indentlvl} ([\$@%][^\s]+) ( $ | \s{2,} ) }xms ) { my $varnm = $1; if ( ! $foundvar ) { $self->set_variable_helptext($helptext, @foundvars); @foundvars = (); $helptext = ""; } $foundvar = 1; push @foundvars, $varnm; $helptext .= substr($line, $indentlvl)."\n"; } # Got help else { $helptext .= length($line) > $indentlvl ? substr($line, $indentlvl)."\n" : $line."\n"; $foundvar = 0; } } } sub set_variable_helptext : PRIVATE { my ($self, $helptext, @targetvars) = @_; SET_HELPTEXT: foreach my $varnm ( @targetvars ) { if ( $self->exist_variable($varnm) ) { next SET_HELPTEXT; } my $var = PlSense::Symbol::Variable->new({ name => $varnm }); $var->set_helptext("\n===== Part of PerlDoc =====\n".$helptext); $self->set_variable($varnm, $var); logger->debug("Got builtin variable : $varnm"); } } sub build_builtin_functions : PRIVATE { my $self = shift; logger->debug("Start build builtin functions"); $methodh_of{ident $self} = {}; my $perldoc = get_config("perldoc"); my @perldocret = qx{ $perldoc -t perlfunc }; my $validline = 0; my $helptext = ""; my $foundfunc = 1; my @foundfuncs = (); LINE: foreach my $line ( @perldocret ) { chomp $line; # Start region of builtin functions if ( $line =~ m{ ^ \s+ Alphabetical \s Listing \s of \s Perl \s Functions $ }xms ) { $validline = 1; logger->debug("Found region start of build builtin functions"); } # End region of builtin functions elsif ( $validline && $line =~ m{ ^ \s+ Non-function \s Keywords \s by \s Cross-reference $ }xms ) { $validline = 0; logger->debug("Found region end of build builtin functions"); if ( $#foundfuncs >= 0 ) { $self->set_function_helptext($helptext, @foundfuncs); @foundfuncs = (); $helptext = ""; } } if ( ! $validline ) { next LINE; } # Defined function if ( $line =~ m{ ^ \s{4} ([a-zA-Z0-9_\-]+) }xms ) { my $funcnm = $1; if ( ! $foundfunc ) { $self->set_function_helptext($helptext, @foundfuncs); @foundfuncs = (); $helptext = ""; } $foundfunc = 1; push @foundfuncs, $funcnm; $helptext .= substr($line, 4)."\n"; } # Got help else { $helptext .= length($line) > 4 ? substr($line, 4)."\n" : $line."\n"; $foundfunc = 0; } } } sub set_function_helptext : PRIVATE { my ($self, $helptext, @targetfuncs) = @_; SET_HELPTEXT: foreach my $funcnm ( @targetfuncs ) { if ( $self->exist_method($funcnm) ) { next SET_HELPTEXT; } my $func = PlSense::Symbol::Method->new({ name => $funcnm }); $func->set_helptext("\n===== Part of PerlDoc =====\n".$helptext); $self->set_method($funcnm, $func); logger->debug("Got builtin function : $funcnm"); } } } 1; __END__ plsense-0.3.4/lib/PlSense/Cacheable.pm000066400000000000000000000027651260377356000175160ustar00rootroot00000000000000package PlSense::Cacheable; use strict; use warnings; use Class::Std; use Cache::FileCache; use PlSense::Logger; use PlSense::Configure; { my %projectnm_of :ATTR(); sub get_project : RESTRICTED { my $self = shift; return $projectnm_of{ident $self}; } sub START { my ($class, $ident, $arg_ref) = @_; $projectnm_of{$ident} = get_default_config("name"); } sub update_project { my $self = shift; $projectnm_of{ident $self} = get_config("name"); } sub setup_without_reload { my $self = shift; } sub setup { my $self = shift; my $force = shift || 0; } sub new_cache : RESTRICTED { my ($self, $namespace) = @_; my $cachedir = get_config("cachedir"); if ( ! -d $cachedir ) { logger->error("Not exist directory[".$cachedir."]"); return; } my $ret = Cache::FileCache->new({ cache_root => $cachedir, namespace => $namespace }); if ( ! $ret ) { logger->error("Can't available cache directory[".$cachedir."]"); } return $ret; } sub get_cache_key : RESTRICTED { my $self = shift; my $mdlnm_or_key = shift || ""; my $filepath = shift || ""; my $projectnm = shift || ""; my $ret = $projectnm ? $projectnm."." : ""; $ret .= $mdlnm_or_key eq "main" ? $mdlnm_or_key."|".$filepath : $mdlnm_or_key; return $ret; } } 1; __END__ plsense-0.3.4/lib/PlSense/CodeAssist.pm000066400000000000000000000052231260377356000177200ustar00rootroot00000000000000package PlSense::CodeAssist; use strict; use warnings; use List::AllUtils qw{ uniq }; use Class::Std; use PPI::Lexer; use Module::Pluggable instantiate => 'new', search_path => 'PlSense::Plugin::CodeAssistant'; use PlSense::Logger; use PlSense::Util; use PlSense::Helper; { my %lexer_of :ATTR(); my %assistants_of :ATTR(); sub BUILD { my ($class, $ident, $arg_ref) = @_; $assistants_of{$ident} = []; $lexer_of{$ident} = PPI::Lexer->new(); } sub START { my ($class, $ident, $arg_ref) = @_; my @assistants = $class->plugins(); ASSISTANT: foreach my $assist ( @assistants ) { push @{$assistants_of{$ident}}, $assist; } } sub get_assist { my ($self, $code) = @_; my @ret; my $currmdl = addrfinder->get_currentmodule; if ( ! $currmdl || ! $currmdl->isa("PlSense::Symbol::Module") ) { logger->warn("Not yet set current module"); return @ret; } $code =~ s{ \n\z }{}xms; if ( ! $code ) { return @ret; } my $doc = $lexer_of{ident $self}->lex_source($code); $doc->prune("PPI::Token::Comment"); $doc->prune("PPI::Token::Pod"); my $tok = eval { $doc->last_token } or return @ret; ASSISTANT: foreach my $assist ( @{$assistants_of{ident $self}} ) { $assist->set_input(""); $assist->init_last_candidate_instance; $assist->init_candidate; } logger->info("Start check only valid context"); ASSISTANT: foreach my $assist ( @{$assistants_of{ident $self}} ) { if ( ! $assist->is_only_valid_context($code, $tok) ) { next ASSISTANT; } CANDIDATE: for my $i ( 1..$assist->count_candidate ) { push @ret, $assist->get_candidate($i); } return uniq(sort @ret); } logger->info("Start check valid context"); ASSISTANT: foreach my $assist ( @{$assistants_of{ident $self}} ) { if ( ! $assist->is_valid_context($code, $tok) ) { next ASSISTANT; } CANDIDATE: for my $i ( 1..$assist->count_candidate ) { push @ret, $assist->get_candidate($i); } } return uniq(sort @ret); } sub get_last_candidate_instance { my ($self, $candidate) = @_; if ( ! $candidate ) { return; } ASSISTANT: foreach my $assist ( @{$assistants_of{ident $self}} ) { my $instance = $assist->get_last_candidate_instance($candidate); if ( ! $instance ) { next ASSISTANT; } return $instance; } } } 1; __END__ plsense-0.3.4/lib/PlSense/Configure.pm000066400000000000000000000220161260377356000175770ustar00rootroot00000000000000package PlSense::Configure; use strict; use warnings; use Config::Tiny; use File::Basename; use File::Spec; use PlSense::Logger; use Exporter 'import'; our @EXPORT = qw( setup_config init_config set_primary_config get_config get_default_config exist_global_config exist_project_config create_global_config create_project_config ); { my $global_config_path = File::Spec->rel2abs( $ENV{HOME}."/.plsense" ); my @gkeys = qw( cachedir port1 port2 port3 maxtasks loglevel logfile perl perldoc clean-env ); my @pkeys = qw( name lib-path perl perldoc clean-env local carton ); my %desc_of = ( cachedir => "cache directory path", port1 => "port number for main server", port2 => "port number for work server", port3 => "port number for resolve server", maxtasks => "limit count of task on server", ); my %default_of = ( cachedir => File::Spec->rel2abs( $ENV{HOME}."/.plsense.d" ), port1 => 33333, port2 => 33334, port3 => 33335, maxtasks => 20, perl => "perl", perldoc => "perldoc", "clean-env" => 0, name => "default", local => 0, carton => 0, ); my $gcnf; my $pcnf; my %pcnf_of = (); my %bkenv_of = (); my %primary_of = (); sub setup_config { my ($filepath, $reload, $interactive) = @_; if ( ! $gcnf || $reload ) { $gcnf = {}; $gcnf->{$_} = $primary_of{$_} foreach grep { defined $primary_of{$_} } @gkeys; if ( ! exist_global_config() && $interactive ) { my $ret = read_string("Not exist config file [$global_config_path]\nMaking? (Y/n) ") || ""; if ( ! $ret || lc($ret) eq 'y' || lc($ret) eq 'yes' ) { create_global_config(); } else { print "Not create [$global_config_path]\n"; } } if ( exist_global_config() ) { $gcnf = load_config($global_config_path, @gkeys) or return; $gcnf->{$_} = $primary_of{$_} foreach grep { defined $primary_of{$_} } @gkeys; } } $pcnf = {}; $pcnf->{$_} = $primary_of{$_} foreach grep { defined $primary_of{$_} } @pkeys; if ( ! $filepath ) { return 1; } my $pconfpath = get_config_path($filepath) or return 1; if ( exists $pcnf_of{$pconfpath} && ! $reload ) { $pcnf = $pcnf_of{$pconfpath}; } else { $pcnf = load_config($pconfpath, @pkeys) or return; $pcnf->{$_} = $primary_of{$_} foreach grep { defined $primary_of{$_} } @pkeys; $pcnf->{confpath} = $pconfpath; makeup_config(); $pcnf_of{$pconfpath} = $pcnf; } fix_env(); return 1; } sub init_config { $gcnf = undef; $pcnf = undef; %pcnf_of = (); %primary_of = (); } sub set_primary_config { my %conf = @_; CONFIG: foreach my $confignm ( keys %conf ) { if ( ! grep { $_ eq $confignm } ( @gkeys, @pkeys ) ) { logger->error("Invalid config name : $confignm"); next CONFIG; } $primary_of{$confignm} = $conf{$confignm}; } } sub get_config { my $confignm = shift || ""; my $not_use_default = shift || 0; if ( ! $pcnf || ! $gcnf ) { logger->error("Not yet setup_config done"); return; } if ( ! grep { $_ eq $confignm } ( @gkeys, @pkeys, "confpath" ) ) { logger->error("Invalid config name : $confignm"); return; } return exists $pcnf->{$confignm} ? $pcnf->{$confignm} : exists $gcnf->{$confignm} ? $gcnf->{$confignm} : $not_use_default ? undef : exists $default_of{$confignm} ? $default_of{$confignm} : undef; } sub get_default_config { my $confignm = shift || ""; if ( ! grep { $_ eq $confignm } ( @gkeys, @pkeys, "confpath" ) ) { logger->error("Invalid config name : $confignm"); return; } return $default_of{$confignm} || ""; } sub exist_global_config { return -f $global_config_path ? 1 : 0; } sub exist_project_config { my ($filepath) = @_; return -f get_config_path($filepath) ? 1 : 0; } sub create_global_config { return create_config($global_config_path, @gkeys); } sub create_project_config { my $rootdir = shift || ""; if ( ! -d $rootdir ) { logger->error("Not exist directory : $rootdir"); return; } return create_config($rootdir."/.plsense", @pkeys); } sub makeup_config { my $prootdir = dirname($pcnf->{confpath}); my $perl = get_config("perl"); my $perldoc = get_config("perldoc"); # absolute lib-path my $libpath = get_config("lib-path", 1); if ( $libpath ) { $pcnf->{"lib-path"} = File::Spec->rel2abs($prootdir."/".$libpath); } # fix for Carton my $carton = get_config("carton", 1); if ( $carton ) { $pcnf->{local} = 1; # I'm not sure that Carton project is a local perl environment. if ( $perl eq get_default_config("perl") ) { $perl = "carton exec -- perl"; } if ( $perldoc eq get_default_config("perldoc") ) { $perldoc = "carton exec -- perldoc"; } } # Execute perl/perldoc after moving to the root of project $pcnf->{perl} = "cd '$prootdir' ; $perl"; $pcnf->{perldoc} = "cd '$prootdir' ; $perldoc"; } sub fix_env { if ( get_config("clean-env") ) { ENV: foreach my $envnm ( "PERL5LIB" ) { if ( ! exists $bkenv_of{$envnm} ) { $bkenv_of{$envnm} = $ENV{$envnm}; } $ENV{$envnm} = ""; } } else { ENV: foreach my $envnm ( "PERL5LIB" ) { if ( exists $bkenv_of{$envnm} ) { $ENV{$envnm} = $bkenv_of{$envnm}; } } } } sub create_config { my ($confpath, @keys) = @_; my $old = -f $confpath ? load_config($confpath, @keys) : {}; my $c = Config::Tiny->new; CONFIG: foreach my $confignm ( @keys ) { my $desc = $desc_of{$confignm}; my $default = $default_of{$confignm}; $c->{_}{$confignm} = $desc ? read_string("Input ${desc}: ($default) ") || $default : exists $old->{$confignm} ? $old->{$confignm} : defined $default ? $default : ""; } my $fh; if ( ! open($fh, '>:utf8', $confpath) ) { logger->error("Failed open conffile[$confpath] : $!"); return; } WRITE: for ( my $str = $c->write_string ) { print $fh $str or logger->error("Failed write [$str] to [$confpath] : $!"); } if ( ! close $fh ) { logger->error("Failed close conffile[$confpath] : $!"); return; } return 1; } sub load_config { my ($confpath, @keys) = @_; my $fh; if ( ! open $fh, '<:utf8', $confpath ) { logger->error("Failed open conffile[$confpath] : $!"); return; } my $c = Config::Tiny->read_string( do { local $/; <$fh> } ); if ( ! close $fh ) { logger->error("Failed close conffile[$confpath] : $!"); return; } my $cnf = {}; CONFIG: foreach my $confignm ( @keys ) { my $v = $c->{_}{$confignm}; if ( ! defined $v || $v eq '' ) { next CONFIG; } $v =~ s{ ^ \s+ }{}xms; $v =~ s{ \s+ $ }{}xms; $cnf->{$confignm} = $v; } return $cnf; } sub get_config_path { my ($filepath) = @_; if ( ! -f $filepath ) { return; } my $dirpath = dirname(File::Spec->rel2abs($filepath)); my $confpath; DIR: while ( -d $dirpath ) { my $curr = $dirpath."/.plsense"; if ( -f $curr && $curr ne $global_config_path ) { $confpath = $curr; last DIR; } $dirpath =~ s{ / [^/]+ $ }{}xms or last DIR; } return $confpath; } sub read_string { my $prompt = shift || ""; print $prompt; my $ret = ; $ret =~ s{ ^\s+ }{}xms; $ret =~ s{ \s+$ }{}xms; return $ret; } } 1; __END__ plsense-0.3.4/lib/PlSense/Entity.pm000066400000000000000000000014571260377356000171400ustar00rootroot00000000000000package PlSense::Entity; use strict; use warnings; use Class::Std::Storable; use PlSense::Logger; { my %type_of :ATTR(); sub set_type : RESTRICTED { my ($self, $type) = @_; $type_of{ident $self} = $type; } sub get_type { my ($self) = @_; return $type_of{ident $self}; } sub START { my ($class, $ident, $arg_ref) = @_; my $type = $type_of{$ident} || ""; if ( $type ne "null" && $type ne "scalar" && $type ne "array" && $type ne "hash" && $type ne "reference" && $type ne "instance" ) { logger->error("Invalid type[$type]"); } } sub to_string { my $self = shift; return ""; } sub clone { my $self = shift; return; } } 1; __END__ plsense-0.3.4/lib/PlSense/Entity/000077500000000000000000000000001260377356000165735ustar00rootroot00000000000000plsense-0.3.4/lib/PlSense/Entity/Array.pm000066400000000000000000000042741260377356000202160ustar00rootroot00000000000000package PlSense::Entity::Array; use parent qw{ PlSense::Entity }; use strict; use warnings; use Class::Std::Storable; use PlSense::Logger; use PlSense::Entity::Null; { my %element_of :ATTR( :init_arg :default('') ); sub set_element { my ($self, $element) = @_; my $eltext = eval { $element->isa("PlSense::Entity") } ? $element->to_string : $element; logger->debug("Set array element : ".$eltext); $element_of{ident $self} = $element; } sub get_element { my ($self) = @_; return $element_of{ident $self}; } my %addresses_of :ATTR(); sub push_address { my ($self, $address) = @_; if ( ! $address ) { return; } push @{$addresses_of{ident $self}}, $address; } sub count_address { my ($self) = @_; return $#{$addresses_of{ident $self}} + 1; } sub get_address { my ($self, $index) = @_; if ( $index !~ m{ ^\d+$ }xms ) { logger->warn("Not Integer"); return; } if ( $index < 1 || $index > $#{$addresses_of{ident $self}} + 1 ) { logger->warn("Out of Index"); return; } return @{$addresses_of{ident $self}}[$index - 1]; } sub BUILD { my ($class, $ident, $arg_ref) = @_; $class->set_type("array"); } sub to_string { my $self = shift; my $ret = "A<"; my $e = $self->get_element || ""; $ret .= eval { $e->isa("PlSense::Entity") } ? $e->to_string : $e; KEY: for my $i ( 1..$self->count_address ) { $ret .= $i == 1 ? " | ".$self->get_address($i) : ", ".$self->get_address($i); } $ret .= ">"; return $ret; } sub clone { my $self = shift; my $ret = PlSense::Entity::Array->new(); ADDR: foreach my $addr ( @{$addresses_of{ident $self}} ) { $ret->push_address($addr); } if ( eval { $element_of{ident $self}->isa("PlSense::Entity") } ) { $ret->set_element( $element_of{ident $self}->clone ); } elsif ( $element_of{ident $self} ) { $ret->set_element( $element_of{ident $self} ); } return $ret; } } 1; __END__ plsense-0.3.4/lib/PlSense/Entity/Hash.pm000066400000000000000000000051151260377356000200160ustar00rootroot00000000000000package PlSense::Entity::Hash; use parent qw{ PlSense::Entity }; use strict; use warnings; use Class::Std::Storable; use PlSense::Logger; { my %membernm_of :ATTR( :default('') ); sub set_membernm { my ($self, $membernm) = @_; $membernm = $self->resolve_membernm($membernm); $membernm_of{ident $self} = $membernm; } my %memberh_of :ATTR(); sub set_member { my ($self, $member) = @_; if ( ! $member ) { return; } my $membernm = $membernm_of{ident $self}; my $membertext = eval { $member->isa("PlSense::Entity") } ? $member->to_string : $member; logger->debug("Set hash member[".$membernm."] : ".$membertext); $memberh_of{ident $self}->{$membernm} = $member; } sub get_member { my ($self) = @_; return $memberh_of{ident $self}->{$membernm_of{ident $self}}; } sub keys_member { my ($self) = @_; return keys %{$memberh_of{ident $self}}; } sub exist_member { my ($self, $membernm) = @_; $membernm = $self->resolve_membernm($membernm); return exists $memberh_of{ident $self}->{$membernm}; } sub BUILD { my ($class, $ident, $arg_ref) = @_; $class->set_type("hash"); $memberh_of{$ident} = {}; } sub resolve_membernm : PRIVATE { my $self = shift; my $membernm = shift || ""; $membernm =~ s{ \A (\{|\[) \s* }{}xms; $membernm =~ s{ \s* (\}|\]) \z }{}xms; $membernm =~ s{ \A ("|') }{}xms; $membernm =~ s{ ("|') \z }{}xms; if ( $membernm !~ m{ \A [a-zA-Z0-9_\-]+ \z }xms ) { $membernm = '*'; } return $membernm; } sub to_string { my $self = shift; my $ret = "H<"; MEMBER: foreach my $m ( $self->keys_member ) { $self->set_membernm($m); my $member = $self->get_member || ""; my $membertext = eval { $member->isa("PlSense::Entity") } ? $member->to_string : $member; $ret .= "$m => $membertext, "; } $ret .= ">"; return $ret; } sub clone { my $self = shift; my $ret = PlSense::Entity::Hash->new(); MEMBER: foreach my $membernm ( keys %{$memberh_of{ident $self}} ) { $ret->set_membernm($membernm); my $member = $memberh_of{ident $self}->{$membernm}; if ( eval { $member->isa("PlSense::Entity") } ) { $ret->set_member($member->clone); } elsif ( $member ) { $ret->set_member($member); } } return $ret; } } 1; __END__ plsense-0.3.4/lib/PlSense/Entity/Instance.pm000066400000000000000000000014621260377356000207000ustar00rootroot00000000000000package PlSense::Entity::Instance; use parent qw{ PlSense::Entity }; use strict; use warnings; use Class::Std::Storable; use PlSense::Logger; { my %modulenm_of :ATTR( :init_arg :default('') ); sub set_modulenm { my ($self, $modulenm) = @_; $modulenm_of{ident $self} = $modulenm; } sub get_modulenm { my ($self) = @_; return $modulenm_of{ident $self}; } sub BUILD { my ($class, $ident, $arg_ref) = @_; $class->set_type("instance"); } sub to_string { my $self = shift; my $ret = "I<"; $ret .= $self->get_modulenm ? $self->get_modulenm : ""; $ret .= ">"; return $ret; } sub clone { my $self = shift; return PlSense::Entity::Instance->new({ modulenm => $modulenm_of{ident $self} }); } } 1; __END__ plsense-0.3.4/lib/PlSense/Entity/Null.pm000066400000000000000000000007021260377356000200420ustar00rootroot00000000000000package PlSense::Entity::Null; use parent qw{ PlSense::Entity }; use strict; use warnings; use Class::Std::Storable; use PlSense::Logger; { sub BUILD { my ($class, $ident, $arg_ref) = @_; $class->set_type("null"); } sub to_string { my $self = shift; my $ret = "NULL"; return $ret; } sub clone { my $self = shift; return PlSense::Entity::Null->new(); } } 1; __END__ plsense-0.3.4/lib/PlSense/Entity/Reference.pm000066400000000000000000000024151260377356000210310ustar00rootroot00000000000000package PlSense::Entity::Reference; use parent qw{ PlSense::Entity }; use strict; use warnings; use Class::Std::Storable; use PlSense::Logger; use PlSense::Entity::Null; { my %entity_of :ATTR( :init_arg :default('') ); sub set_entity { my ($self, $entity) = @_; my $etext = eval { $entity->isa("PlSense::Entity") } ? $entity->to_string : $entity; logger->debug("Set reference referenced : ".$etext); $entity_of{ident $self} = $entity; } sub get_entity { my ($self) = @_; return $entity_of{ident $self}; } sub BUILD { my ($class, $ident, $arg_ref) = @_; $class->set_type("reference"); } sub to_string { my $self = shift; my $ret = "R<"; my $e = $self->get_entity; $ret .= eval { $e->isa("PlSense::Entity") } ? $e->to_string : $e; $ret .= ">"; return $ret; } sub clone { my $self = shift; my $ret = PlSense::Entity::Reference->new(); if ( eval { $entity_of{ident $self}->isa("PlSense::Entity") } ) { $ret->set_entity( $entity_of{ident $self}->clone ); } elsif ( $entity_of{ident $self} ) { $ret->set_entity( $entity_of{ident $self} ); } return $ret; } } 1; __END__ plsense-0.3.4/lib/PlSense/Entity/Scalar.pm000066400000000000000000000013161260377356000203370ustar00rootroot00000000000000package PlSense::Entity::Scalar; use parent qw{ PlSense::Entity }; use strict; use warnings; use Class::Std::Storable; use PlSense::Logger; { my %value_of :ATTR( :init_arg :default('') ); sub get_value { my ($self) = @_; return $value_of{ident $self}; } sub set_value { my ($self, $value) = @_; $value_of{ident $self} = $value; } sub BUILD { my ($class, $ident, $arg_ref) = @_; $class->set_type("scalar"); } sub to_string { my $self = shift; my $ret = "S<".$self->get_value.">"; return $ret; } sub clone { my $self = shift; return PlSense::Entity::Scalar->new({ value => $value_of{ident $self} }); } } 1; __END__ plsense-0.3.4/lib/PlSense/Helper.pm000066400000000000000000000242641260377356000171040ustar00rootroot00000000000000package PlSense::Helper; use strict; use warnings; use Class::Std; use PPI::Lexer; use List::AllUtils qw{ first }; use PlSense::Logger; use PlSense::Util; { my %lexer_of :ATTR(); sub BUILD { my ($class, $ident, $arg_ref) = @_; $lexer_of{$ident} = PPI::Lexer->new(); } sub get_any_help_text { my ($self, $any) = @_; if ( ! $any ) { return ""; } if ( eval { $any->isa("PlSense::Symbol") } ) { return $self->get_symbol_help_text($any); } elsif ( eval { $any->isa("PlSense::Entity") } ) { return $self->get_entity_description($any); } else { return "Not documented.\n"; } } sub get_method_info_by_code { my ($self, $code) = @_; $code =~ s{ ^\s+ }{}xms; $code =~ s{ \s+$ }{}xms; if ( ! $code ) { return ""; } my $doc = $lexer_of{ident $self}->lex_source($code) or return ""; $doc->prune("PPI::Token::Comment"); $doc->prune("PPI::Token::Pod"); # $doc->prune("PPI::Token::Whitespace"); my $tok = eval { $doc->last_token } or return ""; my $mtd = $self->find_implicit_method($tok) || $self->find_explicit_method($tok) || $self->find_arrow_fmt_method($tok) or return ""; logger->info("Found valid method : ".$mtd->get_fullnm); my $ret = "NAME: ".$mtd->get_name."\n"; $ret .= $self->get_method_definition($mtd); $ret .= "FILE: ".($mtd->get_module ? $mtd->get_module->get_filepath : "")."\n"; $ret .= "LINE: ".$mtd->get_linenumber."\n"; $ret .= "COL: ".$mtd->get_colnumber."\n"; return $ret; } sub get_help_text_by_code { my ($self, $code) = @_; $code =~ s{ ^\s+ }{}xms; $code =~ s{ \s+$ }{}xms; if ( ! $code ) { return ""; } my $doc = $lexer_of{ident $self}->lex_source($code) or return ""; $doc->prune("PPI::Token::Comment"); $doc->prune("PPI::Token::Pod"); # $doc->prune("PPI::Token::Whitespace"); my $tok = eval { $doc->last_token } or return ""; my $sym = $self->find_any_symbol($tok) || $self->find_implicit_method($tok) || $self->find_arrow_fmt_method($tok) || $self->find_module($tok) or return ""; logger->info("Found valid symbol : ".$sym->get_fullnm); return $self->get_symbol_help_text($sym); } sub get_symbol_help_text { my ($self, $sym) = @_; my $ret = ""; if ( ! $sym ) { return ""; } if ( $sym->isa("PlSense::Symbol::Module") ) { $ret = $sym->get_name." is Module.\n"; $ret .= "defined in '".$sym->get_filepath."'.\n\n"; $ret .= $sym->get_helptext ? $sym->get_helptext."\n" : "Not documented.\n"; } elsif ( $sym->isa("PlSense::Symbol::Method") ) { my $mdl = $sym->get_module; if ( $mdl ) { $ret = $sym->get_name." is Method of ".$mdl->get_fullnm.".\n\n"; } else { $ret = $sym->get_name." is Builtin Method.\n\n"; } $ret .= $self->get_method_definition($sym); $ret .= $sym->get_helptext ? $sym->get_helptext."\n" : "\nNot documented.\n"; } elsif ( $sym->isa("PlSense::Symbol::Variable") ) { my $owner = $sym->get_belong; if ( $owner ) { $ret = $sym->get_name." is Variable of ".$owner->get_fullnm.".\n\n"; } else { $ret = $sym->get_name." is Builtin Variable.\n\n"; } my $entity = addrrouter->resolve_address($sym->get_fullnm); $ret .= $self->get_entity_description($entity); $ret .= $sym->get_helptext ? $sym->get_helptext."\n" : "\nNot documented.\n"; } else { $ret = "Not documented.\n"; } return $ret; } sub find_module : PRIVATE { my ($self, $tok) = @_; if ( ! $tok->isa("PPI::Token::Word") ) { return; } my $word = "".$tok->content.""; return mdlkeeper->get_module($word); } sub find_implicit_method : PRIVATE { my ($self, $tok) = @_; if ( ! $tok->isa("PPI::Token::Word") ) { return; } my $word = "".$tok->content.""; my $pretok = $tok->previous_sibling; if ( $pretok && ! $pretok->isa("PPI::Token::Whitespace") && ! ( $pretok->isa("PPI::Token::Operator") && $pretok->content eq ',' ) ) { return; } if ( $word =~ m{ \A ([a-zA-Z0-9:]+) :: ([a-zA-Z0-9_]+) \z }xms ) { my ($mdlnm, $mtdnm) = ($1, $2); my $mdl = mdlkeeper->get_module($mdlnm) or return; return $mdl->get_any_original_method($mtdnm); } else { my $mdl = addrfinder->get_currentmodule; return builtin->exist_method($word) ? builtin->get_method($word) : $mdl->get_any_original_method($word); } } sub find_arrow_fmt_method : PRIVATE { my ($self, $tok) = @_; if ( ! $tok->isa("PPI::Token::Word") ) { return; } my $word = "".$tok->content.""; my $pretok = $tok->previous_sibling or return; if ( ! $pretok->isa("PPI::Token::Operator") || $pretok->content ne '->' ) { return; } my @tokens = $self->get_valid_tokens($pretok); my $addr = addrfinder->find_address(@tokens); my $mdl; if ( $addr ) { my $entity = addrrouter->resolve_address($addr) or return; if ( ! $entity->isa("PlSense::Entity::Instance") ) { return; } $mdl = mdlkeeper->get_module($entity->get_modulenm) or return; } else { $pretok = pop @tokens or return; if ( ! $pretok->isa("PPI::Token::Word") ) { return; } $mdl = mdlkeeper->get_module("".$pretok->content."") or return; } return $mdl->get_any_original_method($word); } sub find_explicit_method : PRIVATE { my ($self, $tok) = @_; my $mtd = $self->find_any_symbol($tok) or return; if ( ! $mtd->isa("PlSense::Symbol::Method") ) { return; } return $mtd; } sub find_any_symbol : PRIVATE { my ($self, $tok) = @_; if ( ! $tok->isa("PPI::Token::Symbol") ) { return; } # Not use AddressFinder because can not detect the symbol type of incomplete code like $hoge[... my $symstr = "".$tok->content.""; if ( $symstr !~ m{ \A (\$|@|%|&|\$\#) (.+ ::)? ([^:]+) \z }xms ) { return; } my ($symtype, $mdlnm, $symnm) = ($1, $2, $3); my ($mdl, $mtd); if ( ! $mdlnm ) { $mdl = addrfinder->get_currentmodule; $mtd = addrfinder->get_currentmethod; } else { $mdlnm =~ s{ :: \z }{}xms; $mdl = mdlkeeper->get_module($mdlnm) or return; } if ( $symtype eq '&' ) { if ( ! $mdl->exist_method($symnm) ) { return; } return $mdl->get_any_original_method($symnm); } else { my @varnms = $symtype eq '$' ? ('$'.$symnm, '@'.$symnm, '%'.$symnm) : $symtype eq '$#' ? ('@'.$symnm) : ($symtype.$symnm); SEEK: foreach my $varnm ( @varnms ) { my $var = builtin->exist_variable($varnm) ? builtin->get_variable($varnm) : $mtd && $mtd->exist_variable($varnm) ? $mtd->get_variable($varnm) : $mdl->exist_member($varnm) ? $mdl->get_member($varnm) : first { $_->get_fullnm eq $varnm } $mdl->get_external_any_variables; if ( $var ) { return $var; } } } } sub get_valid_tokens : PRIVATE { my ($self, $tok) = @_; my @ret; PRE_TOKEN: while ( $tok = $tok->previous_sibling ) { if ( $tok->isa("PPI::Token::Whitespace") ) { last PRE_TOKEN; } unshift @ret, $tok; } return @ret; } sub get_method_definition : PRIVATE { my ($self, $mtd) = @_; my $ret = ""; my @mtdargs = $mtd->get_arguments; my $startidx = $mtd->get_module && $mtd->get_module->is_objective ? 1 : 0; my $idx = 0; ARG: for my $i ( $startidx..$#mtdargs ) { my $var = $mtdargs[$i]; my $entity = addrrouter->resolve_address($var->get_fullnm); my $etext = ! $entity ? "Unknown" : $entity->isa("PlSense::Entity::Instance") ? $entity->get_modulenm : uc $entity->get_type; $idx++; $ret .= "ARG".$idx.": ".$var->get_name." As ".$etext."\n"; } my @retaddrs = addrrouter->resolve_anything($mtd->get_fullnm); my $retaddr = $#retaddrs >= 0 ? $retaddrs[0] : ""; my $retnm = eval { $retaddr->isa("PlSense::Entity") } ? "Literal" : $retaddr =~ m{ \A ([\$@%]) .+ :: ([a-zA-Z0-9_]+) \z }xms ? $1.$2 : "NoIdent"; my $entity = addrrouter->resolve_address($mtd->get_fullnm); my $etext = ! $entity ? "Unknown" : $entity->isa("PlSense::Entity::Instance") ? $entity->get_modulenm : uc $entity->get_type; $ret .= "RETURN: $retnm As $etext\n"; return $ret; } sub get_entity_description : PRIVATE { my ($self, $entity) = @_; my $etype = eval { $entity->get_type } || "Unknown"; my $ret = "This is ".uc($etype); if ( $etype eq 'instance' ) { my $mdlnm = $entity->get_modulenm || "Unknown"; $ret .= " of $mdlnm.\n"; } elsif ( $etype ne 'Unknown' ) { my $val = $entity->to_string; $val =~ s{ \A [A-Z]< \s* }{}xms; $val =~ s{ \s* > \z }{}xms; $ret .= ".\nThe value maybe ...\n".$val."\n"; } else { $ret .= ".\n"; } return $ret; } } 1; __END__ plsense-0.3.4/lib/PlSense/Logger.pm000066400000000000000000000040701260377356000170750ustar00rootroot00000000000000package PlSense::Logger; use strict; use warnings; use Log::Handler; use Exporter 'import'; our @EXPORT = qw( logger setup_logger update_logger_level ); { my $logger; my $logger_alias = "logger"; sub logger { if ( ! $logger ) { setup_logger($ENV{PLSENSE_LOG_LEVEL}); } return $logger; } sub setup_logger { my ($level, $filepath) = @_; if ( $filepath ) { $logger = Log::Handler->new( file => { filename => $filepath, utf8 => 1, maxlevel => $level ? $level : "err", timeformat => '%H:%M:%S', message_layout => '%m', message_pattern => [ qw/%T %L %p %l %m/ ], prepare_message => sub { my $m = shift; my $pkgnm = $m->{package}; $pkgnm =~ s{ ^PlSense:: }{}xms; $m->{message} = sprintf("%s %-8s %-4s %-45s %s", $m->{time}, $m->{level}.":", $$, $pkgnm."(".$m->{line}.")", $m->{message}); }, alias => $logger_alias, }, screen => { log_to => "STDERR", maxlevel => "err", message_layout => '%L: %m', }, ); } else { $logger = Log::Handler->new( screen => { log_to => "STDERR", maxlevel => $level ? $level : "err", message_layout => '%L: %m', }, ); } } sub update_logger_level { my ($level) = @_; if ( ! $level ) { return; } if ( ! $logger ) { return; } $logger->debug("Update log level : $level"); $logger->set_level( $logger_alias => { maxlevel => $level } ); return; } } 1; __END__ plsense-0.3.4/lib/PlSense/ModuleBuilder.pm000066400000000000000000000002221260377356000204050ustar00rootroot00000000000000package PlSense::ModuleBuilder; use strict; use warnings; use Class::Std; { sub build { my ($self, $mdl) = @_; } } 1; __END__ plsense-0.3.4/lib/PlSense/ModuleBuilder/000077500000000000000000000000001260377356000200535ustar00rootroot00000000000000plsense-0.3.4/lib/PlSense/ModuleBuilder/DocBuilder.pm000066400000000000000000000067421260377356000224360ustar00rootroot00000000000000package PlSense::ModuleBuilder::DocBuilder; use parent qw{ PlSense::ModuleBuilder }; use strict; use warnings; use Class::Std; use PlSense::Logger; use PlSense::Configure; { sub build { my ($self, $mdl) = @_; my $mdlnm = $mdl->get_name(); if ( $mdlnm eq "main" ) { return; } my $filepath = $mdl->get_filepath; my $perldoc = get_config("perldoc"); my $mdlhelptext = qx{ $perldoc -t $mdlnm 2>/dev/null } || qx{ $perldoc -t '$filepath' 2>/dev/null }; if ( $mdlhelptext ne '' ) { $mdl->set_helptext($mdlhelptext); } else { logger->info("Can't get document of [$mdlnm] in [$filepath]"); return; } my @cands = ($mdl->keys_member, $mdl->keys_method); my @indents = (4, 2, 0); my $remained = 1; BUILD: while ( $remained ) { $remained = 0; my $indent = pop @indents; if ( ! defined $indent ) { last BUILD; } $self->build_from_indent_matched($mdl, $mdlhelptext, $indent); CAND: foreach my $cand ( @cands ) { my $c = $mdl->exist_member($cand) ? $mdl->get_member($cand) : $mdl->get_method($cand); if ( $c->get_helptext() eq "" ) { $remained = 1; last CAND; } } } } sub build_from_indent_matched : PRIVATE { my ($self, $mdl, $text, $indent) = @_; my @cands = ($mdl->keys_member(), $mdl->keys_method()); my ($helptext, $lasttitle); my @curre; TITLE: while ( $text =~ m{ ^ \s{$indent} ([^\s] [^\n]+) $ }xms ) { ($text, $helptext) = ($', $`); my $title = $1; if ( $self->update_helptext($lasttitle, $helptext, $indent, @curre) ) { @curre = (); $lasttitle = ""; } my $c; CAND: foreach my $cand ( @cands ) { my $regexp = quotemeta($cand); if ( $title =~ m{ \A $regexp (\s|$) }xms || $title =~ m{ \A " $regexp " (\s|$) }xms || $title =~ m{ \A ' $regexp ' (\s|$) }xms ) { $c = $mdl->exist_member($cand) ? $mdl->get_member($cand) : $mdl->get_method($cand) and last CAND; } } if ( $c ) { push @curre, $c; $lasttitle .= $title."\n"; } else { @curre = (); $lasttitle = ""; } } $self->update_helptext($lasttitle, $helptext, $indent, @curre); } sub update_helptext : PRIVATE { my ($self, $title, $text, $indent, @idents) = @_; if ( $#idents < 0 || ! $title || ! $text || $text !~ m{ [^\s] }xms ) { return; } my $validhelp; my $helptext = $title; LINE: foreach my $line ( split m{ \n }xms, $text ) { if ( $line =~ m{ [^\s] }xms && $line !~ s{ \A \s{$indent} }{}xms ) { last LINE; } $helptext .= $line."\n"; $validhelp = 1; } if ( ! $validhelp ) { return; } ADD_HELPTEXT: foreach my $e ( @idents ) { if ( ! $e || ! $e->isa("PlSense::Symbol") ) { next ADD_HELPTEXT; } $e->set_helptext($e->get_helptext."\n===== Part of PerlDoc =====\n".$helptext); logger->info("Updated help of [".$e->get_fullnm."]"); } return 1; } } 1; __END__ plsense-0.3.4/lib/PlSense/ModuleBuilder/InheritBuilder.pm000066400000000000000000000020321260377356000233170ustar00rootroot00000000000000package PlSense::ModuleBuilder::InheritBuilder; use parent qw{ PlSense::ModuleBuilder }; use strict; use warnings; use Class::Std; use PlSense::Logger; use PlSense::Configure; use PlSense::Util; { sub build { my ($self, $mdl) = @_; my $mdlnm = $mdl->get_name(); if ( $mdlnm eq "main" ) { return; } my $perl = get_config("perl"); my $libopt = get_config("lib-path") ? "-I'".get_config("lib-path")."'" : ""; INHERIT: foreach my $line ( qx{ $perl $libopt -e 'use $mdlnm; print join "\\n"=>\@${mdlnm}::ISA' 2>/dev/null } ) { chomp $line; if ( $line !~ m{ ^ [a-zA-Z_][a-zA-Z0-9_:]* $ }xms ) { next INHERIT; } my $parent = mdlkeeper->get_module($line); if ( ! $parent ) { logger->warn("Not found module named [$line]"); next INHERIT; } $mdl->push_parent($parent); logger->debug("Found parent module of [".$mdl->get_name."] : ".$parent->get_name); } } } 1; __END__ plsense-0.3.4/lib/PlSense/ModuleBuilder/PPIBuilder.pm000066400000000000000000000237141260377356000223570ustar00rootroot00000000000000package PlSense::ModuleBuilder::PPIBuilder; use parent qw{ PlSense::ModuleBuilder }; use strict; use warnings; use Class::Std; use PPI::Lexer; use Module::Pluggable instantiate => 'new', search_path => 'PlSense::Plugin::PPIBuilder'; use PlSense::Logger; use PlSense::Util; use PlSense::ModuleBuilder::PPIBuilder::IncludeStmt; use PlSense::Symbol::Method; use PlSense::Symbol::Variable; { my %lexer_of :ATTR(); my %plugins_of :ATTR(); my %includestmtbuilder_of :ATTR(); sub BUILD { my ($class, $ident, $arg_ref) = @_; $lexer_of{$ident} = PPI::Lexer->new(); $plugins_of{$ident} = []; } sub START { my ($class, $ident, $arg_ref) = @_; my @plugins = $class->plugins(); PLUGIN: foreach my $p ( @plugins ) { push @{$plugins_of{$ident}}, $p; } $includestmtbuilder_of{$ident} = PlSense::ModuleBuilder::PPIBuilder::IncludeStmt->new(); } sub build { my ($self, $mdl) = @_; $self->build_document($mdl, undef, $mdl->get_source); } sub build_source { my ($self, $mdl, $mtd, $source) = @_; my $ppi = $lexer_of{ident $self}->lex_source($source) or return; $self->build_document($mdl, $mtd, $ppi, 1); } sub build_document : PRIVATE { my ($self, $mdl, $mtd, $ppi, $is_fragment) = @_; if ( ! $ppi ) { return; } logger->debug("Start build document for [".$mdl->get_name."]\n".$ppi->serialize); logger->info("Start find defined method/variable in PPI part"); $self->build_anything($mdl, $mtd, $ppi->clone, $is_fragment); logger->info("Start build source in PPI part"); substbuilder->set_currentmodule($mdl); $self->do_plugins_begin($mdl, $ppi); $ppi->prune("PPI::Token::Comment"); $ppi->prune("PPI::Token::Pod"); $ppi->prune("PPI::Token::Whitespace"); $self->do_plugins_start($mdl, $ppi); my $incstmts = $ppi->find("PPI::Statement::Include"); if ( $incstmts ) { logger->info("Start build include in PPI part"); INCLUDE: foreach my $incstmt ( @{$incstmts} ) { $includestmtbuilder_of{ident $self}->build($mdl, $incstmt); } $ppi->prune("PPI::Statement::Include"); } my $schstmts = $ppi->find("PPI::Statement::Scheduled"); if ( $schstmts ) { logger->info("Start build scheduled in PPI part"); SCHEDULED: foreach my $schstmt ( @{$schstmts} ) { my $stmts = $schstmt->find("PPI::Statement") or next SCHEDULED; STMT: foreach my $stmt ( @{$stmts} ) { if ( $stmt->isa("PPI::Statement::Variable") ) { my $vars = $self->get_variables_from_statement($mdl, undef, $stmt) or next STMT; PLUGIN: foreach my $p ( @{$plugins_of{ident $self}} ) { $p->variable_statement($vars, $stmt); } } else { PLUGIN: foreach my $p ( @{$plugins_of{ident $self}} ) { $p->scheduled_statement($mdl, $schstmt->type, $stmt); } } } } $ppi->prune("PPI::Statement::Scheduled"); } my $mtdstmts = $ppi->find("PPI::Statement::Sub"); if ( $mtdstmts ) { logger->info("Start build sub in PPI part"); METHOD: foreach my $mtdstmt ( @{$mtdstmts} ) { my $mtd = $self->get_method_from_statement($mdl, $mtdstmt) or next METHOD; substbuilder->set_currentmethod($mtd); PLUGIN: foreach my $p ( @{$plugins_of{ident $self}} ) { $p->sub_statement($mtd, $mtdstmt); } if ( $mtdstmt->forward ) { next METHOD; } my $stmts = $mtdstmt->find("PPI::Statement") or next METHOD; STMT: foreach my $stmt ( @{$stmts} ) { if ( $stmt->isa("PPI::Statement::Variable") ) { my $vars = $self->get_variables_from_statement($mdl, $mtd, $stmt) or next STMT; PLUGIN: foreach my $p ( @{$plugins_of{ident $self}} ) { $p->variable_statement($vars, $stmt); } } else { PLUGIN: foreach my $p ( @{$plugins_of{ident $self}} ) { $p->other_statement($mdl, $mtd, $stmt); } } } } $ppi->prune("PPI::Statement::Sub"); } my $stmts = $ppi->find("PPI::Statement"); if ( $stmts ) { logger->info("Start build other statement in PPI part"); if ( $mtd ) { substbuilder->set_currentmethod($mtd); } else { substbuilder->init_currentmethod; } STMT: foreach my $stmt ( @{$stmts} ) { if ( $stmt->isa("PPI::Statement::Variable") ) { my $vars = $self->get_variables_from_statement($mdl, $mtd, $stmt) or next STMT; PLUGIN: foreach my $p ( @{$plugins_of{ident $self}} ) { $p->variable_statement($vars, $stmt); } } else { PLUGIN: foreach my $p ( @{$plugins_of{ident $self}} ) { $p->other_statement($mdl, $mtd, $stmt); } } } } substbuilder->init_currentmethod; $self->do_plugins_end($mdl, $ppi); } sub build_anything : PRIVATE { my ($self, $mdl, $mtd, $ppi, $is_fragment) = @_; my $mtdstmts = $ppi->find("PPI::Statement::Sub"); if ( $mtdstmts ) { METHOD: foreach my $mtdstmt ( @{$mtdstmts} ) { my $mtd = $self->build_method($mdl, $mtdstmt, $is_fragment) or next METHOD; my $varstmts = $mtdstmt->find("PPI::Statement::Variable") or next METHOD; STMT: foreach my $stmt ( @{$varstmts} ) { $self->build_variable($mdl, $mtd, $stmt); } } $ppi->prune("PPI::Statement::Sub"); } my $varstmts = $ppi->find("PPI::Statement::Variable") or return; STMT: foreach my $stmt ( @{$varstmts} ) { $self->build_variable($mdl, $mtd, $stmt); } } sub build_variable : PRIVATE { my ($self, $mdl, $mtd, $stmt) = @_; logger->info("Found variable statement : ".$stmt->content); if ( $stmt->type ne "my" && $stmt->type ne "our" ) { return; } SYMBOL: foreach my $varnm ( $stmt->symbols ) { my $var = $mtd && $mtd->exist_variable($varnm) ? $mtd->get_variable($varnm) : $mdl->exist_member($varnm) ? $mdl->get_member($varnm) : PlSense::Symbol::Variable->new({ name => "$varnm", lexical => $stmt->type eq "our" ? 0 : 1, belong => $mtd && $stmt->type eq "my" ? $mtd : $mdl, }); $var->set_importive(0); } } sub get_variables_from_statement : PRIVATE { my ($self, $mdl, $mtd, $stmt) = @_; if ( $stmt->type ne "my" && $stmt->type ne "our" ) { return; } my @vars; SYMBOL: foreach my $varnm ( $stmt->symbols ) { my $var = $mtd && $mtd->exist_variable($varnm) ? $mtd->get_variable($varnm) : $mdl->exist_member($varnm) ? $mdl->get_member($varnm) : undef; if ( ! $var ) { return; } push @vars, $var; } return \@vars; } sub build_method : PRIVATE { my ($self, $mdl, $mtdstmt, $is_fragment) = @_; my $mtdnm = $mtdstmt->name(); logger->info("Found method statement : $mtdnm"); my $mtd = $mdl->exist_method($mtdnm) ? $mdl->get_method($mtdnm) : PlSense::Symbol::Method->new({ name => "$mtdnm", module => $mdl, publicly => 1 }); $mtd->set_importive(0); if ( $mtdstmt->reserved ) { $mtd->set_reserved(1); } my @tokens = $mtdstmt->children; METHOD_TOKEN: foreach my $tok ( @tokens ) { if ( ! $tok || ! $tok->isa("PPI::Token::Attribute") ) { next METHOD_TOKEN; } my $attr = { content => $tok->content, identifier => $tok->identifier, parameters => $tok->parameters, }; $mtd->set_attribute($attr); last METHOD_TOKEN; } if ( ! $is_fragment ) { $mtd->set_linenumber($mtdstmt->line_number); $mtd->set_colnumber($mtdstmt->column_number); } return $mtd; } sub get_method_from_statement : PRIVATE { my ($self, $mdl, $mtdstmt) = @_; my $mtdnm = $mtdstmt->name(); return $mdl->exist_method($mtdnm) ? $mdl->get_method($mtdnm) : undef; } sub do_plugins_begin : PRIVATE { my ($self, $mdl, $ppi) = @_; PLUGIN: foreach my $p ( @{$plugins_of{ident $self}} ) { $p->begin($mdl, $ppi); } } sub do_plugins_start : PRIVATE { my ($self, $mdl, $ppi) = @_; PLUGIN: foreach my $p ( @{$plugins_of{ident $self}} ) { $p->start($mdl, $ppi); } } sub do_plugins_end : PRIVATE { my ($self, $mdl, $ppi) = @_; PLUGIN: foreach my $p ( @{$plugins_of{ident $self}} ) { $p->end($mdl, $ppi); } } } 1; __END__ plsense-0.3.4/lib/PlSense/ModuleBuilder/PPIBuilder/000077500000000000000000000000001260377356000220125ustar00rootroot00000000000000plsense-0.3.4/lib/PlSense/ModuleBuilder/PPIBuilder/IncludeStmt.pm000066400000000000000000000027271260377356000246130ustar00rootroot00000000000000package PlSense::ModuleBuilder::PPIBuilder::IncludeStmt; use strict; use warnings; use Class::Std; use Module::Pluggable instantiate => 'new', search_path => 'PlSense::Plugin::IncludeStmt'; use PlSense::Logger; use PlSense::Util; { my %plugins_of :ATTR(); sub BUILD { my ($class, $ident, $arg_ref) = @_; $plugins_of{$ident} = []; } sub START { my ($class, $ident, $arg_ref) = @_; my @plugins = $class->plugins(); PLUGIN: foreach my $p ( @plugins ) { push @{$plugins_of{$ident}}, $p; } } sub build { my ($self, $mdl, $stmt) = @_; my $mdlnm = $stmt->module or return; PLUGIN: foreach my $p ( @{$plugins_of{ident $self}} ) { $p->include_statement($mdl, $mdlnm, $stmt); } if ( $stmt->pragma ) { return; } if ( $mdl->exist_usingmdl($mdlnm) ) { return; } my $incmdl = mdlkeeper->get_module($mdlnm); if ( ! $incmdl ) { logger->warn("Not found module : $mdlnm"); return; } my $filepath = $incmdl->get_filepath; if ( ! $filepath || ! -f $filepath ) { logger->warn("Not exist module : $mdlnm"); mdlkeeper->remove_module($incmdl->get_name, $filepath, $incmdl->get_projectnm); return; } logger->debug("Found using module of [".$mdl->get_name."] : ".$incmdl->get_name); $mdl->push_usingmdl($incmdl); return; } } 1; __END__ plsense-0.3.4/lib/PlSense/ModuleBuilder/XrefBuilder.pm000066400000000000000000000105611260377356000226270ustar00rootroot00000000000000package PlSense::ModuleBuilder::XrefBuilder; use parent qw{ PlSense::ModuleBuilder }; use strict; use warnings; use Class::Std; use PlSense::Logger; use PlSense::Configure; use PlSense::Util; use PlSense::Symbol::Method; use PlSense::Symbol::Variable; { sub build { my ($self, $mdl) = @_; my $mdlnm = $mdl->get_name(); my $currpkg = ""; my $currmtd = ""; my $perl = get_config("perl"); my $libopt = get_config("lib-path") ? "-I'".get_config("lib-path")."'" : ""; my $cmdstr = $mdlnm eq "main" ? "'".$mdl->get_filepath."'" : "-e 'use $mdlnm'"; PARSE_XREF: foreach my $line ( qx{ $perl $libopt -MO=Xref $cmdstr 2>/dev/null } ) { chomp $line; if ( $line =~ m{ ^ \s+ Subroutine \s+ (.+) $ }xms ) { my @pkgtree = split m{ :: }xms, $1; my $mtdnm = pop @pkgtree || ""; if ( $mtdnm eq "(definitions)" ) { $currpkg = ""; $currmtd = ""; } elsif ( $mtdnm =~ m{ ^ [a-zA-Z_][a-zA-Z0-9_]* $ }xms ) { $currpkg = join "::", @pkgtree; $currmtd = $mtdnm; } else { $currmtd = ""; } } elsif ( $line =~ m{ ^ \s+ Package \s+ ([a-zA-Z_][a-zA-Z0-9_:]*) $ }xms ) { $currpkg = $1; } elsif ( $line =~ m{ ^ \s+ (\$|\@|\%|\&) ([a-zA-Z_][a-zA-Z_0-9]*) \s+ (.+) $ }xms ) { my ($idtype, $idvalue, $etcinfo) = ($1, $2, $3); if ( $currpkg eq $mdlnm ) { $self->build_parts($mdl, $currmtd, $idtype, $idvalue, $etcinfo); } } } } sub build_parts : PRIVATE { my ($self, $mdl, $mtdnm, $idtype, $idvalue, $etcinfo) = @_; my $mtd; if ( $mtdnm ne "" ) { my $reserved = $mtdnm eq uc($mtdnm) ? 1 : 0; my $publicly = $mtdnm !~ m{ ^ _ }xms && ! $reserved ? 1 : 0; $mtd = $mdl->exist_method($mtdnm) ? $mdl->get_method($mtdnm) : PlSense::Symbol::Method->new({ name => $mtdnm, module => $mdl, publicly => $publicly, importive => 1, reserved => $reserved, }); } if ( $idtype eq '&' ) { if ( ! $mdl->exist_method($idvalue) ) { my $reserved = $idvalue eq uc($idvalue) ? 1 : 0; my $publicly = $idvalue !~ m{ ^ _ }xms && ! $reserved ? 1 : 0; my $mtd = PlSense::Symbol::Method->new({ name => $idvalue, module => $mdl, publicly => $publicly, importive => 1, reserved => $reserved, }); } } elsif ( ! builtin->exist_variable($idtype.$idvalue) ) { my $varnm = $idtype.$idvalue; my $lexical = $etcinfo =~ m{ i }xms ? 1 : 0; my $var; if ( $lexical && $mtd ) { $var = $mtd->exist_variable($varnm) ? $mtd->get_variable($varnm) : PlSense::Symbol::Variable->new({ name => $varnm, belong => $mtd, importive => $lexical ? 0 : 1 }); $var->set_lexical($lexical); } else { $var = $mdl->exist_member($varnm) ? $mdl->get_member($varnm) : PlSense::Symbol::Variable->new({ name => $varnm, belong => $mdl, importive => $lexical ? 0 : 1 }); $var->set_lexical($lexical); } } } } 1; __END__ plsense-0.3.4/lib/PlSense/ModuleKeeper.pm000066400000000000000000000262711260377356000202460ustar00rootroot00000000000000package PlSense::ModuleKeeper; use parent qw{ PlSense::Cacheable }; use strict; use warnings; use Class::Std; use List::AllUtils qw{ uniq }; use Try::Tiny; use PlSense::Logger; use PlSense::Configure; { my %cache_of :ATTR( :default(undef) ); my %projcache_of :ATTR( :default(undef) ); my %moduleh_of :ATTR(); my %projmoduleh_of :ATTR(); my %current_local_is :ATTR(); sub START { my ($class, $ident, $arg_ref) = @_; $cache_of{$ident} = $class->new_cache('IModule'); $projcache_of{$ident} = $class->new_cache('Module.'.$class->get_project()); $class->reset; } sub setup_without_reload { my $self = shift; $self->update_project(); my $projnm = $self->get_project(); my $local = get_config("local"); $cache_of{ident $self}->set_namespace( $local ? "IModule.$projnm" : "IModule" ); $projcache_of{ident $self}->set_namespace("Module.$projnm"); $current_local_is{ident $self} = $local; } sub setup { my $self = shift; my $force = shift || 0; my $projnm = get_config("name"); if ( ! $force && $projnm eq $self->get_project() ) { logger->info("No need switch project data from [$projnm]"); return; } logger->info("Switch project data to [$projnm]"); my $local = get_config("local"); if ( $current_local_is{ident $self} || $local ) { $self->reset_installed_memory(); } $self->reset_project_memory(); $self->setup_without_reload(); # Loading is entrusted to server process return 1; } sub store_module { my ($self, $mdl) = @_; $self->store_module_sentinel($mdl); return; } sub load_module { my $self = shift; my $mdlnm = shift || ""; my $filepath = shift || ""; my $key = $self->get_cache_key($mdlnm, $filepath); return $self->load_module_sentinel($key); } sub remove_module { my $self = shift; my $mdlnm = shift || ""; my $filepath = shift || ""; my $projectnm = shift || ""; my $key = $self->get_cache_key($mdlnm, $filepath); if ( $projectnm ) { delete $projmoduleh_of{ident $self}->{$key}; try { $projcache_of{ident $self}->remove($key); } catch { $projcache_of{ident $self}->remove($key); }; } else { delete $moduleh_of{ident $self}->{$key}; try { $cache_of{ident $self}->remove($key); } catch { $cache_of{ident $self}->remove($key); }; } logger->info("Removed module info of [$mdlnm] in [$filepath]"); } sub remove_project_all_module { my ($self) = @_; $self->reset_project_memory(); try { $projcache_of{ident $self}->clear; } catch { $projcache_of{ident $self}->clear; }; logger->info("Removed all project module info of [".$projcache_of{ident $self}->get_namespace."]"); } sub remove_all_module { my ($self) = @_; $self->reset; try { $cache_of{ident $self}->clear; } catch { $cache_of{ident $self}->clear; }; try { $projcache_of{ident $self}->clear; } catch { $projcache_of{ident $self}->clear; }; logger->info("Removed all module info"); } sub reset { my $self = shift; $self->reset_installed_memory(); $self->reset_project_memory(); } sub get_module { my $self = shift; my $mdlnm = shift || ""; my $filepath = shift || ""; my $key = $self->get_cache_key($mdlnm, $filepath); return $projmoduleh_of{ident $self}->{$key} || $moduleh_of{ident $self}->{$key} || $self->load_module_sentinel($key); } sub get_project_module { my $self = shift; my $mdlnm = shift || ""; my $filepath = shift || ""; my $key = $self->get_cache_key($mdlnm, $filepath); return $projmoduleh_of{ident $self}->{$key} || $self->load_module_sentinel($key, 1); } sub get_installed_module { my $self = shift; my $mdlnm = shift || ""; my $filepath = shift || ""; my $key = $self->get_cache_key($mdlnm, $filepath); return $moduleh_of{ident $self}->{$key} || $self->load_module_sentinel($key, 0, 1); } sub get_module_with_best_effort { my $self = shift; my $mdlnm = shift || ""; my $filepath = shift || ""; my $key = $self->get_cache_key($mdlnm, $filepath); my $mdl = $projmoduleh_of{ident $self}->{$key} || $moduleh_of{ident $self}->{$key}; return $mdl && $mdl->is_initialized ? $mdl : $self->load_module_sentinel($key); } sub get_bundle_modules { my ($self, $filepath) = @_; my @ret = (); if ( ! -f $filepath ) { logger->error("Not exist file [$filepath]"); return @ret; } my $mainmdl = $self->get_module("main", $filepath) or return @ret; push @ret, $mainmdl; for my $i ( 1..$mainmdl->count_bundlemdl ) { push @ret, $mainmdl->get_bundlemdl($i); } return @ret; } sub get_packages { my ($self, $include_main) = @_; my @mdlkeys = uniq ( keys( %{$projmoduleh_of{ident $self}} ), keys( %{$moduleh_of{ident $self}} ) ); my @mdls = map { $projmoduleh_of{ident $self}->{$_} || $moduleh_of{ident $self}->{$_} } @mdlkeys; my @tmdls = $include_main ? @mdls : grep { $_->get_name ne "main" } @mdls; return sort { $a->get_name cmp $b->get_name || $a->get_filepath cmp $b->get_filepath } @tmdls; } sub get_built_modules { my ($self) = @_; return grep { $_->is_initialized } $self->get_packages; } sub describe_keep_value { my ($self) = @_; my @mdlkeys = ( keys( %{$projmoduleh_of{ident $self}} ), keys( %{$moduleh_of{ident $self}} ) ); return "Modules ... ".($#mdlkeys+1)."\n"; } sub reset_installed_memory : PRIVATE { my ($self) = @_; $moduleh_of{ident $self} = {}; return; } sub reset_project_memory : PRIVATE { my ($self) = @_; $projmoduleh_of{ident $self} = {}; return; } sub store_module_sentinel : PRIVATE { my ($self, $mdl) = @_; if ( ! $mdl || ! $mdl->isa("PlSense::Symbol::Module") ) { return; } my (@parents, @usingmdls, @bundlemdls); PARENT: for my $i ( 1..$mdl->count_parent ) { my $parent = $mdl->get_parent($i); push @parents, $parent->renew; } USINGMODULE: for my $i ( 1..$mdl->count_usingmdl ) { my $usingmdl = $mdl->get_usingmdl($i); push @usingmdls, $usingmdl->renew; } BUNDLEMODULE: for my $i ( 1..$mdl->count_bundlemdl ) { my $bundlemdl = $mdl->get_bundlemdl($i); push @bundlemdls, $bundlemdl->renew; } $mdl->reset_parent; $mdl->reset_usingmdl; $mdl->reset_bundlemdl; PARENT: foreach my $parent ( @parents ) { $mdl->push_parent($parent, 1); } USINGMODULE: foreach my $usingmdl ( @usingmdls ) { $mdl->push_usingmdl($usingmdl, 1); } BUNDLEMODULE: foreach my $bundlemdl ( @bundlemdls ) { $mdl->push_bundlemdl($bundlemdl, 1); } my $key = $self->get_cache_key($mdl->get_name, $mdl->get_filepath); if ( $mdl->get_projectnm ) { if ( ! $projmoduleh_of{ident $self}->{$key} ) { $projmoduleh_of{ident $self}->{$key} = $mdl; } try { $projcache_of{ident $self}->set($key, $mdl); } catch { $projcache_of{ident $self}->set($key, $mdl); }; } else { if ( ! $moduleh_of{ident $self}->{$key} ) { $moduleh_of{ident $self}->{$key} = $mdl; } try { $cache_of{ident $self}->set($key, $mdl); } catch { $cache_of{ident $self}->set($key, $mdl); }; } logger->debug("Store module : $key"); return; } sub load_module_sentinel : PRIVATE { my $self = shift; my $key = shift || ""; my $from_project = shift || 0; my $from_system = shift || 0; my $cachemdl; try { $cachemdl = $from_project ? $projcache_of{ident $self}->get($key) : $from_system ? $cache_of{ident $self}->get($key) : $projcache_of{ident $self}->get($key) || $cache_of{ident $self}->get($key); } catch { }; if ( ! $cachemdl || ! $cachemdl->isa("PlSense::Symbol::Module") ) { logger->warn("Failed load cached module data of $key"); return; } my $mdl = $cachemdl->get_projectnm ? $projmoduleh_of{ident $self}->{$key} : $moduleh_of{ident $self}->{$key}; if ( $mdl ) { $mdl->interchange_to($cachemdl); # logger->debug("Interchanged [".$mdl->get_name."] in [".$mdl->get_filepath."] belong [".$mdl->get_projectnm."]"); } else { if ( $cachemdl->get_projectnm ) { $projmoduleh_of{ident $self}->{$key} = $cachemdl; } else { $moduleh_of{ident $self}->{$key} = $cachemdl; } $mdl = $cachemdl; # logger->debug("Loaded [".$mdl->get_name."] in [".$mdl->get_filepath."] belong [".$mdl->get_projectnm."]"); } my (@parents, @usingmdls, @bundlemdls); PARENT: for my $i ( 1..$mdl->count_parent ) { my $parent = $mdl->get_parent($i); my $validmdl = $from_project ? $self->get_project_module($parent->get_name) || $self->get_installed_module($parent->get_name) : $self->get_module($parent->get_name); push @parents, $validmdl; } USINGMODULE: for my $i ( 1..$mdl->count_usingmdl ) { my $usingmdl = $mdl->get_usingmdl($i); my $validmdl = $from_project ? $self->get_project_module($usingmdl->get_name) || $self->get_installed_module($usingmdl->get_name) : $self->get_module($usingmdl->get_name); push @usingmdls, $validmdl; } BUNDLEMODULE: for my $i ( 1..$mdl->count_bundlemdl ) { my $bundlemdl = $mdl->get_bundlemdl($i); my $validmdl = $from_project ? $self->get_project_module($bundlemdl->get_name) || $self->get_installed_module($bundlemdl->get_name) : $self->get_module($bundlemdl->get_name); push @bundlemdls, $validmdl; } $mdl->reset_parent; $mdl->reset_usingmdl; $mdl->reset_bundlemdl; PARENT: foreach my $parent ( @parents ) { $mdl->push_parent($parent); } USINGMODULE: foreach my $usingmdl ( @usingmdls ) { $mdl->push_usingmdl($usingmdl); } BUNDLEMODULE: foreach my $bundlemdl ( @bundlemdls ) { $mdl->push_bundlemdl($bundlemdl); } return $mdl; } } 1; __END__ plsense-0.3.4/lib/PlSense/ModuleSrcUpdater.pm000066400000000000000000000070321260377356000211010ustar00rootroot00000000000000package PlSense::ModuleSrcUpdater; use strict; use warnings; use Class::Std; use PPI::Document; use PlSense::Logger; use PlSense::Util; use PlSense::Symbol::Module; { sub update_or_create_modules { my ($self, $filepath, $projectnm) = @_; my %foundmdl_is; if ( ! -f $filepath ) { logger->error("Not exist file[$filepath]"); return (); } my @attr = stat $filepath; my $lastmodified = $attr[9]; my $currmdl = mdlkeeper->get_module("main", $filepath); if ( ! $currmdl ) { $currmdl = PlSense::Symbol::Module->new({ name => "main", filepath => $filepath, projectnm => $projectnm, lastmodified => $lastmodified, linenumber => 1, colnumber => 1, }); logger->notice("New module [".$currmdl->get_name."] in [".$currmdl->get_filepath."] belong [".$currmdl->get_projectnm."]"); mdlkeeper->store_module($currmdl); } $currmdl->reset_all($lastmodified); $foundmdl_is{$currmdl->get_name} = $currmdl; logger->notice("Start get PPI::Document of module from [".$filepath."]"); my $doc = PPI::Document->new( $filepath, readonly => 1 ); if ( ! $doc ) { logger->warn("Can't get PPI::Document from [$filepath]"); return ($currmdl); } my $mainmdl = $currmdl; TOPSTMT: foreach my $e ( $doc->children ) { # Get current package if ( $e->isa("PPI::Statement::Package") ) { my $mdlnm = "".$e->namespace.""; if ( $mdlnm eq "main" ) { $currmdl = $mainmdl; } elsif ( ! exists $foundmdl_is{$mdlnm} ) { my $mdl = mdlkeeper->get_module($mdlnm); if ( ! $mdl ) { $mdl = PlSense::Symbol::Module->new({ name => $mdlnm, filepath => $filepath, projectnm => $projectnm, lastmodified => $lastmodified }); logger->notice("New module [".$mdl->get_name."] in [".$mdl->get_filepath."] belong [".$mdl->get_projectnm."]"); mdlkeeper->store_module($mdl); } $mdl->reset_all($lastmodified); $foundmdl_is{$mdlnm} = $mdl; logger->debug("Found bundle module of [".$mainmdl->get_name."] : ".$mdl->get_name); $mainmdl->push_bundlemdl($mdl); } $currmdl = $foundmdl_is{$mdlnm}; $currmdl->set_linenumber($e->line_number); $currmdl->set_colnumber($e->column_number); } elsif ( $currmdl && $e->isa("PPI::Element") ) { my $currdoc = $currmdl->get_source; if ( ! $currdoc ) { $currdoc = PPI::Document->new; $currmdl->set_source($currdoc); } if ( ! $currdoc->add_element($e->clone) ) { logger->error("Failed add source to ".$currmdl->get_name); } } } return values %foundmdl_is; } } 1; __END__ plsense-0.3.4/lib/PlSense/Plugin/000077500000000000000000000000001260377356000165555ustar00rootroot00000000000000plsense-0.3.4/lib/PlSense/Plugin/AddressFinder.pm000066400000000000000000000010611260377356000216260ustar00rootroot00000000000000package PlSense::Plugin::AddressFinder; use strict; use warnings; use Class::Std; { my %with_build_is :ATTR( :init_arg ); sub with_build : RESTRICTED { my ($self) = @_; return $with_build_is{ident $self} ? 1 : 0; } my %mediator_of :ATTR( :init_arg ); sub get_mediator : RESTRICTED { my ($self) = @_; return $mediator_of{ident $self}; } sub find_address { my ($self, @tokens) = @_; return; } sub find_address_or_entity { my ($self, @tokens) = @_; return; } } 1; __END__ plsense-0.3.4/lib/PlSense/Plugin/AddressFinder/000077500000000000000000000000001260377356000212725ustar00rootroot00000000000000plsense-0.3.4/lib/PlSense/Plugin/AddressFinder/Builtin.pm000066400000000000000000000014101260377356000232320ustar00rootroot00000000000000package PlSense::Plugin::AddressFinder::Builtin; use parent qw{ PlSense::Plugin::AddressFinder }; use strict; use warnings; use Class::Std; { sub get_builtin_name { my ($self) = @_; return ""; } sub find_address { my ($self, @tokens) = @_; return; } sub find_address_or_entity { my ($self, @tokens) = @_; return; } sub get_argument_tokens { my ($self, @tokens) = @_; my $tok = shift @tokens or return (); if ( ! $tok->isa("PPI::Structure::List") ) { return ($tok, @tokens); } my @children = $tok->children; $tok = shift @children or return (); if ( ! $tok->isa("PPI::Statement") ) { return (); } return $tok->children; } } 1; __END__ plsense-0.3.4/lib/PlSense/Plugin/AddressFinder/Builtin/000077500000000000000000000000001260377356000227005ustar00rootroot00000000000000plsense-0.3.4/lib/PlSense/Plugin/AddressFinder/Builtin/Bless.pm000066400000000000000000000021761260377356000243140ustar00rootroot00000000000000package PlSense::Plugin::AddressFinder::Builtin::Bless; use parent qw{ PlSense::Plugin::AddressFinder::Builtin }; use strict; use warnings; use Class::Std; use PlSense::Logger; use PlSense::Util; { sub get_builtin_name { my ($self) = @_; return "bless"; } sub find_address { my ($self, @tokens) = @_; return $self->find_something(@tokens); } sub find_address_or_entity { my ($self, @tokens) = @_; return $self->find_something(@tokens); } sub find_something : PRIVATE { my ($self, @tokens) = @_; if ( ! $self->with_build ) { return; } my $mediator = $self->get_mediator; my $value = $mediator->find_address_or_entity(@tokens) or return; my $vtype = eval { $value->get_type } || ""; if ( $vtype ) { if ( $vtype ne 'reference' ) { return; } $value = $value->get_entity; } else { $value .= ".R"; } my $mdl = $mediator->get_currentmodule; substkeeper->add_substitute('&'.$mdl->get_name.'::BLESS.R', $value, 1); return; } } 1; __END__ plsense-0.3.4/lib/PlSense/Plugin/AddressFinder/Builtin/Eval.pm000066400000000000000000000017761260377356000241400ustar00rootroot00000000000000package PlSense::Plugin::AddressFinder::Builtin::Eval; use parent qw{ PlSense::Plugin::AddressFinder::Builtin }; use strict; use warnings; use Class::Std; use PlSense::Logger; { sub get_builtin_name { my ($self) = @_; return "eval"; } sub find_address { my ($self, @tokens) = @_; return $self->find_something(1, @tokens); } sub find_address_or_entity { my ($self, @tokens) = @_; return $self->find_something(0, @tokens); } sub find_something : PRIVATE { my ($self, $is_addr, @tokens) = @_; my $e = shift @tokens or return; if ( ! $e->isa("PPI::Structure::Block") ) { return; } my @children = $e->children; my $laststmt = pop @children or return; if ( ! $laststmt->isa("PPI::Statement") ) { return; } return $is_addr ? $self->get_mediator->find_address($laststmt->children) : $self->get_mediator->find_address_or_entity($laststmt->children); } } 1; __END__ plsense-0.3.4/lib/PlSense/Plugin/AddressFinder/Builtin/First.pm000066400000000000000000000023631260377356000243310ustar00rootroot00000000000000package PlSense::Plugin::AddressFinder::Builtin::First; use parent qw{ PlSense::Plugin::AddressFinder::Builtin }; use strict; use warnings; use Class::Std; use PlSense::Logger; { sub get_builtin_name { my ($self) = @_; return "first"; } sub find_address { my ($self, @tokens) = @_; return $self->find_something(1, @tokens); } sub find_address_or_entity { my ($self, @tokens) = @_; return $self->find_something(0, @tokens); } sub find_something : PRIVATE { my ($self, $is_addr, @tokens) = @_; my $tok = shift @tokens or return; if ( ! $tok->isa("PPI::Structure::Block") ) { return; } my $value = $self->get_mediator->find_address_or_entity(@tokens) or return; if ( eval { $value->isa("PlSense::Entity") } ) { if ( ! $value->isa("PlSense::Entity::Array") ) { return; } my $el = $value->get_element; if ( $el ) { if ( $is_addr && eval { $el->isa("PlSense::Entity") } ) { return; } return $el; } if ( $value->count_address > 0 ) { return $value->get_address(1).".A"; } } else { return $value.".A"; } } } 1; __END__ plsense-0.3.4/lib/PlSense/Plugin/AddressFinder/Builtin/Grep.pm000066400000000000000000000020201260377356000241250ustar00rootroot00000000000000package PlSense::Plugin::AddressFinder::Builtin::Grep; use parent qw{ PlSense::Plugin::AddressFinder::Builtin }; use strict; use warnings; use Class::Std; use PlSense::Logger; { sub get_builtin_name { my ($self) = @_; return "grep"; } sub find_address { my ($self, @tokens) = @_; return $self->find_something(@tokens); } sub find_address_or_entity { my ($self, @tokens) = @_; return $self->find_something(@tokens); } sub find_something : PRIVATE { my ($self, @tokens) = @_; my $tok = shift @tokens or return; if ( $tok->isa("PPI::Structure::Block") ) { return $self->get_mediator->find_address(@tokens); } elsif ( $tok->isa("PPI::Token::Regexp::Match") ) { $tok = shift @tokens or return; if ( ! $tok->isa("PPI::Token::Operator") ) { return; } return $self->get_mediator->find_address(@tokens); } else { return; } } } 1; __END__ plsense-0.3.4/lib/PlSense/Plugin/AddressFinder/Builtin/Pop.pm000066400000000000000000000012511260377356000237730ustar00rootroot00000000000000package PlSense::Plugin::AddressFinder::Builtin::Pop; use parent qw{ PlSense::Plugin::AddressFinder::Builtin }; use strict; use warnings; use Class::Std; use PlSense::Logger; { sub get_builtin_name { my ($self) = @_; return "pop"; } sub find_address { my ($self, @tokens) = @_; return $self->find_something(@tokens); } sub find_address_or_entity { my ($self, @tokens) = @_; return $self->find_something(@tokens); } sub find_something : PRIVATE { my ($self, @tokens) = @_; my $addr = $self->get_mediator->find_address(@tokens) or return; return $addr.".A"; } } 1; __END__ plsense-0.3.4/lib/PlSense/Plugin/AddressFinder/Builtin/Push.pm000066400000000000000000000023271260377356000241610ustar00rootroot00000000000000package PlSense::Plugin::AddressFinder::Builtin::Push; use parent qw{ PlSense::Plugin::AddressFinder::Builtin }; use strict; use warnings; use Class::Std; use PlSense::Logger; use PlSense::Util; { sub get_builtin_name { my ($self) = @_; return "push"; } sub find_address { my ($self, @tokens) = @_; return $self->find_something(@tokens); } sub find_address_or_entity { my ($self, @tokens) = @_; return $self->find_something(@tokens); } sub find_something : PRIVATE { my ($self, @tokens) = @_; if ( ! $self->with_build ) { return; } my $mediator = $self->get_mediator; my ($addr, @parts); TOKEN: while ( my $e = shift @tokens ) { if ( $e->isa("PPI::Token::Operator") && $e->content eq "," ) { $addr = $mediator->find_address(@parts) or return; last TOKEN; } else { push @parts, $e; } } if ( ! $addr || $#tokens < 0 ) { return; } my $value = $mediator->find_address_or_entity(@tokens) or return; substkeeper->add_substitute($addr.".A", $value); return; } } 1; __END__ plsense-0.3.4/lib/PlSense/Plugin/AddressFinder/Builtin/Reverse.pm000066400000000000000000000010311260377356000246440ustar00rootroot00000000000000package PlSense::Plugin::AddressFinder::Builtin::Reverse; use parent qw{ PlSense::Plugin::AddressFinder::Builtin }; use strict; use warnings; use Class::Std; use PlSense::Logger; { sub get_builtin_name { my ($self) = @_; return "reverse"; } sub find_address { my ($self, @tokens) = @_; return $self->get_mediator->find_address(@tokens); } sub find_address_or_entity { my ($self, @tokens) = @_; return $self->get_mediator->find_address(@tokens); } } 1; __END__ plsense-0.3.4/lib/PlSense/Plugin/AddressFinder/Builtin/Shift.pm000066400000000000000000000030661260377356000243200ustar00rootroot00000000000000package PlSense::Plugin::AddressFinder::Builtin::Shift; use parent qw{ PlSense::Plugin::AddressFinder::Builtin }; use strict; use warnings; use Class::Std; use PlSense::Logger; { sub get_builtin_name { my ($self) = @_; return "shift"; } sub find_address { my ($self, @tokens) = @_; return $self->find_something(1, @tokens); } sub find_address_or_entity { my ($self, @tokens) = @_; return $self->find_something(0, @tokens); } sub find_something : PRIVATE { my ($self, $is_addr, @tokens) = @_; my $mediator = $self->get_mediator; my $e = shift @tokens; if ( ! $e || ( $e->isa("PPI::Token::Magic") && $e->content eq '@_' ) ) { my $mtd = $mediator->get_currentmethod or return; $mediator->forward_methodindex; return $mtd->get_fullnm."[".$mediator->get_methodindex."]"; } else { my $value = $mediator->find_address_or_entity($e, @tokens) or return; if ( eval { $value->isa("PlSense::Entity") } ) { if ( ! $value->isa("PlSense::Entity::Array") ) { return; } my $el = $value->get_element; if ( $el ) { if ( $is_addr && eval { $el->isa("PlSense::Entity") } ) { return; } return $el; } if ( $value->count_address > 0 ) { return $value->get_address(1).".A"; } } else { return $value.".A"; } } return; } } 1; __END__ plsense-0.3.4/lib/PlSense/Plugin/AddressFinder/Builtin/Sort.pm000066400000000000000000000013751260377356000241730ustar00rootroot00000000000000package PlSense::Plugin::AddressFinder::Builtin::Sort; use parent qw{ PlSense::Plugin::AddressFinder::Builtin }; use strict; use warnings; use Class::Std; use PlSense::Logger; { sub get_builtin_name { my ($self) = @_; return "sort"; } sub find_address { my ($self, @tokens) = @_; return $self->find_something(@tokens); } sub find_address_or_entity { my ($self, @tokens) = @_; return $self->find_something(@tokens); } sub find_something : PRIVATE { my ($self, @tokens) = @_; if ( $#tokens >= 0 && $tokens[0]->isa("PPI::Structure::Block") ) { my $tok = shift @tokens; } return $self->get_mediator->find_address(@tokens); } } 1; __END__ plsense-0.3.4/lib/PlSense/Plugin/AddressFinder/Builtin/Undef.pm000066400000000000000000000006471260377356000243060ustar00rootroot00000000000000package PlSense::Plugin::AddressFinder::Builtin::Undef; use parent qw{ PlSense::Plugin::AddressFinder::Builtin }; use strict; use warnings; use Class::Std; use PlSense::Logger; use PlSense::Entity::Null; { sub get_builtin_name { my ($self) = @_; return "undef"; } sub find_address_or_entity { my ($self, @tokens) = @_; return PlSense::Entity::Null->new(); } } 1; __END__ plsense-0.3.4/lib/PlSense/Plugin/AddressFinder/Builtin/Unshift.pm000066400000000000000000000023351260377356000246610ustar00rootroot00000000000000package PlSense::Plugin::AddressFinder::Builtin::Unshift; use parent qw{ PlSense::Plugin::AddressFinder::Builtin }; use strict; use warnings; use Class::Std; use PlSense::Logger; use PlSense::Util; { sub get_builtin_name { my ($self) = @_; return "unshift"; } sub find_address { my ($self, @tokens) = @_; return $self->find_something(@tokens); } sub find_address_or_entity { my ($self, @tokens) = @_; return $self->find_something(@tokens); } sub find_something : PRIVATE { my ($self, @tokens) = @_; if ( ! $self->with_build ) { return; } my $mediator = $self->get_mediator; my ($addr, @parts); TOKEN: while ( my $e = shift @tokens ) { if ( $e->isa("PPI::Token::Operator") && $e->content eq "," ) { $addr = $mediator->find_address(@parts) or return; last TOKEN; } else { push @parts, $e; } } if ( ! $addr || $#tokens < 0 ) { return; } my $value = $mediator->find_address_or_entity(@tokens) or return; substkeeper->add_substitute($addr.".A", $value); return; } } 1; __END__ plsense-0.3.4/lib/PlSense/Plugin/AddressFinder/Builtin/Values.pm000066400000000000000000000010761260377356000245010ustar00rootroot00000000000000package PlSense::Plugin::AddressFinder::Builtin::Values; use parent qw{ PlSense::Plugin::AddressFinder::Builtin }; use strict; use warnings; use Class::Std; use PlSense::Logger; use PlSense::Entity::Array; { sub get_builtin_name { my ($self) = @_; return "values"; } sub find_address_or_entity { my ($self, @tokens) = @_; my $addr = $self->get_mediator->find_address(@tokens) or return; my $entity = PlSense::Entity::Array->new(); $entity->set_element($addr.".H:*"); return $entity; } } 1; __END__ plsense-0.3.4/lib/PlSense/Plugin/AddressFinder/Ext.pm000066400000000000000000000014031260377356000223660ustar00rootroot00000000000000package PlSense::Plugin::AddressFinder::Ext; use parent qw{ PlSense::Plugin::AddressFinder }; use strict; use warnings; use Class::Std; { sub get_method_name { my ($self) = @_; return ""; } sub find_address { my ($self, @tokens) = @_; return; } sub find_address_or_entity { my ($self, @tokens) = @_; return; } sub get_argument_tokens { my ($self, @tokens) = @_; my $tok = shift @tokens or return (); if ( ! $tok->isa("PPI::Structure::List") ) { return ($tok, @tokens); } my @children = $tok->children; $tok = shift @children or return (); if ( ! $tok->isa("PPI::Statement") ) { return (); } return $tok->children; } } 1; __END__ plsense-0.3.4/lib/PlSense/Plugin/AddressFinder/Ext/000077500000000000000000000000001260377356000220325ustar00rootroot00000000000000plsense-0.3.4/lib/PlSense/Plugin/AddressFinder/Ext/First.pm000066400000000000000000000026361260377356000234660ustar00rootroot00000000000000package PlSense::Plugin::AddressFinder::Ext::First; use parent qw{ PlSense::Plugin::AddressFinder::Ext }; use strict; use warnings; use Class::Std; use PlSense::Logger; { sub get_method_name { my ($self) = @_; return "first"; } sub find_address { my ($self, @tokens) = @_; return $self->find_something(1, @tokens); } sub find_address_or_entity { my ($self, @tokens) = @_; return $self->find_something(0, @tokens); } sub find_something : PRIVATE { my ($self, $is_addr, @tokens) = @_; my $mdl = $self->get_mediator->get_currentmodule; if ( ! $mdl->exist_usingmdl("List::Util") && ! $mdl->exist_usingmdl("List::AllUtils") ) { return; } my $tok = shift @tokens or return; if ( ! $tok->isa("PPI::Structure::Block") ) { return; } my $value = $self->get_mediator->find_address_or_entity(@tokens) or return; if ( eval { $value->isa("PlSense::Entity") } ) { if ( ! $value->isa("PlSense::Entity::Array") ) { return; } my $el = $value->get_element; if ( $el ) { if ( $is_addr && eval { $el->isa("PlSense::Entity") } ) { return; } return $el; } if ( $value->count_address > 0 ) { return $value->get_address(1).".A"; } } else { return $value.".A"; } } } 1; __END__ plsense-0.3.4/lib/PlSense/Plugin/AddressFinder/Ext/Uniq.pm000066400000000000000000000014631260377356000233100ustar00rootroot00000000000000package PlSense::Plugin::AddressFinder::Ext::Uniq; use parent qw{ PlSense::Plugin::AddressFinder::Ext }; use strict; use warnings; use Class::Std; use PlSense::Logger; { sub get_method_name { my ($self) = @_; return "uniq"; } sub find_address { my ($self, @tokens) = @_; return $self->find_something(@tokens); } sub find_address_or_entity { my ($self, @tokens) = @_; return $self->find_something(@tokens); } sub find_something : PRIVATE { my ($self, @tokens) = @_; my $mdl = $self->get_mediator->get_currentmodule; if ( ! $mdl->exist_usingmdl("List::MoreUtils") && ! $mdl->exist_usingmdl("List::AllUtils") ) { return; } return $self->get_mediator->find_address(@tokens); } } 1; __END__ plsense-0.3.4/lib/PlSense/Plugin/CodeAssistant.pm000066400000000000000000000040461260377356000216630ustar00rootroot00000000000000package PlSense::Plugin::CodeAssistant; use strict; use warnings; use Class::Std; use PlSense::Logger; use PlSense::Util; { my %input_of :ATTR( :default('') ); sub set_input { my ($self, $input) = @_; $input_of{ident $self} = $input; } sub get_input : RESTRICTED { my ($self) = @_; return $input_of{ident $self}; } my %candidates_of :ATTR( :default(undef) ); my %lasth_of :ATTR( :default(undef) ); sub push_candidate : RESTRICTED { my ($self, $candidate, $instance) = @_; my $input = quotemeta($self->get_input); if ( $input ne "" && $candidate !~ m{ ^ $input }xms ) { return; } push @{$candidates_of{ident $self}}, $candidate; $lasth_of{ident $self}->{$candidate} = $instance; logger->info("Push candidate : $candidate"); } sub count_candidate { my ($self) = @_; return $#{$candidates_of{ident $self}} + 1; } sub get_candidate { my ($self, $index) = @_; if ( ! $index || $index !~ m{ ^\d+$ }xms ) { logger->warn("Not Integer"); return; } if ( $index < 1 || $index > $#{$candidates_of{ident $self}} + 1 ) { logger->warn("Out of Index"); return; } return $candidates_of{ident $self}->[$index - 1]; } sub init_candidate { my $self = shift; $candidates_of{ident $self} = []; } sub get_last_candidate_instance { my ($self, $candidate) = @_; if ( ! $candidate || ! exists $lasth_of{ident $self}->{$candidate} ) { return; } return $lasth_of{ident $self}->{$candidate}; } sub init_last_candidate_instance { my $self = shift; $lasth_of{ident $self} = {}; } sub BUILD { my ($class, $ident, $arg_ref) = @_; $candidates_of{$ident} = []; $class->init_last_candidate_instance; } sub is_valid_context { my ($self, $code, $tok) = @_; return 0; } sub is_only_valid_context { my ($self, $code, $tok) = @_; return 0; } } 1; __END__ plsense-0.3.4/lib/PlSense/Plugin/CodeAssistant/000077500000000000000000000000001260377356000213215ustar00rootroot00000000000000plsense-0.3.4/lib/PlSense/Plugin/CodeAssistant/ExplicitMethod.pm000066400000000000000000000016621260377356000246060ustar00rootroot00000000000000package PlSense::Plugin::CodeAssistant::ExplicitMethod; use parent qw{ PlSense::Plugin::CodeAssistant }; use strict; use warnings; use Class::Std; use PlSense::Logger; use PlSense::Util; { sub is_only_valid_context { my ($self, $code, $tok) = @_; if ( $code !~ m{ [^\$&] & ([a-zA-Z0-9_:]+) \z }xms ) { return; } my $input = $1; logger->info("Match context : input[$input]"); $self->set_input($input); my $currmdl = addrfinder->get_currentmodule; logger->notice("Found explicit method in ".$currmdl->get_fullnm); METHOD: foreach my $mtd ( $currmdl->get_any_original_methods, builtin->get_methods ) { $self->push_candidate($mtd->get_name, $mtd); } EXT_METHOD: foreach my $mtd ( $currmdl->get_external_methods ) { $self->push_candidate(substr($mtd->get_fullnm, 1), $mtd); } return 1; } } 1; __END__ plsense-0.3.4/lib/PlSense/Plugin/CodeAssistant/HashMember.pm000066400000000000000000000060041260377356000236720ustar00rootroot00000000000000package PlSense::Plugin::CodeAssistant::HashMember; use parent qw{ PlSense::Plugin::CodeAssistant }; use strict; use warnings; use Class::Std; use List::AllUtils qw{ uniq }; use PlSense::Logger; use PlSense::Util; { sub is_only_valid_context { my ($self, $code, $tok) = @_; my $input = ""; my $is_ref = 0; if ( $code =~ m{ -> \{ \s* ["']? ([a-zA-Z0-9_\-]*) \z }xms ) { $input = $1; $is_ref = 1; } elsif ( $code =~ m{ \{ \s* ["']? ([a-zA-Z0-9_\-]*) \z }xms ) { $input = $1; } else { return; } my $stmt; if ( ! $input ) { $tok = $tok->parent or return; $stmt = $tok->parent or return; } else { if ( ! $tok ) { return; } $tok = $tok->parent or return; $tok = $tok->parent or return; $stmt = $tok->parent or return; } $self->set_input($input); logger->info("Match context : input[$input] is_ref[$is_ref]"); my @tokens = $self->get_valid_tokens($stmt); if ( $#tokens < 0 ) { return; } my $addr = addrfinder->find_address(@tokens); if ( ! $addr ) { logger->info("Not found address in current context"); return 1; } if ( $is_ref ) { $addr .= ".R"; } $self->push_candidate_by_resolve($addr); $self->push_candidate_by_match($addr); return 1; } sub get_valid_tokens : PRIVATE { my ($self, $stmt) = @_; my @ret; my @children = $stmt->children; pop @children; PRE_TOKEN: while ( my $tok = pop @children ) { if ( $tok->isa("PPI::Token::Whitespace") ) { last PRE_TOKEN; } unshift @ret, $tok; } return @ret; } sub push_candidate_by_resolve : PRIVATE { my ($self, $addr) = @_; logger->debug("Try push candidate by resolve : $addr"); my $entity = addrrouter->resolve_address($addr); if ( ! $entity || ! $entity->isa("PlSense::Entity::Hash") ) { logger->info("Not hash entity in current context"); return; } logger->notice("Found hash member in $addr"); MEMBER: foreach my $key ( $entity->keys_member ) { if ( $key eq '*' ) { next MEMBER; } $entity->set_membernm($key); my $value = $entity->get_member; $self->push_candidate($key, $value); } return; } sub push_candidate_by_match : PRIVATE { my ($self, $addr) = @_; my @values = ($addr, addrrouter->resolve_anything($addr)); @values = uniq grep { $_ && ! eval { $_->isa("PlSense::Entity") } } @values; VALUE: foreach my $value ( @values ) { logger->debug("Try push candidate by match : $value"); foreach my $m ( addrrouter->get_hash_members($value) ) { $self->push_candidate($m); } } return; } } 1; __END__ plsense-0.3.4/lib/PlSense/Plugin/CodeAssistant/InstanceMethod.pm000066400000000000000000000041221260377356000245630ustar00rootroot00000000000000package PlSense::Plugin::CodeAssistant::InstanceMethod; use parent qw{ PlSense::Plugin::CodeAssistant }; use strict; use warnings; use Class::Std; use PlSense::Logger; use PlSense::Util; { sub is_only_valid_context { my ($self, $code, $tok) = @_; my $input = ""; if ( $tok && $tok->isa("PPI::Token::Word") ) { $input = "".$tok->content.""; $tok = $tok->previous_sibling; } if ( ! $tok || ! $tok->isa("PPI::Token::Operator") || $tok->content ne '->' ) { return; } my @tokens = $self->get_valid_tokens($tok); my $addr = addrfinder->find_address(@tokens) or return; $self->set_input($input); logger->info("Match context : input[$input] addr[$addr]"); my $entity = addrrouter->resolve_address($addr); if ( ! $entity || ! $entity->isa("PlSense::Entity::Instance") ) { logger->info("Can't get instance entity from [$addr]"); return 1; } my $mdl = mdlkeeper->get_module( $entity->get_modulenm ); if ( ! $mdl ) { logger->info("Can't get module of [".$entity->get_modulenm."]"); return 1; } logger->notice("Found instance method of [".$mdl->get_name."]"); my $currmdl = addrfinder->get_currentmodule; INSTANCE_METHOD: foreach my $mtd ( $mdl->get_instance_methods($currmdl) ) { $self->push_candidate($mtd->get_name, $mtd); } if ( $currmdl && $currmdl->get_name eq $mdl->get_name ) { INHERIT_METHOD: foreach my $mtd ( $mdl->get_inherit_methods ) { $self->push_candidate("SUPER::".$mtd->get_name, $mtd); } } $self->push_candidate("isa"); $self->push_candidate("can"); return 1; } sub get_valid_tokens : PRIVATE { my ($self, $tok) = @_; my @ret; PRE_TOKEN: while ( $tok = $tok->previous_sibling ) { if ( $tok->isa("PPI::Token::Whitespace") ) { last PRE_TOKEN; } unshift @ret, $tok; } return @ret; } } 1; __END__ plsense-0.3.4/lib/PlSense/Plugin/CodeAssistant/Method.pm000066400000000000000000000027551260377356000231100ustar00rootroot00000000000000package PlSense::Plugin::CodeAssistant::Method; use parent qw{ PlSense::Plugin::CodeAssistant }; use strict; use warnings; use Class::Std; use PlSense::Logger; use PlSense::Util; { sub is_valid_context { my ($self, $code, $tok) = @_; my $input = ""; if ( $code =~ m{ ([a-zA-Z0-9_:]+) \s+ ([a-zA-Z0-9_:]+) \z }xms ) { my $preword = $1; $input = $2; if ( $preword eq "package" ) { return; } if ( $preword eq "use" ) { return; } if ( $preword eq "require" ) { return; } if ( $preword eq "sub" ) { return; } if ( $preword eq "my" ) { return; } if ( $preword eq "our" ) { return; } if ( $preword eq "local" ) { return; } } elsif ( $code =~ m{ (?:\s|^|;|,|\}|\{|\[|\(|=>|\.) \s* ([a-zA-Z0-9_:]+) \z }xms ) { $input = $1; } else { return; } logger->info("Match context : input[$input]"); $self->set_input($input); my $currmdl = addrfinder->get_currentmodule(); logger->notice("Found method in ".$currmdl->get_fullnm); METHOD: foreach my $mtd ( $currmdl->get_any_original_methods, builtin->get_methods ) { $self->push_candidate($mtd->get_name, $mtd); } EXT_METHOD: foreach my $mtd ( $currmdl->get_external_methods ) { $self->push_candidate(substr($mtd->get_fullnm, 1), $mtd); } return 1; } } 1; __END__ plsense-0.3.4/lib/PlSense/Plugin/CodeAssistant/MethodArgument.pm000066400000000000000000000135441260377356000246110ustar00rootroot00000000000000package PlSense::Plugin::CodeAssistant::MethodArgument; use parent qw{ PlSense::Plugin::CodeAssistant }; use strict; use warnings; use Class::Std; use List::AllUtils qw{ uniq }; use PlSense::Logger; use PlSense::Util; { sub is_valid_context { my ($self, $code, $tok) = @_; my $input = ""; if ( $tok && $tok->isa("PPI::Token::Word") ) { $input = "".$tok->content.""; $tok = $tok->parent or return; if ( ! $tok->isa("PPI::Statement") ) { return; } $tok = $tok->parent or return; if ( ! $tok->isa("PPI::Structure::Block") && ! $tok->isa("PPI::Structure::Constructor") && ! $tok->isa("PPI::Structure::List") ) { return; } } my $bracetok = $self->get_brace_token($tok) or return; my @tokens = $bracetok->children; my $rootstmt = pop @tokens or return; if ( ! $rootstmt->isa("PPI::Statement") ) { return; } $self->set_input($input); logger->info("Match context : input[$input]"); @tokens = $self->get_valid_tokens($bracetok); my $rootaddr = addrfinder->find_address(@tokens); if ( ! $rootaddr ) { logger->info("Not found address in current context"); return 1; } my $e = $bracetok->previous_sibling; $e = $e ? $e->previous_sibling : undef; my $objective = $e && $e->isa("PPI::Token::Operator") && $e->content eq '->' ? 1 : 0; @tokens = $rootstmt->children; my $idx = grep { $_->isa("PPI::Token::Operator") && $_->content eq ',' } @tokens; $idx = $objective ? $idx+2 : $idx+1; $rootaddr .= "[".$idx."]"; my @rrootaddrs = addrrouter->get_reverse_route($rootaddr); if ( $#rrootaddrs >= 0 ) { $rootaddr = shift @rrootaddrs; } my $addr = $self->get_current_address($rootaddr, $rootstmt); logger->notice("Found method argument of $addr"); $self->push_candidate_by_resolve($addr); $self->push_candidate_by_match($addr); return 1; } sub get_brace_token : PRIVATE { my ($self, $tok) = @_; PARENT: while ( $tok ) { if ( $tok->isa("PPI::Structure::List") ) { my $pretok = $tok->previous_sibling or return; if ( $pretok->isa("PPI::Token::Word") ) { return $tok; } } $tok = $tok->parent; } return; } sub get_valid_tokens : PRIVATE { my ($self, $tok) = @_; my @ret; PRE_TOKEN: while ( $tok = $tok->previous_sibling ) { if ( $tok->isa("PPI::Token::Whitespace") ) { last PRE_TOKEN; } unshift @ret, $tok; } return @ret; } sub get_current_address : PRIVATE { my ($self, $addr, $rootstmt) = @_; my $nextstmt = $rootstmt; NEST: while ( $nextstmt && $nextstmt->isa("PPI::Statement") ) { $addr = $self->build_hash_member_address($addr, $nextstmt); my @tokens = $nextstmt->children; my $e = pop @tokens or last NEST; my $is_ref = 0; my $is_hash = 0; if ( $e->isa("PPI::Structure::Block") ) { $is_ref = 1; $is_hash = 1; } elsif ( $e->isa("PPI::Structure::List") ) { } elsif ( $e->isa("PPI::Structure::Constructor") ) { $is_ref = 1; my $value = "".$e->content.""; if ( $value =~ m{ \A \{ }xms ) { $is_hash = 1; } elsif ( $value =~ m{ \A \[ }xms ) { } else { last NEST; } } else { last NEST; } if ( $is_ref ) { $addr .= ".R"; } if ( $is_hash ) { $addr = $self->build_hash_member_address($addr, $e); } else { $addr .= ".A"; } @tokens = $e->children; $nextstmt = pop @tokens; } return $addr; } sub build_hash_member_address : PRIVATE { my ($self, $addr, $tok) = @_; my $pretok = $tok->previous_sibling or return $addr; if ( $pretok->isa("PPI::Token::Whitespace") ) { $pretok = $pretok->previous_sibling; } if ( ! $pretok || $pretok->isa("PPI::Token::Operator") ) { return $addr; } $pretok = $pretok->previous_sibling or return $addr; if ( $pretok->isa("PPI::Token::Whitespace") ) { $pretok = $pretok->previous_sibling; } if ( ! $pretok || ! $pretok->isa("PPI::Token::Word") ) { return $addr; } return $addr.".H:".$pretok->content; } sub push_candidate_by_resolve : PRIVATE { my ($self, $addr) = @_; logger->debug("Try push candidate by resolve : $addr"); my $entity = addrrouter->resolve_address($addr); if ( ! $entity || ! $entity->isa("PlSense::Entity::Hash") ) { logger->info("Not hash entity in current context"); return; } logger->notice("Found hash member in $addr"); MEMBER: foreach my $key ( $entity->keys_member ) { if ( $key eq '*' ) { next MEMBER; } $entity->set_membernm($key); my $value = $entity->get_member; $self->push_candidate($key, $value); } return; } sub push_candidate_by_match : PRIVATE { my ($self, $addr) = @_; my @values = ($addr, addrrouter->resolve_anything($addr)); @values = uniq grep { $_ && ! eval { $_->isa("PlSense::Entity") } } @values; VALUE: foreach my $value ( @values ) { logger->debug("Try push candidate by match : $value"); foreach my $m ( addrrouter->get_hash_members($value) ) { $self->push_candidate($m); } } return; } } 1; __END__ plsense-0.3.4/lib/PlSense/Plugin/CodeAssistant/Module.pm000066400000000000000000000032331260377356000231050ustar00rootroot00000000000000package PlSense::Plugin::CodeAssistant::Module; use parent qw{ PlSense::Plugin::CodeAssistant }; use strict; use warnings; use Class::Std; use PlSense::Logger; use PlSense::Util; { sub is_only_valid_context { my ($self, $code, $tok) = @_; if ( $code !~ m{ \b (?:use|require) \s+ ([a-zA-Z0-9_:]*) \z }xms ) { return; } my $input = $1; $self->do_match($input); return 1; } sub is_valid_context { my ($self, $code, $tok) = @_; my $input; if ( $code =~ m{ ["'] ([a-zA-Z0-9_:]+) \z }xms ) { $input = $1; } elsif ( $code =~ m{ ["'] [^"']+ \s+ ([a-zA-Z0-9_:]+) \z }xms ) { $input = $1; } elsif ( $code =~ m{ ([a-zA-Z0-9_:]+) \s+ ([a-zA-Z0-9_:]+) \z }xms ) { my $preword = $1; $input = $2; if ( $preword eq "package" ) { return; } if ( $preword eq "sub" ) { return; } if ( $preword eq "my" ) { return; } if ( $preword eq "our" ) { return; } if ( $preword eq "local" ) { return; } } elsif ( $code =~ m{ (?:\s|^|;|,|\}|\{|\[|\(|=>|\.) \s* ([a-zA-Z0-9_:]+) \z }xms ) { $input = $1; } else { return; } $self->do_match($input); return 1; } sub do_match : PRIVATE { my ($self, $input) = @_; logger->info("Match context : input[$input]"); $self->set_input($input); logger->notice("Found include modules"); MODULE: foreach my $mdl ( mdlkeeper->get_packages ) { $self->push_candidate($mdl->get_name, $mdl); } } } 1; __END__ plsense-0.3.4/lib/PlSense/Plugin/CodeAssistant/StaticMethod.pm000066400000000000000000000021371260377356000242520ustar00rootroot00000000000000package PlSense::Plugin::CodeAssistant::StaticMethod; use parent qw{ PlSense::Plugin::CodeAssistant }; use strict; use warnings; use Class::Std; use PlSense::Logger; use PlSense::Util; { sub is_only_valid_context { my ($self, $code, $tok) = @_; my $input = ""; if ( $tok && $tok->isa("PPI::Token::Word") ) { $input = "".$tok->content.""; $tok = $tok->previous_sibling; } if ( ! $tok || ! $tok->isa("PPI::Token::Operator") || $tok->content ne '->' ) { return; } $tok = $tok->previous_sibling; if ( ! $tok || ! $tok->isa("PPI::Token::Word") ) { return; } my $mdl = mdlkeeper->get_module("".$tok->content."") or return; $self->set_input($input); logger->info("Match context : input[$input]"); logger->notice("Found static method of [".$mdl->get_name."]"); my $currmdl = addrfinder->get_currentmodule; STATIC_METHOD: foreach my $mtd ( $mdl->get_static_methods($currmdl) ) { $self->push_candidate($mtd->get_name, $mtd); } return 1; } } 1; __END__ plsense-0.3.4/lib/PlSense/Plugin/CodeAssistant/Sub.pm000066400000000000000000000012551260377356000224130ustar00rootroot00000000000000package PlSense::Plugin::CodeAssistant::Sub; use parent qw{ PlSense::Plugin::CodeAssistant }; use strict; use warnings; use Class::Std; use PlSense::Logger; use PlSense::Util; { sub is_only_valid_context { my ($self, $code, $tok) = @_; if ( $code !~ m{ ^ \s* sub \s+ ([a-zA-Z0-9_]*) \z }xms ) { return; } my $input = $1; $self->set_input($input); logger->info("Match context : input[$input]"); my $currmdl = addrfinder->get_currentmodule; INHERIT_METHOD: foreach my $mtd ( $currmdl->get_inherit_methods ) { $self->push_candidate($mtd->get_name, $mtd); } return 1; } } 1; __END__ plsense-0.3.4/lib/PlSense/Plugin/CodeAssistant/UseArgument.pm000066400000000000000000000072171260377356000241250ustar00rootroot00000000000000package PlSense::Plugin::CodeAssistant::UseArgument; use parent qw{ PlSense::Plugin::CodeAssistant }; use strict; use warnings; use Class::Std; use PlSense::Logger; use PlSense::Util; { sub is_only_valid_context { my ($self, $code, $tok) = @_; if ( ! $tok ) { return; } if ( ! $tok->isa("PPI::Token::QuoteLike::Words") && $tok->isa("PPI::Token::Quote") ) { return; } my $stmt = $tok->statement or return; if ( ! $stmt->isa("PPI::Statement::Include") ) { return; } my $mdlnm = $stmt->module or return; if ( $tok->content !~ m{ qw[^\s] \s* ([^;]*) \z }xms && $tok->content !~ m{ ["'] \s* ([^"']*) \z }xms ) { return; } my $argtext = $1 || ""; my @inputed = split m{ \s+ }xms, $argtext; my $input = $argtext eq "" || $argtext =~ m{ \s \z }xms ? "" : pop @inputed; logger->info("Match context : input[$input]"); $self->set_input($input); my %inputed_is; INPUTED: foreach my $inputed ( @inputed ) { $inputed_is{$inputed} = 1; } logger->notice("Found use argument of $mdlnm"); if ( $mdlnm eq "base" || $mdlnm eq "parent" ) { MODULE: foreach my $mdl ( mdlkeeper->get_packages ) { if ( $inputed_is{$mdl->get_name} ) { next MODULE; } $self->push_candidate($mdl->get_name, $mdl); } } else { my $mdl = mdlkeeper->get_module($mdlnm) or return; if ( ! $mdl->is_exportable ) { return; } my @exportvars; if ( $mdl->exist_member('@EXPORT') ) { push @exportvars, $mdl->get_member('@EXPORT'); } if ( $mdl->exist_member('@EXPORT_OK') ) { push @exportvars, $mdl->get_member('@EXPORT_OK'); } EXPORTVAR: foreach my $var ( @exportvars ) { if ( ! $var ) { next EXPORTVAR; } my $resolve = addrrouter->resolve_address($var->get_fullnm) or next EXPORTVAR; if ( ! $resolve->isa("PlSense::Entity::Array") ) { next EXPORTVAR; } my $scalar = $resolve->get_element or next EXPORTVAR; if ( ! eval { $scalar->isa("PlSense::Entity::Scalar") } ) { next EXPORTVAR; } EXPORTABLE: foreach my $somenm ( split m{ \s+ }xms, $scalar->get_value ) { $somenm =~ s{ \A & }{}xms; my $some = $mdl->get_method($somenm) || $mdl->get_member($somenm) or next EXPORTABLE; if ( $some->isa("PlSense::Symbol::Variable") && $some->is_lexical ) { next EXPORTABLE; } if ( $inputed_is{$some->get_name} ) { next EXPORTABLE; } $self->push_candidate($some->get_name, $some); } } if ( $mdl->exist_member('%EXPORT_TAGS') ) { my $var = $mdl->get_member('%EXPORT_TAGS'); my $resolve = addrrouter->resolve_address($var->get_fullnm) or return; if ( ! $resolve->isa("PlSense::Entity::Hash") ) { return; } KEY: foreach my $key ( $resolve->keys_member ) { if ( $key eq '*' ) { next KEY; } $resolve->set_membernm($key); my $value = $resolve->get_member; if ( eval { $value->isa("PlSense::Entity") } ) { $self->push_candidate(":".$key, $value); } else { $self->push_candidate(":".$key, addrrouter->resolve_address($value)); } } } } return 1; } } 1; __END__ plsense-0.3.4/lib/PlSense/Plugin/CodeAssistant/Variable.pm000066400000000000000000000042571260377356000234140ustar00rootroot00000000000000package PlSense::Plugin::CodeAssistant::Variable; use parent qw{ PlSense::Plugin::CodeAssistant }; use strict; use warnings; use Class::Std; use List::AllUtils qw{ uniq }; use PlSense::Logger; use PlSense::Util; { sub is_only_valid_context { my ($self, $code, $tok) = @_; if ( $code !~ m{ (\$|\$\#|@|%) ([^\s\$\#@%]*) \z }xms ) { return; } my $vartype = $1; my $input = $2; if ( $input =~ m{ -> }xms ) { return; } if ( $input =~ m{ [a-zA-Z0-9_][\[\{] }xms ) { return; } my $pretok1 = $tok && $tok->previous_sibling; my $pretok2 = $pretok1 && $pretok1->previous_sibling; if ( $pretok1 && $pretok2 && $pretok1->isa("PPI::Token::Whitespace") && $pretok2->isa("PPI::Token::Word") && ($pretok2->content eq "my" || $pretok2->content eq "our") ) { return; } if ( $vartype eq '$#' ) { $vartype = '@'; } if ( $vartype ne '$' && $vartype ne '@' && $vartype ne '%' ) { return; } $self->set_input($input); logger->info("Match context : vartype[$vartype] input[$input]"); my $currmdl = addrfinder->get_currentmodule; my $currmtd = addrfinder->get_currentmethod; my $mtdnm = $currmtd ? $currmtd->get_name : ""; logger->notice("Found variable of ".$currmdl->get_fullnm." $mtdnm"); VAR: foreach my $var ( $currmdl->get_current_any_variables($mtdnm), builtin->get_variables ) { my $currtype = substr($var->get_name, 0, 1); my $currnm = substr($var->get_name, 1); if ( $vartype eq '@' || $vartype eq '%' ) { if ( $currtype ne $vartype ) { next VAR; } } $self->push_candidate($currnm, $var); } EXT_VAR: foreach my $var ( $currmdl->get_external_any_variables ) { my $currtype = substr($var->get_fullnm, 0, 1); my $currnm = substr($var->get_fullnm, 1); if ( $vartype eq '@' || $vartype eq '%' ) { if ( $currtype ne $vartype ) { next EXT_VAR; } } $self->push_candidate($currnm, $var); } return 1; } } 1; __END__ plsense-0.3.4/lib/PlSense/Plugin/IncludeStmt.pm000066400000000000000000000002521260377356000213450ustar00rootroot00000000000000package PlSense::Plugin::IncludeStmt; use strict; use warnings; use Class::Std; { sub include_statement { my ($self, $mdl, $stmt) = @_; } } 1; __END__ plsense-0.3.4/lib/PlSense/Plugin/IncludeStmt/000077500000000000000000000000001260377356000210105ustar00rootroot00000000000000plsense-0.3.4/lib/PlSense/Plugin/IncludeStmt/Lib.pm000066400000000000000000000044321260377356000220570ustar00rootroot00000000000000package PlSense::Plugin::IncludeStmt::Lib; use parent qw{ PlSense::Plugin::IncludeStmt }; use strict; use warnings; use Class::Std; use File::Basename; use PlSense::Util; { sub include_statement { my ($self, $mdl, $includenm, $stmt) = @_; # if ( $includenm ne "lib" ) { return; } # my @tokens = $stmt->children; # my $e = shift @tokens or return; # if ( ! $e->isa("PPI::Token::Word") ) { return; } # $e = shift @tokens or return; # if ( $e->isa("PPI::Token::Whitespace") ) { $e = shift @tokens or return; } # if ( ! $e->isa("PPI::Token::Word") ) { return; } # $e = shift @tokens or return; # if ( $e->isa("PPI::Token::Whitespace") ) { $e = shift @tokens or return; } # my @libpathes; # if ( $e->isa("PPI::Token::QuoteLike::Words") ) { # LIBPATH: # foreach my $libpath ( $e->literal ) { # push @libpathes, $libpath; # } # } # elsif ( $e->isa("PPI::Structure::List") ) { # @tokens = $e->children; # $e = shift @tokens or return; # if ( ! $e->isa("PPI::Statement::Expression") ) { return; } # TOKEN: # foreach my $tok ( $e->children ) { # if ( ! $tok->isa("PPI::Token::Quote") ) { next TOKEN; } # if ( $tok->isa("PPI::Token::Quote::Single") ) { # push @libpathes, "".$tok->literal.""; # } # else { # my $value = "".$e->content.""; # $value =~ s{ ^ ("|') }{}xms; # $value =~ s{ ("|') $ }{}xms; # push @libpathes, $value; # } # } # } # elsif ( $e->isa("PPI::Token::Quote::Single") ) { # push @libpathes, "".$e->literal.""; # } # elsif ( $e->isa("PPI::Token::Quote") ) { # my $value = "".$e->content.""; # $value =~ s{ ^ ("|') }{}xms; # $value =~ s{ ("|') $ }{}xms; # push @libpathes, $value; # } # my $currpath = dirname($mdl->get_filepath); # LIBPATH: # foreach my $libpath ( @libpathes ) { # mdlkeeper->find_module($currpath."/".$libpath); # } } } 1; __END__ plsense-0.3.4/lib/PlSense/Plugin/IncludeStmt/Vars.pm000066400000000000000000000033571260377356000222710ustar00rootroot00000000000000package PlSense::Plugin::IncludeStmt::Vars; use parent qw{ PlSense::Plugin::IncludeStmt }; use strict; use warnings; use Class::Std; { sub include_statement { my ($self, $mdl, $includenm, $stmt) = @_; if ( $includenm ne "vars" ) { return; } my @tokens = $stmt->children; my $e = shift @tokens or return; if ( ! $e->isa("PPI::Token::Word") ) { return; } $e = shift @tokens or return; if ( $e->isa("PPI::Token::Whitespace") ) { $e = shift @tokens or return; } if ( ! $e->isa("PPI::Token::Word") ) { return; } $e = shift @tokens or return; if ( $e->isa("PPI::Token::Whitespace") ) { $e = shift @tokens or return; } if ( $e->isa("PPI::Token::QuoteLike::Words") ) { VAR: foreach my $varnm ( $e->literal ) { PlSense::Symbol::Variable->new({ name => "$varnm", lexical => 0, belong => $mdl, }); } } elsif ( $e->isa("PPI::Structure::List") ) { @tokens = $e->children; $e = shift @tokens or return; if ( ! $e->isa("PPI::Statement::Expression") ) { return; } VAR: foreach my $tok ( $e->children ) { if ( ! $tok->isa("PPI::Token::Quote") ) { next VAR; } my $varnm; if ( $tok->isa("PPI::Token::Quote::Single") ) { $varnm = "".$tok->literal.""; } else { $varnm = "".$tok->content.""; $varnm =~ s{ \A ("|') }{}xms; $varnm =~ s{ ("|') \z }{}xms; } PlSense::Symbol::Variable->new({ name => $varnm, lexical => 0, belong => $mdl, }); } } } } 1; __END__ plsense-0.3.4/lib/PlSense/Plugin/PPIBuilder.pm000066400000000000000000000011141260377356000210470ustar00rootroot00000000000000package PlSense::Plugin::PPIBuilder; use strict; use warnings; use Class::Std; { sub begin { my ($self, $mdl, $ppi) = @_; } sub start { my ($self, $mdl, $ppi) = @_; } sub end { my ($self, $mdl, $ppi) = @_; } sub scheduled_statement { my ($self, $mdl, $scheduled_type, $stmt) = @_; } sub sub_statement { my ($self, $mtd, $stmt) = @_; } sub variable_statement { my ($self, $vars, $stmt) = @_; } sub other_statement { my ($self, $mdl, $mtd, $stmt) = @_; } } 1; __END__ plsense-0.3.4/lib/PlSense/Plugin/PPIBuilder/000077500000000000000000000000001260377356000205145ustar00rootroot00000000000000plsense-0.3.4/lib/PlSense/Plugin/PPIBuilder/ClassStd.pm000066400000000000000000000156531260377356000226040ustar00rootroot00000000000000package PlSense::Plugin::PPIBuilder::ClassStd; use parent qw{ PlSense::Plugin::PPIBuilder }; use strict; use warnings; use Class::Std; use List::AllUtils qw{ first }; use PlSense::Logger; use PlSense::Util; use PlSense::Symbol::Method; use PlSense::Entity::Reference; use PlSense::Entity::Hash; use PlSense::Entity::Null; { sub end { my ($self, $mdl, $ppi) = @_; if ( ! $mdl->exist_usingmdl("Class::Std") && ! $mdl->exist_usingmdl("Class::Std::Storable") && ! $mdl->exist_usingmdl("Class::Std::Fast::Storable") ) { return; } # Class::Std throws a new 2nd argument to a BUILD/START 3rd argument substkeeper->add_substitute("&".$mdl->get_fullnm."::BUILD[3]", "&".$mdl->get_fullnm."::new[2]", 1); substkeeper->add_substitute("&".$mdl->get_fullnm."::START[3]", "&".$mdl->get_fullnm."::new[2]", 1); # add the reverse connect because reverse route is not added when both is a argument substkeeper->add_substitute("&".$mdl->get_fullnm."::new[2]", "&".$mdl->get_fullnm."::BUILD[3]", 1); substkeeper->add_substitute("&".$mdl->get_fullnm."::new[2]", "&".$mdl->get_fullnm."::START[3]", 1); PARENT: for my $i ( 1..$mdl->count_parent ) { my $parent = $mdl->get_parent($i); # for getting parent initializers at BUILD/START in child substkeeper->add_substitute("&".$mdl->get_fullnm."::BUILD[3]", "&".$parent->get_fullnm."::BUILD[3]", 1); substkeeper->add_substitute("&".$mdl->get_fullnm."::START[3]", "&".$parent->get_fullnm."::START[3]", 1); # for connecting child new arguments to detect parent member type substkeeper->add_substitute("&".$parent->get_fullnm."::new[2]", "&".$mdl->get_fullnm."::new[2]", 1); substkeeper->add_substitute("&".$parent->get_fullnm."::new[2]", "&".$mdl->get_fullnm."::new[2]", 1); } } sub sub_statement { my ($self, $mtd, $stmt) = @_; my $mdl = $mtd->get_module or return; if ( ! $mdl->exist_usingmdl("Class::Std") && ! $mdl->exist_usingmdl("Class::Std::Storable") && ! $mdl->exist_usingmdl("Class::Std::Fast::Storable") ) { return; } my $attr = $mtd->get_attribute or return; if ( $attr->{content} eq 'PRIVATE' ) { $mtd->set_publicly(0); $mtd->set_privately(1); } elsif ( $attr->{content} eq 'RESTRICTED' ) { $mtd->set_publicly(0); } } sub variable_statement { my ($self, $vars, $stmt) = @_; if ( $#{$vars} != 0 ) { return; } my $var = @{$vars}[0]; my $mdl = $var->get_belong or return; if ( ! $mdl->isa("PlSense::Symbol::Module") ) { return; } if ( ! $mdl->exist_usingmdl("Class::Std") && ! $mdl->exist_usingmdl("Class::Std::Storable") && ! $mdl->exist_usingmdl("Class::Std::Fast::Storable") ) { return; } my @tokens = $stmt->children; my $e = shift @tokens or return; if ( ! $e->isa("PPI::Token::Word") || $e->content ne "my" ) { return; } $e = shift @tokens or return; if ( ! $e->isa("PPI::Token::Symbol") ) { return; } $e = shift @tokens or return; if ( ! $e->isa("PPI::Token::Operator") || $e->content ne ':' ) { return; } $e = shift @tokens or return; if ( ! $e->isa("PPI::Token::Word") || $e->content ne 'ATTR' ) { return; } $e = shift @tokens or return; if ( ! $e->isa("PPI::Structure::List") ) { return; } @tokens = $e->children; $e = shift @tokens or return; if ( ! $e->isa("PPI::Statement::Expression") ) { return; } my $attrtext = "".$e->content.""; logger->info("Found Attr of Class::Std for [".$var->get_fullnm."] : ".$attrtext); my ($initnm, $getternm, $setternm); my $namevalue = $self->get_attr_value($attrtext, "name"); if ( $namevalue ) { $initnm = $namevalue; $getternm = $namevalue; $setternm = $namevalue; } else { $initnm = $self->get_attr_value($attrtext, "init_arg"); $getternm = $self->get_attr_value($attrtext, "get"); $setternm = $self->get_attr_value($attrtext, "set"); } my $default = $self->get_attr_value($attrtext, "default"); if ( $getternm ) { my $mtdnm = "get_".$getternm; my $mtd = $mdl->exist_method($mtdnm) ? $mdl->get_method($mtdnm) : PlSense::Symbol::Method->new({ name => $mtdnm, module => $mdl, publicly => 1 }); $mtd->set_importive(0); substkeeper->add_substitute($mtd->get_fullnm, $var->get_fullnm.".H:*", 1); } if ( $setternm ) { my $mtdnm = "set_".$setternm; my $mtd = $mdl->exist_method($mtdnm) ? $mdl->get_method($mtdnm) : PlSense::Symbol::Method->new({ name => $mtdnm, module => $mdl, publicly => 1 }); $mtd->set_importive(0); substkeeper->add_substitute($var->get_fullnm.".H:*", $mtd->get_fullnm."[2]", 1); } if ( $initnm ) { my $mtd = $mdl->get_method("new") or return; substkeeper->add_substitute($var->get_fullnm.".H:*", $mtd->get_fullnm."[2].R.H:".$initnm, 1); # Turn to not make entity but just add hash member # my @routes = addrrouter->get_route($mtd->get_fullnm."[2]"); # my $ref = first { eval { $_->isa("PlSense::Entity::Reference") } } @routes; # if ( ! $ref ) { # $ref = PlSense::Entity::Reference->new(); # substkeeper->add_substitute($mtd->get_fullnm."[2]", $ref, 1); # } # my $hash = $ref->get_entity; # if ( ! eval { $hash->isa("PlSense::Entity::Hash") } ) { # $hash = PlSense::Entity::Hash->new(); # $ref->set_entity($hash); # } # $hash->set_membernm($initnm); # $hash->set_member(PlSense::Entity::Null->new()); addrrouter->add_hash_member($mtd->get_fullnm."[2].R", $initnm); } } sub get_attr_value : PRIVATE { my ($self, $attrtext, $attrnm) = @_; if ( $attrtext =~ m{ \b $attrnm => ' ([^']*) ' }xms ) { return $1; } elsif ( $attrtext =~ m{ \b $attrnm => " ([^"]*) " }xms ) { return $1; } elsif ( $attrtext =~ m{ : $attrnm < ([^>]+) > }xms ) { return $1; } elsif ( $attrtext =~ m{ : $attrnm \( '? ([^']*) '? \) }xms ) { return $1; } elsif ( $attrtext =~ m{ : $attrnm \( "? ([^"]*) "? \) }xms ) { return $1; } return; } } 1; __END__ plsense-0.3.4/lib/PlSense/Plugin/PPIBuilder/Default.pm000066400000000000000000000157541260377356000224520ustar00rootroot00000000000000package PlSense::Plugin::PPIBuilder::Default; use parent qw{ PlSense::Plugin::PPIBuilder }; use strict; use warnings; use Class::Std; use List::AllUtils qw{ firstidx }; use PlSense::Logger; use PlSense::Util; use PlSense::Entity::Instance; use PlSense::Entity::Hash; use PlSense::Symbol::Variable; { sub end { my ($self, $mdl, $ppi) = @_; if ( $mdl->get_name eq 'main' || ! $mdl->is_objective ) { return; } my $mtd = $mdl->get_method("new") or return; my $entity = PlSense::Entity::Instance->new({ modulenm => $mdl->get_name, }); substkeeper->add_substitute($mtd->get_fullnm, $entity, 1); my $baddr = '&'.$mdl->get_name.'::BLESS'; substkeeper->add_substitute($baddr, $entity, 1); } sub scheduled_statement { my ($self, $mdl, $scheduled_type, $stmt) = @_; if ( $scheduled_type eq "END" ) { return; } if ( $stmt->isa("PPI::Statement::Break") ) { return; } if ( $stmt->isa("PPI::Statement::Compound") ) { return; } my @tokens = $stmt->children; $self->build_by_variable_substituted($stmt, @tokens) || $self->build_by_normal_statement($stmt, @tokens); } sub sub_statement { my ($self, $mtd, $stmt) = @_; my $mdl = $mtd->get_module or return; if ( $mdl->is_objective ) { my $baddr = '&'.$mdl->get_name.'::BLESS'; substkeeper->add_substitute($mtd->get_fullnm."[1]", $baddr, 1); } my $block = $stmt->block or return; my @statements = $block->children; my $laststmt = pop @statements or return; if ( $laststmt->isa("PPI::Statement::Break") ) { $self->build_by_break_statement($mtd, $laststmt); } elsif ( $laststmt->isa("PPI::Statement") ) { my @tokens = $laststmt->children; logger->info("Found method last statement : ".$laststmt->content); substbuilder->build_method_return($mtd, @tokens); } } sub variable_statement { my ($self, $vars, $stmt) = @_; my @tokens = $stmt->children; my $eqidx = firstidx { $_->isa("PPI::Token::Operator") && $_->content eq "=" } @tokens; if ( $eqidx < 0 || $eqidx >= $#tokens ) { return; } $eqidx++; substbuilder->build_variable_substitute( $vars, @tokens[$eqidx..$#tokens] ); } sub other_statement { my ($self, $mdl, $mtd, $stmt) = @_; if ( $stmt->isa("PPI::Statement::Break") && $mtd ) { $self->build_by_break_statement($mtd, $stmt); } elsif ( $stmt->isa("PPI::Statement::Compound") ) { my @tokens = $stmt->children; my $e = shift @tokens or return; if ( $e->isa("PPI::Token::Label") ) { $e = shift @tokens or return; } if ( ! $e->isa("PPI::Token::Word") ) { return; } if ( $e->content eq "for" ) { $self->build_by_for_statement($mdl, $mtd, @tokens); } elsif ( $e->content eq "foreach" ) { $self->build_by_foreach_statement($mdl, $mtd, @tokens); } elsif ( $e->content eq "while" ) { $self->build_by_while_statement($mdl, $mtd, @tokens); } } else { my @tokens = $stmt->children; $self->build_by_variable_substituted($stmt, @tokens) || $self->build_by_normal_statement($stmt, @tokens); } } sub build_by_variable_substituted : PRIVATE { my ($self, $stmt, @tokens) = @_; my $eqidx = firstidx { $_->isa("PPI::Token::Operator") && $_->content eq "=" } @tokens; if ( $eqidx <= 0 || $eqidx >= $#tokens ) { return; } logger->info("Found substitute statement : ".$stmt->content); my @lefts = @tokens[0..($eqidx-1)]; my @rights = @tokens[($eqidx+1)..$#tokens]; substbuilder->build_substitute_with_find_variable( \@lefts, @rights ); return 1; } sub build_by_normal_statement : PRIVATE { my ($self, $stmt, @tokens) = @_; substbuilder->build_any_substitute_from_normal_statement(@tokens); } sub build_by_break_statement : PRIVATE { my ($self, $mtd, $stmt) = @_; my @tokens = $stmt->children; my $e = shift @tokens or return; if ( $e->content ne "return" ) { return; } logger->info("Found method break statement : ".$stmt->content); substbuilder->build_method_return($mtd, @tokens); } sub build_by_for_statement : PRIVATE { my ($self, $mdl, $mtd, @tokens) = @_; $self->build_by_foreach_statement($mdl, $mtd, @tokens); } sub build_by_foreach_statement : PRIVATE { my ($self, $mdl, $mtd, @tokens) = @_; my $lexical; my $e = shift @tokens or return; if ( $e->isa("PPI::Token::Word") && $e->content eq "my" ) { $lexical = 1; $e = shift @tokens or return; } if ( ! $e->isa("PPI::Token::Symbol") ) { return; } my $varnm = "".$e->content.""; my $var = $mtd && $mtd->exist_variable($varnm) ? $mtd->get_variable($varnm) : $mdl->exist_member($varnm) ? $mdl->get_member($varnm) : $lexical ? PlSense::Symbol::Variable->new({ name => "$varnm", lexical => 1, belong => $mtd ? $mtd : $mdl, }) : undef; if ( ! $var ) { return; } $e = shift @tokens or return; if ( ! $e->isa("PPI::Structure::List") ) { return; } my @children = $e->children; if ( $#children < 0 ) { return; } $e = shift @children or return; if ( ! $e->isa("PPI::Statement") ) { return; } logger->info("Found for/foreach statement : ".$e->content); @children = $e->children; my $any = addrfinder->find_address_or_entity(@children) or return; if ( eval { $any->isa("PlSense::Entity") } ) { if ( ! $any->isa("PlSense::Entity::Array") ) { return; } my $el = $any->get_element; if ( $el ) { substkeeper->add_substitute($var->get_fullnm, $el); } elsif ( $any->count_address > 0 ) { substkeeper->add_substitute($var->get_fullnm, $any->get_address(1).".A"); } } else { substkeeper->add_substitute($var->get_fullnm, $any.".A"); } } sub build_by_while_statement : PRIVATE { my ($self, $mdl, $mtd, @tokens) = @_; my $e = shift @tokens or return; if ( ! $e->isa("PPI::Structure::Condition") ) { return; } my @children = $e->children; my $eqidx = firstidx { $_->isa("PPI::Token::Operator") && $_->content eq "=" } @children; if ( $eqidx <= 0 || $eqidx >= $#children ) { return; } logger->info("Found while statement : ".$e->content); my @lefts = @children[0..($eqidx-1)]; my @rights = @children[($eqidx+1)..$#children]; } } 1; __END__ plsense-0.3.4/lib/PlSense/SocketClient.pm000066400000000000000000000066531260377356000202560ustar00rootroot00000000000000package PlSense::SocketClient; use strict; use warnings; use Class::Std; use IO::Socket; use PlSense::Logger; use PlSense::Configure; { my %retryinterval_of :ATTR( :init_arg :default(1) ); my %maxretry_of :ATTR( :init_arg :default(10) ); sub get_main_server_response { my ($self, $sendtext, $opt_ref) = @_; my $sock = $self->connect_main_server($opt_ref); return $self->get_server_response($sock, $sendtext); } sub get_work_server_response { my ($self, $sendtext, $opt_ref) = @_; my $sock = $self->connect_work_server($opt_ref); return $self->get_server_response($sock, $sendtext); } sub get_resolve_server_response { my ($self, $sendtext, $opt_ref) = @_; my $sock = $self->connect_resolve_server($opt_ref); return $self->get_server_response($sock, $sendtext); } sub request_main_server { my ($self, $sendtext, $opt_ref) = @_; my $sock = $self->connect_main_server($opt_ref); return $self->request_server($sock, $sendtext); } sub request_work_server { my ($self, $sendtext, $opt_ref) = @_; my $sock = $self->connect_work_server($opt_ref); return $self->request_server($sock, $sendtext); } sub request_resolve_server { my ($self, $sendtext, $opt_ref) = @_; my $sock = $self->connect_resolve_server($opt_ref); return $self->request_server($sock, $sendtext); } sub connect_main_server { my ($self, $opt_ref) = @_; return $self->connect_server("main", get_config("port1"), $opt_ref); } sub connect_work_server { my ($self, $opt_ref) = @_; return $self->connect_server("work", get_config("port2"), $opt_ref); } sub connect_resolve_server { my ($self, $opt_ref) = @_; return $self->connect_server("resolve", get_config("port3"), $opt_ref); } sub connect_server : PRIVATE { my ($self, $svtype, $port, $opt_ref) = @_; my $s; my $wait = 0; my $maxwait = $opt_ref->{maxretry} || $maxretry_of{ident $self}; my $interval = $opt_ref->{retryinterval} || $retryinterval_of{ident $self}; OPEN_SOCKET: while ( ! $s && $wait < $maxwait ) { $s = IO::Socket::INET->new(PeerAddr => "localhost", PeerPort => $port, Proto => "tcp", ); $self->sleep_for($interval); $wait++; } if ( ! $s && ! $opt_ref->{ignore_error} ) { logger->error("Can't connect $svtype server : $!"); return; } return $s; } sub request_server : PRIVATE { my ($self, $sock, $sendtext) = @_; $sendtext =~ s{ \n$ }{}xms; if ( ! $sock ) { return; } $sock->print("$sendtext\n"); $sock->close; return 1; } sub get_server_response : PRIVATE { my ($self, $sock, $sendtext) = @_; $sendtext =~ s{ \n$ }{}xms; if ( ! $sock ) { return ""; } $sock->print("$sendtext\n"); my $ret = ""; LINE: while ( my $line = $sock->getline ) { $ret .= $line; } $sock->close; return $ret; } sub sleep_for : PRIVATE { my ($self, $duration) = @_; select undef, undef, undef, $duration; return; } } 1; __END__ plsense-0.3.4/lib/PlSense/SubstituteBuilder.pm000066400000000000000000000060271260377356000213440ustar00rootroot00000000000000package PlSense::SubstituteBuilder; use strict; use warnings; use Class::Std; use PlSense::Logger; use PlSense::Util; use PlSense::AddressFinder; { sub START { my ($class, $ident, $arg_ref) = @_; set_addrfinder( PlSense::AddressFinder->new({ with_build => 1, }) ); } sub set_currentmodule { my ($self, $currentmodule) = @_; addrfinder->set_currentmodule($currentmodule); } sub set_currentmethod { my ($self, $currentmethod) = @_; addrfinder->set_currentmethod($currentmethod); } sub init_currentmethod { my ($self) = @_; addrfinder->init_currentmethod; } sub build_method_return { my ($self, $mtd, @tokens) = @_; if ( ! $mtd || ! $mtd->isa("PlSense::Symbol::Method") ) { logger->error("Not PlSense::Symbol::Method"); return; } if ( $mtd->get_name eq "new" ) { logger->debug("Quit build method return because method name is new."); return; } my @addresses; push @addresses, $mtd->get_fullnm; $self->build_substitute(\@addresses, @tokens); } sub build_variable_substitute { my ($self, $vars, @tokens) = @_; my @addresses; VAR: foreach my $var ( @$vars ) { if ( ! $var || ! $var->isa("PlSense::Symbol::Variable") ) { logger->error("Not PlSense::Symbol::Variable"); return; } push @addresses, $var->get_fullnm; } if ( $#addresses < 0 ) { return; } $self->build_substitute(\@addresses, @tokens); } sub build_substitute_with_find_variable { my ($self, $lefttokens, @righttokens) = @_; my @lefts = @{$lefttokens}; if ( $#lefts < 0 ) { return; } my @addresses = addrfinder->find_addresses(@lefts); if ( $#addresses < 0 ) { return; } $self->build_substitute(\@addresses, @righttokens); } sub build_any_substitute_from_normal_statement { my ($self, @tokens) = @_; addrfinder->find_address_or_entity(@tokens); } sub build_substitute : PRIVATE { my ($self, $addresses, @tokens) = @_; my @values = addrfinder->find_addresses_or_entities(@tokens); if ( $#values < 0 ) { return; } my $mtd = addrfinder->get_currentmethod; my $argarraddr = $mtd ? '@'.$mtd->get_fullnm."::_" : ""; if ( $argarraddr && ! eval { $values[0]->isa("PlSense::Entity") } && $values[0] eq $argarraddr ) { VAR: foreach my $addr ( @$addresses ) { addrfinder->forward_methodindex; substkeeper->add_substitute_to_argument($addr, $mtd->get_fullnm, addrfinder->get_methodindex, 1); } return; } substkeeper->add_substitutes($addresses, @values); return; } } 1; __END__ plsense-0.3.4/lib/PlSense/SubstituteKeeper.pm000066400000000000000000000636511260377356000211770ustar00rootroot00000000000000package PlSense::SubstituteKeeper; use parent qw{ PlSense::Cacheable }; use strict; use warnings; use Class::Std; use List::AllUtils qw{ any firstidx }; use Try::Tiny; use PlSense::Logger; use PlSense::Configure; use PlSense::Util; use PlSense::Entity::Scalar; use PlSense::Entity::Array; { my %cache_of :ATTR( :default(undef) ); my %projcache_of :ATTR( :default(undef) ); my %substh_of :ATTR(); my %unknownargh_of :ATTR(); my %max_entry_of :ATTR( :init_arg :default(50) ); my %max_address_entry_of :ATTR( :init_arg :default(3) ); my %current_local_is :ATTR(); sub START { my ($class, $ident, $arg_ref) = @_; $cache_of{$ident} = $class->new_cache('ISubst'); $projcache_of{$ident} = $class->new_cache('Subst.'.$class->get_project()); $substh_of{$ident} = {}; $unknownargh_of{$ident} = {}; } sub setup_without_reload { my $self = shift; $self->update_project(); my $projnm = $self->get_project(); my $local = get_config("local"); $cache_of{ident $self}->set_namespace( $local ? "ISubst.$projnm" : "ISubst" ); $projcache_of{ident $self}->set_namespace("Subst.$projnm"); addrrouter->setup_without_reload(); $current_local_is{ident $self} = $local; } sub setup { my $self = shift; my $force = shift || 0; my $projnm = get_config("name"); if ( ! $force && $projnm eq $self->get_project() ) { logger->info("No need switch project data from [$projnm]"); return; } logger->info("Switch project data to [$projnm]"); my $local = get_config("local"); $current_local_is{ident $self} || $local ? $self->reset : $self->remove_project_all_sentinel(1); $self->setup_without_reload(); if ( $local ) { $self->load_installed_all(1); } $self->load_project_all(1); return 1; } sub store { my $self = shift; my $mdlnm = shift || ""; my $filepath = shift || ""; my $projectnm = shift || ""; addrrouter->store($mdlnm, $filepath, $projectnm); my $key = $self->get_cache_key($mdlnm, $filepath, $projectnm); if ( ! $projectnm ) { try { $cache_of{ident $self}->set("[S]".$key, $substh_of{ident $self}); } catch { $cache_of{ident $self}->set("[S]".$key, $substh_of{ident $self}); }; try { $cache_of{ident $self}->set("[A]".$key, $unknownargh_of{ident $self}); } catch { $cache_of{ident $self}->set("[A]".$key, $unknownargh_of{ident $self}); }; } elsif ( $projcache_of{ident $self} ) { try { $projcache_of{ident $self}->set("[S]".$key, $substh_of{ident $self}); } catch { $projcache_of{ident $self}->set("[S]".$key, $substh_of{ident $self}); }; try { $projcache_of{ident $self}->set("[A]".$key, $unknownargh_of{ident $self}); } catch { $projcache_of{ident $self}->set("[A]".$key, $unknownargh_of{ident $self}); }; } logger->info("Stored subst/arg info of $key"); } sub load { my $self = shift; my $mdlnm = shift || ""; my $filepath = shift || ""; my $projectnm = shift || ""; addrrouter->load($mdlnm, $filepath, $projectnm); my $key = $self->get_cache_key($mdlnm, $filepath, $projectnm); $self->load_by_substitute_key("[S]".$key, $projectnm); $self->load_by_unknown_argument_key("[A]".$key, $projectnm); logger->info("Loaded subst/arg info of $key"); } sub load_all { my $self = shift; logger->info("Start Load all"); $self->reset; $self->load_installed_all; $self->load_project_all; $self->resolve_unknown_argument; } sub remove { my $self = shift; my $mdlnm = shift || ""; my $filepath = shift || ""; my $projectnm = shift || ""; addrrouter->remove($mdlnm, $filepath, $projectnm); my $key = $self->get_cache_key($mdlnm, $filepath, $projectnm); $self->remove_by_substitute_key("[S]".$key, $projectnm); $self->remove_by_unknown_argument_key("[A]".$key, $projectnm); logger->info("Removed subst/arg info of $key"); } sub remove_project_all { my $self = shift; $self->remove_project_all_sentinel(0); } sub remove_all { my $self = shift; addrrouter->remove_all; $self->reset; try { $cache_of{ident $self}->clear; } catch { $cache_of{ident $self}->clear; }; if ( $projcache_of{ident $self} ) { try { $projcache_of{ident $self}->clear; } catch { $projcache_of{ident $self}->clear; }; } logger->info("Removed all subst/arg info"); } sub reset { my $self = shift; addrrouter->reset; $substh_of{ident $self} = {}; $unknownargh_of{ident $self} = {}; } sub add_substitutes { my ($self, $lefts, @rights) = @_; SUBSTITUTE: for my $i ( 0..$#{$lefts} ) { if ( $#rights < 0 ) { last SUBSTITUTE; } my $addr = @{$lefts}[$i]; my $type = substr($addr, 0, 1); if ( $i == $#{$lefts} && $#rights > 0 && ( $type eq '@' || $type eq '&' ) ) { # If the remained is multi-value to the last array address or the method return address, # Try merge the remained value. my $arr = PlSense::Entity::Array->new(); my $element; my $scalar = ""; VALUE: foreach my $value ( @rights ) { if ( ! $value ) { next VALUE; } my $etype = eval { $value->get_type } || ""; if ( $etype eq 'instance' ) { $element = $value; last VALUE; } elsif ( $etype eq 'scalar' ) { if ( $scalar ne "" ) { $scalar .= " " } $scalar .= $value->get_value; } elsif ( $etype eq 'array' ) { ADDR: for my $i ( 1..$value->count_address ) { $arr->push_address( $value->get_address($i) ); } my $e = $value->get_element or next VALUE; if ( eval { $e->isa("PlSense::Entity::Instance") } ) { $element = $e; last VALUE; } elsif ( eval { $e->isa("PlSense::Entity::Scalar") } ) { if ( $scalar ne "" ) { $scalar .= " " } $scalar .= $e->get_value; } } elsif ( $etype ne '' ) { $element = $value; } else { $arr->push_address($value); } } if ( $element ) { $arr->set_element($element); } elsif ( $scalar ne "" ) { $arr->set_element( PlSense::Entity::Scalar->new({ value => $scalar }) ); } $self->add_substitute($addr, $arr); } elsif ( $i == $#{$lefts} && $#rights > 0 && $type eq '%' ) { # If the remained is multi-value to the last hash address, # Try build hash value. my $hash = PlSense::Entity::Hash->new(); my $onkey = 1; my $key = ""; VALUE: foreach my $value ( @rights ) { if ( $onkey && $value && eval { $value->isa("PlSense::Entity::Scalar") } ) { $key = $value->get_value; } elsif ( ! $onkey && $key && $value ) { $hash->set_membernm($key); $hash->set_member($value); $key = ""; } $onkey = $onkey ? 0 : 1; } $self->add_substitute($addr, $hash); } else { my $right = shift @rights || ""; if ( eval { $right->isa("PlSense::Entity") } ) { $self->add_substitute($addr, $right); } elsif ( $right =~ s{ \[ ([0-9]+) \] \z }{}xms ) { my $idx = $1; $self->add_substitute_to_argument($addr, $right, $idx); } else { $self->add_substitute($addr, $right); } } } } sub add_substitute { my ($self, $left, $right, $force) = @_; if ( $force || eval { $right->isa("PlSense::Entity") } || addrrouter->exist_route($right) ) { if ( ! addrrouter->add_route($left, $right) ) { return; } $self->move_to_route($left); } else { $self->add_substitute_sentinel($left, $right); } } sub add_unknown_argument { my ($self, $mtdaddr, $idx, $value) = @_; if ( ! $mtdaddr || ! $idx || ! $value ) { return; } my $idxh = $unknownargh_of{ident $self}->{$mtdaddr}; if ( ! $idxh ) { $idxh = {}; $unknownargh_of{ident $self}->{$mtdaddr} = $idxh; } my $values = $idxh->{$idx}; if ( ! $values ) { $values = []; $idxh->{$idx} = $values; } my $vtype = eval { $value->get_type } || ""; my $vtext = $vtype ? $value->to_string : $value; if ( ! $vtype ) { # If this value is address, check current values. my @addridxs; VALUE: for my $i ( 0..$#{$values} ) { my $currv = @{$values}[$i]; if ( eval { $currv->isa("PlSense::Entity") } ) { next VALUE; } # If already exist this value, quit. if ( $currv eq $value ) { return; } push @addridxs, $i; # If count of address in values is max, remove first address. if ( $#addridxs + 1 >= $max_address_entry_of{ident $self} ) { splice @{$values}, $addridxs[0], 1; last VALUE; } } } # If count of values is max, remove first entity or first anything. if ( $#{$values} + 1 >= $max_entry_of{ident $self} ) { my $entityidx = firstidx { eval { $_->isa("PlSense::Entity") } } @{$values}; if ( $entityidx >= 0 ) { splice @{$values}, $entityidx, 1; } else { shift @{$values}; } } push @$values, $value; logger->debug("Add unknown argument of mtdaddr[$mtdaddr] idx[$idx] : $vtext"); } sub add_substitute_to_argument { my ($self, $left, $right, $idx, $force) = @_; if ( ! $left || ! $right || ! $idx ) { return; } $self->add_substitute($left, $right."[".$idx."]", $force); if ( $right !~ m{ \A & (.+) :: ([^:]+) \z }xms ) { return; } my ($mdlkey, $mtdnm) = ($1, $2); my ($mdlnm, $filepath) = $mdlkey =~ m{ \A main \[ (.+) \] \z }xms ? ("main", $1) : ($mdlkey, ""); my $mdl = mdlkeeper->get_module($mdlnm, $filepath) or return; if ( ! $mdl->exist_method($mtdnm) ) { return; } my $mtd = $mdl->get_method($mtdnm); my $mdlre = quotemeta($mdlkey); my $var; if ( $left =~ m{ \A ([\$@%]) & $mdlre :: $mtdnm :: ([^:]+) \z }xms ) { my $varnm = $1.$2; if ( ! $mtd->exist_variable($varnm) ) { return; } $var = $mtd->get_variable($varnm); } elsif ( $left =~ m{ \A ([\$@%]) $mdlre :: ([^:]+) \z }xms ) { my $varnm = $1.$2; if ( ! $mdl->exist_member($varnm) ) { return; } $var = $mdl->get_member($varnm); } if ( ! $var ) { return; } $mtd->set_argument($idx, $var); } sub remove_already_routing { my ($self) = @_; my @addrs = keys %{$substh_of{ident $self}}; logger->info("Start remove already resolved substitute : count[".($#addrs + 1)."]"); SUBST: foreach my $right ( @addrs ) { if ( ! addrrouter->exist_route($right) ) { next SUBST; } delete $substh_of{ident $self}->{$right}; } @addrs = keys %{$unknownargh_of{ident $self}}; my %resolved_of; logger->info("Start remove already resolved unknown argument : count[".($#addrs + 1)."]"); ARG: foreach my $mtdaddr ( @addrs ) { if ( $mtdaddr !~ m{ ^(.+)\.W:([^.]+)$ }xms ) { next ARG; } my ($findaddr, $mtdnm) = ($1, $2); my $resolve = $resolved_of{$findaddr}; if ( ! $resolve ) { $resolve = addrrouter->resolve_address($findaddr) or next ARG; $resolved_of{$findaddr} = $resolve; } if ( ! $resolve->isa("PlSense::Entity::Instance") ) { next ARG; } my $mdl = mdlkeeper->get_module( $resolve->get_modulenm ) or next ARG; my $mtd = $mdl->get_any_method($mtdnm) or next ARG; delete $unknownargh_of{ident $self}->{$mtdaddr}; } } sub resolve_substitute { my ($self) = @_; my @addrs = keys %{$substh_of{ident $self}}; logger->info("Start resolve substitute : count[".($#addrs + 1)."]"); SUBST: foreach my $right ( @addrs ) { my $substs = $substh_of{ident $self}->{$right} or next SUBST; if ( ! addrrouter->exist_route($right) ) { next SUBST; } SUBST: foreach my $left ( @{$substs} ) { if ( ! addrrouter->add_route($left, $right) ) { next SUBST; } $self->move_to_route($left); } delete $substh_of{ident $self}->{$right}; } } sub resolve_unknown_argument { my ($self) = @_; my @addrs = keys %{$unknownargh_of{ident $self}}; my %resolved_of; logger->info("Start resolve unknown argument : count[".($#addrs + 1)."]"); ARG: foreach my $mtdaddr ( @addrs ) { if ( $mtdaddr !~ m{ \A (.+)\.W:([^.]+?) \z }xms ) { next ARG; } my ($findaddr, $mtdnm) = ($1, $2); if ( ! exists $resolved_of{$findaddr} ) { $resolved_of{$findaddr} = undef; if ( addrrouter->exist_route($findaddr) ) { $resolved_of{$findaddr} = addrrouter->resolve_address($findaddr); } } my $resolve = $resolved_of{$findaddr}; if ( ! $resolve || ! $resolve->isa("PlSense::Entity::Instance") ) { next ARG; } my $mdl = mdlkeeper->get_module( $resolve->get_modulenm ) or next ARG; my $mtd = $mdl->get_any_method($mtdnm) or next ARG; logger->debug("Resolved unknown argument : $mtdaddr -> ".$mtd->get_fullnm); my $idxh = $unknownargh_of{ident $self}->{$mtdaddr}; INDEX: foreach my $idx ( keys %$idxh ) { my $curraddr = $mtd->get_fullnm."[".$idx."]"; VALUE: foreach my $value ( @{$idxh->{$idx}} ) { $self->add_substitute($curraddr, $value); # Add reverse route if value is a argument to super method if ( eval { $value->isa("PlSense::Entity") } ) { next VALUE; } if ( $mtdnm !~ m{ \A SUPER:: }xms ) { next VALUE; } addrrouter->add_reverse_route($value, $curraddr); } } delete $unknownargh_of{ident $self}->{$mtdaddr}; } } sub to_string_by_regexp { my ($self, $regexp) = @_; my $ret = ""; SUBST: foreach my $right ( keys %{$substh_of{ident $self}} ) { if ( $right !~ m{ $regexp }xms ) { next SUBST; } my $substs = $substh_of{ident $self}->{$right} or next SUBST; SUBST: foreach my $left ( @{$substs} ) { $ret .= "$left -> $right\n"; } } return $ret; } sub describe_keep_value { my ($self) = @_; my @substs = keys %{$substh_of{ident $self}}; my $substkeys = 0; SUBST: foreach my $right ( @substs ) { my $substs = $substh_of{ident $self}->{$right} or next SUBST; $substkeys += $#{$substs} + 1; } my @unargs = keys %{$unknownargh_of{ident $self}}; my $unargvalues = 0; ARG: foreach my $mtdaddr ( @unargs ) { my $idxh = $unknownargh_of{ident $self}->{$mtdaddr}; INDEX: foreach my $idx ( keys %$idxh ) { my $values = $idxh->{$idx} or next INDEX; $unargvalues += $#{$values} + 1; } } my $ret = "Substitute ... Lefts:".$substkeys." Rights:".($#substs+1)."\n"; $ret .= "Not Clear Argument ... Entrys:".($#unargs+1)." Values:".$unargvalues."\n"; return $ret; } sub add_substitute_sentinel : PRIVATE { my ($self, $left, $right) = @_; if ( ! $left || ! $right ) { return; } my $substs = $substh_of{ident $self}->{$right}; if ( ! $substs ) { $substs = []; $substh_of{ident $self}->{$right} = $substs; } if ( any { $_ eq $left } @{$substs} ) { return; } if ( $#{$substs} + 1 >= $max_entry_of{ident $self} ) { splice @{$substs}, $#{$substs} - 1, 1; } push @{$substs}, $left; logger->debug("Add substitute : $left -> $right"); } sub move_to_route : PRIVATE { my ($self, $addr) = @_; logger->debug("Move to route : $addr"); my %substs_of; ROUTABLE: foreach my $right ( grep { index($addr, $_) == 0 || index($_, $addr) == 0 } keys %{$substh_of{ident $self}} ) { $substs_of{$right} = $substh_of{ident $self}->{$right}; delete $substh_of{ident $self}->{$right}; } FOUND: foreach my $right ( keys %substs_of ) { my $substs = $substs_of{$right} or next FOUND; SUBST: foreach my $left ( @{$substs} ) { if ( ! addrrouter->add_route($left, $right) ) { next SUBST; } $self->move_to_route($left); } } } sub load_by_substitute_key : PRIVATE { my ($self, $key, $is_project) = @_; my $loadh; if ( ! $is_project ) { try { $loadh = $cache_of{ident $self}->get($key); } catch { $loadh = $cache_of{ident $self}->get($key); }; } elsif ( $projcache_of{ident $self} ) { try { $loadh = $projcache_of{ident $self}->get($key); } catch { $loadh = $projcache_of{ident $self}->get($key); }; } if ( ! $loadh ) { return; } RIGHTADDR: foreach my $rightaddr ( keys %$loadh ) { LEFTADDR: foreach my $leftaddr ( @{$loadh->{$rightaddr}} ) { $self->add_substitute_sentinel($leftaddr, $rightaddr); } } } sub load_by_unknown_argument_key : PRIVATE { my ($self, $key, $is_project) = @_; my $loadh; if ( ! $is_project ) { try { $loadh = $cache_of{ident $self}->get($key); } catch { $loadh = $cache_of{ident $self}->get($key); }; } elsif ( $projcache_of{ident $self} ) { try { $loadh = $projcache_of{ident $self}->get($key); } catch { $loadh = $projcache_of{ident $self}->get($key); }; } if ( ! $loadh ) { return; } MTDADDR: foreach my $mtdaddr ( keys %$loadh ) { IDX: foreach my $idx ( keys %{$loadh->{$mtdaddr}} ) { VALUE: foreach my $value ( @{$loadh->{$mtdaddr}->{$idx}} ) { $self->add_unknown_argument($mtdaddr, $idx, $value); } } } } sub remove_by_substitute_key : PRIVATE { my ($self, $key, $is_project, $memoryonly) = @_; my $loadh; if ( ! $is_project ) { try { $loadh = $cache_of{ident $self}->get($key); } catch { $loadh = $cache_of{ident $self}->get($key); }; } elsif ( $projcache_of{ident $self} ) { try { $loadh = $projcache_of{ident $self}->get($key); } catch { $loadh = $projcache_of{ident $self}->get($key); }; } if ( ! $loadh ) { return; } RIGHTADDR: foreach my $rightaddr ( keys %$loadh ) { my $substs = $substh_of{ident $self}->{$rightaddr}; if ( ! $substs ) { next RIGHTADDR; } LEFTADDR: foreach my $leftaddr ( @{$loadh->{$rightaddr}} ) { my $idx = firstidx { $_ eq $leftaddr } @{$substs}; if ( $idx < 0 ) { addrrouter->remove_route($leftaddr, $rightaddr); } else { splice @{$substs}, $idx, 1; } } if ( $#{$substs} < 0 ) { delete $substh_of{ident $self}->{$rightaddr}; } } if ( $memoryonly ) { return; } if ( ! $is_project ) { try { $cache_of{ident $self}->remove($key); } catch { $cache_of{ident $self}->remove($key); }; } elsif ( $projcache_of{ident $self} ) { try { $projcache_of{ident $self}->remove($key); } catch { $projcache_of{ident $self}->remove($key); }; } } sub remove_by_unknown_argument_key : PRIVATE { my ($self, $key, $is_project, $memoryonly) = @_; my $loadh; if ( ! $is_project ) { try { $loadh = $cache_of{ident $self}->get($key); } catch { $loadh = $cache_of{ident $self}->get($key); }; } elsif ( $projcache_of{ident $self} ) { try { $loadh = $projcache_of{ident $self}->get($key); } catch { $loadh = $projcache_of{ident $self}->get($key); }; } if ( ! $loadh ) { return; } MTDADDR: foreach my $mtdaddr ( keys %$loadh ) { my $lidxh = $loadh->{$mtdaddr}; my $idxh = $unknownargh_of{ident $self}->{$mtdaddr}; if ( ! $idxh ) { next MTDADDR; } IDX: foreach my $idx ( keys %$lidxh ) { my $values = $idxh->{$idx} or next IDX; VALUE: foreach my $v ( @{$lidxh->{$idx}} ) { my $fidx = eval { $v->get_type } ? firstidx { eval { $_->to_string eq $v->to_string } } @{$values} : firstidx { ! eval { $_->get_type } && $_ eq $v } @{$values}; if ( $fidx < 0 ) { next VALUE; } splice @{$values}, $fidx, 1; } if ( $#{$values} < 0 ) { delete $idxh->{$idx}; } } my @idxs = keys %$idxh; if ( $#idxs < 0 ) { delete $unknownargh_of{ident $self}->{$mtdaddr}; } } if ( $memoryonly ) { return; } if ( ! $is_project ) { try { $cache_of{ident $self}->remove($key); } catch { $cache_of{ident $self}->remove($key); }; } elsif ( $projcache_of{ident $self} ) { try { $projcache_of{ident $self}->remove($key); } catch { $projcache_of{ident $self}->remove($key); }; } } sub load_installed_all : PRIVATE { my $self = shift; my $not_resolve_subst = shift || 0; my @keys; try { @keys = $cache_of{ident $self}->get_keys; } catch { @keys = $cache_of{ident $self}->get_keys; }; KEY: foreach my $key ( @keys ) { my $ch = substr($key, 1, 1); if ( $ch eq 'S' ) { addrrouter->load_by_cache_key(substr($key, 3)); $self->load_by_substitute_key($key, 0); } elsif ( $ch eq 'A' ) { $self->load_by_unknown_argument_key($key, 0); } } logger->info("Loaded subst/arg info of installed module all"); if ( ! $not_resolve_subst ) { $self->resolve_substitute; } } sub load_project_all : PRIVATE { my $self = shift; my $not_resolve_subst = shift || 0; if ( $self->get_project eq get_default_config("name") ) { return; } my @keys; try { @keys = $projcache_of{ident $self}->get_keys; } catch { @keys = $projcache_of{ident $self}->get_keys; }; KEY: foreach my $key ( @keys ) { my $ch = substr($key, 1, 1); if ( $ch eq 'S' ) { addrrouter->load_by_cache_key(substr($key, 3)); $self->load_by_substitute_key($key, 1); } elsif ( $ch eq 'A' ) { $self->load_by_unknown_argument_key($key, 1); } } logger->info("Loaded subst/arg info of project module all"); if ( ! $not_resolve_subst ) { $self->resolve_substitute; } } sub remove_project_all_sentinel : PRIVATE { my $self = shift; my $memoryonly = shift || 0; my @keys; try { @keys = $projcache_of{ident $self}->get_keys; } catch { @keys = $projcache_of{ident $self}->get_keys; }; KEY: foreach my $key ( @keys ) { my $ch = substr($key, 1, 1); if ( $ch eq 'S' ) { $memoryonly ? addrrouter->remove_by_cache_key_on_memory(substr($key, 3)) : addrrouter->remove_by_cache_key(substr($key, 3)); $self->remove_by_substitute_key($key, 1, $memoryonly); } elsif ( $ch eq 'A' ) { $self->remove_by_unknown_argument_key($key, 1, $memoryonly); } } logger->info("Removed subst/arg info of project module all : memoryonly[$memoryonly]"); } } 1; __END__ plsense-0.3.4/lib/PlSense/Symbol.pm000066400000000000000000000034671260377356000171340ustar00rootroot00000000000000package PlSense::Symbol; use strict; use warnings; use Class::Std::Storable; use PlSense::Logger; { my %name_of :ATTR( :init_arg ); sub get_name { my ($self) = @_; return $name_of{ident $self}; } my %type_of :ATTR( :default('') ); sub set_type { my ($self, $type) = @_; $type_of{ident $self} = $type; } sub get_type { my ($self) = @_; return $type_of{ident $self}; } my %helptext_of :ATTR( :init_arg :default('') ); sub set_helptext { my ($self, $helptext) = @_; $helptext_of{ident $self} = $helptext; } sub get_helptext { my ($self) = @_; return $helptext_of{ident $self}; } my %linenumber_of :ATTR( :init_arg :default(0) ); sub set_linenumber { my ($self, $linenumber) = @_; if ( $linenumber !~ m{ ^\d+$ }xms ) { logger->warn("Not Integer"); return; } $linenumber_of{ident $self} = $linenumber; logger->debug("Set linenumber[$linenumber] to ".$self->get_fullnm); } sub get_linenumber { my ($self) = @_; return $linenumber_of{ident $self}; } my %colnumber_of :ATTR( :init_arg :default(0) ); sub set_colnumber { my ($self, $colnumber) = @_; if ( $colnumber !~ m{ ^\d+$ }xms ) { logger->warn("Not Integer"); return; } $colnumber_of{ident $self} = $colnumber; logger->debug("Set colnumber[$colnumber] to ".$self->get_fullnm); } sub get_colnumber { my ($self) = @_; return $colnumber_of{ident $self}; } sub START { my ($class, $ident, $arg_ref) = @_; my $name = $name_of{$ident} || ""; if ( ! $name ) { logger->error("Name is invalid value : [$name]"); } } sub get_fullnm { my $self = shift; return $self->get_name(); } } 1; __END__ plsense-0.3.4/lib/PlSense/Symbol/000077500000000000000000000000001260377356000165645ustar00rootroot00000000000000plsense-0.3.4/lib/PlSense/Symbol/Method.pm000066400000000000000000000111061260377356000203410ustar00rootroot00000000000000package PlSense::Symbol::Method; use parent qw{ PlSense::Symbol }; use strict; use warnings; use Class::Std::Storable; use Scalar::Util qw{ weaken }; use PlSense::Logger; { my %publicly_is :ATTR( :init_arg :default(0) ); sub set_publicly { my ($self, $publicly) = @_; $publicly_is{ident $self} = $publicly; } sub is_publicly { my ($self) = @_; return $publicly_is{ident $self}; } my %privately_is :ATTR( :init_arg :default(0) ); sub set_privately { my ($self, $privately) = @_; $privately_is{ident $self} = $privately; } sub is_privately { my ($self) = @_; return $privately_is{ident $self}; } my %importive_is :ATTR( :init_arg :default(0) ); sub set_importive { my ($self, $importive) = @_; $importive_is{ident $self} = $importive; } sub is_importive { my ($self) = @_; return $importive_is{ident $self}; } my %reserved_is :ATTR( :init_arg :default(0) ); sub set_reserved { my ($self, $reserved) = @_; $reserved_is{ident $self} = $reserved; } sub is_reserved { my ($self) = @_; return $reserved_is{ident $self}; } my %attribute_of :ATTR( :default(undef) ); sub set_attribute { my ($self, $attribute) = @_; $attribute_of{ident $self} = $attribute; } sub get_attribute { my ($self) = @_; return $attribute_of{ident $self}; } my %module_of :ATTR( :init_arg :default('') ); sub set_module { my ($self, $module) = @_; if ( ! $module || ! $module->isa("PlSense::Symbol::Module") ) { logger->error("Not PlSense::Symbol::Module"); return; } $module_of{ident $self} = $module; weaken $module_of{ident $self}; $module->set_method($self->get_name, $self); } sub get_module { my ($self) = @_; return $module_of{ident $self}; } my %variableh_of :ATTR(); sub set_variable { my ($self, $variablenm, $variable) = @_; if ( ! $variable || ! $variable->isa("PlSense::Symbol::Variable") ) { logger->error("Not PlSense::Symbol::Variable"); return; } if ( $variablenm ne $variable->get_name() ) { logger->warn("Not equal key[$variablenm] and variable's name[".$variable->get_name()."]"); return; } $variableh_of{ident $self}->{$variablenm} = $variable; logger->debug("Set variable of [".$self->get_fullnm()."] : $variablenm"); } sub exist_variable { my ($self, $variablenm) = @_; return $variablenm && exists $variableh_of{ident $self}->{$variablenm}; } sub get_variable { my ($self, $variablenm) = @_; if ( ! exists $variableh_of{ident $self}->{$variablenm} ) { logger->warn("Not exist variable[$variablenm] in ".$self->get_fullnm); return; } return $variableh_of{ident $self}->{$variablenm}; } sub keys_variable { my ($self) = @_; return keys %{$variableh_of{ident $self}}; } my %argumenth_of :ATTR(); sub set_argument { my ($self, $idx, $variable) = @_; if ( ! $variable || ! $variable->isa("PlSense::Symbol::Variable") ) { logger->error("Not PlSense::Symbol::Variable"); return; } $argumenth_of{ident $self}->{$idx} = $variable; logger->debug("Set [$idx] argument of [".$self->get_fullnm."] : ".$variable->get_fullnm); } sub get_argument { my ($self, $idx) = @_; if ( ! exists $argumenth_of{ident $self}->{$idx} ) { return; } return $argumenth_of{ident $self}->{$idx}; } sub get_arguments { my ($self) = @_; my @ret; my $idx = 1; ARG: while ( exists $argumenth_of{ident $self}->{$idx} ) { push @ret, $argumenth_of{ident $self}->{$idx}; $idx++; } return @ret; } sub BUILD { my ($class, $ident, $arg_ref) = @_; $class->set_type("method"); $variableh_of{$ident} = {}; $argumenth_of{$ident} = {}; } sub START { my ($class, $ident, $arg_ref) = @_; if ( exists $arg_ref->{module} ) { $class->set_module($arg_ref->{module}); logger->debug("New method : name[".$class->get_name."] module[".$class->get_module->get_name."]"); } else { logger->debug("New method : name[".$class->get_name."]"); } } sub get_fullnm { my $self = shift; my $module = $module_of{ident $self}; return $module ? "&".$module->get_fullnm."::".$self->get_name : "&".$self->get_name; } } 1; __END__ plsense-0.3.4/lib/PlSense/Symbol/Module.pm000066400000000000000000000655621260377356000203650ustar00rootroot00000000000000package PlSense::Symbol::Module; use parent qw{ PlSense::Symbol }; use strict; use warnings; use Class::Std::Storable; use List::AllUtils qw{ first uniq firstidx }; use Scalar::Util qw{ weaken }; use PlSense::Logger; { my %filepath_of :ATTR( :init_arg ); sub get_filepath { my ($self) = @_; return $filepath_of{ident $self}; } my %projectnm_of :ATTR( :init_arg :default('') ); sub get_projectnm { my ($self) = @_; return $projectnm_of{ident $self}; } my %lastmodified_of :ATTR( :init_arg ); sub get_lastmodified { my ($self) = @_; return $lastmodified_of{ident $self}; } my %initialized_is :ATTR( :default(0) ); sub initialized { my ($self) = @_; $initialized_is{ident $self} = 1; } sub uninitialized { my ($self) = @_; $initialized_is{ident $self} = 0; } sub is_initialized { my ($self) = @_; return $initialized_is{ident $self}; } my %parents_of :ATTR(); sub update_parent { my ($self) = @_; DELETE_INVALID: while ( ( my $idx = firstidx { ! $_ } @{$parents_of{ident $self}} ) >= 0 ) { splice @{$parents_of{ident $self}}, $idx, 1; } } sub push_parent { my ($self, $parent, $not_weaken) = @_; if ( ! $parent || ! $parent->isa("PlSense::Symbol::Module") ) { logger->error("Not PlSense::Symbol::Module"); return; } if ( $self->exist_parent($parent->get_name) ) { logger->warn("Already exist [".$parent->get_name()."]"); return; } push @{$parents_of{ident $self}}, $parent; if ( ! $not_weaken ) { weaken @{$parents_of{ident $self}}[-1]; } } sub count_parent { my ($self) = @_; $self->update_parent; return $#{$parents_of{ident $self}} + 1; } sub get_parent { my ($self, $index) = @_; if ( $index !~ m{ ^\d+$ }xms ) { logger->warn("Not Integer"); return; } if ( $index < 1 || $index > $#{$parents_of{ident $self}} + 1 ) { logger->warn("Out of Index"); return; } return @{$parents_of{ident $self}}[$index - 1]; } sub exist_parent { my ($self, $mdlnm) = @_; my @ret = grep { $_ && $_->get_name eq $mdlnm } @{$parents_of{ident $self}}; return $#ret >= 0 ? 1 : 0; } sub reset_parent { my ($self) = @_; $parents_of{ident $self} = []; } my %usingmdls_of :ATTR(); sub update_usingmdl { my ($self) = @_; DELETE_INVALID: while ( ( my $idx = firstidx { ! $_ } @{$usingmdls_of{ident $self}} ) >= 0 ) { splice @{$usingmdls_of{ident $self}}, $idx, 1; } } sub push_usingmdl { my ($self, $usingmdl, $not_weaken) = @_; if ( ! $usingmdl || ! $usingmdl->isa("PlSense::Symbol::Module") ) { logger->error("Not PlSense::Symbol::Module"); return; } if ( $self->exist_usingmdl($usingmdl->get_name()) ) { logger->warn("Already exist : ".$usingmdl->get_name()); return; } push @{$usingmdls_of{ident $self}}, $usingmdl; if ( ! $not_weaken ) { weaken @{$usingmdls_of{ident $self}}[-1]; } } sub count_usingmdl { my ($self) = @_; $self->update_usingmdl; return $#{$usingmdls_of{ident $self}} + 1; } sub get_usingmdl { my ($self, $index) = @_; if ( $index !~ m{ ^\d+$ }xms ) { logger->warn("Not Integer"); return; } if ( $index < 1 || $index > $#{$usingmdls_of{ident $self}} + 1 ) { logger->warn("Out of Index"); return; } return @{$usingmdls_of{ident $self}}[$index - 1]; } sub exist_usingmdl { my ($self, $mdlnm) = @_; my @ret = grep { $_ && $_->get_name eq $mdlnm } @{$usingmdls_of{ident $self}}; return $#ret >= 0 ? 1 : 0; } sub reset_usingmdl { my ($self) = @_; $usingmdls_of{ident $self} = []; } my %bundlemdls_of :ATTR( :default(undef) ); sub update_bundlemdl { my ($self) = @_; DELETE_INVALID: while ( ( my $idx = firstidx { ! $_ } @{$bundlemdls_of{ident $self}} ) >= 0 ) { splice @{$bundlemdls_of{ident $self}}, $idx, 1; } } sub push_bundlemdl { my ($self, $bundlemdl, $not_weaken) = @_; if ( ! $bundlemdl || ! $bundlemdl->isa("PlSense::Symbol::Module") ) { logger->error("Not PlSense::Symbol::Module"); return; } if ( $self->exist_bundlemdl($bundlemdl->get_name()) ) { logger->warn("Already exist : ".$bundlemdl->get_name()); return; } push @{$bundlemdls_of{ident $self}}, $bundlemdl; if ( ! $not_weaken ) { weaken @{$bundlemdls_of{ident $self}}[-1]; } } sub count_bundlemdl { my ($self) = @_; $self->update_bundlemdl; return $#{$bundlemdls_of{ident $self}} + 1; } sub get_bundlemdl { my ($self, $index) = @_; if ( ! $index || $index !~ m{ ^\d+$ }xms ) { logger->warn("Not Integer"); return; } if ( $index < 1 || $index > $#{$bundlemdls_of{ident $self}} + 1 ) { logger->warn("Out of Index"); return; } return @{$bundlemdls_of{ident $self}}[$index - 1]; } sub exist_bundlemdl { my ($self, $mdlnm) = @_; my @ret = grep { $_ && $_->get_name eq $mdlnm } @{$bundlemdls_of{ident $self}}; return $#ret >= 0 ? 1 : 0; } sub reset_bundlemdl { my ($self) = @_; $bundlemdls_of{ident $self} = []; } my %memberh_of :ATTR(); sub set_member { my ($self, $membernm, $member) = @_; if ( ! $member || ! $member->isa("PlSense::Symbol::Variable") ) { logger->error("Not PlSense::Symbol::Variable"); return; } if ( $membernm ne $member->get_name() ) { logger->warn("Not equal key[$membernm] and member's name[".$member->get_name()."]"); return; } $memberh_of{ident $self}->{$membernm} = $member; } sub exist_member { my ($self, $membernm) = @_; return $membernm && exists $memberh_of{ident $self}->{$membernm}; } sub get_member { my ($self, $membernm) = @_; if ( ! exists $memberh_of{ident $self}->{$membernm} ) { logger->warn("Not exist member[$membernm] in ".$self->get_fullnm); return; } return $memberh_of{ident $self}->{$membernm}; } sub keys_member { my ($self) = @_; return keys %{$memberh_of{ident $self}}; } my %methodh_of :ATTR(); sub set_method { my ($self, $methodnm, $method) = @_; if ( ! $method || ! $method->isa("PlSense::Symbol::Method") ) { logger->error("Not PlSense::Symbol::Method"); return; } if ( $methodnm ne $method->get_name() ) { logger->warn("Not equal key[$methodnm] and method's name[".$method->get_name()."]"); return; } $methodh_of{ident $self}->{$methodnm} = $method; } sub exist_method { my ($self, $methodnm) = @_; return $methodnm && exists $methodh_of{ident $self}->{$methodnm}; } sub get_method { my ($self, $methodnm) = @_; if ( ! exists $methodh_of{ident $self}->{$methodnm} ) { logger->warn("Not exist method[$methodnm] in ".$self->get_fullnm); return; } return $methodh_of{ident $self}->{$methodnm}; } sub keys_method { my ($self) = @_; return keys %{$methodh_of{ident $self}}; } my %source_of :ATTR(); sub set_source { my ($self, $source) = @_; $source_of{ident $self} = $source; } sub get_source { my ($self) = @_; return $source_of{ident $self}; } sub BUILD { my ($class, $ident, $arg_ref) = @_; $class->set_type("module"); $class->reset_all; my $name = $arg_ref->{name} || ""; if ( ! $name || $name !~ m{ ^ [a-zA-Z_][a-zA-Z0-9_:]* $ }xms ) { logger->error("Name is invalid value : [$name]"); } my $filepath = $arg_ref->{filepath} || ""; if ( ! -f $filepath ) { logger->error("Not exist file[$filepath]"); } } sub reset_all { my ($self, $lastmodified) = @_; $parents_of{ident $self} = []; $usingmdls_of{ident $self} = []; $bundlemdls_of{ident $self} = []; $memberh_of{ident $self} = {}; $methodh_of{ident $self} = {}; $source_of{ident $self} = undef; $initialized_is{ident $self} = 0; if ( $lastmodified ) { $lastmodified_of{ident $self} = $lastmodified; } } sub renew { my ($self) = @_; return PlSense::Symbol::Module->new({ name => $self->get_name, filepath => $self->get_filepath, projectnm => $self->get_projectnm, lastmodified => $self->get_lastmodified, linenumber => $self->get_linenumber, colnumber => $self->get_colnumber, }); } sub interchange_to { my ($self, $mdl) = @_; if ( ! $mdl || ! $mdl->isa("PlSense::Symbol::Module") ) { return; } $self->reset_all($mdl->get_lastmodified); MEMBER: foreach my $membernm ( $mdl->keys_member ) { my $member = $mdl->get_member($membernm); $member->set_belong($self); } METHOD: foreach my $methodnm ( $mdl->keys_method ) { my $method = $mdl->get_method($methodnm); $method->set_module($self); } PARENT: for my $i ( 1..$mdl->count_parent ) { $self->push_parent( $mdl->get_parent($i) ); } USINGMDL: for my $i ( 1..$mdl->count_usingmdl ) { $self->push_usingmdl( $mdl->get_usingmdl($i) ); } BUNDLEMDL: for my $i ( 1..$mdl->count_bundlemdl ) { $self->push_bundlemdl( $mdl->get_bundlemdl($i) ); } $self->set_helptext($mdl->get_helptext); $self->set_source($mdl->get_source); $mdl->is_initialized ? $self->initialized : $self->uninitialized; } sub get_fullnm { my $self = shift; return $self->get_name eq "main" ? "main[".$self->get_filepath."]" : $self->get_name; } sub to_detail_string { my $self = shift; my $ret = ""; my $first; my $addr = sprintf("%s", $self); $addr =~ s{ ^ PlSense::Symbol::Module=SCALAR\((.+)\) $ }{$1}xms; $ret .= "MYSELF: ".$self->get_name."($addr)\n"; $ret .= "PARENT: "; $first = 1; PARENT: for ( my $i = 1; $i <= $self->count_parent; $i++ ) { my $mdl = $self->get_parent($i); if ( ! $first ) { $ret .= ", "; } $first = 0; $ret .= $mdl->get_name; my $addr = sprintf("%s", $mdl); $addr =~ s{ ^ PlSense::Symbol::Module=SCALAR\((.+)\) $ }{$1}xms; $ret .= "($addr)"; } $ret .= "\n"; $ret .= "INCLUDE: "; $first = 1; USINGMDL: for ( my $i = 1; $i <= $self->count_usingmdl; $i++ ) { my $mdl = $self->get_usingmdl($i); if ( ! $first ) { $ret .= ", "; } $first = 0; $ret .= $mdl->get_name; my $addr = sprintf("%s", $mdl); $addr =~ s{ ^ PlSense::Symbol::Module=SCALAR\((.+)\) $ }{$1}xms; $ret .= "($addr)"; } $ret .= "\n"; MEMBER: foreach my $var ( values %{$memberh_of{ident $self}} ) { $ret .= $var->get_name." LEXICAL[".$var->is_lexical."] IMPORTIVE[".$var->is_importive."]\n"; } METHOD: foreach my $mtd ( values %{$methodh_of{ident $self}} ) { my $attr = $mtd->get_attribute; my $attrtext = $attr ? $attr->{content} : ""; $ret .= "&".$mtd->get_name." ATTR[".$attrtext."] PUBLIC[".$mtd->is_publicly."] PRIVATE[".$mtd->is_privately."] IMPORTIVE[".$mtd->is_importive."] RESERVED[".$mtd->is_reserved."]\n"; VAR: foreach my $varnm ( $mtd->keys_variable ) { my $var = $mtd->get_variable($varnm); $ret .= " ".$var->get_name." LEXICAL[".$var->is_lexical."] IMPORTIVE[".$var->is_importive."]\n"; } } return $ret; } sub is_objective { my $self = shift; return $self->exist_method("new"); } sub is_exportable { my $self = shift; return $self->exist_parent("Exporter") || $self->exist_usingmdl("Exporter"); } sub is_ancestor_of { my ($self, $mdl) = @_; if ( ! $mdl || ! $mdl->isa("PlSense::Symbol::Module") ) { return; } PARENT: for my $i ( 1..$mdl->count_parent ) { my $parent = $mdl->get_parent($i); if ( $parent->get_name eq $self->get_name ) { return 1; } $self->is_ancestor_of($parent) && return 1; } return; } sub get_own_methods { my ($self, $only_name) = @_; my %mtd_of; METHOD: foreach my $mtd ( values %{$methodh_of{ident $self}} ) { my $mtdnm = $mtd->get_name; if ( $mtd->is_importive ) { next METHOD; } $mtd_of{$mtdnm} = $mtd; } my @ret; PUSH: foreach my $mtdnm ( sort keys %mtd_of ) { push @ret, $only_name ? $mtdnm : $mtd_of{$mtdnm}; } return @ret; } sub get_inherit_methods { my ($self, $only_name) = @_; my %mtd_of; PARENT: for ( my $i = 1; $i <= $self->count_parent; $i++ ) { my $parent = $self->get_parent($i); PARENTMTD: foreach my $mtd ( $parent->get_not_private_methods ) { if ( exists $mtd_of{$mtd->get_name} ) { next PARENTMTD; } $mtd_of{$mtd->get_name} = $mtd; } } my @ret; PUSH: foreach my $mtdnm ( sort keys %mtd_of ) { push @ret, $only_name ? $mtdnm : $mtd_of{$mtdnm}; } return @ret; } sub get_public_methods { my ($self, $only_name) = @_; my %mtd_of; METHOD: foreach my $mtd ( values %{$methodh_of{ident $self}} ) { my $mtdnm = $mtd->get_name; if ( $mtd->is_importive ) { next METHOD; } if ( $mtd->is_reserved ) { next METHOD; } if ( ! $mtd->is_publicly ) { next METHOD; } $mtd_of{$mtdnm} = $mtd; } PARENT: for ( my $i = 1; $i <= $self->count_parent; $i++ ) { my $parent = $self->get_parent($i); PARENTMTD: foreach my $mtd ( $parent->get_public_methods ) { if ( exists $mtd_of{$mtd->get_name} ) { next PARENTMTD; } $mtd_of{$mtd->get_name} = $mtd; } } my @ret; PUSH: foreach my $mtdnm ( sort keys %mtd_of ) { push @ret, $only_name ? $mtdnm : $mtd_of{$mtdnm}; } return @ret; } sub get_not_private_methods { my ($self, $only_name) = @_; my %mtd_of; METHOD: foreach my $mtd ( values %{$methodh_of{ident $self}} ) { my $mtdnm = $mtd->get_name; if ( $mtd->is_importive ) { next METHOD; } if ( $mtd->is_reserved ) { next METHOD; } if ( $mtd->is_privately ) { next METHOD; } $mtd_of{$mtdnm} = $mtd; } INHERITMTD: foreach my $mtd ( $self->get_inherit_methods ) { if ( exists $mtd_of{$mtd->get_name} ) { next INHERITMTD; } $mtd_of{$mtd->get_name} = $mtd; } my @ret; PUSH: foreach my $mtdnm ( sort keys %mtd_of ) { push @ret, $only_name ? $mtdnm : $mtd_of{$mtdnm}; } return @ret; } sub get_all_objective_methods { my ($self, $only_name) = @_; my %mtd_of; METHOD: foreach my $mtd ( values %{$methodh_of{ident $self}} ) { my $mtdnm = $mtd->get_name; if ( $mtd->is_importive ) { next METHOD; } if ( $mtd->is_reserved ) { next METHOD; } $mtd_of{$mtdnm} = $mtd; } INHERITMTD: foreach my $mtd ( $self->get_inherit_methods ) { if ( exists $mtd_of{$mtd->get_name} ) { next INHERITMTD; } $mtd_of{$mtd->get_name} = $mtd; } my @ret; PUSH: foreach my $mtdnm ( sort keys %mtd_of ) { push @ret, $only_name ? $mtdnm : $mtd_of{$mtdnm}; } return @ret; } sub get_instance_methods { my ($self, $mdl, $only_name) = @_; $only_name = $only_name ? 1 : 0; my $is_me = $mdl && $mdl->isa("PlSense::Symbol::Module") && $self->get_name eq $mdl->get_name ? 1 : 0; my $is_ancestor = $self->is_ancestor_of($mdl) ? 1 : 0; my $mdltext = $mdl && $mdl->isa("PlSense::Symbol::Module") ? $mdl->get_name : ""; logger->debug("Get instance methods of [".$self->get_name."] in [$mdltext]. is_me[$is_me] is_ancestor[$is_ancestor] only_name[$only_name]"); return $is_me ? $self->get_all_objective_methods($only_name) : $is_ancestor ? $self->get_not_private_methods($only_name) : $self->get_public_methods($only_name); } sub get_static_methods { my ($self, $mdl, $only_name) = @_; my %mtd_of; INSTANCEMTD: foreach my $mtd ( $self->get_instance_methods($mdl) ) { $mtd_of{$mtd->get_name} = $mtd; } IMPORTMTD: foreach my $mtd ( values %{$methodh_of{ident $self}} ) { my $mtdnm = $mtd->get_name; if ( ! $mtd->is_importive ) { next IMPORTMTD; } if ( $mtd->is_reserved ) { next IMPORTMTD; } if ( exists $mtd_of{$mtdnm} ) { next IMPORTMTD; } USINGMDL: for ( my $i = 1; $i <= $self->count_usingmdl; $i++ ) { my $m = $self->get_usingmdl($i); if ( ! $m->exist_method($mtdnm) ) { next USINGMDL; } my $extmtd = $m->get_method($mtdnm); if ( $extmtd->is_importive ) { next USINGMDL; } $mtd_of{$mtdnm} = $extmtd; last USINGMDL; } if ( ! exists $mtd_of{$mtdnm} ) { $mtd_of{$mtdnm} = $mtd; } } my @ret; PUSH: foreach my $mtdnm ( sort keys %mtd_of ) { push @ret, $only_name ? $mtdnm : $mtd_of{$mtdnm}; } return @ret; } sub get_any_methods { my ($self, $only_name) = @_; my %mtd_of; METHOD: foreach my $mtd ( values %{$methodh_of{ident $self}} ) { my $mtdnm = $mtd->get_name; $mtd_of{$mtdnm} = $mtd; } INHERITMTD: foreach my $mtd ( $self->get_inherit_methods ) { if ( exists $mtd_of{$mtd->get_name} ) { next INHERITMTD; } $mtd_of{$mtd->get_name} = $mtd; } my @ret; PUSH: foreach my $mtdnm ( sort keys %mtd_of ) { push @ret, $only_name ? $mtdnm : $mtd_of{$mtdnm}; } return @ret; } sub get_any_original_methods { my ($self, $only_name) = @_; my %mtd_of; METHOD: foreach my $mtd ( values %{$methodh_of{ident $self}} ) { my $mtdnm = $mtd->get_name; if ( $mtd->is_importive ) { USINGMDL: for ( my $i = 1; $i <= $self->count_usingmdl; $i++ ) { my $m = $self->get_usingmdl($i); if ( ! $m->exist_method($mtdnm) ) { next USINGMDL; } my $extmtd = $m->get_method($mtdnm); # if ( $extmtd->is_importive ) { next USINGMDL; } $mtd_of{$mtdnm} = $extmtd; last USINGMDL; } if ( ! exists $mtd_of{$mtdnm} ) { $mtd_of{$mtdnm} = $mtd; } } else { $mtd_of{$mtdnm} = $mtd; } } INHERITMTD: foreach my $mtd ( $self->get_inherit_methods ) { if ( exists $mtd_of{$mtd->get_name} ) { next INHERITMTD; } $mtd_of{$mtd->get_name} = $mtd; } my @ret; PUSH: foreach my $mtdnm ( sort keys %mtd_of ) { push @ret, $only_name ? $mtdnm : $mtd_of{$mtdnm}; } return @ret; } sub get_external_methods { my ($self, $only_name) = @_; my %mtd_of; USINGMDL: for ( my $i = 1; $i <= $self->count_usingmdl; $i++ ) { my $m = $self->get_usingmdl($i); MTD: foreach my $mtd ( $m->get_public_methods ) { if ( exists $mtd_of{$mtd->get_fullnm} ) { next MTD; } $mtd_of{$mtd->get_fullnm} = $mtd; } } my @ret; PUSH: foreach my $mtdnm ( sort keys %mtd_of ) { push @ret, $only_name ? $mtdnm : $mtd_of{$mtdnm}; } return @ret; } sub get_instance_method { my ($self, $mdl, $mtdnm) = @_; return first { $mtdnm && $_->get_name eq $mtdnm } $self->get_instance_methods($mdl); } sub get_any_method { my ($self, $mtdnm) = @_; if ( ! $mtdnm ) { return; } if ( $mtdnm =~ s{ \A SUPER:: }{}xms ) { PARENT: for my $i ( 1..$self->count_parent ) { my $parent = $self->get_parent($i); # I'm not sure which method is right, get_any_method, get_instance_method. my $mtd = $parent->get_any_method($mtdnm) or next PARENT; return $mtd; } } else { return first { $_->get_name eq $mtdnm } $self->get_any_methods; } } sub get_any_original_method { my ($self, $mtdnm) = @_; my $mtd = $self->get_any_method($mtdnm) or return; if ( ! $mtd->is_importive ) { return $mtd; } USINGMDL: for ( my $i = 1; $i <= $self->count_usingmdl; $i++ ) { my $m = $self->get_usingmdl($i); if ( ! $m->exist_method($mtdnm) ) { next USINGMDL; } my $extmtd = $m->get_method($mtdnm); # if ( $extmtd->is_importive ) { next USINGMDL; } return $extmtd; } return $mtd; } sub exist_instance_method { my ($self, $mdl, $mtdnm) = @_; return $self->get_instance_method($mdl, $mtdnm) ? 1 : 0; } sub exist_any_method { my ($self, $mtdnm) = @_; return $self->get_any_method($mtdnm) ? 1 : 0; } sub get_public_scalars { my ($self, $only_name) = @_; return $self->get_public_variables("scalar", $only_name); } sub get_public_arrays { my ($self, $only_name) = @_; return $self->get_public_variables("array", $only_name); } sub get_public_hashes { my ($self, $only_name) = @_; return $self->get_public_variables("hash", $only_name); } sub get_public_any_variables { my ($self, $only_name) = @_; return $self->get_public_variables("", $only_name); } sub get_public_variables : PRIVATE { my ($self, $type, $only_name) = @_; my %var_of; MEMBER: foreach my $var ( values %{$memberh_of{ident $self}} ) { if ( $var->is_lexical ) { next MEMBER; } # This comment out is wrong. but effort for bad module that not use 'my' and 'our' at definition # if ( $var->is_importive ) { next MEMBER; } if ( $type && $var->get_type ne $type ) { next MEMBER; } $var_of{$var->get_fullnm} = $var; } my @ret; PUSH: foreach my $varnm ( sort keys %var_of ) { push @ret, $only_name ? $varnm : $var_of{$varnm}; } return @ret; } sub get_current_scalars { my ($self, $methodnm, $only_name) = @_; return $self->get_current_variables("scalar", $methodnm, $only_name); } sub get_current_arrays { my ($self, $methodnm, $only_name) = @_; return $self->get_current_variables("array", $methodnm, $only_name); } sub get_current_hashes { my ($self, $methodnm, $only_name) = @_; return $self->get_current_variables("hash", $methodnm, $only_name); } sub get_current_any_variables { my ($self, $methodnm, $only_name) = @_; return $self->get_current_variables("", $methodnm, $only_name); } sub get_current_variables : PRIVATE { my ($self, $type, $mtdnm, $only_name) = @_; my %var_of; if ( $self->exist_method($mtdnm) ) { my $mtd = $self->get_method($mtdnm); VARIABLE: foreach my $varnm ( $mtd->keys_variable ) { my $var = $mtd->get_variable($varnm); if ( $type && $var->get_type ne $type ) { next VARIABLE; } if ( exists $var_of{$varnm} ) { next VARIABLE; } $var_of{$varnm} = $var; } } MEMBER: foreach my $var ( values %{$memberh_of{ident $self}} ) { my $varnm = $var->get_name; if ( $type && $var->get_type ne $type ) { next MEMBER; } if ( exists $var_of{$varnm} ) { next MEMBER; } $var_of{$varnm} = $var; } my @ret; PUSH: foreach my $varnm ( sort keys %var_of ) { push @ret, $only_name ? $varnm : $var_of{$varnm}; } return @ret; } sub get_external_scalars { my ($self, $only_name) = @_; return $self->get_external_variables("scalar", $only_name); } sub get_external_arrays { my ($self, $only_name) = @_; return $self->get_external_variables("array", $only_name); } sub get_external_hashes { my ($self, $only_name) = @_; return $self->get_external_variables("hash", $only_name); } sub get_external_any_variables { my ($self, $only_name) = @_; return $self->get_external_variables("", $only_name); } sub get_external_variables : PRIVATE { my ($self, $type, $only_name) = @_; my %var_of; USINGMDL: for ( my $i = 1; $i <= $self->count_usingmdl; $i++ ) { my $m = $self->get_usingmdl($i); VAR: foreach my $var ( $m->get_public_variables($type, 0) ) { if ( $type && $var->get_type ne $type ) { next VAR; } if ( exists $var_of{$var->get_fullnm} ) { next VAR; } $var_of{$var->get_fullnm} = $var; } } my @ret; PUSH: foreach my $varnm ( sort keys %var_of ) { push @ret, $only_name ? $varnm : $var_of{$varnm}; } return @ret; } sub get_all_parents { my ($self, $only_name) = @_; my @ret; PARENT: for ( my $i = 1; $i <= $self->count_parent; $i++ ) { my $parent = $self->get_parent($i); push @ret, $parent; push @ret, $parent->get_all_parents; } return ! $only_name ? @ret : map { $_->get_name } @ret; } } 1; __END__ plsense-0.3.4/lib/PlSense/Symbol/Variable.pm000066400000000000000000000043671260377356000206610ustar00rootroot00000000000000package PlSense::Symbol::Variable; use parent qw{ PlSense::Symbol }; use strict; use warnings; use Class::Std::Storable; use Scalar::Util qw{ weaken }; use PlSense::Logger; { my %lexical_is :ATTR( :init_arg :default(1) ); sub set_lexical { my ($self, $lexical) = @_; $lexical_is{ident $self} = $lexical; } sub is_lexical { my ($self) = @_; return $lexical_is{ident $self}; } my %importive_is :ATTR( :init_arg :default(0) ); sub set_importive { my ($self, $importive) = @_; $importive_is{ident $self} = $importive; } sub is_importive { my ($self) = @_; return $importive_is{ident $self}; } my %belong_of :ATTR( :init_arg :default('') ); sub set_belong { my ($self, $belong) = @_; $belong_of{ident $self} = $belong; weaken $belong_of{ident $self}; if ( $belong->isa("PlSense::Symbol::Module") ) { $belong->set_member($self->get_name(), $self); } elsif ( $belong->isa("PlSense::Symbol::Method") ) { $belong->set_variable($self->get_name(), $self); } else { logger->error("Invalid value [$belong]"); } } sub get_belong { my ($self) = @_; return $belong_of{ident $self}; } sub BUILD { my ($class, $ident, $arg_ref) = @_; my $ch = substr($class->get_name(), 0, 1) || ""; $class->set_type( $ch eq '$' ? "scalar" : $ch eq '@' ? "array" : $ch eq '%' ? "hash" : "variable"); } sub START { my ($class, $ident, $arg_ref) = @_; if ( exists $arg_ref->{belong} ) { $class->set_belong($arg_ref->{belong}); logger->debug("New variable : name[".$class->get_name."] belong[".$class->get_belong->get_name."]"); } else { logger->debug("New variable : name[".$class->get_name."]"); } } sub get_id { my $self = shift; return substr $self->get_name(), 1; } sub get_fullnm { my $self = shift; my $belong = $self->get_belong(); return $belong ? substr($self->get_name(), 0, 1).$belong->get_fullnm()."::".$self->get_id() : $self->get_name(); } } 1; __END__ plsense-0.3.4/lib/PlSense/Util.pm000066400000000000000000000027731260377356000166030ustar00rootroot00000000000000package PlSense::Util; use strict; use warnings; use PlSense::Configure; use Exporter 'import'; our @EXPORT = qw( builtin mdlkeeper addrrouter addrfinder substkeeper substbuilder set_builtin set_mdlkeeper set_addrrouter set_addrfinder set_substkeeper set_substbuilder get_common_options get_common_option_string ); { my @confnms = qw{ cachedir port1 port2 port3 loglevel logfile }; my $builtin; my $mdlkeeper; my $addrrouter; my $addrfinder; my $substkeeper; my $substbuilder; sub builtin { return $builtin; } sub mdlkeeper { return $mdlkeeper; } sub addrrouter { return $addrrouter; } sub addrfinder { return $addrfinder; } sub substkeeper { return $substkeeper; } sub substbuilder { return $substbuilder; } sub set_builtin { $builtin = shift; } sub set_mdlkeeper { $mdlkeeper = shift; } sub set_addrrouter { $addrrouter = shift; } sub set_addrfinder { $addrfinder = shift; } sub set_substkeeper { $substkeeper = shift; } sub set_substbuilder { $substbuilder = shift; } sub get_common_options { my @ret; CONF: foreach my $confnm ( @confnms ) { push @ret, "--".$confnm, get_config($confnm) || ""; } return @ret; } sub get_common_option_string { my $ret = ""; CONF: foreach my $confnm ( @confnms ) { $ret .= " --".$confnm." '".( get_config($confnm) || "" )."'"; } return $ret; } } 1; __END__ plsense-0.3.4/t/000077500000000000000000000000001260377356000134435ustar00rootroot00000000000000plsense-0.3.4/t/01_new.t000066400000000000000000000001321260377356000147150ustar00rootroot00000000000000use Test::More; BEGIN { use_ok("PlSense"); } require_ok("PlSense"); done_testing(); plsense-0.3.4/t/10_array.t000066400000000000000000000011371260377356000152500ustar00rootroot00000000000000use Test::More; use PlSense::Entity::Array; use PlSense::Entity::Null; my $e = PlSense::Entity::Array->new(); ok($e->isa("PlSense::Entity::Array"), "new"); is($e->get_type, "array", "get type"); is($e->to_string, "A<>", "to string"); $e->set_element(PlSense::Entity::Null->new()); is($e->to_string, "A", "to string in null"); $e->push_address('$PlSense::VERSION'); is($e->to_string, 'A', "to string in address"); my $ee = $e->clone; ok($ee->isa("PlSense::Entity::Array"), "clone"); is($ee->to_string, 'A', "to string of clone"); done_testing(); plsense-0.3.4/t/10_hash.t000066400000000000000000000011551260377356000150550ustar00rootroot00000000000000use Test::More; use PlSense::Entity::Hash; use PlSense::Entity::Null; my $e = PlSense::Entity::Hash->new(); ok($e->isa("PlSense::Entity::Hash"), "new"); is($e->get_type, "hash", "get type"); is($e->to_string, "H<>", "to string"); ok(! $e->exist_member("hoge"), "not exist member"); $e->set_membernm("hoge"); $e->set_member(PlSense::Entity::Null->new()); ok($e->exist_member("hoge"), "exist member"); is($e->to_string, "H NULL, >", "to string in null"); my $ee = $e->clone; ok($ee->exist_member("hoge"), "exist member in clone"); is($ee->to_string, "H NULL, >", "to string of clone"); done_testing(); plsense-0.3.4/t/10_method.t000066400000000000000000000003271260377356000154120ustar00rootroot00000000000000use Test::More; use PlSense::Symbol::Method; my $mtd = PlSense::Symbol::Method->new({ name => "fuga", }); ok($mtd->isa("PlSense::Symbol::Method"), "new"); is($mtd->get_name, "fuga", "get name"); done_testing(); plsense-0.3.4/t/10_module.t000066400000000000000000000005241260377356000154160ustar00rootroot00000000000000use Test::More; use FindBin; use PlSense::Symbol::Module; my $filepath = $FindBin::Bin."/../tlib/TestSupport.pm"; my $mdl = PlSense::Symbol::Module->new({ name => "TestSupport", filepath => $filepath, lastmodified => 0, }); ok($mdl->isa("PlSense::Symbol::Module"), "new"); is($mdl->get_name, "TestSupport", "get name"); done_testing(); plsense-0.3.4/t/10_null.t000066400000000000000000000005261260377356000151050ustar00rootroot00000000000000use Test::More; use PlSense::Entity::Null; my $e = PlSense::Entity::Null->new(); ok($e->isa("PlSense::Entity::Null"), "new"); is($e->get_type, "null", "get type"); is($e->to_string, "NULL", "to string"); my $ee = $e->clone; ok($ee->isa("PlSense::Entity::Null"), "clone"); is($ee->to_string, "NULL", "to string of clone"); done_testing(); plsense-0.3.4/t/10_reference.t000066400000000000000000000011051260377356000160630ustar00rootroot00000000000000use Test::More; use PlSense::Entity::Reference; use PlSense::Entity::Scalar; my $e = PlSense::Entity::Reference->new(); ok($e->isa("PlSense::Entity::Reference"), "new"); is($e->get_type, "reference", "get type"); is($e->to_string, "R<>", "to string"); $e->set_entity(PlSense::Entity::Scalar->new({ value => "hoge", })); is($e->to_string, "R>", "to string after set"); my $ee = $e->clone(); ok($ee->isa("PlSense::Entity::Reference"), "clone"); my $entity = $ee->get_entity; is($entity->to_string, "S", "to string of entity in clone"); done_testing(); plsense-0.3.4/t/10_scalar.t000066400000000000000000000010171260377356000153740ustar00rootroot00000000000000use Test::More; use PlSense::Entity::Scalar; my $e = PlSense::Entity::Scalar->new(); ok($e->isa("PlSense::Entity::Scalar"), "new"); is($e->get_type, "scalar", "get type"); is($e->to_string, "S<>", "to string"); $e->set_value("hoge"); is($e->get_value, "hoge", "get value"); is($e->to_string, "S", "to string after set value"); my $ee = $e->clone; ok($ee->isa("PlSense::Entity::Scalar"), "clone"); is($ee->get_value, "hoge", "get value of clone"); is($ee->to_string, "S", "to string of clone"); done_testing(); plsense-0.3.4/t/10_variable.t000066400000000000000000000003371260377356000157200ustar00rootroot00000000000000use Test::More; use PlSense::Symbol::Variable; my $var = PlSense::Symbol::Variable->new({ name => '$hoge', }); ok($var->isa("PlSense::Symbol::Variable"), "new"); is($var->get_name, '$hoge', "get name"); done_testing(); plsense-0.3.4/t/30_create_tmp_dir.t000066400000000000000000000002511260377356000171110ustar00rootroot00000000000000use Test::More; use FindBin; use lib "$FindBin::Bin/../tlib"; use TestSupport; my $tmpdir = create_tmp_dir(); ok(-d $tmpdir, "create tmp directory"); done_testing(); plsense-0.3.4/t/31_addrrouter.t000066400000000000000000000027461260377356000163170ustar00rootroot00000000000000use Test::More; use FindBin; use lib "$FindBin::Bin/../tlib"; use TestSupport; use PlSense::Configure; use PlSense::Util; use PlSense::ModuleKeeper; use PlSense::AddressRouter; use PlSense::Entity::Scalar; my $tmpdir = get_tmp_dir(); ok(-d $tmpdir, "get tmp directory"); set_primary_config(cachedir => $tmpdir); setup_config(); set_mdlkeeper(PlSense::ModuleKeeper->new()); my $addrrouter = PlSense::AddressRouter->new({ with_build => 0 }); ok($addrrouter->isa("PlSense::AddressRouter"), "new"); my @routes; @routes = $addrrouter->get_route("addr1"); ok($#routes < 0, "not regist route"); $addrrouter->add_route("addr1", "resolve1"); @routes = $addrrouter->get_route("addr1"); ok($#routes == 0 && $routes[0] eq "resolve1", "registed route 1"); $addrrouter->add_route("addr1", PlSense::Entity::Scalar->new({ value => "resolve2", })); @routes = $addrrouter->get_route("addr1"); ok($#routes == 1 && $routes[0] eq "resolve1", "registed route 1 of 2"); ok($#routes == 1 && $routes[1]->isa("PlSense::Entity::Scalar") && $routes[1]->get_value eq "resolve2", "registed route 2 of 2"); $addrrouter->store_current_project; $addrrouter->reset; @routes = $addrrouter->get_route("addr1"); ok($#routes < 0, "reset route"); $addrrouter->load_current_project; @routes = $addrrouter->get_route("addr1"); ok($#routes == 1 && $routes[0] eq "resolve1", "stored route 1 of 2"); ok($#routes == 1 && $routes[1]->isa("PlSense::Entity::Scalar") && $routes[1]->get_value eq "resolve2", "stored route 2 of 2"); done_testing(); plsense-0.3.4/t/31_modulekeeper.t000066400000000000000000000036771260377356000166310ustar00rootroot00000000000000use Test::More; use FindBin; use lib "$FindBin::Bin/../tlib"; use TestSupport; use PlSense::Configure; use PlSense::ModuleKeeper; use PlSense::Symbol::Module; use PlSense::Symbol::Method; use PlSense::Symbol::Variable; my $tmpdir = get_tmp_dir(); ok(-d $tmpdir, "get tmp directory"); set_primary_config(cachedir => $tmpdir); setup_config(); my $mdlkeeper = PlSense::ModuleKeeper->new(); ok($mdlkeeper->isa("PlSense::ModuleKeeper"), "new"); my $filepath = $FindBin::Bin."/../tlib/TestSupport.pm"; my $mdl = PlSense::Symbol::Module->new({ name => "hoge", filepath => $filepath, lastmodified => 0, }); my $mtd = PlSense::Symbol::Method->new({ name => "met", module => $mdl }); my $var = PlSense::Symbol::Variable->new({ name => '$va', belong => $mtd }); my ($mdl2, $debugstr); $mdl2 = $mdlkeeper->get_module($mdl->get_name, $mdl->get_filepath); ok(! $mdl2, "not yet keep"); $mdl2 = $mdlkeeper->load_module($mdl->get_name, $mdl->get_filepath); ok(! $mdl2, "not yet store"); $mdlkeeper->store_module($mdl); $mdl2 = $mdlkeeper->get_module($mdl->get_name, $mdl->get_filepath); ok($mdl2 && $mdl2->isa("PlSense::Symbol::Module"), "get kept"); $debugstr = $mdlkeeper->describe_keep_value; is($debugstr, "Modules ... 1\n", "keep info"); $mdlkeeper->reset; $debugstr = $mdlkeeper->describe_keep_value; is($debugstr, "Modules ... 0\n", "reset"); $mdl2 = $mdlkeeper->load_module($mdl->get_name, $mdl->get_filepath); ok($mdl2 && $mdl2->isa("PlSense::Symbol::Module") && $mdl2->get_name eq "hoge", "get stored module"); $debugstr = $mdlkeeper->describe_keep_value; is($debugstr, "Modules ... 1\n", "keep info after loaded"); my $mtd2 = $mdl2->exist_method("met") && $mdl2->get_method("met"); ok($mtd2 && $mtd2->isa("PlSense::Symbol::Method") && $mtd2->get_name eq "met", "get stored method"); my $var2 = $mtd2->exist_variable('$va') && $mtd2->get_variable('$va'); ok($var2 && $var2->isa("PlSense::Symbol::Variable") && $var2->get_name eq '$va', "get stored variable"); done_testing(); plsense-0.3.4/t/31_substkeeper.t000066400000000000000000000022041260377356000164650ustar00rootroot00000000000000use Test::More; use FindBin; use lib "$FindBin::Bin/../tlib"; use TestSupport; use PlSense::Configure; use PlSense::Util; use PlSense::ModuleKeeper; use PlSense::AddressRouter; use PlSense::SubstituteKeeper; my $tmpdir = get_tmp_dir(); ok(-d $tmpdir, "get tmp directory"); set_primary_config(cachedir => $tmpdir); setup_config(); set_mdlkeeper(PlSense::ModuleKeeper->new()); set_addrrouter(PlSense::AddressRouter->new({ with_build => 0 })); my $substkeeper = PlSense::SubstituteKeeper->new(); ok($substkeeper->isa("PlSense::SubstituteKeeper"), "new"); my $debugstr = $substkeeper->to_string_by_regexp('.+'); is($debugstr, "", "not yet exist subst"); $substkeeper->add_substitute("leftaddr1", "rightaddr1"); $debugstr = $substkeeper->to_string_by_regexp('.+'); is($debugstr, "leftaddr1 -> rightaddr1\n", "regist subst"); $substkeeper->store("Hoge", "/tmp/Hoge.pm"); $substkeeper->reset; $debugstr = $substkeeper->to_string_by_regexp('.+'); is($debugstr, "", "reset subst"); $substkeeper->load("Hoge", "/tmp/Hoge.pm"); $debugstr = $substkeeper->to_string_by_regexp('.+'); is($debugstr, "leftaddr1 -> rightaddr1\n", "stored subst"); done_testing(); plsense-0.3.4/t/51_builtin.t000066400000000000000000000012231260377356000156010ustar00rootroot00000000000000use Test::More; use FindBin; use lib "$FindBin::Bin/../tlib"; use TestSupport; use PlSense::Configure; use PlSense::Builtin; my $tmpdir = get_tmp_dir(); ok(-d $tmpdir, "get tmp directory"); set_primary_config(cachedir => $tmpdir); setup_config(); my $builtin = PlSense::Builtin->new(); ok($builtin->isa("PlSense::Builtin"), "new"); $builtin->remove(); $builtin->build(); ok($builtin->exist_variable('$ARG'), "exists builtin variable 1"); ok($builtin->exist_variable('%SIG'), "exists builtin variable 2"); ok($builtin->exist_method("abs"), "exists builtin function 1"); ok($builtin->exist_method("write"), "exists builtin function 2"); done_testing(); plsense-0.3.4/t/90_create_tmp_dir.t000066400000000000000000000002511260377356000171170ustar00rootroot00000000000000use Test::More; use FindBin; use lib "$FindBin::Bin/../tlib"; use TestSupport; my $tmpdir = create_tmp_dir(); ok(-d $tmpdir, "create tmp directory"); done_testing(); plsense-0.3.4/t/91_start.t000066400000000000000000000032231260377356000152760ustar00rootroot00000000000000use Test::More; use FindBin; use lib "$FindBin::Bin/../tlib"; use TestSupport; my $tmpdir = get_tmp_dir(); ok(-d $tmpdir, "get tmp directory") or done_mytest(); my @unusedports = get_unused_port(); is($#unusedports, 2, "get unused port") or done_mytest(); my ($mainport, $workport, $resolveport) = @unusedports; my $commonopt = "--cachedir '$tmpdir' --port1 $mainport --port2 $workport --port3 $resolveport"; my $addpath = "PATH=$FindBin::Bin/../blib/script:$FindBin::Bin/../bin:\${PATH} ; export PATH"; my ($stat, $mainstat, $workstat, $resolvestat); system "$addpath ; plsense $commonopt svstart > /dev/null"; $stat = qx{ $addpath ; plsense $commonopt svstat }; $mainstat = $stat =~ m{ ^ Main \s+ Server \s+ is \s+ Running\. $ }xms; $workstat = $stat =~ m{ ^ Work \s+ Server \s+ is \s+ Running\. $ }xms; $resolvestat = $stat =~ m{ ^ Resolve \s+ Server \s+ is \s+ Running\. $ }xms; ok($mainstat && $workstat && $resolvestat, "start server process"); my $count = 0; WAIT_IDLE: while ( $count < 100 ) { my $ps = qx{ $addpath ; plsense $commonopt ps }; $ps =~ s{ ^\s+ }{}xms; $ps =~ s{ \s+$ }{}xms; if ( ! $ps ) { last WAIT_IDLE; } sleep 2; $count++; } system "$addpath ; plsense $commonopt svstop > /dev/null"; $stat = qx{ $addpath ; plsense $commonopt svstat }; $mainstat = $stat =~ m{ ^ Main \s+ Server \s+ is \s+ Not \s+ running\. $ }xms; $workstat = $stat =~ m{ ^ Work \s+ Server \s+ is \s+ Not \s+ running\. $ }xms; $resolvestat = $stat =~ m{ ^ Resolve \s+ Server \s+ is \s+ Not \s+ running\. $ }xms; ok($mainstat && $workstat && $resolvestat, "stop server process"); done_testing(); exit 0; sub done_mytest { done_testing(); exit 0; } plsense-0.3.4/t/92_config.t000066400000000000000000000064031260377356000154120ustar00rootroot00000000000000use Test::More; use FindBin; use lib "$FindBin::Bin/../tlib"; use TestSupport; my $tmpdir = get_tmp_dir(); ok(-d $tmpdir, "get tmp directory") or done_mytest(); my @unusedports = get_unused_port(); is($#unusedports, 2, "get unused port") or done_mytest(); my ($mainport, $workport, $resolveport) = @unusedports; my $workpath = get_work_dir(); if ( ! -d $workpath ) { ok(mkdir($workpath), "create work home") or done_mytest(); } my $confpath = "$workpath/.plsense"; if ( -f $confpath ) { ok(unlink($confpath), "init config") or done_mytest(); } my $addpath = "PATH=$FindBin::Bin/../blib/script:$FindBin::Bin/../bin:\${PATH} ; export PATH"; my $chhome = "HOME=$workpath ; export HOME"; # cancel my $ret = qx{ $addpath ; $chhome ; echo n | plsense 2> /dev/null }; ok($ret =~ m{ ^ Making\? \s+ \(Y/n\) \s+ Not \s+ create }xms, "show message about not created"); ok(! -f $confpath, "not created config"); my $fh; # do default open $fh, '>', "$workpath/.param"; ok($fh, "open parameter") or done_mytest(); print $fh "\n"; print $fh "\n"; print $fh "\n"; print $fh "\n"; print $fh "\n"; print $fh "\n"; close $fh; $ret = qx{ $addpath ; $chhome ; plsense < '$workpath/.param' }; ok(-f $confpath, "created config"); open $fh, '<', "$confpath"; ok($fh, "open config") or done_mytest(); my @confvalues = <$fh>; close $fh; is($#confvalues, 9, "default config entry count"); is($confvalues[0], "cachedir=$workpath/.plsense.d\n", "default config about cache directory"); is($confvalues[1], "clean-env=0\n", "default config about whether clean env"); is($confvalues[2], "logfile=\n", "default config about log file"); is($confvalues[3], "loglevel=\n", "default config about log level"); is($confvalues[4], "maxtasks=20\n", "default config about task limit"); is($confvalues[5], "perl=perl\n", "default config about perl"); is($confvalues[6], "perldoc=perldoc\n", "default config about perldoc"); is($confvalues[7], "port1=33333\n", "default config about main port"); is($confvalues[8], "port2=33334\n", "default config about work port"); is($confvalues[9], "port3=33335\n", "default config about resolve port"); # update open $fh, '>', "$workpath/.param"; ok($fh, "open parameter") or done_mytest(); print $fh "$tmpdir\n"; print $fh "$mainport\n"; print $fh "$workport\n"; print $fh "$resolveport\n"; print $fh "19\n"; close $fh; $ret = qx{ $addpath ; $chhome ; plsense config < '$workpath/.param' }; ok(-f $confpath, "created config"); open $fh, '<', "$confpath"; ok($fh, "open config") or done_mytest(); @confvalues = <$fh>; close $fh; is($#confvalues, 9, "config entry count"); is($confvalues[0], "cachedir=$tmpdir\n", "config about cache directory"); is($confvalues[1], "clean-env=0\n", "config about whether clean env"); is($confvalues[2], "logfile=\n", "config about log file"); is($confvalues[3], "loglevel=\n", "config about log level"); is($confvalues[4], "maxtasks=19\n", "config about task limit"); is($confvalues[5], "perl=perl\n", "config about perl"); is($confvalues[6], "perldoc=perldoc\n", "config about perldoc"); is($confvalues[7], "port1=$mainport\n", "config about main port"); is($confvalues[8], "port2=$workport\n", "config about work port"); is($confvalues[9], "port3=$resolveport\n", "config about resolve port"); done_testing(); exit 0; sub done_mytest { done_testing(); exit 0; } plsense-0.3.4/tlib/000077500000000000000000000000001260377356000141325ustar00rootroot00000000000000plsense-0.3.4/tlib/TestSupport.pm000066400000000000000000000172311260377356000170100ustar00rootroot00000000000000#!/usr/bin/perl package TestSupport; use strict; use warnings; use Exporter 'import'; use FindBin; use File::Path; use IO::Socket; our @EXPORT = qw( get_tmp_dir get_work_dir create_tmp_dir get_unused_port get_any_testcmd_string get_plsense_testcmd_string get_plsense_testcmd_result run_plsense_testcmd is_server_running is_server_stopping wait_fin_task wait_fin_timeout wait_ready get_proc_memory_quantity get_current_project get_current_file used_modules ); { sub get_tmp_dir { my $ret = $ENV{TMP} || $ENV{TMPDIR} || "/tmp"; if ( ! -d $ret ) { print STDERR "Can't get tmp path"; return; } $ret =~ s{ /$ }{}xms; return $ret."/.plsense"; } sub get_work_dir { my $ret = $ENV{TMP} || $ENV{TMPDIR} || "/tmp"; if ( ! -d $ret ) { print STDERR "Can't get work path"; return; } $ret =~ s{ /$ }{}xms; return $ret."/.plsense.work"; } sub create_tmp_dir { my $ret = get_tmp_dir(); if ( -d $ret ) { if ( ! rmtree($ret) ) { print STDERR "Can't remove already exist tmp directory"; return; } } if ( ! mkdir $ret ) { print STDERR "Can't create tmp directory"; return; } return $ret; } sub get_unused_port { my $s1 = IO::Socket::INET->new(LocalAddr => "localhost", LocalPort => 0, Proto => "tcp", Listen => 1, ReUse => 1, ); if ( ! $s1 ) { print STDERR "Can't create socket : $!"; return; } if ( ! $s1->listen ) { print STDERR "Can't listening port : $!"; return; } my $s2 = IO::Socket::INET->new(LocalAddr => "localhost", LocalPort => 0, Proto => "tcp", Listen => 1, ReUse => 1, ); if ( ! $s2 ) { print STDERR "Can't create socket : $!"; return; } if ( ! $s2->listen ) { print STDERR "Can't listening port : $!"; return; } my $s3 = IO::Socket::INET->new(LocalAddr => "localhost", LocalPort => 0, Proto => "tcp", Listen => 1, ReUse => 1, ); if ( ! $s3 ) { print STDERR "Can't create socket : $!"; return; } if ( ! $s3->listen ) { print STDERR "Can't listening port : $!"; return; } my @ret = ($s1->sockport, $s2->sockport, $s3->sockport); $s1->close; $s2->close; $s3->close; return @ret; } sub get_any_testcmd_string { my $cmdstr = shift || ""; my $workpath = get_work_dir(); my $addpath = "PATH=$FindBin::Bin/../blib/script:$FindBin::Bin/../bin:\${PATH} ; export PATH"; my $chhome = "HOME=$workpath ; export HOME"; return "$addpath ; $chhome ; $cmdstr"; } sub get_plsense_testcmd_string { my $cmdstr = shift || ""; return get_any_testcmd_string("plsense $cmdstr"); } sub get_plsense_testcmd_result { my $cmdstr = shift || ""; $cmdstr = get_plsense_testcmd_string($cmdstr); return qx{ $cmdstr }; } sub run_plsense_testcmd { my $cmdstr = shift || ""; system get_plsense_testcmd_string($cmdstr); } sub is_server_running { my $stat = get_plsense_testcmd_result("svstat"); my $mainstat = $stat =~ m{ ^ Main \s+ Server \s+ is \s+ Running\. $ }xms; my $workstat = $stat =~ m{ ^ Work \s+ Server \s+ is \s+ Running\. $ }xms; my $resolvestat = $stat =~ m{ ^ Resolve \s+ Server \s+ is \s+ Running\. $ }xms; return $mainstat && $workstat && $resolvestat ? 1 : 0; } sub is_server_stopping { my $stat = get_plsense_testcmd_result("svstat"); my $mainstat = $stat =~ m{ ^ Main \s+ Server \s+ is \s+ Not \s+ running\. $ }xms; my $workstat = $stat =~ m{ ^ Work \s+ Server \s+ is \s+ Not \s+ running\. $ }xms; my $resolvestat = $stat =~ m{ ^ Resolve \s+ Server \s+ is \s+ Not \s+ running\. $ }xms; return $mainstat && $workstat && $resolvestat ? 1 : 0; } sub wait_fin_task { my $chk_interval = shift || 5; my $chk_max = shift || 300; my $count = 0; my $pscmd = get_plsense_testcmd_string("ps"); WAIT_IDLE: while ( $count < $chk_max ) { my $ps = qx{ $pscmd }; $ps =~ s{ ^\s+ }{}xms; $ps =~ s{ \s+$ }{}xms; if ( ! $ps && is_server_running() ) { last WAIT_IDLE; } sleep $chk_interval; $count++; } } sub wait_fin_timeout { if ( $ENV{PLSENSE_NOT_WAIT_TIMEOUT} ) { return 1; } my $sysfile = "/proc/sys/net/ipv4/tcp_fin_timeout"; if ( ! -f $sysfile ) { return 1; } my $value = qx{ cat $sysfile }; chomp $value; my $waitsec = $value =~ m{ \A ([0-9]+) \z }xms ? $1 + 90 : undef; if ( ! defined $waitsec ) { return; } sleep $waitsec; return $waitsec; } sub wait_ready { my $mdl_or_file = shift or return; my $chk_interval = shift || 3; my $chk_max = shift || 100; WAIT_READY: for ( my $i = 0; $i <= $chk_max; $i++ ) { my $readyret = get_plsense_testcmd_result("ready '$mdl_or_file'"); chomp $readyret; if ( $readyret eq "Yes" ) { last WAIT_READY; } sleep $chk_interval; } } sub get_proc_memory_quantity { my @keywords = @_; my $grepcmdstr = join(" | ", map { "grep $_" } @keywords); my $mem = qx{ ps alx | $grepcmdstr | grep -v grep | awk '{printf \$8}' }; chomp $mem; return $mem =~ m{ \A \d+ \z }xms ? $mem : 0; } sub get_proc_id { my @keywords = @_; my $grepcmdstr = join(" | ", map { "grep $_" } @keywords); my $id = qx{ ps alx | $grepcmdstr | grep -v grep | awk '{printf \$3}' }; chomp $id; return $id =~ m{ \A \d+ \z }xms ? $id : 0; } sub get_current_project { my $loc = get_plsense_testcmd_result("loc"); return $loc =~ m{ ^ Project: \s+ ([^\n]*?) $ }xms ? $1 : ""; } sub get_current_file { my $loc = get_plsense_testcmd_result("loc"); return $loc =~ m{ ^ File: \s+ ([^\n]*?) $ }xms ? $1 : ""; } sub used_modules { my $dir = shift || ""; if ( $dir eq "sample" ) { return qw{ File::Spec File::Basename File::Copy FindBin Class::Std Exporter List::Util List::MoreUtils List::AllUtils IO::File IO::Socket MtdExport BlessParent BlessChild ClassStdParent ClassStdChild }; } elsif ( $dir eq "sample2" ) { return qw{ File::Copy }; } elsif ( $dir eq "sample3" ) { return qw{ File::Copy }; } else { return (); } } } 1; __END__ plsense-0.3.4/xt/000077500000000000000000000000001260377356000136335ustar00rootroot00000000000000plsense-0.3.4/xt/31_modulekeeper_get_packages_uniq.t000066400000000000000000000022341260377356000225360ustar00rootroot00000000000000use Test::More; use FindBin; use lib "$FindBin::Bin/../tlib"; use TestSupport; use PlSense::Configure; use PlSense::ModuleKeeper; use PlSense::Symbol::Module; my $tmpdir = get_tmp_dir(); ok(-d $tmpdir, "get tmp directory"); set_primary_config(cachedir => $tmpdir); setup_config(); my $mdlkeeper = PlSense::ModuleKeeper->new(); ok($mdlkeeper->isa("PlSense::ModuleKeeper"), "new"); my $filepath = $FindBin::Bin."/../tlib/TestSupport.pm"; $mdlkeeper->store_module(PlSense::Symbol::Module->new({ name => "hoge", filepath => $filepath, lastmodified => 0, })); $mdlkeeper->store_module(PlSense::Symbol::Module->new({ name => "fuga", filepath => $filepath, lastmodified => 0, })); $mdlkeeper->store_module(PlSense::Symbol::Module->new({ name => "hoge", filepath => $filepath, lastmodified => 0, })); $mdlkeeper->store_module(PlSense::Symbol::Module->new({ name => "bar", filepath => $filepath, lastmodified => 0, })); my @mdls = $mdlkeeper->get_packages(); is( $#mdls, 2, "number of package" ); is( $mdls[0]->get_name(), "bar", "name of package 1" ); is( $mdls[1]->get_name(), "fuga", "name of package 2" ); is( $mdls[2]->get_name(), "hoge", "name of package 3" ); done_testing(); plsense-0.3.4/xt/93_build.t000066400000000000000000000043111260377356000154310ustar00rootroot00000000000000use Test::More; use FindBin; use lib "$FindBin::Bin/../tlib"; use TestSupport; my $wait = wait_fin_timeout() || ""; ok($wait, "wait $wait for network timeout") or done_mytest(); run_plsense_testcmd("svstart > /dev/null"); ok(is_server_running(), "start server process") or done_mytest(); my @testsrcs; if ( @testsrcs = grep { -f $_ } @ARGV ) { do_build_test(\@testsrcs, undef, 1, undef); } elsif ( @testsrcs = split m{ : }xms, $ENV{PLSENSE_TEST_SOURCE} ) { do_build_test(\@testsrcs, undef, 0, undef); } else { PROJ: foreach my $projdir ( "sample", "sample2", "sample3" ) { @testsrcs = glob("$FindBin::Bin/$projdir/*.pl"); my @usingmdls = used_modules($projdir); do_build_test(\@testsrcs, \@usingmdls, 0, $projdir); } } done_mytest(); exit 0; sub done_mytest { run_plsense_testcmd("svstop > /dev/null"); ok(is_server_stopping(), "stop server process"); done_testing(); exit 0; } sub do_build_test { my $testsrcs = shift or return; my $waited_modules = shift || []; my $update = shift || 0; my $test_ident = shift || "NoIdent"; SRC: foreach my $f ( @{$testsrcs} ) { run_plsense_testcmd("open '$f' > /dev/null"); wait_ready($f, 3, 40); } if ( $update ) { SRC: foreach my $f ( @{$testsrcs} ) { run_plsense_testcmd("update '$f' > /dev/null"); wait_ready($f, 3, 40); } } WAIT_MDL_READY: for ( my $i = 0; $i <= 100; $i++ ) { my @readys = split m{ \s+ }xms, get_plsense_testcmd_result("ready"); my $notyet = 0; MDL: foreach my $mdl ( @{$waited_modules} ) { if ( ! grep { $_ eq $mdl } @readys ) { $notyet = 1; last MDL; } } if ( ! $notyet ) { last WAIT_MDL_READY; } sleep 6; } wait_fin_task(); my $notready; CHK_READY: foreach my $f ( @{$testsrcs} ) { my $readyret = get_plsense_testcmd_result("ready '$f'"); chomp $readyret; is($readyret, "Yes", "check ready $f") or $notready = 1; } if ( $notready ) { print STDERR "The result of ready in $test_ident\n".get_plsense_testcmd_result("ready")."\n"; } } plsense-0.3.4/xt/94_assist.t000066400000000000000000000102521260377356000156420ustar00rootroot00000000000000use Test::More; use FindBin; use List::AllUtils qw{ first }; use lib "$FindBin::Bin/../tlib"; use TestSupport; my $wait = wait_fin_timeout() || ""; ok($wait, "wait $wait for network timeout") or done_mytest(); run_plsense_testcmd("svstart > /dev/null"); ok(is_server_running(), "start server process") or done_mytest(); my @testsrc = grep { -f $_ } @ARGV; if ( $#testsrc < 0 ) { @testsrc = split m{ : }xms, $ENV{PLSENSE_TEST_SOURCE}; } if ( $#testsrc < 0 ) { @testsrc = (glob("$FindBin::Bin/sample/*.pl") , glob("$FindBin::Bin/sample/lib/*.pm")); } my ($fh, $cmdret); SOURCE: foreach my $f ( @testsrc ) { my $openret = get_plsense_testcmd_result("open '$f'"); chomp $openret; is($openret, "Done", "do open $f") or next SOURCE; wait_fin_task(1, 120); open $fh, '<', "$f"; ok($fh, "open test source : $f") or done_mytest(); my ($readcode, $testdesc, $testcode, $testmethod, $expected) = (0, "", "", "", ""); LINE: while ( my $line = <$fh> ) { chomp $line; $line =~ s{ ^\s+ }{}xms; if ( $line =~ m{ ^ package \s+ ([a-zA-Z0-9:]+) }xms ) { my $pkgnm = $1; $cmdret = get_plsense_testcmd_result("onmod $pkgnm"); chomp $cmdret; is($cmdret, "Done", "set current module to $pkgnm") or last LINE; } elsif ( $line =~ m{ ^ sub \s+ ([^\s]+) }xms ) { my $subnm = $1; $cmdret = get_plsense_testcmd_result("onsub $subnm"); chomp $cmdret; is($cmdret, "Done", "set current method to $subnm") or last LINE; } elsif ( $line =~ m{ ^ \# \s* astart \s+ (.+) $ }xms ) { $testdesc = $1; $readcode = 1; $testcode = ""; } elsif ( $line =~ m{ ^ \# \s* aend \s+ ([a-z]+): \s* (.*) \s* $ }xms ) { ($testmethod, $expected) = ($1, $2); $readcode = 0; $cmdret = get_plsense_testcmd_result("assist '$testcode'"); $cmdret =~ s{ \n+ }{ }xmsg; $cmdret =~ s{ \s+ }{ }xmsg; $cmdret =~ s{ \A \s+ }{}xms; $cmdret =~ s{ \s+ \z }{}xms; my @rets = split m{ \s+ }xms, $cmdret; if ( $testmethod eq "equal" ) { is($cmdret, $expected, "assist check $testmethod $testdesc"); } elsif ( $testmethod eq "include" ) { my $include = 1; EXPECT: foreach my $e ( split m{ \s+ }xms, $expected ) { my $found = first { $_ eq $e } @rets; if ( ! $found ) { $include = 0; print STDERR "Not included a expected value [$e]\n"; last EXPECT; } } ok($include, "assist check $testmethod $testdesc") or print STDERR "Got: ".join(", ", @rets)."\n"; } elsif ( $testmethod eq "exclude" ) { my $exclude = 1; EXPECT: foreach my $e ( split m{ \s+ }xms, $expected ) { my $found = first { $_ eq $e } @rets; if ( $found ) { $exclude = 0; print STDERR "Not excluded a expected value [$e]\n"; last EXPECT; } } ok($exclude, "assist check $testmethod $testdesc") or print STDERR "Got: ".join(", ", @rets)."\n"; } } elsif ( $line =~ m{ ^ \# \s* ahelp \s+ ([^\s]+) \s+ : \s+ ([^\n]+) $ }xms ) { my ($cand, $regexp) = ($1, $2); $cmdret = get_plsense_testcmd_result("assisthelp $cand"); if ( ! ok($cmdret =~ m{ $regexp }xms, "assist help $cand match '$regexp' at $testdesc") ) { print STDERR "$cmdret"; } } elsif ( $readcode ) { $line =~ s{ ^ \# }{}xms; if ( $testcode ) { $testcode .= " "; } $testcode .= $line; } } close $fh; } done_mytest(); exit 0; sub done_mytest { run_plsense_testcmd("svstop > /dev/null"); ok(is_server_stopping(), "stop server process"); done_testing(); exit 0; } plsense-0.3.4/xt/95_help.t000066400000000000000000000045411260377356000152710ustar00rootroot00000000000000use Test::More; use FindBin; use lib "$FindBin::Bin/../tlib"; use TestSupport; my $wait = wait_fin_timeout() || ""; ok($wait, "wait $wait for network timeout") or done_mytest(); run_plsense_testcmd("svstart > /dev/null"); ok(is_server_running(), "start server process") or done_mytest(); my @testsrc = grep { -f $_ } @ARGV; if ( $#testsrc < 0 ) { @testsrc = split m{ : }xms, $ENV{PLSENSE_TEST_SOURCE}; } if ( $#testsrc < 0 ) { @testsrc = (glob("$FindBin::Bin/sample/*.pl") , glob("$FindBin::Bin/sample/lib/*.pm")); } my ($fh, $cmdret); BUILD: foreach my $f ( @testsrc ) { my $openret = get_plsense_testcmd_result("open '$f'"); chomp $openret; is($openret, "Done", "do open $f") or next SOURCE; wait_fin_task(1, 120); open $fh, '<', "$f"; ok($fh, "open test source : $f") or done_mytest(); my ($readcode, $testdesc, $testcode, $regexp) = (0, "", "", ""); LINE: while ( my $line = <$fh> ) { chomp $line; $line =~ s{ ^\s+ }{}xms; if ( $line =~ m{ ^ package \s+ ([a-zA-Z0-9:]+) }xms ) { my $pkgnm = $1; $cmdret = get_plsense_testcmd_result("onmod $pkgnm"); chomp $cmdret; is($cmdret, "Done", "set current module to $pkgnm") or last LINE; } elsif ( $line =~ m{ ^ sub \s+ ([^\s]+) }xms ) { my $subnm = $1; $cmdret = get_plsense_testcmd_result("onsub $subnm"); chomp $cmdret; is($cmdret, "Done", "set current method to $subnm") or last LINE; } elsif ( $line =~ m{ ^ \# \s* hstart \s+ (.+) $ }xms ) { $testdesc = $1; $readcode = 1; $testcode = ""; } elsif ( $line =~ m{ ^ \# \s* hend \s+ ([^\n]+) $ }xms ) { $regexp = $1; $readcode = 0; $cmdret = get_plsense_testcmd_result("codehelp '$testcode'"); if ( ! ok($cmdret =~ m{ $regexp }xms, "help check $testdesc match $regexp") ) { print STDERR "$cmdret"; } } elsif ( $readcode ) { $line =~ s{ ^ \# }{}xms; if ( $testcode ) { $testcode .= " "; } $testcode .= $line; } } close $fh; } done_mytest(); exit 0; sub done_mytest { run_plsense_testcmd("svstop > /dev/null"); ok(is_server_stopping(), "stop server process"); done_testing(); exit 0; } plsense-0.3.4/xt/96_minfo.t000066400000000000000000000045411260377356000154520ustar00rootroot00000000000000use Test::More; use FindBin; use lib "$FindBin::Bin/../tlib"; use TestSupport; my $wait = wait_fin_timeout() || ""; ok($wait, "wait $wait for network timeout") or done_mytest(); run_plsense_testcmd("svstart > /dev/null"); ok(is_server_running(), "start server process") or done_mytest(); my @testsrc = grep { -f $_ } @ARGV; if ( $#testsrc < 0 ) { @testsrc = split m{ : }xms, $ENV{PLSENSE_TEST_SOURCE}; } if ( $#testsrc < 0 ) { @testsrc = (glob("$FindBin::Bin/sample/*.pl") , glob("$FindBin::Bin/sample/lib/*.pm")); } my ($fh, $cmdret); BUILD: foreach my $f ( @testsrc ) { my $openret = get_plsense_testcmd_result("open '$f'"); chomp $openret; is($openret, "Done", "do open $f") or next SOURCE; wait_fin_task(1, 120); open $fh, '<', "$f"; ok($fh, "open test source : $f") or done_mytest(); my ($readcode, $testdesc, $testcode, $regexp) = (0, "", "", ""); LINE: while ( my $line = <$fh> ) { chomp $line; $line =~ s{ ^\s+ }{}xms; if ( $line =~ m{ ^ package \s+ ([a-zA-Z0-9:]+) }xms ) { my $pkgnm = $1; $cmdret = get_plsense_testcmd_result("onmod $pkgnm"); chomp $cmdret; is($cmdret, "Done", "set current module to $pkgnm") or last LINE; } elsif ( $line =~ m{ ^ sub \s+ ([^\s]+) }xms ) { my $subnm = $1; $cmdret = get_plsense_testcmd_result("onsub $subnm"); chomp $cmdret; is($cmdret, "Done", "set current method to $subnm") or last LINE; } elsif ( $line =~ m{ ^ \# \s* mstart \s+ (.+) $ }xms ) { $testdesc = $1; $readcode = 1; $testcode = ""; } elsif ( $line =~ m{ ^ \# \s* mend \s+ ([^\n]+) $ }xms ) { $regexp = $1; $readcode = 0; $cmdret = get_plsense_testcmd_result("subinfo '$testcode'"); if ( ! ok($cmdret =~ m{ $regexp }xms, "minfo check $testdesc match $regexp") ) { print STDERR "$cmdret"; } } elsif ( $readcode ) { $line =~ s{ ^ \# }{}xms; if ( $testcode ) { $testcode .= " "; } $testcode .= $line; } } close $fh; } done_mytest(); exit 0; sub done_mytest { run_plsense_testcmd("svstop > /dev/null"); ok(is_server_stopping(), "stop server process"); done_testing(); exit 0; } plsense-0.3.4/xt/97_explore.t000066400000000000000000000030671260377356000160230ustar00rootroot00000000000000use Test::More; use FindBin; use lib "$FindBin::Bin/../tlib"; use TestSupport; my $wait = wait_fin_timeout() || ""; ok($wait, "wait $wait for network timeout") or done_mytest(); run_plsense_testcmd("svstart > /dev/null"); ok(is_server_running(), "start server process") or done_mytest(); FILE: foreach my $f ( glob("$FindBin::Bin/sample/*.pl") ) { run_plsense_testcmd("onfile '$f' > /dev/null"); last FILE; } sleep 2; WAIT_SWITCH: for ( my $i = 0; $i <= 50; $i++ ) { if ( is_server_running() ) { last WAIT_SWITCH; } sleep 6; } my $expect = 'BlessChild \s .+/BlessChild\.pm \s 11:1\n'; $expect .= '\s\s > \s BlessParent\n'; $expect .= '\s\s < \s BlessParent\n'; $expect .= '\s\s &get_bar \s 32:1\n'; $expect .= '\s\s &get_foo \s 41:1\n'; $expect .= '\s\s &new \s 20:1\n'; $expect .= '\s\s &set_bar \s 27:1\n\n'; $expect .= 'BlessParent \s .+/BlessParent\.pm \s 1:1\n'; $expect .= '\s\s &get_fuga \s 40:1\n'; $expect .= '\s\s &get_hoge \s 26:1\n'; $expect .= '\s\s &new \s 6:1\n'; $expect .= '\s\s &set_fuga \s 35:1\n'; $expect .= '\s\s &set_hoge \s 17:1\n\n'; my $cmdret = get_plsense_testcmd_result("explore ^Bless[A-Z]"); like( $cmdret, qr{ \A $expect \z }xms, "explore match" ); $cmdret = get_plsense_testcmd_result("explore"); like( $cmdret, qr{ .+ $expect .+ }xms, "explore all" ); $cmdret = get_plsense_testcmd_result("explore ^HogeFugaBar\$"); is( $cmdret, "", "explore no match" ); done_mytest(); exit 0; sub done_mytest { run_plsense_testcmd("svstop > /dev/null"); ok(is_server_stopping(), "stop server process"); done_testing(); exit 0; } plsense-0.3.4/xt/97_setlevel.t000066400000000000000000000060451260377356000161670ustar00rootroot00000000000000use Test::More; use FindBin; use lib "$FindBin::Bin/../tlib"; use TestSupport; my $workpath = get_work_dir(); my $confpath = "$workpath/.plsense"; my $logpath = "$workpath/plsense.log"; my $fh; open $fh, '<', "$confpath"; ok($fh, "read config") or done_mytest(); my @confvalues = <$fh>; $confvalues[2] = "logfile=$logpath\n"; $confvalues[3] = "loglevel=debug\n"; close $fh; open $fh, '>', "$confpath"; ok($fh, "write config") or done_mytest(); print $fh join("", @confvalues); close $fh; my $wait = wait_fin_timeout() || ""; ok($wait, "wait $wait for network timeout") or done_mytest(); run_plsense_testcmd("svstart > /dev/null"); ok(is_server_running(), "start server process") or done_mytest(); sleep 5; WAIT_SWITCH: for ( my $i = 0; $i <= 50; $i++ ) { if ( is_server_running() ) { last WAIT_SWITCH; } sleep 6; } my (@logs, @founds); system "rm -f $logpath > /dev/null"; run_plsense_testcmd("loglevel info all > /dev/null"); open $fh, '<', "$logpath"; ok($fh, "read logfile") or done_mytest(); @logs = <$fh>; close $fh; @founds = grep { index($_, "Update log level : info") >= 0 } @logs; is( $#founds, 2, "up log level of all server" ); system "rm -f $logpath > /dev/null"; run_plsense_testcmd("loglevel debug all > /dev/null"); open $fh, '<', "$logpath"; ok($fh, "read logfile") or done_mytest(); @logs = <$fh>; close $fh; @founds = grep { index($_, "Update log level : debug") >= 0 } @logs; is( $#founds, -1, "no logging down log level of all server" ); run_plsense_testcmd("loglevel info main > /dev/null"); system "rm -f $logpath > /dev/null"; run_plsense_testcmd("loglevel debug all > /dev/null"); open $fh, '<', "$logpath"; ok($fh, "read logfile") or done_mytest(); @logs = <$fh>; close $fh; @founds = grep { index($_, "Update log level : debug") >= 0 } @logs; is( $#founds, 1, "logging down log level of other than main server" ); run_plsense_testcmd("loglevel info work > /dev/null"); system "rm -f $logpath > /dev/null"; run_plsense_testcmd("loglevel debug all > /dev/null"); open $fh, '<', "$logpath"; ok($fh, "read logfile") or done_mytest(); @logs = <$fh>; close $fh; @founds = grep { index($_, "Update log level : debug") >= 0 } @logs; is( $#founds, 1, "logging down log level of other than work server" ); run_plsense_testcmd("loglevel info resolve > /dev/null"); system "rm -f $logpath > /dev/null"; run_plsense_testcmd("loglevel debug all > /dev/null"); open $fh, '<', "$logpath"; ok($fh, "read logfile") or done_mytest(); @logs = <$fh>; close $fh; @founds = grep { index($_, "Update log level : debug") >= 0 } @logs; is( $#founds, 1, "logging down log level of other than resolve server" ); system "rm -f $logpath > /dev/null"; run_plsense_testcmd("loglevel debug > /dev/null"); open $fh, '<', "$logpath"; ok($fh, "read logfile") or done_mytest(); @logs = <$fh>; close $fh; @founds = grep { index($_, "Update log level : debug") >= 0 } @logs; is( $#founds, 0, "update log level of local" ); done_mytest(); exit 0; sub done_mytest { run_plsense_testcmd("svstop > /dev/null"); ok(is_server_stopping(), "stop server process"); done_testing(); exit 0; } plsense-0.3.4/xt/99_chgproject.t000066400000000000000000000105331260377356000164730ustar00rootroot00000000000000use Test::More; use FindBin; use lib "$FindBin::Bin/../tlib"; use TestSupport; my $wait = wait_fin_timeout() || ""; ok($wait, "wait $wait for network timeout") or done_mytest(); run_plsense_testcmd("svstart > /dev/null"); ok(is_server_running(), "start server process") or done_mytest(); wait_fin_task(); my ($projfile, $main_mem, $work_mem, $resolve_mem); # Basic Project $projfile = "$FindBin::Bin/sample/01_method.pl"; run_plsense_testcmd("open '$projfile' > /dev/null"); wait_ready($projfile, 3, 20); wait_fin_task(); my $proj1nm = get_current_project(); is($proj1nm, "SampleProj", "Project1 name is $proj1nm"); my @proj1_readys = split m{ \s+ }xms, get_plsense_testcmd_result("ready"); ok(grep( { $_ eq "List::AllUtils" } @proj1_readys ), "$proj1nm readys installed module"); ok(grep( { $_ eq "BlessChild" } @proj1_readys ), "$proj1nm readys project module"); ok(! grep( { $_ eq "String::Random" } @proj1_readys ), "$proj1nm don't ready carton module"); $main_mem = get_proc_memory_quantity("plsense-server-main"); $work_mem = get_proc_memory_quantity("plsense-server-work"); $resolve_mem = get_proc_memory_quantity("plsense-server-resolve"); ok($main_mem > 0 && $work_mem > 0 && $resolve_mem > 0, "Memory consumption is main[$main_mem] work[$work_mem] resolve[$resolve_mem]"); # Other Project $projfile = "$FindBin::Bin/sample2/01_chgproject.pl"; run_plsense_testcmd("open '$projfile' > /dev/null"); wait_ready($projfile, 3, 20); wait_fin_task(); my $proj2nm = get_current_project(); is($proj2nm, "OtherProj", "Project2 name is $proj2nm"); my @proj2_readys = split m{ \s+ }xms, get_plsense_testcmd_result("ready"); ok(grep( { $_ eq "List::AllUtils" } @proj2_readys ), "$proj2nm readys installed module"); ok(! grep( { $_ eq "BlessChild" } @proj2_readys ), "$proj2nm don't ready project module"); ok(! grep( { $_ eq "String::Random" } @proj2_readys ), "$proj2nm don't ready carton module"); ok($#proj2_readys < $#proj1_readys, "$proj2nm readys[$#proj2_readys] is less than $proj1nm readys[$#proj1_readys]"); $main_mem = get_proc_memory_quantity("plsense-server-main"); $work_mem = get_proc_memory_quantity("plsense-server-work"); $resolve_mem = get_proc_memory_quantity("plsense-server-resolve"); ok($main_mem > 0 && $work_mem > 0 && $resolve_mem > 0, "Memory consumption is main[$main_mem] work[$work_mem] resolve[$resolve_mem]"); # Local Project $projfile = "$FindBin::Bin/sample3/01_chgproject.pl"; run_plsense_testcmd("open '$projfile' > /dev/null"); wait_ready($projfile, 3, 20); wait_fin_task(); my $proj3nm = get_current_project(); is($proj3nm, "LocalProj", "Project3 name is $proj3nm"); my @proj3_readys = split m{ \s+ }xms, get_plsense_testcmd_result("ready"); ok(! grep( { $_ eq "List::AllUtils" } @proj3_readys ), "$proj3nm don't ready installed module"); ok(! grep( { $_ eq "String::Random" } @proj3_readys ), "$proj3nm don't ready carton module"); ok($#proj3_readys >= 0 && $#proj3_readys < $#proj2_readys, "$proj3nm readys[$#proj3_readys] is less than $proj2nm readys[$#proj2_readys]"); $main_mem = get_proc_memory_quantity("plsense-server-main"); $work_mem = get_proc_memory_quantity("plsense-server-work"); $resolve_mem = get_proc_memory_quantity("plsense-server-resolve"); ok($main_mem > 0 && $work_mem > 0 && $resolve_mem > 0, "Memory consumption is main[$main_mem] work[$work_mem] resolve[$resolve_mem]"); # Carton Project $projfile = "$FindBin::Bin/sample4/01_chgproject.pl"; run_plsense_testcmd("open '$projfile' > /dev/null"); wait_ready($projfile, 3, 20); wait_fin_task(); my $proj4nm = get_current_project(); is($proj4nm, "CartonProj", "Project4 name is $proj4nm"); my @proj4_readys = split m{ \s+ }xms, get_plsense_testcmd_result("ready"); ok(grep( { $_ eq "String::Random" } @proj4_readys ), "$proj4nm readys carton module"); # At present, Carton means local = 1 ok($#proj4_readys < $#proj2_readys, "$proj4nm readys[$#proj4_readys] is less than $proj2nm readys[$#proj2_readys]"); $main_mem = get_proc_memory_quantity("plsense-server-main"); $work_mem = get_proc_memory_quantity("plsense-server-work"); $resolve_mem = get_proc_memory_quantity("plsense-server-resolve"); ok($main_mem > 0 && $work_mem > 0 && $resolve_mem > 0, "Memory consumption is main[$main_mem] work[$work_mem] resolve[$resolve_mem]"); done_mytest(); exit 0; sub done_mytest { run_plsense_testcmd("svstop > /dev/null"); ok(is_server_stopping(), "stop server process"); done_testing(); exit 0; } plsense-0.3.4/xt/99_refresh.t000066400000000000000000000070101260377356000157750ustar00rootroot00000000000000use Test::More; use FindBin; use lib "$FindBin::Bin/../tlib"; use TestSupport; my $wait = wait_fin_timeout() || ""; ok($wait, "wait $wait for network timeout") or done_mytest(); run_plsense_testcmd("svstart > /dev/null"); ok(is_server_running(), "start server process") or done_mytest(); wait_fin_task(); my $leeway = 300; # KB my @testsrcs = ( "$FindBin::Bin/sample/01_var.pl", "$FindBin::Bin/sample2/01_chgproject.pl", "$FindBin::Bin/sample3/01_chgproject.pl", "$FindBin::Bin/sample4/01_chgproject.pl" ); REFRESH: for ( my $i = 1; $i <= $#testsrcs + 1; $i++ ) { my $src = $testsrcs[$i-1]; run_plsense_testcmd("open '$src' > /dev/null"); wait_ready($src, 3, 20); wait_fin_task(); is(get_current_file(), $src, "[Unit$i] Target Location is $src") or done_mytest(); my $target_main_mem = get_proc_memory_quantity("plsense-server-main"); my $target_work_mem = get_proc_memory_quantity("plsense-server-work"); my $target_resolve_mem = get_proc_memory_quantity("plsense-server-resolve"); my @target_readys = split m{ \s+ }xms, get_plsense_testcmd_result("ready"); ok($target_main_mem > 0 && $target_work_mem > 0 && $target_resolve_mem > 0 && $#target_readys >= 0, "[Unit$i] Target location resource :" ." MainMem[$target_main_mem]" ." WorkMem[$target_work_mem]" ." ResolveMem[$target_resolve_mem]" ." Readys[$#target_readys]") or done_mytest(); SRC: foreach my $f ( @testsrcs ) { run_plsense_testcmd("open '$f' > /dev/null"); wait_ready($f, 3, 20); wait_fin_task(); } run_plsense_testcmd("open '$src' > /dev/null"); wait_fin_task(); is(get_current_file(), $src, "[Unit$i] Open all project file") or done_mytest(); my $before_main_mem = get_proc_memory_quantity("plsense-server-main"); my $before_work_mem = get_proc_memory_quantity("plsense-server-work"); my $before_resolve_mem = get_proc_memory_quantity("plsense-server-resolve"); my @before_readys = split m{ \s+ }xms, get_plsense_testcmd_result("ready"); ok($before_main_mem > $target_main_mem && $before_work_mem >= $target_work_mem && $before_resolve_mem > $target_resolve_mem && $#before_readys >= $#target_readys, "[Unit$i] All location resource :" ." MainMem[$before_main_mem]" ." WorkMem[$before_work_mem]" ." ResolveMem[$before_resolve_mem]" ." Readys[$#before_readys]"); run_plsense_testcmd("refresh > /dev/null"); wait_fin_task(); ok(is_server_running(), "[Unit$i] Refresh all server") or done_mytest(); my $after_main_mem = get_proc_memory_quantity("plsense-server-main"); my $after_work_mem = get_proc_memory_quantity("plsense-server-work"); my $after_resolve_mem = get_proc_memory_quantity("plsense-server-resolve"); my @after_readys = split m{ \s+ }xms, get_plsense_testcmd_result("ready"); ok($after_main_mem < $before_main_mem && $after_work_mem < $before_work_mem + $leeway && $after_resolve_mem < $before_resolve_mem && $#after_readys == $#target_readys, "[Unit$i] Resource is refreshed :" ." MainMem[$after_main_mem]" ." WorkMem[$after_work_mem]" ." ResolveMem[$after_resolve_mem]" ." Readys[$#after_readys]"); is(get_current_file(), $src, "[Unit$i] Location is refreshed") or done_mytest(); } done_mytest(); exit 0; sub done_mytest { run_plsense_testcmd("svstop > /dev/null"); ok(is_server_stopping(), "stop server process"); done_testing(); exit 0; } plsense-0.3.4/xt/sample/000077500000000000000000000000001260377356000151145ustar00rootroot00000000000000plsense-0.3.4/xt/sample/.plsense000066400000000000000000000000411260377356000165610ustar00rootroot00000000000000name = SampleProj lib-path = lib plsense-0.3.4/xt/sample/01_method.pl000066400000000000000000000017731260377356000172410ustar00rootroot00000000000000#!/usr/bin/perl use File::Spec; # astart explicit call #&s # aend include: shift sort splice # astart method word #m # aend include: map # aend exclude: min max # ahelp map : ^ map \s is \s Builtin \s Method\. $ # ahelp map : ^ RETURN: \s # ahelp map : ^ map \s+ BLOCK \s+ LIST \s # ahelp map : ^ map \s+ EXPR,LIST \s # astart static call #File::Spec-> # aend include: rel2abs abs2rel # aend exclude: grep # ahelp abs2rel : ^ abs2rel \s is \s Method \s of \s File::Spec # ahelp abs2rel : ^ ===== \s Part \s of \s PerlDoc \s ===== \s+ abs2rel \s # hstart builtin method #map # hend ^ map \s is \s Builtin \s Method\. $ # hend ^ RETURN: \s # hend ^ map \s+ BLOCK \s+ LIST \s # hend ^ map \s+ EXPR,LIST \s # hstart static method #File::Spec->abs2rel # hend ^ abs2rel \s is \s Method \s of \s File::Spec # hend ^ ===== \s Part \s of \s PerlDoc \s ===== \s+ abs2rel \s # mstart static method #File::Spec->abs2rel # mend ^ NAME: \s abs2rel $ # mend ^ FILE: \s [^\s]+ # mend ^ LINE: \s \d+ $ # mend ^ COL: \s \d+ $ plsense-0.3.4/xt/sample/01_package.pl000066400000000000000000000020461260377356000173460ustar00rootroot00000000000000#!/usr/bin/perl use File::Basename; # astart use #use # aend include: Exporter File::Spec Getopt::Long strict warnings # aend exclude: grep map shift $_ @ARGV %ENV # astart require #require # aend include: Exporter File::Spec Getopt::Long strict warnings # aend exclude: grep map shift $_ @ARGV %ENV # astart use has word #use Fi # aend include: File::Spec File::Basename FindBin # aend exclude: Exporter Getopt::Long strict warnings # astart package word #Fi # aend include: File::Spec File::Basename FindBin # aend exclude: Exporter Getopt::Long strict warnings # ahelp File::Basename : ^ File::Basename \s is \s Module\. $ # ahelp File::Basename : ^ defined \s in \s ' [^']+ ' \. $ # ahelp File::Basename : ^ NAME \s+ File::Basename \s+ - \s # ahelp File::Basename : ^ \s* "basename" \s # ahelp File::Basename : ^ \s* "dirname" \s # hstart package #use File::Basename # hend ^ File::Basename \s is \s Module\. $ # hend ^ defined \s in \s ' [^']+ ' \. $ # hend ^ NAME \s+ File::Basename \s+ - \s # hend ^ \s* "basename" \s # hend ^ \s* "dirname" \s plsense-0.3.4/xt/sample/01_var.pl000066400000000000000000000012701260377356000165410ustar00rootroot00000000000000#!/usr/bin/perl # astart scalar #$ # aend include: _ / , ARGV ENV # ahelp ENV : ^ %ENV \s is \s Builtin \s Variable\. $ # ahelp ENV : ^ ===== \s Part \s of \s PerlDoc \s ===== \n . # astart array #@ # aend include: ARGV # ahelp ARGV : ^ @ARGV \s is \s Builtin \s Variable\. $ # ahelp ARGV : ^ ===== \s Part \s of \s PerlDoc \s ===== \n . # astart hash #% # aend include: ENV # astart array index #$# # aend include: ARGV # astart scalar in str #print "$ # aend include: _ / , ARGV ENV # astart my #my $ # aend equal: # astart our #our @ # aend equal: # hstart builtin variable #@ARGV # hend ^ @ARGV \s is \s Builtin \s Variable\. $ # hend ^ ===== \s Part \s of \s PerlDoc \s ===== \n . plsense-0.3.4/xt/sample/02_defsub.pl000066400000000000000000000053731260377356000172320ustar00rootroot00000000000000#!/usr/bin/perl =head1 NAME defsub.pl - Check about defined sub. =cut # Inner package package DefSub; =head1 NAME DefSub - This is a inner package. =cut # Start inner package # Inner method sub barar { my $barvar = shift; return ""; } 1; package main; =head1 DESCRIPTION The following sub is defined. - hogege - fugaga =cut # Start main package my $glovalvar; sub hogege { my $hogevar = shift; # astart variable in method 1 #$ # aend include: glovalvar hogevar # aend exclude: fugavar1 return ""; } sub fugaga { my ($fugavar1, @fugavar2) = @_; # astart variable in method 2 #$ # aend include: glovalvar fugavar1 # aend exclude: hogevar return @fugavar2; } # astart explicit call own method 1 #&h # aend include: hogege # astart explicit call own method 2 #&f # aend include: fugaga # astart own method word 1 #h # aend include: hogege # ahelp hogege : ^ hogege \s is \s Method \s of \s main\[ [^\n]+ \]\. $ # ahelp hogege : ^ ARG1: \s \$hogevar \s As \s Unknown $ # ahelp hogege : ^ RETURN: \s Literal \s As \s SCALAR $ # astart own method word 2 #f # aend include: fugaga # ahelp fugaga : ^ fugaga \s is \s Method \s of \s main\[ [^\n]+ \]\. $ # ahelp fugaga : ^ ARG1: \s \$fugavar1 \s As \s Unknown $ # ahelp fugaga : ^ ARG2: \s @fugavar2 \s As \s Unknown $ # ahelp fugaga : ^ RETURN: \s @fugavar2 \s As \s Unknown $ # hstart own method #hogege # hend ^ hogege \s is \s Method \s of \s main\[ [^\n]+ \]\. $ # hend ^ ARG1: \s \$hogevar \s As \s Unknown $ # hend ^ RETURN: \s Literal \s As \s SCALAR $ # hstart explicit own method #&hogege # hend ^ hogege \s is \s Method \s of \s main\[ [^\n]+ \]\. $ # hend ^ ARG1: \s \$hogevar \s As \s Unknown $ # hend ^ RETURN: \s Literal \s As \s SCALAR $ # mstart own main method #hogege # mend ^ NAME: \s hogege $ # mend ^ ARG1: \s \$hogevar \s As \s Unknown $ # mend ^ RETURN: \s Literal \s As \s SCALAR $ # mend ^ FILE: \s .+ /02_defsub.pl $ # mend ^ LINE: \s 45 $ # mend ^ COL: \s 1 $ # mstart own main method 2 #fugaga # mend ^ NAME: \s fugaga $ # mend ^ ARG1: \s \$fugavar1 \s As \s Unknown $ # mend ^ ARG2: \s \@fugavar2 \s As \s Unknown $ # mend ^ RETURN: \s \@fugavar2 \s As \s Unknown $ # mend ^ FILE: \s .+ /02_defsub.pl $ # mend ^ LINE: \s 56 $ # mend ^ COL: \s 1 $ # mstart explicit own main method #&hogege # mend ^ NAME: \s hogege $ # mend ^ ARG1: \s \$hogevar \s As \s Unknown $ # mend ^ RETURN: \s Literal \s As \s SCALAR $ # mend ^ FILE: \s .+ /02_defsub.pl $ # mend ^ LINE: \s 45 $ # mend ^ COL: \s 1 $ # mstart explicit own main method reference #\&hogege # mend ^ NAME: \s hogege $ # mend ^ ARG1: \s \$hogevar \s As \s Unknown $ # mend ^ RETURN: \s Literal \s As \s SCALAR $ # mend ^ FILE: \s .+ /02_defsub.pl $ # mend ^ LINE: \s 45 $ # mend ^ COL: \s 1 $ plsense-0.3.4/xt/sample/02_defvar.pl000066400000000000000000000017541260377356000172300ustar00rootroot00000000000000#!/usr/bin/perl my $scalar1; my @arr1; my %hash1; our ($scalar2, @arr2, %hash2); # astart own scalar #$ # aend include: scalar1 arr1 hash1 scalar2 arr2 hash2 # astart own array #@ # aend include: arr1 arr2 # astart own hash #% # aend include: hash1 hash2 # ahelp hash1 : ^ %hash1 \s is \s Variable \s of \s main\[ [^\n]+ \] \. $ # ahelp hash1 : ^ Not \s documented\. $ # hstart own scalar #$scalar1 # hend ^ \$scalar1 \s is \s Variable \s of \s main\[ [^\n]+ \] \. $ # hend ^ Not \s documented\. $ # hstart own array 1 #@arr1 # hend ^ @arr1 \s is \s Variable \s of \s main\[ [^\n]+ \] \. $ # hend ^ Not \s documented\. $ # hstart own array 2 #$arr1 # hend ^ @arr1 \s is \s Variable \s of \s main\[ [^\n]+ \] \. $ # hend ^ Not \s documented\. $ # hstart own hash 1 #%hash2 # hend ^ %hash2 \s is \s Variable \s of \s main\[ [^\n]+ \] \. $ # hend ^ Not \s documented\. $ # hstart own hash 2 #$hash2 # hend ^ %hash2 \s is \s Variable \s of \s main\[ [^\n]+ \] \. $ # hend ^ Not \s documented\. $ plsense-0.3.4/xt/sample/02_hashmember.pl000066400000000000000000000005441260377356000200700ustar00rootroot00000000000000#!/usr/bin/perl my %hash1; $hash1{key1} = ""; $hash1{key2} = undef; my $scalar1 = \%hash1; # astart hash key #$hash1{ # aend equal: key1 key2 # astart hash key has word #$hash1{k # aend equal: key1 key2 # astart hash key of reference #$scalar1->{ # aend equal: key1 key2 # astart hash key of reference has word #$scalar1->{k # aend equal: key1 key2 plsense-0.3.4/xt/sample/02_import.pl000066400000000000000000000004601260377356000172640ustar00rootroot00000000000000#!/usr/bin/perl use FindBin; use List::AllUtils qw{ min max }; # astart import scalar #$ # aend include: FindBin::Bin # astart import method #m # aend include: map min max # ahelp max : ^ max \s is \s Method \s of \s List::AllUtils\. $ # ahelp max : ^ RETURN: \s # ahelp max : ^ \s* max \s+ LIST \s plsense-0.3.4/xt/sample/02_instance.pl000066400000000000000000000021311260377356000175530ustar00rootroot00000000000000#!/usr/bin/perl use IO::File; use lib "lib/space dir"; use MtdExport qw{ immtd }; my $scalar1 = IO::File->new(); # astart scalar instance #$scalar1-> # aend include: ioctl seek fcntl # ahelp ioctl : ^ ioctl \s is \s Method \s of \s IO:: my @arr1; $arr1[0] = IO::File->new(); # astart array instance #$arr1[0]-> # aend include: ioctl seek fcntl my %hash1; $hash1{key1} = IO::File->new(); # astart hash scalar instance #$hash1{key1}-> # aend include: ioctl seek fcntl $hash1{key2} = \@arr1; # astart hash array instance #$hash1{key2}->[0]-> # aend include: ioctl seek fcntl my $scalar2 = \%hash1; # astart reference instance #$scalar2->{key1}-> # aend include: ioctl seek fcntl # astart import instance #immtd-> # aend include: accept listen foreach my $io ( @arr1 ) { # astart loop var instance #$io-> # aend include: ioctl seek fcntl } # hstart instance method #$scalar2->{key1}->ioctl # hend ^ ioctl \s is \s Method \s of \s IO:: # mstart instance method #$scalar2->{key1}->ioctl # mend ^ NAME: \s ioctl $ # mend ^ FILE: \s .+ /IO/ .+ $ # mend ^ LINE: \s \d+ $ # mend ^ COL: \s \d+ $ plsense-0.3.4/xt/sample/02_loop.pl000066400000000000000000000015031260377356000167220ustar00rootroot00000000000000#!/usr/bin/perl for my $idx ( 0..10 ) { # astart for var 1 #$ # aend include: idx } for ( my $count = 0; $count <= 10; $count++ ) { # astart for var 2 #$ # aend include: count } foreach my $currword ( "hoge", "fuga" ) { # astart foreach var #$ # aend include: currword } while ( my $line = <> ) { # astart while var #$ # aend include: line } INDEX: for my $lidx ( 0..10 ) { # astart label for var 1 #$ # aend include: lidx } ELEMENT: for ( my $lcount = 0; $lcount <= 10; $lcount++ ) { # astart label for var 2 #$ # aend include: lcount } WORD: foreach my $lcurrword ( "hoge", "fuga" ) { # astart label foreach var #$ # aend include: lcurrword } LINE: while ( my $lline = <> ) { # astart label while var #$ # aend include: lline } plsense-0.3.4/xt/sample/02_usearg.pl000066400000000000000000000011531260377356000172400ustar00rootroot00000000000000#!/usr/bin/perl use List::AllUtils; # astart use base #use base qw{ # aend include: Exporter Getopt::Long # aend exclude: grep _ ARGV ENV # astart use parent #use parent qw{ # aend include: Exporter Getopt::Long # aend exclude: grep _ ARGV ENV # astart choice import #use List::AllUtils qw{ # aend include: first all uniq :all # aend exclude: Exporter grep _ ARGV ENV # astart choice import has word #use List::AllUtils qw{ uniq # aend include: first all :all # aend exclude: uniq # ahelp max : ^ max \s is \s Method \s of \s List::AllUtils\. $ # ahelp max : ^ RETURN: \s # ahelp max : ^ \s* max \s+ LIST \s plsense-0.3.4/xt/sample/05_builtin.pl000066400000000000000000000022371260377356000174270ustar00rootroot00000000000000#!/usr/bin/perl use IO::File; my $io = IO::File->new(); my @arrio; push @arrio, $io; my $sio = shift @arrio; # astart shift #$sio-> # aend include: ioctl seek fcntl my $pio = pop @arrio; # astart pop #$pio-> # aend include: ioctl seek fcntl my @greped = grep { $_ && $_->isa("IO::File") } @arrio; # astart grep #$greped[0]-> # aend include: ioctl seek fcntl my @sorted = sort @arrio; # astart sort #$sorted[0]-> # aend include: ioctl seek fcntl my @arrio2; unshift @arrio2, $io; my $sio2 = shift @arrio2; # astart unshift #$sio2-> # aend include: ioctl seek fcntl my @revs = reverse @arrio; # astart reverse #$revs[0]-> # aend include: ioctl seek fcntl my (%hashio, $keynm); $hashio{$keynm} = $io; foreach my $hashv ( values %hashio ) { # astart values #$hashv-> # aend include: ioctl seek fcntl } my $evalio = eval { print ""; $io; }; # astart eval #$evalio-> # aend include: ioctl seek fcntl my @arrio3; push(@arrio3, $io); my $sio3 = shift(@arrio3); # astart shift with brace #$sio3-> # aend include: ioctl seek fcntl my @greped2 = grep( { $_ && $_->isa("IO::File") } @arrio ); # astart grep with brace #$greped2[0]-> # aend include: ioctl seek fcntl plsense-0.3.4/xt/sample/11_BlessSimple.pl000066400000000000000000000010411260377356000201700ustar00rootroot00000000000000#!/usr/bin/perl use IO::File; use lib "lib"; use BlessParent; my $io = IO::File->new(); my $b1 = BlessParent->new({ hoge => $io, }); my $hoge = $b1->get_hoge; # astart literal method of blessed class #my $b2 = BlessParent-> # aend include: new # astart instance method of blessed class #$b1-> # aend equal: can get_fuga get_hoge isa new set_fuga set_hoge # astart initialized attribute of blessed class #$hoge-> # aend include: ioctl seek fcntl # astart initializer of blessed class #my $b2 = BlessParent->new({ # aend equal: fuga hoge plsense-0.3.4/xt/sample/11_ClassStdSimple.pl000066400000000000000000000012301260377356000206400ustar00rootroot00000000000000#!/usr/bin/perl use IO::File; use lib "lib"; use ClassStdParent; my $io = IO::File->new(); my $c1 = ClassStdParent->new({ attr1 => $io, }); my $attr = $c1->get_attr1; # astart include project library package #use # aend include: ClassStdParent # astart literal method of Class::Std class #my $c2 = ClassStdParent-> # aend include: new # astart instance method of Class::Std class #$c1-> # aend equal: can f_1 get_attr1 get_attr_second isa set_attr1 set_attr3 # astart attribute of Class::Std class #$attr-> # aend include: ioctl seek fcntl # astart initializer of Class::Std class #my $c2 = ClassStdParent->new({ # aend equal: attr1 attr2 cattr1 cattr2 plsense-0.3.4/xt/sample/12_BlessFamily.pl000066400000000000000000000030651260377356000201710ustar00rootroot00000000000000#!/usr/bin/perl use IO::File; use IO::Socket; use lib "lib"; use BlessChild; my $sock = IO::Socket::INET->new(); my $bc = BlessChild->new({ fuga => $sock, }); my $fuga = $bc->get_fuga; my $io = IO::File->new(); $bc->set_bar($io); # astart literal method of blessed child class #my $b2 = BlessChild-> # aend include: new # astart instance method of blessed child class #$bc-> # aend equal: can get_bar get_foo get_fuga get_hoge isa new set_bar set_fuga set_hoge # astart initialized attribute of blessed child class #$fuga-> # aend include: accept listen # astart attribute of blessed child class #$bc->get_bar-> # aend include: ioctl seek fcntl # astart return super method of blessed child class #$bc->get_foo-> # aend include: ioctl seek fcntl # astart initializer of blessed child class #my $b2 = BlessChild->new({ # aend equal: fuga hoge # hstart instance method of blessed child class #$bc->set_bar # hend ^ set_bar \s is \s Method \s of \s BlessChild # hstart instance method of blessed parent class #$bc->get_fuga # hend ^ get_fuga \s is \s Method \s of \s BlessParent # mstart instance method of blessed child class #$bc->set_bar # mend ^ NAME: \s set_bar $ # mend ^ ARG1: \s \$bar \s As \s IO::File $ # mend ^ RETURN: \s NoIdent \s As \s IO::File $ # mend ^ FILE: \s .+ /BlessChild.pm $ # mend ^ LINE: \s 27 $ # mend ^ COL: \s 1 $ # mstart instance method of blessed parent class #$bc->get_fuga # mend ^ NAME: \s get_fuga $ # mend ^ RETURN: \s NoIdent \s As \s IO::Socket::INET $ # mend ^ FILE: \s .+ /BlessParent.pm $ # mend ^ LINE: \s 40 $ # mend ^ COL: \s 1 $ plsense-0.3.4/xt/sample/12_ClassStdFamily.pl000066400000000000000000000040071260377356000206360ustar00rootroot00000000000000#!/usr/bin/perl use IO::File; use IO::Socket; use lib "lib"; use ClassStdChild; use BlessParent; my $io = IO::File->new(); my $cc = ClassStdChild->new({ attr2 => $io, cattr2 => BlessParent->new(), }); $cc->set_attr3(IO::Socket::INET->new()); # astart literal method of Class::Std child class #my $c2 = ClassStdChild-> # aend include: new # astart instance method of Class::Std child class #$cc-> # aend equal: can cf_1 f_1 get_attr1 get_attr_second get_cattr1 get_cattr_second isa set_attr1 set_attr3 set_cattr1 set_cattr3 # astart super attribute of Class::Std child class #$cc->get_attr1-> # aend include: ioctl seek fcntl # astart super method of Class::Std child class #$cc->get_attr_second-> # aend include: ioctl seek fcntl # astart BlessParent attribute of Class::Std child class #$cc->get_cattr_second-> # aend equal: can get_fuga get_hoge isa new set_fuga set_hoge # astart super call method of Class::Std child class #$cc->cf_1-> # aend include: accept listen # astart initializer of Class::Std child class #my $c2 = ClassStdChild->new({ # aend equal: attr1 attr2 cattr1 cattr2 # hstart instance method of Class::Std child class #$cc->get_cattr1 # hend ^ get_cattr1 \s is \s Method \s of \s ClassStdChild # hstart instance method of Class::Std parent class #$cc->get_attr1 # hend ^ get_attr1 \s is \s Method \s of \s ClassStdParent # mstart instance method of Class::Std child class #$cc->get_cattr1 # mend ^ NAME: \s get_cattr1 $ # mend ^ RETURN: \s NoIdent \s As \s Unknown $ # mend ^ FILE: \s .+ /ClassStdChild.pm $ # mend ^ LINE: \s 0 $ # mend ^ COL: \s 0 $ # mstart instance method of Class::Std parent class #$cc->get_attr1 # mend ^ NAME: \s get_attr1 $ # mend ^ RETURN: \s NoIdent \s As \s IO::File $ # mend ^ FILE: \s .+ /ClassStdParent.pm $ # mend ^ LINE: \s 0 $ # mend ^ COL: \s 0 $ # mstart instance own method of Class::Std child class #$cc->cf_1 # mend ^ NAME: \s cf_1 $ # mend ^ RETURN: \s NoIdent \s As \s IO::Socket::INET $ # mend ^ FILE: \s .+ /ClassStdChild.pm $ # mend ^ LINE: \s 34 $ # mend ^ COL: \s 5 $ plsense-0.3.4/xt/sample/50_first.pl000066400000000000000000000003441260377356000171050ustar00rootroot00000000000000#!/usr/bin/perl use List::Util qw{ first }; use IO::File; my $io = IO::File->new(); my @arrio; push @arrio, $io; my $fst = first { $_ && $_->isa("IO::File") } @arrio; # astart first #$fst-> # aend include: ioctl seek fcntl plsense-0.3.4/xt/sample/50_uniq.pl000066400000000000000000000004671260377356000167400ustar00rootroot00000000000000#!/usr/bin/perl use List::MoreUtils qw{ uniq }; use IO::File; my $io = IO::File->new(); my @arrio; push @arrio, $io; my @uarrio = uniq @arrio; # astart uniq #$uarrio[0]-> # aend include: ioctl seek fcntl my @uarrio2 = uniq(@arrio); # astart uniq with brace #$uarrio2[0]-> # aend include: ioctl seek fcntl plsense-0.3.4/xt/sample/70_call_clone.pl000066400000000000000000000002531260377356000200520ustar00rootroot00000000000000#!/usr/bin/perl use lib "lib"; use ClassStdClone; my $cl = ClassStdClone->new(); my $cc = $cl->clone; # astart resolve clone #$cc-> # aend equal: can clmtd clone isa plsense-0.3.4/xt/sample/90_issue18.pl000066400000000000000000000011151260377356000172600ustar00rootroot00000000000000#!/usr/bin/perl use File::Copy; # astart project module prior to installed module #&File::Copy:: # aend equal: File::Copy::dummy_copy # mstart project module prior method #File::Copy::dummy_copy # mend ^ NAME: \s dummy_copy $ # mend ^ RETURN: \s Literal \s As \s SCALAR $ # mend ^ FILE: \s .+ /File\.Copy\.pm $ # mend ^ LINE: \s 6 $ # mend ^ COL: \s 1 $ # mstart explicit project module prior method #&File::Copy::dummy_copy # mend ^ NAME: \s dummy_copy $ # mend ^ RETURN: \s Literal \s As \s SCALAR $ # mend ^ FILE: \s .+ /File\.Copy\.pm $ # mend ^ LINE: \s 6 $ # mend ^ COL: \s 1 $ plsense-0.3.4/xt/sample/90_issue1_1.pl000066400000000000000000000001321260377356000174060ustar00rootroot00000000000000#!/usr/bin/perl use vars ('$hoge'); # astart use vars by brace #$ # aend include: hoge plsense-0.3.4/xt/sample/90_issue1_2.pl000066400000000000000000000002671260377356000174200ustar00rootroot00000000000000#!/usr/bin/perl use vars ('$fuga', '@bar'); # astart use vars by brace has multiple 1 #$ # aend include: fuga bar # astart use vars by brace has multiple 2 #@ # aend include: bar plsense-0.3.4/xt/sample/90_issue1_3.pl000066400000000000000000000002671260377356000174210ustar00rootroot00000000000000#!/usr/bin/perl use vars qw( $foo %hogege ); # astart use vars by qw has multiple 1 #$ # aend include: foo hogege # astart use vars by qw has multiple 2 #% # aend include: hogege plsense-0.3.4/xt/sample/lib/000077500000000000000000000000001260377356000156625ustar00rootroot00000000000000plsense-0.3.4/xt/sample/lib/BlessChild.pm000066400000000000000000000022571260377356000202420ustar00rootroot00000000000000=head1 NAME BlessChild - Child class defined by normal method. =head1 DESCRIPTION Check the inheritance/own definition of class by normal method. =cut package BlessChild; use strict; use warnings; use BlessParent; our @ISA = qw{ BlessParent }; # Constructor by normal method sub new { my ($class, $arg_ref) = @_; my $self = $class->SUPER::new($arg_ref); bless $self, $class; return $self; } sub set_bar { my ($self, $bar) = @_; $self->{bar} = $bar; } sub get_bar { my ($self) = @_; return $self->{bar}; # astart own method of blessed child class #$self-> # aend equal: SUPER::get_fuga SUPER::get_hoge SUPER::new SUPER::set_fuga SUPER::set_hoge can get_bar get_foo get_fuga get_hoge isa new set_bar set_fuga set_hoge } sub get_foo { my ($self) = @_; return $self->SUPER::get_hoge; # astart blessed hash member #$self->{ # aend equal: bar # mstart super method of blessed child class #$self->SUPER::get_hoge # mend ^ NAME: \s get_hoge $ # mend ^ FILE: \s .+/BlessParent\.pm $ } # astart define inherite method in blessed child class #sub # aend equal: get_fuga get_hoge new set_fuga set_hoge 1; __END__ plsense-0.3.4/xt/sample/lib/BlessParent.pm000066400000000000000000000015521260377356000204450ustar00rootroot00000000000000package BlessParent; use strict; use warnings; sub new { my ($class, $arg_ref) = @_; my $self = {}; $self->{hoge} = $arg_ref->{hoge} || undef; $self->{fuga} = $arg_ref->{fuga} || undef; bless $self, $class; return $self; } sub set_hoge { my ($self, $hoge) = @_; $self->{hoge} = $hoge; # astart blessed hash member #$self->{ # aend equal: fuga hoge } sub get_hoge { my $self = shift; return $self->{hoge}; # astart own method of blessed class by shift #$self-> # aend equal: can get_fuga get_hoge isa new set_fuga set_hoge } sub set_fuga { my ($self, $fuga) = @_; $self->{fuga} = $fuga; } sub get_fuga { my ($self) = @_; return $self->{fuga}; # astart own method of blessed class by @_ #$self-> # aend equal: can get_fuga get_hoge isa new set_fuga set_hoge } 1; __END__ plsense-0.3.4/xt/sample/lib/ClassStdChild.pm000066400000000000000000000042301260377356000207030ustar00rootroot00000000000000package ClassStdChild; use parent qw{ ClassStdParent }; use strict; use warnings; use Class::Std; { my %cattr1_of :ATTR( :name ); my %cattr2_of :ATTR( :init_arg('cattr2') :get :default(undef) ); my %cattr3_of :ATTR( :set => 'cattr3' :default('') ); sub BUILD { my ($class, $ident, $arg_ref) = @_; # astart own instance of BUILD in Class::Std child #$class-> # aend equal: SUPER::f_1 SUPER::f_2 SUPER::get_attr1 SUPER::get_attr_second SUPER::set_attr1 SUPER::set_attr3 can cf_1 f_1 f_2 get_attr1 get_attr_second get_cattr1 get_cattr_second isa set_attr1 set_attr3 set_cattr1 set_cattr3 # astart own initializer of BUILD in Class::Std child #$arg_ref->{ # aend equal: attr1 attr2 cattr1 cattr2 # astart own scalar of BUILD in Class::Std child #$ # aend include: cattr1_of cattr2_of cattr3_of class ident arg_ref # aend exclude: attr1_of attr2_of attr3_of # astart own hash of BUILD in Class::Std child #% # aend include: cattr1_of cattr2_of cattr3_of # aend exclude: attr1_of attr2_of attr3_of } sub cf_1 { my ($self) = @_; # astart own instance of own method in Class::Std child #$self-> # aend equal: SUPER::f_1 SUPER::f_2 SUPER::get_attr1 SUPER::get_attr_second SUPER::set_attr1 SUPER::set_attr3 can cf_1 f_1 f_2 get_attr1 get_attr_second get_cattr1 get_cattr_second isa set_attr1 set_attr3 set_cattr1 set_cattr3 # astart own scalar of own method in Class::Std child #$ # aend include: cattr1_of cattr2_of cattr3_of self # aend exclude: attr1_of attr2_of attr3_of class ident arg_ref # astart super method in Class::Std child #$self->SUPER::f_1-> # aend include: ioctl seek fcntl # mstart super method of Class::Std child class #$self->SUPER::f_1 # mend ^ NAME: \s f_1 $ # mend ^ FILE: \s .+/ClassStdParent\.pm $ return $self->f_2; } # astart define inherite method in Class::Std child #sub # aend equal: f_1 f_2 get_attr1 get_attr_second set_attr1 set_attr3 } 1; __END__ plsense-0.3.4/xt/sample/lib/ClassStdClone.pm000066400000000000000000000003251260377356000207210ustar00rootroot00000000000000package ClassStdClone; use strict; use warnings; use Class::Std; { sub clmtd { } sub clone { my $self = shift; my $ret = ClassStdClone->new; return $ret; } } 1; __END__ plsense-0.3.4/xt/sample/lib/ClassStdParent.pm000066400000000000000000000036301260377356000211140ustar00rootroot00000000000000package ClassStdParent; use strict; use warnings; use Class::Std; use FindBin; use File::Basename; { my %attr1_of :ATTR( :name ); my %attr2_of :ATTR( :init_arg('attr2') :get :default(undef) ); my %attr3_of :ATTR( :set => 'attr3' :default('') ); sub BUILD { my ($class, $ident, $arg_ref) = @_; # astart own instance of BUILD in Class::Std #$class-> # aend equal: can f_1 f_2 f_3 get_attr1 get_attr_second isa set_attr1 set_attr3 # astart own initializer of BUILD in Class::Std #$arg_ref->{ # aend equal: attr1 attr2 cattr1 cattr2 } sub START { my ($class, $ident, $arg_ref) = @_; # astart own instance of START in Class::Std #$class-> # aend equal: can f_1 f_2 f_3 get_attr1 get_attr_second isa set_attr1 set_attr3 # astart own initializer of START in Class::Std #$arg_ref->{ # aend equal: attr1 attr2 cattr1 cattr2 # astart own scalar of START in Class::Std #$ # aend include: attr1_of attr2_of attr3_of class ident arg_ref # astart own hash of START in Class::Std #% # aend include: attr1_of attr2_of attr3_of } sub f_1 { my ($self) = @_; # astart own instance of own method in Class::Std #$self-> # aend equal: can f_1 f_2 f_3 get_attr1 get_attr_second isa set_attr1 set_attr3 # astart own scalar of own method in Class::Std #$ # aend include: attr1_of attr2_of attr3_of self # aend exclude: class ident arg_ref return $self->get_attr1; } sub f_2 : RESTRICTED { my $self = shift; # astart instance of own member in Class::Std #$attr1_of{ident $self}-> # aend include: ioctl seek fcntl return $attr3_of{ident $self}; } sub f_3 : PRIVATE { my $self = shift; } } 1; __END__ plsense-0.3.4/xt/sample/lib/File.Copy.pm000066400000000000000000000001271260377356000200100ustar00rootroot00000000000000package File::Copy; use strict; use warnings; sub dummy_copy { return ""; } 1; plsense-0.3.4/xt/sample/lib/space dir/000077500000000000000000000000001260377356000175145ustar00rootroot00000000000000plsense-0.3.4/xt/sample/lib/space dir/MtdExport.pm000066400000000000000000000002771260377356000220060ustar00rootroot00000000000000package MtdExport; use strict; use warnings; use Exporter 'import'; use IO::Socket; our @EXPORT = qw{ immtd }; { sub immtd { return IO::Socket::INET->new(); } } 1; __END__ plsense-0.3.4/xt/sample2/000077500000000000000000000000001260377356000151765ustar00rootroot00000000000000plsense-0.3.4/xt/sample2/.plsense000066400000000000000000000000401260377356000166420ustar00rootroot00000000000000name = OtherProj lib-path = lib plsense-0.3.4/xt/sample2/01_chgproject.pl000066400000000000000000000002001260377356000201530ustar00rootroot00000000000000#!/usr/bin/perl use File::Copy; # astart project module in other project #&File::Copy:: # aend equal: File::Copy::other_copy plsense-0.3.4/xt/sample2/lib/000077500000000000000000000000001260377356000157445ustar00rootroot00000000000000plsense-0.3.4/xt/sample2/lib/File.Copy.pm000066400000000000000000000001271260377356000200720ustar00rootroot00000000000000package File::Copy; use strict; use warnings; sub other_copy { return ""; } 1; plsense-0.3.4/xt/sample3/000077500000000000000000000000001260377356000151775ustar00rootroot00000000000000plsense-0.3.4/xt/sample3/.plsense000066400000000000000000000000521260377356000166460ustar00rootroot00000000000000name = LocalProj lib-path = lib local = 1 plsense-0.3.4/xt/sample3/01_chgproject.pl000066400000000000000000000001761260377356000201700ustar00rootroot00000000000000#!/usr/bin/perl use File::Copy; # astart installed module in local project #&File::Copy:: # aend include: File::Copy::copy plsense-0.3.4/xt/sample4/000077500000000000000000000000001260377356000152005ustar00rootroot00000000000000plsense-0.3.4/xt/sample4/.plsense000066400000000000000000000000541260377356000166510ustar00rootroot00000000000000name = CartonProj lib-path = lib carton = 1 plsense-0.3.4/xt/sample4/01_chgproject.pl000066400000000000000000000002151260377356000201630ustar00rootroot00000000000000#!/usr/bin/perl use String::Random qw{ random_string }; # astart installed module in carton project #&random_ # aend equal: random_string plsense-0.3.4/xt/sample4/cpanfile000066400000000000000000000000331260377356000167000ustar00rootroot00000000000000requires 'String::Random'; plsense-0.3.4/xt/sample4/cpanfile.snapshot000066400000000000000000000005001260377356000205350ustar00rootroot00000000000000# carton snapshot format: version 1.0 DISTRIBUTIONS String-Random-0.26 pathname: S/SH/SHLOMIF/String-Random-0.26.tar.gz provides: String::Random 0.26 requirements: Carp 0 Exporter 0 Module::Build 0.36 Test::More 0 perl 5.006 strict 0 vars 0 warnings 0 plsense-0.3.4/xt/sample4/local/000077500000000000000000000000001260377356000162725ustar00rootroot00000000000000plsense-0.3.4/xt/sample4/local/cache/000077500000000000000000000000001260377356000173355ustar00rootroot00000000000000plsense-0.3.4/xt/sample4/local/cache/authors/000077500000000000000000000000001260377356000210225ustar00rootroot00000000000000plsense-0.3.4/xt/sample4/local/cache/authors/id/000077500000000000000000000000001260377356000214165ustar00rootroot00000000000000plsense-0.3.4/xt/sample4/local/cache/authors/id/S/000077500000000000000000000000001260377356000216205ustar00rootroot00000000000000plsense-0.3.4/xt/sample4/local/cache/authors/id/S/SH/000077500000000000000000000000001260377356000221325ustar00rootroot00000000000000plsense-0.3.4/xt/sample4/local/cache/authors/id/S/SH/SHLOMIF/000077500000000000000000000000001260377356000232335ustar00rootroot00000000000000plsense-0.3.4/xt/sample4/local/cache/authors/id/S/SH/SHLOMIF/String-Random-0.26.tar.gz000066400000000000000000000471261260377356000274430ustar00rootroot00000000000000ZI[Ȓ@|e\10xBJ@m!1r?}͕TvQ;mˠTdĊV[z=[-ݹW}wy;Z\ZtoJ#?g }@ˎݓ^=&g/닝s} > tA${giW tcmJV2}vP$qwn&iioH;in%'iuOҤ>'A2&^;=I;$}Ǩn ,m&N%IziOgfnvZIM$ck?L xY] Ӥ::fu)HiRӨ'i:YҬ ӣaO~en'KOg58Na~4IOgff=9.뷚a*29vL' 8{t;`I=2jv}p̵:ʹX{wAO n?>꼟,y dtШU~|Lz(~wyW1"9?w-H~g l! W#++$T*rV򿐿ۋre.ybg#Rx<9ldz}k66;س~TszN#}Io2Z6pTɭY{u36[/{a;Y&3{Q c.p.Y "_azqEiz,}[T6 ;ekn!h~!O^6Gs4|;=Oþ"Q~?g<ߑCi;yeiS [gsdY&_eV?$qt,ፆydK[Fq] hZ[2AfgbZ[K^ݰF5472MNzRo*s۔՛Jͺ}278%WxsL0,ISY ֙\ד#L4pl2<*`di$J0m:䨔nq\f|@fY\ssh\Oh0*Sx]KK n2O?EԱقg3^s?vD@7`Ɨރ:C_$;ŅaO'_D@4Q]v =8?ӧIq\yg3f vaV2ic >@%J!iGTnn6WMϾKk5/ܟ.[}{ηp!SܬTn$Z+p W~XݖNܥ}җwp;wlOo }X/^Ű?qאpBeIObvi?MQgNpJAĔ$%Yd23 C09ṢjY9pkJV*sS~ /6מ%[# 1ҙ؜ ,\n̓3<}edӨYM!AfuH:iE?FuQגŅ ɫJI>!C!9iamޙY&80h;@}J1(l8Fho}R#m[CdԒZ N"i:2'O4!ؐgƄ2_'\x jr<_W"_3^U %fuLjzꤣ3IU@RM˺ s 7v^(7փz $%)DzEpAYWX ޓw[Ҡ iުVwJ љ,:h:[`H{@R&5A-bY@?B{G)=/FN.6(W)#+HE:#v2O=GؔF :vP'R+HaUbDNK|wyEPKX#{--JX0٣餗\XhU^usIRVG@pٗݬ- lˆ<d,gUghE1Ӟ0e$ܠT>0R^ R&*<ܬ @MV25 NRO d葃7 0O+(x *{Oz3>%e>Ia6$Q>%c_`htTbt b>Ȋ@Q` k/\*kMBW;Vbt~EH q@[a= {`\RxEBb7 ,A֮&nBj6y_>|R 5eENDpotܧ!1*uIx`^qHAW!X 75r i7_9B#=Y:s``owFDaKd*m*ur~t쭢,aKFVEh;ȇx[/h D LmK='=Rkb,f+(Ѓ @kE_\`rjvS7 5h|p#AT>ъ ʊN+&?QLC j YHosLcpx%9 b+M?mii9<fe΄0QcVai H'HHd[W֑O^*2ܔ-V>!UdLüî/L(hQ\ )s>º%[AOdQCxNI0ޔ}V0CZVʺ[-۫)&n27uט hӱU8{6 A,eWE7ʝ] t'&L109+i^LlzJ3n~(B$ڗwT/jaIX V+thyPkPVZ0N\^GOVY'NoëPXZ'E2 %[AэnF=͠ f;#hg#aƴ5q? >s|Ķz`UaQweᆬIY'Z/̸+W j1mрu!['<_G dF(7һgDg3λ fG9δr(Vؠr>sjj$)leg:l0!=hrM9$s̒!"u;fY]yFJ61R"|R4@"w)F'pB&eIꚈaՁ? E /ռ[6#4G&XעMJ<6(VR'u-"%#-\(51mOÄVH l C3XX?/%OT A[:k |#1 cY|g~Q$ x|,ifu׊N B,D3PB9}=WR1TN9u=~bA,,"՘&tc<# xi K(pM!KBV|(ӿjbh cX2*Ҵ6F(i0V$-Je]$l*pD)0dc>A֋^ϕkҔE:ľIbgHDށ s\"rpn3e 1Ŗ]$(wѾ |Si){91M"*<\ B%(h!kcQPrOW1>%0+IJFå1qǪE%h)Wʍ|(TXp5S/F#fT[ 84k|ڜxDRLWA_V HϞwZZPӶ&Dê1qWHaMΤA@ 6bNk>T%xD3?C(gvek t41:U].U,軂/XH/o7Mُ.*v m}(׭/ ca搁hJGh^ JKuVE@@?=9׾vNo \Ҙ@,}c U(4jsBя||aÖ3ɏQ(tG ̈˄A ;>$M (0 UwkB)\%va3֐yZ+ l"ה7@ qNPgWTR.V`9^?gPXO$ Fai^/M%-X38!x5BNr#I *d q4Km#0W#Ev]!Bau%R7B=G#`(]L ;Vg4oW5KǣHi'B&PCBijՊZ'+M1=.#f:Y5Y&'VrSL4Z)_6AT&T[D16##6Qq,k9+^1 P Q4BbeH(|`rMR"=#J8ꂂp܄8 OzhZ+!TkQ9çhP)f |gi Ȅk=xl9yՊh1ۺpG0Ӡׄ24^,g'7Z}vGPUǓ<-(aحxN8jdԷSͳS I8,@ rͼr9>މ'5j0XBW]JxmH2[cBVd]8R䴤E\w+qYA*UiV[Y9Cp Uf"ez fHbEl4$WfBˠ(]0roDNKF($R=q> 0M\u@T˄=㉘B fjߤvs ;5^OB0'c 2 %} G_ 뒙>/Ô1Ktl$W:X.K/#֌*o&agCh_L. XIގ u}/1dVl陒tQ$ AHl2V F6:k)A=#vB)t&P"!4Rȯ8\L2>`9? m)FLd09~UaJ)u X!fD%#P̞G="!aNT- >Zΰ# kq܍n~P Y؜ajiq|XZsBaƑł_ @K\pZS;X=8wP_U{7h&07jdpO;GIiة,I*!˔vU2}-RxͲavz0p$\;4wD6n" jcBXl3y]U$XaF4 vLr@J,]e%ßonZ02.|ĖdB67J#A[(@,)npΚ0kɘPg#*[e9Yj|Ucekxx&\OcK(,Vʤ %ZU9[9pd) VH.#*|Uڋ V-6vjle%pڠ,v ddXM] lڶ/6"cP 9jXq iPt\ƒo!{Ab 9eujJq&H8G ry5Hy\[#UԩT1(mTD z(`V p2 @`)2SLMK_δ}YɖQfD_U+$=!wLDDMss|F]umT`''S3J'It%8:  Ab"l~G"?u9tٻ6?0% *4@H.3DIa!,FD3g~ S>xNs5*FICDL\J%lFT<X=>Ax-weY8M]v#Gm2@$ x Y?\!=J.w(BnR"Q)LDˋK^ nXS[=r{QE9|E-ZEEڙrZ doTIKlYoݯL~%Hlv) ]]'sZ y1y#۠&]>1Z`*ŵD1IH-n}YL?)gxȔ]dPPmgyqFnv|.z/x^YOqp8Z}kPs!z=rG!uFiQS'8 Uu$-5c]Ќ0OkW.-Β#Ac>6ܕ.+L.`W}嗻@uNg}N{S ?aoS}υhĘ-DQ雜=f(_s}ri]G3)jҶW;m[k8;=v$S[ ]E{Qww7K ^MDT8syC_}+emFq%Yv1Ŭ6%ML3py)i5d+񵨿pƔJ/ 559^(uI-9+.\ʆoo/LUE5auRz1ѷ.q͊2miԹ*mhab4&skMRrI5nlW6z(-WdoiS֨Ơ;WOKO(Yu"*:_ׁ ^# ?i+܌1FVFrN/c:e6OÑ^e/*\j?Gyw]_p9l׻K\p]\?7o-@5Y& ,P5θUrsPEhveuNרr K0 V]>Kۏ}>w}ă+ *j=68cTxtaƌ :YmlӒ>KJ*>10\_̾ `?~0s`j4>cyZba8CEbc]6 @ONVo&rvuah@{cħ~F@svrZG_Un{cPZ*HTOճ.@ah'{q79;bhLrbʼncI{v2]e,/k^uU"Nu'c?Pyʚt\dâk1\Q M #8(ϯ$ (> LMy|٤.X&j8NG;6PB9rNٲr8bTa\0qQt*%ջ`k RC8Œ/@aG5vNc^PS*;vvN_%I^kn%oVQQ% *m>B^^* !.K[/0F |tj~QrK*8=z'I%wVs~g~gAebh-IgkaF2:eSͨb}$]uy9}5#~kB2'G$1xV1H 4 jKEHG gGrn՝OKtU5P!MԵ8lP[.9_-!HB?<%? z'G~]͝-c{_%~ׄO/&_ͥ߶ 9./rAp|^Yu|c,WIkiK>,8OpOFna dҐyկU/vUrͣKq,@Վ*g<0Xr'E*%%"\*:qS9ՠW;Pvx.v+ p{!^( ;!8E]Q<׉ļVbKhsg⏿rɅ$(/Dݵvh0LbMZh *3ɛ$(߬G>Xc6tp'qɔR*m3Կ9Zv^8?llZVG5'{\_MHzA{\2X=o<۷k{w._ߝ]\8Q#c6ydFufwqjz9TvK,APNC`gdku+b$ozb\lb}+]Ǧtƒ_8 ej=c%'$Sؐ?dž0\e/ÏA|sZ|80QkSG;4NeJ&B׌g$>N/j_'sẖ-r4%,BI3~-D\LvE@ ,G-rq4됪~n,ɷcE xEd^ /{l̲w?=,[OצuM2G^j6j&!aOsnS|3ɿ+ZNLo8̚IΡ y-W.sc_(69-UYeƴ7AΞ57\2XëvY,vj]b=e4)/mPQrwM\ի~L!~¬vrss9 Ұ5cD\X Bd[܀R6aSBtUۇُo 7,^ ,.^ 9luіS&d^g\KD97;oc^ @|MMi3Og9dNU8yADxʔOP1>a f._5g&di[Å^1|:k2CK0׳7Og49-9׼53k޼.xy˅7y8&j[ѨTS|8 ]p~NÎǀfxh!f816oG[K\> %` @#8aKm̗N*+U?)a9NsșȏDU`5;07ͅ@9(s#05 7qbWɝNoEie)N3ŧ8}{NĐ2!"+l q#<랤G9,V9N$Iꇤ\99CbpJ#tXz٪Һ|hߴ#TjatOI՛9ڨ*_tz("dG%Qń5Ienj񗧀}u vϡǜmI)L?,qW5gCH Bk.ΰSuJHxZLMX~lyJ1_ M1!=S^(q%^9~9p#dG5~MW[zڛޛfǽ7{}?9t#Y'⩾* z^h\ 'JR# : PN|N&ϔewNǫ9 5xdȀo}3Wc1 uA)K1Zhʖ'U~ EyO# p'.?a;\vdk<=9+/Od>Ւ0$)Y ÅX{1oxԾz;v#h ~qOjH$m C*aAes+Ul:gU1/&/8ez>C0n V!L挽Fv̄ϜSX.4.qjM~C岺@)JeM֭]6$\K5W6ɡ>h*yrn |A|b|t(5\/W%ekkqwZeMEc}Nđbu5t_Ϲ^q접|pSקw*]풺v-vnCBe<*ub͒)bFzM̲h|htҠeJp`RpұV_Փ_T*S_p%i 9C&/&1U&EJX_ hG]p*Tف*>c6M;8ޞvLv޸$C!\!9n  1 Wqitw<1j<~jihCO/;ǩf4k\L@P 9yA&Е{nѷ,G#\8k;1!Y Qcd$Q[wHRLR~JsFV; CO}@bg[Q7o\ q7B2SNOg E]tOY\e>d @h8嚁^Ɯ-JP>F g[ًE\!҆ˆOB./̬epq5nq&=m#{k~y9!Ah0-CJA]qήkS]6y{2I WʱLsC hjbr}_X^1loQ9z.+ \1a(R.լ#ɜ s d[|BA&w.@N %^`LargeuvиP? )UnR"!?i%j~K^&\zE{M1+0rh3;M1b=~p17"G^Qa&n2m-Q"F劼f*fH=:è&Üԗ=ĘRX]uHJXpQ:]/KӠjPuα܇buFa~hQ"h<.e#`R6Kc\}kƤ> %IwaI}dK@#TEPg$֋GiY7cݏJv$x"v܈ͨ  j|uSG$-cZŅY^W*L9?xèAu667#C HuzQEn[L,k1{uMiO!猠I 9cmֆ7ko9MĺegiuƱ`h,3v?rfG} cA^8a"!+HxMaae6*Qڎ<|X?k'ϊS׊L'/2;s9䮇 5xgS[Tzo7L>MاGVյg;/+w pG+^?[؁ޗKɽM=x_?K??w 'Z^A‰?,dwrݱ- o~9Oo/8y`\iKvOʃ:fד=z!*U39hSh6hƤ})I'LOi]u>%8cuu˯=Tj*KMBvgcRx{}6~>ANPD2@.H/ WuT^W'BY}YݱkԠ[* NpX4A㴩V}/hQ#f5ib%m+&tKtrє_8\%Su9Am +pNjjny!9O:lN rHn7*uXNtD@K ]1gO 5$`¨F@ʜr~ksH " B(h3-VV6vbjIu`(6ukUԭI9_M,G)Sp 2߼4ޔ.,.y}{N)sFUӹ_5G^›;m>|Pz@7;^w{^p;JO=WzrbyM)Uv@rwIH83œn$+F0.lƢHLwNå3ҊR* -i9ΩiW*le%,yo^7XyŗR+hbV\`|DZ>"PX``dTkxs&6OܟO~TK׸MB9u2e rn 5+39^bЂ7Ζga|՞f;]9zA=y{C SɧQFvhMwd_Saw9T$cjl׊U%XVw9/{S3D= *DѭԦLBb2k'&^ٰr39O9-qd_/.rgS^0S8/272?(J\[>R v|4!,ѝ${|(.k[ɬ?0{>Vt&Ov !^n]Q^Rل̏We^79y.(>·l0<<4E}SKĻ.Ks% >D b;EJ>( SWj3w[oǿ mo>~~ 3{[a/{+Z"CPo4U_hGq :yP_?^|M3B'K]ƿ_-, ^=7vHݏ Ѯ5ac{_f}O<\0~{_d< WO2%RIqsmbO -wVMf/ӟgҕ ov; 3 S<;P S:erdNDh)򩙜:{4З4h;?fW;c_w}G}>;.vF;ѱj)UZN?ay_l*Bo/*`_Hkb7}0)},.nRkSbqSgKU7^I6Nz fu _E/ϗZF:rBSvCA$t}׶{,{D8-u5{=٣_QCٗW>,3}*%):J۱lzu 0WߟE687im vziXĝxaY)H}r }K,OܷA*zexM@": ]{FD3 `~^j;n/N /Yد/?}w:ܿ1c5}Qfpdm_~W;wpK]ϐr5:3֘0 =@Xgf<|kQQZ =[i~1EqJ.FJhvI8 dM9)g # # This program is free software; you can redistribute it # and/or modify it under the same terms as Perl itself. # # 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. # # $Id: Random.pm,v 1.4 2006/09/21 17:34:07 steve Exp $ package String::Random; require 5.006_001; use strict; use warnings; use Carp; use Exporter (); our @ISA = qw(Exporter); our %EXPORT_TAGS = ( 'all' => [ qw( &random_string &random_regex ) ] ); our @EXPORT_OK = ( @{ $EXPORT_TAGS{'all'} } ); our @EXPORT = (); our $VERSION = '0.26'; # These are the various character sets. our @upper=("A".."Z"); our @lower=("a".."z"); our @digit=("0".."9"); our @punct=map { chr($_); } (33..47,58..64,91..96,123..126); our @any=(@upper, @lower, @digit, @punct); our @salt=(@upper, @lower, @digit, ".", "/"); our @binary=map { chr($_) } (0..255); # What's important is how they relate to the pattern characters. # These are the old patterns for randpattern/random_string. our %old_patterns = ( 'C' => [ @upper ], 'c' => [ @lower ], 'n' => [ @digit ], '!' => [ @punct ], '.' => [ @any ], 's' => [ @salt ], 'b' => [ @binary ], ); # These are the regex-based patterns. our %patterns = ( # These are the regex-equivalents. '.' => [ @any ], '\d' => [ @digit ], '\D' => [ @upper, @lower, @punct ], '\w' => [ @upper, @lower, @digit, "_" ], '\W' => [ grep { $_ ne "_" } @punct ], '\s' => [ " ", "\t" ], # Would anything else make sense? '\S' => [ @upper, @lower, @digit, @punct ], # These are translated to their double quoted equivalents. '\t' => [ "\t" ], '\n' => [ "\n" ], '\r' => [ "\r" ], '\f' => [ "\f" ], '\a' => [ "\a" ], '\e' => [ "\e" ], ); # These characters are treated specially in randregex(). our %regch = ( "\\" => sub { my ($self, $ch, $chars, $string)=@_; if (@{$chars}) { my $tmp=shift(@{$chars}); if ($tmp eq "x") { # This is supposed to be a number in hex, so # there had better be at least 2 characters left. $tmp=shift(@{$chars}) . shift(@{$chars}); push(@{$string}, [chr(hex($tmp))]); } elsif ($tmp=~/[0-7]/) { carp "octal parsing not implemented. treating literally."; push(@{$string}, [$tmp]); } elsif (defined($patterns{"\\$tmp"})) { $ch.=$tmp; push(@{$string}, $patterns{$ch}); } else { if ($tmp =~ /\w/) { carp "'\\$tmp' being treated as literal '$tmp'"; } push(@{$string}, [$tmp]); } } else { croak "regex not terminated"; } }, '.' => sub { my ($self, $ch, $chars, $string)=@_; push(@{$string}, $patterns{$ch}); }, '[' => sub { my ($self, $ch, $chars, $string)=@_; my @tmp; while (defined($ch=shift(@{$chars})) && ($ch ne "]")) { if (($ch eq "-") && @{$chars} && @tmp) { $ch=shift(@{$chars}); for (my $n=ord($tmp[$#tmp]);$n sub { my ($self, $ch, $chars, $string)=@_; unshift(@{$chars}, split("", "{0,}")); }, '+' => sub { my ($self, $ch, $chars, $string)=@_; unshift(@{$chars}, split("", "{1,}")); }, '?' => sub { my ($self, $ch, $chars, $string)=@_; unshift(@{$chars}, split("", "{0,1}")); }, '{' => sub { my ($self, $ch, $chars, $string)=@_; my ($n, $closed); for ($n=0;$n[$n] eq "}") { $closed++; last; } } if ($closed) { my $tmp; while (defined($ch=shift(@{$chars})) && ($ch ne "}")) { croak "'$ch' inside {} not supported" if ($ch!~/[\d,]/); $tmp.=$ch; } if ($tmp=~/,/) { if (my ($min,$max) = $tmp =~ /^(\d*),(\d*)$/) { $min = 0 if (!length($min)); $max = $self->{'_max'} if (!length($max)); croak "bad range {$tmp}" if ($min>$max); if ($min == $max) { $tmp = $min; } else { $tmp = $min + int(rand($max - $min +1)); } } else { croak "malformed range {$tmp}"; } } if ($tmp) { my $last=$string->[$#{$string}]; for ($n=0;$n<($tmp-1);$n++) { push(@{$string}, $last); } } else { pop(@{$string}); } } else { # { isn't closed, so treat it literally. push(@{$string}, [$ch]); } }, ); sub new { my $proto=shift; my $class=ref($proto) || $proto; my $self; $self={ %old_patterns }; # makes $self refer to a copy of %old_patterns my %args=(); %args=@_ if (@_); if (defined($args{'max'})) { $self->{'_max'}=$args{'max'}; } else { $self->{'_max'}=10; } return bless($self, $class); } # Returns a random string for each regular expression given as an # argument, or the strings concatenated when used in a scalar context. sub randregex { my $self=shift; croak "called without a reference" if (!ref($self)); my @strings=(); while (defined(my $pattern=shift)) { my $ch; my @string=(); my $string=''; # Split the characters in the pattern # up into a list for easier parsing. my @chars=split(//, $pattern); while (defined($ch=shift(@chars))) { if (defined($regch{$ch})) { $regch{$ch}->($self, $ch, \@chars, \@string); } elsif ($ch=~/[\$\^\*\(\)\+\{\}\]\|\?]/) { # At least some of these probably should have special meaning. carp "'$ch' not implemented. treating literally."; push(@string, [$ch]); } else { push(@string, [$ch]); } } foreach $ch (@string) { $string.=$ch->[int(rand(scalar(@{$ch})))]; } push(@strings, $string); } return wantarray ? @strings : join("", @strings); } # For compatibility with an ancient version, please ignore... sub from_pattern { my $self=shift; croak "called without a reference" if (!ref($self)); return $self->randpattern(@_); } sub randpattern { my $self=shift; croak "called without a reference" if (!ref($self)); my @strings=(); while (defined(my $pattern=shift)) { my $string=''; for my $ch (split(//, $pattern)) { if (defined($self->{$ch})) { $string.=$self->{$ch}->[int(rand(scalar(@{$self->{$ch}})))]; } else { croak qq(Unknown pattern character "$ch"!); } } push(@strings, $string); } return wantarray ? @strings : join("", @strings); } sub random_regex { my $foo=new String::Random; return $foo->randregex(@_); } sub random_string { my($pattern,@list)=@_; my($n,$foo); $foo=new String::Random; for ($n=0;$n<=$#list;$n++) { @{$foo->{$n}}=@{$list[$n]}; } return $foo->randpattern($pattern); } 1; __END__ =encoding utf8 =head1 NAME String::Random - Perl module to generate random strings based on a pattern =head1 SYNOPSIS use String::Random; my $string_gen = String::Random->new; print $string_gen->randregex('\d\d\d'); # Prints 3 random digits # Prints 3 random printable characters print $string_gen->randpattern("..."); I use String::Random qw(random_regex random_string); print random_regex('\d\d\d'); # Also prints 3 random digits print random_string("..."); # Also prints 3 random printable characters =head1 DESCRIPTION This module makes it trivial to generate random strings. As an example, let's say you are writing a script that needs to generate a random password for a user. The relevant code might look something like this: use String::Random; my $pass = String::Random->new; print "Your password is ", $pass->randpattern("CCcc!ccn"), "\n"; This would output something like this: Your password is UDwp$tj5 B: currently, String::Random uses Perl's built-in predictable random number generator so the passwords generated by it are insecure. If you are more comfortable dealing with regular expressions, the following code would have a similar result: use String::Random; my $pass = String::Random->new; print "Your password is ", $pass->randregex('[A-Z]{2}[a-z]{2}.[a-z]{2}\d'), "\n"; =head2 Patterns The pre-defined patterns (for use with C and C) are as follows: c Any Latin lowercase character [a-z] C Any Latin uppercase character [A-Z] n Any digit [0-9] ! A punctuation character [~`!@$%^&*()-_+={}[]|\:;"'.<>?/#,] . Any of the above s A "salt" character [A-Za-z0-9./] b Any binary data These can be modified, but if you need a different pattern it is better to create another pattern, possibly using one of the pre-defined as a base. For example, if you wanted a pattern C that contained all upper and lower case letters (C<[A-Za-z]>), the following would work: my $gen = String::Random->new; $gen->{'A'} = [ 'A'..'Z', 'a'..'z' ]; I my $gen = String::Random->new; $gen->{'A'} = [ @{$gen->{'C'}}, @{$gen->{'c'}} ]; The random_string function, described below, has an alternative interface for adding patterns. =head2 Methods =over 8 =item new =item new max =E I Create a new String::Random object. Optionally a parameter C can be included to specify the maximum number of characters to return for C<*> and other regular expression patterns that do not return a fixed number of characters. =item randpattern LIST The randpattern method returns a random string based on the concatenation of all the pattern strings in the list. It will return a list of random strings corresponding to the pattern strings when used in list context. =item randregex LIST The randregex method returns a random string that will match the regular expression passed in the list argument. Please note that the arguments to randregex are not real regular expressions. Only a small subset of regular expression syntax is actually supported. So far, the following regular expression elements are supported: \w Alphanumeric + "_". \d Digits. \W Printable characters other than those in \w. \D Printable characters other than those in \d. . Printable characters. [] Character classes. {} Repetition. * Same as {0,}. ? Same as {0,1}. + Same as {1,}. Regular expression support is still somewhat incomplete. Currently special characters inside [] are not supported (with the exception of "-" to denote ranges of characters). The parser doesn't care for spaces in the "regular expression" either. =back =head2 Functions =over 8 =item random_string PATTERN,LIST =item random_string PATTERN When called with a single scalar argument, random_string returns a random string using that scalar as a pattern. Optionally, references to lists containing other patterns can be passed to the function. Those lists will be used for 0 through 9 in the pattern (meaning the maximum number of lists that can be passed is 10). For example, the following code: print random_string("0101", ["a", "b", "c"], ["d", "e", "f"]), "\n"; would print something like this: cebd =back =head1 BUGS This is Bug Free™ code. (At least until somebody finds one…) Please report bugs here: L . =head1 AUTHOR Original Author: Steven Pritchard C<< steve@silug.org >> Now maintained by: Shlomi Fish ( L ). =head1 LICENSE This program is free software; you can redistribute it and/or modify it under the same terms as Perl itself. =head1 SEE ALSO perl(1). =cut # vi: set ai et: plsense-0.3.4/xt/sample4/local/lib/perl5/i686-linux/000077500000000000000000000000001260377356000217205ustar00rootroot00000000000000plsense-0.3.4/xt/sample4/local/lib/perl5/i686-linux/.meta/000077500000000000000000000000001260377356000227245ustar00rootroot00000000000000plsense-0.3.4/xt/sample4/local/lib/perl5/i686-linux/.meta/String-Random-0.26/000077500000000000000000000000001260377356000257735ustar00rootroot00000000000000plsense-0.3.4/xt/sample4/local/lib/perl5/i686-linux/.meta/String-Random-0.26/MYMETA.json000066400000000000000000000025051260377356000276640ustar00rootroot00000000000000{ "abstract" : "Perl module to generate random strings based on a pattern", "author" : [ "Shlomi Fish " ], "dynamic_config" : 0, "generated_by" : "Module::Build version 0.4205", "keywords" : [ "generate", "random", "regex", "regexp", "regular-expression", "string" ], "license" : [ "perl_5" ], "meta-spec" : { "url" : "http://search.cpan.org/perldoc?CPAN::Meta::Spec", "version" : "2" }, "name" : "String-Random", "prereqs" : { "build" : { "requires" : { "Test::More" : "0" } }, "configure" : { "requires" : { "Module::Build" : "0.36" } }, "runtime" : { "requires" : { "Carp" : "0", "Exporter" : "0", "perl" : "5.006", "strict" : "0", "vars" : "0", "warnings" : "0" } } }, "provides" : { "String::Random" : { "file" : "lib/String/Random.pm", "version" : "0.26" } }, "release_status" : "stable", "resources" : { "license" : [ "http://dev.perl.org/licenses/" ], "repository" : { "url" : "http://github.com/shlomif/String-Random" } }, "version" : "0.26" } plsense-0.3.4/xt/sample4/local/lib/perl5/i686-linux/.meta/String-Random-0.26/install.json000066400000000000000000000003431260377356000303340ustar00rootroot00000000000000{"version":"0.26","target":"String::Random","pathname":"S/SH/SHLOMIF/String-Random-0.26.tar.gz","dist":"String-Random-0.26","provides":{"String::Random":{"version":"0.26","file":"lib/String/Random.pm"}},"name":"String::Random"}plsense-0.3.4/xt/sample4/local/lib/perl5/i686-linux/auto/000077500000000000000000000000001260377356000226705ustar00rootroot00000000000000plsense-0.3.4/xt/sample4/local/lib/perl5/i686-linux/auto/String/000077500000000000000000000000001260377356000241365ustar00rootroot00000000000000plsense-0.3.4/xt/sample4/local/lib/perl5/i686-linux/auto/String/Random/000077500000000000000000000000001260377356000253565ustar00rootroot00000000000000plsense-0.3.4/xt/sample4/local/lib/perl5/i686-linux/auto/String/Random/.packlist000066400000000000000000000000711260377356000271670ustar00rootroot00000000000000/tmp/plsense/xt/sample3/local/lib/perl5/String/Random.pm

! h5la /.ָv-4 `Hz^.da| ]_jm,gA >,5 _hÞ,ƶm/i@@,rvp3qp00o#>9C3cY7֑g<Ӱ7/pyKy@<. \66a k\&?y8R<2qo<\y}>'D/:w/% !X,> Yh9rC|M9sE7[;`|;nܸlf8WI0Al2L|̊}ibΝ<#kVPA񉓆ͥM&֌YX!N5+gvVO̙ ZV,Dw[}^߾!+,Ux H*\ȰÇ#JHŋ3jȱǏ CIɓ(SB,b 0cʜI͛8sɳϟA>,*]ʴӧPJJ&Caׯ`ÊKَT|۷pʝK]BE䊯! L CQ@LB!L˘3) >l`ӨS^nT҄PRZͻ0Y N\8ȓ+_sṾKNzŭkνw؉OGϾOϿ(h;4F(Vhfaa (NA',0(ʘ1<0(~8H&i@6PF)>XfQ'8d2e=ihXXpƉ(djypH~er&tz9ڥu ,%㊀e$詨&('FȚz*Jmk v&,8k̎)h:린V _5dS 3혈+ k2V`xVql.8;r~[ Ꮌ5.p$U`0+ (r(OA^v ﲺ3H2G<з~W#8\(D1C{Bԡ5i 6zF7 4"z< z~s @9vLfNd 2pzvtf-)jrQ5W٨Ӷ2-4[Q#(N5#V  |(؁#,P@`ƕ5o@ 8@V[WCP ffak_Mˢqt?{ ~Z0>1Q~b\@Nn]"msu lP(V G|?dwq>J-PѮ݃ mqV k4V6}Q{ӰPQ?`P]," `}1B )(;w5&yzJ&{wSAqLfX\< 0r]=vmA b[ 0mzr!lf=W  h ̘v\|/jX\F @ZmpF,8k3n7pUxuсW` ≆h0G:3Mv@ )_@b.9 `T( G8 _{cp0旺w{77}|cWe/|{Giw.~ewFnWԑ$R)kƐ7ra^#[83u8^ V5a  h@C9ތg<Ǩ4|؎Z $7Ɓ{-t&9p phǁ_J|3.q#h4 iGꋱpC}Tgo2[與kiCHA >ar87 Z4 ӰrW * k ɠ p ׀ L[L`~&HBPZ"0 (`HXp $ X& [U%xX@)h )Ё   ՠP V ` p?^(# `~ ^_&P"PD@A %UW<[X]8(0&p{焜؆ -: ͠ P  Ї0 *P8 ː~0O$H{S1)0pT a) ֨P)p'  xHpWhPvx}QEv883Xh0 ^X樉&{Xَ& X( U& 90$@ޤ`6X% 7P( Ph') %uQ2TZ'y^x6a3DPH똋'PM{7Ei/"`QEM hXR [H0 PKpA%  扒P%PՐ "  a zQW@fGyr q L0 ((@yfI+ H5t Б P`Y]܅1_ 8]&` P[e*{֩{8׉$`I x&z* " q 2E? p' N @ K6MP@ɴ 'p puf蝿T xP P F G p `)T2 b [0 Y~ 5mw ~:W$! \'GD mmmʺڬ:Zzؚںڭ:Zz蚮꺮ڮ:Zzگ;[{ ۰;[{۱ ";$[&{(*,۲.02;4[6{8:<۳>@B;D[F{HJL۴NPR;T[V{XZ\۵^`b;d[f{hjl۶npr;t[v{xz|۷~;[{۸;[{۹;[{ۺ;4hy^Z`Flqpy:~P[pk`Pnn]fk&ۻLL0yPg|efիכ۽LjghpF9u.WZ_Zpmlh{P0~<[y{WiZuU!PZ> "lYymp[r`8 S -[p%MFm`fnܽ0YWS\x|7<W~QOWPpWFP lƛ/ n`yl{|^1\_T\+d{9[ɸɜɠã\~ŨlP_dq_XtrylH^0q_lVrmL[fw<&W@lϻk ,3P|m @|h@_,;| (Tm@lU|`X\[ sk2\1__`9\,_b0dMic}b@iF-Xp_ZP]{mhp޼+ ]Ɨ SfP~ >`p]8v  r@p P g} xBypJ N'P Ԁ @ { ϐ pXv   !vM}ɽ=t rވ :Wo( 0zP Ð N' pBtrآ"-m rm-  \dr " B#~ %n! p tԀ - 79kp7y w ('"@.- mp @  @`vS> Z iw \n}! )0 @=p _: @0`!7 ,'c>`NvwxUF3hrYಘGu\ƾQ`0nާ. $  @@6 0\<^q )PT֮nܼn pxAQ@6> 7e%.^o{{,00[@~0Ju/°)wz>AeVe_9M1n` ] -I  x0  0nE/` @?0 r@|Y? w xo^W!^,A kaU .`SN[Ѐ3wZlEqWdkZ6J( AeUmOILMG FF "}Oz޼q&)EԩӬ4I+DrpC=iHEVVPD= ԠB p61B!`| Tڵ:Wst%-PZ9_O'0hP$,/ޢ DuÝi p >H ȕk@_$ngΗy_#;Fsg%;>ͅ.~!7, g H"40!#JHŋ!Ǐ Cy1ɓ(Q<)0˔_ʜIL!Z$S`9#IqhОsķӆZtꇫXVݚP+Wt횵ٳh~tWjV[Ԧ]<}{n̏Wm(`$/[P_A#},9"""&80ỠwVx ;lWʣ8uaxXwHuAxqA&˧Zj߾}ţ_ޢzwz~=߀Hd,XFXU/|S >S >d#!W bCdC9S5.}7ꬳnHs!2~`! 4["P <DވN4F m De"]IInb6 >|yrqϸ+$!X* ,@]@O9VH5ρ988Vv5HI:ժF5< 3&L3ۮ7ԋ, 1d0$S0J0+K. ,3lEc ;%κ,Z4r/' C`&LÀDL+1Ŝ1D$1ܨ3LA$+ܲ|Z(36(/$K;s볓#ʹ DPs$p@CDʋE# T[9l4/bzzK.,//o'7G/Wogw/o觯/o HL:'H Z̠7z GH(L W0 gH8̡w@ HD3cDqx">H*{GL'zQm ؖuơD+^Wb5jw:1|hT#>ظE&1$0a*JD[j]&oc$ 9BN|h8f];p1IJ4іN2Óc G1_tQ,$*UHc(\㖹.f|hd3yIh2D_4\j5d~9N&/'!,,1UI H*\ȰÇ#JHŋ3jȱǏ CIɓ(1hFʗ0cʜI͛8sɳ'#+O H*]ʴӧPJ2ТGjʵׯ`Ê;(>]f%˶۷pʝ@5d˷߿ &[bǐ#KL9b"@~ Ƈ CMT0kC O˞M 5NCQ%PȣKN:RYќ RËOTJJ RROϿ(h& 6F_8Vhfv 衄$hE",0(#B.h8j8<Ƙ@ bD預H&L6YPFTVXf\v9`di曣)t x>&'>u)eמ~&*裐7FjZQ鋘vR⧤*3:3`M5sv(9(5ְ M62VhȆ +j++:Cl$ 3@3~LsN3bɌ2ʄ5ٌmCkn.KGl/\s- #2L2 M0le5Ѵ 3,CnJ,sqL;$ ,8S2H-L < 4Ќ b3X (ȳ9YƳ;r17Ua3ΰ#^k$TQrN4K4H8p,$ǔr<80L3d 4֤2ℓ֒$p S1,F3O ;M:{/dr84*ؓ4%#^pG2}b;@Qh@#C G5;tp#Zݜ!k/;/Iȣ=qNp4f1Ot"z! H{CD 6vcw^tըR~jiNqUle ?JYae8oD'䑡o810 t䶆CX=T,X4VqZs,;! {xBB nb3! "8 Ig;>Ϫ^Jhb,drS=;,f# ŨF)8G;MI7zAT :$!`oo)bvuh$U cɈUG{X̂+@y.ԫ^GDA ]ut(Lh! r( ^Yx\Ç;\V>Ѐ׬FGqd}-i{'P">V;˯򵕋l-tvHi ߶]}BC; g=lu1YR{dw=~vw@_"cn/i OQ;K¾x\^[jJB/cF5 4 e4 OC%u0=|,1 OHBG J`fG:HekLjW"0^\@!_@_ȢBY;V0@ B 4Twco*,nߜfﴜ j<`fQ'@H!XSgp"RBX<{ Yq>Hh _"ZBTCC*0i _Xb618lpF-z`$2P"Ȣ,`!Lj 8qKChΫY%@cbu8 ` נ`Ű:S1F P pY [ȅ+`(E($X"Ґ J@5B0L8ŀ @iQ  ؀wztt I7 =?}찂qz 0 +8e؍p@ #hS?֋H*  Ѩxx 9ٸlI*wdvBӰE ޠ1@ C+1 [E  ` U V ( ) tC7P9I[&p'z5%y5Gi) ,/)X)mefo`o8$%p<3 p>N%`' 8g 4P"({Yo Ó$hG 1٠ jcx`Ґ:T"fy?Q9"p# @98&0K)'0Kd$ Gw yW&`7iY9yy@y0)D ;yY$* Z0yG;T #ys G9K@)5@P ᴡ) 0(:T"  y* p 0%jꛗ) a I,9Ig2JXj$@B%G0#Ev 9٩4SِۄpY;r pM$ FZd* C9ɡi9$iq  `ZѐfЧ #ZԠ ln7$Iga9&Nz)`g"  )১›И*w#I+ω* Ԭz HZz AW y={Z*  O9P&0j?) g00 v;YȊ p =@.`{' ? < 4io1[ {Zkbr`o' a0p K <{6ٕ OQ_N;X۶PVu'1` ]e{Q涄+&bp pە{ 񸅻۹;[{ۺ;[{ۻ;[{țʻۼ;[{؛ڻ۽;[{蛾껾۾;[{ۿ<\| <\| "<$\&|(*,.02<4\6|8:<>@BD,.IK~MN!1, HA|*48+[A_3|nkg9 G2"A`-\/6o,V̙Mqbgς+ym5H %jςݰeFhNyBJ5UY 6kkj-8Yj%gӪ[%^{JRÁ:} A&"PRԠs5&خpղ+&̚tF6cϮvSuNՄ7]8s:>\\$R.9 l)diE4ߐSQ>)'~hpT8asgÄ栄j衈M4l~f.csb~1ev *#hjꩨg"䞛hx(cY_$i匘1kXJ"03jF+nu 0-X㥳n XF"읱R9y»lVkmiȥ,X*(pĸV" \ J<2Vks~_,<$D:}6iv;D}5c:4VA;W<͗&Bkk\wuxF  B~B;{i~@w}PߪnTb)җ%XaN_G.䔏k=0 T1DrGvQ;L,#⋿_<[ߵ*}jڞkl*KxԄ+ws kNާ8;ƷCںOm^H!!s;nW%qMES:X3 O 0)sRXi*~uo-,\*oh(v0%(HxL($Ls3hNY6DX_!B>e  PW#"'n.:"H:'8.AӬD ֲ8+1hK3XW+ ,z!ю̤&͒]7Qld(BOjb㸰XI%5뒛 0I\Xcȼ3 nlѸhT=EM`L;, ]$֖ DAg`Lg@ `@vxC61zʑದ?4~BTB">`Sb#)F)с HGJҒ(MJWҖ&-H9:Ճ?X^BHZDhL2HM8PXRHZH-Vxw[҅^qbx ߐJp *lwze(V`z8$Z#A q8%\whWyX$p`E5S}[\v(Z AW(Rx c%^'R mrb_u+Bx_jgxX(Y 0ѠRX@8RA0,",1_rR ae-0z. XøeR 0 ͘R> e=6V`{4x&`옐b0k6eQ`e^ 0*xR(R#r5h{VR- F6)n HnF!y{'Ih*_0cbs(\_ql^;80+z d$%]xeD {&'(@k* QHta9ey@R_5Gw@bTguX%e'R耘! و0! ! `LY(a '"Yj™ `9ÙXX@g)^J1 p ـ "0 Yy׀LiՀLX`9p΀ ͠ А !|2Zuzt#j4:GԀI⟓a uQDD7: / ʠ "O 0 ЀGB:0WK!q s&n)n+ns 01.@`׀9r-AnrC/~B.^0%K.+!0,c H-*\ȰÇ#JHŋ3jȱǏ CIɓ(S\ɲ˗0cʜI͛8sɳϟ@ JѣH*]ʴӧPJJիXjʵׯ`ÊKٳhӪ]˶۷pʝKx˷߿ LÈ+^̸ǐ#KL˘3k̹ϠCMӨS^9ְaM;ڸM;nw-xlƓ[F9O9Nu?].8p%^fͫreOϿ(h& 6F(Vhfv ($h(,0(4h8<@)DiH&L6PF)TViXf\v`)dihlp)tix|矀*蠄j衈&袌6裐F*餔Vj饘f馜v駠*ꨤjꩨꪬ꫰>*무j뭸뮼+k&6F+Vkfm_ >y!1,?` \!r _#J%ٹt%81gΚa\v9  w>ʘ1ӗϟ@  pU 7o2I3GիXØqcǏ4xLY,@/׀ɓ"ѻ?{R}+nsN:n ]Qv"swΜ5v~k⊝N\t_ղMv1ϬENk8]vȓ+_μУKN]yF+휱ËO]˟|_~Y / " bqb :g5̈́5( F  |@]3aax 4B̉  t !@ BDX]8Gc-͋ !Dž>)$uD5V9F8`pg`@ 6`eÍA)Xh#r@!!8PÔɑy `@qu)pC U ;Cr}Q@QڈQ#H/|p(+MଚQ pŰ-@0 ZOcΪZPa- + H т^(7Aπ~`4?PS@})DՙҢ:oI|04pKg옑(0I(@jԠRSH+UzN ٠)H H l$U8~`yg^MJ֣eJU~3<*꯮bI!hbYҚ-ZJ>F3JN2~mZw u>OKRSmI?pvQ-Hiv+n!35+rW\T egIV +^Jł j,ڶm3߻RA_/뎻AX+{Zb- x$w?YHֽ-8YX֘D1_CWRMlH;RҺpYa~0Z%5iֱ Ǯ<1\X;>O:r,gI 5@:k 9=׹xBЈNC3z61DҘδ7N{ӛn|YX*蠄 Xjw]BeY&g鞐mtډg矆ꪬ*R*pj뭸뮉Śج*knl6Fk`Z-[fnEmVk7}UƻH6IlsބؚA)G,Z%D60w dqK1׆,<2Nř,$l82A۫1x,D?W%g|2PzBIEAG\;9;MwmhGW4@TL1ձ'As 4C[mP5ܠ؆\575sN8~gN䬓M6oSL8UGM8ՠ&QwQWl82h6䐳y6#80 >!>9W~9 >R7Ht'7PSഖ3ϤF_nN;ٰCHt4d4`MQysr86WfqgԈ#N_3C9Y*uF6Tb "8NEML8sm4r>fcts2DP:9.;hnw iCxFtA&upHћ^ r(=H؎c{P@G?;qh@fT#E;HwAh`%2=#_Io3 v!y!4nH\(3w k`s\Q y,G"MpDI(4A AehP2.$lGz{ġ/;9R|"5fTC e-~鬆7񍂸c#j𑌿p* e<48M*}ӂn.7c$hL5)]L"JMԴP? ewf}‰UiS \E)sbp'KYzSn?'nH y$J]^%%_G?Z8&EV' P6*jzӜpGR N[@YAL|l~6z->Q\/Ihql/FAM Xt2|wUV D 2=Qq d  a+emm b\>9H})(V0V; f7D "כ8WJd2pt8Hu.xƆfخ@+ c;|$q8 P wh4-H(J"er(m)(`Ȑo cB{# ! Z=Em fz }ƇzH.j RCp@I >d Xh;fp.Bl{PF;6г>1i'rp(EIc`vG6\" {Vg<(2OLjBA0N {Y@u(3[ю~b8Z\}"+H j{> OT61P/‚/@~ bh@y0a 0q %fWp%otf ߠy:6}|,2ruZ: \'P '0'Q5Wyq7sS$ۑ rh^3V\ |&+ 4X0}5;H` 3RLEG0q3 k=sL]%]ⰃfޠH$j\b$ rՂH1*\2XuPp@W=w <u, Ұ`$ %7KX Y6 ؆% !hc5Klш p8 r8뷍\vE68%q?ׁkŏ◎ΐY0 Y  '1% A L @(  )R CuA`YM Gp-a(=΀ 3)MP P < AT OUPfM0  ;@6 0p  x eFWcv50|q @4 j  !7; 2   k ||H<3' |tY Q AR > Ts 7  0p1& " $q1o9A>kv ; O <> i :АДOQi8R `9ar ͓:@ Z w ` :rtGl r0Q _n` 0;C97;PgSNP; La0@SMG<>0 V"au٦90QME]S$ǀP 'ҰZ#OrL Dl[< Шz 7&qH ՠM g ! Qcoc 6sA=ZRdժ$T # o:YQ m :zȚDA6P0 D!U:79 4D!]Js\"'R%"UU8q31Ӻ޸l+n kN`]#ÕY K /ҫ"!ܫʽ⽷k!Hġ  ܾ|"|es-K;l:Z[ 0,/ ,K |-ܼ>,-61³ 4gK~ˎ c,&b mX48Rr,pc[@1 1 qGE!P78y,A }BhuJ'y֎Lֳ^&ZXWq]֏b>I^H-c砀 QH{ ɝ3/? ,qwR^)5Ұu B% L>;p a|QQl ە.{ 5=SB< e{517t (mh%ЍŮZipK_N8|"e:U$&7k(np,1; & e+Z2"Js/-S 8E0΄x0w/z$XA .dC%NXE M,!qg᫆o@PIt05p&p>I =,(8p,n = D];fs֎ә T S=U(O`GDӡzz͢k^iIFf3;3N\e̙5ogСEZ %:x)l@MOvg.Hxj 1 HSpAtA#pB ++hig Bk G2H GXxXF-$ \ᆠO)& Bđ&#(*(JȆha|%Up4*kGi4G t 21 AS=j Yڑ&|f' \!Rs1Z:'q(ll"省3&X+V\suW^{!iV&o)!yUYpơ5^alF\ƛl#q-[nZuQpq*YJ`Lћ<_vIZSHqti[|m?d&]t)g$\!p &vi1i2\rqԠpri9di[dfsu~w_J=UuƷU)(U EgWV{mvWsz`4 GtM6lNeVedFjL,mfcii4-<+|YeTLle|i_] Q e(O/Nq4&`^H9DUƬeԚonwyg)?#lo q>F'ti'!q]~oJZ<*vKwZ8HQKscљtK]E$p&TAj|; O #@117]gz4dYc׽O|+/|}TA6Qc$c8JxiotZqِ!0 (Q[L4ю K?XVFVHĘo(@9ь9 MhE/t$!E!-x Kk@ s M( |,OK3q c$䙉Ǭjx0ًje.ָьDScFG9cͰ OT][bQOp8hGq901Α Ҁ>|aYλu}JPP,&=s8tqA4ыҞ(|1&ߖj"{I/X1a)6;uq΁"pil"u ~p->P_u!+6[/'wyF @]ai=M'1Ye}<;y}ޠKSR$3#xA܁9;Qrz MUy,eD@Gy7\kg{3"z E@qEKeˬ9CMAHUܑ;2A{c-$w)]|/sނн wHޛ)wF3~2K!;B<}{!?zx#>8OR#)H bECtQA||B߶_gnc<,q2KHˢ⸾kvs{q1?7]`?@ A{X/{y@3 8ԡXø((!=lXp4 rBB)B2ACA(nc6|`sg8,1$ $hX(BD$HƒHd3* DADP0~6҉HKkho)jxh_Pk`9ahPuh񶟹 i%r[xᐽAdXK34Be *X1b-Ol礱dQϒOAX~i|P TOO"N8xԛ9h@P̬MPQp c"9V 󃁨!T\ RHc͝Q+RQ|ccCfm&5HR%ȞJ,S:u:89ӊPц&X.U>p\,w8^XSIԃ;TppX_ӃX K@h8Pmz! U%ɢ!_xTMTYU^Th!]mgl.5K1VyS*Y5`ȐUn8+tՅU͡K)Ub`Ӊ+fv mOoW|-!Ԃׁ qa)hH%M5n ``̸z%:aRoH‡o)i`Nb%ړ V-D9b!"#^b/ba0c2n31.c4Nc:c5nc7+6~c9cc:c<;c>c?dA@dC>)dD^dF EndHdxdIdKJdMdNOdPeKeR>F6eT^eAHbW0!ex; 'o]")`\taRCN ipHPco膖HjP[p -줗κHn<|0ST"%)k)1/D|X0rL?@fc 9DbV~hqeeYNZv[e e^_.`|LcdeiHg._`B?‡lf`n&b&]#,Fu^Q y.*R |fg겡6ƢjYhV64ih>k\iwM'3! Zn kΊ(ˢHa)'&Jj(,fr#+H|%n` bkɮ z5k~ef[?4!*Ckߦ*ndžkVw뻞Gk B ͪip萄W@UIlQ6l?! s !s~KC {bvp~=_(\X| ,ws=]݈HP8gC {ַ̲?P7O3{Mi* wUw B' 8|z';89&4tPu6L>D+A0Ak}OجS-O)%2f$ XA9_ 1H0jڵpFSW">{%W/ṗv.Dh9)k,|wL+!uȵ W6Zjײm-ܸrҭk.޼z/.ls tVM丶F Z ۞!JL8bApSk];s$I;Y&M&΄:-g~5-8y vHTs41Vsf.8hn=ӯo>MU\b⌧':jq8fE<=iAeL;ѭ%A0(G|Rr8hȖ<WCPEvxR`PC}Kr=8 QJ9%UZy%YQB^G7;߂ e&>D>e/}8,QA'6;p%ǩΌq;K<==\3̈́juu͓Z:*z*B SL19"2 ݒAXD@P\ Q<5!N10H $/̪X8ըCT5J93D5l#PҬt3(RPհ3XD1(LKi BrL;8AH4 |  -rL5}#3@sJDK;ƞ5|39s~8YS/*+AT`:$̌Hf ,B貮z-T#9戳 3055U/h6N1:HDC݉mK/IfSB80(v: K*920;ՌK8,s9BH z#]҆#WLʦ:>HǖyL3_"M2͈ 0앃4<=[=F"Xv!c5XÎ5 TA␳^Z՘e}E 2H+hFb2yQO8vh68Cs8CЋ@h|00Ea챰.|! =iUK5W/$`0- gC5R&] \OD D8,x j!D  )\a (9ұDa|; DŽ- ǡ|$$)ƀ$Ҹ$Hr\F~RM"*SJ8 3xT_ ~Ҏ%03O,H!rL$69IICZ6 F21g8Ly UdY^X",-$ԥ0*Ё>Ĵ3?GuhH(JE9l`i5$W〨ࣆD)PAȣG ZAr Uenm͵V 4VR5VcZvmA1>3VpXB2Rm.͡ |;=1SHG:`ŘH#i& OѸT J Ǝ@,74^|ұy@Ɗ\AO6 $隁 ѵ`,#fpK 82? BcŨ+F5N yw9HIrQQ),eCvX AlBl ǎr B! NnǭϹm1<43Qt|$#[/7$.,!6(prǸ6]*,- "4 $i9QD9IDžsaɌOrW A3i:3ֿ~^= EAlB A 2FEg,iM~b'$@^[@C[M1Q7@G,ULD  _A80Ej4/%CJťLD1A $0@C}P_D]a! '$1È ,DjFD @6xD1,-D!<D7e4F GAAh;xZ5!HChAT8JV8$ [|C^Jþ]]8"A@C-t A#2H!,D֢-b^b V8DQx"ʝ׍ND,%z 4G̝N A`Z)& a]D!/PC5\WA,E<D Dt"4=E 'O$(6(6Ut LD$->̢"HH[s3 3GaZRB,JAp\Bc HOA[ EDN!QSz|$TZ 6Fe"W3\U&0\C*(PHKr\+B$ 8<LpM`&V[ 5F&1F0]AhTH:L: @LAp[08___JZx'e9DcA /B/8b &D5B , >Be^/>A4 <iG9Clt[T>D4gj$DDB@E\G:xCr4 eA!TJB8%MC.$b.ih8MY@a;LCo A\H̕fBC$yLBǥm%[h)[TX,H=&a'[W=\_U<;Ψt n!iYU[Y2)vd?Rj"/^]c^]:.Rd:C0i9jb4xD801$9ۈ0+mhՉN8-@M֔E'zɞlTъO&HgڭS# eyEb҄ j1kUʢu8hTRk.`j4M9XR/$jCDD6HƵÚ%,[/OfDe%k->`y+$9ڼ97Wd!DBM; 91.,FU6D1C9 k6QuʶQ%PY܀*1\"3uC6<2ZD$ߔ%3#ՏHt.5AL4ю7d,H2:̲Y.S7D{O0?0ys(c2D)/q\5Ŋ5{n6'F7s8_/ 3:7SSO%>6#}0%-4]Qؔ4ZYj\XX8Ƹבc4ȈDS;Å9LD ,zC$gCCg)jE<:7y9z:%tAN3e):j 4X^BT@G de$Z@%& @>$|vAc|ǔwO.ۉL^Op;8?J%Z@ǶCGiAx9$ ۔{}]JY@NDCO)o90Rx{\}>C1?SO"{}~A$D]k@]˞Zꓐ'k{ 4/<` 5c׻GL4HDf281VF|%pAOoDIZhAxlYМC5ziRK6ujTSVzkV[vATdj׬Me>)oIKKME0H`a>`f̀Z2`ղl9f . 4-['-Z4*HI˻nݲׄ֩A‡-iöGh6׸oz}zٷw~|0k֮cVzi g![qrEqƑ|k+,1O Yag1qy4`ڲ6˦Z9_)&sȑeedÇ6|ܰ i1r|vY gq0`l'eĴ^ڙ4fI-s#B =D]T>g 3ɏEfd\9ihzL^>IJHbtFA9}o!RBsPB+luQ'j0qMl9pp9`QguQpЊ%bD *z\&m$Ok;,fF`V >m2qa[&RL[LZ:FeBjpYQFU3[ wd_zopļf|=GQwoQgbvgsYHZjٵz0 oyFRNCqjsd 1IfDZec͹j5dYJБ&Z'Y s g"YWGXSj'!&ܠsu>o!jIajh<u1CsF3iʴyWceaԐߞ~*Rqo6%p.?6W96'q}C]BXua;ůdx8'<+4K3<=}KRϭ|!IXB*03q*/s\@':tZZwNsf4hlL^E/%,+^j$2u6׻ F7q4J W0}2\j}(쇿tS#FOL8)RVD3*u_aX- Q[JWL9j2|}/\.e= 6<@<}~>d 9DЈx9f=11 O-fq`4#SAj(kv δG1Id! Z$&-jOym`DHsܖuD"79XQerVD$%+- /#Lj['R s$CqED0|iJLyǘ^S2|܀]L v#h| #0Ⱦs~cq;|RKhQEd93r qoA N%ٵkb`G̨ŗDµBq@Vj|ĥb  w80AC֞@̴ `;#1Ať-#QDtrq沃?T# 2cx"H," Y_L lJ Z80₏ E2xSy=C1=wQ s1ҏ睖f}"D?CH lOW"qsdCBi_{}eb:'JY/.nї f\B}^]|a~*"/(l -,PB-~F"P'Q=$?C"t G&SPO$$<CkMPp{OcuoP Nޢ)v$>(/ ֚!g P(4=P p00 pPQQ> Q+'+($3Q37?%AKESQW_q [gPksQnQ{Q X!6N ^>D4cMgP"!. ! N*1!Rc14!ELB<(nA3!"eF~'ؑge:6R`6DUA)j9/YȨBgKe~ ^Q$-PLPL a B &Kb D<֡!,6I$\nA!?b4OD"lF%AL^Jhu T`D~lbaItN#8NT N> D6ew?$BH\ZAVķ$|~[_A$&*an]:bMMcCaN+/vAQL\dtai0c"ZrQGaVbp,,(sȀ]Th!B5kNtN%ܔ(^CtvZ&WG$ ky&*Ҫ!xd9%u?4a!ZfZyZ6R[[b $Z4gkim^Lp'#jB ar,rN n("ȏā;yL ࡶ ZbV6 SbZ  H (.'> Ot(tT\%l ͐V&krk2"*A vmyscׂoE2**%x,Lm @ Bw "Br-#'zb )"Ft@ }f2gU4ʋ.",ut'w''ƒ[ Iɮ!t5 !(l" $x$mq]gA%>%#&s%szfena !'f!J@aquOuw?.Lw$"q ­ר, 8#귲M (W EPEJ:ځ(y\$OAre"يAb΁eh@P9r,(Z?Ua\C5ݛ]PP$}I )}ަJԡ6`'*m^  uyx> ?> G ؟~Y*'.t)(rҽQ/# _Y 1 @!ċB ^މϟl.:mŎz"d,X8#W7of 4w̦.^EG"X6F׮{̙4kڼ3Ν<{ 4СD=4ҥL:} 5ԩTq'fCI9K"A%iՂqĕe̪tڽ7޽| 8`dJê_"\IVrخdU.WnAKKr >:լ[~ ;`9#8u5mG@dụlCa7I ZcfZ˛?>q+.7l%hǓ/o[%<ٔL- L>MHa^aV1$L7sN1g;ӕ4 Hɒ7 %6YU3 H2Y#ÀandJ.dN ;8%L1&XEA!|ťp2W9أE|M6A id>IgvމgNcNx9c\HM4჈,dBHIbBL4#0Ijj昃D]ⳑ:|KKK|R^|# 0HwL&nm~9O:3@4 0h:PsN*lKwtnj+rNV.p?LjL̦3ǴSK7hZ⚜,ǖ,v~"/0:s>6@T 6|nK2 0m3d8ԛAd8$2C~bMvfD.a LOG=uY Zݖ`}vNiKe3/)L}M;X3ꃈ mV3h]ᢏNzz>P7t_G>y^~5{+\8nzz5ٌ# tZD7dÍ753YM3M%0Ր[1 3t3M::/#}n=M,N1ͽ>%xN6B&7$+ဎip$wA'_{^W 0eC 8!5cRs_w:(p~_DL8QyBPl!QЂZAx+GSU"\5qg(#|Z5>"pFñi*:A<`,(QpzN9&$y4KTxAћ FhG0m"EZ/ zZ` H]qLQeՁ,f F0+ZkVp*A_D;<\{Zʑ28id3!f(*e e͐fecӰUgr]| \$PPE}1b4A|k`GI |C4آ[4C2>Duht/ dOk;ݜD.N7<թQB9aWh@~JQE7ycH+(KI(f;-ؠװ1A'$]i䱀^"_` Mp&NU cl S.-kϛDB\r[L Ip|f|S;s3Md!|y 2lof`v xoZF21Ɩ0HT7al1u8.6f)ɊnC*8j q^wz5&fLz~`] Uε]'rc _"X}OffnɴG?@@ MY7@xgswZصJ9wh21B/FX 48+ ȓ42GYl6!qĶ__C=`Q (5A0ж(8$_! ?v6&%тi/0=/ZP1jtZ)j £9~pz1((V {wEr fDV>r[[5 5Hez6Ѳ01{sE79$^%a6cD^j  (" YQT;aiq I6H?B \/:]ixж}"*3GDxKڷ0nB*`I?UA%V%Tp Pk P( `gC1 G i3VDalnq/Gy1b@ z ]  /pOW)BӢ|+.ėh!QnjZ$;-|$,΁C1;.qt"p 쀸}B oĠAt _3I0% jiA<':|.;'39V5(CD|52vb2B r<KgTiF bWCW? `S b&-#/qeҚP,19`I*b=MwD+t4$'-'Sq2-/M!C EHjr9- |#ٟf-:Awl1- p tM'rWb>Lױ6 ?Y#?Hq[ _!-ms<-ѧvmَ30 m y*Ly#Y)X$5v+ot8ʼn m2Dژ>!$BC20#J rU?W&@ ʃd [ظ6.XU-  'no+-nZ1~2?5C?K4/ @P ѩ{~F1 !SGVO*b栝9 wt/ע4QG,kuGz?Dk9$ G  4&⢝'C ` <'> ; S 7H@:~'P^Yl6PM4x*{ ?d^GT"_j/u@/6~# 'lш҉0-ҭ[ގtBތpqu@GȰ&q tb!CP@k7 תA W"~;jknV @͒PT[!  %`UI&,n)o߼-Ka-l0S)@ =4>G:>BhCpU_)M&u03sˡT 0D2%!C KPl%$O}}ͯ̏RS/]P31>Nۡ4q#3! }C|daGoϓ! 0.#gP m Ҩ 4`H$wҪme]xM5}uRH%MĈ/>-]SL5męSN=}TPEETRJ/ G9gf,AS>u1+-de"]q+LkKwêe$w!@1t7kЀ UL3E7rhҥKlZj֭][lڵg?%Z-6k׊VsK_hᳲe 4t2`²_5l,a 'M])vǬ <4+>UvGPfq@@ $LcQ-B 'B /0C Z)z;Ǘ^"abD,`b鑙N;.^ q/kRGY@^+Y(HAD$7dM7߄3N9 &c)曩%B|q\ nvtSgaԙ&b?" nɲG@0J0M_5Na%XcEMSOjdbwe)EiuToyǥhfP(`e;[@L2zGpՕL8┒b/8c8cvY-`1_'Oi|Qg+A1=+Sb}8p'pw8(&d)&<#QY_LnZddnG榽g*sF/[lZFgj@fas1ff[v>"k}iǰ߀vЉJ(c@;|'|GelJQxk'II,9,"e 5a\qvDb&W_8G=i&fzo̓(^px7Ր4auC0A n8c?/#&pЀ+A >0lJzpT;YY4SD`7C|6dz8HBҐ:C0 q,clьj~xE8FvӾNb03E|k8a-С7،fD3F5s:эiTjpf64 mm#Ҝ!9d:չNvR(XdKH($>0llaW(5ŗT%+JXre;aVW4,e{<'W_0Og_\8w]@O·Y7}HҗXWPO7mLsM0Ae15c8u41>[c]([Huh WvM5klwۧ񬶻&ƒAm ."?#?<̈́#||%ytPSE0?D;>.C/z~"o_hַC:z˜$B#:LC b<|sPHo &qqqahZ*Ќӣ%,&̆h@+SpYB2,4\6Ԍkp(lCRR=kCkDDҌK̨nC| ):DKjKX8C(OPEQk)fHU̓VtE#̠E[ q (w;skpJ`ІW:fg4ijFP⪕F'*_lq+j؏@p `EY@2$'xsx\(]慀,-]F,MpY ZHg I``dq(=(w0DHyHACS-O-qOuwpx#o0b= u VS|7 >t {aRlY‡v芲e0=<6 {] X> qo-ZRhVpW;`Ek5=fMNXaPh}aOxEbv_VWpfXym%'hU,p+x 8ySb/ucTM2NJq@clac:f V9~ ZAZ>CzTd}|0dg8_sZ[bp h XQ m0`h@= L8v_)yQAXEqe?XOe{8\{pj-ޖlk(=]0pVXpyP^Y8Q@Qj]IXypbЎ5YLxLgK wi}!c6L)h t b@ڔ>֜= .`P#_a^ Ƈ\n(NXfD%8 "Y8g.#VPH@(lFf@8V-A 6U CYb]MSm - P֍pl[hS >r0y4/.Yأb`r !NH؝>P|Rg<; `2*8Y>AfP*\؏/` <0&|%;HW*|*8|`LWUA}h X/Qm\H \Hh-x>H``\{iE^ȆXh( Xk.>#]YhvhĀ+%Y` ,`_H#uP ͠A`^*S`o`Px~0Av`0,JUx7G Zp"bE` \w(Y:ܮG  )]ne v֔>&rpyTu(̟!&'`JqseVf:0@ ;TGŜB9HsȅLCptk( (h˫R(ĈI ZϐIkP౨)"Mur]1hoXV^^`oW֣7BGQ]"L k1rI<_AQQ^Qh> ] Lp\5_xrJx —8N܌faEu;WrdZb5oުUYmkAO:וMH9ܮBij-c\I*1b DG8Ow><\b%^-iN;PlTsLDUSFuD9SR;휔R}3K L"cN:OADQ l80RQud7B6VYo9JП HҞ⠴ >p3E|N:9 F30Y3(58RPT/Nk:+nZŮ4c;*ԑ8װH3B:gR1#`*8p u%ߑxͶ( Lnܠ`YP"0\go)Z~OT/s>ȴo;>#\'ܘZqـ):1pNip%'vў*g雋:M$20VB;gZ ƶi*9*9 uE1ST챝jg4<.r̵V;L-@y 27߬S3ڻ-" ,sp 7ÀE<Ֆd/c".%U#3/ZA $C9 5s-4l$4F<8fbC͠L9#M;tAcP:Ѫ@G6Jru=W(V50հ7lr8S7zl-pTnjpfF3MU'Wvf#qB|#^ZReE3Ha"/1b2;G3N i|F1ħp}:G&O!#.C$PA@AQ A52fC G/(BńV6TR(gXC`u| #dW-DLDM`EdU|%%1b3&7Ȕ*I Kc :Y`GzET:ѓY]?+V8cyCXxF'[ITs3+_71|(O FRfd*=abgZ C}HVŶvXI aHC(iu$A 6ۤxB<%c;'d2kv }Ȇ7kmo9Brʂ)ŜѪp~`úWGVXqtY8UdC4m-HB.irW, ͔[o`LwR/$]08@pq T 32GT,K7Q uDcNEc9׺5{#COQhX̩N7+FVbJZ|rMU"ŬhAqqe'$@IQKg ^2;o4Nk=np7Y𸵯+ncܷ R $ ,! lȂX2@#ߊr1kc[۳Oك܁@ -K =o%~I,{ ?X; [$t_;v/yXP^|Zg C K'VΘ ?+ DV:FLg@tB$ Yf6cN;$AF6L qҟ%٣#<PۛCJq ! 'J Ѓ0M1}I^/'kƂ95q~b zы@hڝ^5C1Ԟե[:҉9]$(E` q%L_V\VVl;{Cɹͩ'H)dUy_h Vܧ 8": UԀU>Oh֍T F1 yP[у,,ك<=C h xB=z7ȃ@ S Tϝ`&j&AB@/ n f6;U rO|!>EVT\!h1Fb!bOLHiVa#zœaֻyaÉJJ!C,;,"qC,&Urb==UOcW~}V@!Vp/ʢƀE, O9 4@C JM 3@1k$`}' B'ȃ}H/pC- I$f ,hNdx$Nb<.]^">2eS:n]%|T#AF݁'xWb> YOEDaUF⊱F}]fE lX$!KЎE':^C7a@'Q#Z"TaSbffjfyy&:@B:H F: O;B930LYHC(E.TCTiiYD6B M YrfN6„;b@-l/HC}HF88W;C:0cLTM}D@$iHZ]y5 T@C;h'APgZ38W.fRhZ[ "Hϧ|hCM~  F;ԇ9Y|:DŇl5:>`7J/PN6W> 5hN9\B4@j D9DZj 5ϪT*bD : W*~Edv*+kU+l*2ԓ8X.WhW,V@^kꯞ"@Eça\ħC. q FD@kV\ǚHaW4Z,*@^ll:l,ll*mm*Ҟ+2BmjJmZՖ brmVzm؊B%ٚ٢폁mڲmۺmmmb mFnnߊ-%2n㺭VJ-&+bnJz,nΊnnnnbf&nn>n Y"2n)oBozJoZ/Qj&OrxooJocFVoooopo0p#pp30.pC>pS0Npc^psnp~ppp p p ð޾p p 0p0pqpq#q3.qC>qS1Nqcq^qsqkvqq/qՒqf1S1' 1 r'q!n!_."32r#Cr>*rFr%$[r&W#kr';/&{r(1(r)1)r*1*r+2+r,2a,q-.r/ 01+2/3m314S3V%s5cc\s6s3s73~s8ms93Ws:ss;sɬs<s7s?g?t5 @CsA2#tB 2CC413GtEkDOEktƽ6F8NIBdZJwG2HH7I %+M[+NoK/K/L7tP G0e4M 5c=RUhR'"<hV[uruX?AWWWs5>WsoXӵX'\AL[w\o]׵bOh>_qX5\ $eAA,@Cv\3F6X`vV`AaUAvXW6XW|>p#Fp[tAY{V,oFnm_w[FpVbCqӁAicx_xuaY} 6dصU\AnX5Yl5dUGUxAA\ˁ\O\AXEnCvgdSobȷOv368v`Xv`A t|A`Ѐvia\z_kO pd{5@7 \8>`i``b@va8Wx__V`o VVY|ซg7Yn/zax|dxXC8y[Eu(7UTOUpsioAWU/U6xs5Yz T[$>\v|h[ӵaU{;r8VOdh9_V[hH|b6ucbtclU8bpA{WxVXlUtacpw ?GYv 8>h>4@Vj+O g `ȶYsuC`/OH7>ػL<>prx5՟}}ǛdC@Ai{ eo{ȶXϻ`tɐ6aHn+xOwaUt~ VX=dod`|V`̼UUx[߈> @8z~UWy#ɋ9ՋA7x@xogŞAXED=7egP@@DȓNj@ ҆-X,-Ӹ3n4J(GA(iӑeK4K,/qzc 5#  +R-//c+3L^`C - P9X Kh ˬ$K+.*`24 0%#{@p ӌ9Xb81ɂ X{Ս9TRCHT+'Z7Jb8;C h!7C+#51<@Íq;n͍(l齎#Xâ5(U}Ԕ5!@a> =sO.x|M%RXZR#(Ѽe\%_ jl%FQIm՗ ԗP 3)[߄MJ!J.+ȍ-f5q!1 "\¢?p#1PCg>p1 imjp(7_o<'b_Zrg_I(7130>8DP@-h>>ˋ-l$ S/\#"#6hC 382 $RUq ^^p#5YZ7B3W-6}3*ި /3 DZᲮ9Q5#Ð @" Yîm$vN3 6jUo^![1uD1R}H ßLsǒH5B!#^  X7A`ța3AmFl@ ^p@<̡,yɾ85δd2 B|Z 6ǖ]'Y BXw̽ t`!40e YrUEE銨*2L#8MHr&r  QxTn$^\0"!-%@h -#dq*x!]Ċ _( 28)PX-0 /JZeEМU@#tdטi JM~Ƒq}PJY`9Z#MYf_1YnBˇ2pxt+-QfHYh }C>TI`-:!Tpղ6!I^X5؎i&ّTmnXZ9@U%/JdA#zI >ӆ8-<>/1 )tT^1r.IvSޏƁ8 U":Peŗ5"FY5D% %:( TYXKNj%H0^s# Ve1׆>9H4&Z] @H^7{pY1s'~g6h7!yjK*" :1_y*4?A 27Q>sop^ >:31O: |@x3A\, _ָ8qq0_ү3 glFjՐ>6Q r|3C.a#zA#~||A#}MA8/O/oa/o#fAAAa2ap~!4:"!!!!ZP/Ps0|Pp#.08%pDwy1"p#rA'q9A+k0UqYM Q#b1Y!^.pqy{1J eq[Q8q%k(!ɱ#7B %#g'PSr 2!r!!!!2"%r")"-"añ#1=CRgqyC;O#`r%m&q6 sS #'9%+jr#dRh))2*Q*}c$R*(CVPAo)r-ٲ-B-{c$$17Ē7,-2/ 0r0{#11!321%2-2133wX253=3A34ۈ3E4M4Q354U5]5aS2Y36i6m6or6qs7y7}Su7s88)839s9S893:7!-, H*\ȰÇ#JHbs3XˢǏ CIɓ(S\ɲ˗0cʜ)Y3f+ϟ@ JѣH*UQepkիXjʵׯDiZd˶۷pDn%IqCn:tƜٮY;`Ӳeٲpذ#c`͂lwZ/e9q̒ LgϠsF[pm͖pĝ(ݷo۽>ƅ홳bڹO Zp~y wtWZlӬN88tS 4 8騃7մ/3ޅƜUT(V 31`͇͘65ħ 4$NFl̈K\@)DdW]x:`SKk-cMVe͸ 0SMbFig(\8^2h Y'".(#6<(UF+Y>L3 >H";p; 0 `"d:ܼ ʸ#5:25C۶2K$/'xx= ̌V95-wʁc8"+6 od#N;Q Z-nы"Z.uZp4SNs>RȀ|Љ9́'ȑ\%h⋷8%0(sbdxl<ƙ[^LxpE8DIJݩM1 Q^:n\Y XNJ7kIpረA0V`Trj4! t& $T@F# q}x J@@#ǂMNvBB 9Q$nXĹA }0>8`"  4!8iC B|8I9@׀H@CzP@. X Pdq\f̢X;-fmGZ GyEr.\Z8 jE/9WIp,a`X%ll3 fqk2& B" Ff%Vs u}Pv @ 0 P k4}hj(L! Lc8-m/@v&lȤ~&TA {-2@ Pn6twYd0wyg:s6Y x: d&T^0-ktrQ:, B>_ PЃ? ƅ  JT PQ-6:Ņ'#dtηX @8L$ ZawWWg8a7xL/$b 8c0ep02&LFxGJ2&eTMmZ cPX6ǣ4/ `@AV3w@j DC> <Ôtȱ ܂p0tc6/i+} ^DP_]Ρ lc|ٗ&XWgL]7& WܗVuteɘY86w b d#P#mSxgcҀmY 0d3i%*0 ^"u ^B0A (Iy0?1+ d  0> $k 0|0?0M?-[V[j PIĪ\`۴e+ȑ B!]۠M+Qq{v{I+E \ a˧AԠ>+TN[P[x;4dI>+84aI{qR[;[{ۻ;[{țʻۼ;[{؛ڻ۽;[{蛾껾۾;[{ۿ<\| <\| "<$\&|(*,.02<4\6|8:<>@B7`6c +Pj{Pֆ` C bpE+ jmi{|P}mg0դ=_|\bk`-pi @۽}ps=((eMMxiPks}0~(b=n jZPyF0Wh=! yG11a[ 8Xp,)l+Җ*>k.f^/m tpx6WP]  Dn(:|-[p^pf_ų a~A҆mmr}s^D.=g0pi~PW=m>8:Q/0WpR֠m y/>Xp p]PW}.Qϯݍ=|.An߼^P mqbҮ~D`-g^P~\OYz Բ]<7xfWy*ly!m^ _g~y`P~҄m7F^r _CN{P\@-gZphi I[ LPm{X'_c/e0ɽ `T[g25ڼmp{Gj--I/[0=0[0o0{qk.>hkMಮ,r ӕ=w]@t@GG.n3|Q <|q .\E~1CP D1eΤIL9uOA%ZQI.eSQNZ*3mxɓׯm>1KŬBt |nnfMŝkў֡y> 6=$xLG2o<'ɕngСE&]YvvlٳծM3t?U޾i0{4p1䝒)k+Dٵowŏƀ!yǯg{?*Ι3q…5qg@pϙg&fIs two0tYe '@|&q_ɦ&r`|3H|LH& gI@oJ*J,2K$2(sL24L4|%2M8sN:/;O@4<_ 5P4|5tPFuQH#II+RL3MsM05SPC<9TTSUu՟8UR!E,VM H*\ȰÇ#JHŋ3jȱǏ CyI"k\ɲ˗0cʜI͛1DIІ 8 JѣH* uԨdիXjʵPB䵬ٳhӪ]{Pmqۻx++Ho! T}+^̸㊥"T R>̹]SfE:3i|A^ͺ됤Yx_׸sͻ Nȓ+_μУKNسkνËOӫ_Ͼ˟OϿ(h& 6F(Vhfv ($h(,0(4h8<@)DiH&L6PF)%s;di9cΔ`Wed"w8TSõsN8)l2\03最~i砍y|)s J}]#)3<42*vPj)j V5:L1i*0dS9|S 2ڪ)&U$@$;zr0HR@Pk,fknR"z&@H/ᴋ/N2;K%(  ޚ81K4 W+1$N`!m#rH0ᆲH8˽bD^=tLo4ҾFNTwP@!-,  H*\ȰÇ#JHbB`9s֌Y8q…Hɓ(S\ɲ˗0cʜI͛8kW,ϟ@ JѣH*L^KJJիXjeL>T٪chӪ]˶۷D{" W-X"G˷߿{]y ^̸ǐb[W,⼑3k̹g WӨSެ`xEMJ8؊q NIc>μ )L~Y6سklwËrӫ_Ͼ˟O~>(&f$dr F(ᄎ=* >n(/洓!V$f"#(` 9hc|28<#訔/%($H5vcTY\vѕ=fd) $Z15iI(k&ˤ6F+Vkfv+k覫+k,l' 7G,Wlgw ,$l(,0,4l8<@-DmH'L7PG-TWmXg\w`-dmhlp-tmx|߀.n'7G.Wng@Xm >x^]xgxK~|1qEmı>knP. GƷ^`QAml1цW^-UA[lO9A;<_x +>6Ohy4syK \ Z6A{V< sHB/.hH, \W2:T W6ȻLKA^H@}lPZ@|x W"Bp=  p7d"c@@A"1\cȒ>-wNڷ/O -P0Ќ<? Hs>r7(!'<` yРJBKM#03xpCAA-[%qA=2<X8a xW_=H Q 7" n90U82jސ9 "8 .pC Rf7@` XϤ9jЂ0Szjp'>hM 0^r+`7@N>N nh5A ,C?:!20V|B|@ B(|AB/%3 CEPz Y]@P: Oՠ2 o=Y di9jơ O ^5'bākP 0XPۮҵ }v5LinFwٰ -@atfXtϰ5LySːҎ.BbukN{m&ħk8oTڱ׽t^|UG`ױ fr a*@e ld7p94:q7at87ƑiLa7jT92+!!-,  EHpDȰÇ#"4(q%fxF~H%TJ-'diB6-Vd!-,x /2gΊek0k#J᳋3b8Dl CͣɊSn|h#ɗ![vD2%GaIb͌7yZӹS5?7*k$Dl՚5cm۶ljʵׯ`ÊKٳhӪ]˶۷pʝKY2thiR,%iϿAyYo8l|q`ŒҦ%FZӨS^ͺװc˞u\)1;ǍoēK/sN^zaK7ղNLY2`!JϿ?~ic1b&xKE4J#V( >X.L Z( fa 2Xb#"'x/6آ56K/- 1PF)TVYV$84Ÿc8߈yvWb)se9viGfgzkZf2uvu'ukB 3zM3 Bi壐F*餔VM1NwY^)wnryɧ`zuj% jM;gkȾ!D+Vkfv+kM4&+4,,l' m&j7ިSͼgϵ ,$l(+m*Xu,4m<@*L8dL72;- mXg5Kp4Lc hڰ n-t׽pTMmc}6ۀ.f}uv'kw%.W^2kQ[nیםVÑ~mNy.7 lS$G/Pxg~w/>!$K|PfOD:1/+Ћ@̏jV Zn]ܡj` ШEGHo F As 7: wZCl5Kv2`P(=CݏXbɌȲVE4~12w(W X-lHdžrF6qb㌀ 8H q<@::cp!$C:Nz (GIRL*WV򕰌,[ (qZ@4! uh!IbL2f:Ќ4IjZج]2 gƲIrL:fb8Iç>|nZf=JPIMBzR+,D' %ZhFK]Ɠ ~4JҒ䨴 *Җ46(LgJSB4KwS@ *; ȈяTZX 1 upM?hMYLͪ\zҭ2 Bj `@,a F0] A@~ zȜd);F'X!xuggoljwuJ`dWFȕ2X$ aQtAaHRakz xչU`6-_to:&DZͰ/~KzfXQ_`ܷg'La.Y#X \F̅ `` B^GpRem=\ #;u2-TH* c#ng9k[&DognDX  iധ 톣N˴l3t1f_{vl^Jps wWn9o|X0|@ۯ0,'zYWY @v4v2Oܪ!8]`߸6B^ʝvA]Z[7$B<|p|a|RKTaN&?ƫI  P۽Ի7# Bvs۱7 äBʂa.7pL ?hQ4wsD f깰z[i'9_3*ۙO~~WLekH,8M 8` 58)xL р(tc؁&) $ X'S2LmPb05>L[0g789gR|/ M&V[V5t;ٓ0ג$yUKa!'1WQI}TY&iʈzW_ /Pt2P Hg<ȖM@Rpxq `ehxe#f{y~ʄfaGyvk7LYpid9>gEnW_'VbPY9onL҇ehd)e))xe҉cYx e:eə九9驞(aٝEFh`܉RƟzBIfhA ZU VXE\0*:XxOR]Vš)yO\y(y١!G `3X*z-#ZX}xjzyGGUhDunis0.1ՄN R8+ J0gC,0lE/$C0= /0 XZRMYhc#&_*bZP&qV 0Z `Q'y Yq8fB*ʃ}fG5Lzפ'ynuRHLn ,Hժ:wzz$Zccחup]^[ڣ~FujQ@Zpݚr/XX%P1<IU @pu P3GJ&UgbǯcJjV-XФI1J`KR83c ຳ׳>G&h19+L{N cP8UK]`@_ p[۵a;:f{}\p_t:g+Fv+x+U6giw[Jet`rԧ+hԞ+Y%it HdK{7%YZT3Y7i} kUf|Q{N6ԧO)V#v;_lLۻ Ta9eɼ"Yk()pL,`\rkTt)z ׋UJvf';۽[([}D T9g!)lG] I4{<йGLηLͧoVժEL!Lk%xqr[n@UB,!P 0 F|I<^KMQ<>\%j PP\|^^` bLf|Ơi TB,f[  pvr<5U }j t\p;ԇ]L y ZA%cl0dMGui, eg bqvyz@%^&__p W}ʼIbp[@|kp|U,,S\`^N}bN[d.Sa泵1n>XS $sXunyVth|.f%L/PyマM~SŇpeO.=5ECp0ᮘ难S DhkJT|٦}᧎V7Y 0-oU˱h~R}KPZ{U>̍TU `ѮUхXL* pLP#%h!oPJNa\>Q^%@+]kzE}~NjVsВ:d/5w No-c5o <N{ALCOdGIIMIO$S/H팲mՔlEjV`?Mipr@7n7?CTU`S HEiFmuo=LvUW@ ߀rWyĦv^' P: pKMڦ>~ꦯn*rXM߰N;D7GT0`*_L\`+~p0 ;@W$/a<j/QFp!.[paP >}EXE5nG!E$YI)UdK1EY3*40@PMA%ZQI.eSQl̈́ ryHqLaŎ%[Yiծeq[qΥ[ݣYr_&\x/fzve̙5oGȡE&]z䆔%~fkرes4]mܹQ;;owqsѥOg]Iuٵ*ŏ'_Kկgwϧ__~|p@ t?TШ@#pB *>0hAåT2 STqEC*ʂ !@FӸpDQlG 0=i@AFt2AV @-J|PH0<"*a#H`'tA* 6xrL>ӷ2 @}sQF ĽzsSN;,К` 1@C6UM+WtKtOOsuW@%JJ b*MuUd0NZ1 W^Z|$TcFX!u]x?aK r\~ םx 6y=3Jh~#0Nh XԨ=xc=ΘK6OSWdH>ehføbgsQhph,ZSiz٬C]zl[>l3mKS{50b6p\prE +C 2qCG|u㜳@( 1`wmܣ>$݉~8um7WA^4 57?jeТx7%|_"| U82@S`C@(I"Ն,( ndw2ED&VB C   &1ot :#pJ"'(a(,)[<xƨQK!ѺF8lsKFiwPZ˕t@dj|&:%*y$X7hQ:`aiҧfu6,#dZByBBB*T+\;,$*-B¢CU!4CCFQcìr7(CECÕ7C?+@tAD*69DD+E|Fl9| `?9+v lD/Dw|r BDTlCU|Y)M XdY3(B^_܏Q(g#b:(cfEÒi raNUR1S1ưFr'2yRG`vĢ8!zT{Gn1SNHG%\HVjHxH$G Ë$/8/-zHȎlPt':RA8仂.!-IIɕ 2q@ ,@ʅRJ~ɦhc tRl .'\J(y740-~1#A` DYP`x즵dKɉ0,LLnҫIYIGQ :4Ĥc+d43B,$M| 0M$ ?2.^jM 'l|ܴ̎\4_ oN2(pqȆkK$ ,LO\X108pi> PZL ,qEM"mзxB |0PP|P P BI$ѣ0QP՟D ; M<# =# QWQ5+3%&՟'38Z*&$.)HI x]S/:a28˷X;MRZe_e\V, x05VR+v8_d=f]Vb 9Q8|nEop=Jq8os8vhsXrvh 4XU ŇuX] M؄55 o sHW|%vw=b(o(e`rh`f֎؀e׊8؅}ؓ؊mXيM e،%-shڎvXWYQHIv`Zjiy0yY@YZLk^l`P@xoX[M\0JKP0@zI0xmE\-]h5Ji[M\\Yk5]ܝ ](1ص@No]^]0 \pP^p^I^5y-]{^m__\-ɍ͵O`_p^| H`p_@_&RpRYIX=Ε^`}`V H0JeAA\8E`f` af H5aa (EpHhPW``b 8IP`Opzb/>)b1HZx hBoPuqqi1㖈vH-zuohuc8:n`gtNgu^gvngw~gxgygzg{g|g}g~gghh.h>hNh^hnh~hhhhhhhhhii.i>iNi^ini~iiiiiiiiijj.j>jNj^jnj~jjjjjjjjjkk.k> Y= ڵkp8`xDkRkh뷎빮kV/N fhjȆjټ&lFlF0E앻-5tm 3`6p6l"rVl56h/5؃=Xm/V>Hn.F-#0|`/;?X2504pЭ5@<7vݑ=I|n.7hn0Kւ@p=\,69ȃ="J@=|v3P5@Ђ/PnƂƇ1++ ߃q6NF6[@%Ƀ24@.<9؃2n7noup|8|PFoւ(-Hm4o ,0Q+ȃ9P7`x4"`|9.| 2p0qǂe?ȃ9p-6 H?Fϗm 1Z'J:)s HEnV@!k \GPTyA!]izT.xF`lh@ Y:pACaQwW1(+]X)骫gyH@-NF|0 7j@Rz [XH!@@`\deAH<`@,P@]p?+,y|qcFeJ3a!6A % PE-*|5Yom1LpT2 a@A>HZ}7Y, YASiqGgyx}|>,3`t1?lZbUE,W6`2BDqnqF;|HrH/}xlgpnرFq,l#>1+?ѣm1>dlIV#i} c@Ï|G=bXXҢ/%w9`:|@W`#/h <j%bBX kEL<񰇐SH jоAM: VZգ18L'|GfHOH`a%PРF/ fh㬀h&>򣏎#p$3\BR64dz@@\X$&;#D!шH8L#3UP종@$5f:Arp3fP4`0 {rq>9YLӘF5Ɍf@t2qq2,zs|,8ґP 9vJp5&MY s K kh2ohF;vT3F6RQ!*, :+ As*\ȰÇ#JHŋ3jȱG  ɓ(S\ɲˇ&9sVl:IFڴR۾5nͶV,Yzޕwmal{n^ )N\8_u̹gBMz炔-c|\Kݺ8s즩\}fq`ɒ+kgvn,n~ \pet`c3Dh.wa35fcÉ׬Y5k<3̀ؤ8l:pW 9Ts5xM5T΅t̀`) 8` :(1v:^c̀8 5% 39GM6(٠eg10C88c-̌:,x D/Im{1@khKe=OM=$Q@xt94oȓA4AP#=]ZS=hNV+A iLckF-Y-) y 1*B.QSYN$#IޗPo0G1fbSj:w0FxS13 T*x kdT`y0Oh&0yT#hGxGXڱXs4 VOUOy`}U]b5x쳟N'::В]uCJՈԎ0;0ڠsXcձ})f(ɺUP:юd4n7WPDhjD(R!=%OPY @jY\ tPD&!GXG=hGD bD1HH?@ZG=3_ /bUA 0 C#* *X.:>]ylG+M 1r gCJE׾OIЮq `tP$7dgmOᰆ5@,i^30Kc"S1(ciTBl!@1KPOd7nWNt7MHxI / V;~A11c\C$\Efwpao =((Vq.VO[<)sGC-,s%[d'[_ cI@[r8grσ}`l fح^Ȣ(,O8pTK@G$hX/ wLw9 ץ] _u Q%P@<$N|kL I&?&( &LsQzlj<cV*Pba3QnzU4+ lH}jKKol5af-x+raxh$G7A64$ " =WE@X4SX1MReGsi!.DP1P1 %uuŐ 8R(J`?˰?3 YP 0@=EdA%:(P PQ oEdvNY1=菧8<7d~ xW:yG 1)2{Rz` Cf=N5ΠŌuG0s ŰTFX1IyՍ @9 @t., 9 ^ pM;̀)(@ @ ρa[(1hsD`> w   `b }R I IP`` p@ yP , 0g5E P @ @ M@ yp  0٠, }0@ @,P" pQ* 0 Ep =Н`}@ @ ri ) f=w{`ZeO#88 @Q?g0'dY/2 Lp p ~D;~ [>E~\: 0C ɠvǡ% @40~iAJ6/0 ̀.w \L $,Y:'f㚤%:vc P φ {B~Ҁ u>96$%2 7̧o$ ` `6gS"P[Zw +P7Q"P Dp!2 @PJ `) 48C{$ R~ rx\L[p xQ Gl3;#j`&P y`}#SxRzX 3Z $J˙ p'  cBr :f否D',qP [WRЬKt S ʕY =D԰0 Q*6à _) ^b`!Z2 a{" 3 pQ͠7( *+ D i~aA~SWwAh; tQr #(xa&TLW =' j xʚJҀ\ YYsAqg  yj! ɰZ9":PH4jkǠQ $Q2~ j˺K'p0] 2|8vaS9r=4-M!Ar|VX ff)1{USTa q!tv"qȰI !41^Ǝ !ɹKɋl ɯ><|LL|ʎruʰlڔ<~|˞˄˴|ɉl/ȩ̗|!̳,ζ ȁ,ZrȬƪ˝|θlͨLl|;B=DA]HB}JN-LR=|T}XVc!:F!՞! K]M(j&df?H}!B7G"6q7Z";v]xB{-E578}D% z|\1~87Ԗ=Ԙ٥ڢO\דږB/a 3 p˅]X0>PI ` nEMemc/6 !@4`5,o$N@yE9(6@ Sq$yL'Q i+ ,{_c-[JAJ 0\ % Xj S@@PQw@Ҩ p %]lHGW F(*AdriA/%  $ ֧}= #X@޾SHTL#FͱP I#&0o +j  >[(IKb pE/}cAvp $z0 p  9vG_k&@-=  [xH?F*W\3x \r|Ԛ%'](&GRܐAJ-&A?fgsBN E >Oz&EK&AN(uM94)WLR+UT@WtMҭK$ GNjU@RM"o @_Ld^P{Ո %6QX5oL}K0@#UV4wW!*n ހ4P`  4&HV7.hc? XURMT9w%<%T nutGDNiJ Sx<NƜQ=%K8i2289LHIRp͵$1W&A{rh>AwԴiZY[o$QXaYtDqttBǁo#EDX$h,>{=NgQ&6E=T+SClFɠ%rfuXlWLaF+%7QY_y) 'YYQ(ol3E0;GGOfqF$T]ɚYԲ"ݑ%?O΄ǗczēB)\+x-nzq8<`Т3??]Ϲj&@R׽xLox$!tC#pr03<]IP[^#bɦĖ\LGhˊavqco}_ X%#E.ї2 WT*F*&౹ +X`,^2Ed D$! ]j#F o`RL3%7T%!H;D"kY#x *2``3zppE94L!@nt#+~EN E;,`PPF3z@mن`e ((;%L@p.>4H0Q iBPd XD^"t462`r}83́aC/La]ԩ! Y0A " ] @\eANp3akX" npm@ ȒЉ&]#٠d9͔:E3#"}׸D6v"`4x>"2 Q q`T0G;i#\ ! [4]א/nqaH 2j)/!ZC ] lL[)1epe6pQ `@9lqfUaS_CTG9ssWF=Go|ÛpFmOq#P]A=~ FmZkW ꪁQ8F3Raܐ'\kшF6ьІ#O9aS`xuz x.Aʉ%a]k`# dB-H3 bc+F6] oC@AQc6 d/aTXC T8| f(LZ"߈0)tL~2: )W1aCV '#Ƶ-8dޠi) w4hƔ oyLd,d67#!RYq3` 8F Gxp;2o a7x-Ƌc,cƽYc8C>Gd] +J,1gNf8_F㠳7\9&RF|&+g܌A[9 eiJ_l5XF3JU[ʔE29`u3 g$ 6 iฑu cƹ4q v3EӔ q㉂z%_n;;4784y:\{.EM,oH95Qw!gyêTRI-#$;GѨrmrg&?p/[C,Un:acF跕i41/cxYzcLa`}(;vPc+mEw7d!~/  4œƛcK3$qK.`ؼg<3 _8 <@ !ljy uAKIlB ` ti;2C:f d4ninYhbx%$@!$@3i`1`zA t, ±K"f8BK%T30{Zhv(+;fB 1 01$CTCW|EX4C6d 6 79K.430BD>oȆαnc0;hŽC22h<")rȆnzn;'qUdEӋEzG{t64[:\ԕo L.a\)bD+9lHƨbƲxgiJEmDnĺ{jy$/dv /3a2GWE7,KA\;`X:S&YvH sR). ˰\xiP˵+bj(*p8ˬT sX8Y0r`:iJ<ôŬN$ I_0@ s1 H((d hP%O' .ۓMȍ"3 X6D({01l" QthIh@: #2"sXP{P@Q xxp,$AKPYPDҚNcУuiPY@Æpp6PYBq1ѹdAjdlASKT8ӛ ] =. TŨ ($6vP^`lpTH ICL}Vh]h<=2OP1UWݘ@PGpz`+ُ┤p/kh.VV1mȆTxq-WE/C>(nH?ު(33e]fH;.I"fL>dgzdfVc9 wfk>lfn^ n⼼=qKgF#_ik adcgNL|Nc0s8`pahXl+ \p i>>r&rwN(]BfbF㐅wbNjXfp8C;^OVS[&[& RwPh(h('e?r0fgXdj}X{OHfbfiNNo4wFa qp{?좎gFjm돦pO>46ϲlw.Z ȞlɲYl͆mJmz&mMlk.lnAnw`Z͖l?lwl6?jXOXNoVo^olflF(lu~8nBV 𝖆O WX݊fl lwkNu rXo&owx=wmF?lq"m$ܐp)_CJprB 4FB(.n; Wn6la  ?.=`|pe~o?&l7|4xu7rNϯ* WN O \5r@ilf>HqwMB!Gt!i{@nw^4 -uwtNv t?QHPY[˸i ?!wX'Z@8k uOшknVo>wxH@;Ȇbf&ntv Nq.HwJ_w{_oV}O pu&e_RxuxپBHq b;y M`pWuN{Xpw7__a{s>r_YlAnt|npnU? wA(oXs({_ݶq?(>WҗO\r.y`oV VeI|gC_H&|h\㟀 R,Ȁ P4ަPZ.h|kYx0XATo*,bʃWSХWP * +&X YEkF,i$ʔ*Wl%̘2gg$p̑N'ps(˟5k,p ';_pcg^yk dРS [asz=w7w,2e^I1Ȓ'S&I|Awy9_E :4jɛM=N~|Mj9[Z v`c{"uE upkgr;vL׳of̹kKiΡG RD,TUVlo No808=c9#uέsE7usN;HC0czx#9N8|#3\ :|3TzQ$QCL43!Yj%Z3!0UM50ife80pnwc3.4]#rt5sSD:hX:=Cv3pw9a0yLb=}NkջdELSTkt^40X E-#*=<לtbIedHR:Q@G5" G氇AEyVB^d8sT0HrbqIT"]fѶ)y'aUEUu_\8:Uul8ce,_i(FD#Z \b?)RъkL.~buFtqs̑ϰ&=Ϗ⼆ A1<"GB#DSWL͙RP)5Jt,GK[VO3$ IH'1vVxG9O,f HD $!; )@" @F4@qkAi y xi;Qp_d! uEndc@E17fTQ& !2숆:sU3f@tN5 k{,!uH@J ڎiֈ4bێ$I;ZWءV Ϩ H0I0)h!`c% \1eF^CFK颤!YH"Q8pqЀTQ uwYO[1E3e0)Nʡr␆7WJTE6@a 7ԁC$ 'kB@"Sֲ7ԡs%;>w׻/BLي$9>7u 4\\$`<$Sb$uq~=bT hF2zhsJ% x 0FOcGC )qh H@e98tǠķOiy=2UJ$r?^6,4tW:a;柜!(0EI,畀WJW<:d"HB7V)DL>@C;OD TUbC#hi /ȂP:8BơR).yl6@̂-|jRik)i\=-j0*, *"1lj< 0\ 10*W$gFEdwq7x54R[;leY) VSH6D1C\KCfCCLn 5,$5Z<6$:j}X`.|.ą9|:.C䅂QC}:- ,-$.h,Y4ÇCn=C}9ҧ5x<@9E0&~ dH1B4,:!!MD5xC4MrQL嘅hCX2EEQzT[E|Y8h;δL2K(%!ZeO>)O{5L-TmI\mֆvmؒmۜm8m3>Y Nʜ'eݪcNK:>JFrP.N骇J.P.IX2I`tآFc, 9zC5Bb3B;@Yz˔JȐ蔉į/Y$C3$#N@E8dnD/O{7MbϦgILiT^oo}!e/6 XW/ oVo@Ma?p+0p8D4mbTӫx:z0 Y{ CeҎ78饱K1jpG}t\(b1Dh4_eC/@FQ81Oz-/1jE@`Q7p#?3$K0LP<$܇m5GE6;ZC83L*aIDtL$<8/=K,3Q37I t8| BG`TL,E.BNSX C'nZEo/:C:$:Jkʬ| I-C9 X \B1,00 :plï7(JC̯<Bm0At TCe .L3t@uV2B;1`v$4V:|C.*38ZGlu P 04 49B4,`1lTu.EHk>,,alv,WC,1Z1ÐE_D+58!ҢT 5BbC=M95A(:d&$;`t 1!^,1-8r\f9-C/xc$6/|:rBv.:oeSeMfovc  UVOdBYyxVP2$C;.uNt7Pqq';0C}07687O s} uCuE4oRn/- 9x;v/(4|׷=puf#vWVʂ9$яv_C(8S"%1C6W:C6XbdG'>p 7;qO'0{R «c;H:I@,x] ,(PyiYtIɅwϦ WMRo0H,;Kbw$`DU5Fj+URA@nt<F t$Y$Wu$Vs‰&_J(H_V4YY"p "xvW d!oµ=\x6m3u={f a~(("AY1(w 5!Sh|K]ܷq-4p Kj:WAnw X ^P$E-X~& (9Qh"bWp# wev-Gj,bfϘqpb42>$Jif +OTLwQ췊J;D ;VPqv&̮@^:FGXɆ5`Ђ g9$tze p hڻX P@As;q D;Yb ."qfy X![&h`X_y bh%"*-fTx~wyƕ=J+{iə@y'X`/ Ncʿ la[-2EY23t_z H  1I C=ZeV  @jg5pkX["*=oD p jnq Q$ѝHk) AkCܱ^@A$A՘E^ t9YO8100-f1| 5̛25Ox׳|5ZX Ja2 J!3bTXCf!  %(DK TpDZ(0)f|y=QJ sl3u*aI!M-~.x,000!F<*"TaibnH@u BBEF%qO k|hz~BU;!  1!)9I+[ "_D`rCJVt(JP)tZp-Vȡ 'e8x鍩.w6[,ȢSsӦbDfcJnzSϰEՎZt&n:Qv!ΑEe Pt D2Rc3@Yh$d|1u6(HKy@Xfʗ&~,  D[|!0ڒJJ#(XZEXU߁ ^LB| >X[)ָuGU!an[!^x,AhHCQupkvа; k؈4DaAd֕Lg"ܙk58!(.~z1sH;p uHLXh!H4ѐ:jB9q \x8n8`,nJɸb5Рui #̀F-Q 1Y`t;fQhHΖ"af1 -9ֱ_ G.F:u#U^p8΄ȢmJNf`eÛ6)ro-l`|HG塎rŨE-b$uF; oDC$4$fÜ2N,'L mӎt/l|g eFL¶čm&E:! N:R J[Nn2jF3L}vƬ i92qEx3"HZH> d00Ϭ* %_MX9nrD3H isx H tΛj:8Q odcm 0^l`ЦkT ⨲z*@?0v2P `0OTkc3?֐4~de!STNwfv'lS>cd-@l4ԘAa>j80e"eҍ|Mdp:&L! AX`dpQ;h>Ḩ: ;`|>a|*3a>#MB"CLJġږaQGn'hrHhA|:X '6GAAnA(ns6CۢQrAY?#8lEpm r{ҀQi! Q1aj g Ҋ2N&11;q\!a1K&"epb W !,!""7"ds$)/z$ErH$ %A%%%jQ&&'!0AH4ro)׼~,@dU4P'Hd- ҁ)L2a8OSAqQ&| ^xa è֊!ho.ĦK>A^/vda<qA7)C?CSSDGD-/!63" 'Nts~&S>oDs3-7 ;fAPpaA3C!=Փ=3Q>3?lm@@T-/A+j,C@CP DQi2>!B=^6L$>$,U/?ARA*>2yUOxf(AR  `Tf 3xA [4;  [;Dc>R5PgQMPO(A@ˢe,OQ54Q?Q_Q##"Rm'4U1D@6hDJ$?_H@RuU[^b*:VV(v+|Ab%XW@UY- ZZa[[\ŵG$uF!]=]1h0u^^^_v___S>*Fi8-q\ FS;a`/Rr26:SaSSEJ :A 8%>W Wz!~̡tDpVrplF("rcru=uoW>a p,k7_VyylSaWF@0m!N(:LiHa ERwz7p}A}-bRq!Y._*rU s7wWEM.Vt"u)6,-|aWwzc""d`dVa0$Az6x-LPl y_ygQ)G&E8jV2lbbC d%u!bJv"0"P#`)F LDwZ+f+6W@!}&R Y+$a" !0z$d" G" @ 0R.`yD7KV"(‡%~?a7zbA-AÁ8nZyb %E>!_y1(fFԘ{a*n؎bOawY\?|OWJVaO?9Gٔ%VvR!6!._aGK@pY zfPvo#MWExGRS^ "aw6Yd!:@ָDz>waYJhdu &VZ/za$FcdHepe2 ?C:9kLQzoZeDZjETƧ߄AbϙEzW3G:I` Ek GZl9ecB*S%4bR Sy䴻y5lWiK L;/8r?u25ADxǛ|7SUzF$/XCX1`9u\u%"gT5"aWk"$UzU@6 ..ڊ"Zfl-Iؠk`Wfࡼ;{dۤ(bX6AF鷽b>* zIfe'3yO4& br@ {s$D`w !\AΑeF|:#"w D~x`@d;!>P2`@2}@|@@fY. )<n3r!ΥbaXDA$Jjo wJx'@ `᫏˿=lOTxz6ݶۡ5aǤ&Le@Yo\ҏ,ҁԢ^3(I6!V+ {)8aȡ,!LN o\ZC`J<.EQM.M\xيga5|ԕě6CpOJ!6'>z҇2!2oO{2udF-u!ecCz7WҤTwF!>daDPA1GDUơ>߶GoAIjl!l]eB uAd!az2>6G޾vfqLq~A2^A3ئ@d*Egl/l٪%04vЅ m4i:;wNő$K<2ʕ,[|yLAzv_1c+C :4(Is;ص~ZzZꈆ'n8^sy5_Ҳ윳eٰ l.ϸ@.3-f8g휅v8Vcidđ#(ѤK>zL6qPFS:Sj^uk%kZnK3z X0aÈ.n8!-cμ瑡S?~jJ˖-.*9G͆Qb=u2Q]So?ǕWƍuQYS)'so1#:b}Ei:0P]aAO,L;˄'d0yh Idg~mF`Iׂ :p>܅-a[v!y9 &" b80H8X^CEzgdj53(c,S9II)5 E>Ve})U;NB`=D,ʤ}5cmN< 3L(< IhҦLH SIzS] J 0pY7Ԅ]* @ z52@Lon6`H{x;cANqƤU+ (Q 8B9RxͥqzRZb;2H 818ML 4;:N_+K1]qb1(+$d!OFj[Br>@TSa~fI aF@X"` { oxc-b4ʸXB]mЂm 1C  kʃNs_ _p,ҐT_Fx>&=qD)bkc/@&J kXJSlHk%QSU-m@spKܝ xEю~.w} M8|Ѐ2IH¼F4Lzw˧$Deo`f! (\CCf8$ w:hn!; @ aIx**viG21a8cf 9.2@;JAJ U4*eu")W6. H‡$Lޕ Ȇْ-@Ȣv[!a œ%d"m81 ybtAh`c WR`@g!&]Kg)b$_E.AwZSDx8q%Ł⊿OΒVÄ7|4o2 H(cD/я+PZ(TʯVZw}/!]\i?IņxwȀ rՒ (7HJ(hȁ؁!( 8'-肥Qx3HY X9=胅2Cڐ"QdsȞ Yș Šm M\2bq(UC pn` $;=G=P ` CQ"C3 8$^( /#0"@ Pc0 *@  " D # 6&n{L)`S?|˹0e9 4r9ΐ sVk;Cj# *D{0nDzy9|- 0{ Lϋ6L˹ػ<óe%"p𐽛C;zeyS` y[ ȓ-~ P$ hR@ 'n42$ SHWJ DY%PFAT`Ch#<%Ò}  u|O)"  JCMCۦÒ`BVN,CL@g#0Cya/<,íН L܎o-M܌Ο@DHW Mzi3=7myz}|m|˶=ȉC ?љ ) ps&\wX0 %2X-o RK~k O "ږۺ$p40 EKܼϐzUD4p !I)+\eAj YKĹ/K;CO W@)0#A=m<▘x8;Cc 3* Ou20P,MY\f*Ɋ\Opw.nֆuv9 xH ? [ #CgP 0  P0 a p " (*ܳ,6 ۈ P 9 @6{ 4P Kڲ? !C x Ԁ t E p= 16 ߩ  ` 8d\f}h= :N갏"t: KL*Bް Ki]qk Xlh;,b]˵[Y$ TB~ysS~ gf8&fgfeΦV#NAmgcEI?0D49DYI0ONyh;l&ϡy ];&ӥOOvGhpX$CdI<8wIAyGy.Q<5i]y[=ws$q9N( q8)p! $^qӐ}> wS'P {O*c7u$s,5Yt`ӈG\#G&XAa`B8E*kc X?A9GBD = &xx$jP18I=QH5w<uA3*Ґb MɏwVirR@HiD$87ϐ*iGqDOejI&w|Oo&. sJ{ VREp(O Qtjdp+s |Q^WEկXZբ; 8V"^\h5l{YD㐆n{zb kGImRklRr;`*75/zný-|k$,`w}M\J0C4AkXY*daR!p34aQgAbXXL8Tb82*X=r 6QLOKC(Y?p9rT`kGKt" ] f4 f#,툌4r,t:V]v1?FR)T892Ō2hn5ּ8*rM;9Au4 mD+dэMC:B4XJ6qp:0IMn:'JE5͗H׺ f0!!A!f : ȅBLa1䀜eQ &D($M!7aXcࠜ8ʣX#pھ$# H8a~l Aq/%߸<$d(9Qʕ|p97Ac+(A%Y:ѧat{hogPVou+| ơF@DUFl4 A-#6XBsXzx>@ 2wX(ƛ A\ B<o ; Xq7xH ,pc# ?Hxt=ٛAbF+ &hPIBaNߚP` oi(`أ : Ap8H<9,Kc(!I(Tb :\H wu0.E$TBi=kQBB=YF=.|/̆0)ejlI:mrjh:;ipBTL@n@`p FsxF =#wII P`D\&|fhfhb8fnkv+ Ѕh`9t\ 4\:.;dH(,%C8Hc T2`QtpO;#o& j$;0Z.Q}sђQWZ !-.AR%9JU#БnHf0qR/]UI¦1e hs`SxӾ,MXɓW<Sl.cAEI(w`9F}ÇW*uud@U^ubo( 9_<KBFZH{ j:Nc ^86^Ua ؅!qoh1 o@ضpn88v|4mmTnWr=s]t]v xEy}Uy|, qX`<#5 cpbp oؐXtEͱ8;EY6qRŅsII5QaX]_PrHwHfkj5/ :S` /j;lx6 EN˱s3fr`uf0i@ipG޸oЅexyڛ3'WBAA+ 3+FF*N>,Rg8f. @pkSIxjuh@ƄȆvaxm <glH"8SYH8@0Qܢkѝ颽>v`oV6y6nbiox%!ƒXx&ߐ@F8C̑ˉy8u(Ȯ(lأxӉ5!quy_q_ q#]N۱ݡ wZ A E8y$ :j٨Oc;K³]v;Չ!4asF-K$SeԦ9UOqS1F;p eNǀ-Q op11Y#*`qUiuSBK-$¼ ZɡVV'nc _8,SN#7tSQjbX<:Hx(~; irlbQ9vrϘAav եM'G:H"&v|umPq\:VtgCj H ."2 /}gr_z V6p CGt6"@x&!i#4䒁gi/~fVӲ! z:bV͹ŵ|1 E ; м`Č-;t!F`v"S-&Rs68F"pG/_g[s'e YH؃,fqr_4nhv3_q9J2H4]Cl#4QFqMwNȳ/Qb@fv8Bju~(Wk\CK VXM`hG-aƮABp1@pl1+xы{Q'`C -P("sTG ~tA(7 ϐpudi9^H oV7]KPƠVJ aF/UR}s.L<@Р$,@'* B"`џt=EO uhD1%@@ D! E}! P4QX`DbC['yM&jLc@=`c5zQd>}IhFE,! @jp0x1(>@sA B  T,,C1C'H^},B8,@5";|u @ $B)4@רGx"0͚)aG) y@X ׬ `! tZA;IB D ` X5 B^ (eL|;4 4t9 6X 6;dTz Hy(tM _ 4""$4\A@š9 <@ P^< q4 IsLK48+0čX>7<N3(@^/;^! &zqJ(Zb?vEobC0F<$C$4,CU=- Q`C =j NX55!X1p 4.`hq9dEI4c+dA BF!=?)fɳܔD@ Xe X B,`YUZ$-gX/X$lGr\(0@A A\^vј14C-M17&f [1@ a@@TAs) RX&Jpߐ1S&TbT>Ufa `ALaz e;5itN CD ۭDڡa KrV3$CTjt@ܤa 5Gpc<`ftBh iGd&>?lgGB/ē:B12AYC;=R.Xh-0vC%DC2P:baG^99C8P8d7C1 EFCK1XQ-Cf8waf(gk6!%LecD:Ea9`g(l!((Ce !O9:ފ܇"ϨJ8C C8ª< ChUU.;0@I6Hü fb畒b 3g 7O:aY*Xsm(b97J2t̤>n#- N8ZCnԳF#-5w[ym=%:γ?7R@@DAwATB? 6B8HtZU6SB802ūkN,9_C2H5C:$Wrѝ67LÄL;MDNNFPQQ'3hH/`5$Nчɷ4ă Zx¼p 1YR3}TkHHKÈW=x (=@U?UAB7M\=k=;ׇ=@V铊ZWVtka1hP I>\Ç; >xH)G.\Ҽo1$ooxA3g]$V-n[As詀_-YEjh {$Q 1eaIp |`X#hYOdo)ϠE,3vqG+|{>V8 b1HDOJX7 Gg;&b @Vplw kiCڐQk Q$qb'8!ʹOQ84Nvhƶiзyb η6e8n{E Uy9zx]HS=JD Ox6[ʑ^!Y'1wr̞ /vĩ e!D`PUW^}䖹$@ wAڲKl,!of+Q`"-wZ@^90$L4)Oh$Nx$;3yr̝[9GyF3tDm5AAsf3P@5u9ᨦ\}gCDzdWjkx^JGZ´pD@eđC i{)U6]{\)0[hji@V!Js&gLÏl2e^wp'kS(,I:-k AT@ܱ/tD*8x܁qlKeTfIbv-wguJչuJZGa֬fiӠ&5L'Wk6Qǁіv6m7dByC}cp˟'g"~\K.Ar8ȵvx.0""Z!-\W0*H/Ew/` 8cŊCyћAl|k;' -NF> ro'H(F4x1_To uƜ˰irJiJhM@񎒙} PL|P(` 'T3=Qe[U:zV 0Fa[ !wvr ށ8sqO bJ,c [!<Qa&f@,&,{Ì"z=Q А$'2@F]r# YQ hD m,Ѐl"Z|d8UU `ZzV]HcF,AcLv:Ab'h!lYp>燛WoGOk\Y,Z1 Z,}609A\@cE; a 9LҹVO-`` ox1tutN=9QcpM$¤GTn;y6Qbp{cNj0MְS4O ox#0N+LJBDyT2< 0zK`N@9`UZKH(J3QTǻk4y#4ÜXF81j0: Ӈ pAf`PC(7\iL4ڦ0Aub$ JȇȧmG(CZ/^b̚/OA4|/L O\QO&.4<@DPO\o0`J0jp`z*f\$Ttoɬ`oo'M"o'/Ӄg!$ p9((Pݜ3p%E>0Ccš/a(-z!p|aD/)"=aLa"t'/aPo؁hoOxIJO2o@!r6F|ܨ)1Lf!vd*0O§afavn,0p z¯bЁB`! Aao)EaQ'@DFaځxdc"iqluL1Q!P` nB&Aۣ}qlLܡڡQo*vd ϲf !O"6,ۣwb3;E@dSacC%%%#&g&)0'a'ɡ''2kM*ќ\ppƁ 'hƐxڅDңơCa0Rt!`!AN'  kM'Ճ̉* !HD~)n! jna|M=!Cc|laEw*!wNLJ4Kt0BC(S9An:ڬP;zπ/HD^QB˒?sAA`TA{ǡBМ0TC9CDET=HN4EWE3G& T1| ItԃJ{bK5ZKS9>k9 aNԞ# t*I)E<<ܡɶRSѡ/X㙠t'a3*f(n u@C!ӜӚ3(I1 ^<#\a, zp&RH$0b`!CP`y/FT TZvj44#fS$\ŕe\s]f86^W^Bz%M_["/D`j(Baoc$bc"cAc14dodCMP{Gl]Ega% b/ BwFOg}gDk`PeyivRs*jjj;Qbzc#k|>~!Ufgׂ:a?>L Ȫڡc8X\JFR<[!pAQ> !` Aʍ!̩S̜|!^A~^lŸf!^a(H]䊡T'j|!+&X!sJwxZZǡ{W`#@!>!pa7 ~a"y|7 a}Hd}cJa8G܁ WطBAbe0-XXH>h!BCKbaex+v-n zap^A nڮAu!鮡pTY8 S/Ojf:$Tx6a7C:> !Jڡ @*r i2Wnvt<.@\At WAwŞAWl{( vEAWvZ ٩ @qj幯e%B|cjMC:7a-j!.& dda$ [4AC\t_ #%eRD WMv 'Myz fA! J"b!W %K_+p t;ca$Z@ 0aӀj ܁c'Li@gPF7(ڨ ;H9`uE-:(+Z% o#%f65`B E{@0FE q `c96OiAu# `b@ v`MY,Sab; Vih9 "!H7\3reEZM^e!jFb kÓjFf&`"_$6Atlf̡Ҝ=̡@Iw`V^8@ b+f ѭZKa&A C{}C1|*'iYZBi*" RQtV݁FE @ `u5ܴ}g=|L!8gA_Zt1[=ּ^p&x {8~k̈9Ae уO͚5/P ADԮ!Ѱ&`(W)BQ # *>rͩ6vXaڝFcr`,qАg.Bf4kӚ \8Ԩ.SV TgyY֟r^8 !3, '1 H*\x0/iJHŋ3fv-[5 CyїqH\ɲH]ʜIs :|j8gJTHTӧPJJիXu".K*ʪ o۷yR(;uLpBp +^uEw2L˘3k̹ϠMztӨ.끫I:iڸ=ݾ_.8cƓ+_μУKNسkνËOӫ_Ͼ˟OϿ(hoC 6Lcu*ȠVL2d >Th!r!u@3d8t%"+F7x#8܌5ޘ@6iH&L69q@֔}38X֖4\v)dihlp)tixg+|AԴ 0N$ 4&S9Dz49s1ƜS10L3ihWj14駡"}J^ Wkj ,Y+VrlX-ˬU>KUVkfv+ڊc:*>" >Ф;\yUfZ5-.{ -- "̒¶1|,= 3%foQc4rO#KmװlK/-Vsi7B;,4-3d>'?BP#xXg\w`-dmhk V-Q9@I)HtuH9f$~'Kn'7G.WngPVNAHcn䕀z6C^:8ߴ:Ҙ#y%=l);[~k87>Ӷ/Ohcfs_d?o觯ۂ;XP1ނ-4AQ `"qmcCs8_C2 *-9vj{Ncȍi 0T"#, %B.ͅȍ lnCZ4Md=a$D LH6P*qdAĦQT9,&7, )BrD$pAaTG IBL"F:򑐌$'IJZ̤&7Nz (GIRL*WV򕰌,gIZ̥.w^ 0Ib"_ؔ 6f~͙^fפ5jn͚̦6nz '}nqC9{L΍@A9x>~ @JЂMBІ:R@!vK o! im4ai|lHER^t!IMzec`Z:vcv@ jPA(f07FNwJ՘T m.2mL"UsoyVcծwK8dԶ!0+PACn 4!`, Pq H*\ȰÇ#JHŋ3jȱǏ CIɓ(S"Rjسk7 m0jӫY=!@*0V`yh& 6F(Vhfv ($h(,0(4h8<@)DiH&L6PF)TViXf\v`)dihlp)tix|矀*蠄j衈&袌6裐F*餔Vj饘f馜v駠*ꨤjꩨꪬ꫰*무j뭸뮼+k&6F+Vkfv+z2N2.0#4d39c3(53L <89g "/\5$L8#/cN8k,[{4!\2B',,dN3V>43"$sP6/4`J?ô$"5`-{bsnV9 "c( 'H.3pxWN0{{7nxA B ;~ mT}b< x&މ'Nb 2Ǡ^7'ߔ끧 )Hr' CG~7$ΗPBX0x83w|֣G,>b:! 1~Gc<9A ""P'ЍqUۗ'Wip N ~0E Hhbd+T H-m B"MX;%"l OPъ,̢M‡ph@&@\rTD*<r dRዘ%1G;BW!H|@^3$"7 ye% Mo$'WI_ÕlH_і-^nd #}I̙@Nd19Ќf4IMH|f5nz 8IrL:v~ @JЂMBІ:D'JъZͨF7юz HGJҒ(MJWҖ0LgJӚ8ͩNwӞ@ PJԢHMRԦ:PTJժZXͪVծz` XJֲhMZֶp\J׺xͫ^׾ `+6 lhk|h!X" `Hd# pҚmaXj &-`,eۀ H{ZӦM5iBclxP]Sr{hAp||aGqûՂ P+ y` v : E0g6|aAP5pg|AT:lcBs B]΂! yPv԰9 uڠe,[55_0C\8m:ZnmnԢ[mBw9ٞ4\@z:; g8>1 jx3Nk `5|!qTC]hF8qc95`Pm7g$ߐ9/C!wF3Q tnЋ~oLw:!u[ZR$1uT# 9*a$C]ME$"f0c8AlCq뎏}|wG3?>]: . iK&sӘ4navLdߒ$jC82񋟳Ѱ}1!XB=ZTΒ%I³ t0D\v@xM u #~W4dVF0 `{h0 ygQ`xLH%0 @y4 P87' @ "(\BH`\2 f`Y@LX \`|LH8Gxn؄su%Od,0Ȅ@~0~C GL8f^iFx8 _h` p .0  0  K(wh  t܀ 0 Kx% G2r24ဍ&!), Oq H*\ȰÇ#JHŋ3jȱǏ CIɓ(S"dR*cʜI͛8sɳϟ@)6i钠 |G*]ʴӧPJJ,uĪׯ`ÊKٳ %!۷pʝK.RTAzTƑRv LÈ @J˘3kgBTBT*S^ͺkb}6׸sͻ٬dʷȓ+ \8ˣKNzϡ[ν2g;#Ğ]o.PvϿ(h& 6F(Vhfv ($h(,0(4h8<@)DiH&L6PF)TViXf\v`)dihlp)tix|g|M6SL1Ҩ3N6,)i:s:hA3xJ,#P '&ĪG)Ԫk d*:/RmÎA(iJbjBP-nXX`> >\S+%.<M/2 ;̜ >ث:L3,00,#5L3 T3$F6pW|q!,TC7x5`3ʜ8d73>|s;lA]I3RL -8 >L80D >Ì2m[||{ue; f6n3]y_Us0Ċ7M53S7L4q8 4̈JY}:@Cç_ꭿ;+M7H#,-2SҜ;82~K۾-_4G#Rꈣ;/L2@9hțO2&dq'O1` TA$ !n<AQbPH6B3G<5ְ ,l 4n,|`7q&G1fdoF,`$~G:29< (^X8F3ڱ0x[—fN:HH<ʍ*Hbh#fHg)4bl1Zhm]2*5[$l:0I˱:yvc|p82x9TY_@cpGjI͌DH.:|dc4X֙q/!l,`;f3YD h@1D(:Q k ᐅAbE@"@u?fI m Isld;ٻyggv @wQqߐ.^n091 k P@/q `TR(q"S4iHEDI#R" 5%vc(gO_N|s؞;7{ړb}CPB@VVŞX| Lc0f)VoDXkDÜjei3sm]sԯ<` kXf V`3nsh:PNZ-gA #x-J$R-/d^3v< {#gm:fc'Q\{gEdQv/au-kbÞH5Q`:CSB3F3ΩLQ6_cU<@q):G c1=V\hbtK,*l\ 0e}a?uC)Z5j6dBDbsBp>%*D$)+_:_)A <1c щO+0 DzL Yֲ(&K4@Qlaun ጅ"T8^,$*@a@V 0ac4`Ga0S  Rln) I@" >. I;?Z!E%_\ȡa|@ ($@p? җz|OCI[qKD icA :A;G0|=?.b$ qtwܢF$ `_(2{ v"yC.a jxc2 'aEKŠ,dz'@@'XW> l{23 CP*b !_4G8A=c.CD U(;AJ;?!r{=!t8&8->.'~X J~?< $k;(NiD>yC +@ } pF` /@pPU`N ƠS3  `0j|6XfE& ;}0f' wv}y1& wmP(s  }gP# ( y 7F /`85y U%x) SPuE17! S D@,hIvmC^(i @  P'._L h~`(d0' yP s=0D@ aI Y P C0 @EFpNLp[p ,&6H 5hp mH 7Ґ~g) & z$gs7i8y 0 @?DHu \f {Tȍ޸|ЌFP  ]5莑rriFAxKiD”IAU8sV ;pu{ '& Qۣ TZ }ZTz@ {E F@ p&ϧrAgp8ʂ_)F]@ _Qp W` X 0 `هN@H~I I`o 0K|p /Cm p, RN1DP 1D, QWIs$ n ` @ c Mp))G gz NPC@H(V rkj Jc׉Р,fn$ ` `Z4M]}*dpcp`ZPcHӰ\^oNncWZWepV6_ Ya 0xb()L^pUPu  YeSLTL V ѤnLNFKХ ZDove'Q `06% qm*QEVWLN ` 'N U!V6*IJ[V^Rq~ ,QZN-zEKPwAzELHڬk 4pb4aOP=sZ5%7S4Gگ1ͧ 77U X: +7 m (p So EP<۳0Ib -{/Ck7;۳XZư jE{IL۴d%[hglk۶pKot[v{xz|۷~;[{۸;[{۹;[{ۺ;[{ۻ;[{țʻۼ;[{؛ڻ۽;[{蛾껾۾;[{ۿ<\| <\|h@z^F`_w@t~eg@`P\0n#l`j\sy0%lHYY 0yPg0|ef<<9> BLsrh[T9.WZ*Zp/mjb'dl^h0.i0WZl uL!~,ȃ&m#\r\p^`,P 0.@m`fʢLʥWD0]WPpWFP ˾ m nbyekZ^t `T\{ `t*_m"΍|~L|Uy&Sm_GD{uPМ x2u˜*= *l4&S\Fjpn@ j,g;g,j"rjn\ {`vq_ב| p-\hbS,gѝhXPͤ^]}&ш=k_؈ p]ٗٛg rV3PGP<#9^_r؝Z~\Rac%^NgiXmo^%ksu%y~n'!\,QO) H*\ȰÇ#JHŋ3jȱǏ CIɓrPʗ0cʜI͛8sɳI@XϣH*]ʴӧP&=r>Fjʵׯ`ÊJ!ֱhӪ]˶۷IlȰ ߿ 5J.AK;,;d0244Cs:` 8 -2܂;#:(̽ Xgu\3o&kMʵdM;-] Ŭt1MSOWkuׄ\ 03SN9ؽ8~3N8~/:SL;=W-p : $.80<~9#:h:ւ;M4,YֲN{<" & xutP$8H{p|\,=IwLkI&n a5:IDWB# !C#%¬% a0Y,b’e2'yxc =jڃ%uHbY^1E v˝&;={3")k2G g*ъGREE ";h%~T ቡ&KM-{K,Gz3FPNy>a*RE=1CU+RSB1o% HHQc59 vE|ч VpW(X` Ec k h,6@G(v ~%Xc)cm-s]`o26Y$=dfeָ;5 k!mkK,)6d%ms}7㾬Xpk*wn`,-/L(0@= osY» /r3v 2 `8p1_㾀(P7XC51WR4kX0va9w_*6al/f 5qڡq9`]*[X@,ҎM Gǜqdc.AlTCO.ڔL:cnUl+ޘEQr,^sh,ѐȣ#MiLҘδ7N{ӠGMRԨNWVհgMZָεw^MbNf;ЎMj[ζn{MrNvMzη~NO;'N[ϸ7{ GN(OW0gN; m`ڀ4 B ?\ L`|!k p[ 6usA XP>>`=l!+(ҏ, h@@W=89έ@8@@$lgqTa|:mc]0@ + B7$?yVǹ` \ qP<۝ﭟ6h"`*~}N|ɗ}sC@XX`tk_ݷ~:ׂhB}Q}W1y^h0{DpF=@+ `EyWv Yp b@" 8{ CB'0Wy@ {S!y|w.kn0 `X|/,nA`X__?][^\0F"uPJ(b_h{[q8r_`My[lw؆, ntW~mju=^x_(\pn8爏y0 u;h{Z[ " 7rKd"bc z8ՠbp0 P1 p/뤌_!,, HP9_zI6f]+H_8 :lLbłk4lLN80Ȓ'SN[ҠXFfpH_>*I)$}ϐR0a"ԪIګ,SɅX"S/hࢥݼ"Rtjw5=yu[u ^` {wj,J1`8v879svjw\v4} 48qfʺuDb-{y8抝K37m:W;esډ Xd̘>~oG9㌳KcN;ܗ_E: 9'!3!*,}M8qgnC_#B\; "TСǏrUn޸qfraÅ׮Ifņ&QdeI5kհ2="fH.˨zz\WuըZr2]5m0`ղ ,.jٺ+W˘󥖚7oJh` {k4@ 2لO*Gͼg{oIy\bUc->q^K'-\T/8Hd/t.l;D:s݁2k1gzsϧ$l;%}/5~9&H!/,K H*\ȰÇ#JHŋ3jȱǏ CI"k0ɲ˗0cʜI͛8s,`IѣH*]ʴӇMz jիXjʵWT\ٳhӪ]˶mAB krKݻxX@ lTqÈ+^8'+H~RƘ3k̹R QD R {^ͺOSfE;u˰sͻwGڬdʷȓ.8mУKԳk*λOKͫ_Ͼ}DcwOϿ(h& 6F(Vhfv ($h(,0(4h8<@)DiH&L6PF)TViXf\v`)dihlp)tix|矀*蠄j衈&袌6裐F*餔Vj饘f馜v駠*ꨤjꩨꪬ꫰*무j뭸뮼f#9.9l .N,+mDd,xC7<:34 >L+5Hb¼+$ 3̘cιV.+,K00;|M 7W3{q˱7,m;N5`0Xs5*Or8,s4یsξ(HB9# ΂t xr7 IBL"F:򑐌$'IJZ̤&7Nz (GIRL*WV򕰌,gIZ̥.w^ 04!^>`# _ja gXP|| \Hܐ. jX9 c"S\扏y `y(0A f9N/d΀4 4BrA  +hA X6 @P1ԡ^= ,TGS'MJaɌn+pX [8XP mІ6?O\S^x4 U8#i]k[3nhh- ^؃4orې.\`@BPs_`B`-7 ap~ |k qpe'|pn[Pe,>p5!&E1` /oBR5 ]|!HNCYT^镳d : f\ rn~2(jp\Ǒ2}p8 gψ3y3!., Ǎ'.>| $YZJ8qa Ylج0`/7bT8 x HeT%×1kes&>s[ܩZ6i>~dƌbJ+56}U*Ux2eM޶v΁G%E> =vm[=+֮4͘Y\kZuwY3ehs,aĊzGjئY>,I`9{ZtaҊ-٣5nܺƌW{wa vGhʘM.j |]sХS? ۉ搖̚{͵/}ϯ{GQv߁)xv 8Q@!-,}WAs %0 !0, Kq H*\ȰÇ#JHŋ3jȱǏ CIɓ(S&0*]ʴӧPJJ*F4Ԫׯ`ÊKٳj2)ڷpʝK],v˷߿ LH?r/ǐ#KL"E$桸F ,,Mpdb0M۸GRYz 2N ٵ5!NeKQa2NeB &ROK'B2~h + ؠ|F(Vhfv ($h(,0(4h8<@)DiH&L6PF)TViXf\v`)dihlp)tix|矀*蠄j衈&袌6裐F*餔Vj饘f馜v駠*ꨤjꩨꪬ꫰*무j뭸뮼+k&6F+Vkfv+k覫+k/\3 3L( νەL20K83N;cpTL3k/Ŭ:t,sY%_c4+1,4Xk:M5Ҩ#8CW3N8 M/M?rS[mTt(*D 4rsNUmB |2AG{7+u1m 50*NTzO✓y wy]Nh~$C1r/쮼N{ç,z'6.Hƿ}Cl)2f*"Jd!o~/)Rъh2F66hά_[bӸ6:\TGBxF:򑐌$'IJZ̤&7Nz (GIRL*WV򕰌,gIZ̥.w^ 0IbL2f:Ќ4IjZ̦6nz 8IrL:v~ @JЂMBІ:D'JъZͨF7юz HGJҒ(MJWҖ0-N6h@@`~0 A>lp m8Tzi5iN͠,(Bmv4 ^*UjU6tSi V y A 8ռRj\S64ՂV8L,ΐөT F0@` ^,RІ8 B\W՞hpm 0@p[?ַ] p[U 9a!,Aju[NbwsޚjAFUYX޶ש%|˄< ^@l!D`.!yp02 F !=@@@@ `ݰ6a '.sBذC !jC d!_Ñ1աh) l>㧢 rȀ* m 6 6 .XrCx`3a >p pSGҒ.,o,P5] & h !@C2P(c:;s(3nׯW;A d\NӘ5X3B$_Ԁa~Q֠7A}%0;iO1#0rL\70]o[:scX1]c--Ebd> i~t1ĵnhG;wuCPGZޥQ49b!;o  %Id jDEҷ2C14f["h0rGw0j1vo׆7Q \xC (܁OϨ/W$J @~:;@v;DQˬc0pXd ꭤz W ܑ(A 7D$~1 ;A^C@h,ςȺ;@! | puCu%u`Y0 W}u8Pp[ p4DT % 8 p @}uZ ~-h/%_,0 }@~0 %0/0~ 瓁DXe0 `TpaZ@ =`~` p#   50  @`=uX% ` @P?0 v 8 W Šqb&!f,  H*\ȰÇ#>͛Bik׎Y;͚'ܹbS\ɲ˕ac:|̘ Q#G E4ѣH*ٳY첍髝:lѼI5W.[i[7ҳhӪ_q%-Vz+lIk 1j+ܺuߊi5[hݪiVlQ Cv }KN3`*{M?['|$ HP'O@!„ qvMس+jP )!ӫ_ξlQOfuBt{9c]nhB$7 'HŸHԁfO8('By&,WB' i"{w"h"ދ<&K˩p"H8L];$h$\ xX'G&_6j95 qߩ,ְ]i9s -ܞæ[.t<1@;$ ѵ0vz,6RX˛>é.79By2FW;s1y+,ԦNIC 4 K5 4VC:2SCS讫oCS8: 4|3N6#:cN1. o|07ߤ8S,$l(,0,4l8<@-DmH'L7PG-TWmXg\w`-dmhlp-tmx|߀.n'7G.Wngw砇.褗n騧ꬷMGBU89#M{jeڲ3X|iW280,߼I.Sok+9{{ۑ|/2c;װcM_sM8R_&;~PG.̡s?*/c%q;`"p0#pb1Á>.Om협 _wυAs Qn"xĸ%1ET"ՇD)Bq9ъQ0qd$8!B΍ !.,c v\(nSwn/I Ǐ×q#>(E.\ŕ[~| SG+m&Ϙ>adP:&j(ӥRindMVʬԦA`ײC'K'>_`ŒVLVUn]rܤv)oiVW_#ۙ !Z,y (0\8|wÇ#JHŋ3jȱǏ CIɓ(S\ɲ˗0ciB3sɳϟ@ JѣHQLaҧPJJիXj]ӭ`ÊKٳh*5+jʝKݻx:4ۯz LÈ e 7c|#K˘/V8獓CLOXkĝ;'/`5+6v6jqCw1ql}}n5v΅/sq}#X u>W,ܵ|Ǭ㪱f}V^\TG9e^{8 0UNvC3v_,0,Ú3|AÍ7TCC,"0< 3N6d5t4ք>L 6C^{<5M84 3H# u@#3'wK6L2аy 3`'0Ԡ矀Z6/u1p'N.ʹes5Yu͆vA4ِr^[W|L;Ѫ^ X `F%: vpH".(#:4zych:Lc$(ɤE7TL1;fy]fdF#M/fuʊW\W%X( yJ2.p.L3 23윧@0sM6 >{(*y5'9$io }sJgM`VgMN 9)):Pwu]2xy!㐎>;tNOᓪ5L5<_@̖ 87|;(93%5 .`a<u,P5O842sds!8yDKc4J3 3;kAXg4]G vhcc(. ڴ6Mxӷp7){[ 2r\589 tnuqh("{=qwK[Db8OCXiZ&Oo |c x͑Dx8G6 ^|#:T@! dWbF{b fC!_j>fA. d8bw!$pC6Li"Č$'A!N~h Hެ8@>d!XZVhRgS`jhe.ư@lܱ=tF;@z!ZHp:AS31%,h:e<(!$ S*T QɴEoLa*0K8F[J/7o" { Yl@ ܶz=AhpTр Ǡ|Dti1^3l,- r nyA@酈/I-t8Z5 0ȝf"94ֽ׮7ADˏ,@ ǡ灘q,c|!!BхT/"Aw;1HX"T 3%< q H"e0R/)Z- ,Qx>qӾ 0G)x T@dAZ@ h,1A&@^DA-N!ZC7 "zG%@eq 0tG> [|,# caT2 $P  0 A+`};+UP `~Q ) ׀ wHpBbp7 ~ 0p' r f21$_ JcTѐtwg q|!΀  @+pye}&WRSuPxV /g" 1@ }i ` C+J2. 2` t@t } ƀׁ! pPI6%ЂfHD9ޣt r 2 MI8(82 &q c3 W0 l W!`#I$T q$G˰m16 V%Sȃee(>` %*Ceb&7R/t)h!` #R P 31 #62tR>r|6/RQYbA  x*C+eR bWER* P^@*W_D5A2FXx! _a 5P a.6y8;;'@ ~r96 `9h` =V ͐٠3(aA 臸@+zcᐆˀ^ٖWəet!B+bHЗH|pp| ܀ ՏtR n1t  ~g6zS1 "h6!o6W+[hp&R!8_?N!4LQ Qq 8b*:!I(q`:ZbQDiB>:Uk:NG !8AO;'[jzcgBjm <4IZP1Q- QzZѨA*/Mv*:aZjڣ :ZʤNڧJ ZJz[-hhFJqzZz3j`A"˪6HO +ۭ}  ;>$ D[F[B{JLKI۴PRO;V{X \۵^;d;U[hb{j۶n+l{A>.J+cZ3o@V1picQҮ-Z<"+U[J+":; K[A{ѹ ;t#1Ij1BK%[!y/ @gc*Q%R:DoYO =)% a !sf{[0 Nq FM m;m'D^]J*v` yY9>w ѐ} ! N Jj/32 `'> |%D E@fYh) -rۡ  h Nou812ag o¹1 Da&d\о]cQ Q ?}1n fn&e @bM |D 8%a2" a2C&7W"aFP *)_㑍|cހujקW+cCo g9` ٰ"e|̀q%6,Aqv!2d`$] dFv,g[ F$jRM‹Ro2 'f`Sl;Zw>tѱ;]^Ul 9ɢ1AvAS2M|DK)0p qq`-C.3x a :q9`~`}P@Eq :d1 5H4^ J mg"3p[UFRťh\o03q$%eY@1})hz]}GUZ@q C,ZA ֲm̀]֝5f PG@30o\M,C 0ڈ=d͝1\EU iƍ8&ۭŀxa /mwwg۳}߇QGjm Ұ^ Mi@=ex H\ g`DFI]C!vYN?s{moՒݱQbz-VnW8g4#APJnFeFU 1DD%Txv*`6~3Y1WqV֊NFa(@R&]!ɪ1!(c="0 q7m@R$rK~yAQKF%Fxw3oTylׄJSvEwg\4A= Lz ;nX>hT~au@_WntנN1`6UfEPN̶  et!ڛd?aRsAQ-E3CtC4 "D]UT).. Z  $JT  p a65}AL ҅ ҹ HfR4>r 7p!ֈ  ! {0  8FY IJ^X Lr3q|R7_40h! %ީ*bҙ ҈bM@R`  l ސtd}Xp zˢtn.Z B+)l:Έ` /\E XbGl  #+ ч0$Di_ ƅW`b'9`ɒݺe0`̖ka\ 4kԩX5rZl B( NA%ZQI.eSQNZUYnW >{rQq זk± 7'q[͜m %N4u5SY8i0v .őkۖjRfX4fͪkOFq ش* v \ƥUnZni*|]Td縹U3b<[\|.]o@ -f;[p@ J,|ƫ欢Z:B:aMk j3.(xR's 2ɀ0 : F+MIm\;*ٮ v߂vi<;Pκ +n/) Re =J!f3pN:NĜkPBƸ~2t: lisr6Y#je#1 ¨k\r, j2:qMq.=Ǚf/qAG%igfZkPt2spFغcQHT - M-^ꊬ[kLft]%tffkO;cCyd 4b*CGQlutH%5KJ/t6NIPGOZ8W}UVkhU/tW`b%-e%uZkG[e6pi|nIuKlݴN`w|kk_x1emfSO%Άb>fh8pC}tK7t$i'Z9lI'iҒƛb*lFr~n`&C J޳ Hmfm&f^5U>l-(uw}ug;ׅj&ٵf.wg|׮%nxHВ<1'G,*X{+׎4)bu_wĨca ]BPN1MjE%PpIkzc72E`4aN쐩63$`C֘A!Y#G7P"O)*\ F8QsS se:Rde+[Y i#A ,@(*G.p6^(4hU j(Gg7m5s)$8cpFB$ !8G6"iAC PXYL'g\eiM8 kg|1a;NwgrIB!o˸/?x>وze&5y#fn`amg!JN zmj֖d}g_to ծ4t~^T|_ Sp4qwTz_~RvxߩZ")`p0Z: s; ~#-SÛĻ3A,A>ʛ TJ Z>eh# X 4 D#P= A3A%\B& <9 I@|("|*:a @x#l=lB5\C6Dc?)4*h /0+hCB$lCE\D舂8cqø/N4}C L$ġq@8dDXŰsD|OPc0JKTS$ )ER|E k᛾C센V&M iPoO#L hTSXi{)d3dO =e\qy V0WhfH^\Q4W=EEY8жiF}\Sy\XώR p(5!Qv E(@QmQ.- JQ1ZS6mS7}a!elo`R=SSSA3"5SC=T7 9S;SSHTSx j ,NTٍoH ‡o(yTIMUU J KLSTZTPU,)e9UU_VUa6 Vb=Vd-0cMVfmVZVgVi5*hVkVVlVn}#mVp W(q-WsWs]Wv omWxW=yWyW{%zW}WW~W  X-X"WMX]XMXI·bhJH#bPk!Ks8P ^q@n&ۉtCJn PeX瑲('lY;S4q$l 3-pΰ!2 I/" 1CՇ;&؊u =Xْؐ]T kuY- h)b@Yo%-ǸCi;/# Ө@ AEۜ [+X[ Xex[[[  `o2_q #Q%2t8YH"iů`9%j8 lTQ|1a_ <i'eJ+=y^^^ũ1 pF^ |H9]_ Y$zĉ;c=_E;|``0u;Q`Cj `˃r:[۸ ~ >2^c=#; I<oTJYyX.cHeoij*Zzhϲq/`PT-#l拎X j);Ni8u@&s`evPK|l$Na7^y|cH[Y3]:f8c@+ &@ԺQ0dco7v"S.UeqAƇB~ |3c:$5]P 0!M`qئvx\qy.;ei WTBpxR-ŭX&] 躍YxsXJg/yihd:oi)+|5A?ƚ`+Xz"I"3w(ȂvƇNo( {x.wƇbHM- ^ kx#*lfT 5 yPKOͲ*|@X.jȞj`. [NN9`4 Auk{eLVk1H3f {X/ jӺ ,YYb &#^lyl.j0ق|x'IGEӡŶX4h.= [ kd ˝2Ck{bHvp,\:a^(ʲ"63p(rpDshgphK #p0@oi,,) z< 46ngm&mqxy0Q+ J|+Zgq2 OHł vj+Ȃq/rҧ2^jش%֘.PqƮhƩ6-i8\@+{eƇ R ag 6 ^V;A;,s[NJ vkH8G97 pT$ ?ҿrZ\$2FJOlR\kMo4Zk_ޚ^hp"w`mwwur8Y@+ƚ;u ITD9vƇH u( oyҫt5v6yr0x.Ϭ?6s@ m(pm@+J yh_@>y,\>l|OO7H[Aw GOx␝3Wywct ' c`x@:8^=/f Yx% pxj@WX,Z+ z8i轡/z?+92 bp$,z|L|hq"fX}Zp@IM dFrRe}r6&WLRdvPhjgp&umpp7$PWAxX`XcPH]ah8|@5.|m\Fe1GyoIS0fƅ,Y2`҅N]k0[I3gN2fes| G3۶X+^֮Z_x;-dXu֬e+7Qs=!0vFɭjr\V"v̘YfzJ Lrv2|)Y3v Zfps5| U5زgӮm6ܺw7‡/n8ʗ elXw5kvjő[Q<0ѧ_(MBX7 3z >Mɔ883s30^ ͆DžKBX )"-"18#nŕt}t]vu]xT6{ 9q'UCZ5_&s (Ƞ@(!b! 9 ȍX49'uy'yYHG&}|[X 9䜜q,5q _=|1K-As9nݑYGK&}m6饛~:ƢHh5|3xts͒_ "Z46Hǿ6:8=w9qڎWy03<_\MԤ~?r(.ى#9γ}wGA+5h\ISA=/zң%2N_$^#uq$QEBgt$0F5~v\CΞeR5AED"8G:Ё4Nf"ReǐH% 31\!R\|(#8 -j"#~舧 > ]1jЅ&(d^Qoɀ,EGFDzg_*aQV^2;21>d/T4 ZLgfD"<'>)bD4O$ asih$dg4CyI0~! @ R:u3lڱ qH+ #l& #X 42)u#Pcr֜2ȣZ94%XF1C#hG9[Hk(;1>`ӎ-Ij<3Noqd `8Z mpsPNq(Qiq"q'<iD>3rN!~>1V6*ˮ#橗am $$h |>@ٌČ!,hqLTl# fbgH3AD#v?zŇF&92#=M`D,Dg#, S8hIQbZ?"H MX ni5dc~$lV@\|TqG?\u_ÍFa pM `3\b1^Mfb%dC)2?HИ _|Xlt[0E1>eqdwЄ9 |GQ.wVl7OceϱkNFlaGĢz_TgAp\ k{a]sUػ՘_;r6=H q<2Z=R}'@аCݪVc&)H jw3 nǟXbMJhG`>g융ix#,>2b(z vD"M=rW0#ʭq\f3Ht;67!%g !cݠ#I"kXql9T^9wSzlu6$Pi`M:Rx#kR,6wwwdRiQ5kBI.`L띒-HEIES< I;GCnyąuuZG/8lPt_xD,9A^ 8TG$eT22 GT, |!B)Ct9GEm BO9j>BY@G8FC(HE 2GXGH۴NylDl :xi4\G,ǭ!x8`D}DT( zHC.PG¼(bq  9{I&cLCuąeV5GX}Y:4 m!=O;L#΂$ GV EaMn XX 9)zyDkAF5|Gjcd/p"")?cl،!v`^l*rJF5ZM:.JSYC0Tc9Ƅ:Dy IkCAcH/G|CM8@];`t37-GOd.`M\jDDCK1F;D2`'D8|4.3U-Bm IX\RGpi!R -:9,l?IZLU6|0TC-܂BT4Z]c>&dB9\S$G|$w/\Gj4Apd1lD&P-8D.yԣmhF9XU/>>MdV҉HKTRS$if؄Q6e6`G4H^T4BIdfb%7It܀*5ha5|$)CDXxLD`Bbpo$H/lB؁G@0@ʼ\ n `Xa}B5CF ] C1ffG(O5` |C$@NO@V28JVGWHCuC_q* D8\AhUdž*R_&L)NJ(D ] B͙ho jTF;<0(_ FU4Eyd a=US|7p:MD+f87k;CWh )1ss+ CraMM6,Ɖk-2_\B\J7Ppt`bҊl엢aFG>Rn RΪLz*JʺmBiZp/O%ѕlQ(!-t IfSM Y<8hGd:|RZ8%('Ѓ<@ NeK_0F%K@7U90ЄBC`jѐho6popC@o'wx4o,DN^P6Hb pX(vHt@G[mbb :O1kq<|UM5ܘG4GTWxCmEG GCSy=\*2Sf02( [Ut,U;@cS!/̀>6JO2,*G BpF1. !R8 Ӈ8 /w=\ "#Crt`$_6sHE'g/52~ǕJ*w 2Ų<ϳ?ұTЃ; Gy\k0Cum:N б=ȂDO7_':J MGK'K FٳTtC;ܗ)޳kC;4>dGNE.Fl+F aBIxl{CT칟oV%x*d B `vL7T*0G4AC,h5rnuOCx)̀Gd>F~DBS0"xM;q5,(`Sx7DC4)HCuC7dA)L{0 Cpc|-*  ;-<>4-07<_|TggKG_~+xjsn\pU& *0q-nWX >r #O]̌f|;{ 5oE _ԲUM]^}W|M3gʠIHyӒ^8x*fv|xɗ7}zn䪀6~^72S3 ͱZ(͹`F6 7x[9~n:Cemuܑ^Q&fKLey 2|>'4K[Tc-B67ƚqi~a0WKjIľ[-EXJy\F}H%T-oĚ|(Aӌ<4Okp[&qЬFM6݄SN:tO?Ũ+Phj۬ȉgyIIMK |VT/0U- UL3g w,f3|a`&2͖=En M4Av<5˘{tB} ߫eFr`'Xߋsv묵Zo4L >ҍJwDu-L|e-oi*XLngă=k~PeUl68*ȍ-skqQV?;ݴg~uX{dnR{obhWNp= pNqC19ɝ<襟siXL|0(:nZ´*w: +_;fq6XX4",JдbX}1}!qܻ.(*:<#7X?|0aT UaɌ  YeFTtXn*A r P VAiTc%QQߠg^#̸cU"nq*9E hTY,$Tʡo$0obG1rBٴ[Ԃ*سJW\kcUHM*$R>n#XqyH`c'dD%i# I~|Sg6gbdC Z,NwSR4|aw_U(hq*1Q |la n.SL(TZ P$ p;XROo:hBW&:EV93r eNySE?A *=9B)H-|i BNq I8'xq%R;̡x!a*%0O1aX/VD/>N/**ځ96,Ơ$&>K[tA&+"NbqG'#/$fKP**I/`B."<0pqG+,"O5jc>ʰ*gh:o3n9/bT|# - gOYmY$'#*X"-1`P꜏4nrH'*bp4/I հ ?" 9 21xO+5Đв ꂄؐgOl۩䈐Ebiap"ϠځT`Exq2-aΡ"r"h~nAA+A~ .+\< apb5 QV|H+P~jd a"z!1Cppa@j&t!%BC c3LQ*]!+~&hn+' b!W/w͑#ܡndʑ!8 0cA̡V2 qp _3Ў+!h11dž,2a$'Ba"Æ!(" }B܁9d~7xd~RȠ0()0DI*p*b*@$0$$g*-Hh+LFA+ *h|""Bj|Z*eS6*3 bD +!h\**+k+m97z.&Ѯ*DiB3s)AA5*R`* iBB=Ó ,=q13+!R`F博k$@bF".#**d+*2C`*IPn*>O(v cBF*Q+s*>!Dj <$R2`r*Av G*TꡇLf<& B-"*J*g!N.TWA *ܴ*NH~pΦ4RBCb|N&MB w=Q*ࡥ^*!SSSt1Du*H5ALU@ V״*puW vz*L."b*q*!Ig"/  ]mRH.$3H#@" j2KСbUG>h]HvM:`z ;$a_"b*aIJB}c1oZdQ6 #Z0<]*ag"|gPgˈlFa%mHG&bri'_ 4\=ajr !k_Wd^ fg@l42VN*V #a*(t*g>TAIi` q#6#"Ef+4f nh #3.4!("( 5A`W+^ uaWAfypȰt  +\L+B@86V!A!*T3Φ$hѬB}˵3KGl g I&W }IIw*+B6+vX+Tid**B0pbEo*op8"C~~DPIIQ%Ρo¡#6!fU⤃цaOu[ ar8AԁOvo%恎ƴ~r2!l(/cB:/|pVYH'C7"ѾΆh9F[)>T)цw>pa/7NY(#Wwϭnqa3fr$p~xy 97!0 򱠊Aq΁#gI=R#1ʰR)"'od䛠 k#~2j7$V3l#a9!MC0D>PIĵ "|bBoB>Bb|C>ڀ3CZy쪵V$a8  .#;+ֺ+B2؊0I3A<",ZvK{ ;WF*A65*r+ĐnZ̆,0\ƒVׯH۴[P[3HG1,O5l̼0&"+M%DJNK*Ɍgz,;1Z=*;ʽɥ*@!Oď~!{ \ȇ<HS-ǰBőş<^/t&*asfp\AL̇ȑܤ|YWcš\΋A6y2~BaΡfRE#[[5R**b{t*|!ӣ&S}@g!}jA(2|*`Q8*A䙬AThdA\A2hk#aԧؿ]g>lbHT&nAan ar#>}+ !k* 4+㝈 dsA~rLGUJa<#{|wAg[$>%JaӷZJߋ ŽF+.!g<⹱kns[x|~ fAό쁭:L5O➱z5A!*ځf*7gƎ\?ڒ(!Fpe_0~D~fO q >U !Zθ8?ߚlaphn\*^8Q 14X?a]41^mѴ D7%#p5`Sr#$*L>X$?VD#Y <0… :|1ĉ+Z1ƍ;z苠jٰMƬk g‰knjY8rΉ"Lsd,Rf:} 5ԩTZ5֭\zr`dʚT˘KfZ6 GhKqƅk ௄ >8Ō;~ YbXc˞Mo΅7&šEW7Ȭ[~ ;ٴkw ߵl㤍=ܷqٸyO\iBkv$Y`ȑ7p;֌9|9Nb%G<|+Μua8>L,]q6J`8% o.5RP}b"Hb&Bn]gr1@<0Uw]v:0^;g0{|V;/)_8$/RR,(M:A(a5JBái'މgzgUJpU9(L9XfRF3 ֋@N5O)- 0#3}4WQb0(OA()]g.l>j(D&&iZ` 2J`3*Jr*>O ɊPrjp 4L5 ܳ /p?(0;N:L32 ,>+P"L% G<\K7`L ) Al@9? uRO}"!_ bo,/H@Ir`A2;,nᣳAh-"52=C/ՂNx{eA((=,6I uVS@ .$AЁ-d8?Cɱ0V[ 0ɐayx| %@'(&Pn9B/t>z1 k.! H" ihfh.;9% 2I1h Pα ` 0G* ͱAqf G;؁hEZ (Jq$v8cd+!(Atm%%_' 4p S72R<,DC#5e>tbcD3f!1Lrl3BDB'"Qv @C@BidIFxi fK\"D0RȢ)1]iK9.XST^zz$3"_:Ԓ/!Omc;Qa-q(>!)KoC v,E/! u( xExQP'~OAGƢ Ne_[$;!lK!Mq8HկT<"\@Ȋw}4䥔2J[;{,2N  [B%ҥuk쎣xc͡w,n1"Ѯ $',Qox,c:A:#S,nZ-gM6"8#NQ3')ډ8` 3Xv$LJp r6=830QtܪHItMiz"2B2Ŕl42/Io\[Դts3 ς47!Bz%0|hg8 &/t_Ʒp`'leF-e(J^cPN >!O '=Ƭ} !H|3I@8 I.+P07݂Vz%s#P9 ת5TC9!0Smϔ MPMolSw,C4K* p8\y%n #x58q%FYVQn ~哢FUN|to;H|p8 B}773s%gC<%,az* z+0ޤ99)uHxaovagS, 1ՄE/_h"ؘ_ΐ\ WnQ5ؑvh#C獱*K'zhO`p `*aWx)6`e $8|ǒbCs Ca|sbZ>&dWU7 (vRG#'32 '` @~` G ! I% ro%x4ӔhgT!uN’mxpNcQ7j qW~ u70ibX_\4LYs0>PM aɇdO q A* 0C\P d0.d8+p20LV3 _6!֐XX8@ Qz8~ }(ptŗ%xPz8wqCC?T,/(T73b+@Aq1WgbIs!)3DA !HP oh BU aZ h394專A ޠ)0  iI@n 9cIR PQ(=~ !q+`&@`O  'Y5  U/ ޶ :' gK Fo3Y[5хey'gYĐ ъ {v1jЗJD>qW+iN!,͝|7Jзݧtʼn!˙ja:1$P @< jqRmp̿YӬ3ɣ!`7 Y] _rTC7srk#H[xABї ( 4UO"k95ߠh,}-= Q LC.k:H mЍK - P5c*r%oz 0W5W ŰAA+-(d) %P?j~nEPP F| T Wի CC~>QDiPRL9,P p Js1>V5A;O$U QjS}1- t%L@ .W24WPM#Z@*`zc.잸P^Tv .E {$2hj/>Рd 2މ8}]$`)FnڗNPRnN C 0`2h%NFSG g@[^2 H>8FqQ<|qr=bv7p Q TP!6pH[`.`wN!vmI~A?!!W} La>lAY82 48! 0Y6 MnWcp*8{L;rvIy:֐ 4 ݅p 00 :0.xAL"r4l`,qZE*YǓ0=1vO @T? pCˮ cc)<b#=1yrV̿uJX?|Wvs'<@"Cď.<5x=I{D`H%"RU$ qs -֝n^;osH>.3a G8.gMcCЇQz>DH*Saَ"b`v\>* 0CKZe YY \a \`g\d2švڲFC>яtKuD$Aa5rE>{d$`}P}{`%k~< E"3\C?w_ A& C2E4XF²2gRxsGwJ:HjVӚR |tM!F3Dr&{ 'Eq璈Vɬ2)+ˤ<} BP0*{3wI,hF5l* (,P 3w$vnpvE!;9\(av95+=y S4QFwjiY[Ͼ81f@׽EKqR$|2"X.|\PA;?O2hLee APP2 _bIv|`m^'F|R oNS;oMeAiK~!~%m_J֟6?Z8O~xsGs^J>4,gTL>o}tW^Xf޽yi;q%4-,,iܱY6Dܫ\K׿^r8{E̸lf7φv=mjWv )> BFwսnvwnDƷpw/t1Ǽ>pw}G^x[}pWGwqw< =`'GGr܊[7?u\tGGzV|'}/zԥnWK/՟@X`A@>@@( a a67Bހzwp >PWw `@ !| a, Q!hBn÷~ᅞ@,`&gp܀H@0 џܻ+@tӿ7=ģ= =,s+P0@@@ ?_A?s X x0(B<,+4OB"@+A:/ B,$8-$. >1\ ;Y Jdp !Бq2J48?.DD D0DDTaSqDّQ,JWLĴ TJAwы2^|WdYdFEű pJ;~y 9FTpf$zFhD cu^Fvu0Ჹ@ id,r:DZA =jJǦ 9mѐGbGpȍ<*ȵy\ fhyxyƆHeȝLP|uHI*Zɖ {@#Dɍɪܨ}i_M) xi yx|y(lDi` i`tX _iXE|kVxa(̦8YhJ K` poɗ,|qōKq@ YE s8NBĦɆh`|s( Ј hKX|X̆l ԈrȆ$ILL`LlȀϱć^`n`K s LΚ8͋:֬i ڼM܎Z Μ5}XѦkwʬǹQ|ψЈXQ UA, gxYpɠN O w_h + iI,X`1-ۑ)KY`7S|xBx' @?uU7<=Be7tRuBQP xOAQ!mF݊#͋%'Ҥ .m |&X@|4USȂp$՗\S|:];Q*:8.<6<1t;k@i :,7yG%W9̰˨ d@RwHвf(>ץuU hSp F}]m xLIR>]?x)q]P Ԉ8uثT|Ո(0ؿWDR`_A>ZHgXCHA T@<E>Ε.\7V~ {xI ]]RoQhTx_(VhWx!O) o[|pcpY^ʠX*`MYhpWX[x=Թs+;8.#`"T_u`bZw Bqm]Sp]Pث8kshhVX( z^w8al ^8\RuQz{8&ͣipVKcA*@ <-?[;VC:\7`x-b Yi1!c5ֶҬP([cxؠ\/T荈Cvhm"Y(IJNcTA[M^hp] '6 l4\Ž+^pUZVh[FmHP\^g@i'jR\Xg3P>aP*|AV͂,;Zx<_*@L8vAװ>|@W#(u3|\Hȅ\-ǫ@δ^Ȇ^ X0Ŵ<@(/HF8,07Vvul}k謨 (]P xv@2^lur`@u(9qQ A@vD$Ky$(̔ŇHlusPk ]\80_X Ƈ㠓kj8;ApСA _hks rv0ٷJ MhR'] ΐ ) d-+"IRwD )ѢX "AGP##k(@jS r mvp'p'} -'Fd봒j8MyNJ?'?_fqfM" #$_%7&Yq:r+OF,W-'u 򫨄Ahnr <j^X j79) 6o ADe `$v \DP}iP[?YFj oHt+pDl Jn(0njPOFRGpUVwmYEZl_u`u_` bOcEhPf vːv Ij(vpwr7wtq`w`www_ 'W4xrHz[M;l@  Ei(vhsE)l(Pg[߈&Ǒq(Q7MfP\ϊ態)h[sN_10 EIaPha^fVdH j𔣰`y{ohŦhG?~g~;uVzϡqkG^Gv`f(D{h wk_WƼO]9 ѩ|'Nܸl׮;X-f| 8`ϞsYaYvP">`U,YsȅkFg˲yvm`j͚ njٹp#89lӪ)lnjժVbͪu+׮^ Y|΢Mv-۴e+w.ݺvͫw/߾~,x0†#N/+=xe%s n:^3lpղeeId eohI|U{˭Ak~^JuA&1hke~n9q榕W3PWjҤӿS4h¿Ң{`%Erpf%:l5" 2ؠ,RXbr\AdO mVgg}&Nhfj;F}Woa8 YDž4Ra3Qg4%w7^yٜl^|L}WDTX 1w٧!EF$AdR-Μ[RLVz62npP;,sNR.R9A$9c]8"N1/R䀚*5x\\g} #zg3'-it&8ApAP98ӕ4LU\#r*5O64:Ti9;1.$D;qIB7YRֵ:l:*9L9 LH̀J$4h7ؼ/YJ[2Š/Ħ-䲞CJ83L3< ,E;p!,D9}\ .3޸7(]¥"wU>VvxPoY4oueW d!M .1jMߣ[jQAh F8AH! B=`9h>/XCO+d ! iC"RPK$Ex _6(Q- kdC.@M'bw0.&˂ 5 %4|.좈ph9qQERW8EFg  ph8" +XP+t*\';wfu0)dL]ZyOsF;QJ|̒,$KoЎ"KB.0']?{ 3"1" |rzfUa#Af 0@|iLgUԧB5'] dQ\@1 {e`N$A9xC7AN#)pg\ED,S(4"8;|(4\,hD6.K;N`wo> "hf Я @l AԢ .VTH5.qFչD\):LXƳ<5.p3kXdPM)ua +Z" g=WDN؃~-NY).[/|`Y yz\Q w[^8vP #(NlCob8N ; qf>0/(KWS`(r lP@^Pԉ$֓׷*B04+mx01 :8(6-v \_+`~=bOabTCH1$\{?O0C@D+1 ui > \P8ē SXJ}t5W3ɬD8A[(0 [$7D *8d]sheC8 )(hD3TCJF4 0B|,GYH|d92 sM8tM NQ|aaja$8 PGd!VA<`V58.4r\|`t!:Ȃ4D:9~,~:`hC1,CF 0ܠ3 DW;Pi2Dt9p bXma..U/$$ 0YxGA 0؜Y,~19H~QG8 2$XbHD:tHiH5^N0A 8MCJH:,2OFR 98ĸhFn-~dHdIIdJ䒉$/K]"00Y hY$*#>0#3D4N8T#Bv8#E9œd,GQ=$NL$jJ;D?Ge3.@VAtC;0C^T:.GE"Tύ-p_.d`BޅX6NJV^b2&LfM&O; BdPY!0F6=5_A\C<BB^DAEr(Lm@ &Y4P;PCMP7h 0)z(Urݐ\ 5l[C18ąY> l&;PJ$*~29U4B1C @  *ƭ$<څ҅6ϲR[|B֖ +B%ٺ<n*, p񡤅B*!/P>C]aYʅ BǑ!B2 >@Y\Hƅ,LHo)J%ۅr݂R EPs și-":~,8p7XBL T>LU"d#+tZ14}>tAAlO2^2,+( 0.0$r5'H}lZ66CBJIܵ40uGi/Tp "EC4Ɂ:~M`6ZunvpCn6DC . n`Q4C)0](D8rrߊD]*911̄e4yJ\zwP$Ttt|We%JJ.Liٽ| Z/Ŵ)CCȘm,ۣSy"1o+x%Xq.G[yy[|90ŘZ|$]9ccW?RElyRLB|B0`/6TWy;\9_gKIx9ykz"yDŦgz "9Y@ UrSVGzOb͔vMGJNÇ2{3N%HuR텖2{3;>$2u:c|xT;hP8p:~LT yʰ MSdCL@`\x"3v{;:&<;GTv3|Ĵs;z;F7$:zB\9LBL| G76^?sgku7|FhpjS ~M;53}[ȿgj*bY5NdI;ؓa@};ʞnLKC7qǓcyԇ}ګiga$Ā=`̚3L꽤[o1FK6~{>=>Ο˭PC)_,$e~3ُߣţb=V]~7>Kc+zJSTaL 3[O9=s'0K>_?ʲ3iLg!@‡O4WB!F8bE1fԸcGA9dI'QTeK/a(` 5gO?:hQG&U:s`Aq\:jUWfպkWi:kYgѦUm[`m]wջݰr;paÇ'VӇdGzB{w﫱|y 8}{oUw|9~ 0#@l[P*)$P 9-A Q>QYlEV|Qi\*qQrw R!C#L2"#l!|R)e+,- S3+5N6ጓ7NS=Y˓?@ -tA MTQ]GjI)JJ1͔K5ӡ8TQc SQ=TYmU]U։`[][Օ_Ia;c)5eUg uikmԖoqs4uTwtyq{_}Qԗ9 R,; NJ§`CXቛdXwc⍝`œ pIYq‰?adUfecykV'fYcgq|n%9Q:j@6hC 2Έj|l$7"<H {D-0|";28c > 75xۍF㢾=L8Ը{). /ضh苋3%2:¢wg1"!a({~-И1i=v$_BB06a k Np3 D|QCC60d x䰇2t 2…d jKPDaA.G 6d{uC,BBHO #BǃqG؇>|}[`ÇH"rFIQ _PXWy!xn!TZD~n8D5| b<yb6dy LH.!\p&)!).! 'Kw#2,!7l 93op@`q~:g\n !h>80(n sC!3lMpDOƃ CHf^t,$߃%b͏  #C[R"H͑葔 F$;Hb X 9AoHn#40:|6 NH r3c)s~o ej p  o8#0t0Oo?:#|!ES*Oȇ#@JpNd&A@!@Z8.UW=gC`ȁcZ˲QkDHtH5!#I#snXj1X \8X]۫K'`$! DƉv1ӨFa) 1ЌU#xB_I!L| yf@I>/ B;mK·N,ղ;Aw?Fo = Z$.DPE# ]9r B`3%Ez!/BĆV GKbg$_N92R$T Ri8h r\< z4>Z'͙hP1>"*ٽD3-Kٮp3X;* 4`~G.! nS 0}63!N!:kې8{'!"A>7fKM.`.$[˚'ɰ|x[dp`\ĥ( w _j0 yPщ m7ғHv|:(!j"( fҮt P t@לG}k No 2m' L- ,h| 썧Z$B %*&/$ 0 kJ (`` Lg t!  1e "!! (4m%,H2 `(w  bN r¬B;-V` v{ #* AC/4As]tEYFkTE#D'B f(ԙttH T@= Id Ͱ,^< NGfǮs2H8r4DzTNS%u4)Ӭ&d⌭lQ Xҏ4$Se) `0r2qxjst9F4KQt KNɔv̴T4k Mq5=tN&kլOeiOOAۀvhb2@'?Z[&)2[ a &2ndfffh&5_ȡe&ā"!A_`Ab[%1!dbec eRaF΁gbc¡,6e,_6Aad!iUik"k!e!V&f&ltoq*dLfB c^wftq!d9!,4U]wp?p#"q7tEwrC'u7u36pp! 7KH^Mt5!Z|w]5^se!jKnqs8 wW]!~7dkCp7v?w wvvwwyu}uzWv{}WrW| 8keq{WyߗpW~mwյ~~W}WJw׀}C*W8pl-d=xiQ@L{Scׅe8>`kgۣEy:t;~ 8:88!1,Sl ج3s*\ȰÇ#JHbBuamvjHɓ(S\ɲ˔ҢEV28sɳϟ@ JhN~xɴӧP[իXjʵׯ`ÊKٳhӪ]˶۷p<&R!V7ΦGv]`s8 ,9q2n|$)2f9OtdI{T3Ԫ M" ߖsGC^ذz.uw2ӧgmؾ旷5΀x6V{&܂NX^O "XUaR AY"T†(p"I.UU, TE8zIC> &5D[-!4. VR>Ⓡ@lyUffi&o6fdIXv!ILiU8P~69үM{2D^5߆>HS 4V>YJ'P6T-խ/3( 0dSX4c[GdyWFJC/T+zM~:Iy>x}c'6I|{q d>u혽_k>rK?b }s`/!T,K H*\ȰÇ#JHŋ3jȱǏ CI @(ɲ˗0cʜI͛8sVA ;x3nװ ֧KY7! #2W*13&@uGC:Ғ4ț$XhN2 8!h9!ș - RJ۸ր51_xHހw >,ptm*T1sFhgd 3By[,@8QÖc҈Fc9 q;*KҸ#*g _ +IKI`jlg;Op#T-!Q#h!nqIz\&Wu_9qH(9].xKbƘ@3b7nXĜ;60J`_#zZطX J0yH| ` `<)O!!@!ֱF347X $! ~A#.Y̌f8n|g4#c?K2d$c(YbQp8Ɵ̻_)k4;Uz`{P{{*{{V ~T||`}zP} ۇ~71s8\~~F0 z'8 ug4tM @ a FEFG| {P Qא 4ߗ = p}'{2T }@Y=R b2Ywy28D]68 8E4 ѐ >X2CXGJ LX?ku@0RtVl^(a84TpiF7oq8Pp[x?ppVHHH0\ 54 x9S3b @C0\yQ樌YϘY( 3ֈ}K}-ƍ ErI46 ^ ՠ|Ujt p==o䄈؏ y4UP @`X@H pؑٓ! Hdd}Fjs8q Ő:P ?Ced@P=iGy 7My' |c@FP  Ȱ9e w#  GaP -`P!TE( ` 7Mb09 %AT XDY-P| `K` p9kY0ٝa`D Zs)0 i0I0?d< F4 @ PBy x3hW yPE -x*6c ` Iu70GA@p  "jD İ&NаGA0crWrT C Y$(6OU+~0 CQP BI՞ Mʦڦ%P)"xX5ٜ+6 5 L5dxQDE=09UB? G ͠pt7:zˀx`a ut ; H3 FF ͪ Q @xXBJPC n ֠x`@C@pd #Tp ;6 Ү*:B0B(psB4ů0 9= ;:հ1QbnH8 k'vP wl|G'4vf6 ؠFl34x=0?Ylqv{! &MKlC>G8wᐵ-( !Idk$i{=l=Aqk s{  w]ks%}{ӵw} &x[{bpA  0 08٠Bpl3]] fFY A3 ;vGк8K[P  # !7k6G{qf 7 qsbfAI :%$&`' /&[ÅPQ hWy F | |;MVBl|E$ %) G'@M l XTQ $ưF{H56k Ai|PB, 9'$ƽVƁ&ǁ0 MKN ,}T V $ amAɌO-֧  ϐsm6E*GڋtlV< ϶k{S# ռەMƗ]͙-Мݬ$ >mIXRmƓ=ОXDH Xˬ, }܃-|ͦ?OI {ǖ`Wq|q ^ @q *G{z 0  d9{aJP} 3t̸v9~'jsv]k?*7`4D^Hp7v הɰ I ]X^kbN_.[Okhp(s`{@lC677b `>QlPlvlsbYGs# `ws3>BvY '܍G=[13 p{β Nހ  Ȯ> u. P?٧+ !R7P nYYZ`M45A9gJ&l:,X=o>\ː_Dz$o*,.02?4_68:<>@B?D_FHJLNPR?T_VXZ\^`b?d_fhjlnpr?t_vxz|~?_?_?_?_?_ȟxmlhfZX~p_@ _F` \g,/Zٿ[+P߯mXv0Р6g.TC%NXE5nG!E$YI)UdKmd&TFK |iF  p LQNZUYn̦6A0"@+ghQ-ZSy_<BZp@08D0PE2e˘5'B'^ 5 A5f}9Qޞwŏ s- `@m};y߿$<‹<0>"82+B'̃ BqDK$n "$ś Hl|0H$TrɩX7p k9S[/_}DZck׬aL3fe Z2_Щ[5`<׌ǟ?Å[ٳg!sOqKP|弩[\N2KF'cǀ3Vշ '߹b27,ik,ܸ+ rst'3r6;.էI,JmZUװc˞M۸sͻ LÈ+^̸-H$MT%L4m̌0f=Q %j)0gݮ2q޲Mz5f-I@8Z\sY1ㄣctL_`j83Ceiƙg@hΔvx4jmh8<㏻M3 >մ_;ߍW;b_s{%uR3EEM54IcUSLH#M]`81HZÎJsIED~2MI}X@9/\sT3|X\∃ 30QpO;eQHe@rKj6jwE5jEO?! 9$TNk+kȾ%$FBK6\bRWYnYLהc&)T5;\^QᩧDŎi )(?9 >èA*\9D9*0EΪ̴*8#kxfsk2Ε0,4K΅RS ( >昣b. >3<\%7K8}]&1@30(5aD 6TK. M5`S183!ټIT -MH;ԩ 18L2Ζ -zwcP#w$K%P㎳ߤ.l'|w-J"Bm4W% ;M_Sw34옣-Dyg;SP:pS*7PtV`(GwwiF9 qPJ4lvJs[N: K[{L/dZupNx "HLnW H i&N9@ iTFNp\}Ψ3F;A\oU$WP-<*^eD+ xp @* Ot= O6= m F ֣=FYO,Z%-h)#^c7P -1:a x; @DP@lȗq\#z7C@eATqQjTbٹ7Q,pGo aw@QT15DgLf$Ѵ)66_DYF%X$! n*@2>J0vYkq kP. ("|Qqo Zt+m;$(7t|AĘ4H{5;+vDQps 3Z sP!;; `f0K@RiU$ ~p8WT; H~$x=K@e\Apk&7Zb7# ,Rv}bI&(ydj&+ D:Ejf{HϚ|1#d9bC#=X``EU pns`B*AyH@$0`aOEbup H;),!(wEk$*2}B#p8@$ -`z7if;v)8 `Z,*!0 -~ 8dzxy/,E3"ͧ'XrOfDq!xt q,b|5N )CځF6 Z:G\s Tq`tmgQ ^XPni^\wM0 pvv  pрE@~USP ]Bd@ 7Fx &C@kSyty Vya`w;^E6 y6lX4n׆n/N5y7׀pڗ} vHE@އxd eU$ pm b 'q7fefrU60h4 *P v 0H o`xA 58Ky;$FE0 %mĔv mWPHKE+p0 f RB@- ma B  XlG UxM0 `WJpk"xGv0uh!cّ!rpXY |ȇpE@ p}+WEog$ X~hEHh $\ sEx &` Y vXj` IV7vu@ 癩 hkI V  0HH @Vx!Qp8a3ilmV`D@JҨHH T@ aklٛL3'E,}ЇwWX|YIdZ PWw &f~(Y% (~"f%`ZIe Ufg iaEZАP$ށ sJ?CpTCp ';P @W iV  f:iG p Ð777 ۦ !@ I 9}9u aA^JחfU 0% V p TbYfzoNEEwoGPGP?b?FYuE@։eٓRDED'\#VP{&Оڨf3E%@tP ʧT)HZHp 퀠 նmpjUS3C`! p6pRf1Z ` @u5DA:CPQF%kCO/:8j 0Z Kz, +;oX[  }@w@l plT@_ X l 3u  R TP1?< 9? 6m X 6p63: 1rb A1=%භ{  _G OW!bH @JBHb F  @кk  m+[ۑWY@_+MD@ր %'r(+'Ѐ P q aGs@%j1B]N Q )FB 2 +20jS5io{ q; FS 1{j[6J``JOF1"pc 怾а@ \4L_a2sA]K;[VnMT p R `  j 30f" e|i&kj3^4:3L4퀸 `2pi#Ŏ70I& @ LB./Emt 0Kd`Pm% E6 l ľ%Yk4Wo~^SX;S|ODVWWYR `C zƻ0j" `jtfpLǻPǻ 0]kj[bCD#Xݬ6EڌpL0F]L3Tm7l&Ke !P>m EhEFsAX6Bm@~DO j3K;ɲPF0Qd| K{ '1}+ EӰ;;R= q uƭa'(r@( BB K&3= |6"$2(}3G!N=~]D->5}؊؎ :"ٔhǨIڣ<'X+a29 9Bۢ= -l-,4c}=3v iKش$v"F;B{E (אk  P /c0 @.C ː @2@% 4^?}0Q ݊ 0z k! ."#%~RÜ.?V6~hH ejr>t#$h u|~lx!#?~jA6_c> &MNEXK ^1|@ 7>W#鮾1>^~Ȟʾ>^~؞ھ>^~>^~?_ ?_ "?$_&(*,.02?4_68:<>@B?D_FHJLNPR?T_VXZ\^`b?d_fhjlnpr?t_vxz|~?_?_0+A! iߩfZ/ff\q_Ŀ\ZWp^_f@_gZ/w?oدmn kj{஁y~l ZpWɳ@aK|{ha@XvH<_ ʕ9W0p >DaB6/ٲn8lX2 9;b 9 `Er=V-h5p@ 4P-$.@ 0.̻ 7H.&-԰N66TcH#ͽ<ڨ !/?"W@$TrI&tIܐC氊C*€ˆ%4֘)@J6&P /b /+,s hn;\!0." <JL3tSN;67ΠCp"肈> 4X-|L.̃&/ܠ p  YTFB%*4O[pwI@㽯 P<( bu[‹碳A,lp̃6ՠր x75*{q",h.mi[ѴcCydz, 5CvщoW|;8h*ڂX8c Yˀ r9+!{Bp5!'_Pܐ+ BlaXz0-xAd?j\B0Sj_!Bʰ1ȡ rC6 ]B:('Q<E |@svb~.. Q|H2cxԜs^ s IrH0ď~p7+R " <4ȅ!nMI8L 8 <0:!]ȟe-mi=c9/4"3<2eJ`N,HLjs$BQ JTiRXnyNtSBTNvsg=9q8G81l\88 |xF5ьd0H7q8oӟ7aGӑs,G8iL#$3" kd6Qjx`3&5P*STé=zUfUSKjWJUUc%+l:Uveek[֣xիT*\zW{^WU%UZX&VTxѡA!v81F An/cbY%Nw̼F&΍@#*@wt00|9[fjC@ bbZ].n\kmN&o:u_S?W5iȁ۟8.\8!],? H*\ȰAs#Bt(PuA{͛vؕk ڹuΩT'Oŏڭk8sgȚ%SG>ٵF 1{5qHhʭ'%K6$Q%UU뵭۷׺SYX2\nOCÈ+^̸ǐ#KLY˘/7͜blEo^n*W1gqWj`I{ko ְaym*u*Jf:`b\;Y# 2gמW89s8|3$#A2K;FX}F(Vh* v ($h(,0"( 8d<@6DiH&LHc;6TViX4d\v`%L3dlb[)ti'd|U٤$ rg&袃P‹$ $$i%H,SyjꩨJ&(`0~.0- 4:jVk*{(ޚL  ;Ȼ/ϊ[8.=@+4qR 0iY4 p52 7bw ^p-tiM]@ЖR,B͵VMά:e=k7^#ivﭹ"z+0z/ . O{FW/% 3dz'<-'v`!C &VoD׭.> Xڕ@`-._!JV Z8DAxLXw"vzd XDpmDKFHz `؈PΆZ֡VQD%CX@w$?]  XZKK43&bZC=Dk%i<&C'~ (,FƬ񮨵_2#}ACհ5FmZ(TYaN,dRowB І5Mm ټrm9O}lNv/0HQW^o[3F{H'N{ 8㝐qg}qJk&WNV9goE9wnn9χm'mt;B__[}gQ#]{aYߺؽ]rc9 ~宣R;(;>'n;%Y<#R|+xˆ$mJgĔ͛^GĨ8&:hFëfU&*g>m_}d\ou7W `P@IT8-٢gVڐpy,πpٳ4Ƣe:ߒS"31~({$"5|aRzؗ}"{,IK5[x4PJ2SV'|2Q!a25Z[5_6Mz&4²Qv:4&Bu;87'*6C99ao3q37g$N8N+;5K/4u.4B14@_u[@ ?ͳB޳|L=55]`65Y$S>;N",u=?qXx#QX@}ss!SkTP @BHNCyWgNP)U/UB1G5OW1,L͢B'I(B">a).UT7GT3DPD4}zw芜x+h:CLʇ{ԃ(FWXP(GEd:T|$@sD4SFb#S5&F!DL2ݓLxب,%NV؉9c\JXB9D[Z`f:[ta#)F`0| %NԘ#ZT0͵Е|/1Jh70YŘ|EXWl`DT"(>Yn@o#,2/}XX$K4c`>aB"ِpy8yb 3\ꩇ&=%(6F+:5!*أ?ZA*OHEG KjMꤐfP.:Tzx0` ɐ6M ZJG٥;: D'Jlڦ+¥py@sw:J "B!*{w!ৈZ& ¨ w0JqjjzHw0sB"ꪟڡrlj#!p'jZZ"ʺꬁ Jj!©ڬzvfiƺuP Vz#Юr6 & ̠ 2trs[ ۰G*cWs˱s Z'#{s%kR)r+(, (w43e=[+}y":qQxD蘇WLB|D;l9zȍ1V'S ^9k'[z48J؂5DQS4REqSU-T8GX`=`,:'7ECa:cKb([h3?<.@/m(9X IR$a$SeԌ_iJ'BQ4Hu/C[b[%IP:4 PRxJ=˾ )9؀I Sk{ݻ-{L[Th<&Qk\i<Åf/;GVNOF}4"V|;_^Y6EˉyVgE -\Z)"4DýX+0Q@Pй@]UY2PمYC58rBU3c4j"Ic=b%b J1V̊> \)H, 7]3=DFt#t]px  x=؄]؆}؈M׌؁ِؐ؍]ؒٚM m٘٠ؔـh0qusM9׌| ی١}ۇ=ڤ}׶۸ۻ۾M=ܛ]ܝ}܄}3=^g 1   kyC K-=CFs! @!04 a ೐ݍh 3ZNN~)p   .A0P⫌:P 1>5~7 H 9IN*ʾ0_Za]Ѿ`Hmj^gq Nx lHm~}s~ x_~zws>阞难>^~ꨞꪾ>^~븞뺾>^~Ȟʾ>^~؞ھ>^~>^~?_ ?_ "?$_&(*,.02?4_68:<>@B?D_FHJLNP?y^F`_w~0eg|u_\pnWl`jk JVZ*epgaPj`\ W^@vzghyT9,A@Z~pZW0ylj^h0CpXp!Z_fp//W,^`,Df`mPֿد?D<%W8p \icL4nG!E$YI)UdK1eΤYM9uT&O7h|a€!WY D- P°ʞ@ LdWaŎ%[YiծeF@!jRNp:u*_n+o/fcȑ%Oyef`)q>1  xR7_̦\mܹuXoyN Bb F,B*.!A+HD| 02aT(b؁86<@DޢGj= ##H\0!hx<wmsK`xî$0`r[8*)XvWb,ܡ ZICr=כ\I(EPPCW%61wF4$<Ъ)@g!%Zpnd_e$> %0ȅٷ;P*qUxah^C(F1;<@EGC,gm[];e'b&K5p lD8vc1[ڮE.j1 AX@8_,:1VD"rX%"iM#(4CĂ׸5HSYp^u"hG3UznYOyj/,gy0zDjBf3Z.} `W" 8+ A$>/Wѝt$-o[8, dwnAm+Fj^|lDh,7@B &SqxQ f1<Fy~(&hZŤn LR.w6:ҧU |St>ƻ89myѥ1aXa0L{ e[j@ΩuE\@/g$cpD?w h]xN\"  M^#"3qUP <@qpwy\Tu]z% %^ 0^` Ae GHd  ѐa g|Ƿ40<# # P [$ _bU [}*p `A *tP?3 T  G Sq[beH ~( <  A<0  x $ PBp ~ +6 4{WXtT ʐ `>Nɐ >@1Wf pcpcpgHˣdIt S u\JH% TD#Bs ͠;NؐC ,,OP # j6FWԊ hIh ԋ0PpuČ1xqGY Շ0C˃ՠ>PpՐ ^NYK ـP ) d[4p@P0Tpt p` S 4 ËHv@F'dA=DH d tx N0 AnC>| J f D ? ߰A`?ivX[ٕ_cy[`hlI0 w{ɋ7FNyɎuIz &9`i )ə Cyϐyt P Bl_8à ^#JYc áU P#C%jO+ʢJ1*B iE;ʣ@A*B;cG"3 z ` p9J #L:2NFXt4t˓ZJ Ơsl GF]j /jʦ:C>q32:jz #t 4τkY@NѨ꩝3!;S F}yj*J8꫽E㤱b */B cʬЪ!1j@ h ЭzK~꪿ zP @C:p`gC 5PJ ZGDH }Cc̠ K5p!I!FS*@ 0/# @;3IH[U(fJ˴V2Aa QWaD ^ l 4жr3p0z[3q(1wy;q};۸;[{۹;[{ۺ;[{ۻ;[{țʻۼ;[{؛ڻ۽;[{蛾껾۾;[{ۿ<\| <\| "<$\&|(*,.02<4\6|8:<>@B`  9-7!Y,y H*\ȰÇ#JHŋ2k֌Yl٪=wɓ(S\ɲ˗0cʜI͛8scȍ3 JѣH*]ʴӧPbH$ujʵׯ`rUhӪ]˶۷p1g:˷ߠs ̶Znf92۸0ǐ#KL剌/ˠC[6*cE^ͺחk6nۍS[)jѰ -dȓ+_|̸o;fNވ7nu.Rҫ_Ͼ˟OϿ}`{4U% VG^$'Vhf{^6($XY8#y,^,u8HB L"A򑐌/X8AE,@!1O0`#WV@@qBa$wˁLrX` X"rTX t6YGK` A 0\>/QXI- 4a%+I+ \JH i, 'ʗΆr'B @|. )ВT5(B 9s:hDшB,hGq}"#=PJ~^ p1P L6qQT>*JֲШ\jSOԨS= ԠAM "g jh-Z˷:q Ir==:X-lb 󱨅lhWZ-:2_d[Kfkխp%p["U.s6B.u2b.wk0C/y-°-0j,{+pXf0>#~?_:XR'!VB ӭ n0a 'H O D blB=@^Zj,wA h^K|")@4S( hBxA{ߤe ٰ̀BEwzSxAɬ: wHPL%2="5k876@'>=-7m"Co R5}Uˑ2W}+m9M# X p՝𬤆UbЛWHkg]fhЂh 6V;ә6W8ڥ4vS\M(a&I>oX0aB u8;: _oX[|5eX{2߸[\2!QX|0)_[%2W9ms@c͹Г1?sE>N)n tPzR˄.W] XN &論Г.AпϲzhOH{!,,*!to œGHq0 (@g+K 8{䱛KڥُynAXusbi)lBAH*-=Y? o ֢ 4n1]t"ō8W9J1{EW5Z/0`vwS`Y/fc-feucz h\ l%z6*H8vy+h|-肔1{3H{ p pB9_ƃ>CQFcHAȄTN JXLxX`Z8\8^ceh腆i(kȆo?GO6OatV.&%b{HbуRX7mdv>nf0X p (cxBvꁈ[*[NAP, L1Lz%M[UZNg((hLZS%0Dj:vj*hW@x0 WS fP\cyzwIH~}XuS95zW Z(H(aRNKWgPY}hXdi}َi-tD g!j5S 0ՌITy(BToTdrsƒ-)T6[ p84YGO$CiXJɔMy|3S~us6WDdI[e6cIjYl0tIpoqYl_0c b@dwiyyq5d|!jcИYY?KN0_Zv%[\)&AYvXdQD3cYƚ'嚰9YyZ׌S|$[_` 9ʙuQ*4Qx1$QY&Hةi O)I0W0O87yJUvHvGKTO tS8f0F@TMdeQV8 Hv \ @ uy 0}𡀐gmJ?u~1FҹLu^i0yB::XpU :)V1IP*b@UBSWU(٥Y36QDdTH”W\_kʦp:J(xYo~|}IʨjQ{-Va0=RN/ɩTngz꘣J8z0I2O>FYI*fc2V&LWpS*GZRsJjs犮㺨s $JZsD{j]Kk ]c~&Hۗ{r9a.`J+.7vڤ~ ˲ax9[oF; eD?6{-hbE.K7[UY)Zĉ@&d9Iqj6SG3 -JXeRp 3GdDfN:i+[fǨOkκ|nFc g5ghcOah} lʁRk,}~;YgfNźf Zdi5ypn`zo֕ ʼ[4y$Lgkp9Szvmv@MsL@L..@XĀ黾۾[x$J}'P4&$LVoGYB e\h f]fMh`(̮*Lkж+-pmJ/D;5lz MA PC̾EiᠱKlFMOldQ<ŠU4|XZlX\|^R[4e[tQhDjƃY[J4t^< е zC)k}<],@Ȇ|ȋ|CőL]@w9pV h_@.yw$wj›\C ZK:@^ ʡ\0P5z-O 7by/@ԈɻLn'N] Yc~%PB~pvzy|C+* [p <ϔdj'LU+`ӇY6I6UEV$҄@_VMM ] ,XOOv1URw}D.}p&`*Y0N[- [̠35m9fBJR~J._ ؕ"g)S\FBoVj c-|LdJ$U$'d.ث5ZGo-\qBt M>}%JЪ{]C#M % M̕\}53Lٯ[-ηM]=ЎH٩ۨܺ_`ܮܹJ`0 %ӽJ-EB۽Mß =}}UޭtX-߫D߭M[N? ca:@w ߦG%Jr 6ʕ%JObALu#Lf'Hκ(UVzN.O!,@?3 m,_z˷,~=nQp==7mB!%˷~V٠GNL>\ T[5>Wne[6QQ/pgHNbng*/n-<P NrYe@)d~~M,O&O! k(EOňkƭE`Ϟ.PmmO}D~JlNչ۲-)o% AFĞB9ZjͭSht~nFG^nEh^G_?G ȩ DLƛ'e oB"/$F&?DxD?%mz`ʰJ U*ܽl1^6F8C,P|44Q)zM.JNLOK8z$!WSLJe0gG8c }crQbzݞ~n[~Q>}э/Џ}HTCMug*beOzW];@,п0ל ظ*b{hLsbT{t?Jzo_)D'ۮDoP $XA .dC%NXEp(ƣG|!E$YI)UdK1eΤYM9uO4f$ZQI.epcǏbNZUYnWC%[Ydr*[qΥ[]b_k%\aĉ/cȑ%?e̙5o9ɡE&}GϩUf5UzqlڶK/dں}]q9vHd@u>Xwŏʜ U={뫧?} ?k/# H2TpA ɼ @ `C 6< @fӐPWeVVZmTW1xa5%hYoS@B`v>Wv_05[sb75`] lA-)Fl 0!V~K69U+ncyĂ p`g*d̙dzpg^(ڀ5Nf-uzz {llj#vmg2;m^;{ooZC8pǞ;p<ܯ|rorXآp)a-|t05lSWS JކУt2pW$P ]Oj)@bcܣ_jȁz񂜂*7]7(h{/.AXe<_}p9 G, `B W8tSU @;ߋP2#@ưf  1PTC* %.<p=-XE`d @P["]d6 СPa` uQmX1<&l@ c0h!X+?,WLC yJTaD$&$0`  "B,$2d'2 UR1>#H41W p0IMӘCYtygB\Ԥg=aRAH-hzȁ<%(A 3$P `JDD&u殝y'@Ӟ#%I " Ғ&U"PJ8sK=T* R]U:ȫfUEͯUak[-RֳTs![z׈ehk_hW!zu_zV=a)%WFwelemdֽBVY*gM8 /[IkƶoO}΃عN>z{J[ֶVk{ڀjV˅mc" J@HhC-Ngd-mx0qܸ2WMzZ̀;-3/%t!*,z )-٘dEe_0P{a O<0;ܶ [z\SCiQX1Z7M" @fK" b E! i[ˣE1qvc#ø屏d?L,F'D! N’b>,SVl.da)J` {0@OH;&Z+[\H-}e bI#r *cٝי ܀#p e6F AHQ:5% [0ɀ  0> D@k1m OL^{NShaqR.7P]Zu{Gn:oYVw޿p}\IGq \j>,\cA"쉆Ⴈ÷+B'#D¿QBok'B)2B, C-D./:1\(C{,61tìC=';**C=$>T?ALD]A xB9@T5-+)ݫDK䜩DUCAH: Rѭ>ߊR4EҨ-۩%,!\E6##Jb=. i>E^ 򂎨FbF|,ˮMb2 ` `kK; F0300G:,0@QBkA |q>k>(<HUH[P!4 ,SBH/C5H,TRHȐl=JDIPɉdID\A|R 幨`=(`kH{4Jɔ(cJ''  sc ,Ѵ<4 - ʬLdA*Du1 ! 6Qb+*hL ,x6aK$48=1))G Ҕ$l@lMy4ڴMM:bMNNMM<>rF[hN|NN]r= Ll=v4 0HT"(ϗAx<%lOO"OAf !-p`$,ћ hhD24K! A4kEЕPP;᩠EZ%b"'YƓ QХ)z+5UQ &pQj̐r1ʦ&/<$ ,\+<:B(% BRѱ-1 t*.33e4]6P|ӑ8PpRKlس1xA- [D:Y,|`H`YS T+,cxLݦMNOm RMŪKT(B kKVHH3hHp6FB'-C`M [{J+;VhWwXuiUg ߺUئ\ʲH≽݉FF@]*lmܔڷ[4I[ *1h`E#p:Z&q=@  #\*0 C`L\%]<_[#=EAEPqUW^P C^e`e+QU}=fHW^f^kfg& heiN7jflmn8bof }<.gs^9tFfpwb\z6{gjSKHP; T)ZU> _[!pZgze/ɣ2 کڤ0R"]!_&`&M.Տ^8*",EB-(4K(8r'lTSH'.@ ꋃ k iܦ?bKe^a^=Hgԣ(ȱ&?'x*8?lR}ewꂟfV/N A3!hj i?ZEjacvaJX"x/0>Y ~zzVlŘXoYm.m #.1iz^AQn;kfA}~oufoo7j_w>pHpxfp W٭f p U 'qBw sЅsxE pĕCu( _^q qeqrB@@e/m*Y8|9-YW$3%o/$1i|l.1jzq56FC@|kX)*U.тl) 2Iei"i} R.W8SwC}D/ `hy`QT={@(vHiWuo`C?_,hTkj,!usvNuÇ1*k!/\{#g_hA8[?f:ng lv,&vi %:ENHYmww_*y@ kRIj{YJ-^qo?2:w [G,x8i@x@KҘM鸍 |H|(1v~ky"^@p cXᐍdadedB8MUl>0a ORGuĂ)f/rzuow(/ .v')qf[_kGZ ێ|iʿ/ϗY?pȆouO(1׏ٗuԷ}}לc, G9opm=pe߬%|I _nZ@ 1[A PA(`  B !h>rt@#Ȑ"G,i$ʔ*Wl%̘-PA71B-j(ҤJ2m)ԨRRj*֬Zr+ذbb=)a@H#@  k   H$2A,|R*ydRl2̚71` P1dWn5زgӮmT :@,@X<@F IdowǓ/o^a#+a1/bȐI7?6 qt"E-D~BwAvDy!!~ ^|՗Z-"18#[ U8ETH4 @ZD@B}In 8Hi7@"Zy%Yd. Džx&i&mV5 D'B,`Xu YMW em8Z*(#]cɢZz)jʚY@B \ )0,8 %A &Qoԛ,B ;lL\B*\aP:,JIP$  m9wVV? \;/!G&,/ fg +f[id6;0[|1Dld21!S14J $D2$0N:錃4\s6 0I34C:,3 0s>78O- uM6E;#8;#*,>9X35H3:s(FBN8;QH >;8T0 >x&(5dC9F1nL02d9y_~M5WstTzf`'2ŋ,9);-̲4ی< bL; T[\s9Rvޓ]i_#.:veo}G1΁ Icᾶ=rO*w9|F6[@snc:muh@W8|΅[Bw3(!yɻ I0(M2X'QpPG6#HF8ȌfchƁioըF:as| CR \ d#iSҖ ;E &>m  _I>C tE@Z=b[ Q $'ZyBQ!4"=Ց$pCŃ!@8,CU= 3/BU,:\`v"໅Q`C@[9`a'  @j['&2b*b6![(6ߑ[?ja$͘4\c6vM5C>d!N$EV)X;Dy=@ ] X0¾uڻQXI8d$:>(ڡ XK'+C/ B x+ʂ` H''q.[A=48;И4VByb`Q @ԙ>e8޼q'tFgR\<<|9Z8 y7؂0&_$< dT&;JRڂ7PܕU>]: &'lTO14)B,L>"b%9 V Z_N"=f.N9,rbzA!Z,lb9j0ăB7 `],FN,V^,N,\(Pg(L;5|v}vJ:‡ "Waa 8U~)=Tjͫb]}ngW•ڃ:Cʃv%CF8*Vѵ7ZU]]63؁߱&+ZגGcc.^ מ@ |'|k2k:L/i9&?!o('چ0m*'ო.閮ƲIB0#}d]-I!-I[Z$Z9^ %V;h:]_W,YƟ'͟ZUBC4`5B/IB B+8;̂b bM+$u#ƒF>P/Vnxڂ-'|J!;:EVu.]ԥ 5,>2(re"qOzm p/%o(V2#Ua-\r@ t (!";/XN4h/=e6Bү;(-84XU-,Dô.pqI"zkp;޿=c1j sA -JB:a72/[$4"!4@dd5"$) $sLX5s*$3!)X17 (]4D "C.BC)$ Q\Q B> BQ? lg @sQȀ,(QՔ8Ղ"4d2߭1O!\E-e0'E -Tf9O@+$"4";L3P214W!Xs B%OSp1@*%5,@Q(/p5$U,4QȂ,^﵁$5/h3;/*]Q>(]b&QavW!i_FQ :[bM.тq:-it UShS- .̘:k5`w5_8S;B4B/H4QHgc;8QRLѲTj.Yjޕ%>7 E V5iwU8B;6 50VaTQxM 1^1BqQ AU0Û]b4CR>8Mn1 @QlAxi0z%jcMw?y5W mUEG޴zj5O8^r/:_$$3= 4> 0"Yxj2C128vaR6ĂQ<5';Aj$>A wCUQkxr.:V[V7,xQ3>xGOK%C1<9Ęz0TRβMXV20QVlO=շI_9d/|mt|SXɏK׳<)81Kc Rs (2hЧ "0 ҇Wz^7W107 J30!MXqb܃U`0d:/9$˷,)I94#89tRAҠЧ>P S58PjY=>G?D71ۆRj}[;ëa>>O7:R%0l>?PD5r3xaB 64b!*嫝/dH#I4yeJ+YtfL3iִygN;y-ZР]yiRK6ujTSVzUalްaʮ(Vcɖ5{mZkٶm_פo^{pZ:7vrdɓ)@B =D]F}H%J-L5ݔN=PERM=TU]V]}XeZm\uݕ^}`b=d]f}hjlݖnp #襢p`ʝs+rI]v݅W^z]Xf&j]7{ӽf݂N኏R:-㌙`6hCg:C 9Uj /Pc=lB_9^fq~aME#<#a8Ïxy >/f7ܰ 6Pc55C9 40([@V |0"- /؈#=hڋ/0(@@&:6( 3 .8h-"k|X ү@||i7"q6VC 3p9N T0" ~]Au3@Sg*  \>Αu3arF"mpp82 [8YܶA&8nA\" 67CB)ӺC@tlpݧt]kșxj [<@`-/"hP _ P.\N !Pt8hVGѻ05N @962~`>~7ɄT 0;o/%)&T3aC4-(`.@\`S[lG8.b=U #B>@ ~Pжq XG mTCݸi kw&9J p@Zէ.n@C EwZNYBz*Wi\Wҗv/x@T3Mij!D p6: iU@`0ˡa ; X'< /*8X( h╗f]in yy+Ȍ&n̳& `*dUC `/V4A VłNR-K-/ xxc~U7 \gK ȯÁ :( r`AA@Jiv hXPwy(Vl/{*|-J]lrKf쌠6ġo _M)$qnCKΐj m|%OIԑ|".ʅ:TBPZnP@A ˑ R. Pe.@ @=l!  A Ou0PJs#Q"%2!0!36 } .Q&. $$$D%*1!(I%` aaaZ~aanaQ`%dqya7Z1!b1, ""A!aԡq.đǁa7Aafa`؁$Qb# !^,1J H0 *\Ç#JHŋ3jȱǏ !.Iɓ(S\ɲ˗0cʜSJ8sɳϟ٤IѣH*]Z4'ӧPJJեŪXjʵ&ή`Ê*ٳhӪ5t۷pKݣm˗ažJÈ+(㵋#KLe3k:m֬gСv 3`ȁ;wkfЀ]&N7nV7Ι3f֬U]͵kk~ 3eհ&_ز Ɖ[9q5k.[;v7apdz^:yTsL3H3/S8#}Mc9Ҏ1UM6 3 k]&mfJuYhvZjZlv[6'4pw rÜsE -]w}xc^Ǟ{*G}G[7 h$`5K1`XΆyz*S5A >'7nnj20Nm[6@@ *-PoX3 (";L<RB v8 874wlϬZkP VW-6f+I "}=K誫2j c/+ɾfMY\w<$-\ 5ذ =`vحષ1o+H'M76=Dsvڟ؃a.MߒMϩtN:LM8P*r#̒$e;*гoP]B'Xk{b^5(#ñ% Ђp $ fN)^dG;j6y_#H *AJpJqbZ  "@ XV P$A@qBA% QఆF,q#+sᾒ(YÀO JAPB*`@j $P>HHB b H I 1Zwf^ ,p JHΣ1  d!Xz VP.kNzL`!$kw~)7D#xTt'b xgJ I`6pF/y9X'dh6gnT3!G8ir;ivj[H0A=񰚼mXF`:K#ʣn?A݁P\`F;(DsL l4dmHⳡ< 7`ңF/[I ߐ Ib轋b2BȒD ,0's|mqш 4L9d \2! ,xH,\ )|p " XPF4 38!Lh`r h `lhʘ**2`CG6P:+ D[4RD,"^cNK8j IG:d ||3~ uӑ}qC(yD|C7,nы\P Q g:ր9dA] !.n24WKgӷPN/̳tzCvX5qկ1Keغ~p}pdE;W֬c:q_CY,a We2`oSeM6xF8ѱqh5t`50ǥXi ځĝH8ȱ!C7ތj9Q^kΡ%t;S{7r{,3'v1C:رy-rԹCv,aшFՁQCX*:νm_cx5r#eyL#R@iiOjHŗQ?K~1Ա^y7hyŀSu چea("8ay рiǁA"-wX,#Ur%+؂:X0؃Q!,g57H>K& HဃGVLx!AHQȀFxbXSZX2ᄽ68a8nf0tX%xv|y)ч؇X%1X 8\Ȉ-xh8Hk؊嵊芲8SxTx;(q(H"hǸeȌ(ΨX3Lhȃظ>эM8嘎Xx0؎8sHX"(؏~99i I ɐ yُ)yrI!l#I%c')+-c/ 1^3Y5i7 9yX;ɓ=yS?A)CEiSGIMKiMOQYHS U) BJa[)MQ:UW[ڥ_1$df а$Ҧoq@Gw p.ذːn0 |7&aҥ4 CʰĐ1!e)_2j5a@-A+7 Dž᪰wUR2*Ē*:*/ɺQΪ!@ ` qSj p. %) Wn"axp&2 wiʭ~{Oef)xNg,Pѯ0 ɐi ` K[mb #  qlB G iJߦy{nOP AjH0 P6T8BT3y8p C~I| @e#*-@ b @+P 4In50;#0 *ѷW8pk\S ` {CP¶  ( 0 @C `0ۺ0  {2 KIp]*z&< ʖY Po0~ \5[<  W$ѷDvW KD%@{Qp Su Nv` PvouElF " B %`'?`9 3- ~0 @0k s3p; ` 0 ovI@+xb +@{+?' o `b հps@`2:BlL ͐ v؀'' L (,? +qp @ p  :.u` IğŦR:y G*ŴPz  ` 0Ts#>|Lw  Spڔ3 1Vu/ WRN'/y 6 Gм\ `c5}*?ۢ? * Q@W(]̞F *4ԍ3TR}e vLj4 B`Ƥ; ǰ@P f E٣ B \[1#p s42ҫ$u @ Җ*2]C`)\I_:/6NCݓ #P PM),Ă  -vQ EmU:` Q* ư،"00W 01}f= -NǨ- Уڂ-01լ(ᬘGî}.- ^^ZZ,!s @k `ѥ~pp' :[PcU X0=qZb|0 [1e0*W#tYp!Jِ;1 ڠ., @ @+` S{g P<k ր P Pܐ|YbPkV mV X ZOP CW.ʞ0 _ VJuq+@v"7OR ܩ; T{4k46[vMɓą6B{$ Bwfڃ w5kO|4YmZs P@@Q HڭCd(& ]{PLpCwC]S{<1Eŗ޾5'pdz0PV?)grr1Tsaa#xb̳[߲ƚjF\Eua'iYsQv~fchhai&iFh Fugbg])F#e&jpkYGoQ_P$i +wlYrIڑpEv~a`(wiGLqB:pY$pp o9;7p)ot<y`y2™.k(Kk4agbwy]O0m!sGlF^b.QfvؙŚ]qǘa<QcVgđbj81 e"^E;Q !J_;A@`d9BQ- s;H)1.386]$I(ύs G-ZÆ ꮑ uHp$Apvb"D 0<4&/zkdc8$:1iH %Ř9:Gll $6l8·j s#`6mxl{Y M Z5tT4od96 @ 3jl4 5Y 9e0LJi`cf .cрd`и&WL> RͰ5Q%hAWGюdI>?S !őE6$8BGiXf'PRW'k}{9uXk]׾2 ` &vc`GcNV72{͆ ֑4mL_FLGY@7x,.qOf-G{ncq垣f}ntGkXs(F21#u@#_mΗ%s 1Ykfsf͜Ys3>|g9O И *P9oE㼭_xGa|Rs8,nPnhp\jH`'…_qH!@R%:`Z `*"%wv@1n ZhkVZ`@"y[gXe&y0; YP2Y G :*$2i pQ8e0,qAAYs  (e:v v1w(eXCYЅ[ {(3*Q{N{IA{pjNde$i0@yOVd%/Z(-q%k(p.U'`ؙF0KChAx"(r"5RyׁL}Y| p`w ,N eXjY IpUqa p5Uq%WsIȁBpu )iY0 x|}XPԢLTI R Cq_^1 ȢvՙPnp GpwP","X" sxےX5u̸jwWIZMUHCPZIXPZPK}ӕCoP%JL0hY޼@ ѷx^(Y{m[wXG2j X 9 MD}t@YZ׭%XDZYp]`]i=$ʭ g,(&!\ @EޘxkYH '>*H B>8a|"!RI`!rQMW8VZסQqH]CoH |ֱihxȆ^0Sv(*1 ල@\I@5v(!r[(:vXȅZ  paPTaLZ|}T DMCUu%_'ߋ c`W{N^dyh VdIOP+ >ު0%8WϚv WХnndI0Z|u8!_F6Epp`AFÑoxh^_op}jb?/GpGH՝=upUg  ' & pgq`+qPe0lHEp5/-M[rdxi_p.jҏRT`&Kʌ,ʧ͐* ;aRC`Y0$y"rhzIlv)%Z]o;ss@Ag(CpEFt ٚV:\t_8"vO'Pp ɆSwrHu12_(^Y᲌]=V\w~O xO?LxNOgςgO7' f"*xD-kss ޘ'",M_ A/ Jr]d u v9 hlf`˥ e0f~7x VLo @zz ''<{_(-qfyЙȘjhFPoKJ5hؕ !2|@|T}Ɵk`j0c.IPOn||Xhp*пѧJW}OON|`·FX7'`K@P}IX߄]Oʹ~&bPw~WhY`Qg|,h „ 2l!Ĉ'Rh"ƌ7r#H[*С@@H& #G jCQT)[AS ȝ3Zr+ذbǒ-۵x'Sz*O "F @D4.ITYrXZ&$RV7s3ТEy3qNΝB6푑EM3餐1iqNKw$91,ҧSn:ڷs;{m<قk39`P! z֭Qn ( K,qD Wo Ё"䢈 >P,!T$#P.. R8 c9ᴃ/>Ⓥ/c pBO".K<%< LK.4@"/&L11xl]n#L8Kg@!a,F H*\ȰÇ#JHŋ3jȱǏ CIᑒ(S\ɲ˗0cʜI&#'ɳϟ@ J4(N|:*]ʴӧPJUx4@aLʵׯ`2iu` ZŪ]˶۷p) ڸx˷"E|ga˸ǐ6 :l$̹ϠkRlsLB^ͺ뇄|9 ^ͻwPT\H(ȓ+_>U,3` ,سk3URhB(>ӫ_Ͼ˟OϿ(h& 6F(Vhfv ($h(,0(4h8<@)DiH&L6PF)TViXf\v`)dihlp)tix|矀*蠄j衈&袌6裐F*餔Vj饘f馜v駠*ꨤjꩨꪬ꫰*무j뭸뮼+찬O2\:G "P %0 uI$(8芊.I[.ⴃ\0'@~R#4кܖ[>к Iׇ woh68O$` Am`?OQCL>O (Nc  N9I`w?0P5E(X4`T>v & EpDDځ-spыձpXK֒Y8h]QZ#XF3XY-71dpS;rAv抗/̑ 4n3"|ODCHKʒC!Ix ѓe%ma|%*1Lf!E,%)I 0IbL2f:Ќ4IjZ̦6nz 8IrL:v~ @JЂMBІ:D'JъZͨF7юz HGJҒ(MJWҖ0LgJӚ8ͩNwӞ@ PJԢHMRԦ:PTՆ6 m`|h!X" a- \hJ3Lu;UjVj-`AXi%kU\:׻jUW? y ŲA 8WղdU>ѪժZ 㵰]Jתj <\ MkbA\,e5\, m^0\!uvׯxZwV=-56c}U V|U-(p]U0rА@,p \FwzhDF. | ԻiÉKa^4E3 w8= h !ȀBč TA7wsw88qqЌ7-gc@F1=Y\̀8횀!1,/ H*\ȰÇ#>5ŋ3jȱǏ CIɓ(Sjė0cʜI͛8sɳ'ŕ@ JѣA[\ʴӧPJիXj*T)կ`ÊK,ӟ\^]%j,Wx˷/NŸmX-|x!p/2\rŀ&WfN14*C69yd@K۸Rd Vl-)XF˟[g2!l=9vEp>37dVT@]iV1Qq[L紮]s^GpV2FRƚ}e^vTw 0ef1-'tt a/.)9ЩrQwluf७-ᕰ9GmmY߫oԪ"2aԽ\sFtl1O[$om.wߟdܠݣ>cfd -loϓFb-!$@Qp s@մqx󄐠YF9\Wi<l{QYH;ѐ֛e_B#jI@ 5) aFcR0>oGJp$2k|`/![R%)H ]1c෽HY jQ|E`|Ĕu.vF-J5qf$ɜMVgӣv :f6I`F3$(#0% ][v1 . I^j7Kh zK[D jnzsdh8IrL:NsIйz37픧>Ox ^ςW@ЯDKІZKyD7юn~ HQHW҉0M)H[JӚF1ͩNR8ݩP:TXE8*XJԦ:3U*܊HU*L}V^KMWU^k} ց@ LPkNzֺ65r!aՂ{ͫMjM(#"5!a'RB6DW|L+dqYHeKۗT~B`mLNBt +K\Y} o}~7f!nq;\޴}s;׸e>݆,75v ׸eyK߉Wy_7~KF5ր 76˂La<8˄+얬1V#ILBNzDBœ=އ,?.R4yTP!O$S<^ŝ1VU/*G#1FeGP# RBd0GEUI(d(9B+IhA%ʈOtʈ)r4 p #I%g*oNʴ5@!Zېԛޜ0PX_˜&M2NNgR Xu& ™-#PNͩlH@ۢvː̳-%B^5- )F3R^\lإ!CkѩݘPTI^M녍▴vZ3F|v=gO`arB%WgSLwtJڕup{ wM6a|;*FlYo zɤKFs;gITL(g3KG6.grIhH0vDO'|aBu}B(sV8nHxVJׄ\pQTSHfY\8`xddfhkXcm`qbsG$PiՇewayxW2Zx/{b8cHvr7Q(1tc޳(T8C?҉{c#b6Edqv$x(=2*U4{$r8GËEgwAf8 #uAE- hTTׂшdmtFmӣ-2AVxggibq:HAL&@gkL~dBvL!AgKxд. @q6V1_MIq-'3xkHK/r9= 4ֈnڂEq! 7bBcmBdC)?Ϩ"9% @/:*vcYxb|ZvJ93c,{C5֒@s$t7dw!j|&~} #_Foi>s:Čyr!0*vD7Ixi2B3t;6b8GLu!'S Qwܗ9&  ă!S#A"hňvKBÁ:AE+QzGI78s"=i霡gwәqNg4JJA8dׂvr&GGVz*F١ $2w7C(j2] UF{ Suq7&Lٌ+WX%`VP%r KWOJRz`j:>zI鞋+NjS0S BV IҤ|CC8D()3',#Q=ӞR*5{&R&[c{E @qgee"(aŤM:bZ0qI~sd0*pEH0Z˪ꬕڅֺ) Yʭ*X*E*W犮:VM*s8\ʯJ0{ fKDqa ˰&SM;k k aC![[-+K2uw3++ 9?K6R6H۳C/ŘM5챕z˙ŒɈ5OL«k$b˫ OћKCxj LkcԐ&M+gkt99&8K+A!GYyC G. H"j  8WY-=/p/~dLܸ£ ?XgeA m,lj!Z6FPE>3>,g 03<wx9^Z;\,a-9Fl\iTD.S#?rib zǷFe.48܈'rbC#Wtɧypj/Jɚ7\LHAyi FD(JC>Zd @Q+dKD )0D @5l.j|o˅6Rb+w20+v:dʇzl|Û6sJ.ū?庯{X 6SL!cmh^? (*.0`4]6}:<}76-0=.-@}=:}@-D=F8I-7OQm4MU4]00 Ӏ P $]p pr=tm;-u=wy9ׁM؆v} xM؅ - 0 j]ڥ}׏-ًիدMճ׷Ի]׿& m-ڣmڦږ}ÍMǍ} ؔ-rm]ɽ ]ӽߺ ߕ].m Y> =N᪭ N.%j5> P6>*)`>~0=:^ "P$ F% 䁠,"P.\~Y-n僐"[f.W_a>PppSY. bN=q4Vnl|># *L#eNھ蒾 4.P`镮t겮N=>H.D>^~Ȟʾ>^~؞ھ>^~>^~?_ ?_ "?$_&(*,.02?4_68:<>@B?D_FHJLNPR?T_VXZ\^`b?d_fhjlnpюy^F`_w~0eg|u_\pnwl`jk mGvzuCepaPj`\ w^@vghyT9@G,A@Z~pZW0ylj/s^hk{`0WZtȯ!?o/pmwrWh ! % pJ3flG!E$YI)UdK1eΤYM9ug6n %E Bd?]hpʁW)"F%[Yiծe[5l$]e !,ji`JUb`"_$ǥ\e̙5oyܺwݫ_r@/XϹuo '>4#l@1VpCk8dō=Nۛ5v5R k& 6F(48NiG]|3L_\ȍAE_X4< >~)ԗ_#cXw;bR<CSmݸvIB Y4x^6McP2C]J`)dihم!^}b$ ٳ֒"A3(P ݈OhM?) F*PJ"V;#%J^%>_ ԉ꫰*c҃З1 BF3@J;y"/2PA,ŗ7,K1+>%CDKA&MG+ +j<S#l<ZP ѣ3 ()$@$2`[q#0߆;@ Duк+0,4l3Bx DBA+ E/>B XA#;:PJA];=R '/ PD ]c)tmxKMBTtA5>8NA)k]OAtLOvBbD m0<ް.NA` {;B@ˍ}:AǼO6KWbi3 8weܸ D>< ;A n!T0G8 =5&5 a3PVM PH6