summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--.clang-tidy1
-rw-r--r--.codespellrc4
-rw-r--r--.gitlab-ci.yml98
-rw-r--r--.gitlab/ci/configure_fedora37_clang_analyzer.cmake1
-rw-r--r--.gitlab/ci/configure_fedora37_makefiles_clang.cmake1
-rw-r--r--.gitlab/ci/configure_fedora37_ninja_clang.cmake1
-rw-r--r--.gitlab/ci/configure_fedora38_asan.cmake (renamed from .gitlab/ci/configure_fedora37_asan.cmake)2
-rw-r--r--.gitlab/ci/configure_fedora38_clang_analyzer.cmake3
-rw-r--r--.gitlab/ci/configure_fedora38_common.cmake (renamed from .gitlab/ci/configure_fedora37_common.cmake)0
-rw-r--r--.gitlab/ci/configure_fedora38_common_clang.cmake (renamed from .gitlab/ci/configure_fedora37_common_clang.cmake)0
-rw-r--r--.gitlab/ci/configure_fedora38_extdeps.cmake (renamed from .gitlab/ci/configure_fedora37_extdeps.cmake)0
-rw-r--r--.gitlab/ci/configure_fedora38_makefiles.cmake (renamed from .gitlab/ci/configure_fedora37_makefiles.cmake)0
-rw-r--r--.gitlab/ci/configure_fedora38_makefiles_clang.cmake1
-rw-r--r--.gitlab/ci/configure_fedora38_ninja.cmake (renamed from .gitlab/ci/configure_fedora37_ninja.cmake)2
-rw-r--r--.gitlab/ci/configure_fedora38_ninja_clang.cmake (renamed from .gitlab/ci/configure_linux_clang_cxx_modules_ninja.cmake)2
-rw-r--r--.gitlab/ci/configure_fedora38_ninja_multi.cmake (renamed from .gitlab/ci/configure_fedora37_ninja_multi.cmake)0
-rw-r--r--.gitlab/ci/configure_fedora38_ninja_multi_clang.cmake (renamed from .gitlab/ci/configure_linux_clang_cxx_modules_ninja_multi.cmake)2
-rw-r--r--.gitlab/ci/configure_fedora38_sphinx.cmake (renamed from .gitlab/ci/configure_fedora37_sphinx.cmake)0
-rw-r--r--.gitlab/ci/configure_fedora38_sphinx_package.cmake (renamed from .gitlab/ci/configure_fedora37_sphinx_package.cmake)0
-rw-r--r--.gitlab/ci/configure_fedora38_tidy.cmake (renamed from .gitlab/ci/configure_fedora37_tidy.cmake)2
-rw-r--r--.gitlab/ci/ctest_memcheck_fedora38_asan.lsan.supp (renamed from .gitlab/ci/ctest_memcheck_fedora37_asan.lsan.supp)0
-rw-r--r--.gitlab/ci/docker/clang_cxx_modules/Dockerfile13
-rwxr-xr-x.gitlab/ci/docker/clang_cxx_modules/install_cmake_deps.sh7
-rwxr-xr-x.gitlab/ci/docker/clang_cxx_modules/install_deps.sh7
-rwxr-xr-x.gitlab/ci/docker/clang_cxx_modules/install_llvm.sh39
-rw-r--r--.gitlab/ci/docker/fedora38/Dockerfile (renamed from .gitlab/ci/docker/fedora37/Dockerfile)2
-rw-r--r--.gitlab/ci/docker/fedora38/deps_packages.lst (renamed from .gitlab/ci/docker/fedora37/deps_packages.lst)1
-rwxr-xr-x.gitlab/ci/docker/fedora38/install_deps.sh (renamed from .gitlab/ci/docker/fedora37/install_deps.sh)0
-rwxr-xr-x.gitlab/ci/docker/fedora38/install_iwyu.sh (renamed from .gitlab/ci/docker/fedora37/install_iwyu.sh)0
-rwxr-xr-x.gitlab/ci/docker/fedora38/install_rvm.sh (renamed from .gitlab/ci/docker/fedora37/install_rvm.sh)0
-rw-r--r--.gitlab/ci/docker/fedora38/iwyu_packages.lst (renamed from .gitlab/ci/docker/fedora37/iwyu_packages.lst)0
-rw-r--r--.gitlab/ci/docker/fedora38/rvm_packages.lst (renamed from .gitlab/ci/docker/fedora37/rvm_packages.lst)0
-rw-r--r--.gitlab/ci/env_fedora37_makefiles_clang.sh1
-rw-r--r--.gitlab/ci/env_fedora37_ninja_clang.sh1
-rw-r--r--.gitlab/ci/env_fedora38_asan.sh (renamed from .gitlab/ci/env_fedora37_asan.sh)0
-rw-r--r--.gitlab/ci/env_fedora38_clang_analyzer.sh (renamed from .gitlab/ci/env_fedora37_clang_analyzer.sh)0
-rw-r--r--.gitlab/ci/env_fedora38_common_clang.sh (renamed from .gitlab/ci/env_fedora37_common_clang.sh)4
-rw-r--r--.gitlab/ci/env_fedora38_extdeps.sh (renamed from .gitlab/ci/env_fedora37_extdeps.sh)0
-rw-r--r--.gitlab/ci/env_fedora38_makefiles.cmake (renamed from .gitlab/ci/env_fedora37_makefiles.cmake)0
-rw-r--r--.gitlab/ci/env_fedora38_makefiles.sh (renamed from .gitlab/ci/env_fedora37_makefiles.sh)0
-rw-r--r--.gitlab/ci/env_fedora38_makefiles_clang.sh1
-rw-r--r--.gitlab/ci/env_fedora38_ninja.sh (renamed from .gitlab/ci/env_fedora37_ninja_multi.sh)0
-rw-r--r--.gitlab/ci/env_fedora38_ninja_clang.sh1
-rw-r--r--.gitlab/ci/env_fedora38_ninja_multi.sh (renamed from .gitlab/ci/env_fedora37_ninja.sh)0
-rw-r--r--.gitlab/ci/env_fedora38_ninja_multi_clang.sh1
-rwxr-xr-x.gitlab/ci/extdeps-linux.sh19
-rw-r--r--.gitlab/ci/pre_build_fedora38_tidy.sh (renamed from .gitlab/ci/pre_build_fedora37_tidy.sh)0
-rw-r--r--.gitlab/os-linux.yml105
-rw-r--r--.gitlab/upload.yml4
-rw-r--r--CMakeLists.txt25
-rw-r--r--Help/command/configure_file.rst8
-rw-r--r--Help/command/include_directories.rst2
-rw-r--r--Help/envvar/CMAKE_LANG_IMPLICIT_LINK_DIRECTORIES_EXCLUDE.rst13
-rw-r--r--Help/guide/importing-exporting/index.rst9
-rw-r--r--Help/manual/cmake-env-variables.7.rst1
-rw-r--r--Help/manual/cmake-file-api.7.rst24
-rw-r--r--Help/manual/cmake.1.rst53
-rw-r--r--Help/release/dev/FileAPI-Frameworks.rst7
-rw-r--r--Help/release/dev/cmake-debugger.rst5
-rw-r--r--Help/release/dev/cmake-verbose-print-build-tool-command.rst5
-rw-r--r--Help/release/dev/ep-update-disconnected.rst14
-rw-r--r--Help/variable/CMAKE_LANG_IMPLICIT_LINK_DIRECTORIES.rst7
-rw-r--r--Help/variable/MINGW.rst5
-rw-r--r--Modules/CMakeASMCompiler.cmake.in2
-rw-r--r--Modules/CMakeCCompiler.cmake.in2
-rw-r--r--Modules/CMakeCUDACompiler.cmake.in2
-rw-r--r--Modules/CMakeCXXCompiler.cmake.in2
-rw-r--r--Modules/CMakeDetermineCompilerABI.cmake6
-rw-r--r--Modules/CMakeFindBinUtils.cmake2
-rw-r--r--Modules/CMakeFortranCompiler.cmake.in2
-rw-r--r--Modules/CMakeHIPCompiler.cmake.in2
-rw-r--r--Modules/CMakeOBJCCompiler.cmake.in2
-rw-r--r--Modules/CMakeOBJCXXCompiler.cmake.in2
-rw-r--r--Modules/CMakePackageConfigHelpers.cmake2
-rw-r--r--Modules/CPackComponent.cmake2
-rw-r--r--Modules/Compiler/Clang-HIP.cmake8
-rw-r--r--Modules/Compiler/GNU.cmake5
-rw-r--r--Modules/ExternalProject.cmake107
-rw-r--r--Modules/ExternalProject/PatchInfo.txt.in6
-rw-r--r--Modules/ExternalProject/UpdateInfo.txt.in7
-rw-r--r--Modules/ExternalProject/gitupdate.cmake.in59
-rw-r--r--Modules/FetchContent.cmake23
-rw-r--r--Modules/FindCUDA.cmake2
-rw-r--r--Modules/FindMPI.cmake2
-rw-r--r--Modules/FindMatlab.cmake2
-rw-r--r--Modules/FindOpenGL.cmake2
-rw-r--r--Modules/FindOpenSSL.cmake26
-rw-r--r--Modules/FindwxWindows.cmake2
-rw-r--r--Modules/Internal/CPack/CPackRPM.cmake2
-rw-r--r--Modules/Platform/Windows-IntelLLVM.cmake1
-rw-r--r--Source/CMakeLists.txt32
-rw-r--r--Source/CMakeVersion.cmake2
-rw-r--r--Source/CPack/cmCPackInnoSetupGenerator.cxx2
-rw-r--r--Source/CTest/cmCTestBuildAndTestHandler.cxx4
-rw-r--r--Source/CursesDialog/form/frm_def.c4
-rw-r--r--Source/Modules/CMakeBuildUtilities.cmake16
-rw-r--r--Source/cmCMakeLanguageCommand.cxx2
-rw-r--r--Source/cmCPluginAPI.cxx6
-rw-r--r--Source/cmCPluginAPI.h2
-rw-r--r--Source/cmCacheManager.cxx37
-rw-r--r--Source/cmCacheManager.h5
-rw-r--r--Source/cmCommandArgumentParserHelper.cxx3
-rw-r--r--Source/cmCommonTargetGenerator.cxx2
-rw-r--r--Source/cmConditionEvaluator.cxx4
-rw-r--r--Source/cmConfigure.cmake.h.in1
-rw-r--r--Source/cmCustomCommandGenerator.cxx6
-rw-r--r--Source/cmDebuggerAdapter.cxx462
-rw-r--r--Source/cmDebuggerAdapter.h93
-rw-r--r--Source/cmDebuggerBreakpointManager.cxx200
-rw-r--r--Source/cmDebuggerBreakpointManager.h61
-rw-r--r--Source/cmDebuggerExceptionManager.cxx129
-rw-r--r--Source/cmDebuggerExceptionManager.h70
-rw-r--r--Source/cmDebuggerPipeConnection.cxx293
-rw-r--r--Source/cmDebuggerPipeConnection.h139
-rw-r--r--Source/cmDebuggerProtocol.cxx80
-rw-r--r--Source/cmDebuggerProtocol.h191
-rw-r--r--Source/cmDebuggerSourceBreakpoint.cxx14
-rw-r--r--Source/cmDebuggerSourceBreakpoint.h26
-rw-r--r--Source/cmDebuggerStackFrame.cxx28
-rw-r--r--Source/cmDebuggerStackFrame.h33
-rw-r--r--Source/cmDebuggerThread.cxx150
-rw-r--r--Source/cmDebuggerThread.h59
-rw-r--r--Source/cmDebuggerThreadManager.cxx47
-rw-r--r--Source/cmDebuggerThreadManager.h38
-rw-r--r--Source/cmDebuggerVariables.cxx133
-rw-r--r--Source/cmDebuggerVariables.h124
-rw-r--r--Source/cmDebuggerVariablesHelper.cxx644
-rw-r--r--Source/cmDebuggerVariablesHelper.h106
-rw-r--r--Source/cmDebuggerVariablesManager.cxx38
-rw-r--r--Source/cmDebuggerVariablesManager.h40
-rw-r--r--Source/cmDependsFortran.cxx2
-rw-r--r--Source/cmDependsJavaParserHelper.cxx2
-rw-r--r--Source/cmDyndepCollation.cxx4
-rw-r--r--Source/cmExportBuildFileGenerator.cxx6
-rw-r--r--Source/cmExportInstallFileGenerator.cxx6
-rw-r--r--Source/cmExternalMakefileProjectGenerator.cxx13
-rw-r--r--Source/cmFileAPI.cxx2
-rw-r--r--Source/cmFileAPICodemodel.cxx48
-rw-r--r--Source/cmFindPackageCommand.cxx10
-rw-r--r--Source/cmGeneratorTarget.cxx22
-rw-r--r--Source/cmGetTestPropertyCommand.cxx2
-rw-r--r--Source/cmGlobalCommonGenerator.cxx6
-rw-r--r--Source/cmGlobalGenerator.cxx89
-rw-r--r--Source/cmGlobalGenerator.h29
-rw-r--r--Source/cmGlobalGhsMultiGenerator.cxx10
-rw-r--r--Source/cmGlobalVisualStudio7Generator.cxx2
-rw-r--r--Source/cmMakefile.cxx99
-rw-r--r--Source/cmMakefile.h7
-rw-r--r--Source/cmMakefileLibraryTargetGenerator.cxx2
-rw-r--r--Source/cmMessageCommand.cxx11
-rw-r--r--Source/cmMessenger.cxx63
-rw-r--r--Source/cmMessenger.h17
-rw-r--r--Source/cmOutputConverter.cxx15
-rw-r--r--Source/cmOutputConverter.h1
-rw-r--r--Source/cmPropertyMap.cxx9
-rw-r--r--Source/cmPropertyMap.h3
-rw-r--r--Source/cmQtAutoMocUic.cxx7
-rw-r--r--Source/cmSourceFile.cxx12
-rw-r--r--Source/cmSourceFile.h6
-rw-r--r--Source/cmState.cxx23
-rw-r--r--Source/cmState.h2
-rw-r--r--Source/cmStateDirectory.cxx16
-rw-r--r--Source/cmStateDirectory.h8
-rw-r--r--Source/cmTarget.cxx32
-rw-r--r--Source/cmTarget.h5
-rw-r--r--Source/cmTest.cxx4
-rw-r--r--Source/cmTest.h6
-rw-r--r--Source/cmUVProcessChain.cxx69
-rw-r--r--Source/cmUVProcessChain.h4
-rw-r--r--Source/cmake.cxx173
-rw-r--r--Source/cmake.h36
-rw-r--r--Source/cmakemain.cxx6
-rw-r--r--Source/kwsys/RegularExpression.cxx4
-rw-r--r--Source/kwsys/SystemInformation.cxx4
-rw-r--r--Tests/CMakeLib/CMakeLists.txt26
-rw-r--r--Tests/CMakeLib/DebuggerSample/CMakeLists.txt9
-rw-r--r--Tests/CMakeLib/DebuggerSample/script.cmake1
-rw-r--r--Tests/CMakeLib/testCommon.h30
-rw-r--r--Tests/CMakeLib/testDebugger.h99
-rw-r--r--Tests/CMakeLib/testDebuggerAdapter.cxx173
-rw-r--r--Tests/CMakeLib/testDebuggerAdapterPipe.cxx184
-rw-r--r--Tests/CMakeLib/testDebuggerBreakpointManager.cxx172
-rw-r--r--Tests/CMakeLib/testDebuggerNamedPipe.cxx218
-rw-r--r--Tests/CMakeLib/testDebuggerVariables.cxx185
-rw-r--r--Tests/CMakeLib/testDebuggerVariablesHelper.cxx587
-rw-r--r--Tests/CMakeLib/testDebuggerVariablesManager.cxx50
-rw-r--r--Tests/CMakeLib/testUVProcessChain.cxx122
-rw-r--r--Tests/CMakeLib/testUVProcessChainHelper.cxx7
-rw-r--r--Tests/Cuda/Complex/CMakeLists.txt3
-rw-r--r--Tests/CudaOnly/SharedRuntimePlusToolkit/CMakeLists.txt3
-rw-r--r--Tests/CudaOnly/SharedRuntimeViaCUDAFlags/CMakeLists.txt3
-rw-r--r--Tests/CudaOnly/StaticRuntimePlusToolkit/CMakeLists.txt3
-rw-r--r--Tests/ExternalProjectUpdate/CMakeLists.txt5
-rw-r--r--Tests/ExternalProjectUpdate/ExternalProjectUpdateTest.cmake42
-rw-r--r--Tests/FindOpenAL/Test/main.cxx5
-rw-r--r--Tests/Module/ExternalData/Data1Check.cmake26
-rw-r--r--Tests/Module/ExternalData/Data2/Data2Check.cmake4
-rw-r--r--Tests/Module/ExternalData/Data3/Data3Check.cmake4
-rw-r--r--Tests/Module/ExternalData/Data4/Data4Check.cmake4
-rw-r--r--Tests/Module/ExternalData/Data5/Data5Check.cmake2
-rw-r--r--Tests/Module/ExternalData/DataNoSymlinks/DataNoSymlinksCheck.cmake2
-rw-r--r--Tests/QtAutogen/AutoMocGeneratedFile/CMakeLists.txt23
-rw-r--r--Tests/QtAutogen/AutoMocGeneratedFile/main.cpp7
-rw-r--r--Tests/QtAutogen/Tests.cmake1
-rw-r--r--Tests/RunCMake/CXXModules/examples/export-bmi-and-interface-build-stderr.txt2
-rw-r--r--Tests/RunCMake/CXXModules/examples/export-bmi-and-interface-build/CMakeLists.txt8
-rw-r--r--Tests/RunCMake/CXXModules/examples/export-bmi-and-interface-build/no_modules.cxx3
-rw-r--r--Tests/RunCMake/CXXModules/examples/export-bmi-and-interface-build/subdir/importable.cxx6
-rw-r--r--Tests/RunCMake/CXXModules/examples/export-bmi-and-interface-build/test/CMakeLists.txt22
-rw-r--r--Tests/RunCMake/CXXModules/examples/export-bmi-and-interface-install-stderr.txt2
-rw-r--r--Tests/RunCMake/CXXModules/examples/export-bmi-and-interface-install/CMakeLists.txt8
-rw-r--r--Tests/RunCMake/CXXModules/examples/export-bmi-and-interface-install/no_modules.cxx3
-rw-r--r--Tests/RunCMake/CXXModules/examples/export-bmi-and-interface-install/subdir/importable.cxx6
-rw-r--r--Tests/RunCMake/CXXModules/examples/export-bmi-and-interface-install/test/CMakeLists.txt22
-rw-r--r--Tests/RunCMake/CXXModules/examples/export-interface-build-stderr.txt2
-rw-r--r--Tests/RunCMake/CXXModules/examples/export-interface-build/CMakeLists.txt8
-rw-r--r--Tests/RunCMake/CXXModules/examples/export-interface-build/no_modules.cxx3
-rw-r--r--Tests/RunCMake/CXXModules/examples/export-interface-build/subdir/importable.cxx6
-rw-r--r--Tests/RunCMake/CXXModules/examples/export-interface-build/test/CMakeLists.txt22
-rw-r--r--Tests/RunCMake/CXXModules/examples/export-interface-install-stderr.txt2
-rw-r--r--Tests/RunCMake/CXXModules/examples/export-interface-install/CMakeLists.txt8
-rw-r--r--Tests/RunCMake/CXXModules/examples/export-interface-install/no_modules.cxx3
-rw-r--r--Tests/RunCMake/CXXModules/examples/export-interface-install/subdir/importable.cxx6
-rw-r--r--Tests/RunCMake/CXXModules/examples/export-interface-install/test/CMakeLists.txt22
-rw-r--r--Tests/RunCMake/CXXModules/examples/export-interface-no-properties-build-stderr.txt2
-rw-r--r--Tests/RunCMake/CXXModules/examples/export-interface-no-properties-build/CMakeLists.txt8
-rw-r--r--Tests/RunCMake/CXXModules/examples/export-interface-no-properties-build/no_modules.cxx3
-rw-r--r--Tests/RunCMake/CXXModules/examples/export-interface-no-properties-build/subdir/importable.cxx6
-rw-r--r--Tests/RunCMake/CXXModules/examples/export-interface-no-properties-build/test/CMakeLists.txt10
-rw-r--r--Tests/RunCMake/CXXModules/examples/export-interface-no-properties-install-stderr.txt2
-rw-r--r--Tests/RunCMake/CXXModules/examples/export-interface-no-properties-install/CMakeLists.txt8
-rw-r--r--Tests/RunCMake/CXXModules/examples/export-interface-no-properties-install/no_modules.cxx3
-rw-r--r--Tests/RunCMake/CXXModules/examples/export-interface-no-properties-install/subdir/importable.cxx6
-rw-r--r--Tests/RunCMake/CXXModules/examples/export-interface-no-properties-install/test/CMakeLists.txt10
-rw-r--r--Tests/RunCMake/CheckModules/CheckStructHasMemberWrongKey-stderr.txt2
-rw-r--r--Tests/RunCMake/CheckModules/CheckStructHasMemberWrongKey.cmake2
-rw-r--r--Tests/RunCMake/CheckModules/CheckTypeSizeUnknownArgument-stderr.txt2
-rw-r--r--Tests/RunCMake/CheckModules/CheckTypeSizeUnknownArgument.cmake2
-rw-r--r--Tests/RunCMake/CommandLine/DebuggerArgMissingDapLog-result.txt1
-rw-r--r--Tests/RunCMake/CommandLine/DebuggerArgMissingDapLog-stderr.txt2
-rw-r--r--Tests/RunCMake/CommandLine/DebuggerArgMissingDapLog.cmake1
-rw-r--r--Tests/RunCMake/CommandLine/DebuggerArgMissingPipe-result.txt1
-rw-r--r--Tests/RunCMake/CommandLine/DebuggerArgMissingPipe-stderr.txt2
-rw-r--r--Tests/RunCMake/CommandLine/DebuggerArgMissingPipe.cmake1
-rw-r--r--Tests/RunCMake/CommandLine/DebuggerCapabilityInspect-check.cmake5
-rw-r--r--Tests/RunCMake/CommandLine/DebuggerNotSupported-result.txt1
-rw-r--r--Tests/RunCMake/CommandLine/DebuggerNotSupported-stderr.txt2
-rw-r--r--Tests/RunCMake/CommandLine/DebuggerNotSupported.cmake1
-rw-r--r--Tests/RunCMake/CommandLine/DebuggerNotSupportedDapLog-result.txt1
-rw-r--r--Tests/RunCMake/CommandLine/DebuggerNotSupportedDapLog-stderr.txt2
-rw-r--r--Tests/RunCMake/CommandLine/DebuggerNotSupportedDapLog.cmake1
-rw-r--r--Tests/RunCMake/CommandLine/DebuggerNotSupportedPipe-result.txt1
-rw-r--r--Tests/RunCMake/CommandLine/DebuggerNotSupportedPipe-stderr.txt2
-rw-r--r--Tests/RunCMake/CommandLine/DebuggerNotSupportedPipe.cmake1
-rw-r--r--Tests/RunCMake/CommandLine/E_capabilities-stdout.txt2
-rw-r--r--Tests/RunCMake/CommandLine/RunCMakeTest.cmake11
-rw-r--r--Tests/RunCMake/CompileFeatures/RunCMakeTest.cmake2
-rw-r--r--Tests/RunCMake/FileAPI/codemodel-v2-check.py65
-rw-r--r--Tests/RunCMake/FileAPI/codemodel-v2-data/directories/framework.json17
-rw-r--r--Tests/RunCMake/FileAPI/codemodel-v2-data/directories/top.json29
-rw-r--r--Tests/RunCMake/FileAPI/codemodel-v2-data/projects/codemodel-v2.json3
-rw-r--r--Tests/RunCMake/FileAPI/codemodel-v2-data/projects/framework.json15
-rw-r--r--Tests/RunCMake/FileAPI/codemodel-v2-data/targets/all_build_framework.json90
-rw-r--r--Tests/RunCMake/FileAPI/codemodel-v2-data/targets/all_build_top.json12
-rw-r--r--Tests/RunCMake/FileAPI/codemodel-v2-data/targets/apple_exe_framework.json79
-rw-r--r--Tests/RunCMake/FileAPI/codemodel-v2-data/targets/apple_shared_framework.json9
-rw-r--r--Tests/RunCMake/FileAPI/codemodel-v2-data/targets/apple_static_framework.json9
-rw-r--r--Tests/RunCMake/FileAPI/codemodel-v2-data/targets/c_alias_exe.json1
-rw-r--r--Tests/RunCMake/FileAPI/codemodel-v2-data/targets/c_exe.json1
-rw-r--r--Tests/RunCMake/FileAPI/codemodel-v2-data/targets/c_headers_1.json1
-rw-r--r--Tests/RunCMake/FileAPI/codemodel-v2-data/targets/c_headers_2.json1
-rw-r--r--Tests/RunCMake/FileAPI/codemodel-v2-data/targets/c_lib.json1
-rw-r--r--Tests/RunCMake/FileAPI/codemodel-v2-data/targets/c_object_exe.json1
-rw-r--r--Tests/RunCMake/FileAPI/codemodel-v2-data/targets/c_object_lib.json1
-rw-r--r--Tests/RunCMake/FileAPI/codemodel-v2-data/targets/c_shared_exe.json1
-rw-r--r--Tests/RunCMake/FileAPI/codemodel-v2-data/targets/c_shared_lib.json7
-rw-r--r--Tests/RunCMake/FileAPI/codemodel-v2-data/targets/c_static_exe.json1
-rw-r--r--Tests/RunCMake/FileAPI/codemodel-v2-data/targets/c_static_lib.json1
-rw-r--r--Tests/RunCMake/FileAPI/codemodel-v2-data/targets/c_subdir.json1
-rw-r--r--Tests/RunCMake/FileAPI/codemodel-v2-data/targets/custom_exe.json1
-rw-r--r--Tests/RunCMake/FileAPI/codemodel-v2-data/targets/cxx_alias_exe.json1
-rw-r--r--Tests/RunCMake/FileAPI/codemodel-v2-data/targets/cxx_exe.json3
-rw-r--r--Tests/RunCMake/FileAPI/codemodel-v2-data/targets/cxx_exe_precompileheader.json2
-rw-r--r--Tests/RunCMake/FileAPI/codemodel-v2-data/targets/cxx_exe_precompileheader_2arch.json3
-rw-r--r--Tests/RunCMake/FileAPI/codemodel-v2-data/targets/cxx_exe_precompileheader_multigen.json2
-rw-r--r--Tests/RunCMake/FileAPI/codemodel-v2-data/targets/cxx_lib.json1
-rw-r--r--Tests/RunCMake/FileAPI/codemodel-v2-data/targets/cxx_object_exe.json1
-rw-r--r--Tests/RunCMake/FileAPI/codemodel-v2-data/targets/cxx_object_lib.json1
-rw-r--r--Tests/RunCMake/FileAPI/codemodel-v2-data/targets/cxx_shared_exe.json1
-rw-r--r--Tests/RunCMake/FileAPI/codemodel-v2-data/targets/cxx_shared_lib.json7
-rw-r--r--Tests/RunCMake/FileAPI/codemodel-v2-data/targets/cxx_standard_compile_feature_exe.json1
-rw-r--r--Tests/RunCMake/FileAPI/codemodel-v2-data/targets/cxx_standard_exe.json1
-rw-r--r--Tests/RunCMake/FileAPI/codemodel-v2-data/targets/cxx_static_exe.json1
-rw-r--r--Tests/RunCMake/FileAPI/codemodel-v2-data/targets/cxx_static_lib.json1
-rw-r--r--Tests/RunCMake/FileAPI/codemodel-v2-data/targets/exe_framework.json164
-rw-r--r--Tests/RunCMake/FileAPI/codemodel-v2-data/targets/generated_exe.json2
-rw-r--r--Tests/RunCMake/FileAPI/codemodel-v2-data/targets/interface_exe.json1
-rw-r--r--Tests/RunCMake/FileAPI/codemodel-v2-data/targets/link_imported_exe.json1
-rw-r--r--Tests/RunCMake/FileAPI/codemodel-v2-data/targets/link_imported_interface_exe.json1
-rw-r--r--Tests/RunCMake/FileAPI/codemodel-v2-data/targets/link_imported_object_exe.json1
-rw-r--r--Tests/RunCMake/FileAPI/codemodel-v2-data/targets/link_imported_shared_exe.json1
-rw-r--r--Tests/RunCMake/FileAPI/codemodel-v2-data/targets/link_imported_static_exe.json1
-rw-r--r--Tests/RunCMake/FileAPI/codemodel-v2-data/targets/shared_framework.json102
-rw-r--r--Tests/RunCMake/FileAPI/codemodel-v2-data/targets/static_framework.json87
-rw-r--r--Tests/RunCMake/FileAPI/codemodel-v2-data/targets/zero_check_framework.json73
-rw-r--r--Tests/RunCMake/FileAPI/codemodel-v2.cmake1
-rw-r--r--Tests/RunCMake/FileAPI/framework/CMakeLists.txt17
-rw-r--r--Tests/RunCMake/File_Generate/CMP0070-NEW-check.cmake2
-rw-r--r--Tests/RunCMake/File_Generate/CMP0070-OLD-check.cmake2
-rw-r--r--Tests/RunCMake/File_Generate/CMP0070-WARN-check.cmake2
-rw-r--r--Tests/RunCMake/GenEx-LINK_LIBRARY/RunCMakeTest.cmake2
-rw-r--r--Tests/RunCMake/GeneratorToolset/TestToolsetCustomFlagTableDir-check.cmake2
-rw-r--r--Tests/RunCMake/GoogleTest/GoogleTestXML.cmake4
-rw-r--r--Tests/RunCMake/MacOSVersions/MacOSVersions-build-check.cmake2
-rw-r--r--Tests/RunCMake/Ninja/CustomCommandDepfile-check.cmake6
-rw-r--r--Tests/RunCMake/Ninja/CustomCommandJobPool-check.cmake4
-rw-r--r--Tests/RunCMake/Ninja/VerboseBuild-nowork-stdout.txt2
-rw-r--r--Tests/RunCMake/NinjaMultiConfig/CustomCommandDepfile-check.cmake6
-rw-r--r--Tests/RunCMake/ParseImplicitLinkInfo/ExcludeDirs.cmake10
-rw-r--r--Tests/RunCMake/ParseImplicitLinkInfo/Inspect.cmake12
-rw-r--r--Tests/RunCMake/ParseImplicitLinkInfo/RunCMakeTest.cmake8
-rw-r--r--Tests/RunCMake/ctest_memcheck/testAddressLeakSanitizer.cmake6
-rw-r--r--Tests/RunCMake/ctest_memcheck/testAddressSanitizer.cmake2
-rw-r--r--Tests/RunCMake/ctest_memcheck/testLeakSanitizer.cmake6
-rw-r--r--Tests/RunCMake/ctest_memcheck/testMemorySanitizer.cmake2
-rw-r--r--Tests/RunCMake/file/COPY_FILE-file-replace.cmake2
-rw-r--r--Tests/RunCMake/file/COPY_FILE-link-to-file.cmake2
-rw-r--r--Tests/RunCMake/file/LOCK-error-guard-incorrect-stderr.txt2
-rw-r--r--Tests/RunCMake/file/LOCK-error-guard-incorrect.cmake2
-rw-r--r--Tests/RunCMake/file/RENAME-file-replace.cmake2
-rw-r--r--Tests/RunCMake/message/RunCMakeTest.cmake2
-rw-r--r--Utilities/ClangTidyModule/CMakeLists.txt10
-rw-r--r--Utilities/ClangTidyModule/UsePragmaOnceCheck.cxx2
-rw-r--r--Utilities/IWYU/mapping.imp2
-rwxr-xr-xUtilities/Scripts/update-cppdap.bash30
-rw-r--r--Utilities/cm3p/cppdap/dap.h11
-rw-r--r--Utilities/cm3p/cppdap/future.h11
-rw-r--r--Utilities/cm3p/cppdap/io.h11
-rw-r--r--Utilities/cm3p/cppdap/optional.h11
-rw-r--r--Utilities/cm3p/cppdap/protocol.h11
-rw-r--r--Utilities/cm3p/cppdap/session.h11
-rw-r--r--Utilities/cm3p/cppdap/types.h11
-rw-r--r--Utilities/cm3p/json/forwards.h11
-rw-r--r--Utilities/cm3p/json/json.h11
-rw-r--r--Utilities/cmThirdParty.h.in1
-rw-r--r--Utilities/cmbzip2/bzlib.c4
-rw-r--r--Utilities/cmbzip2/compress.c8
-rw-r--r--Utilities/cmcppdap/.gitattributes1
-rw-r--r--Utilities/cmcppdap/CMakeLists.txt37
-rw-r--r--Utilities/cmcppdap/LICENSE202
-rw-r--r--Utilities/cmcppdap/NOTICE5
-rw-r--r--Utilities/cmcppdap/include/dap/any.h211
-rw-r--r--Utilities/cmcppdap/include/dap/dap.h35
-rw-r--r--Utilities/cmcppdap/include/dap/future.h179
-rw-r--r--Utilities/cmcppdap/include/dap/io.h97
-rw-r--r--Utilities/cmcppdap/include/dap/network.h62
-rw-r--r--Utilities/cmcppdap/include/dap/optional.h263
-rw-r--r--Utilities/cmcppdap/include/dap/protocol.h2679
-rw-r--r--Utilities/cmcppdap/include/dap/serialization.h253
-rw-r--r--Utilities/cmcppdap/include/dap/session.h449
-rw-r--r--Utilities/cmcppdap/include/dap/traits.h159
-rw-r--r--Utilities/cmcppdap/include/dap/typeinfo.h59
-rw-r--r--Utilities/cmcppdap/include/dap/typeof.h266
-rw-r--r--Utilities/cmcppdap/include/dap/types.h104
-rw-r--r--Utilities/cmcppdap/include/dap/variant.h108
-rw-r--r--Utilities/cmcppdap/src/any_test.cpp262
-rw-r--r--Utilities/cmcppdap/src/chan.h90
-rw-r--r--Utilities/cmcppdap/src/chan_test.cpp35
-rw-r--r--Utilities/cmcppdap/src/content_stream.cpp189
-rw-r--r--Utilities/cmcppdap/src/content_stream.h69
-rw-r--r--Utilities/cmcppdap/src/content_stream_test.cpp99
-rw-r--r--Utilities/cmcppdap/src/dap_test.cpp72
-rw-r--r--Utilities/cmcppdap/src/io.cpp258
-rw-r--r--Utilities/cmcppdap/src/json_serializer.h47
-rw-r--r--Utilities/cmcppdap/src/json_serializer_test.cpp266
-rw-r--r--Utilities/cmcppdap/src/jsoncpp_json_serializer.cpp272
-rw-r--r--Utilities/cmcppdap/src/jsoncpp_json_serializer.h134
-rw-r--r--Utilities/cmcppdap/src/network.cpp100
-rw-r--r--Utilities/cmcppdap/src/network_test.cpp110
-rw-r--r--Utilities/cmcppdap/src/nlohmann_json_serializer.cpp260
-rw-r--r--Utilities/cmcppdap/src/nlohmann_json_serializer.h133
-rw-r--r--Utilities/cmcppdap/src/null_json_serializer.cpp23
-rw-r--r--Utilities/cmcppdap/src/null_json_serializer.h47
-rw-r--r--Utilities/cmcppdap/src/optional_test.cpp169
-rw-r--r--Utilities/cmcppdap/src/protocol_events.cpp126
-rw-r--r--Utilities/cmcppdap/src/protocol_requests.cpp281
-rw-r--r--Utilities/cmcppdap/src/protocol_response.cpp243
-rw-r--r--Utilities/cmcppdap/src/protocol_types.cpp316
-rw-r--r--Utilities/cmcppdap/src/rapid_json_serializer.cpp289
-rw-r--r--Utilities/cmcppdap/src/rapid_json_serializer.h138
-rw-r--r--Utilities/cmcppdap/src/rwmutex.h172
-rw-r--r--Utilities/cmcppdap/src/rwmutex_test.cpp113
-rw-r--r--Utilities/cmcppdap/src/session.cpp516
-rw-r--r--Utilities/cmcppdap/src/session_test.cpp625
-rw-r--r--Utilities/cmcppdap/src/socket.cpp333
-rw-r--r--Utilities/cmcppdap/src/socket.h47
-rw-r--r--Utilities/cmcppdap/src/socket_test.cpp104
-rw-r--r--Utilities/cmcppdap/src/string_buffer.h85
-rw-r--r--Utilities/cmcppdap/src/traits_test.cpp387
-rw-r--r--Utilities/cmcppdap/src/typeinfo.cpp21
-rw-r--r--Utilities/cmcppdap/src/typeinfo_test.cpp65
-rw-r--r--Utilities/cmcppdap/src/typeof.cpp144
-rw-r--r--Utilities/cmcppdap/src/variant_test.cpp94
-rw-r--r--Utilities/cmcurl/curltest.c19
-rw-r--r--Utilities/cmlibarchive/libarchive/archive_acl.c10
-rw-r--r--Utilities/cmlibarchive/libarchive/archive_match.c4
-rw-r--r--Utilities/cmlibarchive/libarchive/archive_ppmd8.c12
-rw-r--r--Utilities/cmlibarchive/libarchive/archive_read_disk_posix.c11
-rw-r--r--Utilities/cmlibarchive/libarchive/archive_read_support_filter_uu.c7
-rw-r--r--Utilities/cmlibarchive/libarchive/archive_read_support_format_7zip.c10
-rw-r--r--Utilities/cmlibarchive/libarchive/archive_read_support_format_iso9660.c2
-rw-r--r--Utilities/cmlibarchive/libarchive/archive_read_support_format_rar.c7
-rw-r--r--Utilities/cmlibarchive/libarchive/archive_read_support_format_rar5.c15
-rw-r--r--Utilities/cmlibarchive/libarchive/archive_write_set_format_iso9660.c9
-rw-r--r--Utilities/cmliblzma/liblzma/common/index.c3
-rw-r--r--Utilities/cmliblzma/liblzma/common/index_encoder.c4
-rw-r--r--Utilities/cmlibrhash/librhash/hex.c3
-rw-r--r--Utilities/cmlibuv/src/unix/tty.c4
-rw-r--r--Utilities/cmlibuv/src/unix/udp.c6
-rw-r--r--Utilities/cmnghttp2/lib/nghttp2_buf.c16
-rw-r--r--Utilities/cmzlib/gzread.c6
-rw-r--r--Utilities/cmzlib/gzwrite.c6
-rw-r--r--Utilities/cmzstd/lib/common/bitstream.h2
-rw-r--r--Utilities/cmzstd/lib/compress/fse_compress.c4
-rw-r--r--Utilities/cmzstd/lib/dictBuilder/divsufsort.c11
-rwxr-xr-xbootstrap11
426 files changed, 19684 insertions, 753 deletions
diff --git a/.clang-tidy b/.clang-tidy
index c790467..1b776e1 100644
--- a/.clang-tidy
+++ b/.clang-tidy
@@ -15,6 +15,7 @@ misc-*,\
-misc-no-recursion,\
-misc-non-private-member-variables-in-classes,\
-misc-static-assert,\
+-misc-use-anonymous-namespace,\
modernize-*,\
-modernize-avoid-c-arrays,\
-modernize-macro-to-enum,\
diff --git a/.codespellrc b/.codespellrc
index 0abd94e..00c6c52 100644
--- a/.codespellrc
+++ b/.codespellrc
@@ -4,5 +4,5 @@ check-hidden =
# Disable warnings about binary files
quiet-level = 2
builtin = clear,rare,en-GB_to_en-US
-skip = */.git,*/build,*/Copyright.txt,*/doxygen.config,*/Modules/Internal/CPack/NSIS.template.in,*/Source/CursesDialog/form/*,*/Source/kwsys/*,*/Tests/RunCMake/CPack/tests/DMG_SLA/German.*,*/Tests/RunCMake/ParseImplicitData/*.input,*/Utilities/cm*
-ignore-words-list = aci,ake,ans,ba,cconfiguration,conly,dependees,dne,dum,earch,ect,filetest,fo,helpfull,hiden,isnt,keypair,nd,ned,nin,nknown,ot,pard,seh,ser,te,upto,varn,vas,wee
+skip = */.git,*/build,*/Copyright.txt,*/CTestCustom.cmake.in,*/doxygen.config,*/Modules/Internal/CPack/NSIS.template.in,*/Source/CursesDialog/form/*,*/Source/kwsys/*,*/Tests/RunCMake/CPack/tests/DMG_SLA/German.*,*/Tests/RunCMake/ParseImplicitData/*.input,*/Tests/StringFileTest/test.utf8,*.pfx,*/Utilities/cm*
+ignore-words-list = aci,ags,ake,ans,ba,ccompiler,cconfiguration,certi,conly,dependees,dne,dum,earch,ect,filetest,fo,helpfull,hiden,isnt,keypair,nd,ned,nin,nknown,ot,pard,seh,ser,te,upto,varn,vas,wee
diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml
index 305c8d2..6e0d01a 100644
--- a/.gitlab-ci.yml
+++ b/.gitlab-ci.yml
@@ -55,7 +55,7 @@ p:source-package:
p:doc-package:
extends:
- - .fedora37_sphinx_package
+ - .fedora38_sphinx_package
- .cmake_prep_doc_linux
- .linux_x86_64_tags
- .cmake_doc_artifacts
@@ -103,16 +103,16 @@ l:iwyu-debian10:
- .linux_x86_64_tags
- .run_automatically
-l:tidy-fedora37:
+l:tidy-fedora38:
extends:
- - .fedora37_tidy
+ - .fedora38_tidy
- .cmake_build_linux
- .linux_x86_64_tags
- .run_automatically
-l:sphinx-fedora37:
+l:sphinx-fedora38:
extends:
- - .fedora37_sphinx
+ - .fedora38_sphinx
- .cmake_build_linux
- .cmake_sphinx_artifacts
- .linux_x86_64_tags
@@ -121,9 +121,9 @@ l:sphinx-fedora37:
CMAKE_CI_JOB_CONTINUOUS: "true"
CMAKE_CI_JOB_HELP: "true"
-l:clang-analyzer-fedora37:
+l:clang-analyzer-fedora38:
extends:
- - .fedora37_clang_analyzer
+ - .fedora38_clang_analyzer
- .cmake_build_linux
- .linux_x86_64_tags
- .run_automatically
@@ -195,9 +195,9 @@ t:debian10-makefiles-clang:
variables:
CMAKE_CI_JOB_NIGHTLY: "true"
-t:fedora37-ninja-clang:
+t:fedora38-ninja-clang:
extends:
- - .fedora37_ninja_clang
+ - .fedora38_ninja_clang
- .cmake_test_linux_release
- .linux_x86_64_tags
- .run_dependent
@@ -205,9 +205,9 @@ t:fedora37-ninja-clang:
variables:
CMAKE_CI_JOB_NIGHTLY: "true"
-t:fedora37-makefiles-clang:
+t:fedora38-ninja-multi-clang:
extends:
- - .fedora37_makefiles_clang
+ - .fedora38_ninja_multi_clang
- .cmake_test_linux_release
- .linux_x86_64_tags
- .run_dependent
@@ -215,17 +215,27 @@ t:fedora37-makefiles-clang:
variables:
CMAKE_CI_JOB_NIGHTLY: "true"
-t:fedora37-makefiles:
+t:fedora38-makefiles-clang:
extends:
- - .fedora37_makefiles
+ - .fedora38_makefiles_clang
+ - .cmake_test_linux_release
+ - .linux_x86_64_tags
+ - .run_dependent
+ - .needs_centos6_x86_64
+ variables:
+ CMAKE_CI_JOB_NIGHTLY: "true"
+
+t:fedora38-makefiles:
+ extends:
+ - .fedora38_makefiles
- .cmake_test_linux_release
- .linux_x86_64_tags
- .run_dependent
- .needs_centos6_x86_64
-t:fedora37-makefiles-nospace:
+t:fedora38-makefiles-nospace:
extends:
- - .fedora37_makefiles
+ - .fedora38_makefiles
- .cmake_test_linux_release
- .linux_x86_64_tags
- .cmake_junit_artifacts
@@ -233,7 +243,7 @@ t:fedora37-makefiles-nospace:
- .needs_centos6_x86_64
variables:
GIT_CLONE_PATH: "$CI_BUILDS_DIR/cmake-ci"
- CMAKE_CI_BUILD_NAME: fedora37_makefiles_nospace
+ CMAKE_CI_BUILD_NAME: fedora38_makefiles_nospace
CMAKE_CI_JOB_NIGHTLY: "true"
t:nvhpc22.11-ninja:
@@ -334,29 +344,9 @@ t:linux-gcc-cxx-modules-ninja-multi:
variables:
CMAKE_CI_JOB_NIGHTLY: "true"
-t:linux-clang-cxx-modules-ninja:
- extends:
- - .clang_cxx_modules_ninja
- - .cmake_test_linux_release
- - .linux_x86_64_tags
- - .run_dependent
- - .needs_centos6_x86_64
- variables:
- CMAKE_CI_JOB_NIGHTLY: "true"
-
-t:linux-clang-cxx-modules-ninja-multi:
- extends:
- - .clang_cxx_modules_ninja_multi
- - .cmake_test_linux_release
- - .linux_x86_64_tags
- - .run_dependent
- - .needs_centos6_x86_64
- variables:
- CMAKE_CI_JOB_NIGHTLY: "true"
-
-b:fedora37-ninja:
+b:fedora38-ninja:
extends:
- - .fedora37_ninja
+ - .fedora38_ninja
- .cmake_build_linux
- .cmake_build_artifacts
- .linux_x86_64_tags
@@ -391,40 +381,40 @@ b:debian10-aarch64-extdeps:
variables:
CMAKE_CI_JOB_NIGHTLY: "true"
-b:fedora37-extdeps:
+b:fedora38-extdeps:
extends:
- - .fedora37_extdeps
+ - .fedora38_extdeps
- .cmake_build_linux_standalone
- .linux_x86_64_tags
- .run_manually
variables:
CMAKE_CI_JOB_NIGHTLY: "true"
-t:fedora37-ninja:
+t:fedora38-ninja:
extends:
- - .fedora37_ninja
+ - .fedora38_ninja
- .cmake_test_linux
- .linux_x86_64_tags_x11
- .cmake_test_artifacts
- .run_dependent
dependencies:
- - b:fedora37-ninja
+ - b:fedora38-ninja
needs:
- - b:fedora37-ninja
+ - b:fedora38-ninja
variables:
CMAKE_CI_JOB_CONTINUOUS: "true"
-t:fedora37-ninja-multi:
+t:fedora38-ninja-multi:
extends:
- - .fedora37_ninja_multi
+ - .fedora38_ninja_multi
- .cmake_test_linux_external
- .linux_x86_64_tags
- .cmake_junit_artifacts
- .run_dependent
dependencies:
- - t:fedora37-ninja
+ - t:fedora38-ninja
needs:
- - t:fedora37-ninja
+ - t:fedora38-ninja
t:intel2016-makefiles:
extends:
@@ -791,9 +781,9 @@ u:linux-aarch64-package:
## Sanitizer builds
-b:fedora37-asan:
+b:fedora38-asan:
extends:
- - .fedora37_asan
+ - .fedora38_asan
- .cmake_build_linux
- .cmake_build_artifacts
- .linux_x86_64_tags
@@ -801,16 +791,16 @@ b:fedora37-asan:
variables:
CMAKE_CI_JOB_NIGHTLY: "true"
-t:fedora37-asan:
+t:fedora38-asan:
extends:
- - .fedora37_asan
+ - .fedora38_asan
- .cmake_memcheck_linux
- .linux_x86_64_tags
- .run_dependent
dependencies:
- - b:fedora37-asan
+ - b:fedora38-asan
needs:
- - b:fedora37-asan
+ - b:fedora38-asan
variables:
CMAKE_CI_JOB_NIGHTLY: "true"
diff --git a/.gitlab/ci/configure_fedora37_clang_analyzer.cmake b/.gitlab/ci/configure_fedora37_clang_analyzer.cmake
deleted file mode 100644
index f4c4cdd..0000000
--- a/.gitlab/ci/configure_fedora37_clang_analyzer.cmake
+++ /dev/null
@@ -1 +0,0 @@
-include("${CMAKE_CURRENT_LIST_DIR}/configure_fedora37_common.cmake")
diff --git a/.gitlab/ci/configure_fedora37_makefiles_clang.cmake b/.gitlab/ci/configure_fedora37_makefiles_clang.cmake
deleted file mode 100644
index 7b82a9a..0000000
--- a/.gitlab/ci/configure_fedora37_makefiles_clang.cmake
+++ /dev/null
@@ -1 +0,0 @@
-include("${CMAKE_CURRENT_LIST_DIR}/configure_fedora37_common_clang.cmake")
diff --git a/.gitlab/ci/configure_fedora37_ninja_clang.cmake b/.gitlab/ci/configure_fedora37_ninja_clang.cmake
deleted file mode 100644
index 7b82a9a..0000000
--- a/.gitlab/ci/configure_fedora37_ninja_clang.cmake
+++ /dev/null
@@ -1 +0,0 @@
-include("${CMAKE_CURRENT_LIST_DIR}/configure_fedora37_common_clang.cmake")
diff --git a/.gitlab/ci/configure_fedora37_asan.cmake b/.gitlab/ci/configure_fedora38_asan.cmake
index 363e953..8eae500 100644
--- a/.gitlab/ci/configure_fedora37_asan.cmake
+++ b/.gitlab/ci/configure_fedora38_asan.cmake
@@ -1,4 +1,4 @@
set(CMAKE_C_FLAGS "-fsanitize=address" CACHE STRING "")
set(CMAKE_CXX_FLAGS "-fsanitize=address" CACHE STRING "")
-include("${CMAKE_CURRENT_LIST_DIR}/configure_fedora37_common.cmake")
+include("${CMAKE_CURRENT_LIST_DIR}/configure_fedora38_common.cmake")
diff --git a/.gitlab/ci/configure_fedora38_clang_analyzer.cmake b/.gitlab/ci/configure_fedora38_clang_analyzer.cmake
new file mode 100644
index 0000000..c11eef1
--- /dev/null
+++ b/.gitlab/ci/configure_fedora38_clang_analyzer.cmake
@@ -0,0 +1,3 @@
+set(configure_no_sccache 1)
+
+include("${CMAKE_CURRENT_LIST_DIR}/configure_fedora38_common.cmake")
diff --git a/.gitlab/ci/configure_fedora37_common.cmake b/.gitlab/ci/configure_fedora38_common.cmake
index 4484e26..4484e26 100644
--- a/.gitlab/ci/configure_fedora37_common.cmake
+++ b/.gitlab/ci/configure_fedora38_common.cmake
diff --git a/.gitlab/ci/configure_fedora37_common_clang.cmake b/.gitlab/ci/configure_fedora38_common_clang.cmake
index 70c9df9..70c9df9 100644
--- a/.gitlab/ci/configure_fedora37_common_clang.cmake
+++ b/.gitlab/ci/configure_fedora38_common_clang.cmake
diff --git a/.gitlab/ci/configure_fedora37_extdeps.cmake b/.gitlab/ci/configure_fedora38_extdeps.cmake
index 8e545f5..8e545f5 100644
--- a/.gitlab/ci/configure_fedora37_extdeps.cmake
+++ b/.gitlab/ci/configure_fedora38_extdeps.cmake
diff --git a/.gitlab/ci/configure_fedora37_makefiles.cmake b/.gitlab/ci/configure_fedora38_makefiles.cmake
index c2f9982..c2f9982 100644
--- a/.gitlab/ci/configure_fedora37_makefiles.cmake
+++ b/.gitlab/ci/configure_fedora38_makefiles.cmake
diff --git a/.gitlab/ci/configure_fedora38_makefiles_clang.cmake b/.gitlab/ci/configure_fedora38_makefiles_clang.cmake
new file mode 100644
index 0000000..ff30ad9
--- /dev/null
+++ b/.gitlab/ci/configure_fedora38_makefiles_clang.cmake
@@ -0,0 +1 @@
+include("${CMAKE_CURRENT_LIST_DIR}/configure_fedora38_common_clang.cmake")
diff --git a/.gitlab/ci/configure_fedora37_ninja.cmake b/.gitlab/ci/configure_fedora38_ninja.cmake
index 5b40677..ac6b9f6 100644
--- a/.gitlab/ci/configure_fedora37_ninja.cmake
+++ b/.gitlab/ci/configure_fedora38_ninja.cmake
@@ -11,4 +11,4 @@ set(CMAKE_CXX_FLAGS_RELEASE "-O3" CACHE STRING "")
# Cover compilation with C++11 only and not higher standards.
set(CMAKE_CXX_STANDARD "11" CACHE STRING "")
-include("${CMAKE_CURRENT_LIST_DIR}/configure_fedora37_common.cmake")
+include("${CMAKE_CURRENT_LIST_DIR}/configure_fedora38_common.cmake")
diff --git a/.gitlab/ci/configure_linux_clang_cxx_modules_ninja.cmake b/.gitlab/ci/configure_fedora38_ninja_clang.cmake
index 671c625..214a123 100644
--- a/.gitlab/ci/configure_linux_clang_cxx_modules_ninja.cmake
+++ b/.gitlab/ci/configure_fedora38_ninja_clang.cmake
@@ -1,4 +1,4 @@
set(CMake_TEST_MODULE_COMPILATION "named,collation,partitions,internal_partitions,export_bmi,install_bmi,shared" CACHE STRING "")
set(CMake_TEST_MODULE_COMPILATION_RULES "${CMAKE_CURRENT_LIST_DIR}/cxx_modules_rules_clang.cmake" CACHE STRING "")
-include("${CMAKE_CURRENT_LIST_DIR}/configure_external_test.cmake")
+include("${CMAKE_CURRENT_LIST_DIR}/configure_fedora38_common_clang.cmake")
diff --git a/.gitlab/ci/configure_fedora37_ninja_multi.cmake b/.gitlab/ci/configure_fedora38_ninja_multi.cmake
index 94af721..94af721 100644
--- a/.gitlab/ci/configure_fedora37_ninja_multi.cmake
+++ b/.gitlab/ci/configure_fedora38_ninja_multi.cmake
diff --git a/.gitlab/ci/configure_linux_clang_cxx_modules_ninja_multi.cmake b/.gitlab/ci/configure_fedora38_ninja_multi_clang.cmake
index 671c625..214a123 100644
--- a/.gitlab/ci/configure_linux_clang_cxx_modules_ninja_multi.cmake
+++ b/.gitlab/ci/configure_fedora38_ninja_multi_clang.cmake
@@ -1,4 +1,4 @@
set(CMake_TEST_MODULE_COMPILATION "named,collation,partitions,internal_partitions,export_bmi,install_bmi,shared" CACHE STRING "")
set(CMake_TEST_MODULE_COMPILATION_RULES "${CMAKE_CURRENT_LIST_DIR}/cxx_modules_rules_clang.cmake" CACHE STRING "")
-include("${CMAKE_CURRENT_LIST_DIR}/configure_external_test.cmake")
+include("${CMAKE_CURRENT_LIST_DIR}/configure_fedora38_common_clang.cmake")
diff --git a/.gitlab/ci/configure_fedora37_sphinx.cmake b/.gitlab/ci/configure_fedora38_sphinx.cmake
index 90d159b..90d159b 100644
--- a/.gitlab/ci/configure_fedora37_sphinx.cmake
+++ b/.gitlab/ci/configure_fedora38_sphinx.cmake
diff --git a/.gitlab/ci/configure_fedora37_sphinx_package.cmake b/.gitlab/ci/configure_fedora38_sphinx_package.cmake
index e839de8..e839de8 100644
--- a/.gitlab/ci/configure_fedora37_sphinx_package.cmake
+++ b/.gitlab/ci/configure_fedora38_sphinx_package.cmake
diff --git a/.gitlab/ci/configure_fedora37_tidy.cmake b/.gitlab/ci/configure_fedora38_tidy.cmake
index f8eb9ab..5b062da 100644
--- a/.gitlab/ci/configure_fedora37_tidy.cmake
+++ b/.gitlab/ci/configure_fedora38_tidy.cmake
@@ -2,4 +2,4 @@ set(CMake_RUN_CLANG_TIDY ON CACHE BOOL "")
set(CMake_USE_CLANG_TIDY_MODULE ON CACHE BOOL "")
set(CMake_CLANG_TIDY_MODULE "$ENV{CI_PROJECT_DIR}/Utilities/ClangTidyModule/build/libcmake-clang-tidy-module.so" CACHE FILEPATH "")
-include("${CMAKE_CURRENT_LIST_DIR}/configure_fedora37_common.cmake")
+include("${CMAKE_CURRENT_LIST_DIR}/configure_fedora38_common.cmake")
diff --git a/.gitlab/ci/ctest_memcheck_fedora37_asan.lsan.supp b/.gitlab/ci/ctest_memcheck_fedora38_asan.lsan.supp
index 8ec1a03..8ec1a03 100644
--- a/.gitlab/ci/ctest_memcheck_fedora37_asan.lsan.supp
+++ b/.gitlab/ci/ctest_memcheck_fedora38_asan.lsan.supp
diff --git a/.gitlab/ci/docker/clang_cxx_modules/Dockerfile b/.gitlab/ci/docker/clang_cxx_modules/Dockerfile
deleted file mode 100644
index 4e58125..0000000
--- a/.gitlab/ci/docker/clang_cxx_modules/Dockerfile
+++ /dev/null
@@ -1,13 +0,0 @@
-FROM fedora:37
-MAINTAINER Ben Boeckel <ben.boeckel@kitware.com>
-
-# Install build dependencies for packages.
-COPY install_deps.sh /root/install_deps.sh
-RUN sh /root/install_deps.sh
-
-COPY install_llvm.sh /root/install_llvm.sh
-RUN sh /root/install_llvm.sh
-
-# Install build dependencies for CMake's CI.
-COPY install_cmake_deps.sh /root/install_cmake_deps.sh
-RUN sh /root/install_cmake_deps.sh
diff --git a/.gitlab/ci/docker/clang_cxx_modules/install_cmake_deps.sh b/.gitlab/ci/docker/clang_cxx_modules/install_cmake_deps.sh
deleted file mode 100755
index 465e125..0000000
--- a/.gitlab/ci/docker/clang_cxx_modules/install_cmake_deps.sh
+++ /dev/null
@@ -1,7 +0,0 @@
-#!/bin/sh
-
-set -e
-
-dnf install -y --setopt=install_weak_deps=False \
- file git-core
-dnf clean all
diff --git a/.gitlab/ci/docker/clang_cxx_modules/install_deps.sh b/.gitlab/ci/docker/clang_cxx_modules/install_deps.sh
deleted file mode 100755
index c1957c3..0000000
--- a/.gitlab/ci/docker/clang_cxx_modules/install_deps.sh
+++ /dev/null
@@ -1,7 +0,0 @@
-#!/bin/sh
-
-set -e
-
-dnf install -y --setopt=install_weak_deps=False \
- gcc-c++ cmake ninja-build
-dnf clean all
diff --git a/.gitlab/ci/docker/clang_cxx_modules/install_llvm.sh b/.gitlab/ci/docker/clang_cxx_modules/install_llvm.sh
deleted file mode 100755
index 35f925e..0000000
--- a/.gitlab/ci/docker/clang_cxx_modules/install_llvm.sh
+++ /dev/null
@@ -1,39 +0,0 @@
-#!/bin/sh
-
-set -e
-
-readonly revision="6d859df46e93e04bd7a4f90d9a9056763998f638" # llvmorg-16.0.0-rc2-31-g6d859df46e93
-readonly tarball="https://github.com/llvm/llvm-project/archive/$revision.tar.gz"
-
-readonly workdir="$HOME/llvm"
-readonly srcdir="$workdir/llvm"
-readonly builddir="$workdir/build"
-
-mkdir -p "$workdir"
-cd "$workdir"
-curl -L "$tarball" > "llvm-$revision.tar.gz"
-tar xf "llvm-$revision.tar.gz"
-mv "llvm-project-$revision" "$srcdir"
-mkdir -p "$builddir"
-cd "$builddir"
-cmake -GNinja \
- -DCMAKE_BUILD_TYPE=Release \
- -DBUILD_SHARED_LIBS=ON \
- -DLLVM_ENABLE_BINDINGS=OFF \
- -DLLVM_INCLUDE_BENCHMARKS=OFF \
- -DLLVM_INCLUDE_DOCS=OFF \
- -DLLVM_INCLUDE_EXAMPLES=OFF \
- -DLLVM_INCLUDE_RUNTIMES=OFF \
- -DLLVM_INCLUDE_TESTS=OFF \
- -DLLVM_INCLUDE_UTILS=OFF \
- -DLLVM_TARGETS_TO_BUILD=X86 \
- -DLLVM_TOOL_CLANG_BUILD=ON \
- -DLLVM_USE_SYMLINKS=ON \
- "-DLLVM_EXTERNAL_CLANG_SOURCE_DIR=$srcdir/clang" \
- -DLLVM_PARALLEL_LINK_JOBS=1 \
- -DCLANG_BUILD_TOOLS=ON \
- "-DCMAKE_INSTALL_PREFIX=/opt/llvm-p1689" \
- "$srcdir/llvm"
-ninja
-ninja install/strip
-rm -rf "$workdir"
diff --git a/.gitlab/ci/docker/fedora37/Dockerfile b/.gitlab/ci/docker/fedora38/Dockerfile
index 5439e9d..4918693 100644
--- a/.gitlab/ci/docker/fedora37/Dockerfile
+++ b/.gitlab/ci/docker/fedora38/Dockerfile
@@ -1,6 +1,6 @@
# syntax=docker/dockerfile:1
-ARG BASE_IMAGE=fedora:37
+ARG BASE_IMAGE=fedora:38
FROM ${BASE_IMAGE} AS dnf-cache
# Populate DNF cache w/ the fresh metadata and prefetch packages.
diff --git a/.gitlab/ci/docker/fedora37/deps_packages.lst b/.gitlab/ci/docker/fedora38/deps_packages.lst
index 68777f0..c7c1385 100644
--- a/.gitlab/ci/docker/fedora37/deps_packages.lst
+++ b/.gitlab/ci/docker/fedora38/deps_packages.lst
@@ -19,7 +19,6 @@ make
bzip2-devel
expat-devel
jsoncpp-devel
-json-devel
libarchive-devel
libcurl-devel
libuv-devel
diff --git a/.gitlab/ci/docker/fedora37/install_deps.sh b/.gitlab/ci/docker/fedora38/install_deps.sh
index cd2701e..cd2701e 100755
--- a/.gitlab/ci/docker/fedora37/install_deps.sh
+++ b/.gitlab/ci/docker/fedora38/install_deps.sh
diff --git a/.gitlab/ci/docker/fedora37/install_iwyu.sh b/.gitlab/ci/docker/fedora38/install_iwyu.sh
index 684e355..684e355 100755
--- a/.gitlab/ci/docker/fedora37/install_iwyu.sh
+++ b/.gitlab/ci/docker/fedora38/install_iwyu.sh
diff --git a/.gitlab/ci/docker/fedora37/install_rvm.sh b/.gitlab/ci/docker/fedora38/install_rvm.sh
index 10e7545..10e7545 100755
--- a/.gitlab/ci/docker/fedora37/install_rvm.sh
+++ b/.gitlab/ci/docker/fedora38/install_rvm.sh
diff --git a/.gitlab/ci/docker/fedora37/iwyu_packages.lst b/.gitlab/ci/docker/fedora38/iwyu_packages.lst
index e3551bd..e3551bd 100644
--- a/.gitlab/ci/docker/fedora37/iwyu_packages.lst
+++ b/.gitlab/ci/docker/fedora38/iwyu_packages.lst
diff --git a/.gitlab/ci/docker/fedora37/rvm_packages.lst b/.gitlab/ci/docker/fedora38/rvm_packages.lst
index 1dc852e..1dc852e 100644
--- a/.gitlab/ci/docker/fedora37/rvm_packages.lst
+++ b/.gitlab/ci/docker/fedora38/rvm_packages.lst
diff --git a/.gitlab/ci/env_fedora37_makefiles_clang.sh b/.gitlab/ci/env_fedora37_makefiles_clang.sh
deleted file mode 100644
index 9ff1d84..0000000
--- a/.gitlab/ci/env_fedora37_makefiles_clang.sh
+++ /dev/null
@@ -1 +0,0 @@
-. .gitlab/ci/env_fedora37_common_clang.sh
diff --git a/.gitlab/ci/env_fedora37_ninja_clang.sh b/.gitlab/ci/env_fedora37_ninja_clang.sh
deleted file mode 100644
index 9ff1d84..0000000
--- a/.gitlab/ci/env_fedora37_ninja_clang.sh
+++ /dev/null
@@ -1 +0,0 @@
-. .gitlab/ci/env_fedora37_common_clang.sh
diff --git a/.gitlab/ci/env_fedora37_asan.sh b/.gitlab/ci/env_fedora38_asan.sh
index e976486..e976486 100644
--- a/.gitlab/ci/env_fedora37_asan.sh
+++ b/.gitlab/ci/env_fedora38_asan.sh
diff --git a/.gitlab/ci/env_fedora37_clang_analyzer.sh b/.gitlab/ci/env_fedora38_clang_analyzer.sh
index d732c0b..d732c0b 100644
--- a/.gitlab/ci/env_fedora37_clang_analyzer.sh
+++ b/.gitlab/ci/env_fedora38_clang_analyzer.sh
diff --git a/.gitlab/ci/env_fedora37_common_clang.sh b/.gitlab/ci/env_fedora38_common_clang.sh
index b03b757..fc9c041 100644
--- a/.gitlab/ci/env_fedora37_common_clang.sh
+++ b/.gitlab/ci/env_fedora38_common_clang.sh
@@ -1,4 +1,4 @@
-export CC=/usr/bin/clang-15
-export CXX=/usr/bin/clang++-15
+export CC=/usr/bin/clang-16
+export CXX=/usr/bin/clang++-16
export FC=/usr/bin/flang-new
export FFLAGS=-flang-experimental-exec
diff --git a/.gitlab/ci/env_fedora37_extdeps.sh b/.gitlab/ci/env_fedora38_extdeps.sh
index 7076e18..7076e18 100644
--- a/.gitlab/ci/env_fedora37_extdeps.sh
+++ b/.gitlab/ci/env_fedora38_extdeps.sh
diff --git a/.gitlab/ci/env_fedora37_makefiles.cmake b/.gitlab/ci/env_fedora38_makefiles.cmake
index ef13cda..ef13cda 100644
--- a/.gitlab/ci/env_fedora37_makefiles.cmake
+++ b/.gitlab/ci/env_fedora38_makefiles.cmake
diff --git a/.gitlab/ci/env_fedora37_makefiles.sh b/.gitlab/ci/env_fedora38_makefiles.sh
index c482642..c482642 100644
--- a/.gitlab/ci/env_fedora37_makefiles.sh
+++ b/.gitlab/ci/env_fedora38_makefiles.sh
diff --git a/.gitlab/ci/env_fedora38_makefiles_clang.sh b/.gitlab/ci/env_fedora38_makefiles_clang.sh
new file mode 100644
index 0000000..9f3edde
--- /dev/null
+++ b/.gitlab/ci/env_fedora38_makefiles_clang.sh
@@ -0,0 +1 @@
+. .gitlab/ci/env_fedora38_common_clang.sh
diff --git a/.gitlab/ci/env_fedora37_ninja_multi.sh b/.gitlab/ci/env_fedora38_ninja.sh
index 217ff30..217ff30 100644
--- a/.gitlab/ci/env_fedora37_ninja_multi.sh
+++ b/.gitlab/ci/env_fedora38_ninja.sh
diff --git a/.gitlab/ci/env_fedora38_ninja_clang.sh b/.gitlab/ci/env_fedora38_ninja_clang.sh
new file mode 100644
index 0000000..9f3edde
--- /dev/null
+++ b/.gitlab/ci/env_fedora38_ninja_clang.sh
@@ -0,0 +1 @@
+. .gitlab/ci/env_fedora38_common_clang.sh
diff --git a/.gitlab/ci/env_fedora37_ninja.sh b/.gitlab/ci/env_fedora38_ninja_multi.sh
index 217ff30..217ff30 100644
--- a/.gitlab/ci/env_fedora37_ninja.sh
+++ b/.gitlab/ci/env_fedora38_ninja_multi.sh
diff --git a/.gitlab/ci/env_fedora38_ninja_multi_clang.sh b/.gitlab/ci/env_fedora38_ninja_multi_clang.sh
new file mode 100644
index 0000000..9f3edde
--- /dev/null
+++ b/.gitlab/ci/env_fedora38_ninja_multi_clang.sh
@@ -0,0 +1 @@
+. .gitlab/ci/env_fedora38_common_clang.sh
diff --git a/.gitlab/ci/extdeps-linux.sh b/.gitlab/ci/extdeps-linux.sh
index f0d4c0d..f091525 100755
--- a/.gitlab/ci/extdeps-linux.sh
+++ b/.gitlab/ci/extdeps-linux.sh
@@ -57,6 +57,25 @@ cmake -S jsoncpp-1.6.0 -B jsoncpp-1.6.0-build \
-DCMAKE_BUILD_TYPE=Release \
-DJSONCPP_LIB_BUILD_STATIC=ON \
-DJSONCPP_LIB_BUILD_SHARED=ON \
+ -DJSONCPP_WITH_CMAKE_PACKAGE=ON \
-DCMAKE_INSTALL_PREFIX=/opt/extdeps
cmake --build jsoncpp-1.6.0-build --target install
+echo >> /opt/extdeps/lib/cmake/jsoncpp/jsoncppConfig.cmake '
+# Backport imported target from jsoncpp 1.9.5.
+add_library(JsonCpp::JsonCpp INTERFACE IMPORTED)
+set_target_properties(JsonCpp::JsonCpp PROPERTIES INTERFACE_LINK_LIBRARIES "jsoncpp_lib")'
rm -rf jsoncpp-1.6.0*
+
+#----------------------------------------------------------------------------
+# cppdap
+
+git clone https://github.com/google/cppdap.git
+cd cppdap
+git checkout 03cc18678ed2ed8b2424ec99dee7e4655d876db5 # 2023-05-25
+cd ..
+cmake -S cppdap -B cppdap-build \
+ -DCPPDAP_USE_EXTERNAL_JSONCPP_PACKAGE=ON \
+ -DCMAKE_INSTALL_PREFIX=/opt/extdeps \
+ -DCMAKE_PREFIX_PATH=/opt/extdeps
+cmake --build cppdap-build --target install
+rm -rf cppdap*
diff --git a/.gitlab/ci/pre_build_fedora37_tidy.sh b/.gitlab/ci/pre_build_fedora38_tidy.sh
index 7580ef1..7580ef1 100644
--- a/.gitlab/ci/pre_build_fedora37_tidy.sh
+++ b/.gitlab/ci/pre_build_fedora38_tidy.sh
diff --git a/.gitlab/os-linux.yml b/.gitlab/os-linux.yml
index 4ac7772..f4cc401 100644
--- a/.gitlab/os-linux.yml
+++ b/.gitlab/os-linux.yml
@@ -5,7 +5,7 @@
### Release
.linux_prep_source:
- image: "fedora:37"
+ image: "fedora:38"
variables:
GIT_CLONE_PATH: "$CI_BUILDS_DIR/cmake ci"
@@ -68,8 +68,8 @@
### Fedora
-.fedora37:
- image: "kitware/cmake:ci-fedora37-x86_64-2023-05-17"
+.fedora38:
+ image: "kitware/cmake:ci-fedora38-x86_64-2023-05-22"
variables:
GIT_CLONE_PATH: "$CI_BUILDS_DIR/cmake ci/long file name for testing purposes"
@@ -77,37 +77,37 @@
#### Lint builds
-.fedora37_tidy:
- extends: .fedora37
+.fedora38_tidy:
+ extends: .fedora38
variables:
- CMAKE_CONFIGURATION: fedora37_tidy
+ CMAKE_CONFIGURATION: fedora38_tidy
CTEST_NO_WARNINGS_ALLOWED: 1
CMAKE_CI_NO_INSTALL: 1
-.fedora37_clang_analyzer:
- extends: .fedora37
+.fedora38_clang_analyzer:
+ extends: .fedora38
variables:
- CMAKE_CONFIGURATION: fedora37_clang_analyzer
+ CMAKE_CONFIGURATION: fedora38_clang_analyzer
CMAKE_CI_BUILD_TYPE: Debug
CTEST_NO_WARNINGS_ALLOWED: 1
CMAKE_CI_NO_INSTALL: 1
-.fedora37_sphinx:
- extends: .fedora37
+.fedora38_sphinx:
+ extends: .fedora38
variables:
- CMAKE_CONFIGURATION: fedora37_sphinx
+ CMAKE_CONFIGURATION: fedora38_sphinx
CTEST_NO_WARNINGS_ALLOWED: 1
CTEST_SOURCE_SUBDIRECTORY: "Utilities/Sphinx"
CMAKE_CI_NO_INSTALL: 1
-.fedora37_sphinx_package:
- extends: .fedora37
+.fedora38_sphinx_package:
+ extends: .fedora38
variables:
- CMAKE_CONFIGURATION: fedora37_sphinx_package
+ CMAKE_CONFIGURATION: fedora38_sphinx_package
CTEST_SOURCE_SUBDIRECTORY: "Utilities/Sphinx"
#### Build and test
@@ -153,35 +153,35 @@
CMAKE_CI_BUILD_TYPE: Release
CTEST_NO_WARNINGS_ALLOWED: 1
-.fedora37_extdeps:
- extends: .fedora37
+.fedora38_extdeps:
+ extends: .fedora38
variables:
- CMAKE_CONFIGURATION: fedora37_extdeps
+ CMAKE_CONFIGURATION: fedora38_extdeps
CMAKE_CI_BUILD_TYPE: Release
CTEST_NO_WARNINGS_ALLOWED: 1
-.fedora37_ninja:
- extends: .fedora37
+.fedora38_ninja:
+ extends: .fedora38
variables:
- CMAKE_CONFIGURATION: fedora37_ninja
+ CMAKE_CONFIGURATION: fedora38_ninja
CMAKE_CI_BUILD_TYPE: Release
CTEST_NO_WARNINGS_ALLOWED: 1
-.fedora37_ninja_multi:
- extends: .fedora37
+.fedora38_ninja_multi:
+ extends: .fedora38
variables:
- CMAKE_CONFIGURATION: fedora37_ninja_multi
+ CMAKE_CONFIGURATION: fedora38_ninja_multi
CTEST_NO_WARNINGS_ALLOWED: 1
CMAKE_GENERATOR: "Ninja Multi-Config"
-.fedora37_makefiles:
- extends: .fedora37
+.fedora38_makefiles:
+ extends: .fedora38
variables:
- CMAKE_CONFIGURATION: fedora37_makefiles
+ CMAKE_CONFIGURATION: fedora38_makefiles
CTEST_NO_WARNINGS_ALLOWED: 1
CMAKE_GENERATOR: "Unix Makefiles"
@@ -200,18 +200,25 @@
variables:
CMAKE_CONFIGURATION: debian10_ninja_clang
-.fedora37_makefiles_clang:
- extends: .fedora37
+.fedora38_makefiles_clang:
+ extends: .fedora38
variables:
- CMAKE_CONFIGURATION: fedora37_makefiles_clang
+ CMAKE_CONFIGURATION: fedora38_makefiles_clang
CMAKE_GENERATOR: "Unix Makefiles"
-.fedora37_ninja_clang:
- extends: .fedora37
+.fedora38_ninja_clang:
+ extends: .fedora38
variables:
- CMAKE_CONFIGURATION: fedora37_ninja_clang
+ CMAKE_CONFIGURATION: fedora38_ninja_clang
+
+.fedora38_ninja_multi_clang:
+ extends: .fedora38
+
+ variables:
+ CMAKE_CONFIGURATION: fedora38_ninja_multi_clang
+ CMAKE_GENERATOR: "Ninja Multi-Config"
### Sanitizers
@@ -226,13 +233,13 @@
CTEST_MEMORYCHECK_TYPE: AddressSanitizer
CTEST_MEMORYCHECK_SANITIZER_OPTIONS: ""
-.fedora37_asan:
+.fedora38_asan:
extends:
- - .fedora37
+ - .fedora38
- .fedora_asan_addon
variables:
- CMAKE_CONFIGURATION: fedora37_asan
+ CMAKE_CONFIGURATION: fedora38_asan
### Intel Compiler
@@ -376,28 +383,6 @@
CMAKE_CONFIGURATION: linux_gcc_cxx_modules_ninja_multi
CMAKE_GENERATOR: "Ninja Multi-Config"
-.clang_cxx_modules_x86_64:
- image: "kitware/cmake:ci-clang_cxx_modules-x86_64-2023-02-15"
-
- variables:
- GIT_CLONE_PATH: "$CI_BUILDS_DIR/cmake ci"
- CMAKE_ARCH: x86_64
- CC: "/opt/llvm-p1689/bin/clang"
- CXX: "/opt/llvm-p1689/bin/clang++"
-
-.clang_cxx_modules_ninja:
- extends: .clang_cxx_modules_x86_64
-
- variables:
- CMAKE_CONFIGURATION: linux_clang_cxx_modules_ninja
-
-.clang_cxx_modules_ninja_multi:
- extends: .clang_cxx_modules_x86_64
-
- variables:
- CMAKE_CONFIGURATION: linux_clang_cxx_modules_ninja_multi
- CMAKE_GENERATOR: "Ninja Multi-Config"
-
## Tags
.linux_x86_64_tags:
@@ -478,7 +463,7 @@
.cmake_codespell_linux:
stage: build
- extends: .fedora37
+ extends: .fedora38
script:
- .gitlab/ci/codespell.sh
interruptible: true
@@ -623,7 +608,7 @@
.cmake_org_help:
stage: build
extends:
- - .fedora37
+ - .fedora38
- .linux_x86_64_tags
- .cmake_org_help_artifacts
script:
diff --git a/.gitlab/upload.yml b/.gitlab/upload.yml
index 114808f..caa2119 100644
--- a/.gitlab/upload.yml
+++ b/.gitlab/upload.yml
@@ -1,7 +1,7 @@
# Steps for uploading artifacts
.rsync_upload_package:
- image: "fedora:37"
+ image: "fedora:38"
stage: upload
tags:
- cmake
@@ -21,7 +21,7 @@
.rsync_upload_help:
stage: upload
- image: "fedora:37"
+ image: "fedora:38"
tags:
- cmake
- docker
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 6322aa6..d559c08 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -131,6 +131,23 @@ if(CMake_BUILD_LTO)
endif()
endif()
+# Check whether to build support for the debugger mode.
+if(NOT CMake_TEST_EXTERNAL_CMAKE)
+ if(NOT DEFINED CMake_ENABLE_DEBUGGER)
+ # The debugger uses cppdap, which does not compile everywhere.
+ if(CMAKE_SYSTEM_NAME MATCHES "Windows|Darwin|Linux|BSD|DragonFly|CYGWIN|MSYS"
+ AND NOT (CMAKE_CXX_COMPILER_ID STREQUAL "MSVC" AND CMAKE_CXX_COMPILER_VERSION VERSION_LESS 19.16)
+ AND NOT (CMAKE_CXX_COMPILER_ID STREQUAL "XLClang" AND CMAKE_CXX_COMPILER_VERSION VERSION_LESS 16.1)
+ )
+ set(CMake_ENABLE_DEBUGGER 1)
+ else()
+ set(CMake_ENABLE_DEBUGGER 0)
+ endif()
+ endif()
+else()
+ set(CMake_ENABLE_DEBUGGER 0)
+endif()
+
#-----------------------------------------------------------------------
# a macro to deal with system libraries, implemented as a macro
# simply to improve readability of the main script
@@ -141,7 +158,7 @@ macro(CMAKE_HANDLE_SYSTEM_LIBRARIES)
# Allow the user to enable/disable all system utility library options by
# defining CMAKE_USE_SYSTEM_LIBRARIES or CMAKE_USE_SYSTEM_LIBRARY_${util}.
- set(UTILITIES BZIP2 CURL EXPAT FORM JSONCPP LIBARCHIVE LIBLZMA LIBRHASH LIBUV NGHTTP2 ZLIB ZSTD)
+ set(UTILITIES BZIP2 CPPDAP CURL EXPAT FORM JSONCPP LIBARCHIVE LIBLZMA LIBRHASH LIBUV NGHTTP2 ZLIB ZSTD)
foreach(util IN LISTS UTILITIES)
if(NOT DEFINED CMAKE_USE_SYSTEM_LIBRARY_${util}
AND DEFINED CMAKE_USE_SYSTEM_LIBRARIES)
@@ -169,6 +186,9 @@ macro(CMAKE_HANDLE_SYSTEM_LIBRARIES)
# Optionally use system utility libraries.
option(CMAKE_USE_SYSTEM_LIBARCHIVE "Use system-installed libarchive" "${CMAKE_USE_SYSTEM_LIBRARY_LIBARCHIVE}")
+ if(CMake_ENABLE_DEBUGGER)
+ option(CMAKE_USE_SYSTEM_CPPDAP "Use system-installed cppdap" "${CMAKE_USE_SYSTEM_LIBRARY_CPPDAP}")
+ endif()
option(CMAKE_USE_SYSTEM_CURL "Use system-installed curl" "${CMAKE_USE_SYSTEM_LIBRARY_CURL}")
option(CMAKE_USE_SYSTEM_EXPAT "Use system-installed expat" "${CMAKE_USE_SYSTEM_LIBRARY_EXPAT}")
CMAKE_DEPENDENT_OPTION(CMAKE_USE_SYSTEM_ZLIB "Use system-installed zlib"
@@ -182,7 +202,8 @@ macro(CMAKE_HANDLE_SYSTEM_LIBRARIES)
CMAKE_DEPENDENT_OPTION(CMAKE_USE_SYSTEM_NGHTTP2 "Use system-installed nghttp2"
"${CMAKE_USE_SYSTEM_LIBRARY_NGHTTP2}" "NOT CMAKE_USE_SYSTEM_CURL" ON)
option(CMAKE_USE_SYSTEM_FORM "Use system-installed libform" "${CMAKE_USE_SYSTEM_LIBRARY_FORM}")
- option(CMAKE_USE_SYSTEM_JSONCPP "Use system-installed jsoncpp" "${CMAKE_USE_SYSTEM_LIBRARY_JSONCPP}")
+ CMAKE_DEPENDENT_OPTION(CMAKE_USE_SYSTEM_JSONCPP "Use system-installed jsoncpp"
+ "${CMAKE_USE_SYSTEM_LIBRARY_JSONCPP}" "NOT CMAKE_USE_SYSTEM_CPPDAP" ON)
option(CMAKE_USE_SYSTEM_LIBRHASH "Use system-installed librhash" "${CMAKE_USE_SYSTEM_LIBRARY_LIBRHASH}")
option(CMAKE_USE_SYSTEM_LIBUV "Use system-installed libuv" "${CMAKE_USE_SYSTEM_LIBRARY_LIBUV}")
diff --git a/Help/command/configure_file.rst b/Help/command/configure_file.rst
index 6f4cedf..07dc2e1 100644
--- a/Help/command/configure_file.rst
+++ b/Help/command/configure_file.rst
@@ -12,10 +12,10 @@ Copy a file to another location and modify its contents.
[NEWLINE_STYLE [UNIX|DOS|WIN32|LF|CRLF] ])
Copies an ``<input>`` file to an ``<output>`` file and substitutes
-variable values referenced as ``@VAR@`` or ``${VAR}`` in the input
-file content. Each variable reference will be replaced with the
-current value of the variable, or the empty string if the variable
-is not defined. Furthermore, input lines of the form
+variable values referenced as ``@VAR@``, ``${VAR}``, ``$CACHE{VAR}`` or
+``$ENV{VAR}`` in the input file content. Each variable reference will be
+replaced with the current value of the variable, or the empty string if
+the variable is not defined. Furthermore, input lines of the form
.. code-block:: c
diff --git a/Help/command/include_directories.rst b/Help/command/include_directories.rst
index d2948ed..e68bb81 100644
--- a/Help/command/include_directories.rst
+++ b/Help/command/include_directories.rst
@@ -25,7 +25,7 @@ prepending, independent of the default.
If the ``SYSTEM`` option is given, the compiler will be told the
directories are meant as system include directories on some platforms.
-Signalling this setting might achieve effects such as the compiler
+Signaling this setting might achieve effects such as the compiler
skipping warnings, or these fixed-install system files not being
considered in dependency calculations - see compiler docs.
diff --git a/Help/envvar/CMAKE_LANG_IMPLICIT_LINK_DIRECTORIES_EXCLUDE.rst b/Help/envvar/CMAKE_LANG_IMPLICIT_LINK_DIRECTORIES_EXCLUDE.rst
new file mode 100644
index 0000000..36c79fa
--- /dev/null
+++ b/Help/envvar/CMAKE_LANG_IMPLICIT_LINK_DIRECTORIES_EXCLUDE.rst
@@ -0,0 +1,13 @@
+CMAKE_<LANG>_IMPLICIT_LINK_DIRECTORIES_EXCLUDE
+----------------------------------------------
+
+.. versionadded:: 3.27
+
+.. include:: ENV_VAR.txt
+
+A :ref:`semicolon-separated list <CMake Language Lists>` of directories
+to exclude from the :variable:`CMAKE_<LANG>_IMPLICIT_LINK_DIRECTORIES`
+variable when it is automatically detected from the ``<LANG>`` compiler.
+
+This may be used to work around misconfigured compiler drivers that pass
+extraneous implicit link directories to their linker.
diff --git a/Help/guide/importing-exporting/index.rst b/Help/guide/importing-exporting/index.rst
index 51a09c0..b1812c1 100644
--- a/Help/guide/importing-exporting/index.rst
+++ b/Help/guide/importing-exporting/index.rst
@@ -285,9 +285,9 @@ command.
:end-before: # include CMakePackageConfigHelpers macro
This command generates the ``MathFunctionsTargets.cmake`` file and arranges
-to install it to ``lib/cmake``. The file contains code suitable for
-use by downstreams to import all targets listed in the install command from
-the installation tree.
+to install it to ``${CMAKE_INSTALL_LIBDIR}/cmake/MathFunctions``. The file
+contains code suitable for use by downstreams to import all targets listed in
+the install command from the installation tree.
The ``NAMESPACE`` option will prepend ``MathFunctions::`` to the target names
as they are written to the export file. This convention of double-colons
@@ -317,7 +317,8 @@ were built in its own tree. For example:
.. code-block:: cmake
:linenos:
- include(${INSTALL_PREFIX}/lib/cmake/MathFunctionTargets.cmake)
+ include(GNUInstallDirs)
+ include(${INSTALL_PREFIX}/${CMAKE_INSTALL_LIBDIR}/cmake/MathFunctions/MathFunctionTargets.cmake)
add_executable(myexe src1.c src2.c )
target_link_libraries(myexe PRIVATE MathFunctions::MathFunctions)
diff --git a/Help/manual/cmake-env-variables.7.rst b/Help/manual/cmake-env-variables.7.rst
index f7ae94d..197e56e 100644
--- a/Help/manual/cmake-env-variables.7.rst
+++ b/Help/manual/cmake-env-variables.7.rst
@@ -50,6 +50,7 @@ Environment Variables that Control the Build
/envvar/CMAKE_GENERATOR_TOOLSET
/envvar/CMAKE_INSTALL_MODE
/envvar/CMAKE_LANG_COMPILER_LAUNCHER
+ /envvar/CMAKE_LANG_IMPLICIT_LINK_DIRECTORIES_EXCLUDE
/envvar/CMAKE_LANG_LINKER_LAUNCHER
/envvar/CMAKE_MSVCIDE_RUN_PATH
/envvar/CMAKE_NO_VERBOSE
diff --git a/Help/manual/cmake-file-api.7.rst b/Help/manual/cmake-file-api.7.rst
index 7ff9728..0bdb419 100644
--- a/Help/manual/cmake-file-api.7.rst
+++ b/Help/manual/cmake-file-api.7.rst
@@ -425,7 +425,7 @@ Version 1 does not exist to avoid confusion with that from
{
"kind": "codemodel",
- "version": { "major": 2, "minor": 5 },
+ "version": { "major": 2, "minor": 6 },
"paths": {
"source": "/path/to/top-level-source-dir",
"build": "/path/to/top-level-build-dir"
@@ -1211,6 +1211,28 @@ with members:
an unsigned integer 0-based index into the ``backtraceGraph``
member's ``nodes`` array.
+ ``frameworks``
+ Optional member that is present when, on Apple platforms, there are
+ frameworks. The value is a JSON array with an entry for each directory.
+ Each entry is a JSON object with members:
+
+ ``path``
+ A string specifying the path to the framework directory,
+ represented with forward slashes.
+
+ ``isSystem``
+ Optional member that is present with boolean value ``true`` if
+ the framework is marked as a system one.
+
+ ``backtrace``
+ Optional member that is present when a CMake language backtrace to
+ the :command:`target_link_libraries` or other command invocation
+ that added this framework is available. The value is
+ an unsigned integer 0-based index into the ``backtraceGraph``
+ member's ``nodes`` array.
+
+ This field was added in codemodel version 2.6.
+
``precompileHeaders``
Optional member that is present when :command:`target_precompile_headers`
or other command invocations set :prop_tgt:`PRECOMPILE_HEADERS` on the
diff --git a/Help/manual/cmake.1.rst b/Help/manual/cmake.1.rst
index 1ea7626..b5848f7 100644
--- a/Help/manual/cmake.1.rst
+++ b/Help/manual/cmake.1.rst
@@ -517,6 +517,53 @@ Options
If ``<type>`` is omitted, ``configure`` is assumed. The current working
directory must contain CMake preset files.
+.. option:: --debugger
+
+ Enables interactive debugging of the CMake language. CMake exposes a debugging
+ interface on the pipe named by :option:`--debugger-pipe <cmake --debugger-pipe>`
+ that conforms to the `Debug Adapter Protocol`_ specification with the following
+ modifications.
+
+ The ``initialize`` response includes an additional field named ``cmakeVersion``
+ which specifies the version of CMake being debugged.
+
+ .. code-block:: json
+ :caption: Debugger initialize response
+
+ {
+ "cmakeVersion": {
+ "major": 3,
+ "minor": 27,
+ "patch": 0,
+ "full": "3.27.0"
+ }
+ }
+
+ The members are:
+
+ ``major``
+ An integer specifying the major version number.
+
+ ``minor``
+ An integer specifying the minor version number.
+
+ ``patch``
+ An integer specifying the patch version number.
+
+ ``full``
+ A string specifying the full CMake version.
+
+.. _`Debug Adapter Protocol`: https://microsoft.github.io/debug-adapter-protocol/
+
+.. option:: --debugger-pipe <pipe name>, --debugger-pipe=<pipe name>
+
+ Name of the pipe (on Windows) or domain socket (on Unix) to use for
+ debugger communication.
+
+.. option:: --debugger-dap-log <log path>, --debugger-dap-log=<log path>
+
+ Logs all debugger communication to the specified file.
+
.. _`Build Tool Mode`:
Build a Project
@@ -809,6 +856,12 @@ Available commands are:
``true`` if TLS support is enabled and ``false`` otherwise.
+ ``debugger``
+ .. versionadded:: 3.27
+
+ ``true`` if the :option:`--debugger <cmake --debugger>` mode
+ is supported and ``false`` otherwise.
+
.. option:: cat [--] <files>...
.. versionadded:: 3.18
diff --git a/Help/release/dev/FileAPI-Frameworks.rst b/Help/release/dev/FileAPI-Frameworks.rst
new file mode 100644
index 0000000..65cf043
--- /dev/null
+++ b/Help/release/dev/FileAPI-Frameworks.rst
@@ -0,0 +1,7 @@
+FileAPI-Frameworks
+------------------
+
+* The :manual:`cmake-file-api(7)` "codemodel" version 2 ``version`` field has
+ been updated to 2.6.
+* The :manual:`cmake-file-api(7)` "codemodel" version 2 "target" object gained
+ a new "frameworks" field in the "compileGroups" objects.
diff --git a/Help/release/dev/cmake-debugger.rst b/Help/release/dev/cmake-debugger.rst
new file mode 100644
index 0000000..bfc4f6c
--- /dev/null
+++ b/Help/release/dev/cmake-debugger.rst
@@ -0,0 +1,5 @@
+cmake-debugger
+--------------
+
+* :manual:`cmake(1)` now supports interactive debugging of the CMake language.
+ See the :option:`--debugger <cmake --debugger>` option.
diff --git a/Help/release/dev/cmake-verbose-print-build-tool-command.rst b/Help/release/dev/cmake-verbose-print-build-tool-command.rst
new file mode 100644
index 0000000..4f13231
--- /dev/null
+++ b/Help/release/dev/cmake-verbose-print-build-tool-command.rst
@@ -0,0 +1,5 @@
+cmake-verbose-print-build-tool-command
+--------------------------------------
+
+* ``cmake --build $dir --verbose`` will now print the working directory and
+ command line used to perform the build.
diff --git a/Help/release/dev/ep-update-disconnected.rst b/Help/release/dev/ep-update-disconnected.rst
new file mode 100644
index 0000000..a162698
--- /dev/null
+++ b/Help/release/dev/ep-update-disconnected.rst
@@ -0,0 +1,14 @@
+ep-update-disconnected
+----------------------
+
+* The ``update`` and ``patch`` steps of an :module:`ExternalProject` will now
+ always re-execute if any of their details change, even if
+ ``UPDATE_DISCONNECTED`` was set to true in the call to
+ :command:`ExternalProject_Add`. If using the GIT download method and the
+ ``GIT_TAG`` is changed and the new ``GIT_TAG`` isn't already known locally,
+ this is now a fatal error instead of silently using the previous ``GIT_TAG``.
+
+* When ``UPDATE_DISCONNECTED`` is set to true in a call to
+ :command:`ExternalProject_Add`, the ``configure`` step will no longer
+ re-run on every build. It will only re-run if details of the ``download``,
+ ``update`` or ``patch`` step change.
diff --git a/Help/variable/CMAKE_LANG_IMPLICIT_LINK_DIRECTORIES.rst b/Help/variable/CMAKE_LANG_IMPLICIT_LINK_DIRECTORIES.rst
index 081c4da..7e008df 100644
--- a/Help/variable/CMAKE_LANG_IMPLICIT_LINK_DIRECTORIES.rst
+++ b/Help/variable/CMAKE_LANG_IMPLICIT_LINK_DIRECTORIES.rst
@@ -6,9 +6,14 @@ Implicit linker search path detected for language ``<LANG>``.
Compilers typically pass directories containing language runtime
libraries and default library search paths when they invoke a linker.
These paths are implicit linker search directories for the compiler's
-language. For each language enabled by the :command:`project` or
+language.
+
+For each language enabled by the :command:`project` or
:command:`enable_language` command, CMake automatically detects these
directories and reports the results in this variable.
+The :envvar:`CMAKE_<LANG>_IMPLICIT_LINK_DIRECTORIES_EXCLUDE` environment
+variable may be set to exclude specific directories from the automatically
+detected results.
When linking to a static library, CMake adds the implicit link directories
from this variable for each language used in the static library (except
diff --git a/Help/variable/MINGW.rst b/Help/variable/MINGW.rst
index 27c56ea..fc2af2d 100644
--- a/Help/variable/MINGW.rst
+++ b/Help/variable/MINGW.rst
@@ -3,6 +3,7 @@ MINGW
.. versionadded:: 3.2
-``True`` when using MinGW
+Set to a true value when at least one language is enabled
+with a compiler targeting the GNU ABI on Windows (MinGW).
-Set to ``true`` when the compiler is some version of MinGW.
+Otherwise, this variable is not set by CMake.
diff --git a/Modules/CMakeASMCompiler.cmake.in b/Modules/CMakeASMCompiler.cmake.in
index 8a1718b..1efd9f5 100644
--- a/Modules/CMakeASMCompiler.cmake.in
+++ b/Modules/CMakeASMCompiler.cmake.in
@@ -17,6 +17,6 @@ set(CMAKE_ASM@ASM_DIALECT@_COMPILER_ENV_VAR "@_CMAKE_ASM_COMPILER_ENV_VAR@")
set(CMAKE_ASM@ASM_DIALECT@_IGNORE_EXTENSIONS h;H;o;O;obj;OBJ;def;DEF;rc;RC)
set(CMAKE_ASM@ASM_DIALECT@_LINKER_PREFERENCE 0)
-set(CMAKE_ASM@ASM_DIALECT@_LINKER_DEPFILE_SUPPORTED "@CMAKE_ASM_LINKER_DEPFILE_SUPPORTED@")
+set(CMAKE_ASM@ASM_DIALECT@_LINKER_DEPFILE_SUPPORTED @CMAKE_ASM_LINKER_DEPFILE_SUPPORTED@)
@CMAKE_ASM_COMPILER_CUSTOM_CODE@
diff --git a/Modules/CMakeCCompiler.cmake.in b/Modules/CMakeCCompiler.cmake.in
index cf3a242..2f0b774 100644
--- a/Modules/CMakeCCompiler.cmake.in
+++ b/Modules/CMakeCCompiler.cmake.in
@@ -39,7 +39,7 @@ set(CMAKE_C_COMPILER_ID_RUN 1)
set(CMAKE_C_SOURCE_FILE_EXTENSIONS c;m)
set(CMAKE_C_IGNORE_EXTENSIONS h;H;o;O;obj;OBJ;def;DEF;rc;RC)
set(CMAKE_C_LINKER_PREFERENCE 10)
-set(CMAKE_C_LINKER_DEPFILE_SUPPORTED "@CMAKE_C_LINKER_DEPFILE_SUPPORTED@")
+set(CMAKE_C_LINKER_DEPFILE_SUPPORTED @CMAKE_C_LINKER_DEPFILE_SUPPORTED@)
# Save compiler ABI information.
set(CMAKE_C_SIZEOF_DATA_PTR "@CMAKE_C_SIZEOF_DATA_PTR@")
diff --git a/Modules/CMakeCUDACompiler.cmake.in b/Modules/CMakeCUDACompiler.cmake.in
index 3d7d552..3c28c28 100644
--- a/Modules/CMakeCUDACompiler.cmake.in
+++ b/Modules/CMakeCUDACompiler.cmake.in
@@ -30,7 +30,7 @@ set(CMAKE_CUDA_COMPILER_ID_RUN 1)
set(CMAKE_CUDA_SOURCE_FILE_EXTENSIONS cu)
set(CMAKE_CUDA_LINKER_PREFERENCE 15)
set(CMAKE_CUDA_LINKER_PREFERENCE_PROPAGATES 1)
-set(CMAKE_CUDA_LINKER_DEPFILE_SUPPORTED "@CMAKE_CUDA_LINKER_DEPFILE_SUPPORTED@")
+set(CMAKE_CUDA_LINKER_DEPFILE_SUPPORTED @CMAKE_CUDA_LINKER_DEPFILE_SUPPORTED@)
set(CMAKE_CUDA_SIZEOF_DATA_PTR "@CMAKE_CUDA_SIZEOF_DATA_PTR@")
set(CMAKE_CUDA_COMPILER_ABI "@CMAKE_CUDA_COMPILER_ABI@")
diff --git a/Modules/CMakeCXXCompiler.cmake.in b/Modules/CMakeCXXCompiler.cmake.in
index 2052e7f..8b6f82b 100644
--- a/Modules/CMakeCXXCompiler.cmake.in
+++ b/Modules/CMakeCXXCompiler.cmake.in
@@ -50,7 +50,7 @@ endforeach()
set(CMAKE_CXX_LINKER_PREFERENCE 30)
set(CMAKE_CXX_LINKER_PREFERENCE_PROPAGATES 1)
-set(CMAKE_CXX_LINKER_DEPFILE_SUPPORTED "@CMAKE_CXX_LINKER_DEPFILE_SUPPORTED@")
+set(CMAKE_CXX_LINKER_DEPFILE_SUPPORTED @CMAKE_CXX_LINKER_DEPFILE_SUPPORTED@)
# Save compiler ABI information.
set(CMAKE_CXX_SIZEOF_DATA_PTR "@CMAKE_CXX_SIZEOF_DATA_PTR@")
diff --git a/Modules/CMakeDetermineCompilerABI.cmake b/Modules/CMakeDetermineCompilerABI.cmake
index 3fd54cc..13bfeec 100644
--- a/Modules/CMakeDetermineCompilerABI.cmake
+++ b/Modules/CMakeDetermineCompilerABI.cmake
@@ -42,7 +42,7 @@ function(CMAKE_DETERMINE_COMPILER_ABI lang src)
__TestCompiler_setTryCompileTargetType()
# Avoid failing ABI detection on warnings.
- string(REGEX REPLACE "(^| )-Werror([= ][^ ]*)?( |$)" " " CMAKE_${lang}_FLAGS "${CMAKE_${lang}_FLAGS}")
+ string(REGEX REPLACE "(^| )-Werror([= ][^-][^ ]*)?( |$)" " " CMAKE_${lang}_FLAGS "${CMAKE_${lang}_FLAGS}")
# Save the current LC_ALL, LC_MESSAGES, and LANG environment variables
# and set them to "C" that way GCC's "search starts here" text is in
@@ -181,6 +181,10 @@ function(CMAKE_DETERMINE_COMPILER_ABI lang src)
endif()
endif()
+ if(DEFINED ENV{CMAKE_${lang}_IMPLICIT_LINK_DIRECTORIES_EXCLUDE})
+ list(REMOVE_ITEM implicit_dirs $ENV{CMAKE_${lang}_IMPLICIT_LINK_DIRECTORIES_EXCLUDE})
+ endif()
+
set(CMAKE_${lang}_IMPLICIT_LINK_LIBRARIES "${implicit_libs}" PARENT_SCOPE)
set(CMAKE_${lang}_IMPLICIT_LINK_DIRECTORIES "${implicit_dirs}" PARENT_SCOPE)
set(CMAKE_${lang}_IMPLICIT_LINK_FRAMEWORK_DIRECTORIES "${implicit_fwks}" PARENT_SCOPE)
diff --git a/Modules/CMakeFindBinUtils.cmake b/Modules/CMakeFindBinUtils.cmake
index 604d25c..461839a 100644
--- a/Modules/CMakeFindBinUtils.cmake
+++ b/Modules/CMakeFindBinUtils.cmake
@@ -135,7 +135,7 @@ elseif("x${CMAKE_${_CMAKE_PROCESSING_LANGUAGE}_COMPILER_ID}" MATCHES "^xIAR$")
elseif("${CMAKE_${_CMAKE_PROCESSING_LANGUAGE}_COMPILER_ARCHITECTURE_ID}" IN_LIST _CMAKE_IAR_XTOOLS)
__append_IAR_tool(AR "xar")
if("${CMAKE_${_CMAKE_PROCESSING_LANGUAGE}_COMPILER_ARCHITECTURE_ID}" STREQUAL "AVR" AND
- (CMAKE_${_CMAKE_PROCESSING_LANGUAGE}_COMPILER_VERSION VERSION_GREATER 7))
+ (CMAKE_${_CMAKE_PROCESSING_LANGUAGE}_COMPILER_VERSION VERSION_GREATER_EQUAL 8))
# IAR UBROF Linker V8.10+ for Microchip AVR is `xlinkavr`
__append_IAR_tool(LINKER "xlink${_CMAKE_IAR_LOWER_ARCHITECTURE_ID}")
else()
diff --git a/Modules/CMakeFortranCompiler.cmake.in b/Modules/CMakeFortranCompiler.cmake.in
index a7caf2b..6a2be28 100644
--- a/Modules/CMakeFortranCompiler.cmake.in
+++ b/Modules/CMakeFortranCompiler.cmake.in
@@ -29,7 +29,7 @@ set(CMAKE_Fortran_COMPILER_ID_RUN 1)
set(CMAKE_Fortran_SOURCE_FILE_EXTENSIONS f;F;fpp;FPP;f77;F77;f90;F90;for;For;FOR;f95;F95;f03;F03;f08;F08@CMAKE_Fortran_VENDOR_SOURCE_FILE_EXTENSIONS@)
set(CMAKE_Fortran_IGNORE_EXTENSIONS h;H;o;O;obj;OBJ;def;DEF;rc;RC)
set(CMAKE_Fortran_LINKER_PREFERENCE 20)
-set(CMAKE_Fortran_LINKER_DEPFILE_SUPPORTED "@CMAKE_Fortran_LINKER_DEPFILE_SUPPORTED@")
+set(CMAKE_Fortran_LINKER_DEPFILE_SUPPORTED @CMAKE_Fortran_LINKER_DEPFILE_SUPPORTED@)
if(UNIX)
set(CMAKE_Fortran_OUTPUT_EXTENSION .o)
else()
diff --git a/Modules/CMakeHIPCompiler.cmake.in b/Modules/CMakeHIPCompiler.cmake.in
index 32c1223..c94153b 100644
--- a/Modules/CMakeHIPCompiler.cmake.in
+++ b/Modules/CMakeHIPCompiler.cmake.in
@@ -26,7 +26,7 @@ set(CMAKE_HIP_COMPILER_ID_RUN 1)
set(CMAKE_HIP_SOURCE_FILE_EXTENSIONS hip)
set(CMAKE_HIP_LINKER_PREFERENCE 90)
set(CMAKE_HIP_LINKER_PREFERENCE_PROPAGATES 1)
-set(CMAKE_HIP_LINKER_DEPFILE_SUPPORTED "@CMAKE_HIP_LINKER_DEPFILE_SUPPORTED@")
+set(CMAKE_HIP_LINKER_DEPFILE_SUPPORTED @CMAKE_HIP_LINKER_DEPFILE_SUPPORTED@)
set(CMAKE_HIP_SIZEOF_DATA_PTR "@CMAKE_HIP_SIZEOF_DATA_PTR@")
set(CMAKE_HIP_COMPILER_ABI "@CMAKE_HIP_COMPILER_ABI@")
diff --git a/Modules/CMakeOBJCCompiler.cmake.in b/Modules/CMakeOBJCCompiler.cmake.in
index 0ceb804..de73645 100644
--- a/Modules/CMakeOBJCCompiler.cmake.in
+++ b/Modules/CMakeOBJCCompiler.cmake.in
@@ -37,7 +37,7 @@ set(CMAKE_OBJC_COMPILER_ID_RUN 1)
set(CMAKE_OBJC_SOURCE_FILE_EXTENSIONS m)
set(CMAKE_OBJC_IGNORE_EXTENSIONS h;H;o;O)
set(CMAKE_OBJC_LINKER_PREFERENCE 5)
-set(CMAKE_OBJC_LINKER_DEPFILE_SUPPORTED "@CMAKE_OBJC_LINKER_DEPFILE_SUPPORTED@")
+set(CMAKE_OBJC_LINKER_DEPFILE_SUPPORTED @CMAKE_OBJC_LINKER_DEPFILE_SUPPORTED@)
foreach (lang C CXX OBJCXX)
foreach(extension IN LISTS CMAKE_OBJC_SOURCE_FILE_EXTENSIONS)
diff --git a/Modules/CMakeOBJCXXCompiler.cmake.in b/Modules/CMakeOBJCXXCompiler.cmake.in
index f087ec3..94d24ff 100644
--- a/Modules/CMakeOBJCXXCompiler.cmake.in
+++ b/Modules/CMakeOBJCXXCompiler.cmake.in
@@ -54,7 +54,7 @@ endforeach()
set(CMAKE_OBJCXX_LINKER_PREFERENCE 25)
set(CMAKE_OBJCXX_LINKER_PREFERENCE_PROPAGATES 1)
-set(CMAKE_OBJCXX_LINKER_DEPFILE_SUPPORTED "@CMAKE_OBJCXX_LINKER_DEPFILE_SUPPORTED@")
+set(CMAKE_OBJCXX_LINKER_DEPFILE_SUPPORTED @CMAKE_OBJCXX_LINKER_DEPFILE_SUPPORTED@)
# Save compiler ABI information.
set(CMAKE_OBJCXX_SIZEOF_DATA_PTR "@CMAKE_OBJCXX_SIZEOF_DATA_PTR@")
diff --git a/Modules/CMakePackageConfigHelpers.cmake b/Modules/CMakePackageConfigHelpers.cmake
index 1dc850a..581e65c 100644
--- a/Modules/CMakePackageConfigHelpers.cmake
+++ b/Modules/CMakePackageConfigHelpers.cmake
@@ -188,7 +188,7 @@ resulting version file. Depending on the ``COMPATIBILITY``, the corresponding
``BasicConfigVersion-<COMPATIBILITY>.cmake.in`` file is used.
Please note that these files are internal to CMake and you should not call
:command:`configure_file()` on them yourself, but they can be used as starting
-point to create more sophisticted custom ``ConfigVersion.cmake`` files.
+point to create more sophisticated custom ``ConfigVersion.cmake`` files.
Example Generating Package Files
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
diff --git a/Modules/CPackComponent.cmake b/Modules/CPackComponent.cmake
index 529f4e7..3b23b9f 100644
--- a/Modules/CPackComponent.cmake
+++ b/Modules/CPackComponent.cmake
@@ -149,7 +149,7 @@ installed or not.
REQUIRED indicates that this component is required, and therefore will
always be installed. It will be visible in the graphical installer,
but it cannot be unselected. (Typically, required components are
-shown greyed out).
+shown grayed out).
DISABLED indicates that this component should be disabled (unselected)
by default. The user is free to select this component for
diff --git a/Modules/Compiler/Clang-HIP.cmake b/Modules/Compiler/Clang-HIP.cmake
index 7e3c99c..92925f1 100644
--- a/Modules/Compiler/Clang-HIP.cmake
+++ b/Modules/Compiler/Clang-HIP.cmake
@@ -1,13 +1,5 @@
include(Compiler/Clang)
-#
-# For now, deactivate globally linker dependency file support because
-# HIP compiler is based on Clang which provides support of other languages
-#
-foreach (lang IN ITEMS "C" "CXX" "OBJC" "OBJCXX" "Fortran" "ASM")
- set(CMAKE_${lang}_LINKER_DEPFILE_SUPPORTED FALSE)
-endforeach()
-
__compiler_clang(HIP)
__compiler_clang_cxx_standards(HIP)
diff --git a/Modules/Compiler/GNU.cmake b/Modules/Compiler/GNU.cmake
index f140208..251e05a 100644
--- a/Modules/Compiler/GNU.cmake
+++ b/Modules/Compiler/GNU.cmake
@@ -53,7 +53,7 @@ macro(__compiler_gnu lang)
endif()
# define flags for linker depfile generation
- if (NOT DEFINED CMAKE_${lang}_LINKER_DEPFILE_SUPPORTED)
+ if(NOT DEFINED CMAKE_${lang}_LINKER_DEPFILE_SUPPORTED)
## Ensure ninja tool is recent enough...
if(CMAKE_GENERATOR MATCHES "^Ninja")
# Ninja 1.10 or upper is required
@@ -71,7 +71,7 @@ macro(__compiler_gnu lang)
if (NOT DEFINED CMAKE_${lang}_LINKER_DEPFILE_SUPPORTED)
## check if this feature is supported by the linker
- execute_process(COMMAND "${CMAKE_LINKER}" --help
+ execute_process(COMMAND "${CMAKE_${lang}_COMPILER}" -Wl,--help
OUTPUT_VARIABLE _linker_capabilities
ERROR_VARIABLE _linker_capabilities)
if(_linker_capabilities MATCHES "--dependency-file")
@@ -82,6 +82,7 @@ macro(__compiler_gnu lang)
unset(_linker_capabilities)
endif()
endif()
+
if (CMAKE_${lang}_LINKER_DEPFILE_SUPPORTED)
set(CMAKE_${lang}_LINKER_DEPFILE_FLAGS "LINKER:--dependency-file,<DEP_FILE>")
set(CMAKE_${lang}_LINKER_DEPFILE_FORMAT gcc)
diff --git a/Modules/ExternalProject.cmake b/Modules/ExternalProject.cmake
index 1fdd754..bac126c 100644
--- a/Modules/ExternalProject.cmake
+++ b/Modules/ExternalProject.cmake
@@ -448,13 +448,23 @@ External Project Definition
``UPDATE_DISCONNECTED <bool>``
.. versionadded:: 3.2
- When enabled, this option causes the update step to be skipped. It does
- not, however, prevent the download step. The update step can still be
+ When enabled, this option causes the update step to be skipped (but see
+ below for changed behavior where this is not the case). It does not
+ prevent the download step. The update step can still be
added as a step target (see :command:`ExternalProject_Add_StepTargets`)
and called manually. This is useful if you want to allow developers to
build the project when disconnected from the network (the network may
still be needed for the download step though).
+ .. versionchanged:: 3.27
+
+ When ``UPDATE_DISCONNECTED`` is true, the update step will be executed
+ if any details about the update or download step are changed.
+ Furthermore, if using the git download/update method, the update
+ logic will be modified to skip attempts to contact the remote.
+ If the ``GIT_TAG`` mentions a ref that is not known locally, the
+ update step will halt with a fatal error.
+
When this option is present, it is generally advisable to make the value
a cache variable under the developer's control rather than hard-coding
it. If this option is not present, the default value is taken from the
@@ -3216,7 +3226,7 @@ function(_ep_get_update_disconnected var name)
endfunction()
function(_ep_add_update_command name)
- ExternalProject_Get_Property(${name} source_dir tmp_dir)
+ ExternalProject_Get_Property(${name} source_dir stamp_dir tmp_dir)
get_property(cmd_set TARGET ${name} PROPERTY _EP_UPDATE_COMMAND SET)
get_property(cmd TARGET ${name} PROPERTY _EP_UPDATE_COMMAND)
@@ -3230,6 +3240,7 @@ function(_ep_add_update_command name)
set(work_dir)
set(comment)
set(always)
+ set(file_deps)
if(cmd_set)
set(work_dir ${source_dir})
@@ -3291,6 +3302,7 @@ function(_ep_add_update_command name)
endif()
set(work_dir ${source_dir})
set(comment "Performing update step for '${name}'")
+ set(comment_disconnected "Performing disconnected update step for '${name}'")
get_property(git_tag
TARGET ${name}
@@ -3344,8 +3356,10 @@ function(_ep_add_update_command name)
_ep_get_git_submodules_recurse(git_submodules_recurse)
+ set(update_script "${tmp_dir}/${name}-gitupdate.cmake")
+ list(APPEND file_deps ${update_script})
_ep_write_gitupdate_script(
- "${tmp_dir}/${name}-gitupdate.cmake"
+ "${update_script}"
"${GIT_EXECUTABLE}"
"${git_tag}"
"${git_remote_name}"
@@ -3356,7 +3370,8 @@ function(_ep_add_update_command name)
"${work_dir}"
"${git_update_strategy}"
)
- set(cmd ${CMAKE_COMMAND} -P ${tmp_dir}/${name}-gitupdate.cmake)
+ set(cmd ${CMAKE_COMMAND} -Dcan_fetch=YES -P ${update_script})
+ set(cmd_disconnected ${CMAKE_COMMAND} -Dcan_fetch=NO -P ${update_script})
set(always 1)
elseif(hg_repository)
if(NOT HG_EXECUTABLE)
@@ -3364,6 +3379,7 @@ function(_ep_add_update_command name)
endif()
set(work_dir ${source_dir})
set(comment "Performing update step (hg pull) for '${name}'")
+ set(comment_disconnected "Performing disconnected update step for '${name}'")
get_property(hg_tag
TARGET ${name}
@@ -3389,9 +3405,23 @@ Update to Mercurial >= 2.1.1.
${HG_EXECUTABLE} pull
COMMAND ${HG_EXECUTABLE} update ${hg_tag}
)
+ set(cmd_disconnected ${HG_EXECUTABLE} update ${hg_tag})
set(always 1)
endif()
+ # We use configure_file() to write the update_info_file so that the file's
+ # timestamp is not updated if we don't change the contents
+ if(NOT DEFINED cmd_disconnected)
+ set(cmd_disconnected "${cmd}")
+ endif()
+ set(update_info_file ${stamp_dir}/${name}-update-info.txt)
+ list(APPEND file_deps ${update_info_file})
+ configure_file(
+ "${CMAKE_CURRENT_FUNCTION_LIST_DIR}/ExternalProject/UpdateInfo.txt.in"
+ "${update_info_file}"
+ @ONLY
+ )
+
get_property(log
TARGET ${name}
PROPERTY _EP_LOG_UPDATE
@@ -3425,16 +3455,39 @@ Update to Mercurial >= 2.1.1.
EXCLUDE_FROM_MAIN \${update_disconnected}
WORKING_DIRECTORY \${work_dir}
DEPENDEES download
+ DEPENDS \${file_deps}
${log}
${uses_terminal}
)"
)
+ if(update_disconnected)
+ if(NOT DEFINED comment_disconnected)
+ set(comment_disconnected "${comment}")
+ endif()
+ set(__cmdQuoted)
+ foreach(__item IN LISTS cmd_disconnected)
+ string(APPEND __cmdQuoted " [==[${__item}]==]")
+ endforeach()
+
+ cmake_language(EVAL CODE "
+ ExternalProject_Add_Step(${name} update_disconnected
+ INDEPENDENT TRUE
+ COMMENT \${comment_disconnected}
+ COMMAND ${__cmdQuoted}
+ WORKING_DIRECTORY \${work_dir}
+ DEPENDEES download
+ DEPENDS \${file_deps}
+ ${log}
+ ${uses_terminal}
+ )"
+ )
+ endif()
endfunction()
function(_ep_add_patch_command name)
- ExternalProject_Get_Property(${name} source_dir)
+ ExternalProject_Get_Property(${name} source_dir stamp_dir)
get_property(cmd_set TARGET ${name} PROPERTY _EP_PATCH_COMMAND SET)
get_property(cmd TARGET ${name} PROPERTY _EP_PATCH_COMMAND)
@@ -3445,6 +3498,15 @@ function(_ep_add_patch_command name)
set(work_dir ${source_dir})
endif()
+ # We use configure_file() to write the patch_info_file so that the file's
+ # timestamp is not updated if we don't change the contents
+ set(patch_info_file ${stamp_dir}/${name}-patch-info.txt)
+ configure_file(
+ "${CMAKE_CURRENT_FUNCTION_LIST_DIR}/ExternalProject/PatchInfo.txt.in"
+ "${patch_info_file}"
+ @ONLY
+ )
+
get_property(log
TARGET ${name}
PROPERTY _EP_LOG_PATCH
@@ -3466,11 +3528,6 @@ function(_ep_add_patch_command name)
endif()
_ep_get_update_disconnected(update_disconnected ${name})
- if(update_disconnected)
- set(patch_dep download)
- else()
- set(patch_dep update)
- endif()
set(__cmdQuoted)
foreach(__item IN LISTS cmd)
@@ -3481,11 +3538,28 @@ function(_ep_add_patch_command name)
INDEPENDENT TRUE
COMMAND ${__cmdQuoted}
WORKING_DIRECTORY \${work_dir}
- DEPENDEES \${patch_dep}
+ EXCLUDE_FROM_MAIN \${update_disconnected}
+ DEPENDEES update
+ DEPENDS \${patch_info_file}
${log}
${uses_terminal}
)"
)
+
+ if(update_disconnected)
+ cmake_language(EVAL CODE "
+ ExternalProject_Add_Step(${name} patch_disconnected
+ INDEPENDENT TRUE
+ COMMAND ${__cmdQuoted}
+ WORKING_DIRECTORY \${work_dir}
+ DEPENDEES update_disconnected
+ DEPENDS \${patch_info_file}
+ ${log}
+ ${uses_terminal}
+ )"
+ )
+ endif()
+
endfunction()
function(_ep_get_file_deps var name)
@@ -3695,6 +3769,13 @@ function(_ep_add_configure_command name)
list(APPEND file_deps ${tmp_dir}/${name}-cfgcmd.txt)
list(APPEND file_deps ${_ep_cache_args_script})
+ _ep_get_update_disconnected(update_disconnected ${name})
+ if(update_disconnected)
+ set(dependees patch_disconnected)
+ else()
+ set(dependees patch)
+ endif()
+
get_property(log
TARGET ${name}
PROPERTY _EP_LOG_CONFIGURE
@@ -3724,7 +3805,7 @@ function(_ep_add_configure_command name)
INDEPENDENT FALSE
COMMAND ${__cmdQuoted}
WORKING_DIRECTORY \${binary_dir}
- DEPENDEES patch
+ DEPENDEES \${dependees}
DEPENDS \${file_deps}
${log}
${uses_terminal}
diff --git a/Modules/ExternalProject/PatchInfo.txt.in b/Modules/ExternalProject/PatchInfo.txt.in
new file mode 100644
index 0000000..112953c
--- /dev/null
+++ b/Modules/ExternalProject/PatchInfo.txt.in
@@ -0,0 +1,6 @@
+# This is a generated file and its contents are an internal implementation detail.
+# The update step will be re-executed if anything in this file changes.
+# No other meaning or use of this file is supported.
+
+command=@cmd@
+work_dir=@work_dir@
diff --git a/Modules/ExternalProject/UpdateInfo.txt.in b/Modules/ExternalProject/UpdateInfo.txt.in
new file mode 100644
index 0000000..67ee434
--- /dev/null
+++ b/Modules/ExternalProject/UpdateInfo.txt.in
@@ -0,0 +1,7 @@
+# This is a generated file and its contents are an internal implementation detail.
+# The patch step will be re-executed if anything in this file changes.
+# No other meaning or use of this file is supported.
+
+command (connected)=@cmd@
+command (disconnected)=@cmd_disconnected@
+work_dir=@work_dir@
diff --git a/Modules/ExternalProject/gitupdate.cmake.in b/Modules/ExternalProject/gitupdate.cmake.in
index 50f0167..eb3cda7 100644
--- a/Modules/ExternalProject/gitupdate.cmake.in
+++ b/Modules/ExternalProject/gitupdate.cmake.in
@@ -3,6 +3,15 @@
cmake_minimum_required(VERSION 3.5)
+function(do_fetch)
+ message(VERBOSE "Fetching latest from the remote @git_remote_name@")
+ execute_process(
+ COMMAND "@git_EXECUTABLE@" --git-dir=.git fetch --tags --force "@git_remote_name@"
+ WORKING_DIRECTORY "@work_dir@"
+ COMMAND_ERROR_IS_FATAL LAST
+ )
+endfunction()
+
function(get_hash_for_ref ref out_var err_var)
execute_process(
COMMAND "@git_EXECUTABLE@" --git-dir=.git rev-parse "${ref}^0"
@@ -33,17 +42,16 @@ execute_process(
)
if(show_ref_output MATCHES "^[a-z0-9]+[ \\t]+refs/remotes/")
# Given a full remote/branch-name and we know about it already. Since
- # branches can move around, we always have to fetch.
- set(fetch_required YES)
+ # branches can move around, we should always fetch, if permitted.
+ if(can_fetch)
+ do_fetch()
+ endif()
set(checkout_name "@git_tag@")
elseif(show_ref_output MATCHES "^[a-z0-9]+[ \\t]+refs/tags/")
# Given a tag name that we already know about. We don't know if the tag we
- # have matches the remote though (tags can move), so we should fetch.
- set(fetch_required YES)
- set(checkout_name "@git_tag@")
-
- # Special case to preserve backward compatibility: if we are already at the
+ # have matches the remote though (tags can move), so we should fetch. As a
+ # special case to preserve backward compatibility, if we are already at the
# same commit as the tag we hold locally, don't do a fetch and assume the tag
# hasn't moved on the remote.
# FIXME: We should provide an option to always fetch for this case
@@ -53,12 +61,20 @@ elseif(show_ref_output MATCHES "^[a-z0-9]+[ \\t]+refs/tags/")
return()
endif()
+ if(can_fetch)
+ do_fetch()
+ endif()
+ set(checkout_name "@git_tag@")
+
elseif(show_ref_output MATCHES "^[a-z0-9]+[ \\t]+refs/heads/")
# Given a branch name without any remote and we already have a branch by that
# name. We might already have that branch checked out or it might be a
- # different branch. It isn't safe to use a bare branch name without the
- # remote, so do a fetch and replace the ref with one that includes the remote.
- set(fetch_required YES)
+ # different branch. It isn't fully safe to use a bare branch name without the
+ # remote, so do a fetch (if allowed) and replace the ref with one that
+ # includes the remote.
+ if(can_fetch)
+ do_fetch()
+ endif()
set(checkout_name "@git_remote_name@/@git_tag@")
else()
@@ -70,20 +86,26 @@ else()
elseif(tag_sha STREQUAL "")
# We don't know about this ref yet, so we have no choice but to fetch.
+ if(NOT can_fetch)
+ message(FATAL_ERROR
+ "Requested git ref \"@git_tag@\" is not present locally, and not "
+ "allowed to contact remote due to UPDATE_DISCONNECTED setting."
+ )
+ endif()
+
# We deliberately swallow any error message at the default log level
# because it can be confusing for users to see a failed git command.
# That failure is being handled here, so it isn't an error.
- set(fetch_required YES)
- set(checkout_name "@git_tag@")
if(NOT error_msg STREQUAL "")
message(VERBOSE "${error_msg}")
endif()
+ do_fetch()
+ set(checkout_name "@git_tag@")
else()
# We have the commit, so we know we were asked to find a commit hash
# (otherwise it would have been handled further above), but we don't
- # have that commit checked out yet
- set(fetch_required NO)
+ # have that commit checked out yet. We don't need to fetch from the remote.
set(checkout_name "@git_tag@")
if(NOT error_msg STREQUAL "")
message(WARNING "${error_msg}")
@@ -92,15 +114,6 @@ else()
endif()
endif()
-if(fetch_required)
- message(VERBOSE "Fetching latest from the remote @git_remote_name@")
- execute_process(
- COMMAND "@git_EXECUTABLE@" --git-dir=.git fetch --tags --force "@git_remote_name@"
- WORKING_DIRECTORY "@work_dir@"
- COMMAND_ERROR_IS_FATAL ANY
- )
-endif()
-
set(git_update_strategy "@git_update_strategy@")
if(git_update_strategy STREQUAL "")
# Backward compatibility requires REBASE as the default behavior
diff --git a/Modules/FetchContent.cmake b/Modules/FetchContent.cmake
index 74ac8aa..56fc0ed 100644
--- a/Modules/FetchContent.cmake
+++ b/Modules/FetchContent.cmake
@@ -665,10 +665,16 @@ A number of cache variables can influence the behavior where details from a
This is a less severe download/update control compared to
:variable:`FETCHCONTENT_FULLY_DISCONNECTED`. Instead of bypassing all
download and update logic, ``FETCHCONTENT_UPDATES_DISCONNECTED`` only
- disables the update stage. Therefore, if content has not been downloaded
- previously, it will still be downloaded when this option is enabled.
- This can speed up the configure stage, but not as much as
- :variable:`FETCHCONTENT_FULLY_DISCONNECTED`. It is ``OFF`` by default.
+ prevents the update step from making connections to remote servers
+ when using the git or hg download methods. Updates still occur if details
+ about the update step change, but the update is attempted with only the
+ information already available locally (so switching to a different tag or
+ commit that is already fetched locally will succeed, but switching to an
+ unknown commit hash will fail). The download step is not affected, so if
+ content has not been downloaded previously, it will still be downloaded
+ when this option is enabled. This can speed up the configure step, but
+ not as much as :variable:`FETCHCONTENT_FULLY_DISCONNECTED`.
+ ``FETCHCONTENT_UPDATES_DISCONNECTED`` is ``OFF`` by default.
.. variable:: FETCHCONTENT_TRY_FIND_PACKAGE_MODE
@@ -735,10 +741,11 @@ content name:
This is the per-content equivalent of
:variable:`FETCHCONTENT_UPDATES_DISCONNECTED`. If the global option or
- this option is ``ON``, then updates will be disabled for the named content.
- Disabling updates for individual content can be useful for content whose
- details rarely change, while still leaving other frequently changing content
- with updates enabled.
+ this option is ``ON``, then updates for the git and hg methods will not
+ contact any remote for the named content. They will only use information
+ already available locally. Disabling updates for individual content can
+ be useful for content whose details rarely change, while still leaving
+ other frequently changing content with updates enabled.
.. _`fetch-content-examples`:
diff --git a/Modules/FindCUDA.cmake b/Modules/FindCUDA.cmake
index 220b9ab..0d7f1a4 100644
--- a/Modules/FindCUDA.cmake
+++ b/Modules/FindCUDA.cmake
@@ -1942,7 +1942,7 @@ function(CUDA_LINK_SEPARABLE_COMPILATION_OBJECTS output_file cuda_target options
list(APPEND flags -Xcompiler ${f})
endforeach()
- # Add our general CUDA_NVCC_FLAGS with the configuration specifig flags
+ # Add our general CUDA_NVCC_FLAGS with the configuration specific flags
set(nvcc_flags ${CUDA_NVCC_FLAGS} ${config_specific_flags} ${nvcc_flags})
file(RELATIVE_PATH output_file_relative_path "${CMAKE_BINARY_DIR}" "${output_file}")
diff --git a/Modules/FindMPI.cmake b/Modules/FindMPI.cmake
index 1fbb4f9..e3246c6 100644
--- a/Modules/FindMPI.cmake
+++ b/Modules/FindMPI.cmake
@@ -1554,7 +1554,7 @@ foreach(LANG IN ITEMS C CXX Fortran)
endif()
endif()
- # We are on a Cray, environment identfier: PE_ENV is set (CRAY), and
+ # We are on a Cray, environment identifier: PE_ENV is set (CRAY), and
# have NOT found an mpic++-like compiler wrapper (previous block),
# and we do NOT use the Cray cc/CC compiler wrappers as CC/CXX CMake
# compiler.
diff --git a/Modules/FindMatlab.cmake b/Modules/FindMatlab.cmake
index e111b79..3ab6bc1 100644
--- a/Modules/FindMatlab.cmake
+++ b/Modules/FindMatlab.cmake
@@ -951,7 +951,7 @@ function(matlab_add_unit_test)
endif()
# The option to run a batch program with MATLAB changes depending on the MATLAB version
- # For MATLAB before R2019a (9.6), the only supported option is -r, afterwords the suggested option
+ # For MATLAB before R2019a (9.6), the only supported option is -r, afterwards the suggested option
# is -batch as -r is deprecated
set(maut_BATCH_OPTION "-r")
if(NOT (Matlab_VERSION_STRING STREQUAL ""))
diff --git a/Modules/FindOpenGL.cmake b/Modules/FindOpenGL.cmake
index a773601..843f787 100644
--- a/Modules/FindOpenGL.cmake
+++ b/Modules/FindOpenGL.cmake
@@ -160,7 +160,7 @@ The value may be one of:
.. versionchanged:: 3.11
This is the default, unless policy :policy:`CMP0072` is set to ``OLD``
- and no components are requeted (since components
+ and no components are requested (since components
correspond to GLVND libraries).
``LEGACY``
diff --git a/Modules/FindOpenSSL.cmake b/Modules/FindOpenSSL.cmake
index 45dc9ac..426d00d 100644
--- a/Modules/FindOpenSSL.cmake
+++ b/Modules/FindOpenSSL.cmake
@@ -107,13 +107,13 @@ The following variables may be set to control search behavior:
``ENV{PKG_CONFIG_PATH}``
On UNIX-like systems, ``pkg-config`` is used to locate the system OpenSSL.
- Set the ``PKG_CONFIG_PATH`` environment varialbe to look in alternate
+ Set the ``PKG_CONFIG_PATH`` environment variable to look in alternate
locations. Useful on multi-lib systems.
#]=======================================================================]
macro(_OpenSSL_test_and_find_dependencies ssl_library crypto_library)
unset(_OpenSSL_extra_static_deps)
- if((CMAKE_SYSTEM_NAME STREQUAL "Linux") AND
+ if(UNIX AND
(("${ssl_library}" MATCHES "\\${CMAKE_STATIC_LIBRARY_SUFFIX}$") OR
("${crypto_library}" MATCHES "\\${CMAKE_STATIC_LIBRARY_SUFFIX}$")))
set(_OpenSSL_has_dependencies TRUE)
@@ -140,7 +140,7 @@ macro(_OpenSSL_test_and_find_dependencies ssl_library crypto_library)
endif()
endforeach()
unset(_OPENSSL_DEP_LIB)
- else()
+ elseif(CMAKE_SYSTEM_NAME STREQUAL "Linux")
set(_OpenSSL_has_dependency_dl TRUE)
endif()
if(_OpenSSL_ldflags_other)
@@ -152,7 +152,7 @@ macro(_OpenSSL_test_and_find_dependencies ssl_library crypto_library)
endif()
endforeach()
unset(_OPENSSL_DEP_LDFLAG)
- else()
+ elseif(CMAKE_SYSTEM_NAME STREQUAL "Linux")
set(_OpenSSL_has_dependency_threads TRUE)
find_package(Threads)
endif()
@@ -230,13 +230,15 @@ else()
set(_OPENSSL_FIND_PATH_SUFFIX "include")
endif()
-if (MSVC)
+if ((DEFINED OPENSSL_ROOT_DIR) OR (DEFINED ENV{OPENSSL_ROOT_DIR}))
+ set(_OPENSSL_ROOT_HINTS HINTS ${OPENSSL_ROOT_DIR} ENV OPENSSL_ROOT_DIR)
+ set(_OPENSSL_ROOT_PATHS NO_DEFAULT_PATH)
+elseif (MSVC)
# http://www.slproweb.com/products/Win32OpenSSL.html
set(_OPENSSL_ROOT_HINTS
- ${OPENSSL_ROOT_DIR}
+ HINTS
"[HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\OpenSSL (32-bit)_is1;Inno Setup: App Path]"
"[HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\OpenSSL (64-bit)_is1;Inno Setup: App Path]"
- ENV OPENSSL_ROOT_DIR
)
if("${CMAKE_SIZEOF_VOID_P}" STREQUAL "8")
@@ -255,6 +257,7 @@ if (MSVC)
endif()
set(_OPENSSL_ROOT_PATHS
+ PATHS
"${_programfiles}/OpenSSL"
"${_programfiles}/OpenSSL-${_arch}"
"C:/OpenSSL/"
@@ -262,16 +265,11 @@ if (MSVC)
)
unset(_programfiles)
unset(_arch)
-else ()
- set(_OPENSSL_ROOT_HINTS
- ${OPENSSL_ROOT_DIR}
- ENV OPENSSL_ROOT_DIR
- )
endif ()
set(_OPENSSL_ROOT_HINTS_AND_PATHS
- HINTS ${_OPENSSL_ROOT_HINTS}
- PATHS ${_OPENSSL_ROOT_PATHS}
+ ${_OPENSSL_ROOT_HINTS}
+ ${_OPENSSL_ROOT_PATHS}
)
find_path(OPENSSL_INCLUDE_DIR
diff --git a/Modules/FindwxWindows.cmake b/Modules/FindwxWindows.cmake
index 15dacbb..6e4be91 100644
--- a/Modules/FindwxWindows.cmake
+++ b/Modules/FindwxWindows.cmake
@@ -613,7 +613,7 @@ else()
option(WXWINDOWS_USE_SHARED_LIBS "Use shared versions (.so) of wxWindows libraries" ON)
mark_as_advanced(WXWINDOWS_USE_SHARED_LIBS)
- # JW removed option and force the develper th SET it.
+ # JW removed option and force the developer to SET it.
# option(WXWINDOWS_USE_GL "use wxWindows with GL support (use additional
# --gl-libs for wx-config)?" OFF)
diff --git a/Modules/Internal/CPack/CPackRPM.cmake b/Modules/Internal/CPack/CPackRPM.cmake
index 8ac1f6b..36c0a3f 100644
--- a/Modules/Internal/CPack/CPackRPM.cmake
+++ b/Modules/Internal/CPack/CPackRPM.cmake
@@ -1150,7 +1150,7 @@ function(cpack_rpm_generate_package)
endforeach()
# CPACK_RPM_SPEC_INSTALL_POST
- # May be used to define a RPM post intallation script
+ # May be used to define a RPM post installation script
# for example setting it to "/bin/true" may prevent
# rpmbuild from stripping binaries.
if(CPACK_RPM_SPEC_INSTALL_POST)
diff --git a/Modules/Platform/Windows-IntelLLVM.cmake b/Modules/Platform/Windows-IntelLLVM.cmake
index 43f5874..eac3f0a 100644
--- a/Modules/Platform/Windows-IntelLLVM.cmake
+++ b/Modules/Platform/Windows-IntelLLVM.cmake
@@ -54,6 +54,7 @@ macro(__windows_compiler_intel lang)
"${_CMAKE_VS_LINK_EXE}<CMAKE_${lang}_COMPILER> ${CMAKE_CL_NOLOGO} <CMAKE_${lang}_LINK_FLAGS> <OBJECTS> ${CMAKE_START_TEMP_FILE} <LINK_FLAGS> <LINK_LIBRARIES> /link /out:<TARGET> /implib:<TARGET_IMPLIB> /pdb:<TARGET_PDB> /version:<TARGET_VERSION_MAJOR>.<TARGET_VERSION_MINOR>${_PLATFORM_LINK_FLAGS} ${CMAKE_END_TEMP_FILE}")
set(CMAKE_${lang}_CREATE_SHARED_LIBRARY
"${_CMAKE_VS_LINK_DLL}<CMAKE_${lang}_COMPILER> ${CMAKE_CL_NOLOGO} <CMAKE_${lang}_LINK_FLAGS> <OBJECTS> ${CMAKE_START_TEMP_FILE} -LD <LINK_FLAGS> <LINK_LIBRARIES> -link /out:<TARGET> /implib:<TARGET_IMPLIB> /pdb:<TARGET_PDB> /version:<TARGET_VERSION_MAJOR>.<TARGET_VERSION_MINOR>${_PLATFORM_LINK_FLAGS} ${CMAKE_END_TEMP_FILE}")
+ set(CMAKE_${lang}_CREATE_SHARED_MODULE ${CMAKE_${lang}_CREATE_SHARED_LIBRARY})
if (NOT "${lang}" STREQUAL "Fortran" OR CMAKE_${lang}_COMPILER_VERSION VERSION_GREATER_EQUAL 2022.1)
# The Fortran driver does not support -fuse-ld=llvm-lib before compiler version 2022.1
set(CMAKE_${lang}_CREATE_STATIC_LIBRARY
diff --git a/Source/CMakeLists.txt b/Source/CMakeLists.txt
index 2354f3d..bcaf890 100644
--- a/Source/CMakeLists.txt
+++ b/Source/CMakeLists.txt
@@ -762,6 +762,38 @@ target_link_libraries(
ZLIB::ZLIB
)
+if(CMake_ENABLE_DEBUGGER)
+ target_sources(
+ CMakeLib
+ PRIVATE
+ cmDebuggerAdapter.cxx
+ cmDebuggerAdapter.h
+ cmDebuggerBreakpointManager.cxx
+ cmDebuggerBreakpointManager.h
+ cmDebuggerExceptionManager.cxx
+ cmDebuggerExceptionManager.h
+ cmDebuggerPipeConnection.cxx
+ cmDebuggerPipeConnection.h
+ cmDebuggerProtocol.cxx
+ cmDebuggerProtocol.h
+ cmDebuggerSourceBreakpoint.cxx
+ cmDebuggerSourceBreakpoint.h
+ cmDebuggerStackFrame.cxx
+ cmDebuggerStackFrame.h
+ cmDebuggerThread.cxx
+ cmDebuggerThread.h
+ cmDebuggerThreadManager.cxx
+ cmDebuggerThreadManager.h
+ cmDebuggerVariables.cxx
+ cmDebuggerVariables.h
+ cmDebuggerVariablesHelper.cxx
+ cmDebuggerVariablesHelper.h
+ cmDebuggerVariablesManager.cxx
+ cmDebuggerVariablesManager.h
+ )
+ target_link_libraries(CMakeLib PUBLIC cppdap::cppdap)
+endif()
+
# Check if we can build the Mach-O parser.
if(CMake_USE_MACH_PARSER)
target_sources(
diff --git a/Source/CMakeVersion.cmake b/Source/CMakeVersion.cmake
index dd759da..00d3236 100644
--- a/Source/CMakeVersion.cmake
+++ b/Source/CMakeVersion.cmake
@@ -1,7 +1,7 @@
# CMake version number components.
set(CMake_VERSION_MAJOR 3)
set(CMake_VERSION_MINOR 26)
-set(CMake_VERSION_PATCH 20230519)
+set(CMake_VERSION_PATCH 20230531)
#set(CMake_VERSION_RC 0)
set(CMake_VERSION_IS_DIRTY 0)
diff --git a/Source/CPack/cmCPackInnoSetupGenerator.cxx b/Source/CPack/cmCPackInnoSetupGenerator.cxx
index d8825d4..5d2c208 100644
--- a/Source/CPack/cmCPackInnoSetupGenerator.cxx
+++ b/Source/CPack/cmCPackInnoSetupGenerator.cxx
@@ -277,7 +277,7 @@ bool cmCPackInnoSetupGenerator::ProcessSetupSection()
return false;
}
- const std::string& architecture = GetOption("CPACK_INNOSETUP_ARCHITECTURE");
+ cmValue const architecture = GetOption("CPACK_INNOSETUP_ARCHITECTURE");
if (architecture != "x86" && architecture != "x64" &&
architecture != "arm64" && architecture != "ia64") {
cmCPackLogger(cmCPackLog::LOG_ERROR,
diff --git a/Source/CTest/cmCTestBuildAndTestHandler.cxx b/Source/CTest/cmCTestBuildAndTestHandler.cxx
index cece98e..5feb953 100644
--- a/Source/CTest/cmCTestBuildAndTestHandler.cxx
+++ b/Source/CTest/cmCTestBuildAndTestHandler.cxx
@@ -246,7 +246,6 @@ int cmCTestBuildAndTestHandler::RunCMakeAndTest(std::string* outstring)
return 1;
}
}
- std::string output;
const char* config = nullptr;
if (!this->CTest->GetConfigType().empty()) {
config = this->CTest->GetConfigType().c_str();
@@ -259,9 +258,8 @@ int cmCTestBuildAndTestHandler::RunCMakeAndTest(std::string* outstring)
PackageResolveMode::Disable);
int retVal = cm.GetGlobalGenerator()->Build(
cmake::NO_BUILD_PARALLEL_LEVEL, this->SourceDir, this->BinaryDir,
- this->BuildProject, { tar }, output, this->BuildMakeProgram, config,
+ this->BuildProject, { tar }, out, this->BuildMakeProgram, config,
buildOptions, false, remainingTime);
- out << output;
// if the build failed then return
if (retVal) {
if (outstring) {
diff --git a/Source/CursesDialog/form/frm_def.c b/Source/CursesDialog/form/frm_def.c
index 645b3ba..569057b 100644
--- a/Source/CursesDialog/form/frm_def.c
+++ b/Source/CursesDialog/form/frm_def.c
@@ -220,6 +220,10 @@ static int Connect_Fields(FORM * form, FIELD ** fields)
for(page_nr = 0;page_nr < form->maxpage; page_nr++)
{
FIELD *fld = (FIELD *)0;
+ #ifdef __clang_analyzer__
+ /* Tell clang-analyzer the loop body runs at least once. */
+ assert(form->page[page_nr].pmin <= form->page[page_nr].pmax);
+ #endif
for(j = form->page[page_nr].pmin;j <= form->page[page_nr].pmax;j++)
{
fields[j]->index = j;
diff --git a/Source/Modules/CMakeBuildUtilities.cmake b/Source/Modules/CMakeBuildUtilities.cmake
index d6e3e88..c891fe9 100644
--- a/Source/Modules/CMakeBuildUtilities.cmake
+++ b/Source/Modules/CMakeBuildUtilities.cmake
@@ -376,3 +376,19 @@ if(BUILD_CursesDialog)
message(FATAL_ERROR "CMAKE_USE_SYSTEM_FORM in ON but CURSES_FORM_LIBRARY is not set!")
endif()
endif()
+
+#---------------------------------------------------------------------
+# Build cppdap library.
+if(CMake_ENABLE_DEBUGGER)
+ if(CMAKE_USE_SYSTEM_CPPDAP)
+ find_package(cppdap CONFIG)
+ if(NOT cppdap_FOUND)
+ message(FATAL_ERROR
+ "CMAKE_USE_SYSTEM_CPPDAP is ON but a cppdap is not found!")
+ endif()
+ else()
+ add_subdirectory(Utilities/cmcppdap)
+ add_library(cppdap::cppdap ALIAS cmcppdap)
+ CMAKE_SET_TARGET_FOLDER(cppdap "Utilities/3rdParty")
+ endif()
+endif()
diff --git a/Source/cmCMakeLanguageCommand.cxx b/Source/cmCMakeLanguageCommand.cxx
index 68e658c..c7e9209 100644
--- a/Source/cmCMakeLanguageCommand.cxx
+++ b/Source/cmCMakeLanguageCommand.cxx
@@ -303,7 +303,7 @@ bool cmCMakeLanguageCommandSET_DEPENDENCY_PROVIDER(
state->SetDependencyProvider({ parsedArgs.Command, methods });
state->SetGlobalProperty(
fcmasProperty,
- supportsFetchContentMakeAvailableSerial ? parsedArgs.Command.c_str() : "");
+ supportsFetchContentMakeAvailableSerial ? parsedArgs.Command : "");
return true;
}
diff --git a/Source/cmCPluginAPI.cxx b/Source/cmCPluginAPI.cxx
index abec968..c2c5bdb 100644
--- a/Source/cmCPluginAPI.cxx
+++ b/Source/cmCPluginAPI.cxx
@@ -615,7 +615,11 @@ static void CCONV cmSourceFileSetProperty(void* arg, const char* prop,
{
cmCPluginAPISourceFile* sf = static_cast<cmCPluginAPISourceFile*>(arg);
if (cmSourceFile* rsf = sf->RealSourceFile) {
- rsf->SetProperty(prop, value);
+ if (value == nullptr) {
+ rsf->SetProperty(prop, nullptr);
+ } else {
+ rsf->SetProperty(prop, value);
+ }
} else if (prop) {
if (!value) {
value = "NOTFOUND";
diff --git a/Source/cmCPluginAPI.h b/Source/cmCPluginAPI.h
index 13a93b7..92dff57 100644
--- a/Source/cmCPluginAPI.h
+++ b/Source/cmCPluginAPI.h
@@ -32,7 +32,7 @@ cmCPLuginAPI.cxx
typedef struct
{
/*=========================================================================
- Here we define the set of functions that a plugin may call. The first goup
+ Here we define the set of functions that a plugin may call. The first group
of functions are utility functions that are specific to the plugin API
=========================================================================*/
/* set/Get the ClientData in the cmLoadedCommandInfo structure, this is how
diff --git a/Source/cmCacheManager.cxx b/Source/cmCacheManager.cxx
index d95dcc4..8633de1 100644
--- a/Source/cmCacheManager.cxx
+++ b/Source/cmCacheManager.cxx
@@ -84,7 +84,7 @@ bool cmCacheManager::LoadCache(const std::string& path, bool internal,
continue;
}
}
- e.SetProperty("HELPSTRING", helpString.c_str());
+ e.SetProperty("HELPSTRING", helpString);
if (cmState::ParseCacheEntry(realbuffer, entryKey, e.Value, e.Type)) {
if (excludes.find(entryKey) == excludes.end()) {
// Load internal values if internal is set.
@@ -102,7 +102,7 @@ bool cmCacheManager::LoadCache(const std::string& path, bool internal,
" loaded from external file. "
"To change this value edit this file: ",
path, "/CMakeCache.txt");
- e.SetProperty("HELPSTRING", helpString.c_str());
+ e.SetProperty("HELPSTRING", helpString);
}
if (!this->ReadPropertyEntry(entryKey, e)) {
e.Initialized = true;
@@ -186,11 +186,11 @@ bool cmCacheManager::ReadPropertyEntry(const std::string& entryKey,
std::string key = entryKey.substr(0, entryKey.size() - plen);
if (auto* entry = this->GetCacheEntry(key)) {
// Store this property on its entry.
- entry->SetProperty(p, e.Value.c_str());
+ entry->SetProperty(p, e.Value);
} else {
// Create an entry and store the property.
CacheEntry& ne = this->Cache[key];
- ne.SetProperty(p, e.Value.c_str());
+ ne.SetProperty(p, e.Value);
}
return true;
}
@@ -541,10 +541,11 @@ void cmCacheManager::AddCacheEntry(const std::string& key, cmValue value,
cmSystemTools::ConvertToUnixSlashes(e.Value);
}
}
- e.SetProperty("HELPSTRING",
- helpString
- ? helpString
- : "(This variable does not exist and should not be used)");
+ e.SetProperty(
+ "HELPSTRING",
+ helpString ? std::string{ helpString }
+ : std::string{
+ "(This variable does not exist and should not be used)" });
}
void cmCacheManager::CacheEntry::SetValue(cmValue value)
@@ -580,12 +581,12 @@ bool cmCacheManager::CacheEntry::GetPropertyAsBool(
}
void cmCacheManager::CacheEntry::SetProperty(const std::string& prop,
- const char* value)
+ const std::string& value)
{
if (prop == "TYPE") {
- this->Type = cmState::StringToCacheEntryType(value ? value : "STRING");
+ this->Type = cmState::StringToCacheEntryType(value);
} else if (prop == "VALUE") {
- this->Value = value ? value : "";
+ this->Value = value;
} else {
this->Properties.SetProperty(prop, value);
}
@@ -593,7 +594,19 @@ void cmCacheManager::CacheEntry::SetProperty(const std::string& prop,
void cmCacheManager::CacheEntry::SetProperty(const std::string& p, bool v)
{
- this->SetProperty(p, v ? "ON" : "OFF");
+ this->SetProperty(p, v ? std::string{ "ON" } : std::string{ "OFF" });
+}
+
+void cmCacheManager::CacheEntry::SetProperty(const std::string& prop,
+ std::nullptr_t)
+{
+ if (prop == "TYPE") {
+ this->Type = cmState::StringToCacheEntryType("STRING");
+ } else if (prop == "VALUE") {
+ this->Value = "";
+ } else {
+ this->Properties.SetProperty(prop, cmValue{ nullptr });
+ }
}
void cmCacheManager::CacheEntry::AppendProperty(const std::string& prop,
diff --git a/Source/cmCacheManager.h b/Source/cmCacheManager.h
index bc3fb51..a2da0b5 100644
--- a/Source/cmCacheManager.h
+++ b/Source/cmCacheManager.h
@@ -39,8 +39,9 @@ class cmCacheManager
std::vector<std::string> GetPropertyList() const;
cmValue GetProperty(const std::string& property) const;
bool GetPropertyAsBool(const std::string& property) const;
- void SetProperty(const std::string& property, const char* value);
+ void SetProperty(const std::string& property, const std::string& value);
void SetProperty(const std::string& property, bool value);
+ void SetProperty(const std::string& property, std::nullptr_t);
void AppendProperty(const std::string& property, const std::string& value,
bool asString = false);
@@ -127,7 +128,7 @@ public:
std::string const& value)
{
if (auto* entry = this->GetCacheEntry(key)) {
- entry->SetProperty(propName, value.c_str());
+ entry->SetProperty(propName, value);
}
}
diff --git a/Source/cmCommandArgumentParserHelper.cxx b/Source/cmCommandArgumentParserHelper.cxx
index 2ed04e5..a20f5a5 100644
--- a/Source/cmCommandArgumentParserHelper.cxx
+++ b/Source/cmCommandArgumentParserHelper.cxx
@@ -96,7 +96,8 @@ const char* cmCommandArgumentParserHelper::ExpandVariable(const char* var)
}
if (this->FileLine >= 0 && strcmp(var, "CMAKE_CURRENT_LIST_LINE") == 0) {
std::string line;
- cmListFileContext const& top = this->Makefile->GetBacktrace().Top();
+ cmListFileBacktrace bt = this->Makefile->GetBacktrace();
+ cmListFileContext const& top = bt.Top();
if (top.DeferId) {
line = cmStrCat("DEFERRED:"_s, *top.DeferId);
} else {
diff --git a/Source/cmCommonTargetGenerator.cxx b/Source/cmCommonTargetGenerator.cxx
index 2615494..e635dd9 100644
--- a/Source/cmCommonTargetGenerator.cxx
+++ b/Source/cmCommonTargetGenerator.cxx
@@ -236,7 +236,7 @@ std::string cmCommonTargetGenerator::GetManifests(const std::string& config)
manifests.reserve(manifest_srcs.size());
std::string lang = this->GeneratorTarget->GetLinkerLanguage(config);
- std::string const& manifestFlag =
+ std::string manifestFlag =
this->Makefile->GetDefinition("CMAKE_" + lang + "_LINKER_MANIFEST_FLAG");
for (cmSourceFile const* manifest_src : manifest_srcs) {
manifests.push_back(manifestFlag +
diff --git a/Source/cmConditionEvaluator.cxx b/Source/cmConditionEvaluator.cxx
index 288e107..6f9f541 100644
--- a/Source/cmConditionEvaluator.cxx
+++ b/Source/cmConditionEvaluator.cxx
@@ -741,8 +741,8 @@ bool cmConditionEvaluator::HandleLevel2(cmArgumentList& newArgs,
keyVERSION_LESS_EQUAL, keyVERSION_GREATER,
keyVERSION_GREATER_EQUAL, keyVERSION_EQUAL))) {
const auto op = MATCH2CMPOP[matchNo - 1];
- const std::string& lhs = this->GetVariableOrString(*args.current);
- const std::string& rhs = this->GetVariableOrString(*args.nextnext);
+ const cmValue lhs = this->GetVariableOrString(*args.current);
+ const cmValue rhs = this->GetVariableOrString(*args.nextnext);
const auto result = cmSystemTools::VersionCompare(op, lhs, rhs);
newArgs.ReduceTwoArgs(result, args);
}
diff --git a/Source/cmConfigure.cmake.h.in b/Source/cmConfigure.cmake.h.in
index 3f19a11..de74716 100644
--- a/Source/cmConfigure.cmake.h.in
+++ b/Source/cmConfigure.cmake.h.in
@@ -20,6 +20,7 @@
#cmakedefine HAVE_ENVIRON_NOT_REQUIRE_PROTOTYPE
#cmakedefine HAVE_UNSETENV
+#cmakedefine CMake_ENABLE_DEBUGGER
#cmakedefine CMake_USE_MACH_PARSER
#cmakedefine CMake_USE_XCOFF_PARSER
#cmakedefine CMAKE_USE_WMAKE
diff --git a/Source/cmCustomCommandGenerator.cxx b/Source/cmCustomCommandGenerator.cxx
index 7623ccf..2c1480a 100644
--- a/Source/cmCustomCommandGenerator.cxx
+++ b/Source/cmCustomCommandGenerator.cxx
@@ -332,9 +332,9 @@ const char* cmCustomCommandGenerator::GetArgv0Location(unsigned int c) const
bool cmCustomCommandGenerator::HasOnlyEmptyCommandLines() const
{
- for (size_t i = 0; i < this->CommandLines.size(); ++i) {
- for (size_t j = 0; j < this->CommandLines[i].size(); ++j) {
- if (!this->CommandLines[i][j].empty()) {
+ for (cmCustomCommandLine const& ccl : this->CommandLines) {
+ for (std::string const& cl : ccl) {
+ if (!cl.empty()) {
return false;
}
}
diff --git a/Source/cmDebuggerAdapter.cxx b/Source/cmDebuggerAdapter.cxx
new file mode 100644
index 0000000..d03f79d
--- /dev/null
+++ b/Source/cmDebuggerAdapter.cxx
@@ -0,0 +1,462 @@
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
+
+#include "cmConfigure.h" // IWYU pragma: keep
+
+#include "cmDebuggerAdapter.h"
+
+#include <algorithm>
+#include <climits>
+#include <condition_variable>
+#include <cstdint>
+#include <functional>
+#include <iostream>
+#include <stdexcept>
+#include <utility>
+
+#include <cm/memory>
+#include <cm/optional>
+
+#include <cm3p/cppdap/io.h> // IWYU pragma: keep
+#include <cm3p/cppdap/protocol.h>
+#include <cm3p/cppdap/session.h>
+
+#include "cmDebuggerBreakpointManager.h"
+#include "cmDebuggerExceptionManager.h"
+#include "cmDebuggerProtocol.h"
+#include "cmDebuggerSourceBreakpoint.h" // IWYU pragma: keep
+#include "cmDebuggerStackFrame.h"
+#include "cmDebuggerThread.h"
+#include "cmDebuggerThreadManager.h"
+#include "cmListFileCache.h"
+#include "cmMakefile.h"
+#include "cmValue.h"
+#include "cmVersionConfig.h"
+#include <cmcppdap/include/dap/optional.h>
+#include <cmcppdap/include/dap/types.h>
+
+namespace cmDebugger {
+
+// Event provides a basic wait and signal synchronization primitive.
+class SyncEvent
+{
+public:
+ // Wait() blocks until the event is fired.
+ void Wait()
+ {
+ std::unique_lock<std::mutex> lock(Mutex);
+ Cv.wait(lock, [&] { return Fired; });
+ }
+
+ // Fire() sets signals the event, and unblocks any calls to Wait().
+ void Fire()
+ {
+ std::unique_lock<std::mutex> lock(Mutex);
+ Fired = true;
+ Cv.notify_all();
+ }
+
+private:
+ std::mutex Mutex;
+ std::condition_variable Cv;
+ bool Fired = false;
+};
+
+class Semaphore
+{
+public:
+ Semaphore(int count_ = 0)
+ : Count(count_)
+ {
+ }
+
+ inline void Notify()
+ {
+ std::unique_lock<std::mutex> lock(Mutex);
+ Count++;
+ // notify the waiting thread
+ Cv.notify_one();
+ }
+
+ inline void Wait()
+ {
+ std::unique_lock<std::mutex> lock(Mutex);
+ while (Count == 0) {
+ // wait on the mutex until notify is called
+ Cv.wait(lock);
+ }
+ Count--;
+ }
+
+private:
+ std::mutex Mutex;
+ std::condition_variable Cv;
+ int Count;
+};
+
+cmDebuggerAdapter::cmDebuggerAdapter(
+ std::shared_ptr<cmDebuggerConnection> connection,
+ std::string const& dapLogPath)
+ : cmDebuggerAdapter(std::move(connection),
+ dapLogPath.empty()
+ ? cm::nullopt
+ : cm::optional<std::shared_ptr<dap::Writer>>(
+ dap::file(dapLogPath.c_str())))
+{
+}
+
+cmDebuggerAdapter::cmDebuggerAdapter(
+ std::shared_ptr<cmDebuggerConnection> connection,
+ cm::optional<std::shared_ptr<dap::Writer>> logger)
+ : Connection(std::move(connection))
+ , SessionActive(true)
+ , DisconnectEvent(cm::make_unique<SyncEvent>())
+ , ConfigurationDoneEvent(cm::make_unique<SyncEvent>())
+ , ContinueSem(cm::make_unique<Semaphore>())
+ , ThreadManager(cm::make_unique<cmDebuggerThreadManager>())
+{
+ if (logger.has_value()) {
+ SessionLog = std::move(logger.value());
+ }
+ ClearStepRequests();
+
+ Session = dap::Session::create();
+ BreakpointManager =
+ cm::make_unique<cmDebuggerBreakpointManager>(Session.get());
+ ExceptionManager =
+ cm::make_unique<cmDebuggerExceptionManager>(Session.get());
+
+ // Handle errors reported by the Session. These errors include protocol
+ // parsing errors and receiving messages with no handler.
+ Session->onError([this](const char* msg) {
+ if (SessionLog) {
+ dap::writef(SessionLog, "dap::Session error: %s\n", msg);
+ }
+
+ std::cout << "[CMake Debugger] DAP session error: " << msg << std::endl;
+
+ BreakpointManager->ClearAll();
+ ExceptionManager->ClearAll();
+ ClearStepRequests();
+ ContinueSem->Notify();
+ DisconnectEvent->Fire();
+ SessionActive.store(false);
+ });
+
+ // https://microsoft.github.io/debug-adapter-protocol/specification#Requests_Initialize
+ Session->registerHandler([this](const dap::CMakeInitializeRequest& req) {
+ SupportsVariableType = req.supportsVariableType.value(false);
+ dap::CMakeInitializeResponse response;
+ response.supportsConfigurationDoneRequest = true;
+ response.cmakeVersion.major = CMake_VERSION_MAJOR;
+ response.cmakeVersion.minor = CMake_VERSION_MINOR;
+ response.cmakeVersion.patch = CMake_VERSION_PATCH;
+ response.cmakeVersion.full = CMake_VERSION;
+ ExceptionManager->HandleInitializeRequest(response);
+ return response;
+ });
+
+ // https://microsoft.github.io/debug-adapter-protocol/specification#Events_Initialized
+ Session->registerSentHandler(
+ [&](const dap::ResponseOrError<dap::CMakeInitializeResponse>&) {
+ Session->send(dap::InitializedEvent());
+ });
+
+ // https://microsoft.github.io/debug-adapter-protocol/specification#Requests_Threads
+ Session->registerHandler([this](const dap::ThreadsRequest& req) {
+ (void)req;
+ std::unique_lock<std::mutex> lock(Mutex);
+ dap::ThreadsResponse response;
+ dap::Thread thread;
+ thread.id = DefaultThread->GetId();
+ thread.name = DefaultThread->GetName();
+ response.threads.push_back(thread);
+ return response;
+ });
+
+ // https://microsoft.github.io/debug-adapter-protocol/specification#Requests_StackTrace
+ Session->registerHandler([this](const dap::StackTraceRequest& request)
+ -> dap::ResponseOrError<dap::StackTraceResponse> {
+ std::unique_lock<std::mutex> lock(Mutex);
+
+ cm::optional<dap::StackTraceResponse> response =
+ ThreadManager->GetThreadStackTraceResponse(request.threadId);
+ if (response.has_value()) {
+ return response.value();
+ }
+
+ return dap::Error("Unknown threadId '%d'", int(request.threadId));
+ });
+
+ // https://microsoft.github.io/debug-adapter-protocol/specification#Requests_Scopes
+ Session->registerHandler([this](const dap::ScopesRequest& request)
+ -> dap::ResponseOrError<dap::ScopesResponse> {
+ std::unique_lock<std::mutex> lock(Mutex);
+ return DefaultThread->GetScopesResponse(request.frameId,
+ SupportsVariableType);
+ });
+
+ // https://microsoft.github.io/debug-adapter-protocol/specification#Requests_Variables
+ Session->registerHandler([this](const dap::VariablesRequest& request)
+ -> dap::ResponseOrError<dap::VariablesResponse> {
+ return DefaultThread->GetVariablesResponse(request);
+ });
+
+ // https://microsoft.github.io/debug-adapter-protocol/specification#Requests_Pause
+ Session->registerHandler([this](const dap::PauseRequest& req) {
+ (void)req;
+ PauseRequest.store(true);
+ return dap::PauseResponse();
+ });
+
+ // https://microsoft.github.io/debug-adapter-protocol/specification#Requests_Continue
+ Session->registerHandler([this](const dap::ContinueRequest& req) {
+ (void)req;
+ ContinueSem->Notify();
+ return dap::ContinueResponse();
+ });
+
+ // https://microsoft.github.io/debug-adapter-protocol/specification#Requests_Next
+ Session->registerHandler([this](const dap::NextRequest& req) {
+ (void)req;
+ NextStepFrom.store(DefaultThread->GetStackFrameSize());
+ ContinueSem->Notify();
+ return dap::NextResponse();
+ });
+
+ // https://microsoft.github.io/debug-adapter-protocol/specification#Requests_StepIn
+ Session->registerHandler([this](const dap::StepInRequest& req) {
+ (void)req;
+ // This would stop after stepped in, single line stepped or stepped out.
+ StepInRequest.store(true);
+ ContinueSem->Notify();
+ return dap::StepInResponse();
+ });
+
+ // https://microsoft.github.io/debug-adapter-protocol/specification#Requests_StepOut
+ Session->registerHandler([this](const dap::StepOutRequest& req) {
+ (void)req;
+ StepOutDepth.store(DefaultThread->GetStackFrameSize() - 1);
+ ContinueSem->Notify();
+ return dap::StepOutResponse();
+ });
+
+ // https://microsoft.github.io/debug-adapter-protocol/specification#Requests_Launch
+ Session->registerHandler([](const dap::LaunchRequest& req) {
+ (void)req;
+ return dap::LaunchResponse();
+ });
+
+ // Handler for disconnect requests
+ Session->registerHandler([this](const dap::DisconnectRequest& request) {
+ (void)request;
+ BreakpointManager->ClearAll();
+ ExceptionManager->ClearAll();
+ ClearStepRequests();
+ ContinueSem->Notify();
+ DisconnectEvent->Fire();
+ SessionActive.store(false);
+ return dap::DisconnectResponse();
+ });
+
+ Session->registerHandler([this](const dap::EvaluateRequest& request) {
+ dap::EvaluateResponse response;
+ if (request.frameId.has_value()) {
+ std::shared_ptr<cmDebuggerStackFrame> frame =
+ DefaultThread->GetStackFrame(request.frameId.value());
+
+ auto var = frame->GetMakefile()->GetDefinition(request.expression);
+ if (var) {
+ response.type = "string";
+ response.result = var;
+ return response;
+ }
+ }
+
+ return response;
+ });
+
+ // The ConfigurationDone request is made by the client once all configuration
+ // requests have been made.
+ // https://microsoft.github.io/debug-adapter-protocol/specification#Requests_ConfigurationDone
+ Session->registerHandler([this](const dap::ConfigurationDoneRequest& req) {
+ (void)req;
+ ConfigurationDoneEvent->Fire();
+ return dap::ConfigurationDoneResponse();
+ });
+
+ std::string errorMessage;
+ if (!Connection->StartListening(errorMessage)) {
+ throw std::runtime_error(errorMessage);
+ }
+
+ // Connect to the client. Write a well-known message to stdout so that
+ // clients know it is safe to attempt to connect.
+ std::cout << "Waiting for debugger client to connect..." << std::endl;
+ Connection->WaitForConnection();
+ std::cout << "Debugger client connected." << std::endl;
+
+ if (SessionLog) {
+ Session->connect(spy(Connection->GetReader(), SessionLog),
+ spy(Connection->GetWriter(), SessionLog));
+ } else {
+ Session->connect(Connection->GetReader(), Connection->GetWriter());
+ }
+
+ // Start the processing thread.
+ SessionThread = std::thread([this] {
+ while (SessionActive.load()) {
+ if (auto payload = Session->getPayload()) {
+ payload();
+ }
+ }
+ });
+
+ ConfigurationDoneEvent->Wait();
+
+ DefaultThread = ThreadManager->StartThread("CMake script");
+ dap::ThreadEvent threadEvent;
+ threadEvent.reason = "started";
+ threadEvent.threadId = DefaultThread->GetId();
+ Session->send(threadEvent);
+}
+
+cmDebuggerAdapter::~cmDebuggerAdapter()
+{
+ if (SessionThread.joinable()) {
+ SessionThread.join();
+ }
+
+ Session.reset(nullptr);
+
+ if (SessionLog) {
+ SessionLog->close();
+ }
+}
+
+void cmDebuggerAdapter::ReportExitCode(int exitCode)
+{
+ ThreadManager->EndThread(DefaultThread);
+ dap::ThreadEvent threadEvent;
+ threadEvent.reason = "exited";
+ threadEvent.threadId = DefaultThread->GetId();
+ DefaultThread.reset();
+
+ dap::ExitedEvent exitEvent;
+ exitEvent.exitCode = exitCode;
+
+ dap::TerminatedEvent terminatedEvent;
+
+ if (SessionActive.load()) {
+ Session->send(threadEvent);
+ Session->send(exitEvent);
+ Session->send(terminatedEvent);
+ }
+
+ // Wait until disconnected or error.
+ DisconnectEvent->Wait();
+}
+
+void cmDebuggerAdapter::OnFileParsedSuccessfully(
+ std::string const& sourcePath,
+ std::vector<cmListFileFunction> const& functions)
+{
+ BreakpointManager->SourceFileLoaded(sourcePath, functions);
+}
+
+void cmDebuggerAdapter::OnBeginFunctionCall(cmMakefile* mf,
+ std::string const& sourcePath,
+ cmListFileFunction const& lff)
+{
+ std::unique_lock<std::mutex> lock(Mutex);
+ DefaultThread->PushStackFrame(mf, sourcePath, lff);
+
+ if (lff.Line() == 0) {
+ // File just loaded, continue to first valid function call.
+ return;
+ }
+
+ auto hits = BreakpointManager->GetBreakpoints(sourcePath, lff.Line());
+ lock.unlock();
+
+ bool waitSem = false;
+ dap::StoppedEvent stoppedEvent;
+ stoppedEvent.allThreadsStopped = true;
+ stoppedEvent.threadId = DefaultThread->GetId();
+ if (!hits.empty()) {
+ ClearStepRequests();
+ waitSem = true;
+
+ dap::array<dap::integer> hitBreakpoints;
+ hitBreakpoints.resize(hits.size());
+ std::transform(hits.begin(), hits.end(), hitBreakpoints.begin(),
+ [&](const int64_t& id) { return dap::integer(id); });
+ stoppedEvent.reason = "breakpoint";
+ stoppedEvent.hitBreakpointIds = hitBreakpoints;
+ }
+
+ if (long(DefaultThread->GetStackFrameSize()) <= NextStepFrom.load() ||
+ StepInRequest.load() ||
+ long(DefaultThread->GetStackFrameSize()) <= StepOutDepth.load()) {
+ ClearStepRequests();
+ waitSem = true;
+
+ stoppedEvent.reason = "step";
+ }
+
+ if (PauseRequest.load()) {
+ ClearStepRequests();
+ waitSem = true;
+
+ stoppedEvent.reason = "pause";
+ }
+
+ if (waitSem) {
+ Session->send(stoppedEvent);
+ ContinueSem->Wait();
+ }
+}
+
+void cmDebuggerAdapter::OnEndFunctionCall()
+{
+ DefaultThread->PopStackFrame();
+}
+
+static std::shared_ptr<cmListFileFunction> listFileFunction;
+
+void cmDebuggerAdapter::OnBeginFileParse(cmMakefile* mf,
+ std::string const& sourcePath)
+{
+ std::unique_lock<std::mutex> lock(Mutex);
+
+ listFileFunction = std::make_shared<cmListFileFunction>(
+ sourcePath, 0, 0, std::vector<cmListFileArgument>());
+ DefaultThread->PushStackFrame(mf, sourcePath, *listFileFunction);
+}
+
+void cmDebuggerAdapter::OnEndFileParse()
+{
+ DefaultThread->PopStackFrame();
+ listFileFunction = nullptr;
+}
+
+void cmDebuggerAdapter::OnMessageOutput(MessageType t, std::string const& text)
+{
+ cm::optional<dap::StoppedEvent> stoppedEvent =
+ ExceptionManager->RaiseExceptionIfAny(t, text);
+ if (stoppedEvent.has_value()) {
+ stoppedEvent->threadId = DefaultThread->GetId();
+ Session->send(*stoppedEvent);
+ ContinueSem->Wait();
+ }
+}
+
+void cmDebuggerAdapter::ClearStepRequests()
+{
+ NextStepFrom.store(INT_MIN);
+ StepInRequest.store(false);
+ StepOutDepth.store(INT_MIN);
+ PauseRequest.store(false);
+}
+
+} // namespace cmDebugger
diff --git a/Source/cmDebuggerAdapter.h b/Source/cmDebuggerAdapter.h
new file mode 100644
index 0000000..f261d88
--- /dev/null
+++ b/Source/cmDebuggerAdapter.h
@@ -0,0 +1,93 @@
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
+#pragma once
+
+#include "cmConfigure.h" // IWYU pragma: keep
+
+#include <atomic>
+#include <cstdint>
+#include <memory>
+#include <mutex>
+#include <string>
+#include <thread>
+#include <vector>
+
+#include <cm/optional>
+
+#include <cm3p/cppdap/io.h> // IWYU pragma: keep
+
+#include "cmMessageType.h"
+
+class cmListFileFunction;
+class cmMakefile;
+
+namespace cmDebugger {
+class Semaphore;
+class SyncEvent;
+class cmDebuggerBreakpointManager;
+class cmDebuggerExceptionManager;
+class cmDebuggerThread;
+class cmDebuggerThreadManager;
+}
+
+namespace dap {
+class Session;
+}
+
+namespace cmDebugger {
+
+class cmDebuggerConnection
+{
+public:
+ virtual ~cmDebuggerConnection() = default;
+ virtual bool StartListening(std::string& errorMessage) = 0;
+ virtual void WaitForConnection() = 0;
+ virtual std::shared_ptr<dap::Reader> GetReader() = 0;
+ virtual std::shared_ptr<dap::Writer> GetWriter() = 0;
+};
+
+class cmDebuggerAdapter
+{
+public:
+ cmDebuggerAdapter(std::shared_ptr<cmDebuggerConnection> connection,
+ std::string const& dapLogPath);
+ cmDebuggerAdapter(std::shared_ptr<cmDebuggerConnection> connection,
+ cm::optional<std::shared_ptr<dap::Writer>> logger);
+ ~cmDebuggerAdapter();
+
+ void ReportExitCode(int exitCode);
+
+ void OnFileParsedSuccessfully(
+ std::string const& sourcePath,
+ std::vector<cmListFileFunction> const& functions);
+ void OnBeginFunctionCall(cmMakefile* mf, std::string const& sourcePath,
+ cmListFileFunction const& lff);
+ void OnEndFunctionCall();
+ void OnBeginFileParse(cmMakefile* mf, std::string const& sourcePath);
+ void OnEndFileParse();
+
+ void OnMessageOutput(MessageType t, std::string const& text);
+
+private:
+ void ClearStepRequests();
+ std::shared_ptr<cmDebuggerConnection> Connection;
+ std::unique_ptr<dap::Session> Session;
+ std::shared_ptr<dap::Writer> SessionLog;
+ std::thread SessionThread;
+ std::atomic<bool> SessionActive;
+ std::mutex Mutex;
+ std::unique_ptr<SyncEvent> DisconnectEvent;
+ std::unique_ptr<SyncEvent> ConfigurationDoneEvent;
+ std::unique_ptr<Semaphore> ContinueSem;
+ std::atomic<int64_t> NextStepFrom;
+ std::atomic<bool> StepInRequest;
+ std::atomic<int64_t> StepOutDepth;
+ std::atomic<bool> PauseRequest;
+ std::unique_ptr<cmDebuggerThreadManager> ThreadManager;
+ std::shared_ptr<cmDebuggerThread> DefaultThread;
+ std::unique_ptr<cmDebuggerBreakpointManager> BreakpointManager;
+ std::unique_ptr<cmDebuggerExceptionManager> ExceptionManager;
+ bool SupportsVariableType;
+};
+
+} // namespace cmDebugger
diff --git a/Source/cmDebuggerBreakpointManager.cxx b/Source/cmDebuggerBreakpointManager.cxx
new file mode 100644
index 0000000..152f0f5
--- /dev/null
+++ b/Source/cmDebuggerBreakpointManager.cxx
@@ -0,0 +1,200 @@
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
+#include "cmDebuggerBreakpointManager.h"
+
+#include <algorithm>
+#include <cstddef>
+#include <cstdint>
+#include <memory>
+
+#include <cm3p/cppdap/optional.h>
+#include <cm3p/cppdap/session.h>
+#include <cm3p/cppdap/types.h>
+
+#include "cmDebuggerSourceBreakpoint.h"
+#include "cmListFileCache.h"
+#include "cmSystemTools.h"
+
+namespace cmDebugger {
+
+cmDebuggerBreakpointManager::cmDebuggerBreakpointManager(
+ dap::Session* dapSession)
+ : DapSession(dapSession)
+{
+ // https://microsoft.github.io/debug-adapter-protocol/specification#Requests_SetBreakpoints
+ DapSession->registerHandler([&](const dap::SetBreakpointsRequest& request) {
+ return HandleSetBreakpointsRequest(request);
+ });
+}
+
+int64_t cmDebuggerBreakpointManager::FindFunctionStartLine(
+ std::string const& sourcePath, int64_t line)
+{
+ auto location =
+ find_if(ListFileFunctionLines[sourcePath].begin(),
+ ListFileFunctionLines[sourcePath].end(),
+ [=](cmDebuggerFunctionLocation const& loc) {
+ return loc.StartLine <= line && loc.EndLine >= line;
+ });
+
+ if (location != ListFileFunctionLines[sourcePath].end()) {
+ return location->StartLine;
+ }
+
+ return 0;
+}
+
+int64_t cmDebuggerBreakpointManager::CalibrateBreakpointLine(
+ std::string const& sourcePath, int64_t line)
+{
+ auto location = find_if(ListFileFunctionLines[sourcePath].begin(),
+ ListFileFunctionLines[sourcePath].end(),
+ [=](cmDebuggerFunctionLocation const& loc) {
+ return loc.StartLine >= line;
+ });
+
+ if (location != ListFileFunctionLines[sourcePath].end()) {
+ return location->StartLine;
+ }
+
+ if (!ListFileFunctionLines[sourcePath].empty() &&
+ ListFileFunctionLines[sourcePath].back().EndLine <= line) {
+ // return last function start line for any breakpoints after.
+ return ListFileFunctionLines[sourcePath].back().StartLine;
+ }
+
+ return 0;
+}
+
+dap::SetBreakpointsResponse
+cmDebuggerBreakpointManager::HandleSetBreakpointsRequest(
+ dap::SetBreakpointsRequest const& request)
+{
+ std::unique_lock<std::mutex> lock(Mutex);
+
+ dap::SetBreakpointsResponse response;
+
+ auto sourcePath =
+ cmSystemTools::GetActualCaseForPath(request.source.path.value());
+ const dap::array<dap::SourceBreakpoint> defaultValue{};
+ const auto& breakpoints = request.breakpoints.value(defaultValue);
+ if (ListFileFunctionLines.find(sourcePath) != ListFileFunctionLines.end()) {
+ // The file has loaded, we can validate breakpoints.
+ if (Breakpoints.find(sourcePath) != Breakpoints.end()) {
+ Breakpoints[sourcePath].clear();
+ }
+ response.breakpoints.resize(breakpoints.size());
+ for (size_t i = 0; i < breakpoints.size(); i++) {
+ int64_t correctedLine =
+ CalibrateBreakpointLine(sourcePath, breakpoints[i].line);
+ if (correctedLine > 0) {
+ Breakpoints[sourcePath].emplace_back(NextBreakpointId++,
+ correctedLine);
+ response.breakpoints[i].id = Breakpoints[sourcePath].back().GetId();
+ response.breakpoints[i].line =
+ Breakpoints[sourcePath].back().GetLine();
+ response.breakpoints[i].verified = true;
+ } else {
+ response.breakpoints[i].verified = false;
+ response.breakpoints[i].line = breakpoints[i].line;
+ }
+ dap::Source dapSrc;
+ dapSrc.path = sourcePath;
+ response.breakpoints[i].source = dapSrc;
+ }
+ } else {
+ // The file has not loaded, validate breakpoints later.
+ ListFilePendingValidations.emplace(sourcePath);
+
+ response.breakpoints.resize(breakpoints.size());
+ for (size_t i = 0; i < breakpoints.size(); i++) {
+ Breakpoints[sourcePath].emplace_back(NextBreakpointId++,
+ breakpoints[i].line);
+ response.breakpoints[i].id = Breakpoints[sourcePath].back().GetId();
+ response.breakpoints[i].line = Breakpoints[sourcePath].back().GetLine();
+ response.breakpoints[i].verified = false;
+ dap::Source dapSrc;
+ dapSrc.path = sourcePath;
+ response.breakpoints[i].source = dapSrc;
+ }
+ }
+
+ return response;
+}
+
+void cmDebuggerBreakpointManager::SourceFileLoaded(
+ std::string const& sourcePath,
+ std::vector<cmListFileFunction> const& functions)
+{
+ std::unique_lock<std::mutex> lock(Mutex);
+ if (ListFileFunctionLines.find(sourcePath) != ListFileFunctionLines.end()) {
+ // this is not expected.
+ return;
+ }
+
+ for (cmListFileFunction const& func : functions) {
+ ListFileFunctionLines[sourcePath].emplace_back(
+ cmDebuggerFunctionLocation{ func.Line(), func.LineEnd() });
+ }
+
+ if (ListFilePendingValidations.find(sourcePath) ==
+ ListFilePendingValidations.end()) {
+ return;
+ }
+
+ ListFilePendingValidations.erase(sourcePath);
+
+ for (size_t i = 0; i < Breakpoints[sourcePath].size(); i++) {
+ dap::BreakpointEvent breakpointEvent;
+ breakpointEvent.breakpoint.id = Breakpoints[sourcePath][i].GetId();
+ breakpointEvent.breakpoint.line = Breakpoints[sourcePath][i].GetLine();
+ auto source = dap::Source();
+ source.path = sourcePath;
+ breakpointEvent.breakpoint.source = source;
+ int64_t correctedLine = CalibrateBreakpointLine(
+ sourcePath, Breakpoints[sourcePath][i].GetLine());
+ if (correctedLine != Breakpoints[sourcePath][i].GetLine()) {
+ Breakpoints[sourcePath][i].ChangeLine(correctedLine);
+ }
+ breakpointEvent.reason = "changed";
+ breakpointEvent.breakpoint.verified = (correctedLine > 0);
+ if (breakpointEvent.breakpoint.verified) {
+ breakpointEvent.breakpoint.line = correctedLine;
+ } else {
+ Breakpoints[sourcePath][i].Invalid();
+ }
+
+ DapSession->send(breakpointEvent);
+ }
+}
+
+std::vector<int64_t> cmDebuggerBreakpointManager::GetBreakpoints(
+ std::string const& sourcePath, int64_t line)
+{
+ std::unique_lock<std::mutex> lock(Mutex);
+ const auto& all = Breakpoints[sourcePath];
+ std::vector<int64_t> breakpoints;
+ if (all.empty()) {
+ return breakpoints;
+ }
+
+ auto it = all.begin();
+
+ while ((it = std::find_if(
+ it, all.end(), [&](const cmDebuggerSourceBreakpoint& breakpoint) {
+ return (breakpoint.GetIsValid() && breakpoint.GetLine() == line);
+ })) != all.end()) {
+ breakpoints.emplace_back(it->GetId());
+ ++it;
+ }
+
+ return breakpoints;
+}
+
+void cmDebuggerBreakpointManager::ClearAll()
+{
+ std::unique_lock<std::mutex> lock(Mutex);
+ Breakpoints.clear();
+}
+
+} // namespace cmDebugger
diff --git a/Source/cmDebuggerBreakpointManager.h b/Source/cmDebuggerBreakpointManager.h
new file mode 100644
index 0000000..a4e5df5
--- /dev/null
+++ b/Source/cmDebuggerBreakpointManager.h
@@ -0,0 +1,61 @@
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
+#pragma once
+
+#include "cmConfigure.h" // IWYU pragma: keep
+
+#include <cstdint>
+#include <mutex>
+#include <string>
+#include <unordered_map>
+#include <unordered_set>
+#include <vector>
+
+#include <cm3p/cppdap/protocol.h>
+
+class cmListFileFunction;
+
+namespace cmDebugger {
+class cmDebuggerSourceBreakpoint;
+}
+
+namespace dap {
+class Session;
+}
+
+namespace cmDebugger {
+
+struct cmDebuggerFunctionLocation
+{
+ int64_t StartLine;
+ int64_t EndLine;
+};
+
+/** The breakpoint manager. */
+class cmDebuggerBreakpointManager
+{
+ dap::Session* DapSession;
+ std::mutex Mutex;
+ std::unordered_map<std::string, std::vector<cmDebuggerSourceBreakpoint>>
+ Breakpoints;
+ std::unordered_map<std::string,
+ std::vector<struct cmDebuggerFunctionLocation>>
+ ListFileFunctionLines;
+ std::unordered_set<std::string> ListFilePendingValidations;
+ int64_t NextBreakpointId = 0;
+
+ dap::SetBreakpointsResponse HandleSetBreakpointsRequest(
+ dap::SetBreakpointsRequest const& request);
+ int64_t FindFunctionStartLine(std::string const& sourcePath, int64_t line);
+ int64_t CalibrateBreakpointLine(std::string const& sourcePath, int64_t line);
+
+public:
+ cmDebuggerBreakpointManager(dap::Session* dapSession);
+ void SourceFileLoaded(std::string const& sourcePath,
+ std::vector<cmListFileFunction> const& functions);
+ std::vector<int64_t> GetBreakpoints(std::string const& sourcePath,
+ int64_t line);
+ void ClearAll();
+};
+
+} // namespace cmDebugger
diff --git a/Source/cmDebuggerExceptionManager.cxx b/Source/cmDebuggerExceptionManager.cxx
new file mode 100644
index 0000000..a27426c
--- /dev/null
+++ b/Source/cmDebuggerExceptionManager.cxx
@@ -0,0 +1,129 @@
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
+#include "cmDebuggerExceptionManager.h"
+
+#include <utility>
+#include <vector>
+
+#include <cm3p/cppdap/optional.h>
+#include <cm3p/cppdap/session.h>
+#include <cm3p/cppdap/types.h>
+
+#include "cmDebuggerProtocol.h"
+#include "cmMessageType.h"
+
+namespace cmDebugger {
+
+cmDebuggerExceptionManager::cmDebuggerExceptionManager(
+ dap::Session* dapSession)
+ : DapSession(dapSession)
+{
+ // https://microsoft.github.io/debug-adapter-protocol/specification#Requests_SetExceptionBreakpoints
+ DapSession->registerHandler(
+ [&](const dap::SetExceptionBreakpointsRequest& request) {
+ return HandleSetExceptionBreakpointsRequest(request);
+ });
+
+ // https://microsoft.github.io/debug-adapter-protocol/specification#Requests_ExceptionInfo
+ DapSession->registerHandler([&](const dap::ExceptionInfoRequest& request) {
+ (void)request;
+ return HandleExceptionInfoRequest();
+ });
+
+ ExceptionMap[MessageType::AUTHOR_WARNING] =
+ cmDebuggerExceptionFilter{ "AUTHOR_WARNING", "Warning (dev)" };
+ ExceptionMap[MessageType::AUTHOR_ERROR] =
+ cmDebuggerExceptionFilter{ "AUTHOR_ERROR", "Error (dev)" };
+ ExceptionMap[MessageType::FATAL_ERROR] =
+ cmDebuggerExceptionFilter{ "FATAL_ERROR", "Fatal error" };
+ ExceptionMap[MessageType::INTERNAL_ERROR] =
+ cmDebuggerExceptionFilter{ "INTERNAL_ERROR", "Internal error" };
+ ExceptionMap[MessageType::MESSAGE] =
+ cmDebuggerExceptionFilter{ "MESSAGE", "Other messages" };
+ ExceptionMap[MessageType::WARNING] =
+ cmDebuggerExceptionFilter{ "WARNING", "Warning" };
+ ExceptionMap[MessageType::LOG] =
+ cmDebuggerExceptionFilter{ "LOG", "Debug log" };
+ ExceptionMap[MessageType::DEPRECATION_ERROR] =
+ cmDebuggerExceptionFilter{ "DEPRECATION_ERROR", "Deprecation error" };
+ ExceptionMap[MessageType::DEPRECATION_WARNING] =
+ cmDebuggerExceptionFilter{ "DEPRECATION_WARNING", "Deprecation warning" };
+ RaiseExceptions["AUTHOR_ERROR"] = true;
+ RaiseExceptions["FATAL_ERROR"] = true;
+ RaiseExceptions["INTERNAL_ERROR"] = true;
+ RaiseExceptions["DEPRECATION_ERROR"] = true;
+}
+
+dap::SetExceptionBreakpointsResponse
+cmDebuggerExceptionManager::HandleSetExceptionBreakpointsRequest(
+ dap::SetExceptionBreakpointsRequest const& request)
+{
+ std::unique_lock<std::mutex> lock(Mutex);
+ dap::SetExceptionBreakpointsResponse response;
+ RaiseExceptions.clear();
+ for (const auto& filter : request.filters) {
+ RaiseExceptions[filter] = true;
+ }
+
+ return response;
+}
+
+dap::ExceptionInfoResponse
+cmDebuggerExceptionManager::HandleExceptionInfoRequest()
+{
+ std::unique_lock<std::mutex> lock(Mutex);
+
+ dap::ExceptionInfoResponse response;
+ if (TheException.has_value()) {
+ response.exceptionId = TheException->Id;
+ response.breakMode = "always";
+ response.description = TheException->Description;
+ TheException = {};
+ }
+ return response;
+}
+
+void cmDebuggerExceptionManager::HandleInitializeRequest(
+ dap::CMakeInitializeResponse& response)
+{
+ std::unique_lock<std::mutex> lock(Mutex);
+ response.supportsExceptionInfoRequest = true;
+
+ dap::array<dap::ExceptionBreakpointsFilter> exceptionBreakpointFilters;
+ for (auto& pair : ExceptionMap) {
+ dap::ExceptionBreakpointsFilter filter;
+ filter.filter = pair.second.Filter;
+ filter.label = pair.second.Label;
+ filter.def = RaiseExceptions[filter.filter];
+ exceptionBreakpointFilters.emplace_back(filter);
+ }
+
+ response.exceptionBreakpointFilters = exceptionBreakpointFilters;
+}
+
+cm::optional<dap::StoppedEvent>
+cmDebuggerExceptionManager::RaiseExceptionIfAny(MessageType t,
+ std::string const& text)
+{
+ cm::optional<dap::StoppedEvent> maybeStoppedEvent;
+ std::unique_lock<std::mutex> lock(Mutex);
+ if (RaiseExceptions[ExceptionMap[t].Filter]) {
+ dap::StoppedEvent stoppedEvent;
+ stoppedEvent.allThreadsStopped = true;
+ stoppedEvent.reason = "exception";
+ stoppedEvent.description = "Pause on exception";
+ stoppedEvent.text = text;
+ TheException = cmDebuggerException{ ExceptionMap[t].Filter, text };
+ maybeStoppedEvent = std::move(stoppedEvent);
+ }
+
+ return maybeStoppedEvent;
+}
+
+void cmDebuggerExceptionManager::ClearAll()
+{
+ std::unique_lock<std::mutex> lock(Mutex);
+ RaiseExceptions.clear();
+}
+
+} // namespace cmDebugger
diff --git a/Source/cmDebuggerExceptionManager.h b/Source/cmDebuggerExceptionManager.h
new file mode 100644
index 0000000..b819128
--- /dev/null
+++ b/Source/cmDebuggerExceptionManager.h
@@ -0,0 +1,70 @@
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
+#pragma once
+
+#include "cmConfigure.h" // IWYU pragma: keep
+
+#include <cstddef>
+#include <functional>
+#include <mutex>
+#include <string>
+#include <unordered_map>
+
+#include <cm/optional>
+
+#include <cm3p/cppdap/protocol.h>
+
+#include "cmMessageType.h"
+
+namespace dap {
+class Session;
+struct CMakeInitializeResponse;
+}
+
+namespace cmDebugger {
+
+struct cmDebuggerException
+{
+ std::string Id;
+ std::string Description;
+};
+
+struct cmDebuggerExceptionFilter
+{
+ std::string Filter;
+ std::string Label;
+};
+
+/** The exception manager. */
+class cmDebuggerExceptionManager
+{
+ // Some older C++ standard libraries cannot hash an enum class by default.
+ struct MessageTypeHash
+ {
+ std::size_t operator()(MessageType t) const
+ {
+ return std::hash<int>{}(static_cast<int>(t));
+ }
+ };
+
+ dap::Session* DapSession;
+ std::mutex Mutex;
+ std::unordered_map<std::string, bool> RaiseExceptions;
+ std::unordered_map<MessageType, cmDebuggerExceptionFilter, MessageTypeHash>
+ ExceptionMap;
+ cm::optional<cmDebuggerException> TheException;
+
+ dap::SetExceptionBreakpointsResponse HandleSetExceptionBreakpointsRequest(
+ dap::SetExceptionBreakpointsRequest const& request);
+
+ dap::ExceptionInfoResponse HandleExceptionInfoRequest();
+
+public:
+ cmDebuggerExceptionManager(dap::Session* dapSession);
+ void HandleInitializeRequest(dap::CMakeInitializeResponse& response);
+ cm::optional<dap::StoppedEvent> RaiseExceptionIfAny(MessageType t,
+ std::string const& text);
+ void ClearAll();
+};
+
+} // namespace cmDebugger
diff --git a/Source/cmDebuggerPipeConnection.cxx b/Source/cmDebuggerPipeConnection.cxx
new file mode 100644
index 0000000..1b54346
--- /dev/null
+++ b/Source/cmDebuggerPipeConnection.cxx
@@ -0,0 +1,293 @@
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
+#include "cmDebuggerPipeConnection.h"
+
+#include <algorithm>
+#include <cassert>
+#include <cstring>
+#include <stdexcept>
+#include <utility>
+
+namespace cmDebugger {
+
+struct write_req_t
+{
+ uv_write_t req;
+ uv_buf_t buf;
+};
+
+cmDebuggerPipeBase::cmDebuggerPipeBase(std::string name)
+ : PipeName(std::move(name))
+{
+ Loop.init();
+ LoopExit.init(
+ *Loop, [](uv_async_t* handle) { uv_stop((uv_loop_t*)handle->data); },
+ Loop);
+ WriteEvent.init(
+ *Loop,
+ [](uv_async_t* handle) {
+ auto* conn = static_cast<cmDebuggerPipeBase*>(handle->data);
+ conn->WriteInternal();
+ },
+ this);
+ PipeClose.init(
+ *Loop,
+ [](uv_async_t* handle) {
+ auto* conn = static_cast<cmDebuggerPipeBase*>(handle->data);
+ if (conn->Pipe.get()) {
+ conn->Pipe->data = nullptr;
+ conn->Pipe.reset();
+ }
+ },
+ this);
+}
+
+void cmDebuggerPipeBase::WaitForConnection()
+{
+ std::unique_lock<std::mutex> lock(Mutex);
+ Connected.wait(lock, [this] { return isOpen() || FailedToOpen; });
+ if (FailedToOpen) {
+ throw std::runtime_error("Failed to open debugger connection.");
+ }
+}
+
+void cmDebuggerPipeBase::close()
+{
+ std::unique_lock<std::mutex> lock(Mutex);
+
+ CloseConnection();
+ PipeClose.send();
+ lock.unlock();
+ ReadReady.notify_all();
+}
+
+size_t cmDebuggerPipeBase::read(void* buffer, size_t n)
+{
+ std::unique_lock<std::mutex> lock(Mutex);
+ ReadReady.wait(lock, [this] { return !isOpen() || !ReadBuffer.empty(); });
+
+ if (!isOpen() && ReadBuffer.empty()) {
+ return 0;
+ }
+
+ auto size = std::min(n, ReadBuffer.size());
+ memcpy(buffer, ReadBuffer.data(), size);
+ ReadBuffer.erase(0, size);
+ return size;
+}
+
+bool cmDebuggerPipeBase::write(const void* buffer, size_t n)
+{
+ std::unique_lock<std::mutex> lock(Mutex);
+ WriteBuffer.append(static_cast<const char*>(buffer), n);
+ lock.unlock();
+ WriteEvent.send();
+
+ lock.lock();
+ WriteComplete.wait(lock, [this] { return WriteBuffer.empty(); });
+ return true;
+}
+
+void cmDebuggerPipeBase::StopLoop()
+{
+ LoopExit.send();
+
+ if (LoopThread.joinable()) {
+ LoopThread.join();
+ }
+}
+
+void cmDebuggerPipeBase::BufferData(const std::string& data)
+{
+ std::unique_lock<std::mutex> lock(Mutex);
+ ReadBuffer += data;
+ lock.unlock();
+ ReadReady.notify_all();
+}
+
+void cmDebuggerPipeBase::WriteInternal()
+{
+ std::unique_lock<std::mutex> lock(Mutex);
+ auto n = WriteBuffer.length();
+ assert(this->Pipe.get());
+ write_req_t* req = new write_req_t;
+ req->req.data = &WriteComplete;
+ char* rawBuffer = new char[n];
+ req->buf = uv_buf_init(rawBuffer, static_cast<unsigned int>(n));
+ memcpy(req->buf.base, WriteBuffer.data(), n);
+ WriteBuffer.clear();
+ lock.unlock();
+
+ uv_write(
+ reinterpret_cast<uv_write_t*>(req), this->Pipe, &req->buf, 1,
+ [](uv_write_t* cb_req, int status) {
+ (void)status; // We need to free memory even if the write failed.
+ write_req_t* wr = reinterpret_cast<write_req_t*>(cb_req);
+ reinterpret_cast<std::condition_variable*>(wr->req.data)->notify_all();
+ delete[] (wr->buf.base);
+ delete wr;
+ });
+
+#ifdef __clang_analyzer__
+ // Tell clang-analyzer that 'rawBuffer' does not leak.
+ // We pass ownership to the closure.
+ delete[] rawBuffer;
+#endif
+}
+
+cmDebuggerPipeConnection::cmDebuggerPipeConnection(std::string name)
+ : cmDebuggerPipeBase(std::move(name))
+{
+ ServerPipeClose.init(
+ *Loop,
+ [](uv_async_t* handle) {
+ auto* conn = static_cast<cmDebuggerPipeConnection*>(handle->data);
+ if (conn->ServerPipe.get()) {
+ conn->ServerPipe->data = nullptr;
+ conn->ServerPipe.reset();
+ }
+ },
+ this);
+}
+
+cmDebuggerPipeConnection::~cmDebuggerPipeConnection()
+{
+ StopLoop();
+}
+
+bool cmDebuggerPipeConnection::StartListening(std::string& errorMessage)
+{
+ this->ServerPipe.init(*Loop, 0,
+ static_cast<cmDebuggerPipeConnection*>(this));
+
+ int r;
+ if ((r = uv_pipe_bind(this->ServerPipe, this->PipeName.c_str())) != 0) {
+ errorMessage =
+ "Internal Error with " + this->PipeName + ": " + uv_err_name(r);
+ return false;
+ }
+
+ r = uv_listen(this->ServerPipe, 1, [](uv_stream_t* stream, int status) {
+ if (status >= 0) {
+ auto* conn = static_cast<cmDebuggerPipeConnection*>(stream->data);
+ if (conn) {
+ conn->Connect(stream);
+ }
+ }
+ });
+
+ if (r != 0) {
+ errorMessage =
+ "Internal Error listening on " + this->PipeName + ": " + uv_err_name(r);
+ return false;
+ }
+
+ // Start the libuv event loop thread so that a client can connect.
+ LoopThread = std::thread([this] { uv_run(Loop, UV_RUN_DEFAULT); });
+
+ StartedListening.set_value();
+
+ return true;
+}
+
+std::shared_ptr<dap::Reader> cmDebuggerPipeConnection::GetReader()
+{
+ return std::static_pointer_cast<dap::Reader>(shared_from_this());
+}
+
+std::shared_ptr<dap::Writer> cmDebuggerPipeConnection::GetWriter()
+{
+ return std::static_pointer_cast<dap::Writer>(shared_from_this());
+}
+
+bool cmDebuggerPipeConnection::isOpen()
+{
+ return this->Pipe.get() != nullptr;
+}
+
+void cmDebuggerPipeConnection::CloseConnection()
+{
+ ServerPipeClose.send();
+}
+
+void cmDebuggerPipeConnection::Connect(uv_stream_t* server)
+{
+ if (this->Pipe.get()) {
+ // Accept and close all pipes but the first:
+ cm::uv_pipe_ptr rejectPipe;
+
+ rejectPipe.init(*Loop, 0);
+ uv_accept(server, rejectPipe);
+
+ return;
+ }
+
+ cm::uv_pipe_ptr ClientPipe;
+ ClientPipe.init(*Loop, 0, static_cast<cmDebuggerPipeConnection*>(this));
+
+ if (uv_accept(server, ClientPipe) != 0) {
+ return;
+ }
+
+ StartReading<cmDebuggerPipeConnection>(ClientPipe);
+
+ std::unique_lock<std::mutex> lock(Mutex);
+ Pipe = std::move(ClientPipe);
+ lock.unlock();
+ Connected.notify_all();
+}
+
+cmDebuggerPipeClient::~cmDebuggerPipeClient()
+{
+ StopLoop();
+}
+
+void cmDebuggerPipeClient::Start()
+{
+ this->Pipe.init(*Loop, 0, static_cast<cmDebuggerPipeClient*>(this));
+
+ uv_connect_t* connect = new uv_connect_t;
+ connect->data = this;
+ uv_pipe_connect(
+ connect, Pipe, PipeName.c_str(), [](uv_connect_t* cb_connect, int status) {
+ auto* conn = static_cast<cmDebuggerPipeClient*>(cb_connect->data);
+ if (status >= 0) {
+ conn->Connect();
+ } else {
+ conn->FailConnection();
+ }
+ delete cb_connect;
+ });
+
+ // Start the libuv event loop so that the pipe can connect.
+ LoopThread = std::thread([this] { uv_run(Loop, UV_RUN_DEFAULT); });
+}
+
+bool cmDebuggerPipeClient::isOpen()
+{
+ return IsConnected;
+}
+
+void cmDebuggerPipeClient::CloseConnection()
+{
+ IsConnected = false;
+}
+
+void cmDebuggerPipeClient::Connect()
+{
+ StartReading<cmDebuggerPipeClient>(Pipe);
+ std::unique_lock<std::mutex> lock(Mutex);
+ IsConnected = true;
+ lock.unlock();
+ Connected.notify_all();
+}
+
+void cmDebuggerPipeClient::FailConnection()
+{
+ std::unique_lock<std::mutex> lock(Mutex);
+ FailedToOpen = true;
+ lock.unlock();
+ Connected.notify_all();
+}
+
+} // namespace cmDebugger
diff --git a/Source/cmDebuggerPipeConnection.h b/Source/cmDebuggerPipeConnection.h
new file mode 100644
index 0000000..0991ff7
--- /dev/null
+++ b/Source/cmDebuggerPipeConnection.h
@@ -0,0 +1,139 @@
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
+#pragma once
+
+#include "cmConfigure.h" // IWYU pragma: keep
+
+#include <condition_variable>
+#include <cstddef>
+#include <future>
+#include <memory>
+#include <mutex>
+#include <string>
+#include <thread>
+
+#include <cm3p/cppdap/io.h>
+#include <cm3p/uv.h>
+
+#include "cmDebuggerAdapter.h"
+#include "cmUVHandlePtr.h"
+
+namespace cmDebugger {
+
+class cmDebuggerPipeBase : public dap::ReaderWriter
+{
+public:
+ cmDebuggerPipeBase(std::string name);
+
+ void WaitForConnection();
+
+ // dap::ReaderWriter implementation
+
+ void close() final;
+ size_t read(void* buffer, size_t n) final;
+ bool write(const void* buffer, size_t n) final;
+
+protected:
+ virtual void CloseConnection(){};
+ template <typename T>
+ void StartReading(uv_stream_t* stream)
+ {
+ uv_read_start(
+ stream,
+ // alloc_cb
+ [](uv_handle_t* handle, size_t suggested_size, uv_buf_t* buf) {
+ (void)handle;
+ char* rawBuffer = new char[suggested_size];
+ *buf =
+ uv_buf_init(rawBuffer, static_cast<unsigned int>(suggested_size));
+ },
+ // read_cb
+ [](uv_stream_t* readStream, ssize_t nread, const uv_buf_t* buf) {
+ auto conn = static_cast<T*>(readStream->data);
+ if (conn) {
+ if (nread >= 0) {
+ conn->BufferData(std::string(buf->base, buf->base + nread));
+ } else {
+ conn->close();
+ }
+ }
+ delete[] (buf->base);
+ });
+ }
+ void StopLoop();
+
+ const std::string PipeName;
+ std::thread LoopThread;
+ cm::uv_loop_ptr Loop;
+ cm::uv_pipe_ptr Pipe;
+ std::mutex Mutex;
+ std::condition_variable Connected;
+ bool FailedToOpen = false;
+
+private:
+ void BufferData(const std::string& data);
+ void WriteInternal();
+
+ cm::uv_async_ptr LoopExit;
+ cm::uv_async_ptr WriteEvent;
+ cm::uv_async_ptr PipeClose;
+ std::string WriteBuffer;
+ std::string ReadBuffer;
+ std::condition_variable ReadReady;
+ std::condition_variable WriteComplete;
+};
+
+class cmDebuggerPipeConnection
+ : public cmDebuggerPipeBase
+ , public cmDebuggerConnection
+ , public std::enable_shared_from_this<cmDebuggerPipeConnection>
+{
+public:
+ cmDebuggerPipeConnection(std::string name);
+ ~cmDebuggerPipeConnection() override;
+
+ void WaitForConnection() override
+ {
+ cmDebuggerPipeBase::WaitForConnection();
+ }
+
+ bool StartListening(std::string& errorMessage) override;
+ std::shared_ptr<dap::Reader> GetReader() override;
+ std::shared_ptr<dap::Writer> GetWriter() override;
+
+ // dap::ReaderWriter implementation
+
+ bool isOpen() override;
+
+ // Used for unit test synchronization
+ std::promise<void> StartedListening;
+
+private:
+ void CloseConnection() override;
+ void Connect(uv_stream_t* server);
+
+ cm::uv_pipe_ptr ServerPipe;
+ cm::uv_async_ptr ServerPipeClose;
+};
+
+class cmDebuggerPipeClient : public cmDebuggerPipeBase
+{
+public:
+ using cmDebuggerPipeBase::cmDebuggerPipeBase;
+ ~cmDebuggerPipeClient() override;
+
+ void Start();
+
+ // dap::ReaderWriter implementation
+
+ bool isOpen() override;
+
+private:
+ void CloseConnection() override;
+ void Connect();
+ void FailConnection();
+
+ bool IsConnected = false;
+};
+
+} // namespace cmDebugger
diff --git a/Source/cmDebuggerProtocol.cxx b/Source/cmDebuggerProtocol.cxx
new file mode 100644
index 0000000..505de35
--- /dev/null
+++ b/Source/cmDebuggerProtocol.cxx
@@ -0,0 +1,80 @@
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
+
+#include "cmDebuggerProtocol.h"
+
+#include <string>
+
+namespace dap {
+DAP_IMPLEMENT_STRUCT_TYPEINFO(CMakeVersion, "", DAP_FIELD(major, "major"),
+ DAP_FIELD(minor, "minor"),
+ DAP_FIELD(patch, "patch"),
+ DAP_FIELD(full, "full"));
+
+DAP_IMPLEMENT_STRUCT_TYPEINFO(
+ CMakeInitializeResponse, "",
+ DAP_FIELD(additionalModuleColumns, "additionalModuleColumns"),
+ DAP_FIELD(completionTriggerCharacters, "completionTriggerCharacters"),
+ DAP_FIELD(exceptionBreakpointFilters, "exceptionBreakpointFilters"),
+ DAP_FIELD(supportSuspendDebuggee, "supportSuspendDebuggee"),
+ DAP_FIELD(supportTerminateDebuggee, "supportTerminateDebuggee"),
+ DAP_FIELD(supportedChecksumAlgorithms, "supportedChecksumAlgorithms"),
+ DAP_FIELD(supportsBreakpointLocationsRequest,
+ "supportsBreakpointLocationsRequest"),
+ DAP_FIELD(supportsCancelRequest, "supportsCancelRequest"),
+ DAP_FIELD(supportsClipboardContext, "supportsClipboardContext"),
+ DAP_FIELD(supportsCompletionsRequest, "supportsCompletionsRequest"),
+ DAP_FIELD(supportsConditionalBreakpoints, "supportsConditionalBreakpoints"),
+ DAP_FIELD(supportsConfigurationDoneRequest,
+ "supportsConfigurationDoneRequest"),
+ DAP_FIELD(supportsDataBreakpoints, "supportsDataBreakpoints"),
+ DAP_FIELD(supportsDelayedStackTraceLoading,
+ "supportsDelayedStackTraceLoading"),
+ DAP_FIELD(supportsDisassembleRequest, "supportsDisassembleRequest"),
+ DAP_FIELD(supportsEvaluateForHovers, "supportsEvaluateForHovers"),
+ DAP_FIELD(supportsExceptionFilterOptions, "supportsExceptionFilterOptions"),
+ DAP_FIELD(supportsExceptionInfoRequest, "supportsExceptionInfoRequest"),
+ DAP_FIELD(supportsExceptionOptions, "supportsExceptionOptions"),
+ DAP_FIELD(supportsFunctionBreakpoints, "supportsFunctionBreakpoints"),
+ DAP_FIELD(supportsGotoTargetsRequest, "supportsGotoTargetsRequest"),
+ DAP_FIELD(supportsHitConditionalBreakpoints,
+ "supportsHitConditionalBreakpoints"),
+ DAP_FIELD(supportsInstructionBreakpoints, "supportsInstructionBreakpoints"),
+ DAP_FIELD(supportsLoadedSourcesRequest, "supportsLoadedSourcesRequest"),
+ DAP_FIELD(supportsLogPoints, "supportsLogPoints"),
+ DAP_FIELD(supportsModulesRequest, "supportsModulesRequest"),
+ DAP_FIELD(supportsReadMemoryRequest, "supportsReadMemoryRequest"),
+ DAP_FIELD(supportsRestartFrame, "supportsRestartFrame"),
+ DAP_FIELD(supportsRestartRequest, "supportsRestartRequest"),
+ DAP_FIELD(supportsSetExpression, "supportsSetExpression"),
+ DAP_FIELD(supportsSetVariable, "supportsSetVariable"),
+ DAP_FIELD(supportsSingleThreadExecutionRequests,
+ "supportsSingleThreadExecutionRequests"),
+ DAP_FIELD(supportsStepBack, "supportsStepBack"),
+ DAP_FIELD(supportsStepInTargetsRequest, "supportsStepInTargetsRequest"),
+ DAP_FIELD(supportsSteppingGranularity, "supportsSteppingGranularity"),
+ DAP_FIELD(supportsTerminateRequest, "supportsTerminateRequest"),
+ DAP_FIELD(supportsTerminateThreadsRequest,
+ "supportsTerminateThreadsRequest"),
+ DAP_FIELD(supportsValueFormattingOptions, "supportsValueFormattingOptions"),
+ DAP_FIELD(supportsWriteMemoryRequest, "supportsWriteMemoryRequest"),
+ DAP_FIELD(cmakeVersion, "cmakeVersion"));
+
+DAP_IMPLEMENT_STRUCT_TYPEINFO(
+ CMakeInitializeRequest, "initialize", DAP_FIELD(adapterID, "adapterID"),
+ DAP_FIELD(clientID, "clientID"), DAP_FIELD(clientName, "clientName"),
+ DAP_FIELD(columnsStartAt1, "columnsStartAt1"),
+ DAP_FIELD(linesStartAt1, "linesStartAt1"), DAP_FIELD(locale, "locale"),
+ DAP_FIELD(pathFormat, "pathFormat"),
+ DAP_FIELD(supportsArgsCanBeInterpretedByShell,
+ "supportsArgsCanBeInterpretedByShell"),
+ DAP_FIELD(supportsInvalidatedEvent, "supportsInvalidatedEvent"),
+ DAP_FIELD(supportsMemoryEvent, "supportsMemoryEvent"),
+ DAP_FIELD(supportsMemoryReferences, "supportsMemoryReferences"),
+ DAP_FIELD(supportsProgressReporting, "supportsProgressReporting"),
+ DAP_FIELD(supportsRunInTerminalRequest, "supportsRunInTerminalRequest"),
+ DAP_FIELD(supportsStartDebuggingRequest, "supportsStartDebuggingRequest"),
+ DAP_FIELD(supportsVariablePaging, "supportsVariablePaging"),
+ DAP_FIELD(supportsVariableType, "supportsVariableType"));
+
+} // namespace dap
diff --git a/Source/cmDebuggerProtocol.h b/Source/cmDebuggerProtocol.h
new file mode 100644
index 0000000..4334aed
--- /dev/null
+++ b/Source/cmDebuggerProtocol.h
@@ -0,0 +1,191 @@
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
+#pragma once
+
+#include "cmConfigure.h" // IWYU pragma: keep
+
+#include <vector>
+
+#include <cm3p/cppdap/protocol.h>
+
+#include <cmcppdap/include/dap/optional.h>
+#include <cmcppdap/include/dap/typeof.h>
+#include <cmcppdap/include/dap/types.h>
+
+namespace dap {
+
+// Represents the cmake version.
+struct CMakeVersion : public InitializeResponse
+{
+ // The major version number.
+ integer major;
+ // The minor version number.
+ integer minor;
+ // The patch number.
+ integer patch;
+ // The full version string.
+ string full;
+};
+
+DAP_DECLARE_STRUCT_TYPEINFO(CMakeVersion);
+
+// Response to `initialize` request.
+struct CMakeInitializeResponse : public Response
+{
+ // The set of additional module information exposed by the debug adapter.
+ optional<array<ColumnDescriptor>> additionalModuleColumns;
+ // The set of characters that should trigger completion in a REPL. If not
+ // specified, the UI should assume the `.` character.
+ optional<array<string>> completionTriggerCharacters;
+ // Available exception filter options for the `setExceptionBreakpoints`
+ // request.
+ optional<array<ExceptionBreakpointsFilter>> exceptionBreakpointFilters;
+ // The debug adapter supports the `suspendDebuggee` attribute on the
+ // `disconnect` request.
+ optional<boolean> supportSuspendDebuggee;
+ // The debug adapter supports the `terminateDebuggee` attribute on the
+ // `disconnect` request.
+ optional<boolean> supportTerminateDebuggee;
+ // Checksum algorithms supported by the debug adapter.
+ optional<array<ChecksumAlgorithm>> supportedChecksumAlgorithms;
+ // The debug adapter supports the `breakpointLocations` request.
+ optional<boolean> supportsBreakpointLocationsRequest;
+ // The debug adapter supports the `cancel` request.
+ optional<boolean> supportsCancelRequest;
+ // The debug adapter supports the `clipboard` context value in the `evaluate`
+ // request.
+ optional<boolean> supportsClipboardContext;
+ // The debug adapter supports the `completions` request.
+ optional<boolean> supportsCompletionsRequest;
+ // The debug adapter supports conditional breakpoints.
+ optional<boolean> supportsConditionalBreakpoints;
+ // The debug adapter supports the `configurationDone` request.
+ optional<boolean> supportsConfigurationDoneRequest;
+ // The debug adapter supports data breakpoints.
+ optional<boolean> supportsDataBreakpoints;
+ // The debug adapter supports the delayed loading of parts of the stack,
+ // which requires that both the `startFrame` and `levels` arguments and the
+ // `totalFrames` result of the `stackTrace` request are supported.
+ optional<boolean> supportsDelayedStackTraceLoading;
+ // The debug adapter supports the `disassemble` request.
+ optional<boolean> supportsDisassembleRequest;
+ // The debug adapter supports a (side effect free) `evaluate` request for
+ // data hovers.
+ optional<boolean> supportsEvaluateForHovers;
+ // The debug adapter supports `filterOptions` as an argument on the
+ // `setExceptionBreakpoints` request.
+ optional<boolean> supportsExceptionFilterOptions;
+ // The debug adapter supports the `exceptionInfo` request.
+ optional<boolean> supportsExceptionInfoRequest;
+ // The debug adapter supports `exceptionOptions` on the
+ // `setExceptionBreakpoints` request.
+ optional<boolean> supportsExceptionOptions;
+ // The debug adapter supports function breakpoints.
+ optional<boolean> supportsFunctionBreakpoints;
+ // The debug adapter supports the `gotoTargets` request.
+ optional<boolean> supportsGotoTargetsRequest;
+ // The debug adapter supports breakpoints that break execution after a
+ // specified number of hits.
+ optional<boolean> supportsHitConditionalBreakpoints;
+ // The debug adapter supports adding breakpoints based on instruction
+ // references.
+ optional<boolean> supportsInstructionBreakpoints;
+ // The debug adapter supports the `loadedSources` request.
+ optional<boolean> supportsLoadedSourcesRequest;
+ // The debug adapter supports log points by interpreting the `logMessage`
+ // attribute of the `SourceBreakpoint`.
+ optional<boolean> supportsLogPoints;
+ // The debug adapter supports the `modules` request.
+ optional<boolean> supportsModulesRequest;
+ // The debug adapter supports the `readMemory` request.
+ optional<boolean> supportsReadMemoryRequest;
+ // The debug adapter supports restarting a frame.
+ optional<boolean> supportsRestartFrame;
+ // The debug adapter supports the `restart` request. In this case a client
+ // should not implement `restart` by terminating and relaunching the adapter
+ // but by calling the `restart` request.
+ optional<boolean> supportsRestartRequest;
+ // The debug adapter supports the `setExpression` request.
+ optional<boolean> supportsSetExpression;
+ // The debug adapter supports setting a variable to a value.
+ optional<boolean> supportsSetVariable;
+ // The debug adapter supports the `singleThread` property on the execution
+ // requests (`continue`, `next`, `stepIn`, `stepOut`, `reverseContinue`,
+ // `stepBack`).
+ optional<boolean> supportsSingleThreadExecutionRequests;
+ // The debug adapter supports stepping back via the `stepBack` and
+ // `reverseContinue` requests.
+ optional<boolean> supportsStepBack;
+ // The debug adapter supports the `stepInTargets` request.
+ optional<boolean> supportsStepInTargetsRequest;
+ // The debug adapter supports stepping granularities (argument `granularity`)
+ // for the stepping requests.
+ optional<boolean> supportsSteppingGranularity;
+ // The debug adapter supports the `terminate` request.
+ optional<boolean> supportsTerminateRequest;
+ // The debug adapter supports the `terminateThreads` request.
+ optional<boolean> supportsTerminateThreadsRequest;
+ // The debug adapter supports a `format` attribute on the `stackTrace`,
+ // `variables`, and `evaluate` requests.
+ optional<boolean> supportsValueFormattingOptions;
+ // The debug adapter supports the `writeMemory` request.
+ optional<boolean> supportsWriteMemoryRequest;
+ // The CMake version.
+ CMakeVersion cmakeVersion;
+};
+
+DAP_DECLARE_STRUCT_TYPEINFO(CMakeInitializeResponse);
+
+// The `initialize` request is sent as the first request from the client to the
+// debug adapter in order to configure it with client capabilities and to
+// retrieve capabilities from the debug adapter. Until the debug adapter has
+// responded with an `initialize` response, the client must not send any
+// additional requests or events to the debug adapter. In addition the debug
+// adapter is not allowed to send any requests or events to the client until it
+// has responded with an `initialize` response. The `initialize` request may
+// only be sent once.
+struct CMakeInitializeRequest : public Request
+{
+ using Response = CMakeInitializeResponse;
+ // The ID of the debug adapter.
+ string adapterID;
+ // The ID of the client using this adapter.
+ optional<string> clientID;
+ // The human-readable name of the client using this adapter.
+ optional<string> clientName;
+ // If true all column numbers are 1-based (default).
+ optional<boolean> columnsStartAt1;
+ // If true all line numbers are 1-based (default).
+ optional<boolean> linesStartAt1;
+ // The ISO-639 locale of the client using this adapter, e.g. en-US or de-CH.
+ optional<string> locale;
+ // Determines in what format paths are specified. The default is `path`,
+ // which is the native format.
+ //
+ // May be one of the following enumeration values:
+ // 'path', 'uri'
+ optional<string> pathFormat;
+ // Client supports the `argsCanBeInterpretedByShell` attribute on the
+ // `runInTerminal` request.
+ optional<boolean> supportsArgsCanBeInterpretedByShell;
+ // Client supports the `invalidated` event.
+ optional<boolean> supportsInvalidatedEvent;
+ // Client supports the `memory` event.
+ optional<boolean> supportsMemoryEvent;
+ // Client supports memory references.
+ optional<boolean> supportsMemoryReferences;
+ // Client supports progress reporting.
+ optional<boolean> supportsProgressReporting;
+ // Client supports the `runInTerminal` request.
+ optional<boolean> supportsRunInTerminalRequest;
+ // Client supports the `startDebugging` request.
+ optional<boolean> supportsStartDebuggingRequest;
+ // Client supports the paging of variables.
+ optional<boolean> supportsVariablePaging;
+ // Client supports the `type` attribute for variables.
+ optional<boolean> supportsVariableType;
+};
+
+DAP_DECLARE_STRUCT_TYPEINFO(CMakeInitializeRequest);
+
+} // namespace dap
diff --git a/Source/cmDebuggerSourceBreakpoint.cxx b/Source/cmDebuggerSourceBreakpoint.cxx
new file mode 100644
index 0000000..d4665e6
--- /dev/null
+++ b/Source/cmDebuggerSourceBreakpoint.cxx
@@ -0,0 +1,14 @@
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
+#include "cmDebuggerSourceBreakpoint.h"
+
+namespace cmDebugger {
+
+cmDebuggerSourceBreakpoint::cmDebuggerSourceBreakpoint(int64_t id,
+ int64_t line)
+ : Id(id)
+ , Line(line)
+{
+}
+
+} // namespace cmDebugger
diff --git a/Source/cmDebuggerSourceBreakpoint.h b/Source/cmDebuggerSourceBreakpoint.h
new file mode 100644
index 0000000..f6d6cac
--- /dev/null
+++ b/Source/cmDebuggerSourceBreakpoint.h
@@ -0,0 +1,26 @@
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
+#pragma once
+
+#include "cmConfigure.h" // IWYU pragma: keep
+
+#include <cstdint>
+
+namespace cmDebugger {
+
+class cmDebuggerSourceBreakpoint
+{
+ int64_t Id;
+ int64_t Line;
+ bool IsValid = true;
+
+public:
+ cmDebuggerSourceBreakpoint(int64_t id, int64_t line);
+ int64_t GetId() const noexcept { return this->Id; }
+ int64_t GetLine() const noexcept { return this->Line; }
+ void ChangeLine(int64_t line) noexcept { this->Line = line; }
+ bool GetIsValid() const noexcept { return this->IsValid; }
+ void Invalid() noexcept { this->IsValid = false; }
+};
+
+} // namespace cmDebugger
diff --git a/Source/cmDebuggerStackFrame.cxx b/Source/cmDebuggerStackFrame.cxx
new file mode 100644
index 0000000..789b0a5
--- /dev/null
+++ b/Source/cmDebuggerStackFrame.cxx
@@ -0,0 +1,28 @@
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
+#include "cmDebuggerStackFrame.h"
+
+#include <utility>
+
+#include "cmListFileCache.h"
+
+namespace cmDebugger {
+
+std::atomic<int64_t> cmDebuggerStackFrame::NextId(1);
+
+cmDebuggerStackFrame::cmDebuggerStackFrame(cmMakefile* mf,
+ std::string sourcePath,
+ cmListFileFunction const& lff)
+ : Id(NextId.fetch_add(1))
+ , FileName(std::move(sourcePath))
+ , Function(lff)
+ , Makefile(mf)
+{
+}
+
+int64_t cmDebuggerStackFrame::GetLine() const noexcept
+{
+ return this->Function.Line();
+}
+
+} // namespace cmDebugger
diff --git a/Source/cmDebuggerStackFrame.h b/Source/cmDebuggerStackFrame.h
new file mode 100644
index 0000000..dc3b2ab
--- /dev/null
+++ b/Source/cmDebuggerStackFrame.h
@@ -0,0 +1,33 @@
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
+#pragma once
+
+#include "cmConfigure.h" // IWYU pragma: keep
+
+#include <atomic>
+#include <cstdint>
+#include <string>
+
+class cmListFileFunction;
+class cmMakefile;
+
+namespace cmDebugger {
+
+class cmDebuggerStackFrame
+{
+ static std::atomic<std::int64_t> NextId;
+ std::int64_t Id;
+ std::string FileName;
+ cmListFileFunction const& Function;
+ cmMakefile* Makefile;
+
+public:
+ cmDebuggerStackFrame(cmMakefile* mf, std::string sourcePath,
+ cmListFileFunction const& lff);
+ int64_t GetId() const noexcept { return this->Id; }
+ std::string const& GetFileName() const noexcept { return this->FileName; }
+ int64_t GetLine() const noexcept;
+ cmMakefile* GetMakefile() const noexcept { return this->Makefile; }
+};
+
+} // namespace cmDebugger
diff --git a/Source/cmDebuggerThread.cxx b/Source/cmDebuggerThread.cxx
new file mode 100644
index 0000000..fd52f5a
--- /dev/null
+++ b/Source/cmDebuggerThread.cxx
@@ -0,0 +1,150 @@
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
+
+#include "cmDebuggerThread.h"
+
+#include <cstdint>
+#include <utility>
+
+#include <cm3p/cppdap/optional.h>
+#include <cm3p/cppdap/types.h>
+
+#include "cmDebuggerStackFrame.h"
+#include "cmDebuggerVariables.h"
+#include "cmDebuggerVariablesHelper.h"
+#include "cmDebuggerVariablesManager.h"
+
+namespace cmDebugger {
+
+cmDebuggerThread::cmDebuggerThread(int64_t id, std::string name)
+ : Id(id)
+ , Name(std::move(name))
+ , VariablesManager(std::make_shared<cmDebuggerVariablesManager>())
+{
+}
+
+void cmDebuggerThread::PushStackFrame(cmMakefile* mf,
+ std::string const& sourcePath,
+ cmListFileFunction const& lff)
+{
+ std::unique_lock<std::mutex> lock(Mutex);
+ Frames.emplace_back(
+ std::make_shared<cmDebuggerStackFrame>(mf, sourcePath, lff));
+ FrameMap.insert({ Frames.back()->GetId(), Frames.back() });
+}
+
+void cmDebuggerThread::PopStackFrame()
+{
+ std::unique_lock<std::mutex> lock(Mutex);
+ FrameMap.erase(Frames.back()->GetId());
+ FrameScopes.erase(Frames.back()->GetId());
+ FrameVariables.erase(Frames.back()->GetId());
+ Frames.pop_back();
+}
+
+std::shared_ptr<cmDebuggerStackFrame> cmDebuggerThread::GetTopStackFrame()
+{
+ std::unique_lock<std::mutex> lock(Mutex);
+ if (!Frames.empty()) {
+ return Frames.back();
+ }
+
+ return {};
+}
+
+std::shared_ptr<cmDebuggerStackFrame> cmDebuggerThread::GetStackFrame(
+ int64_t frameId)
+{
+ std::unique_lock<std::mutex> lock(Mutex);
+ auto it = FrameMap.find(frameId);
+
+ if (it == FrameMap.end()) {
+ return {};
+ }
+
+ return it->second;
+}
+
+dap::ScopesResponse cmDebuggerThread::GetScopesResponse(
+ int64_t frameId, bool supportsVariableType)
+{
+ std::unique_lock<std::mutex> lock(Mutex);
+ auto it = FrameScopes.find(frameId);
+
+ if (it != FrameScopes.end()) {
+ dap::ScopesResponse response;
+ response.scopes = it->second;
+ return response;
+ }
+
+ auto it2 = FrameMap.find(frameId);
+ if (it2 == FrameMap.end()) {
+ return dap::ScopesResponse();
+ }
+
+ std::shared_ptr<cmDebuggerStackFrame> frame = it2->second;
+ std::shared_ptr<cmDebuggerVariables> localVariables =
+ cmDebuggerVariablesHelper::Create(VariablesManager, "Locals",
+ supportsVariableType, frame);
+
+ FrameVariables[frameId].emplace_back(localVariables);
+
+ dap::Scope scope;
+ scope.name = localVariables->GetName();
+ scope.presentationHint = "locals";
+ scope.variablesReference = localVariables->GetId();
+
+ dap::Source source;
+ source.name = frame->GetFileName();
+ source.path = source.name;
+ scope.source = source;
+
+ FrameScopes[frameId].push_back(scope);
+
+ dap::ScopesResponse response;
+ response.scopes.push_back(scope);
+ return response;
+}
+
+dap::VariablesResponse cmDebuggerThread::GetVariablesResponse(
+ dap::VariablesRequest const& request)
+{
+ std::unique_lock<std::mutex> lock(Mutex);
+ dap::VariablesResponse response;
+ response.variables = VariablesManager->HandleVariablesRequest(request);
+ return response;
+}
+
+dap::StackTraceResponse GetStackTraceResponse(
+ std::shared_ptr<cmDebuggerThread> const& thread)
+{
+ dap::StackTraceResponse response;
+ std::unique_lock<std::mutex> lock(thread->Mutex);
+ for (int i = static_cast<int>(thread->Frames.size()) - 1; i >= 0; --i) {
+ dap::Source source;
+ source.name = thread->Frames[i]->GetFileName();
+ source.path = source.name;
+
+#ifdef __GNUC__
+# pragma GCC diagnostic push
+# pragma GCC diagnostic ignored "-Warray-bounds"
+#endif
+ dap::StackFrame stackFrame;
+#ifdef __GNUC__
+# pragma GCC diagnostic pop
+#endif
+ stackFrame.line = thread->Frames[i]->GetLine();
+ stackFrame.column = 1;
+ stackFrame.name = thread->Frames[i]->GetFileName() + " Line " +
+ std::to_string(stackFrame.line);
+ stackFrame.id = thread->Frames[i]->GetId();
+ stackFrame.source = source;
+
+ response.stackFrames.push_back(stackFrame);
+ }
+
+ response.totalFrames = response.stackFrames.size();
+ return response;
+}
+
+} // namespace cmDebugger
diff --git a/Source/cmDebuggerThread.h b/Source/cmDebuggerThread.h
new file mode 100644
index 0000000..65ee2cf
--- /dev/null
+++ b/Source/cmDebuggerThread.h
@@ -0,0 +1,59 @@
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
+#pragma once
+
+#include "cmConfigure.h" // IWYU pragma: keep
+
+#include <cstddef>
+#include <cstdint>
+#include <memory>
+#include <mutex>
+#include <string>
+#include <unordered_map>
+#include <vector>
+
+#include <cm3p/cppdap/protocol.h>
+
+class cmListFileFunction;
+class cmMakefile;
+
+namespace cmDebugger {
+class cmDebuggerStackFrame;
+class cmDebuggerVariables;
+class cmDebuggerVariablesManager;
+}
+
+namespace cmDebugger {
+
+class cmDebuggerThread
+{
+ int64_t Id;
+ std::string Name;
+ std::vector<std::shared_ptr<cmDebuggerStackFrame>> Frames;
+ std::unordered_map<int64_t, std::shared_ptr<cmDebuggerStackFrame>> FrameMap;
+ std::mutex Mutex;
+ std::unordered_map<int64_t, std::vector<dap::Scope>> FrameScopes;
+ std::unordered_map<int64_t,
+ std::vector<std::shared_ptr<cmDebuggerVariables>>>
+ FrameVariables;
+ std::shared_ptr<cmDebuggerVariablesManager> VariablesManager;
+
+public:
+ cmDebuggerThread(int64_t id, std::string name);
+ int64_t GetId() const { return this->Id; }
+ const std::string& GetName() const { return this->Name; }
+ void PushStackFrame(cmMakefile* mf, std::string const& sourcePath,
+ cmListFileFunction const& lff);
+ void PopStackFrame();
+ std::shared_ptr<cmDebuggerStackFrame> GetTopStackFrame();
+ std::shared_ptr<cmDebuggerStackFrame> GetStackFrame(int64_t frameId);
+ size_t GetStackFrameSize() const { return this->Frames.size(); }
+ dap::ScopesResponse GetScopesResponse(int64_t frameId,
+ bool supportsVariableType);
+ dap::VariablesResponse GetVariablesResponse(
+ dap::VariablesRequest const& request);
+ friend dap::StackTraceResponse GetStackTraceResponse(
+ std::shared_ptr<cmDebuggerThread> const& thread);
+};
+
+} // namespace cmDebugger
diff --git a/Source/cmDebuggerThreadManager.cxx b/Source/cmDebuggerThreadManager.cxx
new file mode 100644
index 0000000..0eb443b
--- /dev/null
+++ b/Source/cmDebuggerThreadManager.cxx
@@ -0,0 +1,47 @@
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
+
+#include "cmDebuggerThreadManager.h"
+
+#include <algorithm>
+
+#include <cm3p/cppdap/protocol.h>
+
+#include "cmDebuggerThread.h"
+
+namespace cmDebugger {
+
+std::atomic<int64_t> cmDebuggerThreadManager::NextThreadId(1);
+
+std::shared_ptr<cmDebuggerThread> cmDebuggerThreadManager::StartThread(
+ std::string const& name)
+{
+ std::shared_ptr<cmDebuggerThread> thread =
+ std::make_shared<cmDebuggerThread>(
+ cmDebuggerThreadManager::NextThreadId.fetch_add(1), name);
+ Threads.emplace_back(thread);
+ return thread;
+}
+
+void cmDebuggerThreadManager::EndThread(
+ std::shared_ptr<cmDebuggerThread> const& thread)
+{
+ Threads.remove(thread);
+}
+
+cm::optional<dap::StackTraceResponse>
+cmDebuggerThreadManager::GetThreadStackTraceResponse(int64_t id)
+{
+ auto it = find_if(Threads.begin(), Threads.end(),
+ [&](const std::shared_ptr<cmDebuggerThread>& t) {
+ return t->GetId() == id;
+ });
+
+ if (it == Threads.end()) {
+ return {};
+ }
+
+ return GetStackTraceResponse(*it);
+}
+
+} // namespace cmDebugger
diff --git a/Source/cmDebuggerThreadManager.h b/Source/cmDebuggerThreadManager.h
new file mode 100644
index 0000000..934cf85
--- /dev/null
+++ b/Source/cmDebuggerThreadManager.h
@@ -0,0 +1,38 @@
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
+#pragma once
+
+#include "cmConfigure.h" // IWYU pragma: keep
+
+#include <atomic>
+#include <cstdint>
+#include <list>
+#include <memory>
+#include <string>
+
+#include <cm/optional>
+
+namespace cmDebugger {
+class cmDebuggerThread;
+}
+
+namespace dap {
+struct StackTraceResponse;
+}
+
+namespace cmDebugger {
+
+class cmDebuggerThreadManager
+{
+ static std::atomic<std::int64_t> NextThreadId;
+ std::list<std::shared_ptr<cmDebuggerThread>> Threads;
+
+public:
+ cmDebuggerThreadManager() = default;
+ std::shared_ptr<cmDebuggerThread> StartThread(std::string const& name);
+ void EndThread(std::shared_ptr<cmDebuggerThread> const& thread);
+ cm::optional<dap::StackTraceResponse> GetThreadStackTraceResponse(
+ std::int64_t id);
+};
+
+} // namespace cmDebugger
diff --git a/Source/cmDebuggerVariables.cxx b/Source/cmDebuggerVariables.cxx
new file mode 100644
index 0000000..40fe41f
--- /dev/null
+++ b/Source/cmDebuggerVariables.cxx
@@ -0,0 +1,133 @@
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
+
+#include "cmDebuggerVariables.h"
+
+#include <algorithm>
+#include <vector>
+
+#include <cm3p/cppdap/optional.h>
+#include <cm3p/cppdap/protocol.h>
+#include <cm3p/cppdap/types.h>
+
+#include "cmDebuggerVariablesManager.h"
+
+namespace cmDebugger {
+
+namespace {
+const dap::VariablePresentationHint PrivatePropertyHint = { {},
+ "property",
+ {},
+ "private" };
+const dap::VariablePresentationHint PrivateDataHint = { {},
+ "data",
+ {},
+ "private" };
+}
+
+std::atomic<int64_t> cmDebuggerVariables::NextId(1);
+
+cmDebuggerVariables::cmDebuggerVariables(
+ std::shared_ptr<cmDebuggerVariablesManager> variablesManager,
+ std::string name, bool supportsVariableType)
+ : Id(NextId.fetch_add(1))
+ , Name(std::move(name))
+ , SupportsVariableType(supportsVariableType)
+ , VariablesManager(std::move(variablesManager))
+{
+ VariablesManager->RegisterHandler(
+ Id, [this](dap::VariablesRequest const& request) {
+ (void)request;
+ return this->HandleVariablesRequest();
+ });
+}
+
+cmDebuggerVariables::cmDebuggerVariables(
+ std::shared_ptr<cmDebuggerVariablesManager> variablesManager,
+ std::string name, bool supportsVariableType,
+ std::function<std::vector<cmDebuggerVariableEntry>()> getKeyValuesFunction)
+ : Id(NextId.fetch_add(1))
+ , Name(std::move(name))
+ , GetKeyValuesFunction(std::move(getKeyValuesFunction))
+ , SupportsVariableType(supportsVariableType)
+ , VariablesManager(std::move(variablesManager))
+{
+ VariablesManager->RegisterHandler(
+ Id, [this](dap::VariablesRequest const& request) {
+ (void)request;
+ return this->HandleVariablesRequest();
+ });
+}
+
+void cmDebuggerVariables::AddSubVariables(
+ std::shared_ptr<cmDebuggerVariables> const& variables)
+{
+ if (variables != nullptr) {
+ SubVariables.emplace_back(variables);
+ }
+}
+
+dap::array<dap::Variable> cmDebuggerVariables::HandleVariablesRequest()
+{
+ dap::array<dap::Variable> variables;
+
+ if (GetKeyValuesFunction != nullptr) {
+ auto values = GetKeyValuesFunction();
+ for (auto const& entry : values) {
+ if (IgnoreEmptyStringEntries && entry.Type == "string" &&
+ entry.Value.empty()) {
+ continue;
+ }
+ variables.push_back(dap::Variable{ {},
+ {},
+ {},
+ entry.Name,
+ {},
+ PrivateDataHint,
+ entry.Type,
+ entry.Value,
+ 0 });
+ }
+ }
+
+ EnumerateSubVariablesIfAny(variables);
+
+ if (EnableSorting) {
+ std::sort(variables.begin(), variables.end(),
+ [](dap::Variable const& a, dap::Variable const& b) {
+ return a.name < b.name;
+ });
+ }
+ return variables;
+}
+
+void cmDebuggerVariables::EnumerateSubVariablesIfAny(
+ dap::array<dap::Variable>& toBeReturned) const
+{
+ dap::array<dap::Variable> ret;
+ for (auto const& variables : SubVariables) {
+ toBeReturned.emplace_back(
+ dap::Variable{ {},
+ {},
+ {},
+ variables->GetName(),
+ {},
+ PrivatePropertyHint,
+ SupportsVariableType ? "collection" : nullptr,
+ variables->GetValue(),
+ variables->GetId() });
+ }
+}
+
+void cmDebuggerVariables::ClearSubVariables()
+{
+ SubVariables.clear();
+}
+
+cmDebuggerVariables::~cmDebuggerVariables()
+{
+ ClearSubVariables();
+ VariablesManager->UnregisterHandler(Id);
+}
+
+} // namespace cmDebugger
diff --git a/Source/cmDebuggerVariables.h b/Source/cmDebuggerVariables.h
new file mode 100644
index 0000000..eaaf2a8
--- /dev/null
+++ b/Source/cmDebuggerVariables.h
@@ -0,0 +1,124 @@
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
+#pragma once
+
+#include "cmConfigure.h" // IWYU pragma: keep
+
+#include <atomic>
+#include <cstdint>
+#include <functional>
+#include <memory>
+#include <string>
+#include <utility>
+#include <vector>
+
+#include <cm3p/cppdap/types.h> // IWYU pragma: keep
+
+namespace cmDebugger {
+class cmDebuggerVariablesManager;
+}
+
+namespace dap {
+struct Variable;
+}
+
+namespace cmDebugger {
+
+struct cmDebuggerVariableEntry
+{
+ cmDebuggerVariableEntry()
+ : cmDebuggerVariableEntry("", "", "")
+ {
+ }
+ cmDebuggerVariableEntry(std::string name, std::string value,
+ std::string type)
+ : Name(std::move(name))
+ , Value(std::move(value))
+ , Type(std::move(type))
+ {
+ }
+ cmDebuggerVariableEntry(std::string name, std::string value)
+ : Name(std::move(name))
+ , Value(std::move(value))
+ , Type("string")
+ {
+ }
+ cmDebuggerVariableEntry(std::string name, const char* value)
+ : Name(std::move(name))
+ , Value(value == nullptr ? "" : value)
+ , Type("string")
+ {
+ }
+ cmDebuggerVariableEntry(std::string name, bool value)
+ : Name(std::move(name))
+ , Value(value ? "TRUE" : "FALSE")
+ , Type("bool")
+ {
+ }
+ cmDebuggerVariableEntry(std::string name, int64_t value)
+ : Name(std::move(name))
+ , Value(std::to_string(value))
+ , Type("int")
+ {
+ }
+ cmDebuggerVariableEntry(std::string name, int value)
+ : Name(std::move(name))
+ , Value(std::to_string(value))
+ , Type("int")
+ {
+ }
+ std::string const Name;
+ std::string const Value;
+ std::string const Type;
+};
+
+class cmDebuggerVariables
+{
+ static std::atomic<int64_t> NextId;
+ int64_t Id;
+ std::string Name;
+ std::string Value;
+
+ std::function<std::vector<cmDebuggerVariableEntry>()> GetKeyValuesFunction;
+ std::vector<std::shared_ptr<cmDebuggerVariables>> SubVariables;
+ bool IgnoreEmptyStringEntries = false;
+ bool EnableSorting = true;
+
+ virtual dap::array<dap::Variable> HandleVariablesRequest();
+ friend class cmDebuggerVariablesManager;
+
+protected:
+ const bool SupportsVariableType;
+ std::shared_ptr<cmDebuggerVariablesManager> VariablesManager;
+ void EnumerateSubVariablesIfAny(
+ dap::array<dap::Variable>& toBeReturned) const;
+ void ClearSubVariables();
+
+public:
+ cmDebuggerVariables(
+ std::shared_ptr<cmDebuggerVariablesManager> variablesManager,
+ std::string name, bool supportsVariableType);
+ cmDebuggerVariables(
+ std::shared_ptr<cmDebuggerVariablesManager> variablesManager,
+ std::string name, bool supportsVariableType,
+ std::function<std::vector<cmDebuggerVariableEntry>()> getKeyValuesFunc);
+ inline int64_t GetId() const noexcept { return this->Id; }
+ inline std::string GetName() const noexcept { return this->Name; }
+ inline std::string GetValue() const noexcept { return this->Value; }
+ inline void SetValue(std::string const& value) noexcept
+ {
+ this->Value = value;
+ }
+ void AddSubVariables(std::shared_ptr<cmDebuggerVariables> const& variables);
+ inline void SetIgnoreEmptyStringEntries(bool value) noexcept
+ {
+ this->IgnoreEmptyStringEntries = value;
+ }
+ inline void SetEnableSorting(bool value) noexcept
+ {
+ this->EnableSorting = value;
+ }
+ virtual ~cmDebuggerVariables();
+};
+
+} // namespace cmDebugger
diff --git a/Source/cmDebuggerVariablesHelper.cxx b/Source/cmDebuggerVariablesHelper.cxx
new file mode 100644
index 0000000..42ce5e7
--- /dev/null
+++ b/Source/cmDebuggerVariablesHelper.cxx
@@ -0,0 +1,644 @@
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
+
+#include "cmDebuggerVariablesHelper.h"
+
+#include <algorithm>
+#include <cstddef>
+#include <functional>
+#include <iomanip>
+#include <map>
+#include <sstream>
+
+#include "cm_codecvt.hxx"
+
+#include "cmDebuggerStackFrame.h"
+#include "cmDebuggerVariables.h"
+#include "cmFileSet.h"
+#include "cmGlobalGenerator.h"
+#include "cmList.h"
+#include "cmListFileCache.h"
+#include "cmMakefile.h"
+#include "cmPropertyMap.h"
+#include "cmState.h"
+#include "cmStateSnapshot.h"
+#include "cmTarget.h"
+#include "cmTest.h"
+#include "cmValue.h"
+#include "cmake.h"
+
+namespace cmDebugger {
+
+std::shared_ptr<cmDebuggerVariables> cmDebuggerVariablesHelper::Create(
+ std::shared_ptr<cmDebuggerVariablesManager> const& variablesManager,
+ std::string const& name, bool supportsVariableType,
+ cmPolicies::PolicyMap const& policyMap)
+{
+ static std::map<cmPolicies::PolicyStatus, std::string> policyStatusString = {
+ { cmPolicies::PolicyStatus::OLD, "OLD" },
+ { cmPolicies::PolicyStatus::WARN, "WARN" },
+ { cmPolicies::PolicyStatus::NEW, "NEW" },
+ { cmPolicies::PolicyStatus::REQUIRED_IF_USED, "REQUIRED_IF_USED" },
+ { cmPolicies::PolicyStatus::REQUIRED_ALWAYS, "REQUIRED_ALWAYS" }
+ };
+
+ return std::make_shared<cmDebuggerVariables>(
+ variablesManager, name, supportsVariableType, [=]() {
+ std::vector<cmDebuggerVariableEntry> ret;
+ ret.reserve(cmPolicies::CMPCOUNT);
+ for (int i = 0; i < cmPolicies::CMPCOUNT; ++i) {
+ if (policyMap.IsDefined(static_cast<cmPolicies::PolicyID>(i))) {
+ auto status = policyMap.Get(static_cast<cmPolicies::PolicyID>(i));
+ std::ostringstream ss;
+ ss << "CMP" << std::setfill('0') << std::setw(4) << i;
+ ret.emplace_back(ss.str(), policyStatusString[status]);
+ }
+ }
+ return ret;
+ });
+}
+
+std::shared_ptr<cmDebuggerVariables> cmDebuggerVariablesHelper::CreateIfAny(
+ std::shared_ptr<cmDebuggerVariablesManager> const& variablesManager,
+ std::string const& name, bool supportsVariableType,
+ std::vector<std::pair<std::string, std::string>> const& list)
+{
+ if (list.empty()) {
+ return {};
+ }
+
+ auto listVariables = std::make_shared<cmDebuggerVariables>(
+ variablesManager, name, supportsVariableType, [=]() {
+ std::vector<cmDebuggerVariableEntry> ret;
+ ret.reserve(list.size());
+ for (auto const& kv : list) {
+ ret.emplace_back(kv.first, kv.second);
+ }
+ return ret;
+ });
+
+ listVariables->SetValue(std::to_string(list.size()));
+ return listVariables;
+}
+
+std::shared_ptr<cmDebuggerVariables> cmDebuggerVariablesHelper::CreateIfAny(
+ std::shared_ptr<cmDebuggerVariablesManager> const& variablesManager,
+ std::string const& name, bool supportsVariableType,
+ cmBTStringRange const& entries)
+{
+ if (entries.empty()) {
+ return {};
+ }
+
+ auto sourceEntries = std::make_shared<cmDebuggerVariables>(
+ variablesManager, name, supportsVariableType);
+
+ for (auto const& entry : entries) {
+ auto arrayVariables = std::make_shared<cmDebuggerVariables>(
+ variablesManager, entry.Value, supportsVariableType, [=]() {
+ cmList items{ entry.Value };
+ std::vector<cmDebuggerVariableEntry> ret;
+ ret.reserve(items.size());
+ int i = 0;
+ for (std::string const& item : items) {
+ ret.emplace_back("[" + std::to_string(i++) + "]", item);
+ }
+ return ret;
+ });
+ arrayVariables->SetEnableSorting(false);
+ sourceEntries->AddSubVariables(arrayVariables);
+ }
+
+ sourceEntries->SetValue(std::to_string(entries.size()));
+ return sourceEntries;
+}
+
+std::shared_ptr<cmDebuggerVariables> cmDebuggerVariablesHelper::CreateIfAny(
+ std::shared_ptr<cmDebuggerVariablesManager> const& variablesManager,
+ std::string const& name, bool supportsVariableType,
+ std::set<std::string> const& values)
+{
+ if (values.empty()) {
+ return {};
+ }
+
+ auto arrayVariables = std::make_shared<cmDebuggerVariables>(
+ variablesManager, name, supportsVariableType, [=]() {
+ std::vector<cmDebuggerVariableEntry> ret;
+ ret.reserve(values.size());
+ int i = 0;
+ for (std::string const& value : values) {
+ ret.emplace_back("[" + std::to_string(i++) + "]", value);
+ }
+ return ret;
+ });
+ arrayVariables->SetValue(std::to_string(values.size()));
+ arrayVariables->SetEnableSorting(false);
+ return arrayVariables;
+}
+
+std::shared_ptr<cmDebuggerVariables> cmDebuggerVariablesHelper::CreateIfAny(
+ std::shared_ptr<cmDebuggerVariablesManager> const& variablesManager,
+ std::string const& name, bool supportsVariableType,
+ std::vector<std::string> const& values)
+{
+ if (values.empty()) {
+ return {};
+ }
+
+ auto arrayVariables = std::make_shared<cmDebuggerVariables>(
+ variablesManager, name, supportsVariableType, [=]() {
+ std::vector<cmDebuggerVariableEntry> ret;
+ ret.reserve(values.size());
+ int i = 0;
+ for (std::string const& value : values) {
+ ret.emplace_back("[" + std::to_string(i++) + "]", value);
+ }
+ return ret;
+ });
+
+ arrayVariables->SetValue(std::to_string(values.size()));
+ arrayVariables->SetEnableSorting(false);
+ return arrayVariables;
+}
+
+std::shared_ptr<cmDebuggerVariables> cmDebuggerVariablesHelper::CreateIfAny(
+ std::shared_ptr<cmDebuggerVariablesManager> const& variablesManager,
+ std::string const& name, bool supportsVariableType,
+ std::vector<BT<std::string>> const& list)
+{
+ if (list.empty()) {
+ return {};
+ }
+
+ auto variables = std::make_shared<cmDebuggerVariables>(
+ variablesManager, name, supportsVariableType, [=]() {
+ std::vector<cmDebuggerVariableEntry> ret;
+ ret.reserve(list.size());
+ int i = 0;
+ for (auto const& item : list) {
+ ret.emplace_back("[" + std::to_string(i++) + "]", item.Value);
+ }
+
+ return ret;
+ });
+
+ variables->SetValue(std::to_string(list.size()));
+ variables->SetEnableSorting(false);
+ return variables;
+}
+
+std::shared_ptr<cmDebuggerVariables> cmDebuggerVariablesHelper::CreateIfAny(
+ std::shared_ptr<cmDebuggerVariablesManager> const& variablesManager,
+ std::string const& name, bool supportsVariableType, cmFileSet* fileSet)
+{
+ if (fileSet == nullptr) {
+ return {};
+ }
+
+ static auto visibilityString = [](cmFileSetVisibility visibility) {
+ switch (visibility) {
+ case cmFileSetVisibility::Private:
+ return "Private";
+ case cmFileSetVisibility::Public:
+ return "Public";
+ case cmFileSetVisibility::Interface:
+ return "Interface";
+ default:
+ return "Unknown";
+ }
+ };
+
+ auto variables = std::make_shared<cmDebuggerVariables>(
+ variablesManager, name, supportsVariableType, [=]() {
+ std::vector<cmDebuggerVariableEntry> ret{
+ { "Name", fileSet->GetName() },
+ { "Type", fileSet->GetType() },
+ { "Visibility", visibilityString(fileSet->GetVisibility()) },
+ };
+
+ return ret;
+ });
+
+ variables->AddSubVariables(CreateIfAny(variablesManager, "Directories",
+ supportsVariableType,
+ fileSet->GetDirectoryEntries()));
+ variables->AddSubVariables(CreateIfAny(variablesManager, "Files",
+ supportsVariableType,
+ fileSet->GetFileEntries()));
+ return variables;
+}
+
+std::shared_ptr<cmDebuggerVariables> cmDebuggerVariablesHelper::CreateIfAny(
+ std::shared_ptr<cmDebuggerVariablesManager> const& variablesManager,
+ std::string const& name, bool supportsVariableType,
+ std::vector<cmFileSet*> const& fileSets)
+{
+ if (fileSets.empty()) {
+ return {};
+ }
+
+ auto fileSetsVariables = std::make_shared<cmDebuggerVariables>(
+ variablesManager, name, supportsVariableType);
+
+ for (auto const& fileSet : fileSets) {
+ fileSetsVariables->AddSubVariables(CreateIfAny(
+ variablesManager, fileSet->GetName(), supportsVariableType, fileSet));
+ }
+
+ return fileSetsVariables;
+}
+
+std::shared_ptr<cmDebuggerVariables> cmDebuggerVariablesHelper::CreateIfAny(
+ std::shared_ptr<cmDebuggerVariablesManager> const& variablesManager,
+ std::string const& name, bool supportsVariableType,
+ std::vector<cmTarget*> const& targets)
+{
+ if (targets.empty()) {
+ return {};
+ }
+
+ auto targetsVariables = std::make_shared<cmDebuggerVariables>(
+ variablesManager, name, supportsVariableType);
+
+ for (auto const& target : targets) {
+ auto targetVariables = std::make_shared<cmDebuggerVariables>(
+ variablesManager, target->GetName(), supportsVariableType, [=]() {
+ std::vector<cmDebuggerVariableEntry> ret = {
+ { "InstallPath", target->GetInstallPath() },
+ { "IsAIX", target->IsAIX() },
+ { "IsAndroidGuiExecutable", target->IsAndroidGuiExecutable() },
+ { "IsAppBundleOnApple", target->IsAppBundleOnApple() },
+ { "IsDLLPlatform", target->IsDLLPlatform() },
+ { "IsExecutableWithExports", target->IsExecutableWithExports() },
+ { "IsFrameworkOnApple", target->IsFrameworkOnApple() },
+ { "IsImported", target->IsImported() },
+ { "IsImportedGloballyVisible", target->IsImportedGloballyVisible() },
+ { "IsPerConfig", target->IsPerConfig() },
+ { "Name", target->GetName() },
+ { "RuntimeInstallPath", target->GetRuntimeInstallPath() },
+ { "Type", cmState::GetTargetTypeName(target->GetType()) },
+ };
+
+ return ret;
+ });
+ targetVariables->SetValue(cmState::GetTargetTypeName(target->GetType()));
+
+ targetVariables->AddSubVariables(Create(variablesManager, "PolicyMap",
+ supportsVariableType,
+ target->GetPolicyMap()));
+ targetVariables->AddSubVariables(
+ CreateIfAny(variablesManager, "Properties", supportsVariableType,
+ target->GetProperties().GetList()));
+
+ targetVariables->AddSubVariables(
+ CreateIfAny(variablesManager, "IncludeDirectories", supportsVariableType,
+ target->GetIncludeDirectoriesEntries()));
+ targetVariables->AddSubVariables(CreateIfAny(variablesManager, "Sources",
+ supportsVariableType,
+ target->GetSourceEntries()));
+ targetVariables->AddSubVariables(
+ CreateIfAny(variablesManager, "CompileDefinitions", supportsVariableType,
+ target->GetCompileDefinitionsEntries()));
+ targetVariables->AddSubVariables(
+ CreateIfAny(variablesManager, "CompileFeatures", supportsVariableType,
+ target->GetCompileFeaturesEntries()));
+ targetVariables->AddSubVariables(
+ CreateIfAny(variablesManager, "CompileOptions", supportsVariableType,
+ target->GetCompileOptionsEntries()));
+ targetVariables->AddSubVariables(CreateIfAny(
+ variablesManager, "CxxModuleHeaderSets", supportsVariableType,
+ target->GetCxxModuleHeaderSetsEntries()));
+ targetVariables->AddSubVariables(
+ CreateIfAny(variablesManager, "CxxModuleSets", supportsVariableType,
+ target->GetCxxModuleSetsEntries()));
+ targetVariables->AddSubVariables(
+ CreateIfAny(variablesManager, "HeaderSets", supportsVariableType,
+ target->GetHeaderSetsEntries()));
+ targetVariables->AddSubVariables(CreateIfAny(
+ variablesManager, "InterfaceCxxModuleHeaderSets", supportsVariableType,
+ target->GetInterfaceCxxModuleHeaderSetsEntries()));
+ targetVariables->AddSubVariables(CreateIfAny(
+ variablesManager, "InterfaceHeaderSets", supportsVariableType,
+ target->GetInterfaceHeaderSetsEntries()));
+ targetVariables->AddSubVariables(
+ CreateIfAny(variablesManager, "LinkDirectories", supportsVariableType,
+ target->GetLinkDirectoriesEntries()));
+ targetVariables->AddSubVariables(CreateIfAny(
+ variablesManager, "LinkImplementations", supportsVariableType,
+ target->GetLinkImplementationEntries()));
+ targetVariables->AddSubVariables(CreateIfAny(
+ variablesManager, "LinkInterfaceDirects", supportsVariableType,
+ target->GetLinkInterfaceDirectEntries()));
+ targetVariables->AddSubVariables(CreateIfAny(
+ variablesManager, "LinkInterfaceDirectExcludes", supportsVariableType,
+ target->GetLinkInterfaceDirectExcludeEntries()));
+ targetVariables->AddSubVariables(
+ CreateIfAny(variablesManager, "LinkInterfaces", supportsVariableType,
+ target->GetLinkInterfaceEntries()));
+ targetVariables->AddSubVariables(
+ CreateIfAny(variablesManager, "LinkOptions", supportsVariableType,
+ target->GetLinkOptionsEntries()));
+ targetVariables->AddSubVariables(CreateIfAny(
+ variablesManager, "SystemIncludeDirectories", supportsVariableType,
+ target->GetSystemIncludeDirectories()));
+ targetVariables->AddSubVariables(CreateIfAny(variablesManager, "Makefile",
+ supportsVariableType,
+ target->GetMakefile()));
+ targetVariables->AddSubVariables(
+ CreateIfAny(variablesManager, "GlobalGenerator", supportsVariableType,
+ target->GetGlobalGenerator()));
+
+ std::vector<cmFileSet*> allFileSets;
+ auto allFileSetNames = target->GetAllFileSetNames();
+ allFileSets.reserve(allFileSetNames.size());
+ for (auto const& fileSetName : allFileSetNames) {
+ allFileSets.emplace_back(target->GetFileSet(fileSetName));
+ }
+ targetVariables->AddSubVariables(CreateIfAny(
+ variablesManager, "AllFileSets", supportsVariableType, allFileSets));
+
+ std::vector<cmFileSet*> allInterfaceFileSets;
+ auto allInterfaceFileSetNames = target->GetAllInterfaceFileSets();
+ allInterfaceFileSets.reserve(allInterfaceFileSetNames.size());
+ for (auto const& interfaceFileSetName : allInterfaceFileSetNames) {
+ allInterfaceFileSets.emplace_back(
+ target->GetFileSet(interfaceFileSetName));
+ }
+ targetVariables->AddSubVariables(
+ CreateIfAny(variablesManager, "AllInterfaceFileSets",
+ supportsVariableType, allInterfaceFileSets));
+
+ targetVariables->SetIgnoreEmptyStringEntries(true);
+ targetsVariables->AddSubVariables(targetVariables);
+ }
+
+ targetsVariables->SetValue(std::to_string(targets.size()));
+ return targetsVariables;
+}
+
+std::shared_ptr<cmDebuggerVariables> cmDebuggerVariablesHelper::Create(
+ std::shared_ptr<cmDebuggerVariablesManager> const& variablesManager,
+ std::string const& name, bool supportsVariableType,
+ std::shared_ptr<cmDebuggerStackFrame> const& frame)
+{
+ auto variables = std::make_shared<cmDebuggerVariables>(
+ variablesManager, name, supportsVariableType, [=]() {
+ return std::vector<cmDebuggerVariableEntry>{ { "CurrentLine",
+ frame->GetLine() } };
+ });
+
+ auto closureKeys = frame->GetMakefile()->GetStateSnapshot().ClosureKeys();
+ auto locals = std::make_shared<cmDebuggerVariables>(
+ variablesManager, "Locals", supportsVariableType, [=]() {
+ std::vector<cmDebuggerVariableEntry> ret;
+ ret.reserve(closureKeys.size());
+ for (auto const& key : closureKeys) {
+ ret.emplace_back(
+ key, frame->GetMakefile()->GetStateSnapshot().GetDefinition(key));
+ }
+ return ret;
+ });
+ locals->SetValue(std::to_string(closureKeys.size()));
+ variables->AddSubVariables(locals);
+
+ std::function<bool(std::string const&)> isDirectory =
+ [](std::string const& key) {
+ size_t pos1 = key.rfind("_DIR");
+ size_t pos2 = key.rfind("_DIRECTORY");
+ return !((pos1 == std::string::npos || pos1 != key.size() - 4) &&
+ (pos2 == std::string::npos || pos2 != key.size() - 10));
+ };
+ auto directorySize =
+ std::count_if(closureKeys.begin(), closureKeys.end(), isDirectory);
+ auto directories = std::make_shared<cmDebuggerVariables>(
+ variablesManager, "Directories", supportsVariableType, [=]() {
+ std::vector<cmDebuggerVariableEntry> ret;
+ ret.reserve(directorySize);
+ for (auto const& key : closureKeys) {
+ if (isDirectory(key)) {
+ ret.emplace_back(
+ key, frame->GetMakefile()->GetStateSnapshot().GetDefinition(key));
+ }
+ }
+ return ret;
+ });
+ directories->SetValue(std::to_string(directorySize));
+ variables->AddSubVariables(directories);
+
+ auto cacheVariables = std::make_shared<cmDebuggerVariables>(
+ variablesManager, "CacheVariables", supportsVariableType);
+ auto* state = frame->GetMakefile()->GetCMakeInstance()->GetState();
+ auto keys = state->GetCacheEntryKeys();
+ for (auto const& key : keys) {
+ auto entry = std::make_shared<cmDebuggerVariables>(
+ variablesManager,
+ key + ":" +
+ cmState::CacheEntryTypeToString(state->GetCacheEntryType(key)),
+ supportsVariableType, [=]() {
+ std::vector<cmDebuggerVariableEntry> ret;
+ auto properties = state->GetCacheEntryPropertyList(key);
+ ret.reserve(properties.size() + 2);
+ for (auto const& propertyName : properties) {
+ ret.emplace_back(propertyName,
+ state->GetCacheEntryProperty(key, propertyName));
+ }
+
+ ret.emplace_back(
+ "TYPE",
+ cmState::CacheEntryTypeToString(state->GetCacheEntryType(key)));
+ ret.emplace_back("VALUE", state->GetCacheEntryValue(key));
+ return ret;
+ });
+
+ entry->SetValue(state->GetCacheEntryValue(key));
+ cacheVariables->AddSubVariables(entry);
+ }
+
+ cacheVariables->SetValue(std::to_string(keys.size()));
+ variables->AddSubVariables(cacheVariables);
+
+ auto targetVariables =
+ CreateIfAny(variablesManager, "Targets", supportsVariableType,
+ frame->GetMakefile()->GetOrderedTargets());
+
+ variables->AddSubVariables(targetVariables);
+ std::vector<cmTest*> tests;
+ frame->GetMakefile()->GetTests(
+ frame->GetMakefile()->GetDefaultConfiguration(), tests);
+ variables->AddSubVariables(
+ CreateIfAny(variablesManager, "Tests", supportsVariableType, tests));
+
+ return variables;
+}
+
+std::shared_ptr<cmDebuggerVariables> cmDebuggerVariablesHelper::CreateIfAny(
+ std::shared_ptr<cmDebuggerVariablesManager> const& variablesManager,
+ std::string const& name, bool supportsVariableType, cmTest* test)
+{
+ if (test == nullptr) {
+ return {};
+ }
+
+ auto variables = std::make_shared<cmDebuggerVariables>(
+ variablesManager, name, supportsVariableType, [=]() {
+ std::vector<cmDebuggerVariableEntry> ret{
+ { "CommandExpandLists", test->GetCommandExpandLists() },
+ { "Name", test->GetName() },
+ { "OldStyle", test->GetOldStyle() },
+ };
+
+ return ret;
+ });
+
+ variables->AddSubVariables(CreateIfAny(
+ variablesManager, "Command", supportsVariableType, test->GetCommand()));
+
+ variables->AddSubVariables(CreateIfAny(variablesManager, "Properties",
+ supportsVariableType,
+ test->GetProperties().GetList()));
+ return variables;
+}
+
+std::shared_ptr<cmDebuggerVariables> cmDebuggerVariablesHelper::CreateIfAny(
+ std::shared_ptr<cmDebuggerVariablesManager> const& variablesManager,
+ std::string const& name, bool supportsVariableType,
+ std::vector<cmTest*> const& tests)
+{
+ if (tests.empty()) {
+ return {};
+ }
+
+ auto variables = std::make_shared<cmDebuggerVariables>(
+ variablesManager, name, supportsVariableType);
+
+ for (auto const& test : tests) {
+ variables->AddSubVariables(CreateIfAny(variablesManager, test->GetName(),
+ supportsVariableType, test));
+ }
+ variables->SetValue(std::to_string(tests.size()));
+ return variables;
+}
+
+std::shared_ptr<cmDebuggerVariables> cmDebuggerVariablesHelper::CreateIfAny(
+ std::shared_ptr<cmDebuggerVariablesManager> const& variablesManager,
+ std::string const& name, bool supportsVariableType, cmMakefile* mf)
+{
+ if (mf == nullptr) {
+ return {};
+ }
+
+ auto AppleSDKTypeString = [&](cmMakefile::AppleSDK sdk) {
+ switch (sdk) {
+ case cmMakefile::AppleSDK::MacOS:
+ return "MacOS";
+ case cmMakefile::AppleSDK::IPhoneOS:
+ return "IPhoneOS";
+ case cmMakefile::AppleSDK::IPhoneSimulator:
+ return "IPhoneSimulator";
+ case cmMakefile::AppleSDK::AppleTVOS:
+ return "AppleTVOS";
+ case cmMakefile::AppleSDK::AppleTVSimulator:
+ return "AppleTVSimulator";
+ default:
+ return "Unknown";
+ }
+ };
+
+ auto variables = std::make_shared<cmDebuggerVariables>(
+ variablesManager, name, supportsVariableType, [=]() {
+ std::vector<cmDebuggerVariableEntry> ret = {
+ { "DefineFlags", mf->GetDefineFlags() },
+ { "DirectoryId", mf->GetDirectoryId().String },
+ { "IsRootMakefile", mf->IsRootMakefile() },
+ { "HomeDirectory", mf->GetHomeDirectory() },
+ { "HomeOutputDirectory", mf->GetHomeOutputDirectory() },
+ { "CurrentSourceDirectory", mf->GetCurrentSourceDirectory() },
+ { "CurrentBinaryDirectory", mf->GetCurrentBinaryDirectory() },
+ { "PlatformIs32Bit", mf->PlatformIs32Bit() },
+ { "PlatformIs64Bit", mf->PlatformIs64Bit() },
+ { "PlatformIsx32", mf->PlatformIsx32() },
+ { "AppleSDKType", AppleSDKTypeString(mf->GetAppleSDKType()) },
+ { "PlatformIsAppleEmbedded", mf->PlatformIsAppleEmbedded() }
+ };
+
+ return ret;
+ });
+
+ variables->AddSubVariables(CreateIfAny(
+ variablesManager, "ListFiles", supportsVariableType, mf->GetListFiles()));
+ variables->AddSubVariables(CreateIfAny(variablesManager, "OutputFiles",
+ supportsVariableType,
+ mf->GetOutputFiles()));
+
+ variables->SetIgnoreEmptyStringEntries(true);
+ variables->SetValue(mf->GetDirectoryId().String);
+ return variables;
+}
+
+std::shared_ptr<cmDebuggerVariables> cmDebuggerVariablesHelper::CreateIfAny(
+ std::shared_ptr<cmDebuggerVariablesManager> const& variablesManager,
+ std::string const& name, bool supportsVariableType, cmGlobalGenerator* gen)
+{
+ if (gen == nullptr) {
+ return {};
+ }
+
+ auto makeFileEncodingString = [](codecvt::Encoding encoding) {
+ switch (encoding) {
+ case codecvt::Encoding::None:
+ return "None";
+ case codecvt::Encoding::UTF8:
+ return "UTF8";
+ case codecvt::Encoding::UTF8_WITH_BOM:
+ return "UTF8_WITH_BOM";
+ case codecvt::Encoding::ANSI:
+ return "ANSI";
+ case codecvt::Encoding::ConsoleOutput:
+ return "ConsoleOutput";
+ default:
+ return "Unknown";
+ }
+ };
+
+ auto variables = std::make_shared<cmDebuggerVariables>(
+ variablesManager, name, supportsVariableType, [=]() {
+ std::vector<cmDebuggerVariableEntry> ret = {
+ { "AllTargetName", gen->GetAllTargetName() },
+ { "CleanTargetName", gen->GetCleanTargetName() },
+ { "EditCacheCommand", gen->GetEditCacheCommand() },
+ { "EditCacheTargetName", gen->GetEditCacheTargetName() },
+ { "ExtraGeneratorName", gen->GetExtraGeneratorName() },
+ { "ForceUnixPaths", gen->GetForceUnixPaths() },
+ { "InstallLocalTargetName", gen->GetInstallLocalTargetName() },
+ { "InstallStripTargetName", gen->GetInstallStripTargetName() },
+ { "InstallTargetName", gen->GetInstallTargetName() },
+ { "IsMultiConfig", gen->IsMultiConfig() },
+ { "Name", gen->GetName() },
+ { "MakefileEncoding",
+ makeFileEncodingString(gen->GetMakefileEncoding()) },
+ { "PackageSourceTargetName", gen->GetPackageSourceTargetName() },
+ { "PackageTargetName", gen->GetPackageTargetName() },
+ { "PreinstallTargetName", gen->GetPreinstallTargetName() },
+ { "NeedSymbolicMark", gen->GetNeedSymbolicMark() },
+ { "RebuildCacheTargetName", gen->GetRebuildCacheTargetName() },
+ { "TestTargetName", gen->GetTestTargetName() },
+ { "UseLinkScript", gen->GetUseLinkScript() },
+ };
+
+ return ret;
+ });
+
+ if (gen->GetInstallComponents() != nullptr) {
+ variables->AddSubVariables(
+ CreateIfAny(variablesManager, "InstallComponents", supportsVariableType,
+ *gen->GetInstallComponents()));
+ }
+
+ variables->SetIgnoreEmptyStringEntries(true);
+ variables->SetValue(gen->GetName());
+
+ return variables;
+}
+
+} // namespace cmDebugger
diff --git a/Source/cmDebuggerVariablesHelper.h b/Source/cmDebuggerVariablesHelper.h
new file mode 100644
index 0000000..9b11eaf
--- /dev/null
+++ b/Source/cmDebuggerVariablesHelper.h
@@ -0,0 +1,106 @@
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
+#pragma once
+
+#include "cmConfigure.h" // IWYU pragma: keep
+
+#include <memory>
+#include <set>
+#include <string>
+#include <utility>
+#include <vector>
+
+#include "cmAlgorithms.h"
+#include "cmPolicies.h"
+
+class cmFileSet;
+class cmGlobalGenerator;
+class cmMakefile;
+class cmTarget;
+class cmTest;
+
+namespace cmDebugger {
+class cmDebuggerStackFrame;
+class cmDebuggerVariables;
+class cmDebuggerVariablesManager;
+}
+
+template <typename T>
+class BT;
+
+namespace cmDebugger {
+
+class cmDebuggerVariablesHelper
+{
+ cmDebuggerVariablesHelper() = default;
+
+public:
+ static std::shared_ptr<cmDebuggerVariables> Create(
+ std::shared_ptr<cmDebuggerVariablesManager> const& variablesManager,
+ std::string const& name, bool supportsVariableType,
+ cmPolicies::PolicyMap const& policyMap);
+
+ static std::shared_ptr<cmDebuggerVariables> CreateIfAny(
+ std::shared_ptr<cmDebuggerVariablesManager> const& variablesManager,
+ std::string const& name, bool supportsVariableType,
+ std::vector<std::pair<std::string, std::string>> const& list);
+
+ static std::shared_ptr<cmDebuggerVariables> CreateIfAny(
+ std::shared_ptr<cmDebuggerVariablesManager> const& variablesManager,
+ std::string const& name, bool supportsVariableType,
+ cmBTStringRange const& entries);
+
+ static std::shared_ptr<cmDebuggerVariables> CreateIfAny(
+ std::shared_ptr<cmDebuggerVariablesManager> const& variablesManager,
+ std::string const& name, bool supportsVariableType,
+ std::set<std::string> const& values);
+
+ static std::shared_ptr<cmDebuggerVariables> CreateIfAny(
+ std::shared_ptr<cmDebuggerVariablesManager> const& variablesManager,
+ std::string const& name, bool supportsVariableType,
+ std::vector<std::string> const& values);
+
+ static std::shared_ptr<cmDebuggerVariables> CreateIfAny(
+ std::shared_ptr<cmDebuggerVariablesManager> const& variablesManager,
+ std::string const& name, bool supportsVariableType,
+ std::vector<BT<std::string>> const& list);
+
+ static std::shared_ptr<cmDebuggerVariables> CreateIfAny(
+ std::shared_ptr<cmDebuggerVariablesManager> const& variablesManager,
+ std::string const& name, bool supportsVariableType, cmFileSet* fileSet);
+
+ static std::shared_ptr<cmDebuggerVariables> CreateIfAny(
+ std::shared_ptr<cmDebuggerVariablesManager> const& variablesManager,
+ std::string const& name, bool supportsVariableType,
+ std::vector<cmFileSet*> const& fileSets);
+
+ static std::shared_ptr<cmDebuggerVariables> CreateIfAny(
+ std::shared_ptr<cmDebuggerVariablesManager> const& variablesManager,
+ std::string const& name, bool supportsVariableType, cmTest* test);
+
+ static std::shared_ptr<cmDebuggerVariables> CreateIfAny(
+ std::shared_ptr<cmDebuggerVariablesManager> const& variablesManager,
+ std::string const& name, bool supportsVariableType,
+ std::vector<cmTest*> const& tests);
+
+ static std::shared_ptr<cmDebuggerVariables> CreateIfAny(
+ std::shared_ptr<cmDebuggerVariablesManager> const& variablesManager,
+ std::string const& name, bool supportsVariableType,
+ std::vector<cmTarget*> const& targets);
+
+ static std::shared_ptr<cmDebuggerVariables> Create(
+ std::shared_ptr<cmDebuggerVariablesManager> const& variablesManager,
+ std::string const& name, bool supportsVariableType,
+ std::shared_ptr<cmDebuggerStackFrame> const& frame);
+
+ static std::shared_ptr<cmDebuggerVariables> CreateIfAny(
+ std::shared_ptr<cmDebuggerVariablesManager> const& variablesManager,
+ std::string const& name, bool supportsVariableType, cmMakefile* mf);
+
+ static std::shared_ptr<cmDebuggerVariables> CreateIfAny(
+ std::shared_ptr<cmDebuggerVariablesManager> const& variablesManager,
+ std::string const& name, bool supportsVariableType,
+ cmGlobalGenerator* gen);
+};
+
+} // namespace cmDebugger
diff --git a/Source/cmDebuggerVariablesManager.cxx b/Source/cmDebuggerVariablesManager.cxx
new file mode 100644
index 0000000..9b9b476
--- /dev/null
+++ b/Source/cmDebuggerVariablesManager.cxx
@@ -0,0 +1,38 @@
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
+
+#include "cmDebuggerVariablesManager.h"
+
+#include <utility>
+
+#include <cm3p/cppdap/protocol.h>
+#include <cm3p/cppdap/types.h>
+
+namespace cmDebugger {
+
+void cmDebuggerVariablesManager::RegisterHandler(
+ int64_t id,
+ std::function<dap::array<dap::Variable>(dap::VariablesRequest const&)>
+ handler)
+{
+ VariablesHandlers[id] = std::move(handler);
+}
+
+void cmDebuggerVariablesManager::UnregisterHandler(int64_t id)
+{
+ VariablesHandlers.erase(id);
+}
+
+dap::array<dap::Variable> cmDebuggerVariablesManager::HandleVariablesRequest(
+ dap::VariablesRequest const& request)
+{
+ auto it = VariablesHandlers.find(request.variablesReference);
+
+ if (it != VariablesHandlers.end()) {
+ return it->second(request);
+ }
+
+ return dap::array<dap::Variable>();
+}
+
+} // namespace cmDebugger
diff --git a/Source/cmDebuggerVariablesManager.h b/Source/cmDebuggerVariablesManager.h
new file mode 100644
index 0000000..c219164
--- /dev/null
+++ b/Source/cmDebuggerVariablesManager.h
@@ -0,0 +1,40 @@
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
+#pragma once
+
+#include "cmConfigure.h" // IWYU pragma: keep
+
+#include <cstdint>
+#include <functional>
+#include <unordered_map>
+#include <vector>
+
+#include <cm3p/cppdap/types.h> // IWYU pragma: keep
+
+namespace dap {
+struct Variable;
+struct VariablesRequest;
+}
+
+namespace cmDebugger {
+
+class cmDebuggerVariablesManager
+{
+ std::unordered_map<
+ int64_t,
+ std::function<dap::array<dap::Variable>(dap::VariablesRequest const&)>>
+ VariablesHandlers;
+ void RegisterHandler(
+ int64_t id,
+ std::function<dap::array<dap::Variable>(dap::VariablesRequest const&)>
+ handler);
+ void UnregisterHandler(int64_t id);
+ friend class cmDebuggerVariables;
+
+public:
+ cmDebuggerVariablesManager() = default;
+ dap::array<dap::Variable> HandleVariablesRequest(
+ dap::VariablesRequest const& request);
+};
+
+} // namespace cmDebugger
diff --git a/Source/cmDependsFortran.cxx b/Source/cmDependsFortran.cxx
index aede3fe..d038db7 100644
--- a/Source/cmDependsFortran.cxx
+++ b/Source/cmDependsFortran.cxx
@@ -416,7 +416,7 @@ bool cmDependsFortran::WriteDependenciesReal(std::string const& obj,
// file is not updated. In such case the stamp file will be always
// older than its prerequisite and trigger cmake_copy_f90_mod
// on each new build. This is expected behavior for incremental
- // builds and can not be changed without preforming recursive make
+ // builds and can not be changed without performing recursive make
// calls that would considerably slow down the building process.
makeDepends << stampFileForMake << ": " << obj_m << '\n';
makeDepends << "\t$(CMAKE_COMMAND) -E cmake_copy_f90_mod " << modFile
diff --git a/Source/cmDependsJavaParserHelper.cxx b/Source/cmDependsJavaParserHelper.cxx
index 0c5d310..6e617f6 100644
--- a/Source/cmDependsJavaParserHelper.cxx
+++ b/Source/cmDependsJavaParserHelper.cxx
@@ -155,7 +155,7 @@ void cmDependsJavaParserHelper::CheckEmpty(
void cmDependsJavaParserHelper::PrepareElement(
cmDependsJavaParserHelper::ParserType* me)
{
- // Inititalize self
+ // Initialize self
me->str = nullptr;
}
diff --git a/Source/cmDyndepCollation.cxx b/Source/cmDyndepCollation.cxx
index f45d81b..80e1357 100644
--- a/Source/cmDyndepCollation.cxx
+++ b/Source/cmDyndepCollation.cxx
@@ -358,6 +358,10 @@ cmDyndepCollation::ParseExportInfo(Json::Value const& tdi)
fsi.Name = tdi_cxx_module_info["name"].asString();
fsi.RelativeDirectory =
tdi_cxx_module_info["relative-directory"].asString();
+ if (!fsi.RelativeDirectory.empty() &&
+ fsi.RelativeDirectory.back() != '/') {
+ fsi.RelativeDirectory = cmStrCat(fsi.RelativeDirectory, '/');
+ }
fsi.SourcePath = tdi_cxx_module_info["source"].asString();
fsi.Type = tdi_cxx_module_info["type"].asString();
fsi.Visibility = cmFileSetVisibilityFromName(
diff --git a/Source/cmExportBuildFileGenerator.cxx b/Source/cmExportBuildFileGenerator.cxx
index 437ae69..a3637d8 100644
--- a/Source/cmExportBuildFileGenerator.cxx
+++ b/Source/cmExportBuildFileGenerator.cxx
@@ -542,6 +542,12 @@ bool cmExportBuildFileGenerator::GenerateImportCxxModuleConfigTargetInclusion(
os.SetCopyIfDifferent(true);
for (auto const* tgt : this->ExportedTargets) {
+ // Only targets with C++ module sources will have a
+ // collator-generated install script.
+ if (!tgt->HaveCxx20ModuleSources()) {
+ continue;
+ }
+
os << "include(\"${CMAKE_CURRENT_LIST_DIR}/target-" << tgt->GetExportName()
<< '-' << config << ".cmake\")\n";
}
diff --git a/Source/cmExportInstallFileGenerator.cxx b/Source/cmExportInstallFileGenerator.cxx
index 51c91f3..df119ae 100644
--- a/Source/cmExportInstallFileGenerator.cxx
+++ b/Source/cmExportInstallFileGenerator.cxx
@@ -752,6 +752,12 @@ bool cmExportInstallFileGenerator::
auto& prop_files = this->ConfigCxxModuleTargetFiles[config];
for (auto const* tgt : this->ExportedTargets) {
+ // Only targets with C++ module sources will have a
+ // collator-generated install script.
+ if (!tgt->HaveCxx20ModuleSources()) {
+ continue;
+ }
+
auto prop_filename = cmStrCat("target-", tgt->GetExportName(), '-',
filename_config, ".cmake");
prop_files.emplace_back(cmStrCat(dest, prop_filename));
diff --git a/Source/cmExternalMakefileProjectGenerator.cxx b/Source/cmExternalMakefileProjectGenerator.cxx
index 5895d66..5fecb35 100644
--- a/Source/cmExternalMakefileProjectGenerator.cxx
+++ b/Source/cmExternalMakefileProjectGenerator.cxx
@@ -17,14 +17,13 @@ void cmExternalMakefileProjectGenerator::EnableLanguage(
std::string cmExternalMakefileProjectGenerator::CreateFullGeneratorName(
const std::string& globalGenerator, const std::string& extraGenerator)
{
- std::string fullName;
- if (!globalGenerator.empty()) {
- if (!extraGenerator.empty()) {
- fullName = cmStrCat(extraGenerator, " - ");
- }
- fullName += globalGenerator;
+ if (globalGenerator.empty()) {
+ return {};
}
- return fullName;
+ if (extraGenerator.empty()) {
+ return globalGenerator;
+ }
+ return cmStrCat(extraGenerator, " - ", globalGenerator);
}
bool cmExternalMakefileProjectGenerator::Open(
diff --git a/Source/cmFileAPI.cxx b/Source/cmFileAPI.cxx
index d1d3d25..8b98916 100644
--- a/Source/cmFileAPI.cxx
+++ b/Source/cmFileAPI.cxx
@@ -728,7 +728,7 @@ std::string cmFileAPI::NoSupportedVersion(
// The "codemodel" object kind.
// Update Help/manual/cmake-file-api.7.rst when updating this constant.
-static unsigned int const CodeModelV2Minor = 5;
+static unsigned int const CodeModelV2Minor = 6;
void cmFileAPI::BuildClientRequestCodeModel(
ClientRequest& r, std::vector<RequestVersion> const& versions)
diff --git a/Source/cmFileAPICodemodel.cxx b/Source/cmFileAPICodemodel.cxx
index 4a8716f..280ebb0 100644
--- a/Source/cmFileAPICodemodel.cxx
+++ b/Source/cmFileAPICodemodel.cxx
@@ -328,6 +328,7 @@ struct CompileData
std::vector<JBT<std::string>> Defines;
std::vector<JBT<std::string>> PrecompileHeaders;
std::vector<IncludeEntry> Includes;
+ std::vector<IncludeEntry> Frameworks;
friend bool operator==(CompileData const& l, CompileData const& r)
{
@@ -335,7 +336,7 @@ struct CompileData
l.Flags == r.Flags && l.Defines == r.Defines &&
l.PrecompileHeaders == r.PrecompileHeaders &&
l.LanguageStandard == r.LanguageStandard &&
- l.Includes == r.Includes);
+ l.Includes == r.Includes && l.Frameworks == r.Frameworks);
}
};
}
@@ -356,6 +357,12 @@ struct hash<CompileData>
hash<Json::ArrayIndex>()(i.Path.Backtrace.Index) ^
(i.IsSystem ? std::numeric_limits<size_t>::max() : 0));
}
+ for (auto const& i : in.Frameworks) {
+ result = result ^
+ (hash<std::string>()(i.Path.Value) ^
+ hash<Json::ArrayIndex>()(i.Path.Backtrace.Index) ^
+ (i.IsSystem ? std::numeric_limits<size_t>::max() : 0));
+ }
for (auto const& i : in.Flags) {
result = result ^ hash<std::string>()(i.Value) ^
hash<Json::ArrayIndex>()(i.Backtrace.Index);
@@ -468,6 +475,7 @@ class Target
Json::Value DumpPaths();
Json::Value DumpCompileData(CompileData const& cd);
Json::Value DumpInclude(CompileData::IncludeEntry const& inc);
+ Json::Value DumpFramework(CompileData::IncludeEntry const& fw);
Json::Value DumpPrecompileHeader(JBT<std::string> const& header);
Json::Value DumpLanguageStandard(JBTs<std::string> const& standard);
Json::Value DumpDefine(JBT<std::string> const& def);
@@ -1294,9 +1302,15 @@ void Target::ProcessLanguage(std::string const& lang)
std::vector<BT<std::string>> includePathList =
lg->GetIncludeDirectories(this->GT, lang, this->Config);
for (BT<std::string> const& i : includePathList) {
- cd.Includes.emplace_back(
- this->ToJBT(i),
- this->GT->IsSystemIncludeDirectory(i.Value, this->Config, lang));
+ if (this->GT->IsApple() && cmSystemTools::IsPathToFramework(i.Value)) {
+ cd.Frameworks.emplace_back(
+ this->ToJBT(i),
+ this->GT->IsSystemIncludeDirectory(i.Value, this->Config, lang));
+ } else {
+ cd.Includes.emplace_back(
+ this->ToJBT(i),
+ this->GT->IsSystemIncludeDirectory(i.Value, this->Config, lang));
+ }
}
std::vector<BT<std::string>> precompileHeaders =
this->GT->GetPrecompileHeaders(this->Config, lang);
@@ -1408,7 +1422,11 @@ CompileData Target::BuildCompileData(cmSourceFile* sf)
bool const isSystemInclude =
this->GT->IsSystemIncludeDirectory(i, this->Config, fd.Language);
BT<std::string> include(i, tmpInclude.Backtrace);
- fd.Includes.emplace_back(this->ToJBT(include), isSystemInclude);
+ if (this->GT->IsApple() && cmSystemTools::IsPathToFramework(i)) {
+ fd.Frameworks.emplace_back(this->ToJBT(include), isSystemInclude);
+ } else {
+ fd.Includes.emplace_back(this->ToJBT(include), isSystemInclude);
+ }
}
}
}
@@ -1481,6 +1499,13 @@ CompileData Target::MergeCompileData(CompileData const& fd)
cd.Includes.insert(cd.Includes.end(), td.Includes.begin(),
td.Includes.end());
+ // Use source-specific frameworks followed by target-wide frameworks.
+ cd.Frameworks.reserve(fd.Frameworks.size() + td.Frameworks.size());
+ cd.Frameworks.insert(cd.Frameworks.end(), fd.Frameworks.begin(),
+ fd.Frameworks.end());
+ cd.Frameworks.insert(cd.Frameworks.end(), td.Frameworks.begin(),
+ td.Frameworks.end());
+
// Use target-wide defines followed by source-specific defines.
cd.Defines.reserve(td.Defines.size() + fd.Defines.size());
cd.Defines.insert(cd.Defines.end(), td.Defines.begin(), td.Defines.end());
@@ -1696,6 +1721,13 @@ Json::Value Target::DumpCompileData(CompileData const& cd)
}
result["includes"] = includes;
}
+ if (!cd.Frameworks.empty()) {
+ Json::Value frameworks = Json::arrayValue;
+ for (auto const& i : cd.Frameworks) {
+ frameworks.append(this->DumpFramework(i));
+ }
+ result["frameworks"] = frameworks;
+ }
if (!cd.Defines.empty()) {
Json::Value defines = Json::arrayValue;
for (JBT<std::string> const& d : cd.Defines) {
@@ -1729,6 +1761,12 @@ Json::Value Target::DumpInclude(CompileData::IncludeEntry const& inc)
return include;
}
+Json::Value Target::DumpFramework(CompileData::IncludeEntry const& fw)
+{
+ // for now, idem as include
+ return this->DumpInclude(fw);
+}
+
Json::Value Target::DumpPrecompileHeader(JBT<std::string> const& header)
{
Json::Value precompileHeader = Json::objectValue;
diff --git a/Source/cmFindPackageCommand.cxx b/Source/cmFindPackageCommand.cxx
index 98b085c..1c2a937 100644
--- a/Source/cmFindPackageCommand.cxx
+++ b/Source/cmFindPackageCommand.cxx
@@ -1804,11 +1804,11 @@ void cmFindPackageCommand::AppendToFoundProperty(const bool found)
notFoundContents.push_back(this->Name);
}
- this->Makefile->GetState()->SetGlobalProperty(
- "PACKAGES_FOUND", foundContents.to_string().c_str());
+ this->Makefile->GetState()->SetGlobalProperty("PACKAGES_FOUND",
+ foundContents.to_string());
- this->Makefile->GetState()->SetGlobalProperty(
- "PACKAGES_NOT_FOUND", notFoundContents.to_string().c_str());
+ this->Makefile->GetState()->SetGlobalProperty("PACKAGES_NOT_FOUND",
+ notFoundContents.to_string());
}
void cmFindPackageCommand::AppendSuccessInformation()
@@ -1845,7 +1845,7 @@ void cmFindPackageCommand::AppendSuccessInformation()
cmStrCat(this->VersionExact ? "==" : ">=", ' ', this->Version);
}
this->Makefile->GetState()->SetGlobalProperty(versionInfoPropName,
- versionInfo.c_str());
+ versionInfo);
if (this->Required) {
std::string const requiredInfoPropName =
cmStrCat("_CMAKE_", this->Name, "_TYPE");
diff --git a/Source/cmGeneratorTarget.cxx b/Source/cmGeneratorTarget.cxx
index 32f0cbd..f8455c8 100644
--- a/Source/cmGeneratorTarget.cxx
+++ b/Source/cmGeneratorTarget.cxx
@@ -59,8 +59,6 @@
namespace {
using LinkInterfaceFor = cmGeneratorTarget::LinkInterfaceFor;
-const cmsys::RegularExpression FrameworkRegularExpression(
- "^(.*/)?([^/]*)\\.framework/(.*)$");
const std::string kINTERFACE_LINK_LIBRARIES = "INTERFACE_LINK_LIBRARIES";
const std::string kINTERFACE_LINK_LIBRARIES_DIRECT =
"INTERFACE_LINK_LIBRARIES_DIRECT";
@@ -2434,11 +2432,10 @@ std::string cmGeneratorTarget::GetSOName(
}
// Use the soname given if any.
if (this->IsFrameworkOnApple()) {
- cmsys::RegularExpressionMatch match;
- if (FrameworkRegularExpression.find(info->SOName.c_str(), match)) {
- auto frameworkName = match.match(2);
- auto fileName = match.match(3);
- return cmStrCat(frameworkName, ".framework/", fileName);
+ auto fwDescriptor = this->GetGlobalGenerator()->SplitFrameworkPath(
+ info->SOName, cmGlobalGenerator::FrameworkFormat::Strict);
+ if (fwDescriptor) {
+ return fwDescriptor->GetVersionedName();
}
}
if (cmHasLiteralPrefix(info->SOName, "@rpath/")) {
@@ -7036,13 +7033,10 @@ std::string cmGeneratorTarget::GetDirectory(
if (this->IsImported()) {
auto fullPath = this->Target->ImportedGetFullPath(config, artifact);
if (this->IsFrameworkOnApple()) {
- cmsys::RegularExpressionMatch match;
- if (FrameworkRegularExpression.find(fullPath.c_str(), match)) {
- auto path = match.match(1);
- if (!path.empty()) {
- path.erase(path.length() - 1);
- }
- return path;
+ auto fwDescriptor = this->GetGlobalGenerator()->SplitFrameworkPath(
+ fullPath, cmGlobalGenerator::FrameworkFormat::Strict);
+ if (fwDescriptor) {
+ return fwDescriptor->Directory;
}
}
// Return the directory from which the target is imported.
diff --git a/Source/cmGetTestPropertyCommand.cxx b/Source/cmGetTestPropertyCommand.cxx
index a4ac9f6..36446c9 100644
--- a/Source/cmGetTestPropertyCommand.cxx
+++ b/Source/cmGetTestPropertyCommand.cxx
@@ -25,7 +25,7 @@ bool cmGetTestPropertyCommand(std::vector<std::string> const& args,
prop = test->GetProperty(args[1]);
}
if (prop) {
- mf.AddDefinition(var, prop->c_str());
+ mf.AddDefinition(var, prop);
return true;
}
}
diff --git a/Source/cmGlobalCommonGenerator.cxx b/Source/cmGlobalCommonGenerator.cxx
index 7a44452..513e3bf 100644
--- a/Source/cmGlobalCommonGenerator.cxx
+++ b/Source/cmGlobalCommonGenerator.cxx
@@ -34,8 +34,8 @@ cmGlobalCommonGenerator::ComputeDirectoryTargets() const
{
std::map<std::string, DirectoryTarget> dirTargets;
for (const auto& lg : this->LocalGenerators) {
- std::string const& currentBinaryDir(
- lg->GetStateSnapshot().GetDirectory().GetCurrentBinary());
+ std::string currentBinaryDir =
+ lg->GetStateSnapshot().GetDirectory().GetCurrentBinary();
DirectoryTarget& dirTarget = dirTargets[currentBinaryDir];
dirTarget.LG = lg.get();
const std::vector<std::string>& configs =
@@ -68,7 +68,7 @@ cmGlobalCommonGenerator::ComputeDirectoryTargets() const
for (cmStateSnapshot dir =
lg->GetStateSnapshot().GetBuildsystemDirectoryParent();
dir.IsValid(); dir = dir.GetBuildsystemDirectoryParent()) {
- std::string const& d = dir.GetDirectory().GetCurrentBinary();
+ std::string d = dir.GetDirectory().GetCurrentBinary();
dirTargets[d].Targets.emplace_back(t);
}
}
diff --git a/Source/cmGlobalGenerator.cxx b/Source/cmGlobalGenerator.cxx
index 040f500..7e6b16a 100644
--- a/Source/cmGlobalGenerator.cxx
+++ b/Source/cmGlobalGenerator.cxx
@@ -47,6 +47,7 @@
#include "cmMSVC60LinkLineComputer.h"
#include "cmMakefile.h"
#include "cmMessageType.h"
+#include "cmOutputConverter.h"
#include "cmPolicies.h"
#include "cmRange.h"
#include "cmSourceFile.h"
@@ -73,6 +74,23 @@ const std::string kCMAKE_PLATFORM_INFO_INITIALIZED =
class cmInstalledFile;
+namespace detail {
+std::string GeneratedMakeCommand::QuotedPrintable() const
+{
+ std::string output;
+ const char* sep = "";
+ int flags = 0;
+#if !defined(_WIN32)
+ flags |= cmOutputConverter::Shell_Flag_IsUnix;
+#endif
+ for (auto const& arg : this->PrimaryCommand) {
+ output += cmStrCat(sep, cmOutputConverter::EscapeForShell(arg, flags));
+ sep = " ";
+ }
+ return output;
+}
+}
+
bool cmTarget::StrictTargetComparison::operator()(cmTarget const* t1,
cmTarget const* t2) const
{
@@ -268,7 +286,7 @@ void cmGlobalGenerator::ResolveLanguageCompiler(const std::string& lang,
changeVars += ";";
changeVars += *cname;
this->GetCMakeInstance()->GetState()->SetGlobalProperty(
- "__CMAKE_DELETE_CACHE_CHANGE_VARS_", changeVars.c_str());
+ "__CMAKE_DELETE_CACHE_CHANGE_VARS_", changeVars);
}
}
}
@@ -2058,9 +2076,12 @@ int cmGlobalGenerator::TryCompile(int jobs, const std::string& srcdir,
mf->GetSafeDefinition("CMAKE_TRY_COMPILE_CONFIGURATION");
cmBuildOptions defaultBuildOptions(false, fast, PackageResolveMode::Disable);
- return this->Build(jobs, srcdir, bindir, projectName, newTarget, output, "",
- config, defaultBuildOptions, true,
- this->TryCompileTimeout);
+ std::stringstream ostr;
+ auto ret =
+ this->Build(jobs, srcdir, bindir, projectName, newTarget, ostr, "", config,
+ defaultBuildOptions, true, this->TryCompileTimeout);
+ output = ostr.str();
+ return ret;
}
std::vector<cmGlobalGenerator::GeneratedMakeCommand>
@@ -2085,7 +2106,7 @@ void cmGlobalGenerator::PrintBuildCommandAdvice(std::ostream& /*os*/,
int cmGlobalGenerator::Build(
int jobs, const std::string& /*unused*/, const std::string& bindir,
const std::string& projectName, const std::vector<std::string>& targets,
- std::string& output, const std::string& makeCommandCSTR,
+ std::ostream& ostr, const std::string& makeCommandCSTR,
const std::string& config, const cmBuildOptions& buildOptions, bool verbose,
cmDuration timeout, cmSystemTools::OutputOption outputflag,
std::vector<std::string> const& nativeOptions)
@@ -2096,16 +2117,13 @@ int cmGlobalGenerator::Build(
* Run an executable command and put the stdout in output.
*/
cmWorkingDirectory workdir(bindir);
- output += "Change Dir: ";
- output += bindir;
- output += "\n";
+ ostr << "Change Dir: '" << bindir << '\'' << std::endl;
if (workdir.Failed()) {
cmSystemTools::SetRunCommandHideConsole(hideconsole);
std::string err = cmStrCat("Failed to change directory: ",
std::strerror(workdir.GetLastResult()));
cmSystemTools::Error(err);
- output += err;
- output += "\n";
+ ostr << err << std::endl;
return 1;
}
std::string realConfig = config;
@@ -2134,9 +2152,8 @@ int cmGlobalGenerator::Build(
this->GenerateBuildCommand(makeCommandCSTR, projectName, bindir,
{ "clean" }, realConfig, jobs, verbose,
buildOptions);
- output += "\nRun Clean Command:";
- output += cleanCommand.front().Printable();
- output += "\n";
+ ostr << "\nRun Clean Command: " << cleanCommand.front().QuotedPrintable()
+ << std::endl;
if (cleanCommand.size() != 1) {
this->GetCMakeInstance()->IssueMessage(MessageType::INTERNAL_ERROR,
"The generator did not produce "
@@ -2149,27 +2166,33 @@ int cmGlobalGenerator::Build(
nullptr, outputflag, timeout)) {
cmSystemTools::SetRunCommandHideConsole(hideconsole);
cmSystemTools::Error("Generator: execution of make clean failed.");
- output += *outputPtr;
- output += "\nGenerator: execution of make clean failed.\n";
+ ostr << *outputPtr << "\nGenerator: execution of make clean failed."
+ << std::endl;
return 1;
}
- output += *outputPtr;
+ ostr << *outputPtr;
}
// now build
std::string makeCommandStr;
- output += "\nRun Build Command(s):";
+ std::string outputMakeCommandStr;
+ bool isWatcomWMake = this->CMakeInstance->GetState()->UseWatcomWMake();
+ bool needBuildOutput = isWatcomWMake;
+ std::string buildOutput;
+ ostr << "\nRun Build Command(s): ";
retVal = 0;
for (auto command = makeCommand.begin();
command != makeCommand.end() && retVal == 0; ++command) {
makeCommandStr = command->Printable();
- if (command != makeCommand.end()) {
+ outputMakeCommandStr = command->QuotedPrintable();
+ if ((command + 1) != makeCommand.end()) {
makeCommandStr += " && ";
+ outputMakeCommandStr += " && ";
}
- output += makeCommandStr;
+ ostr << outputMakeCommandStr << std::endl;
if (!cmSystemTools::RunSingleCommand(command->PrimaryCommand, outputPtr,
outputPtr, &retVal, nullptr,
outputflag, timeout)) {
@@ -2177,21 +2200,24 @@ int cmGlobalGenerator::Build(
cmSystemTools::Error(
"Generator: execution of make failed. Make command was: " +
makeCommandStr);
- output += *outputPtr;
- output += "\nGenerator: execution of make failed. Make command was: " +
- makeCommandStr + "\n";
+ ostr << *outputPtr
+ << "\nGenerator: execution of make failed. Make command was: "
+ << outputMakeCommandStr << std::endl;
return 1;
}
- output += *outputPtr;
+ ostr << *outputPtr << std::flush;
+ if (needBuildOutput) {
+ buildOutput += *outputPtr;
+ }
}
- output += "\n";
+ ostr << std::endl;
cmSystemTools::SetRunCommandHideConsole(hideconsole);
// The OpenWatcom tools do not return an error code when a link
// library is not found!
- if (this->CMakeInstance->GetState()->UseWatcomWMake() && retVal == 0 &&
- output.find("W1008: cannot open") != std::string::npos) {
+ if (isWatcomWMake && retVal == 0 &&
+ buildOutput.find("W1008: cannot open") != std::string::npos) {
retVal = 1;
}
@@ -2598,14 +2624,14 @@ cmGlobalGenerator::SplitFrameworkPath(const std::string& path,
// or (/path/to/)?FwName.framework/FwName(.tbd)?
// or (/path/to/)?FwName.framework/Versions/*/FwName(.tbd)?
static cmsys::RegularExpression frameworkPath(
- "((.+)/)?(.+)\\.framework(/Versions/[^/]+)?(/(.+))?$");
+ "((.+)/)?([^/]+)\\.framework(/Versions/([^/]+))?(/(.+))?$");
auto ext = cmSystemTools::GetFilenameLastExtension(path);
if ((ext.empty() || ext == ".tbd" || ext == ".framework") &&
frameworkPath.find(path)) {
auto name = frameworkPath.match(3);
auto libname =
- cmSystemTools::GetFilenameWithoutExtension(frameworkPath.match(6));
+ cmSystemTools::GetFilenameWithoutExtension(frameworkPath.match(7));
if (format == FrameworkFormat::Strict && libname.empty()) {
return cm::nullopt;
}
@@ -2614,11 +2640,12 @@ cmGlobalGenerator::SplitFrameworkPath(const std::string& path,
}
if (libname.empty() || name.size() == libname.size()) {
- return FrameworkDescriptor{ frameworkPath.match(2), name };
+ return FrameworkDescriptor{ frameworkPath.match(2),
+ frameworkPath.match(5), name };
}
- return FrameworkDescriptor{ frameworkPath.match(2), name,
- libname.substr(name.size()) };
+ return FrameworkDescriptor{ frameworkPath.match(2), frameworkPath.match(5),
+ name, libname.substr(name.size()) };
}
if (format == FrameworkFormat::Extended) {
diff --git a/Source/cmGlobalGenerator.h b/Source/cmGlobalGenerator.h
index 79fe52c..01afabd 100644
--- a/Source/cmGlobalGenerator.h
+++ b/Source/cmGlobalGenerator.h
@@ -85,6 +85,7 @@ struct GeneratedMakeCommand
}
std::string Printable() const { return cmJoin(this->PrimaryCommand, " "); }
+ std::string QuotedPrintable() const;
std::vector<std::string> PrimaryCommand;
bool RequiresOutputForward = false;
@@ -233,7 +234,7 @@ public:
int Build(
int jobs, const std::string& srcdir, const std::string& bindir,
const std::string& projectName,
- std::vector<std::string> const& targetNames, std::string& output,
+ std::vector<std::string> const& targetNames, std::ostream& ostr,
const std::string& makeProgram, const std::string& config,
const cmBuildOptions& buildOptions, bool verbose, cmDuration timeout,
cmSystemTools::OutputOption outputflag = cmSystemTools::OUTPUT_NONE,
@@ -384,9 +385,17 @@ public:
, Name(std::move(name))
{
}
- FrameworkDescriptor(std::string directory, std::string name,
- std::string suffix)
+ FrameworkDescriptor(std::string directory, std::string version,
+ std::string name)
: Directory(std::move(directory))
+ , Version(std::move(version))
+ , Name(std::move(name))
+ {
+ }
+ FrameworkDescriptor(std::string directory, std::string version,
+ std::string name, std::string suffix)
+ : Directory(std::move(directory))
+ , Version(std::move(version))
, Name(std::move(name))
, Suffix(std::move(suffix))
{
@@ -400,6 +409,13 @@ public:
{
return cmStrCat(this->Name, ".framework/"_s, this->Name, this->Suffix);
}
+ std::string GetVersionedName() const
+ {
+ return this->Version.empty()
+ ? this->GetFullName()
+ : cmStrCat(this->Name, ".framework/Versions/"_s, this->Version, '/',
+ this->Name, this->Suffix);
+ }
std::string GetFrameworkPath() const
{
return this->Directory.empty()
@@ -412,8 +428,15 @@ public:
? this->GetFullName()
: cmStrCat(this->Directory, '/', this->GetFullName());
}
+ std::string GetVersionedPath() const
+ {
+ return this->Directory.empty()
+ ? this->GetVersionedName()
+ : cmStrCat(this->Directory, '/', this->GetVersionedName());
+ }
const std::string Directory;
+ const std::string Version;
const std::string Name;
const std::string Suffix;
};
diff --git a/Source/cmGlobalGhsMultiGenerator.cxx b/Source/cmGlobalGhsMultiGenerator.cxx
index 578e805..2453bfc 100644
--- a/Source/cmGlobalGhsMultiGenerator.cxx
+++ b/Source/cmGlobalGhsMultiGenerator.cxx
@@ -101,11 +101,11 @@ bool cmGlobalGhsMultiGenerator::SetGeneratorToolset(std::string const& ts,
/* check if the toolset changed from last generate */
if (cmNonempty(prevTool) && !cmSystemTools::ComparePath(gbuild, *prevTool)) {
- std::string const& e =
- cmStrCat("toolset build tool: ", gbuild,
- "\nDoes not match the previously used build tool: ", *prevTool,
- "\nEither remove the CMakeCache.txt file and CMakeFiles "
- "directory or choose a different binary directory.");
+ std::string const& e = cmStrCat(
+ "toolset build tool: ", gbuild, '\n',
+ "Does not match the previously used build tool: ", *prevTool, '\n',
+ "Either remove the CMakeCache.txt file and CMakeFiles "
+ "directory or choose a different binary directory.");
mf->IssueMessage(MessageType::FATAL_ERROR, e);
return false;
}
diff --git a/Source/cmGlobalVisualStudio7Generator.cxx b/Source/cmGlobalVisualStudio7Generator.cxx
index 694698e..b254777 100644
--- a/Source/cmGlobalVisualStudio7Generator.cxx
+++ b/Source/cmGlobalVisualStudio7Generator.cxx
@@ -716,7 +716,7 @@ std::set<std::string> cmGlobalVisualStudio7Generator::IsPartOfDefaultBuild(
cmGeneratorTarget const* target)
{
std::set<std::string> activeConfigs;
- // if it is a utilitiy target then only make it part of the
+ // if it is a utility target then only make it part of the
// default build if another target depends on it
int type = target->GetType();
if (type == cmStateEnums::GLOBAL_TARGET) {
diff --git a/Source/cmMakefile.cxx b/Source/cmMakefile.cxx
index 01afc44..92ba2d4 100644
--- a/Source/cmMakefile.cxx
+++ b/Source/cmMakefile.cxx
@@ -68,6 +68,10 @@
# include "cmVariableWatch.h"
#endif
+#ifdef CMake_ENABLE_DEBUGGER
+# include "cmDebuggerAdapter.h"
+#endif
+
#ifndef __has_feature
# define __has_feature(x) 0
#endif
@@ -424,6 +428,13 @@ public:
return argsValue;
});
#endif
+#ifdef CMake_ENABLE_DEBUGGER
+ if (this->Makefile->GetCMakeInstance()->GetDebugAdapter() != nullptr) {
+ this->Makefile->GetCMakeInstance()
+ ->GetDebugAdapter()
+ ->OnBeginFunctionCall(mf, lfc.FilePath, lff);
+ }
+#endif
}
~cmMakefileCall()
@@ -434,6 +445,13 @@ public:
this->Makefile->ExecutionStatusStack.pop_back();
--this->Makefile->RecursionDepth;
this->Makefile->Backtrace = this->Makefile->Backtrace.Pop();
+#ifdef CMake_ENABLE_DEBUGGER
+ if (this->Makefile->GetCMakeInstance()->GetDebugAdapter() != nullptr) {
+ this->Makefile->GetCMakeInstance()
+ ->GetDebugAdapter()
+ ->OnEndFunctionCall();
+ }
+#endif
}
cmMakefileCall(const cmMakefileCall&) = delete;
@@ -663,12 +681,33 @@ bool cmMakefile::ReadDependentFile(const std::string& filename,
IncludeScope incScope(this, filenametoread, noPolicyScope);
+#ifdef CMake_ENABLE_DEBUGGER
+ if (this->GetCMakeInstance()->GetDebugAdapter() != nullptr) {
+ this->GetCMakeInstance()->GetDebugAdapter()->OnBeginFileParse(
+ this, filenametoread);
+ }
+#endif
+
cmListFile listFile;
if (!listFile.ParseFile(filenametoread.c_str(), this->GetMessenger(),
this->Backtrace)) {
+#ifdef CMake_ENABLE_DEBUGGER
+ if (this->GetCMakeInstance()->GetDebugAdapter() != nullptr) {
+ this->GetCMakeInstance()->GetDebugAdapter()->OnEndFileParse();
+ }
+#endif
+
return false;
}
+#ifdef CMake_ENABLE_DEBUGGER
+ if (this->GetCMakeInstance()->GetDebugAdapter() != nullptr) {
+ this->GetCMakeInstance()->GetDebugAdapter()->OnEndFileParse();
+ this->GetCMakeInstance()->GetDebugAdapter()->OnFileParsedSuccessfully(
+ filenametoread, listFile.Functions);
+ }
+#endif
+
this->RunListFile(listFile, filenametoread);
if (cmSystemTools::GetFatalErrorOccurred()) {
incScope.Quiet();
@@ -764,12 +803,33 @@ bool cmMakefile::ReadListFile(const std::string& filename)
ListFileScope scope(this, filenametoread);
+#ifdef CMake_ENABLE_DEBUGGER
+ if (this->GetCMakeInstance()->GetDebugAdapter() != nullptr) {
+ this->GetCMakeInstance()->GetDebugAdapter()->OnBeginFileParse(
+ this, filenametoread);
+ }
+#endif
+
cmListFile listFile;
if (!listFile.ParseFile(filenametoread.c_str(), this->GetMessenger(),
this->Backtrace)) {
+#ifdef CMake_ENABLE_DEBUGGER
+ if (this->GetCMakeInstance()->GetDebugAdapter() != nullptr) {
+ this->GetCMakeInstance()->GetDebugAdapter()->OnEndFileParse();
+ }
+#endif
+
return false;
}
+#ifdef CMake_ENABLE_DEBUGGER
+ if (this->GetCMakeInstance()->GetDebugAdapter() != nullptr) {
+ this->GetCMakeInstance()->GetDebugAdapter()->OnEndFileParse();
+ this->GetCMakeInstance()->GetDebugAdapter()->OnFileParsedSuccessfully(
+ filenametoread, listFile.Functions);
+ }
+#endif
+
this->RunListFile(listFile, filenametoread);
if (cmSystemTools::GetFatalErrorOccurred()) {
scope.Quiet();
@@ -791,6 +851,13 @@ bool cmMakefile::ReadListFileAsString(const std::string& content,
return false;
}
+#ifdef CMake_ENABLE_DEBUGGER
+ if (this->GetCMakeInstance()->GetDebugAdapter() != nullptr) {
+ this->GetCMakeInstance()->GetDebugAdapter()->OnFileParsedSuccessfully(
+ filenametoread, listFile.Functions);
+ }
+#endif
+
this->RunListFile(listFile, filenametoread);
if (cmSystemTools::GetFatalErrorOccurred()) {
scope.Quiet();
@@ -1658,11 +1725,33 @@ void cmMakefile::Configure()
assert(cmSystemTools::FileExists(currentStart, true));
this->AddDefinition("CMAKE_PARENT_LIST_FILE", currentStart);
+#ifdef CMake_ENABLE_DEBUGGER
+ if (this->GetCMakeInstance()->GetDebugAdapter() != nullptr) {
+ this->GetCMakeInstance()->GetDebugAdapter()->OnBeginFileParse(
+ this, currentStart);
+ }
+#endif
+
cmListFile listFile;
if (!listFile.ParseFile(currentStart.c_str(), this->GetMessenger(),
this->Backtrace)) {
+#ifdef CMake_ENABLE_DEBUGGER
+ if (this->GetCMakeInstance()->GetDebugAdapter() != nullptr) {
+ this->GetCMakeInstance()->GetDebugAdapter()->OnEndFileParse();
+ }
+#endif
+
return;
}
+
+#ifdef CMake_ENABLE_DEBUGGER
+ if (this->GetCMakeInstance()->GetDebugAdapter() != nullptr) {
+ this->GetCMakeInstance()->GetDebugAdapter()->OnEndFileParse();
+ this->GetCMakeInstance()->GetDebugAdapter()->OnFileParsedSuccessfully(
+ currentStart, listFile.Functions);
+ }
+#endif
+
if (this->IsRootMakefile()) {
bool hasVersion = false;
// search for the right policy command
@@ -3769,6 +3858,12 @@ void cmMakefile::DisplayStatus(const std::string& message, float s) const
return;
}
cm->UpdateProgress(message, s);
+
+#ifdef CMake_ENABLE_DEBUGGER
+ if (cm->GetDebugAdapter() != nullptr) {
+ cm->GetDebugAdapter()->OnMessageOutput(MessageType::MESSAGE, message);
+ }
+#endif
}
std::string cmMakefile::GetModulesFile(const std::string& filename,
@@ -4044,10 +4139,6 @@ int cmMakefile::ConfigureFile(const std::string& infile,
return res;
}
-void cmMakefile::SetProperty(const std::string& prop, const char* value)
-{
- this->StateSnapshot.GetDirectory().SetProperty(prop, value, this->Backtrace);
-}
void cmMakefile::SetProperty(const std::string& prop, cmValue value)
{
this->StateSnapshot.GetDirectory().SetProperty(prop, value, this->Backtrace);
diff --git a/Source/cmMakefile.h b/Source/cmMakefile.h
index d1f5be5..6fdadab 100644
--- a/Source/cmMakefile.h
+++ b/Source/cmMakefile.h
@@ -425,7 +425,7 @@ public:
*/
void SetIncludeRegularExpression(const std::string& regex)
{
- this->SetProperty("INCLUDE_REGULAR_EXPRESSION", regex.c_str());
+ this->SetProperty("INCLUDE_REGULAR_EXPRESSION", regex);
}
const std::string& GetIncludeRegularExpression() const
{
@@ -801,8 +801,11 @@ public:
std::string& debugBuffer) const;
//! Set/Get a property of this directory
- void SetProperty(const std::string& prop, const char* value);
void SetProperty(const std::string& prop, cmValue value);
+ void SetProperty(const std::string& prop, std::nullptr_t)
+ {
+ this->SetProperty(prop, cmValue{ nullptr });
+ }
void SetProperty(const std::string& prop, const std::string& value)
{
this->SetProperty(prop, cmValue(value));
diff --git a/Source/cmMakefileLibraryTargetGenerator.cxx b/Source/cmMakefileLibraryTargetGenerator.cxx
index b07a74b..fc3caa1 100644
--- a/Source/cmMakefileLibraryTargetGenerator.cxx
+++ b/Source/cmMakefileLibraryTargetGenerator.cxx
@@ -785,7 +785,7 @@ void cmMakefileLibraryTargetGenerator::WriteLibraryRules(
if (this->GeneratorTarget->HasSOName(this->GetConfigName())) {
vars.SONameFlag = this->Makefile->GetSONameFlag(linkLanguage);
targetOutSOName = this->LocalGenerator->ConvertToOutputFormat(
- this->TargetNames.SharedObject.c_str(), cmOutputConverter::SHELL);
+ this->TargetNames.SharedObject, cmOutputConverter::SHELL);
vars.TargetSOName = targetOutSOName.c_str();
}
vars.LinkFlags = linkFlags.c_str();
diff --git a/Source/cmMessageCommand.cxx b/Source/cmMessageCommand.cxx
index baf40f8..68b3a5d 100644
--- a/Source/cmMessageCommand.cxx
+++ b/Source/cmMessageCommand.cxx
@@ -3,6 +3,7 @@
#include "cmMessageCommand.h"
#include <cassert>
+#include <memory>
#include <utility>
#include <cm/string_view>
@@ -19,6 +20,10 @@
#include "cmSystemTools.h"
#include "cmake.h"
+#ifdef CMake_ENABLE_DEBUGGER
+# include "cmDebuggerAdapter.h"
+#endif
+
namespace {
enum class CheckingType
@@ -202,6 +207,12 @@ bool cmMessageCommand(std::vector<std::string> const& args,
case Message::LogLevel::LOG_NOTICE:
cmSystemTools::Message(IndentText(message, mf));
+#ifdef CMake_ENABLE_DEBUGGER
+ if (mf.GetCMakeInstance()->GetDebugAdapter() != nullptr) {
+ mf.GetCMakeInstance()->GetDebugAdapter()->OnMessageOutput(type,
+ message);
+ }
+#endif
break;
case Message::LogLevel::LOG_STATUS:
diff --git a/Source/cmMessenger.cxx b/Source/cmMessenger.cxx
index ff513be..4e975d1 100644
--- a/Source/cmMessenger.cxx
+++ b/Source/cmMessenger.cxx
@@ -16,53 +16,44 @@
#include "cmsys/Terminal.h"
+#ifdef CMake_ENABLE_DEBUGGER
+# include "cmDebuggerAdapter.h"
+#endif
+
MessageType cmMessenger::ConvertMessageType(MessageType t) const
{
- bool warningsAsErrors;
-
if (t == MessageType::AUTHOR_WARNING || t == MessageType::AUTHOR_ERROR) {
- warningsAsErrors = this->GetDevWarningsAsErrors();
- if (warningsAsErrors && t == MessageType::AUTHOR_WARNING) {
- t = MessageType::AUTHOR_ERROR;
- } else if (!warningsAsErrors && t == MessageType::AUTHOR_ERROR) {
- t = MessageType::AUTHOR_WARNING;
+ if (this->GetDevWarningsAsErrors()) {
+ return MessageType::AUTHOR_ERROR;
}
- } else if (t == MessageType::DEPRECATION_WARNING ||
- t == MessageType::DEPRECATION_ERROR) {
- warningsAsErrors = this->GetDeprecatedWarningsAsErrors();
- if (warningsAsErrors && t == MessageType::DEPRECATION_WARNING) {
- t = MessageType::DEPRECATION_ERROR;
- } else if (!warningsAsErrors && t == MessageType::DEPRECATION_ERROR) {
- t = MessageType::DEPRECATION_WARNING;
+ return MessageType::AUTHOR_WARNING;
+ }
+ if (t == MessageType::DEPRECATION_WARNING ||
+ t == MessageType::DEPRECATION_ERROR) {
+ if (this->GetDeprecatedWarningsAsErrors()) {
+ return MessageType::DEPRECATION_ERROR;
}
+ return MessageType::DEPRECATION_WARNING;
}
-
return t;
}
bool cmMessenger::IsMessageTypeVisible(MessageType t) const
{
- bool isVisible = true;
-
if (t == MessageType::DEPRECATION_ERROR) {
- if (!this->GetDeprecatedWarningsAsErrors()) {
- isVisible = false;
- }
- } else if (t == MessageType::DEPRECATION_WARNING) {
- if (this->GetSuppressDeprecatedWarnings()) {
- isVisible = false;
- }
- } else if (t == MessageType::AUTHOR_ERROR) {
- if (!this->GetDevWarningsAsErrors()) {
- isVisible = false;
- }
- } else if (t == MessageType::AUTHOR_WARNING) {
- if (this->GetSuppressDevWarnings()) {
- isVisible = false;
- }
+ return this->GetDeprecatedWarningsAsErrors();
+ }
+ if (t == MessageType::DEPRECATION_WARNING) {
+ return !this->GetSuppressDeprecatedWarnings();
+ }
+ if (t == MessageType::AUTHOR_ERROR) {
+ return this->GetDevWarningsAsErrors();
+ }
+ if (t == MessageType::AUTHOR_WARNING) {
+ return !this->GetSuppressDevWarnings();
}
- return isVisible;
+ return true;
}
static bool printMessagePreamble(MessageType t, std::ostream& msg)
@@ -220,6 +211,12 @@ void cmMessenger::DisplayMessage(MessageType t, const std::string& text,
PrintCallStack(msg, backtrace, this->TopSource);
displayMessage(t, msg);
+
+#ifdef CMake_ENABLE_DEBUGGER
+ if (DebuggerAdapter != nullptr) {
+ DebuggerAdapter->OnMessageOutput(t, msg.str());
+ }
+#endif
}
void cmMessenger::PrintBacktraceTitle(std::ostream& out,
diff --git a/Source/cmMessenger.h b/Source/cmMessenger.h
index 451add0..bdefb00 100644
--- a/Source/cmMessenger.h
+++ b/Source/cmMessenger.h
@@ -5,6 +5,7 @@
#include "cmConfigure.h" // IWYU pragma: keep
#include <iosfwd>
+#include <memory>
#include <string>
#include <cm/optional>
@@ -12,6 +13,12 @@
#include "cmListFileCache.h"
#include "cmMessageType.h"
+#ifdef CMake_ENABLE_DEBUGGER
+namespace cmDebugger {
+class cmDebuggerAdapter;
+}
+#endif
+
class cmMessenger
{
public:
@@ -55,6 +62,13 @@ public:
// Print the top of a backtrace.
void PrintBacktraceTitle(std::ostream& out,
cmListFileBacktrace const& bt) const;
+#ifdef CMake_ENABLE_DEBUGGER
+ void SetDebuggerAdapter(
+ std::shared_ptr<cmDebugger::cmDebuggerAdapter> const& debuggerAdapter)
+ {
+ DebuggerAdapter = debuggerAdapter;
+ }
+#endif
private:
bool IsMessageTypeVisible(MessageType t) const;
@@ -66,4 +80,7 @@ private:
bool SuppressDeprecatedWarnings = false;
bool DevWarningsAsErrors = false;
bool DeprecatedWarningsAsErrors = false;
+#ifdef CMake_ENABLE_DEBUGGER
+ std::shared_ptr<cmDebugger::cmDebuggerAdapter> DebuggerAdapter;
+#endif
};
diff --git a/Source/cmOutputConverter.cxx b/Source/cmOutputConverter.cxx
index 53cb21e..02981ae 100644
--- a/Source/cmOutputConverter.cxx
+++ b/Source/cmOutputConverter.cxx
@@ -243,11 +243,6 @@ std::string cmOutputConverter::EscapeForShell(cm::string_view str,
bool unescapeNinjaConfiguration,
bool forResponse) const
{
- // Do not escape shell operators.
- if (cmOutputConverterIsShellOperator(str)) {
- return std::string(str);
- }
-
// Compute the flags for the target shell environment.
int flags = 0;
if (this->GetState()->UseWindowsVSIDE()) {
@@ -283,6 +278,16 @@ std::string cmOutputConverter::EscapeForShell(cm::string_view str,
flags |= Shell_Flag_IsUnix;
}
+ return cmOutputConverter::EscapeForShell(str, flags);
+}
+
+std::string cmOutputConverter::EscapeForShell(cm::string_view str, int flags)
+{
+ // Do not escape shell operators.
+ if (cmOutputConverterIsShellOperator(str)) {
+ return std::string(str);
+ }
+
return Shell_GetArgument(str, flags);
}
diff --git a/Source/cmOutputConverter.h b/Source/cmOutputConverter.h
index 625d897..0ee7afb 100644
--- a/Source/cmOutputConverter.h
+++ b/Source/cmOutputConverter.h
@@ -107,6 +107,7 @@ public:
bool forEcho = false, bool useWatcomQuote = false,
bool unescapeNinjaConfiguration = false,
bool forResponse = false) const;
+ static std::string EscapeForShell(cm::string_view str, int flags);
enum class WrapQuotes
{
diff --git a/Source/cmPropertyMap.cxx b/Source/cmPropertyMap.cxx
index b15000f..568a3d2 100644
--- a/Source/cmPropertyMap.cxx
+++ b/Source/cmPropertyMap.cxx
@@ -10,14 +10,9 @@ void cmPropertyMap::Clear()
this->Map_.clear();
}
-void cmPropertyMap::SetProperty(const std::string& name, const char* value)
+void cmPropertyMap::SetProperty(const std::string& name, std::nullptr_t)
{
- if (!value) {
- this->Map_.erase(name);
- return;
- }
-
- this->Map_[name] = value;
+ this->Map_.erase(name);
}
void cmPropertyMap::SetProperty(const std::string& name, cmValue value)
{
diff --git a/Source/cmPropertyMap.h b/Source/cmPropertyMap.h
index f50b65e..23b50a5 100644
--- a/Source/cmPropertyMap.h
+++ b/Source/cmPropertyMap.h
@@ -4,6 +4,7 @@
#include "cmConfigure.h" // IWYU pragma: keep
+#include <cstddef>
#include <string>
#include <unordered_map>
#include <utility>
@@ -25,7 +26,7 @@ public:
// -- Properties
//! Set the property value
- void SetProperty(const std::string& name, const char* value);
+ void SetProperty(const std::string& name, std::nullptr_t);
void SetProperty(const std::string& name, cmValue value);
void SetProperty(const std::string& name, const std::string& value)
{
diff --git a/Source/cmQtAutoMocUic.cxx b/Source/cmQtAutoMocUic.cxx
index b7af859..a101a81 100644
--- a/Source/cmQtAutoMocUic.cxx
+++ b/Source/cmQtAutoMocUic.cxx
@@ -2272,10 +2272,9 @@ cmQtAutoMocUicT::JobDepFilesMergeT::initialDependencies() const
void cmQtAutoMocUicT::JobDepFilesMergeT::Process()
{
if (this->Log().Verbose()) {
- this->Log().Info(
- GenT::MOC,
- cmStrCat("Merging MOC dependencies into ",
- this->MessagePath(this->BaseConst().DepFile.c_str())));
+ this->Log().Info(GenT::MOC,
+ cmStrCat("Merging MOC dependencies into ",
+ this->MessagePath(this->BaseConst().DepFile)));
}
auto processDepFile =
[this](const std::string& mocOutputFile) -> std::vector<std::string> {
diff --git a/Source/cmSourceFile.cxx b/Source/cmSourceFile.cxx
index 6224d0e..3403745 100644
--- a/Source/cmSourceFile.cxx
+++ b/Source/cmSourceFile.cxx
@@ -278,8 +278,7 @@ bool cmSourceFile::Matches(cmSourceFileLocation const& loc)
return this->Location.Matches(loc);
}
-template <typename ValueType>
-void cmSourceFile::StoreProperty(const std::string& prop, ValueType value)
+void cmSourceFile::SetProperty(const std::string& prop, cmValue value)
{
if (prop == propINCLUDE_DIRECTORIES) {
this->IncludeDirectories.clear();
@@ -304,15 +303,6 @@ void cmSourceFile::StoreProperty(const std::string& prop, ValueType value)
}
}
-void cmSourceFile::SetProperty(const std::string& prop, const char* value)
-{
- this->StoreProperty(prop, value);
-}
-void cmSourceFile::SetProperty(const std::string& prop, cmValue value)
-{
- this->StoreProperty(prop, value);
-}
-
void cmSourceFile::AppendProperty(const std::string& prop,
const std::string& value, bool asString)
{
diff --git a/Source/cmSourceFile.h b/Source/cmSourceFile.h
index 9308af4..3f070a7 100644
--- a/Source/cmSourceFile.h
+++ b/Source/cmSourceFile.h
@@ -4,6 +4,7 @@
#include "cmConfigure.h" // IWYU pragma: keep
+#include <cstddef>
#include <memory>
#include <string>
#include <vector>
@@ -41,8 +42,11 @@ public:
void SetCustomCommand(std::unique_ptr<cmCustomCommand> cc);
//! Set/Get a property of this source file
- void SetProperty(const std::string& prop, const char* value);
void SetProperty(const std::string& prop, cmValue value);
+ void SetProperty(const std::string& prop, std::nullptr_t)
+ {
+ this->SetProperty(prop, cmValue{ nullptr });
+ }
void SetProperty(const std::string& prop, const std::string& value)
{
this->SetProperty(prop, cmValue(value));
diff --git a/Source/cmState.cxx b/Source/cmState.cxx
index f12f91f..a72f830 100644
--- a/Source/cmState.cxx
+++ b/Source/cmState.cxx
@@ -101,11 +101,13 @@ cmStateEnums::CacheEntryType cmState::StringToCacheEntryType(
bool cmState::StringToCacheEntryType(const std::string& s,
cmStateEnums::CacheEntryType& type)
{
- for (size_t i = 0; i < cmCacheEntryTypes.size(); ++i) {
- if (s == cmCacheEntryTypes[i]) {
- type = static_cast<cmStateEnums::CacheEntryType>(i);
- return true;
- }
+ // NOLINTNEXTLINE(readability-qualified-auto)
+ auto const entry =
+ std::find(cmCacheEntryTypes.begin(), cmCacheEntryTypes.end(), s);
+ if (entry != cmCacheEntryTypes.end()) {
+ type = static_cast<cmStateEnums::CacheEntryType>(
+ entry - cmCacheEntryTypes.begin());
+ return true;
}
return false;
}
@@ -562,7 +564,8 @@ void cmState::RemoveUserDefinedCommands()
this->ScriptedCommands.clear();
}
-void cmState::SetGlobalProperty(const std::string& prop, const char* value)
+void cmState::SetGlobalProperty(const std::string& prop,
+ const std::string& value)
{
this->GlobalProperties.SetProperty(prop, value);
}
@@ -581,10 +584,10 @@ cmValue cmState::GetGlobalProperty(const std::string& prop)
{
if (prop == "CACHE_VARIABLES") {
std::vector<std::string> cacheKeys = this->GetCacheEntryKeys();
- this->SetGlobalProperty("CACHE_VARIABLES", cmJoin(cacheKeys, ";").c_str());
+ this->SetGlobalProperty("CACHE_VARIABLES", cmJoin(cacheKeys, ";"));
} else if (prop == "COMMANDS") {
std::vector<std::string> commands = this->GetCommandNames();
- this->SetGlobalProperty("COMMANDS", cmJoin(commands, ";").c_str());
+ this->SetGlobalProperty("COMMANDS", cmJoin(commands, ";"));
} else if (prop == "IN_TRY_COMPILE") {
this->SetGlobalProperty(
"IN_TRY_COMPILE",
@@ -595,10 +598,10 @@ cmValue cmState::GetGlobalProperty(const std::string& prop)
} else if (prop == "ENABLED_LANGUAGES") {
std::string langs;
langs = cmJoin(this->EnabledLanguages, ";");
- this->SetGlobalProperty("ENABLED_LANGUAGES", langs.c_str());
+ this->SetGlobalProperty("ENABLED_LANGUAGES", langs);
} else if (prop == "CMAKE_ROLE") {
std::string mode = this->GetModeString();
- this->SetGlobalProperty("CMAKE_ROLE", mode.c_str());
+ this->SetGlobalProperty("CMAKE_ROLE", mode);
}
#define STRING_LIST_ELEMENT(F) ";" #F
if (prop == "CMAKE_C_KNOWN_FEATURES") {
diff --git a/Source/cmState.h b/Source/cmState.h
index 0a42df0..d9d2c21 100644
--- a/Source/cmState.h
+++ b/Source/cmState.h
@@ -194,7 +194,7 @@ public:
void RemoveUserDefinedCommands();
std::vector<std::string> GetCommandNames() const;
- void SetGlobalProperty(const std::string& prop, const char* value);
+ void SetGlobalProperty(const std::string& prop, const std::string& value);
void SetGlobalProperty(const std::string& prop, cmValue value);
void AppendGlobalProperty(const std::string& prop, const std::string& value,
bool asString = false);
diff --git a/Source/cmStateDirectory.cxx b/Source/cmStateDirectory.cxx
index 20e4604..6e6fcbd 100644
--- a/Source/cmStateDirectory.cxx
+++ b/Source/cmStateDirectory.cxx
@@ -271,9 +271,8 @@ void cmStateDirectory::ClearLinkDirectories()
this->Snapshot_.Position->LinkDirectoriesPosition);
}
-template <typename ValueType>
-void cmStateDirectory::StoreProperty(const std::string& prop, ValueType value,
- cmListFileBacktrace const& lfbt)
+void cmStateDirectory::SetProperty(const std::string& prop, cmValue value,
+ cmListFileBacktrace const& lfbt)
{
if (prop == "INCLUDE_DIRECTORIES") {
if (!value) {
@@ -319,17 +318,6 @@ void cmStateDirectory::StoreProperty(const std::string& prop, ValueType value,
this->DirectoryState->Properties.SetProperty(prop, value);
}
-void cmStateDirectory::SetProperty(const std::string& prop, const char* value,
- cmListFileBacktrace const& lfbt)
-{
- this->StoreProperty(prop, value, lfbt);
-}
-void cmStateDirectory::SetProperty(const std::string& prop, cmValue value,
- cmListFileBacktrace const& lfbt)
-{
- this->StoreProperty(prop, value, lfbt);
-}
-
void cmStateDirectory::AppendProperty(const std::string& prop,
const std::string& value, bool asString,
cmListFileBacktrace const& lfbt)
diff --git a/Source/cmStateDirectory.h b/Source/cmStateDirectory.h
index 8c6b09d..55cc716 100644
--- a/Source/cmStateDirectory.h
+++ b/Source/cmStateDirectory.h
@@ -5,6 +5,7 @@
#include "cmConfigure.h" // IWYU pragma: keep
+#include <cstddef>
#include <string>
#include <vector>
@@ -57,10 +58,13 @@ public:
void SetLinkDirectories(BT<std::string> const& vecs);
void ClearLinkDirectories();
- void SetProperty(const std::string& prop, const char* value,
- cmListFileBacktrace const& lfbt);
void SetProperty(const std::string& prop, cmValue value,
cmListFileBacktrace const& lfbt);
+ void SetProperty(const std::string& prop, std::nullptr_t,
+ cmListFileBacktrace const& lfbt)
+ {
+ this->SetProperty(prop, cmValue{ nullptr }, lfbt);
+ }
void AppendProperty(const std::string& prop, const std::string& value,
bool asString, cmListFileBacktrace const& lfbt);
cmValue GetProperty(const std::string& prop) const;
diff --git a/Source/cmTarget.cxx b/Source/cmTarget.cxx
index 0fbe430..b55554d 100644
--- a/Source/cmTarget.cxx
+++ b/Source/cmTarget.cxx
@@ -1810,26 +1810,7 @@ MAKE_PROP(INTERFACE_LINK_LIBRARIES_DIRECT_EXCLUDE);
#undef MAKE_PROP
}
-namespace {
-// to workaround bug on GCC/AIX
-// Define a template to force conversion to std::string
-template <typename ValueType>
-std::string ConvertToString(ValueType value);
-
-template <>
-std::string ConvertToString<const char*>(const char* value)
-{
- return std::string(value);
-}
-template <>
-std::string ConvertToString<cmValue>(cmValue value)
-{
- return std::string(*value);
-}
-}
-
-template <typename ValueType>
-void cmTarget::StoreProperty(const std::string& prop, ValueType value)
+void cmTarget::SetProperty(const std::string& prop, cmValue value)
{
if (prop == propMANUALLY_ADDED_DEPENDENCIES) {
this->impl->Makefile->IssueMessage(
@@ -1975,7 +1956,7 @@ void cmTarget::StoreProperty(const std::string& prop, ValueType value)
std::string reusedFrom = reusedTarget->GetSafeProperty(prop);
if (reusedFrom.empty()) {
- reusedFrom = ConvertToString(value);
+ reusedFrom = *value;
}
this->impl->Properties.SetProperty(prop, reusedFrom);
@@ -2091,15 +2072,6 @@ void cmTarget::AppendProperty(const std::string& prop,
}
}
-void cmTarget::SetProperty(const std::string& prop, const char* value)
-{
- this->StoreProperty(prop, value);
-}
-void cmTarget::SetProperty(const std::string& prop, cmValue value)
-{
- this->StoreProperty(prop, value);
-}
-
template <typename ValueType>
void cmTargetInternals::AddDirectoryToFileSet(cmTarget* self,
std::string const& fileSetName,
diff --git a/Source/cmTarget.h b/Source/cmTarget.h
index 24f6fcd..5fe5a28 100644
--- a/Source/cmTarget.h
+++ b/Source/cmTarget.h
@@ -180,8 +180,11 @@ public:
std::set<BT<std::pair<std::string, bool>>> const& GetUtilities() const;
//! Set/Get a property of this target file
- void SetProperty(const std::string& prop, const char* value);
void SetProperty(const std::string& prop, cmValue value);
+ void SetProperty(const std::string& prop, std::nullptr_t)
+ {
+ this->SetProperty(prop, cmValue{ nullptr });
+ }
void SetProperty(const std::string& prop, const std::string& value)
{
this->SetProperty(prop, cmValue(value));
diff --git a/Source/cmTest.cxx b/Source/cmTest.cxx
index e6ed01b..b0d9c2d 100644
--- a/Source/cmTest.cxx
+++ b/Source/cmTest.cxx
@@ -52,10 +52,6 @@ bool cmTest::GetPropertyAsBool(const std::string& prop) const
return cmIsOn(this->GetProperty(prop));
}
-void cmTest::SetProperty(const std::string& prop, const char* value)
-{
- this->Properties.SetProperty(prop, value);
-}
void cmTest::SetProperty(const std::string& prop, cmValue value)
{
this->Properties.SetProperty(prop, value);
diff --git a/Source/cmTest.h b/Source/cmTest.h
index 1c14310..8b50b87 100644
--- a/Source/cmTest.h
+++ b/Source/cmTest.h
@@ -4,6 +4,7 @@
#include "cmConfigure.h" // IWYU pragma: keep
+#include <cstddef>
#include <string>
#include <vector>
@@ -34,8 +35,11 @@ public:
std::vector<std::string> const& GetCommand() const { return this->Command; }
//! Set/Get a property of this source file
- void SetProperty(const std::string& prop, const char* value);
void SetProperty(const std::string& prop, cmValue value);
+ void SetProperty(const std::string& prop, std::nullptr_t)
+ {
+ this->SetProperty(prop, cmValue{ nullptr });
+ }
void SetProperty(const std::string& prop, const std::string& value)
{
this->SetProperty(prop, cmValue(value));
diff --git a/Source/cmUVProcessChain.cxx b/Source/cmUVProcessChain.cxx
index 3faf2f6..257c054 100644
--- a/Source/cmUVProcessChain.cxx
+++ b/Source/cmUVProcessChain.cxx
@@ -140,6 +140,19 @@ cmUVProcessChainBuilder& cmUVProcessChainBuilder::SetExternalStream(
return *this;
}
+cmUVProcessChainBuilder& cmUVProcessChainBuilder::SetMergedBuiltinStreams()
+{
+ this->MergedBuiltinStreams = true;
+ return this->SetBuiltinStream(Stream_OUTPUT).SetBuiltinStream(Stream_ERROR);
+}
+
+cmUVProcessChainBuilder& cmUVProcessChainBuilder::SetWorkingDirectory(
+ std::string dir)
+{
+ this->WorkingDirectory = std::move(dir);
+ return *this;
+}
+
cmUVProcessChain cmUVProcessChainBuilder::Start() const
{
cmUVProcessChain chain;
@@ -174,27 +187,6 @@ bool cmUVProcessChain::InternalData::Prepare(
{
this->Builder = builder;
- auto const& output =
- this->Builder->Stdio[cmUVProcessChainBuilder::Stream_OUTPUT];
- auto& outputData = this->OutputStreamData;
- switch (output.Type) {
- case cmUVProcessChainBuilder::None:
- outputData.Stdio.flags = UV_IGNORE;
- break;
-
- case cmUVProcessChainBuilder::Builtin:
- outputData.BuiltinStream.init(*this->Loop, 0);
- outputData.Stdio.flags =
- static_cast<uv_stdio_flags>(UV_CREATE_PIPE | UV_WRITABLE_PIPE);
- outputData.Stdio.data.stream = outputData.BuiltinStream;
- break;
-
- case cmUVProcessChainBuilder::External:
- outputData.Stdio.flags = UV_INHERIT_FD;
- outputData.Stdio.data.fd = output.FileDescriptor;
- break;
- }
-
auto const& error =
this->Builder->Stdio[cmUVProcessChainBuilder::Stream_ERROR];
auto& errorData = this->ErrorStreamData;
@@ -224,6 +216,32 @@ bool cmUVProcessChain::InternalData::Prepare(
break;
}
+ auto const& output =
+ this->Builder->Stdio[cmUVProcessChainBuilder::Stream_OUTPUT];
+ auto& outputData = this->OutputStreamData;
+ switch (output.Type) {
+ case cmUVProcessChainBuilder::None:
+ outputData.Stdio.flags = UV_IGNORE;
+ break;
+
+ case cmUVProcessChainBuilder::Builtin:
+ if (this->Builder->MergedBuiltinStreams) {
+ outputData.Stdio.flags = UV_INHERIT_FD;
+ outputData.Stdio.data.fd = errorData.Stdio.data.fd;
+ } else {
+ outputData.BuiltinStream.init(*this->Loop, 0);
+ outputData.Stdio.flags =
+ static_cast<uv_stdio_flags>(UV_CREATE_PIPE | UV_WRITABLE_PIPE);
+ outputData.Stdio.data.stream = outputData.BuiltinStream;
+ }
+ break;
+
+ case cmUVProcessChainBuilder::External:
+ outputData.Stdio.flags = UV_INHERIT_FD;
+ outputData.Stdio.data.fd = output.FileDescriptor;
+ break;
+ }
+
return true;
}
@@ -248,6 +266,9 @@ bool cmUVProcessChain::InternalData::AddCommand(
arguments.push_back(nullptr);
options.args = const_cast<char**>(arguments.data());
options.flags = UV_PROCESS_WINDOWS_HIDE;
+ if (!this->Builder->WorkingDirectory.empty()) {
+ options.cwd = this->Builder->WorkingDirectory.c_str();
+ }
std::array<uv_stdio_container_t, 3> stdio;
stdio[0] = uv_stdio_container_t();
@@ -289,7 +310,8 @@ bool cmUVProcessChain::InternalData::AddCommand(
bool cmUVProcessChain::InternalData::Finish()
{
if (this->Builder->Stdio[cmUVProcessChainBuilder::Stream_OUTPUT].Type ==
- cmUVProcessChainBuilder::Builtin) {
+ cmUVProcessChainBuilder::Builtin &&
+ !this->Builder->MergedBuiltinStreams) {
this->OutputStreamData.Streambuf.open(
this->OutputStreamData.BuiltinStream);
}
@@ -339,6 +361,9 @@ uv_loop_t& cmUVProcessChain::GetLoop()
std::istream* cmUVProcessChain::OutputStream()
{
+ if (this->Data->Builder->MergedBuiltinStreams) {
+ return this->Data->ErrorStreamData.GetBuiltinStream();
+ }
return this->Data->OutputStreamData.GetBuiltinStream();
}
diff --git a/Source/cmUVProcessChain.h b/Source/cmUVProcessChain.h
index 5e8e7e6..3ade3fd 100644
--- a/Source/cmUVProcessChain.h
+++ b/Source/cmUVProcessChain.h
@@ -30,7 +30,9 @@ public:
const std::vector<std::string>& arguments);
cmUVProcessChainBuilder& SetNoStream(Stream stdio);
cmUVProcessChainBuilder& SetBuiltinStream(Stream stdio);
+ cmUVProcessChainBuilder& SetMergedBuiltinStreams();
cmUVProcessChainBuilder& SetExternalStream(Stream stdio, int fd);
+ cmUVProcessChainBuilder& SetWorkingDirectory(std::string dir);
cmUVProcessChain Start() const;
@@ -57,6 +59,8 @@ private:
std::array<StdioConfiguration, 3> Stdio;
std::vector<ProcessConfiguration> Processes;
+ std::string WorkingDirectory;
+ bool MergedBuiltinStreams = false;
};
class cmUVProcessChain
diff --git a/Source/cmake.cxx b/Source/cmake.cxx
index 0fd7461..3792791 100644
--- a/Source/cmake.cxx
+++ b/Source/cmake.cxx
@@ -38,6 +38,10 @@
#include "cmCMakePresetsGraph.h"
#include "cmCommandLineArgument.h"
#include "cmCommands.h"
+#ifdef CMake_ENABLE_DEBUGGER
+# include "cmDebuggerAdapter.h"
+# include "cmDebuggerPipeConnection.h"
+#endif
#include "cmDocumentation.h"
#include "cmDocumentationEntry.h"
#include "cmDuration.h"
@@ -411,6 +415,11 @@ Json::Value cmake::ReportCapabilitiesJson() const
obj["fileApi"] = cmFileAPI::ReportCapabilities();
obj["serverMode"] = false;
obj["tls"] = static_cast<bool>(curlVersion->features & CURL_VERSION_SSL);
+# ifdef CMake_ENABLE_DEBUGGER
+ obj["debugger"] = true;
+# else
+ obj["debugger"] = false;
+# endif
return obj;
}
@@ -617,6 +626,13 @@ bool cmake::SetCacheArgs(const std::vector<std::string>& args)
};
auto ScriptLambda = [&](std::string const& path, cmake* state) -> bool {
+#ifdef CMake_ENABLE_DEBUGGER
+ // Script mode doesn't hit the usual code path in cmake::Run() that starts
+ // the debugger, so start it manually here instead.
+ if (!this->StartDebuggerIfEnabled()) {
+ return false;
+ }
+#endif
// Register fake project commands that hint misuse in script mode.
GetProjectCommandsInScriptMode(state->GetState());
// Documented behavior of CMAKE{,_CURRENT}_{SOURCE,BINARY}_DIR is to be
@@ -1233,7 +1249,52 @@ void cmake::SetArgs(const std::vector<std::string>& args)
"CMAKE_COMPILE_WARNING_AS_ERROR variable.\n";
state->SetIgnoreWarningAsError(true);
return true;
- } }
+ } },
+ CommandArgument{ "--debugger", CommandArgument::Values::Zero,
+ [](std::string const&, cmake* state) -> bool {
+#ifdef CMake_ENABLE_DEBUGGER
+ std::cout << "Running with debugger on.\n";
+ state->SetDebuggerOn(true);
+ return true;
+#else
+ static_cast<void>(state);
+ cmSystemTools::Error(
+ "CMake was not built with support for --debugger");
+ return false;
+#endif
+ } },
+ CommandArgument{ "--debugger-pipe",
+ "No path specified for --debugger-pipe",
+ CommandArgument::Values::One,
+ [](std::string const& value, cmake* state) -> bool {
+#ifdef CMake_ENABLE_DEBUGGER
+ state->DebuggerPipe = value;
+ return true;
+#else
+ static_cast<void>(value);
+ static_cast<void>(state);
+ cmSystemTools::Error("CMake was not built with support "
+ "for --debugger-pipe");
+ return false;
+#endif
+ } },
+ CommandArgument{
+ "--debugger-dap-log", "No file specified for --debugger-dap-log",
+ CommandArgument::Values::One,
+ [](std::string const& value, cmake* state) -> bool {
+#ifdef CMake_ENABLE_DEBUGGER
+ std::string path = cmSystemTools::CollapseFullPath(value);
+ cmSystemTools::ConvertToUnixSlashes(path);
+ state->DebuggerDapLogFile = path;
+ return true;
+#else
+ static_cast<void>(value);
+ static_cast<void>(state);
+ cmSystemTools::Error(
+ "CMake was not built with support for --debugger-dap-log");
+ return false;
+#endif
+ } },
};
#if defined(CMAKE_HAVE_VS_GENERATORS)
@@ -2138,12 +2199,10 @@ int cmake::DoPreConfigureChecks()
std::string cacheStart =
cmStrCat(*this->State->GetInitializedCacheValue("CMAKE_HOME_DIRECTORY"),
"/CMakeLists.txt");
- std::string currentStart =
- cmStrCat(this->GetHomeDirectory(), "/CMakeLists.txt");
- if (!cmSystemTools::SameFile(cacheStart, currentStart)) {
+ if (!cmSystemTools::SameFile(cacheStart, srcList)) {
std::string message =
- cmStrCat("The source \"", currentStart,
- "\" does not match the source \"", cacheStart,
+ cmStrCat("The source \"", srcList, "\" does not match the source \"",
+ cacheStart,
"\" used to generate cache. Re-run cmake with a different "
"source directory.");
cmSystemTools::Error(message);
@@ -2371,16 +2430,16 @@ int cmake::ActualConfigure()
cmValue genName = this->State->GetInitializedCacheValue("CMAKE_GENERATOR");
if (genName) {
if (!this->GlobalGenerator->MatchesGeneratorName(*genName)) {
- std::string message =
- cmStrCat("Error: generator : ", this->GlobalGenerator->GetName(),
- "\nDoes not match the generator used previously: ", *genName,
- "\nEither remove the CMakeCache.txt file and CMakeFiles "
- "directory or choose a different binary directory.");
+ std::string message = cmStrCat(
+ "Error: generator : ", this->GlobalGenerator->GetName(), '\n',
+ "Does not match the generator used previously: ", *genName, '\n',
+ "Either remove the CMakeCache.txt file and CMakeFiles "
+ "directory or choose a different binary directory.");
cmSystemTools::Error(message);
return -2;
}
}
- if (!this->State->GetInitializedCacheValue("CMAKE_GENERATOR")) {
+ if (!genName) {
this->AddCacheEntry("CMAKE_GENERATOR", this->GlobalGenerator->GetName(),
"Name of generator.", cmStateEnums::INTERNAL);
this->AddCacheEntry(
@@ -2401,11 +2460,11 @@ int cmake::ActualConfigure()
if (cmValue instance =
this->State->GetInitializedCacheValue("CMAKE_GENERATOR_INSTANCE")) {
if (this->GeneratorInstanceSet && this->GeneratorInstance != *instance) {
- std::string message =
- cmStrCat("Error: generator instance: ", this->GeneratorInstance,
- "\nDoes not match the instance used previously: ", *instance,
- "\nEither remove the CMakeCache.txt file and CMakeFiles "
- "directory or choose a different binary directory.");
+ std::string message = cmStrCat(
+ "Error: generator instance: ", this->GeneratorInstance, '\n',
+ "Does not match the instance used previously: ", *instance, '\n',
+ "Either remove the CMakeCache.txt file and CMakeFiles "
+ "directory or choose a different binary directory.");
cmSystemTools::Error(message);
return -2;
}
@@ -2420,9 +2479,9 @@ int cmake::ActualConfigure()
if (this->GeneratorPlatformSet &&
this->GeneratorPlatform != *platformName) {
std::string message = cmStrCat(
- "Error: generator platform: ", this->GeneratorPlatform,
- "\nDoes not match the platform used previously: ", *platformName,
- "\nEither remove the CMakeCache.txt file and CMakeFiles "
+ "Error: generator platform: ", this->GeneratorPlatform, '\n',
+ "Does not match the platform used previously: ", *platformName, '\n',
+ "Either remove the CMakeCache.txt file and CMakeFiles "
"directory or choose a different binary directory.");
cmSystemTools::Error(message);
return -2;
@@ -2436,9 +2495,9 @@ int cmake::ActualConfigure()
this->State->GetInitializedCacheValue("CMAKE_GENERATOR_TOOLSET")) {
if (this->GeneratorToolsetSet && this->GeneratorToolset != *tsName) {
std::string message =
- cmStrCat("Error: generator toolset: ", this->GeneratorToolset,
- "\nDoes not match the toolset used previously: ", *tsName,
- "\nEither remove the CMakeCache.txt file and CMakeFiles "
+ cmStrCat("Error: generator toolset: ", this->GeneratorToolset, '\n',
+ "Does not match the toolset used previously: ", *tsName, '\n',
+ "Either remove the CMakeCache.txt file and CMakeFiles "
"directory or choose a different binary directory.");
cmSystemTools::Error(message);
return -2;
@@ -2620,6 +2679,52 @@ void cmake::PreLoadCMakeFiles()
}
}
+#ifdef CMake_ENABLE_DEBUGGER
+
+bool cmake::StartDebuggerIfEnabled()
+{
+ if (!this->GetDebuggerOn()) {
+ return true;
+ }
+
+ if (DebugAdapter == nullptr) {
+ if (this->GetDebuggerPipe().empty()) {
+ std::cerr
+ << "Error: --debugger-pipe must be set when debugging is enabled.\n";
+ return false;
+ }
+
+ try {
+ DebugAdapter = std::make_shared<cmDebugger::cmDebuggerAdapter>(
+ std::make_shared<cmDebugger::cmDebuggerPipeConnection>(
+ this->GetDebuggerPipe()),
+ this->GetDebuggerDapLogFile());
+ } catch (const std::runtime_error& error) {
+ std::cerr << "Error: Failed to create debugger adapter.\n";
+ std::cerr << error.what() << "\n";
+ return false;
+ }
+ Messenger->SetDebuggerAdapter(DebugAdapter);
+ }
+
+ return true;
+}
+
+void cmake::StopDebuggerIfNeeded(int exitCode)
+{
+ if (!this->GetDebuggerOn()) {
+ return;
+ }
+
+ // The debug adapter may have failed to start (e.g. invalid pipe path).
+ if (DebugAdapter != nullptr) {
+ DebugAdapter->ReportExitCode(exitCode);
+ DebugAdapter.reset();
+ }
+}
+
+#endif
+
// handle a command line invocation
int cmake::Run(const std::vector<std::string>& args, bool noconfigure)
{
@@ -2709,6 +2814,12 @@ int cmake::Run(const std::vector<std::string>& args, bool noconfigure)
return 0;
}
+#ifdef CMake_ENABLE_DEBUGGER
+ if (!this->StartDebuggerIfEnabled()) {
+ return -1;
+ }
+#endif
+
int ret = this->Configure();
if (ret) {
#if defined(CMAKE_HAVE_VS_GENERATORS)
@@ -3263,10 +3374,6 @@ void cmake::GenerateGraphViz(const std::string& fileName) const
#endif
}
-void cmake::SetProperty(const std::string& prop, const char* value)
-{
- this->State->SetGlobalProperty(prop, value);
-}
void cmake::SetProperty(const std::string& prop, cmValue value)
{
this->State->SetGlobalProperty(prop, value);
@@ -3625,7 +3732,6 @@ int cmake::Build(int jobs, std::string dir, std::vector<std::string> targets,
return 1;
}
}
- std::string output;
std::string projName;
cmValue cachedProjectName =
this->State->GetCacheEntryValue("CMAKE_PROJECT_NAME");
@@ -3699,10 +3805,17 @@ int cmake::Build(int jobs, std::string dir, std::vector<std::string> targets,
}
this->GlobalGenerator->PrintBuildCommandAdvice(std::cerr, jobs);
- return this->GlobalGenerator->Build(
- jobs, "", dir, projName, targets, output, "", config, buildOptions,
+ std::stringstream ostr;
+ // `cmGlobalGenerator::Build` logs metadata about what directory and commands
+ // are being executed to the `output` parameter. If CMake is verbose, print
+ // this out.
+ std::ostream& verbose_ostr = verbose ? std::cout : ostr;
+ int buildresult = this->GlobalGenerator->Build(
+ jobs, "", dir, projName, targets, verbose_ostr, "", config, buildOptions,
verbose, cmDuration::zero(), cmSystemTools::OUTPUT_PASSTHROUGH,
nativeOptions);
+
+ return buildresult;
}
bool cmake::Open(const std::string& dir, bool dryRun)
diff --git a/Source/cmake.h b/Source/cmake.h
index 0f8f642..d394a3e 100644
--- a/Source/cmake.h
+++ b/Source/cmake.h
@@ -37,6 +37,13 @@
#endif
class cmConfigureLog;
+
+#ifdef CMake_ENABLE_DEBUGGER
+namespace cmDebugger {
+class cmDebuggerAdapter;
+}
+#endif
+
class cmExternalMakefileProjectGeneratorFactory;
class cmFileAPI;
class cmFileTimeCache;
@@ -404,8 +411,11 @@ public:
std::vector<cmDocumentationEntry> GetGeneratorsDocumentation();
//! Set/Get a property of this target file
- void SetProperty(const std::string& prop, const char* value);
void SetProperty(const std::string& prop, cmValue value);
+ void SetProperty(const std::string& prop, std::nullptr_t)
+ {
+ this->SetProperty(prop, cmValue{ nullptr });
+ }
void SetProperty(const std::string& prop, const std::string& value)
{
this->SetProperty(prop, cmValue(value));
@@ -659,6 +669,23 @@ public:
}
#endif
+#ifdef CMake_ENABLE_DEBUGGER
+ bool GetDebuggerOn() const { return this->DebuggerOn; }
+ std::string GetDebuggerPipe() const { return this->DebuggerPipe; }
+ std::string GetDebuggerDapLogFile() const
+ {
+ return this->DebuggerDapLogFile;
+ }
+ void SetDebuggerOn(bool b) { this->DebuggerOn = b; }
+ bool StartDebuggerIfEnabled();
+ void StopDebuggerIfNeeded(int exitCode);
+ std::shared_ptr<cmDebugger::cmDebuggerAdapter> GetDebugAdapter()
+ const noexcept
+ {
+ return this->DebugAdapter;
+ }
+#endif
+
protected:
void RunCheckForUnusedVariables();
int HandleDeleteCacheVariables(const std::string& var);
@@ -799,6 +826,13 @@ private:
std::unique_ptr<cmMakefileProfilingData> ProfilingOutput;
#endif
+#ifdef CMake_ENABLE_DEBUGGER
+ std::shared_ptr<cmDebugger::cmDebuggerAdapter> DebugAdapter;
+ bool DebuggerOn = false;
+ std::string DebuggerPipe;
+ std::string DebuggerDapLogFile;
+#endif
+
public:
static cmDocumentationEntry CMAKE_STANDARD_OPTIONS_TABLE[18];
};
diff --git a/Source/cmakemain.cxx b/Source/cmakemain.cxx
index ad27443..ced83dc 100644
--- a/Source/cmakemain.cxx
+++ b/Source/cmakemain.cxx
@@ -392,8 +392,14 @@ int do_cmake(int ac, char const* const* av)
// Always return a non-negative value. Windows tools do not always
// interpret negative return values as errors.
if (res != 0) {
+#ifdef CMake_ENABLE_DEBUGGER
+ cm.StopDebuggerIfNeeded(1);
+#endif
return 1;
}
+#ifdef CMake_ENABLE_DEBUGGER
+ cm.StopDebuggerIfNeeded(0);
+#endif
return 0;
}
diff --git a/Source/kwsys/RegularExpression.cxx b/Source/kwsys/RegularExpression.cxx
index f2f5143..b51e16d 100644
--- a/Source/kwsys/RegularExpression.cxx
+++ b/Source/kwsys/RegularExpression.cxx
@@ -378,6 +378,10 @@ bool RegularExpression::compile(const char* exp)
return false;
}
+#ifdef __clang_analyzer__ /* Convince it that the program is initialized. */
+ memset(this->program, 0, comp.regsize);
+#endif
+
// Second pass: emit code.
comp.regparse = exp;
comp.regnpar = 1;
diff --git a/Source/kwsys/SystemInformation.cxx b/Source/kwsys/SystemInformation.cxx
index 20e2edb..7f8485e 100644
--- a/Source/kwsys/SystemInformation.cxx
+++ b/Source/kwsys/SystemInformation.cxx
@@ -3453,6 +3453,10 @@ bool SystemInformationImplementation::RetrieveInformationFromCpuInfoFile()
fileSize++;
}
fclose(fd);
+ if (fileSize < 2) {
+ std::cout << "No data in /proc/cpuinfo" << std::endl;
+ return false;
+ }
buffer.resize(fileSize - 2);
// Number of logical CPUs (combination of multiple processors, multi-core
// and SMT)
diff --git a/Tests/CMakeLib/CMakeLists.txt b/Tests/CMakeLib/CMakeLists.txt
index 0fc3deb..5c14de2 100644
--- a/Tests/CMakeLib/CMakeLists.txt
+++ b/Tests/CMakeLib/CMakeLists.txt
@@ -32,11 +32,22 @@ set(CMakeLib_TESTS
testCMExtEnumSet.cxx
testList.cxx
)
+if(CMake_ENABLE_DEBUGGER)
+ list(APPEND CMakeLib_TESTS
+ testDebuggerAdapter.cxx
+ testDebuggerAdapterPipe.cxx
+ testDebuggerBreakpointManager.cxx
+ testDebuggerVariables.cxx
+ testDebuggerVariablesHelper.cxx
+ testDebuggerVariablesManager.cxx
+ )
+endif()
if (CMake_TEST_FILESYSTEM_PATH OR NOT CMake_HAVE_CXX_FILESYSTEM)
list(APPEND CMakeLib_TESTS testCMFilesystemPath.cxx)
endif()
add_executable(testUVProcessChainHelper testUVProcessChainHelper.cxx)
+target_link_libraries(testUVProcessChainHelper CMakeLib)
set(testRST_ARGS ${CMAKE_CURRENT_SOURCE_DIR})
set(testUVProcessChain_ARGS $<TARGET_FILE:testUVProcessChainHelper>)
@@ -77,3 +88,18 @@ add_subdirectory(PseudoMemcheck)
add_executable(testAffinity testAffinity.cxx)
target_link_libraries(testAffinity CMakeLib)
+
+if(CMake_ENABLE_DEBUGGER)
+ add_executable(testDebuggerNamedPipe testDebuggerNamedPipe.cxx)
+ target_link_libraries(testDebuggerNamedPipe PRIVATE CMakeLib)
+ set(testDebuggerNamedPipe_Project_ARGS
+ "$<TARGET_FILE:cmake>" ${CMAKE_CURRENT_SOURCE_DIR}/DebuggerSample ${CMAKE_CURRENT_BINARY_DIR}/DebuggerSample
+ )
+ set(testDebuggerNamedPipe_Script_ARGS
+ "$<TARGET_FILE:cmake>" ${CMAKE_CURRENT_SOURCE_DIR}/DebuggerSample/script.cmake
+ )
+ foreach(case Project Script)
+ add_test(NAME CMakeLib.testDebuggerNamedPipe-${case} COMMAND testDebuggerNamedPipe ${testDebuggerNamedPipe_${case}_ARGS})
+ set_property(TEST CMakeLib.testDebuggerNamedPipe-${case} PROPERTY TIMEOUT 300)
+ endforeach()
+endif()
diff --git a/Tests/CMakeLib/DebuggerSample/CMakeLists.txt b/Tests/CMakeLib/DebuggerSample/CMakeLists.txt
new file mode 100644
index 0000000..8f8603a
--- /dev/null
+++ b/Tests/CMakeLib/DebuggerSample/CMakeLists.txt
@@ -0,0 +1,9 @@
+cmake_minimum_required(VERSION 3.26)
+project(DebuggerSample NONE)
+message("Hello CMake Debugger")
+
+# There are concerns that because the debugger uses libuv for pipe
+# communication, libuv may register a SIGCHILD handler that interferes with
+# the existing handler used by kwsys process management. Test this case with a
+# simple external process.
+execute_process(COMMAND "${CMAKE_COMMAND}" -E echo test)
diff --git a/Tests/CMakeLib/DebuggerSample/script.cmake b/Tests/CMakeLib/DebuggerSample/script.cmake
new file mode 100644
index 0000000..4c0c00a
--- /dev/null
+++ b/Tests/CMakeLib/DebuggerSample/script.cmake
@@ -0,0 +1 @@
+message(STATUS "This is an example script")
diff --git a/Tests/CMakeLib/testCommon.h b/Tests/CMakeLib/testCommon.h
new file mode 100644
index 0000000..bd2d54e
--- /dev/null
+++ b/Tests/CMakeLib/testCommon.h
@@ -0,0 +1,30 @@
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
+#pragma once
+
+#include <functional>
+#include <iostream>
+#include <vector>
+
+#define ASSERT_TRUE(x) \
+ do { \
+ if (!(x)) { \
+ std::cout << "ASSERT_TRUE(" #x ") failed on line " << __LINE__ << "\n"; \
+ return false; \
+ } \
+ } while (false)
+
+inline int runTests(std::vector<std::function<bool()>> const& tests)
+{
+ for (auto const& test : tests) {
+ if (!test()) {
+ return 1;
+ }
+ std::cout << ".";
+ }
+
+ std::cout << " Passed" << std::endl;
+ return 0;
+}
+
+#define BOOL_STRING(b) ((b) ? "TRUE" : "FALSE")
diff --git a/Tests/CMakeLib/testDebugger.h b/Tests/CMakeLib/testDebugger.h
new file mode 100644
index 0000000..8ba21f6
--- /dev/null
+++ b/Tests/CMakeLib/testDebugger.h
@@ -0,0 +1,99 @@
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
+#pragma once
+
+#include <memory>
+#include <vector>
+
+#include "cmDebuggerAdapter.h"
+#include "cmDebuggerProtocol.h"
+#include "cmListFileCache.h"
+#include "cmMessenger.h"
+#include <cmcppdap/include/dap/io.h>
+#include <cmcppdap/include/dap/session.h>
+#include <cmcppdap/include/dap/types.h>
+
+#include "testCommon.h"
+
+#define ASSERT_VARIABLE(x, expectedName, expectedValue, expectedType) \
+ do { \
+ ASSERT_TRUE(x.name == expectedName); \
+ ASSERT_TRUE(x.value == expectedValue); \
+ ASSERT_TRUE(x.type.value() == expectedType); \
+ ASSERT_TRUE(x.evaluateName.has_value() == false); \
+ if (std::string(expectedType) == "collection") { \
+ ASSERT_TRUE(x.variablesReference != 0); \
+ } \
+ } while (false)
+
+#define ASSERT_VARIABLE_REFERENCE(x, expectedName, expectedValue, \
+ expectedType, expectedReference) \
+ do { \
+ ASSERT_VARIABLE(x, expectedName, expectedValue, expectedType); \
+ ASSERT_TRUE(x.variablesReference == (expectedReference)); \
+ } while (false)
+
+#define ASSERT_VARIABLE_REFERENCE_NOT_ZERO(x, expectedName, expectedValue, \
+ expectedType) \
+ do { \
+ ASSERT_VARIABLE(x, expectedName, expectedValue, expectedType); \
+ ASSERT_TRUE(x.variablesReference != 0); \
+ } while (false)
+
+#define ASSERT_BREAKPOINT(x, expectedId, expectedLine, sourcePath, \
+ isVerified) \
+ do { \
+ ASSERT_TRUE(x.id.has_value()); \
+ ASSERT_TRUE(x.id.value() == expectedId); \
+ ASSERT_TRUE(x.line.has_value()); \
+ ASSERT_TRUE(x.line.value() == expectedLine); \
+ ASSERT_TRUE(x.source.has_value()); \
+ ASSERT_TRUE(x.source.value().path.has_value()); \
+ ASSERT_TRUE(x.source.value().path.value() == sourcePath); \
+ ASSERT_TRUE(x.verified == isVerified); \
+ } while (false)
+
+class DebuggerTestHelper
+{
+ std::shared_ptr<dap::ReaderWriter> Client2Debugger = dap::pipe();
+ std::shared_ptr<dap::ReaderWriter> Debugger2Client = dap::pipe();
+
+public:
+ std::unique_ptr<dap::Session> Client = dap::Session::create();
+ std::unique_ptr<dap::Session> Debugger = dap::Session::create();
+ void bind()
+ {
+ auto client2server = dap::pipe();
+ auto server2client = dap::pipe();
+ Client->bind(server2client, client2server);
+ Debugger->bind(client2server, server2client);
+ }
+ std::vector<cmListFileFunction> CreateListFileFunctions(const char* str,
+ const char* filename)
+ {
+ cmMessenger messenger;
+ cmListFileBacktrace backtrace;
+ cmListFile listfile;
+ listfile.ParseString(str, filename, &messenger, backtrace);
+ return listfile.Functions;
+ }
+};
+
+class ScopedThread
+{
+public:
+ template <class... Args>
+ explicit ScopedThread(Args&&... args)
+ : Thread(std::forward<Args>(args)...)
+ {
+ }
+
+ ~ScopedThread()
+ {
+ if (Thread.joinable())
+ Thread.join();
+ }
+
+private:
+ std::thread Thread;
+};
diff --git a/Tests/CMakeLib/testDebuggerAdapter.cxx b/Tests/CMakeLib/testDebuggerAdapter.cxx
new file mode 100644
index 0000000..394986b
--- /dev/null
+++ b/Tests/CMakeLib/testDebuggerAdapter.cxx
@@ -0,0 +1,173 @@
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
+
+#include <chrono>
+#include <cstdio>
+#include <functional>
+#include <future>
+#include <memory>
+#include <string>
+#include <vector>
+
+#include <cm3p/cppdap/future.h>
+#include <cm3p/cppdap/io.h>
+#include <cm3p/cppdap/optional.h>
+#include <cm3p/cppdap/protocol.h>
+#include <cm3p/cppdap/session.h>
+#include <cm3p/cppdap/types.h>
+
+#include "cmDebuggerAdapter.h"
+#include "cmDebuggerProtocol.h"
+#include "cmVersionConfig.h"
+
+#include "testCommon.h"
+#include "testDebugger.h"
+
+class DebuggerLocalConnection : public cmDebugger::cmDebuggerConnection
+{
+public:
+ DebuggerLocalConnection()
+ : ClientToDebugger(dap::pipe())
+ , DebuggerToClient(dap::pipe())
+ {
+ }
+
+ bool StartListening(std::string& errorMessage) override
+ {
+ errorMessage = "";
+ return true;
+ }
+ void WaitForConnection() override {}
+
+ std::shared_ptr<dap::Reader> GetReader() override
+ {
+ return ClientToDebugger;
+ };
+
+ std::shared_ptr<dap::Writer> GetWriter() override
+ {
+ return DebuggerToClient;
+ }
+
+ std::shared_ptr<dap::ReaderWriter> ClientToDebugger;
+ std::shared_ptr<dap::ReaderWriter> DebuggerToClient;
+};
+
+bool testBasicProtocol()
+{
+ std::promise<bool> debuggerAdapterInitializedPromise;
+ std::future<bool> debuggerAdapterInitializedFuture =
+ debuggerAdapterInitializedPromise.get_future();
+
+ std::promise<bool> initializedEventReceivedPromise;
+ std::future<bool> initializedEventReceivedFuture =
+ initializedEventReceivedPromise.get_future();
+
+ std::promise<bool> exitedEventReceivedPromise;
+ std::future<bool> exitedEventReceivedFuture =
+ exitedEventReceivedPromise.get_future();
+
+ std::promise<bool> terminatedEventReceivedPromise;
+ std::future<bool> terminatedEventReceivedFuture =
+ terminatedEventReceivedPromise.get_future();
+
+ std::promise<bool> threadStartedPromise;
+ std::future<bool> threadStartedFuture = threadStartedPromise.get_future();
+
+ std::promise<bool> threadExitedPromise;
+ std::future<bool> threadExitedFuture = threadExitedPromise.get_future();
+
+ std::promise<bool> disconnectResponseReceivedPromise;
+ std::future<bool> disconnectResponseReceivedFuture =
+ disconnectResponseReceivedPromise.get_future();
+
+ auto futureTimeout = std::chrono::seconds(60);
+
+ auto connection = std::make_shared<DebuggerLocalConnection>();
+ std::unique_ptr<dap::Session> client = dap::Session::create();
+ client->registerHandler([&](const dap::InitializedEvent& e) {
+ (void)e;
+ initializedEventReceivedPromise.set_value(true);
+ });
+ client->registerHandler([&](const dap::ExitedEvent& e) {
+ (void)e;
+ exitedEventReceivedPromise.set_value(true);
+ });
+ client->registerHandler([&](const dap::TerminatedEvent& e) {
+ (void)e;
+ terminatedEventReceivedPromise.set_value(true);
+ });
+ client->registerHandler([&](const dap::ThreadEvent& e) {
+ if (e.reason == "started") {
+ threadStartedPromise.set_value(true);
+ } else if (e.reason == "exited") {
+ threadExitedPromise.set_value(true);
+ }
+ });
+
+ client->bind(connection->DebuggerToClient, connection->ClientToDebugger);
+
+ ScopedThread debuggerThread([&]() -> int {
+ std::shared_ptr<cmDebugger::cmDebuggerAdapter> debuggerAdapter =
+ std::make_shared<cmDebugger::cmDebuggerAdapter>(
+ connection, dap::file(stdout, false));
+
+ debuggerAdapterInitializedPromise.set_value(true);
+ debuggerAdapter->ReportExitCode(0);
+
+ // Ensure the disconnectResponse has been received before
+ // destructing debuggerAdapter.
+ ASSERT_TRUE(disconnectResponseReceivedFuture.wait_for(futureTimeout) ==
+ std::future_status::ready);
+ return 0;
+ });
+
+ dap::CMakeInitializeRequest initializeRequest;
+ auto initializeResponse = client->send(initializeRequest).get();
+ ASSERT_TRUE(initializeResponse.response.cmakeVersion.full == CMake_VERSION);
+ ASSERT_TRUE(initializeResponse.response.cmakeVersion.major ==
+ CMake_VERSION_MAJOR);
+ ASSERT_TRUE(initializeResponse.response.cmakeVersion.minor ==
+ CMake_VERSION_MINOR);
+ ASSERT_TRUE(initializeResponse.response.cmakeVersion.patch ==
+ CMake_VERSION_PATCH);
+ ASSERT_TRUE(initializeResponse.response.supportsExceptionInfoRequest);
+ ASSERT_TRUE(
+ initializeResponse.response.exceptionBreakpointFilters.has_value());
+
+ dap::LaunchRequest launchRequest;
+ auto launchResponse = client->send(launchRequest).get();
+ ASSERT_TRUE(!launchResponse.error);
+
+ dap::ConfigurationDoneRequest configurationDoneRequest;
+ auto configurationDoneResponse =
+ client->send(configurationDoneRequest).get();
+ ASSERT_TRUE(!configurationDoneResponse.error);
+
+ ASSERT_TRUE(debuggerAdapterInitializedFuture.wait_for(futureTimeout) ==
+ std::future_status::ready);
+ ASSERT_TRUE(initializedEventReceivedFuture.wait_for(futureTimeout) ==
+ std::future_status::ready);
+ ASSERT_TRUE(threadStartedFuture.wait_for(futureTimeout) ==
+ std::future_status::ready);
+ ASSERT_TRUE(threadExitedFuture.wait_for(futureTimeout) ==
+ std::future_status::ready);
+ ASSERT_TRUE(exitedEventReceivedFuture.wait_for(futureTimeout) ==
+ std::future_status::ready);
+ ASSERT_TRUE(terminatedEventReceivedFuture.wait_for(futureTimeout) ==
+ std::future_status::ready);
+
+ dap::DisconnectRequest disconnectRequest;
+ auto disconnectResponse = client->send(disconnectRequest).get();
+ disconnectResponseReceivedPromise.set_value(true);
+ ASSERT_TRUE(!disconnectResponse.error);
+
+ return true;
+}
+
+int testDebuggerAdapter(int, char*[])
+{
+ return runTests(std::vector<std::function<bool()>>{
+ testBasicProtocol,
+ });
+}
diff --git a/Tests/CMakeLib/testDebuggerAdapterPipe.cxx b/Tests/CMakeLib/testDebuggerAdapterPipe.cxx
new file mode 100644
index 0000000..643661d
--- /dev/null
+++ b/Tests/CMakeLib/testDebuggerAdapterPipe.cxx
@@ -0,0 +1,184 @@
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
+
+#include <chrono>
+#include <cstdio>
+#include <functional>
+#include <future>
+#include <iostream>
+#include <memory>
+#include <stdexcept>
+#include <string>
+#include <vector>
+
+#include <cm3p/cppdap/future.h>
+#include <cm3p/cppdap/io.h>
+#include <cm3p/cppdap/optional.h>
+#include <cm3p/cppdap/protocol.h>
+#include <cm3p/cppdap/session.h>
+#include <cm3p/cppdap/types.h>
+
+#include "cmDebuggerAdapter.h"
+#include "cmDebuggerPipeConnection.h"
+#include "cmDebuggerProtocol.h"
+#include "cmVersionConfig.h"
+
+#ifdef _WIN32
+# include "cmCryptoHash.h"
+# include "cmSystemTools.h"
+#endif
+
+#include "testCommon.h"
+#include "testDebugger.h"
+
+bool testProtocolWithPipes()
+{
+ std::promise<void> debuggerConnectionCreatedPromise;
+ std::future<void> debuggerConnectionCreatedFuture =
+ debuggerConnectionCreatedPromise.get_future();
+
+ std::future<void> startedListeningFuture;
+
+ std::promise<bool> debuggerAdapterInitializedPromise;
+ std::future<bool> debuggerAdapterInitializedFuture =
+ debuggerAdapterInitializedPromise.get_future();
+
+ std::promise<bool> initializedEventReceivedPromise;
+ std::future<bool> initializedEventReceivedFuture =
+ initializedEventReceivedPromise.get_future();
+
+ std::promise<bool> exitedEventReceivedPromise;
+ std::future<bool> exitedEventReceivedFuture =
+ exitedEventReceivedPromise.get_future();
+
+ std::promise<bool> terminatedEventReceivedPromise;
+ std::future<bool> terminatedEventReceivedFuture =
+ terminatedEventReceivedPromise.get_future();
+
+ std::promise<bool> threadStartedPromise;
+ std::future<bool> threadStartedFuture = threadStartedPromise.get_future();
+
+ std::promise<bool> threadExitedPromise;
+ std::future<bool> threadExitedFuture = threadExitedPromise.get_future();
+
+ std::promise<bool> disconnectResponseReceivedPromise;
+ std::future<bool> disconnectResponseReceivedFuture =
+ disconnectResponseReceivedPromise.get_future();
+
+ auto futureTimeout = std::chrono::seconds(60);
+
+#ifdef _WIN32
+ std::string namedPipe = R"(\\.\pipe\LOCAL\CMakeDebuggerPipe2_)" +
+ cmCryptoHash(cmCryptoHash::AlgoSHA256)
+ .HashString(cmSystemTools::GetCurrentWorkingDirectory());
+#else
+ std::string namedPipe = "CMakeDebuggerPipe2";
+#endif
+
+ std::unique_ptr<dap::Session> client = dap::Session::create();
+ client->registerHandler([&](const dap::InitializedEvent& e) {
+ (void)e;
+ initializedEventReceivedPromise.set_value(true);
+ });
+ client->registerHandler([&](const dap::ExitedEvent& e) {
+ (void)e;
+ exitedEventReceivedPromise.set_value(true);
+ });
+ client->registerHandler([&](const dap::TerminatedEvent& e) {
+ (void)e;
+ terminatedEventReceivedPromise.set_value(true);
+ });
+ client->registerHandler([&](const dap::ThreadEvent& e) {
+ if (e.reason == "started") {
+ threadStartedPromise.set_value(true);
+ } else if (e.reason == "exited") {
+ threadExitedPromise.set_value(true);
+ }
+ });
+
+ ScopedThread debuggerThread([&]() -> int {
+ try {
+ auto connection =
+ std::make_shared<cmDebugger::cmDebuggerPipeConnection>(namedPipe);
+ startedListeningFuture = connection->StartedListening.get_future();
+ debuggerConnectionCreatedPromise.set_value();
+ std::shared_ptr<cmDebugger::cmDebuggerAdapter> debuggerAdapter =
+ std::make_shared<cmDebugger::cmDebuggerAdapter>(
+ connection, dap::file(stdout, false));
+
+ debuggerAdapterInitializedPromise.set_value(true);
+ debuggerAdapter->ReportExitCode(0);
+
+ // Ensure the disconnectResponse has been received before
+ // destructing debuggerAdapter.
+ ASSERT_TRUE(disconnectResponseReceivedFuture.wait_for(futureTimeout) ==
+ std::future_status::ready);
+ return 0;
+ } catch (const std::runtime_error& error) {
+ std::cerr << "Error: Failed to create debugger adapter.\n";
+ std::cerr << error.what() << "\n";
+ return -1;
+ }
+ });
+
+ ASSERT_TRUE(debuggerConnectionCreatedFuture.wait_for(futureTimeout) ==
+ std::future_status::ready);
+ ASSERT_TRUE(startedListeningFuture.wait_for(futureTimeout) ==
+ std::future_status::ready);
+
+ auto client2Debugger =
+ std::make_shared<cmDebugger::cmDebuggerPipeClient>(namedPipe);
+ client2Debugger->Start();
+ client2Debugger->WaitForConnection();
+ client->bind(client2Debugger, client2Debugger);
+
+ dap::CMakeInitializeRequest initializeRequest;
+ auto response = client->send(initializeRequest);
+ auto initializeResponse = response.get();
+ ASSERT_TRUE(!initializeResponse.error);
+ ASSERT_TRUE(initializeResponse.response.cmakeVersion.full == CMake_VERSION);
+ ASSERT_TRUE(initializeResponse.response.cmakeVersion.major ==
+ CMake_VERSION_MAJOR);
+ ASSERT_TRUE(initializeResponse.response.cmakeVersion.minor ==
+ CMake_VERSION_MINOR);
+ ASSERT_TRUE(initializeResponse.response.cmakeVersion.patch ==
+ CMake_VERSION_PATCH);
+ ASSERT_TRUE(initializeResponse.response.supportsExceptionInfoRequest);
+ ASSERT_TRUE(
+ initializeResponse.response.exceptionBreakpointFilters.has_value());
+ dap::LaunchRequest launchRequest;
+ auto launchResponse = client->send(launchRequest).get();
+ ASSERT_TRUE(!launchResponse.error);
+
+ dap::ConfigurationDoneRequest configurationDoneRequest;
+ auto configurationDoneResponse =
+ client->send(configurationDoneRequest).get();
+ ASSERT_TRUE(!configurationDoneResponse.error);
+
+ ASSERT_TRUE(debuggerAdapterInitializedFuture.wait_for(futureTimeout) ==
+ std::future_status::ready);
+ ASSERT_TRUE(initializedEventReceivedFuture.wait_for(futureTimeout) ==
+ std::future_status::ready);
+ ASSERT_TRUE(terminatedEventReceivedFuture.wait_for(futureTimeout) ==
+ std::future_status::ready);
+ ASSERT_TRUE(threadStartedFuture.wait_for(futureTimeout) ==
+ std::future_status::ready);
+ ASSERT_TRUE(threadExitedFuture.wait_for(futureTimeout) ==
+ std::future_status::ready);
+ ASSERT_TRUE(exitedEventReceivedFuture.wait_for(futureTimeout) ==
+ std::future_status::ready);
+
+ dap::DisconnectRequest disconnectRequest;
+ auto disconnectResponse = client->send(disconnectRequest).get();
+ disconnectResponseReceivedPromise.set_value(true);
+ ASSERT_TRUE(!disconnectResponse.error);
+
+ return true;
+}
+
+int testDebuggerAdapterPipe(int, char*[])
+{
+ return runTests(std::vector<std::function<bool()>>{
+ testProtocolWithPipes,
+ });
+}
diff --git a/Tests/CMakeLib/testDebuggerBreakpointManager.cxx b/Tests/CMakeLib/testDebuggerBreakpointManager.cxx
new file mode 100644
index 0000000..83734ea
--- /dev/null
+++ b/Tests/CMakeLib/testDebuggerBreakpointManager.cxx
@@ -0,0 +1,172 @@
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
+
+#include <atomic>
+#include <chrono>
+#include <functional>
+#include <future>
+#include <memory>
+#include <string>
+#include <vector>
+
+#include <cm3p/cppdap/future.h>
+#include <cm3p/cppdap/optional.h>
+#include <cm3p/cppdap/protocol.h>
+#include <cm3p/cppdap/session.h>
+#include <cm3p/cppdap/types.h>
+
+#include "cmDebuggerBreakpointManager.h"
+#include "cmDebuggerSourceBreakpoint.h" // IWYU pragma: keep
+#include "cmListFileCache.h"
+
+#include "testCommon.h"
+#include "testDebugger.h"
+
+static bool testHandleBreakpointRequestBeforeFileIsLoaded()
+{
+ // Arrange
+ DebuggerTestHelper helper;
+ cmDebugger::cmDebuggerBreakpointManager breakpointManager(
+ helper.Debugger.get());
+ helper.bind();
+ dap::SetBreakpointsRequest setBreakpointRequest;
+ std::string sourcePath = "C:/CMakeLists.txt";
+ setBreakpointRequest.source.path = sourcePath;
+ dap::array<dap::SourceBreakpoint> sourceBreakpoints(3);
+ sourceBreakpoints[0].line = 1;
+ sourceBreakpoints[1].line = 2;
+ sourceBreakpoints[2].line = 3;
+ setBreakpointRequest.breakpoints = sourceBreakpoints;
+
+ // Act
+ auto got = helper.Client->send(setBreakpointRequest).get();
+
+ // Assert
+ auto& response = got.response;
+ ASSERT_TRUE(!got.error);
+ ASSERT_TRUE(response.breakpoints.size() == sourceBreakpoints.size());
+ ASSERT_BREAKPOINT(response.breakpoints[0], 0, sourceBreakpoints[0].line,
+ sourcePath, false);
+ ASSERT_BREAKPOINT(response.breakpoints[1], 1, sourceBreakpoints[1].line,
+ sourcePath, false);
+ ASSERT_BREAKPOINT(response.breakpoints[2], 2, sourceBreakpoints[2].line,
+ sourcePath, false);
+ return true;
+}
+
+static bool testHandleBreakpointRequestAfterFileIsLoaded()
+{
+ // Arrange
+ DebuggerTestHelper helper;
+ std::atomic<bool> notExpectBreakpointEvents(true);
+ helper.Client->registerHandler([&](const dap::BreakpointEvent&) {
+ notExpectBreakpointEvents.store(false);
+ });
+
+ cmDebugger::cmDebuggerBreakpointManager breakpointManager(
+ helper.Debugger.get());
+ helper.bind();
+ std::string sourcePath = "C:/CMakeLists.txt";
+ std::vector<cmListFileFunction> functions = helper.CreateListFileFunctions(
+ "# Comment1\nset(var1 foo)\n# Comment2\nset(var2\nbar)\n",
+ sourcePath.c_str());
+
+ breakpointManager.SourceFileLoaded(sourcePath, functions);
+ dap::SetBreakpointsRequest setBreakpointRequest;
+ setBreakpointRequest.source.path = sourcePath;
+ dap::array<dap::SourceBreakpoint> sourceBreakpoints(5);
+ sourceBreakpoints[0].line = 1;
+ sourceBreakpoints[1].line = 2;
+ sourceBreakpoints[2].line = 3;
+ sourceBreakpoints[3].line = 4;
+ sourceBreakpoints[4].line = 5;
+ setBreakpointRequest.breakpoints = sourceBreakpoints;
+
+ // Act
+ auto got = helper.Client->send(setBreakpointRequest).get();
+
+ // Assert
+ auto& response = got.response;
+ ASSERT_TRUE(!got.error);
+ ASSERT_TRUE(response.breakpoints.size() == sourceBreakpoints.size());
+ // Line 1 is a comment. Move it to next valid function, which is line 2.
+ ASSERT_BREAKPOINT(response.breakpoints[0], 0, 2, sourcePath, true);
+ ASSERT_BREAKPOINT(response.breakpoints[1], 1, sourceBreakpoints[1].line,
+ sourcePath, true);
+ // Line 3 is a comment. Move it to next valid function, which is line 4.
+ ASSERT_BREAKPOINT(response.breakpoints[2], 2, 4, sourcePath, true);
+ ASSERT_BREAKPOINT(response.breakpoints[3], 3, sourceBreakpoints[3].line,
+ sourcePath, true);
+ // Line 5 is the 2nd part of line 4 function. No valid function after line 5,
+ // show the breakpoint at line 4.
+ ASSERT_BREAKPOINT(response.breakpoints[4], 4, sourceBreakpoints[3].line,
+ sourcePath, true);
+
+ ASSERT_TRUE(notExpectBreakpointEvents.load());
+
+ return true;
+}
+
+static bool testSourceFileLoadedAfterHandleBreakpointRequest()
+{
+ // Arrange
+ DebuggerTestHelper helper;
+ std::vector<dap::BreakpointEvent> breakpointEvents;
+ std::atomic<int> remainingBreakpointEvents(5);
+ std::promise<void> allBreakpointEventsReceivedPromise;
+ std::future<void> allBreakpointEventsReceivedFuture =
+ allBreakpointEventsReceivedPromise.get_future();
+ helper.Client->registerHandler([&](const dap::BreakpointEvent& event) {
+ breakpointEvents.emplace_back(event);
+ if (--remainingBreakpointEvents == 0) {
+ allBreakpointEventsReceivedPromise.set_value();
+ }
+ });
+ cmDebugger::cmDebuggerBreakpointManager breakpointManager(
+ helper.Debugger.get());
+ helper.bind();
+ dap::SetBreakpointsRequest setBreakpointRequest;
+ std::string sourcePath = "C:/CMakeLists.txt";
+ setBreakpointRequest.source.path = sourcePath;
+ dap::array<dap::SourceBreakpoint> sourceBreakpoints(5);
+ sourceBreakpoints[0].line = 1;
+ sourceBreakpoints[1].line = 2;
+ sourceBreakpoints[2].line = 3;
+ sourceBreakpoints[3].line = 4;
+ sourceBreakpoints[4].line = 5;
+ setBreakpointRequest.breakpoints = sourceBreakpoints;
+ std::vector<cmListFileFunction> functions = helper.CreateListFileFunctions(
+ "# Comment1\nset(var1 foo)\n# Comment2\nset(var2\nbar)\n",
+ sourcePath.c_str());
+ auto got = helper.Client->send(setBreakpointRequest).get();
+
+ // Act
+ breakpointManager.SourceFileLoaded(sourcePath, functions);
+ ASSERT_TRUE(allBreakpointEventsReceivedFuture.wait_for(
+ std::chrono::seconds(10)) == std::future_status::ready);
+
+ // Assert
+ ASSERT_TRUE(breakpointEvents.size() > 0);
+ // Line 1 is a comment. Move it to next valid function, which is line 2.
+ ASSERT_BREAKPOINT(breakpointEvents[0].breakpoint, 0, 2, sourcePath, true);
+ ASSERT_BREAKPOINT(breakpointEvents[1].breakpoint, 1,
+ sourceBreakpoints[1].line, sourcePath, true);
+ // Line 3 is a comment. Move it to next valid function, which is line 4.
+ ASSERT_BREAKPOINT(breakpointEvents[2].breakpoint, 2, 4, sourcePath, true);
+ ASSERT_BREAKPOINT(breakpointEvents[3].breakpoint, 3,
+ sourceBreakpoints[3].line, sourcePath, true);
+ // Line 5 is the 2nd part of line 4 function. No valid function after line 5,
+ // show the breakpoint at line 4.
+ ASSERT_BREAKPOINT(breakpointEvents[4].breakpoint, 4,
+ sourceBreakpoints[3].line, sourcePath, true);
+ return true;
+}
+
+int testDebuggerBreakpointManager(int, char*[])
+{
+ return runTests(std::vector<std::function<bool()>>{
+ testHandleBreakpointRequestBeforeFileIsLoaded,
+ testHandleBreakpointRequestAfterFileIsLoaded,
+ testSourceFileLoadedAfterHandleBreakpointRequest,
+ });
+}
diff --git a/Tests/CMakeLib/testDebuggerNamedPipe.cxx b/Tests/CMakeLib/testDebuggerNamedPipe.cxx
new file mode 100644
index 0000000..d2b0728
--- /dev/null
+++ b/Tests/CMakeLib/testDebuggerNamedPipe.cxx
@@ -0,0 +1,218 @@
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
+
+#include <chrono>
+#include <cstdio>
+#include <exception>
+#include <iostream>
+#include <memory>
+#include <sstream>
+#include <stdexcept>
+#include <string>
+#include <thread>
+#include <vector>
+
+#include <cm3p/cppdap/io.h>
+
+#include "cmsys/RegularExpression.hxx"
+
+#include "cmDebuggerPipeConnection.h"
+#include "cmSystemTools.h"
+
+#ifdef _WIN32
+# include "cmCryptoHash.h"
+#endif
+
+static void sendCommands(std::shared_ptr<dap::ReaderWriter> const& debugger,
+ int delayMs,
+ std::vector<std::string> const& initCommands)
+{
+ for (const auto& command : initCommands) {
+ std::string contentLength = "Content-Length:";
+ contentLength += std::to_string(command.size()) + "\r\n\r\n";
+ debugger->write(contentLength.c_str(), contentLength.size());
+ if (!debugger->write(command.c_str(), command.size())) {
+ std::cout << "debugger write error" << std::endl;
+ break;
+ }
+ std::this_thread::sleep_for(std::chrono::milliseconds(delayMs));
+ }
+}
+
+/** \brief Test CMake debugger named pipe.
+ *
+ * Test CMake debugger named pipe by
+ * 1. Create a named pipe for DAP traffic between the client and the debugger.
+ * 2. Create a client thread to wait for the debugger connection.
+ * - Once the debugger is connected, send the minimum required commands to
+ * get debugger going.
+ * - Wait for the CMake to complete the cache generation
+ * - Send the disconnect command.
+ * - Read and store the debugger's responses for validation.
+ * 3. Run the CMake command with debugger on and wait for it to complete.
+ * 4. Validate the response to ensure we are getting the expected responses.
+ *
+ */
+int runTest(int argc, char* argv[])
+{
+ if (argc < 3) {
+ std::cout << "Usage:\n";
+ std::cout << "\t(project mode) TestDebuggerNamedPipe <CMakePath> "
+ "<SourceFolder> <OutputFolder>\n";
+ std::cout << "\t(script mode) TestDebuggerNamedPipe <CMakePath> "
+ "<ScriptPath>\n";
+ return 1;
+ }
+
+ bool scriptMode = argc == 3;
+
+#ifdef _WIN32
+ std::string namedPipe = R"(\\.\pipe\LOCAL\CMakeDebuggerPipe_)" +
+ cmCryptoHash(cmCryptoHash::AlgoSHA256)
+ .HashString(scriptMode ? argv[2] : argv[3]);
+#else
+ std::string namedPipe =
+ std::string("CMakeDebuggerPipe") + (scriptMode ? "Script" : "Project");
+#endif
+
+ std::vector<std::string> cmakeCommand;
+ cmakeCommand.emplace_back(argv[1]);
+ cmakeCommand.emplace_back("--debugger");
+ cmakeCommand.emplace_back("--debugger-pipe");
+ cmakeCommand.emplace_back(namedPipe);
+
+ if (scriptMode) {
+ cmakeCommand.emplace_back("-P");
+ cmakeCommand.emplace_back(argv[2]);
+ } else {
+ cmakeCommand.emplace_back("-S");
+ cmakeCommand.emplace_back(argv[2]);
+ cmakeCommand.emplace_back("-B");
+ cmakeCommand.emplace_back(argv[3]);
+ }
+
+ // Capture debugger response stream.
+ std::stringstream debuggerResponseStream;
+
+ // Start the debugger client process.
+ std::thread clientThread([&]() {
+ // Poll until the pipe server is running. Clients can also look for a magic
+ // string in the CMake output, but this is easier for the test case.
+ std::shared_ptr<cmDebugger::cmDebuggerPipeClient> client;
+ int attempt = 0;
+ do {
+ attempt++;
+ try {
+ client = std::make_shared<cmDebugger::cmDebuggerPipeClient>(namedPipe);
+ client->Start();
+ client->WaitForConnection();
+ std::cout << "cmDebuggerPipeClient connected.\n";
+ break;
+ } catch (std::runtime_error&) {
+ std::cout << "Failed attempt " << attempt
+ << " to connect to pipe server. Retrying.\n";
+ client.reset();
+ std::this_thread::sleep_for(std::chrono::milliseconds(200));
+ }
+ } while (attempt < 50); // 10 seconds
+
+ if (attempt >= 50) {
+ return -1;
+ }
+
+ // Send init commands to get debugger going.
+ sendCommands(
+ client, 400,
+ { "{\"arguments\":{\"adapterID\":\"\"},\"command\":\"initialize\","
+ "\"seq\":"
+ "1,\"type\":\"request\"}",
+ "{\"arguments\":{},\"command\":\"launch\",\"seq\":2,\"type\":"
+ "\"request\"}",
+ "{\"arguments\":{},\"command\":\"configurationDone\",\"seq\":3,"
+ "\"type\":"
+ "\"request\"}" });
+
+ // Look for "exitCode" as a sign that configuration has completed and
+ // it's now safe to disconnect.
+ for (;;) {
+ char buffer[1];
+ size_t result = client->read(buffer, 1);
+ if (result != 1) {
+ std::cout << "debugger read error: " << result << std::endl;
+ break;
+ }
+ debuggerResponseStream << buffer[0];
+ if (debuggerResponseStream.str().find("exitCode") != std::string::npos) {
+ break;
+ }
+ }
+
+ // Send disconnect command.
+ sendCommands(
+ client, 200,
+ { "{\"arguments\":{},\"command\":\"disconnect\",\"seq\":4,\"type\":"
+ "\"request\"}" });
+
+ // Read any remaining debugger responses.
+ for (;;) {
+ char buffer[1];
+ size_t result = client->read(buffer, 1);
+ if (result != 1) {
+ std::cout << "debugger read error: " << result << std::endl;
+ break;
+ }
+ debuggerResponseStream << buffer[0];
+ }
+
+ client->close();
+
+ return 0;
+ });
+
+ if (!cmSystemTools::RunSingleCommand(cmakeCommand, nullptr, nullptr, nullptr,
+ nullptr, cmSystemTools::OUTPUT_MERGE)) {
+ std::cout << "Error running command" << std::endl;
+ return -1;
+ }
+
+ clientThread.join();
+
+ auto debuggerResponse = debuggerResponseStream.str();
+
+ std::vector<std::string> expectedResponses = {
+ R"("event" : "initialized".*"type" : "event")",
+ R"("command" : "launch".*"success" : true.*"type" : "response")",
+ R"("command" : "configurationDone".*"success" : true.*"type" : "response")",
+ R"("reason" : "started".*"threadId" : 1.*"event" : "thread".*"type" : "event")",
+ R"("reason" : "exited".*"threadId" : 1.*"event" : "thread".*"type" : "event")",
+ R"("exitCode" : 0.*"event" : "exited".*"type" : "event")",
+ R"("command" : "disconnect".*"success" : true.*"type" : "response")"
+ };
+
+ for (auto& regexString : expectedResponses) {
+ cmsys::RegularExpression regex(regexString);
+ if (!regex.find(debuggerResponse)) {
+ std::cout << "Expected response not found: " << regexString << std::endl;
+ std::cout << debuggerResponse << std::endl;
+ return -1;
+ }
+ }
+
+ return 0;
+}
+
+int main(int argc, char* argv[])
+{
+ try {
+ return runTest(argc, argv);
+ } catch (const std::exception& ex) {
+ std::cout << "An exception occurred: " << ex.what() << std::endl;
+ return -1;
+ } catch (const std::string& ex) {
+ std::cout << "An exception occurred: " << ex << std::endl;
+ return -1;
+ } catch (...) {
+ std::cout << "An unknown exception occurred" << std::endl;
+ return -1;
+ }
+}
diff --git a/Tests/CMakeLib/testDebuggerVariables.cxx b/Tests/CMakeLib/testDebuggerVariables.cxx
new file mode 100644
index 0000000..6c19baa
--- /dev/null
+++ b/Tests/CMakeLib/testDebuggerVariables.cxx
@@ -0,0 +1,185 @@
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
+
+#include <cstdint>
+#include <functional>
+#include <memory>
+#include <string>
+#include <unordered_set>
+#include <vector>
+
+#include <cm3p/cppdap/protocol.h>
+#include <cm3p/cppdap/types.h>
+
+#include "cmDebuggerVariables.h"
+#include "cmDebuggerVariablesManager.h"
+
+#include "testCommon.h"
+#include "testDebugger.h"
+
+static dap::VariablesRequest CreateVariablesRequest(int64_t reference)
+{
+ dap::VariablesRequest variableRequest;
+ variableRequest.variablesReference = reference;
+ return variableRequest;
+}
+
+static bool testUniqueIds()
+{
+ auto variablesManager =
+ std::make_shared<cmDebugger::cmDebuggerVariablesManager>();
+
+ std::unordered_set<int64_t> variableIds;
+ bool noDuplicateIds = true;
+ for (int i = 0; i < 10000 && noDuplicateIds; ++i) {
+ auto variable =
+ cmDebugger::cmDebuggerVariables(variablesManager, "Locals", true, []() {
+ return std::vector<cmDebugger::cmDebuggerVariableEntry>();
+ });
+
+ if (variableIds.find(variable.GetId()) != variableIds.end()) {
+ noDuplicateIds = false;
+ }
+ variableIds.insert(variable.GetId());
+ }
+
+ ASSERT_TRUE(noDuplicateIds);
+
+ return true;
+}
+
+static bool testConstructors()
+{
+ auto variablesManager =
+ std::make_shared<cmDebugger::cmDebuggerVariablesManager>();
+
+ auto parent = std::make_shared<cmDebugger::cmDebuggerVariables>(
+ variablesManager, "Parent", true, [=]() {
+ return std::vector<cmDebugger::cmDebuggerVariableEntry>{
+ { "ParentKey", "ParentValue", "ParentType" }
+ };
+ });
+
+ auto children1 = std::make_shared<cmDebugger::cmDebuggerVariables>(
+ variablesManager, "Children1", true, [=]() {
+ return std::vector<cmDebugger::cmDebuggerVariableEntry>{
+ { "ChildKey1", "ChildValue1", "ChildType1" },
+ { "ChildKey2", "ChildValue2", "ChildType2" }
+ };
+ });
+
+ parent->AddSubVariables(children1);
+
+ auto children2 = std::make_shared<cmDebugger::cmDebuggerVariables>(
+ variablesManager, "Children2", true);
+
+ auto grandChildren21 = std::make_shared<cmDebugger::cmDebuggerVariables>(
+ variablesManager, "GrandChildren21", true);
+ grandChildren21->SetValue("GrandChildren21 Value");
+ children2->AddSubVariables(grandChildren21);
+ parent->AddSubVariables(children2);
+
+ dap::array<dap::Variable> variables =
+ variablesManager->HandleVariablesRequest(
+ CreateVariablesRequest(parent->GetId()));
+ ASSERT_TRUE(variables.size() == 3);
+ ASSERT_VARIABLE_REFERENCE(variables[0], "Children1", "", "collection",
+ children1->GetId());
+ ASSERT_VARIABLE_REFERENCE(variables[1], "Children2", "", "collection",
+ children2->GetId());
+ ASSERT_VARIABLE(variables[2], "ParentKey", "ParentValue", "ParentType");
+
+ variables = variablesManager->HandleVariablesRequest(
+ CreateVariablesRequest(children1->GetId()));
+ ASSERT_TRUE(variables.size() == 2);
+ ASSERT_VARIABLE(variables[0], "ChildKey1", "ChildValue1", "ChildType1");
+ ASSERT_VARIABLE(variables[1], "ChildKey2", "ChildValue2", "ChildType2");
+
+ variables = variablesManager->HandleVariablesRequest(
+ CreateVariablesRequest(children2->GetId()));
+ ASSERT_TRUE(variables.size() == 1);
+ ASSERT_VARIABLE_REFERENCE(variables[0], "GrandChildren21",
+ "GrandChildren21 Value", "collection",
+ grandChildren21->GetId());
+
+ return true;
+}
+
+static bool testIgnoreEmptyStringEntries()
+{
+ auto variablesManager =
+ std::make_shared<cmDebugger::cmDebuggerVariablesManager>();
+
+ auto vars = std::make_shared<cmDebugger::cmDebuggerVariables>(
+ variablesManager, "Variables", true, []() {
+ return std::vector<cmDebugger::cmDebuggerVariableEntry>{
+ { "IntValue1", 5 }, { "StringValue1", "" },
+ { "StringValue2", "foo" }, { "StringValue3", "" },
+ { "StringValue4", "bar" }, { "StringValue5", "" },
+ { "IntValue2", int64_t(99) }, { "BooleanTrue", true },
+ { "BooleanFalse", false },
+ };
+ });
+
+ vars->SetIgnoreEmptyStringEntries(true);
+ vars->SetEnableSorting(false);
+
+ dap::array<dap::Variable> variables =
+ variablesManager->HandleVariablesRequest(
+ CreateVariablesRequest(vars->GetId()));
+ ASSERT_TRUE(variables.size() == 6);
+ ASSERT_VARIABLE(variables[0], "IntValue1", "5", "int");
+ ASSERT_VARIABLE(variables[1], "StringValue2", "foo", "string");
+ ASSERT_VARIABLE(variables[2], "StringValue4", "bar", "string");
+ ASSERT_VARIABLE(variables[3], "IntValue2", "99", "int");
+ ASSERT_VARIABLE(variables[4], "BooleanTrue", "TRUE", "bool");
+ ASSERT_VARIABLE(variables[5], "BooleanFalse", "FALSE", "bool");
+
+ return true;
+}
+
+static bool testSortTheResult()
+{
+ auto variablesManager =
+ std::make_shared<cmDebugger::cmDebuggerVariablesManager>();
+
+ auto vars = std::make_shared<cmDebugger::cmDebuggerVariables>(
+ variablesManager, "Variables", true, []() {
+ return std::vector<cmDebugger::cmDebuggerVariableEntry>{
+ { "4", "4" }, { "2", "2" }, { "1", "1" }, { "3", "3" }, { "5", "5" },
+ };
+ });
+
+ dap::array<dap::Variable> variables =
+ variablesManager->HandleVariablesRequest(
+ CreateVariablesRequest(vars->GetId()));
+ ASSERT_TRUE(variables.size() == 5);
+ ASSERT_VARIABLE(variables[0], "1", "1", "string");
+ ASSERT_VARIABLE(variables[1], "2", "2", "string");
+ ASSERT_VARIABLE(variables[2], "3", "3", "string");
+ ASSERT_VARIABLE(variables[3], "4", "4", "string");
+ ASSERT_VARIABLE(variables[4], "5", "5", "string");
+
+ vars->SetEnableSorting(false);
+
+ variables = variablesManager->HandleVariablesRequest(
+ CreateVariablesRequest(vars->GetId()));
+ ASSERT_TRUE(variables.size() == 5);
+ ASSERT_VARIABLE(variables[0], "4", "4", "string");
+ ASSERT_VARIABLE(variables[1], "2", "2", "string");
+ ASSERT_VARIABLE(variables[2], "1", "1", "string");
+ ASSERT_VARIABLE(variables[3], "3", "3", "string");
+ ASSERT_VARIABLE(variables[4], "5", "5", "string");
+
+ return true;
+}
+
+int testDebuggerVariables(int, char*[])
+{
+ return runTests(std::vector<std::function<bool()>>{
+ testUniqueIds,
+ testConstructors,
+ testIgnoreEmptyStringEntries,
+ testSortTheResult,
+ });
+}
diff --git a/Tests/CMakeLib/testDebuggerVariablesHelper.cxx b/Tests/CMakeLib/testDebuggerVariablesHelper.cxx
new file mode 100644
index 0000000..e0bbdf0
--- /dev/null
+++ b/Tests/CMakeLib/testDebuggerVariablesHelper.cxx
@@ -0,0 +1,587 @@
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
+
+#include <functional>
+#include <memory>
+#include <set>
+#include <string>
+#include <utility>
+#include <vector>
+
+#include <cm3p/cppdap/protocol.h>
+#include <cm3p/cppdap/types.h>
+#include <stddef.h>
+#include <stdint.h>
+
+#include "cmDebuggerStackFrame.h"
+#include "cmDebuggerVariables.h"
+#include "cmDebuggerVariablesHelper.h"
+#include "cmDebuggerVariablesManager.h"
+#include "cmFileSet.h"
+#include "cmGlobalGenerator.h"
+#include "cmListFileCache.h"
+#include "cmMakefile.h"
+#include "cmPolicies.h"
+#include "cmPropertyMap.h"
+#include "cmState.h"
+#include "cmStateDirectory.h"
+#include "cmStateSnapshot.h"
+#include "cmStateTypes.h"
+#include "cmTarget.h"
+#include "cmTest.h"
+#include "cmake.h"
+
+#include "testCommon.h"
+#include "testDebugger.h"
+
+static dap::VariablesRequest CreateVariablesRequest(int64_t reference)
+{
+ dap::VariablesRequest variableRequest;
+ variableRequest.variablesReference = reference;
+ return variableRequest;
+}
+
+struct Dummies
+{
+ std::shared_ptr<cmake> CMake;
+ std::shared_ptr<cmMakefile> Makefile;
+ std::shared_ptr<cmGlobalGenerator> GlobalGenerator;
+};
+
+static Dummies CreateDummies(
+ std::string targetName,
+ std::string currentSourceDirectory = "c:/CurrentSourceDirectory",
+ std::string currentBinaryDirectory = "c:/CurrentBinaryDirectory")
+{
+ Dummies dummies;
+ dummies.CMake =
+ std::make_shared<cmake>(cmake::RoleProject, cmState::Project);
+ cmState* state = dummies.CMake->GetState();
+ dummies.GlobalGenerator =
+ std::make_shared<cmGlobalGenerator>(dummies.CMake.get());
+ cmStateSnapshot snapshot = state->CreateBaseSnapshot();
+ snapshot.GetDirectory().SetCurrentSource(currentSourceDirectory);
+ snapshot.GetDirectory().SetCurrentBinary(currentBinaryDirectory);
+ dummies.Makefile =
+ std::make_shared<cmMakefile>(dummies.GlobalGenerator.get(), snapshot);
+ dummies.Makefile->CreateNewTarget(targetName, cmStateEnums::EXECUTABLE);
+ return dummies;
+}
+
+static bool testCreateFromPolicyMap()
+{
+ auto variablesManager =
+ std::make_shared<cmDebugger::cmDebuggerVariablesManager>();
+
+ cmPolicies::PolicyMap policyMap;
+ policyMap.Set(cmPolicies::CMP0000, cmPolicies::NEW);
+ policyMap.Set(cmPolicies::CMP0003, cmPolicies::WARN);
+ policyMap.Set(cmPolicies::CMP0005, cmPolicies::OLD);
+ auto vars = cmDebugger::cmDebuggerVariablesHelper::Create(
+ variablesManager, "Locals", true, policyMap);
+
+ dap::array<dap::Variable> variables =
+ variablesManager->HandleVariablesRequest(
+ CreateVariablesRequest(vars->GetId()));
+ ASSERT_TRUE(variables.size() == 3);
+ ASSERT_VARIABLE(variables[0], "CMP0000", "NEW", "string");
+ ASSERT_VARIABLE(variables[1], "CMP0003", "WARN", "string");
+ ASSERT_VARIABLE(variables[2], "CMP0005", "OLD", "string");
+
+ return true;
+}
+
+static bool testCreateFromPairVector()
+{
+ auto variablesManager =
+ std::make_shared<cmDebugger::cmDebuggerVariablesManager>();
+
+ std::vector<std::pair<std::string, std::string>> pairs = {
+ { "Foo1", "Bar1" }, { "Foo2", "Bar2" }
+ };
+
+ auto vars = cmDebugger::cmDebuggerVariablesHelper::CreateIfAny(
+ variablesManager, "Locals", true, pairs);
+
+ dap::array<dap::Variable> variables =
+ variablesManager->HandleVariablesRequest(
+ CreateVariablesRequest(vars->GetId()));
+
+ ASSERT_TRUE(vars->GetValue() == std::to_string(pairs.size()));
+ ASSERT_TRUE(variables.size() == 2);
+ ASSERT_VARIABLE(variables[0], "Foo1", "Bar1", "string");
+ ASSERT_VARIABLE(variables[1], "Foo2", "Bar2", "string");
+
+ auto none = cmDebugger::cmDebuggerVariablesHelper::CreateIfAny(
+ variablesManager, "Locals", true,
+ std::vector<std::pair<std::string, std::string>>());
+
+ ASSERT_TRUE(none == nullptr);
+
+ return true;
+}
+
+static bool testCreateFromSet()
+{
+ auto variablesManager =
+ std::make_shared<cmDebugger::cmDebuggerVariablesManager>();
+
+ std::set<std::string> set = { "Foo", "Bar" };
+
+ auto vars = cmDebugger::cmDebuggerVariablesHelper::CreateIfAny(
+ variablesManager, "Locals", true, set);
+
+ dap::array<dap::Variable> variables =
+ variablesManager->HandleVariablesRequest(
+ CreateVariablesRequest(vars->GetId()));
+
+ ASSERT_TRUE(vars->GetValue() == std::to_string(set.size()));
+ ASSERT_TRUE(variables.size() == 2);
+ ASSERT_VARIABLE(variables[0], "[0]", "Bar", "string");
+ ASSERT_VARIABLE(variables[1], "[1]", "Foo", "string");
+
+ auto none = cmDebugger::cmDebuggerVariablesHelper::CreateIfAny(
+ variablesManager, "Locals", true, std::set<std::string>());
+
+ ASSERT_TRUE(none == nullptr);
+
+ return true;
+}
+
+static bool testCreateFromStringVector()
+{
+ auto variablesManager =
+ std::make_shared<cmDebugger::cmDebuggerVariablesManager>();
+
+ std::vector<std::string> list = { "Foo", "Bar" };
+
+ auto vars = cmDebugger::cmDebuggerVariablesHelper::CreateIfAny(
+ variablesManager, "Locals", true, list);
+
+ dap::array<dap::Variable> variables =
+ variablesManager->HandleVariablesRequest(
+ CreateVariablesRequest(vars->GetId()));
+
+ ASSERT_TRUE(vars->GetValue() == std::to_string(list.size()));
+ ASSERT_TRUE(variables.size() == 2);
+ ASSERT_VARIABLE(variables[0], "[0]", "Foo", "string");
+ ASSERT_VARIABLE(variables[1], "[1]", "Bar", "string");
+
+ auto none = cmDebugger::cmDebuggerVariablesHelper::CreateIfAny(
+ variablesManager, "Locals", true, std::vector<std::string>());
+
+ ASSERT_TRUE(none == nullptr);
+
+ return true;
+}
+
+static bool testCreateFromTarget()
+{
+ auto variablesManager =
+ std::make_shared<cmDebugger::cmDebuggerVariablesManager>();
+
+ auto dummies = CreateDummies("Foo");
+
+ auto vars = cmDebugger::cmDebuggerVariablesHelper::CreateIfAny(
+ variablesManager, "Locals", true, dummies.Makefile->GetOrderedTargets());
+
+ dap::array<dap::Variable> variables =
+ variablesManager->HandleVariablesRequest(
+ CreateVariablesRequest(vars->GetId()));
+
+ ASSERT_TRUE(variables.size() == 1);
+ ASSERT_VARIABLE(variables[0], "Foo", "EXECUTABLE", "collection");
+
+ variables = variablesManager->HandleVariablesRequest(
+ CreateVariablesRequest(variables[0].variablesReference));
+
+ ASSERT_TRUE(variables.size() == 15);
+ ASSERT_VARIABLE(variables[0], "GlobalGenerator", "Generic", "collection");
+ ASSERT_VARIABLE(variables[1], "IsAIX", "FALSE", "bool");
+ ASSERT_VARIABLE(variables[2], "IsAndroidGuiExecutable", "FALSE", "bool");
+ ASSERT_VARIABLE(variables[3], "IsAppBundleOnApple", "FALSE", "bool");
+ ASSERT_VARIABLE(variables[4], "IsDLLPlatform", "FALSE", "bool");
+ ASSERT_VARIABLE(variables[5], "IsExecutableWithExports", "FALSE", "bool");
+ ASSERT_VARIABLE(variables[6], "IsFrameworkOnApple", "FALSE", "bool");
+ ASSERT_VARIABLE(variables[7], "IsImported", "FALSE", "bool");
+ ASSERT_VARIABLE(variables[8], "IsImportedGloballyVisible", "FALSE", "bool");
+ ASSERT_VARIABLE(variables[9], "IsPerConfig", "TRUE", "bool");
+ ASSERT_VARIABLE(variables[10], "Makefile",
+ dummies.Makefile->GetDirectoryId().String, "collection");
+ ASSERT_VARIABLE(variables[11], "Name", "Foo", "string");
+ ASSERT_VARIABLE(variables[12], "PolicyMap", "", "collection");
+ ASSERT_VARIABLE(variables[13], "Properties",
+ std::to_string(dummies.Makefile->GetOrderedTargets()[0]
+ ->GetProperties()
+ .GetList()
+ .size()),
+ "collection");
+ ASSERT_VARIABLE(variables[14], "Type", "EXECUTABLE", "string");
+
+ auto none = cmDebugger::cmDebuggerVariablesHelper::CreateIfAny(
+ variablesManager, "Locals", true, std::vector<cmTarget*>());
+
+ ASSERT_TRUE(none == nullptr);
+
+ return true;
+}
+
+static bool testCreateFromGlobalGenerator()
+{
+ auto variablesManager =
+ std::make_shared<cmDebugger::cmDebuggerVariablesManager>();
+
+ auto dummies = CreateDummies("Foo");
+
+ auto vars = cmDebugger::cmDebuggerVariablesHelper::CreateIfAny(
+ variablesManager, "Locals", true, dummies.GlobalGenerator.get());
+
+ dap::array<dap::Variable> variables =
+ variablesManager->HandleVariablesRequest(
+ CreateVariablesRequest(vars->GetId()));
+
+ ASSERT_TRUE(variables.size() == 10);
+ ASSERT_VARIABLE(variables[0], "AllTargetName", "ALL_BUILD", "string");
+ ASSERT_VARIABLE(variables[1], "ForceUnixPaths", "FALSE", "bool");
+ ASSERT_VARIABLE(variables[2], "InstallTargetName", "INSTALL", "string");
+ ASSERT_VARIABLE(variables[3], "IsMultiConfig", "FALSE", "bool");
+ ASSERT_VARIABLE(variables[4], "MakefileEncoding", "None", "string");
+ ASSERT_VARIABLE(variables[5], "Name", "Generic", "string");
+ ASSERT_VARIABLE(variables[6], "NeedSymbolicMark", "FALSE", "bool");
+ ASSERT_VARIABLE(variables[7], "PackageTargetName", "PACKAGE", "string");
+ ASSERT_VARIABLE(variables[8], "TestTargetName", "RUN_TESTS", "string");
+ ASSERT_VARIABLE(variables[9], "UseLinkScript", "FALSE", "bool");
+
+ auto none = cmDebugger::cmDebuggerVariablesHelper::CreateIfAny(
+ variablesManager, "Locals", true,
+ static_cast<cmGlobalGenerator*>(nullptr));
+
+ ASSERT_TRUE(none == nullptr);
+
+ return true;
+}
+
+static bool testCreateFromTests()
+{
+ auto variablesManager =
+ std::make_shared<cmDebugger::cmDebuggerVariablesManager>();
+
+ auto dummies = CreateDummies("Foo");
+ cmTest test1 = cmTest(dummies.Makefile.get());
+ test1.SetName("Test1");
+ test1.SetOldStyle(false);
+ test1.SetCommandExpandLists(true);
+ test1.SetCommand(std::vector<std::string>{ "Foo1", "arg1" });
+ test1.SetProperty("Prop1", "Prop1");
+ cmTest test2 = cmTest(dummies.Makefile.get());
+ test2.SetName("Test2");
+ test2.SetOldStyle(false);
+ test2.SetCommandExpandLists(false);
+ test2.SetCommand(std::vector<std::string>{ "Bar1", "arg1", "arg2" });
+ test2.SetProperty("Prop2", "Prop2");
+ test2.SetProperty("Prop3", "Prop3");
+
+ std::vector<cmTest*> tests = { &test1, &test2 };
+
+ auto vars = cmDebugger::cmDebuggerVariablesHelper::CreateIfAny(
+ variablesManager, "Locals", true, tests);
+
+ dap::array<dap::Variable> variables =
+ variablesManager->HandleVariablesRequest(
+ CreateVariablesRequest(vars->GetId()));
+
+ ASSERT_TRUE(vars->GetValue() == std::to_string(tests.size()));
+ ASSERT_TRUE(variables.size() == 2);
+ ASSERT_VARIABLE_REFERENCE_NOT_ZERO(variables[0], test1.GetName(), "",
+ "collection");
+ ASSERT_VARIABLE_REFERENCE_NOT_ZERO(variables[1], test2.GetName(), "",
+ "collection");
+
+ dap::array<dap::Variable> testVariables =
+ variablesManager->HandleVariablesRequest(
+ CreateVariablesRequest(variables[0].variablesReference));
+ ASSERT_TRUE(testVariables.size() == 5);
+ ASSERT_VARIABLE_REFERENCE_NOT_ZERO(testVariables[0], "Command",
+ std::to_string(test1.GetCommand().size()),
+ "collection");
+ ASSERT_VARIABLE(testVariables[1], "CommandExpandLists",
+ BOOL_STRING(test1.GetCommandExpandLists()), "bool");
+ ASSERT_VARIABLE(testVariables[2], "Name", test1.GetName(), "string");
+ ASSERT_VARIABLE(testVariables[3], "OldStyle",
+ BOOL_STRING(test1.GetOldStyle()), "bool");
+ ASSERT_VARIABLE_REFERENCE_NOT_ZERO(testVariables[4], "Properties", "1",
+ "collection");
+
+ dap::array<dap::Variable> commandVariables =
+ variablesManager->HandleVariablesRequest(
+ CreateVariablesRequest(testVariables[0].variablesReference));
+ ASSERT_TRUE(commandVariables.size() == test1.GetCommand().size());
+ for (size_t i = 0; i < commandVariables.size(); ++i) {
+ ASSERT_VARIABLE(commandVariables[i], "[" + std::to_string(i) + "]",
+ test1.GetCommand()[i], "string");
+ }
+
+ dap::array<dap::Variable> propertiesVariables =
+ variablesManager->HandleVariablesRequest(
+ CreateVariablesRequest(testVariables[4].variablesReference));
+ ASSERT_TRUE(propertiesVariables.size() == 1);
+ ASSERT_VARIABLE(propertiesVariables[0], "Prop1", "Prop1", "string");
+
+ testVariables = variablesManager->HandleVariablesRequest(
+ CreateVariablesRequest(variables[1].variablesReference));
+ ASSERT_TRUE(testVariables.size() == 5);
+ ASSERT_VARIABLE_REFERENCE_NOT_ZERO(testVariables[0], "Command",
+ std::to_string(test2.GetCommand().size()),
+ "collection");
+ ASSERT_VARIABLE(testVariables[1], "CommandExpandLists",
+ BOOL_STRING(test2.GetCommandExpandLists()), "bool");
+ ASSERT_VARIABLE(testVariables[2], "Name", test2.GetName(), "string");
+ ASSERT_VARIABLE(testVariables[3], "OldStyle",
+ BOOL_STRING(test2.GetOldStyle()), "bool");
+ ASSERT_VARIABLE_REFERENCE_NOT_ZERO(testVariables[4], "Properties", "2",
+ "collection");
+
+ commandVariables = variablesManager->HandleVariablesRequest(
+ CreateVariablesRequest(testVariables[0].variablesReference));
+ ASSERT_TRUE(commandVariables.size() == test2.GetCommand().size());
+ for (size_t i = 0; i < commandVariables.size(); ++i) {
+ ASSERT_VARIABLE(commandVariables[i], "[" + std::to_string(i) + "]",
+ test2.GetCommand()[i], "string");
+ }
+
+ propertiesVariables = variablesManager->HandleVariablesRequest(
+ CreateVariablesRequest(testVariables[4].variablesReference));
+ ASSERT_TRUE(propertiesVariables.size() == 2);
+ ASSERT_VARIABLE(propertiesVariables[0], "Prop2", "Prop2", "string");
+ ASSERT_VARIABLE(propertiesVariables[1], "Prop3", "Prop3", "string");
+
+ auto none = cmDebugger::cmDebuggerVariablesHelper::CreateIfAny(
+ variablesManager, "Locals", true, std::vector<cmTest*>());
+
+ ASSERT_TRUE(none == nullptr);
+
+ return true;
+}
+
+static bool testCreateFromMakefile()
+{
+ auto variablesManager =
+ std::make_shared<cmDebugger::cmDebuggerVariablesManager>();
+
+ auto dummies = CreateDummies("Foo");
+ auto snapshot = dummies.Makefile->GetStateSnapshot();
+ auto state = dummies.Makefile->GetState();
+ state->SetSourceDirectory("c:/HomeDirectory");
+ state->SetBinaryDirectory("c:/HomeOutputDirectory");
+ auto vars = cmDebugger::cmDebuggerVariablesHelper::CreateIfAny(
+ variablesManager, "Locals", true, dummies.Makefile.get());
+
+ dap::array<dap::Variable> variables =
+ variablesManager->HandleVariablesRequest(
+ CreateVariablesRequest(vars->GetId()));
+
+ ASSERT_TRUE(variables.size() == 12);
+ ASSERT_VARIABLE(variables[0], "AppleSDKType", "MacOS", "string");
+ ASSERT_VARIABLE(variables[1], "CurrentBinaryDirectory",
+ snapshot.GetDirectory().GetCurrentBinary(), "string");
+ ASSERT_VARIABLE(variables[2], "CurrentSourceDirectory",
+ snapshot.GetDirectory().GetCurrentSource(), "string");
+ ASSERT_VARIABLE(variables[3], "DefineFlags", " ", "string");
+ ASSERT_VARIABLE(variables[4], "DirectoryId",
+ dummies.Makefile->GetDirectoryId().String, "string");
+ ASSERT_VARIABLE(variables[5], "HomeDirectory", state->GetSourceDirectory(),
+ "string");
+ ASSERT_VARIABLE(variables[6], "HomeOutputDirectory",
+ state->GetBinaryDirectory(), "string");
+ ASSERT_VARIABLE(variables[7], "IsRootMakefile", "TRUE", "bool");
+ ASSERT_VARIABLE(variables[8], "PlatformIs32Bit", "FALSE", "bool");
+ ASSERT_VARIABLE(variables[9], "PlatformIs64Bit", "FALSE", "bool");
+ ASSERT_VARIABLE(variables[10], "PlatformIsAppleEmbedded", "FALSE", "bool");
+ ASSERT_VARIABLE(variables[11], "PlatformIsx32", "FALSE", "bool");
+
+ auto none = cmDebugger::cmDebuggerVariablesHelper::CreateIfAny(
+ variablesManager, "Locals", true, static_cast<cmMakefile*>(nullptr));
+
+ ASSERT_TRUE(none == nullptr);
+
+ return true;
+}
+
+static bool testCreateFromStackFrame()
+{
+ auto variablesManager =
+ std::make_shared<cmDebugger::cmDebuggerVariablesManager>();
+ auto dummies = CreateDummies("Foo");
+
+ cmListFileFunction lff = cmListFileFunction("set", 99, 99, {});
+ auto frame = std::make_shared<cmDebugger::cmDebuggerStackFrame>(
+ dummies.Makefile.get(), "c:/CMakeLists.txt", lff);
+
+ dummies.CMake->AddCacheEntry("CMAKE_BUILD_TYPE", "Debug", "Build Type",
+ cmStateEnums::CacheEntryType::STRING);
+
+ auto locals = cmDebugger::cmDebuggerVariablesHelper::Create(
+ variablesManager, "Locals", true, frame);
+
+ dap::array<dap::Variable> variables =
+ variablesManager->HandleVariablesRequest(
+ CreateVariablesRequest(locals->GetId()));
+
+ ASSERT_TRUE(variables.size() == 5);
+ ASSERT_VARIABLE(variables[0], "CacheVariables", "1", "collection");
+ ASSERT_VARIABLE(variables[1], "CurrentLine", std::to_string(lff.Line()),
+ "int");
+ ASSERT_VARIABLE(variables[2], "Directories", "2", "collection");
+ ASSERT_VARIABLE(variables[3], "Locals", "2", "collection");
+ ASSERT_VARIABLE(variables[4], "Targets", "1", "collection");
+
+ dap::array<dap::Variable> cacheVariables =
+ variablesManager->HandleVariablesRequest(
+ CreateVariablesRequest(variables[0].variablesReference));
+ ASSERT_TRUE(cacheVariables.size() == 1);
+ ASSERT_VARIABLE(cacheVariables[0], "CMAKE_BUILD_TYPE:STRING", "Debug",
+ "collection");
+
+ dap::array<dap::Variable> directoriesVariables =
+ variablesManager->HandleVariablesRequest(
+ CreateVariablesRequest(variables[2].variablesReference));
+ ASSERT_TRUE(directoriesVariables.size() == 2);
+ ASSERT_VARIABLE(
+ directoriesVariables[0], "CMAKE_CURRENT_BINARY_DIR",
+ dummies.Makefile->GetStateSnapshot().GetDirectory().GetCurrentBinary(),
+ "string");
+ ASSERT_VARIABLE(
+ directoriesVariables[1], "CMAKE_CURRENT_SOURCE_DIR",
+ dummies.Makefile->GetStateSnapshot().GetDirectory().GetCurrentSource(),
+ "string");
+
+ dap::array<dap::Variable> propertiesVariables =
+ variablesManager->HandleVariablesRequest(
+ CreateVariablesRequest(cacheVariables[0].variablesReference));
+ ASSERT_TRUE(propertiesVariables.size() == 3);
+ ASSERT_VARIABLE(propertiesVariables[0], "HELPSTRING", "Build Type",
+ "string");
+ ASSERT_VARIABLE(propertiesVariables[1], "TYPE", "STRING", "string");
+ ASSERT_VARIABLE(propertiesVariables[2], "VALUE", "Debug", "string");
+
+ return true;
+}
+
+static bool testCreateFromBTStringVector()
+{
+ auto variablesManager =
+ std::make_shared<cmDebugger::cmDebuggerVariablesManager>();
+
+ std::vector<BT<std::string>> list(2);
+ list[0].Value = "Foo";
+ list[1].Value = "Bar";
+
+ auto vars = cmDebugger::cmDebuggerVariablesHelper::CreateIfAny(
+ variablesManager, "Locals", true, list);
+
+ dap::array<dap::Variable> variables =
+ variablesManager->HandleVariablesRequest(
+ CreateVariablesRequest(vars->GetId()));
+
+ ASSERT_TRUE(vars->GetValue() == std::to_string(list.size()));
+ ASSERT_TRUE(variables.size() == 2);
+ ASSERT_VARIABLE(variables[0], "[0]", "Foo", "string");
+ ASSERT_VARIABLE(variables[1], "[1]", "Bar", "string");
+
+ auto none = cmDebugger::cmDebuggerVariablesHelper::CreateIfAny(
+ variablesManager, "Locals", true, std::vector<std::string>());
+
+ ASSERT_TRUE(none == nullptr);
+
+ return true;
+}
+
+static bool testCreateFromFileSet()
+{
+ auto variablesManager =
+ std::make_shared<cmDebugger::cmDebuggerVariablesManager>();
+
+ cmake cm(cmake::RoleScript, cmState::Unknown);
+ cmFileSet fileSet(cm, "Foo", "HEADERS", cmFileSetVisibility::Public);
+ BT<std::string> directory;
+ directory.Value = "c:/";
+ fileSet.AddDirectoryEntry(directory);
+ BT<std::string> file;
+ file.Value = "c:/foo.cxx";
+ fileSet.AddFileEntry(file);
+
+ auto vars = cmDebugger::cmDebuggerVariablesHelper::CreateIfAny(
+ variablesManager, "Locals", true, &fileSet);
+
+ dap::array<dap::Variable> variables =
+ variablesManager->HandleVariablesRequest(
+ CreateVariablesRequest(vars->GetId()));
+
+ ASSERT_TRUE(variables.size() == 5);
+ ASSERT_VARIABLE_REFERENCE_NOT_ZERO(variables[0], "Directories", "1",
+ "collection");
+ ASSERT_VARIABLE_REFERENCE_NOT_ZERO(variables[1], "Files", "1", "collection");
+ ASSERT_VARIABLE(variables[2], "Name", "Foo", "string");
+ ASSERT_VARIABLE(variables[3], "Type", "HEADERS", "string");
+ ASSERT_VARIABLE(variables[4], "Visibility", "Public", "string");
+
+ dap::array<dap::Variable> directoriesVariables =
+ variablesManager->HandleVariablesRequest(
+ CreateVariablesRequest(variables[0].variablesReference));
+ ASSERT_TRUE(directoriesVariables.size() == 1);
+ ASSERT_VARIABLE(directoriesVariables[0], "[0]", directory.Value, "string");
+
+ dap::array<dap::Variable> filesVariables =
+ variablesManager->HandleVariablesRequest(
+ CreateVariablesRequest(variables[1].variablesReference));
+ ASSERT_TRUE(filesVariables.size() == 1);
+ ASSERT_VARIABLE(filesVariables[0], "[0]", file.Value, "string");
+
+ return true;
+}
+
+static bool testCreateFromFileSets()
+{
+ auto variablesManager =
+ std::make_shared<cmDebugger::cmDebuggerVariablesManager>();
+
+ cmake cm(cmake::RoleScript, cmState::Unknown);
+ cmFileSet fileSet(cm, "Foo", "HEADERS", cmFileSetVisibility::Public);
+ BT<std::string> directory;
+ directory.Value = "c:/";
+ fileSet.AddDirectoryEntry(directory);
+ BT<std::string> file;
+ file.Value = "c:/foo.cxx";
+ fileSet.AddFileEntry(file);
+
+ auto fileSets = std::vector<cmFileSet*>{ &fileSet };
+ auto vars = cmDebugger::cmDebuggerVariablesHelper::CreateIfAny(
+ variablesManager, "Locals", true, fileSets);
+
+ dap::array<dap::Variable> variables =
+ variablesManager->HandleVariablesRequest(
+ CreateVariablesRequest(vars->GetId()));
+
+ ASSERT_TRUE(variables.size() == 1);
+ ASSERT_VARIABLE_REFERENCE_NOT_ZERO(variables[0], "Foo", "", "collection");
+
+ return true;
+}
+
+int testDebuggerVariablesHelper(int, char*[])
+{
+ return runTests(std::vector<std::function<bool()>>{
+ testCreateFromPolicyMap,
+ testCreateFromPairVector,
+ testCreateFromSet,
+ testCreateFromStringVector,
+ testCreateFromTarget,
+ testCreateFromGlobalGenerator,
+ testCreateFromMakefile,
+ testCreateFromStackFrame,
+ testCreateFromTests,
+ testCreateFromBTStringVector,
+ testCreateFromFileSet,
+ testCreateFromFileSets,
+ });
+}
diff --git a/Tests/CMakeLib/testDebuggerVariablesManager.cxx b/Tests/CMakeLib/testDebuggerVariablesManager.cxx
new file mode 100644
index 0000000..3013b9f
--- /dev/null
+++ b/Tests/CMakeLib/testDebuggerVariablesManager.cxx
@@ -0,0 +1,50 @@
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
+
+#include <functional>
+#include <memory>
+#include <vector>
+
+#include <cm3p/cppdap/protocol.h>
+#include <cm3p/cppdap/types.h>
+#include <stdint.h>
+
+#include "cmDebuggerVariables.h"
+#include "cmDebuggerVariablesManager.h"
+
+#include "testCommon.h"
+
+static bool testVariablesRegistration()
+{
+ auto variablesManager =
+ std::make_shared<cmDebugger::cmDebuggerVariablesManager>();
+
+ int64_t line = 5;
+ auto local = std::make_shared<cmDebugger::cmDebuggerVariables>(
+ variablesManager, "Local", true, [=]() {
+ return std::vector<cmDebugger::cmDebuggerVariableEntry>{ { "CurrentLine",
+ line } };
+ });
+
+ dap::VariablesRequest variableRequest;
+ variableRequest.variablesReference = local->GetId();
+
+ dap::array<dap::Variable> variables =
+ variablesManager->HandleVariablesRequest(variableRequest);
+
+ ASSERT_TRUE(variables.size() == 1);
+
+ local.reset();
+
+ variables = variablesManager->HandleVariablesRequest(variableRequest);
+ ASSERT_TRUE(variables.size() == 0);
+
+ return true;
+}
+
+int testDebuggerVariablesManager(int, char*[])
+{
+ return runTests(std::vector<std::function<bool()>>{
+ testVariablesRegistration,
+ });
+}
diff --git a/Tests/CMakeLib/testUVProcessChain.cxx b/Tests/CMakeLib/testUVProcessChain.cxx
index c924083..cbb4384 100644
--- a/Tests/CMakeLib/testUVProcessChain.cxx
+++ b/Tests/CMakeLib/testUVProcessChain.cxx
@@ -11,6 +11,7 @@
#include <cm3p/uv.h>
#include "cmGetPipes.h"
+#include "cmStringAlgorithms.h"
#include "cmUVHandlePtr.h"
#include "cmUVProcessChain.h"
#include "cmUVStreambuf.h"
@@ -228,6 +229,61 @@ bool testUVProcessChainBuiltin(const char* helperCommand)
return true;
}
+bool testUVProcessChainBuiltinMerged(const char* helperCommand)
+{
+ cmUVProcessChainBuilder builder;
+ std::unique_ptr<cmUVProcessChain> chain;
+ builder.AddCommand({ helperCommand, "echo" })
+ .AddCommand({ helperCommand, "capitalize" })
+ .AddCommand({ helperCommand, "dedup" })
+ .SetMergedBuiltinStreams();
+
+ if (!checkExecution(builder, chain)) {
+ return false;
+ }
+
+ if (!chain->OutputStream()) {
+ std::cout << "OutputStream() was null, expecting not null" << std::endl;
+ return false;
+ }
+ if (!chain->ErrorStream()) {
+ std::cout << "ErrorStream() was null, expecting not null" << std::endl;
+ return false;
+ }
+ if (chain->OutputStream() != chain->ErrorStream()) {
+ std::cout << "OutputStream() and ErrorStream() expected to be the same"
+ << std::endl;
+ return false;
+ }
+
+ std::string merged = getInput(*chain->OutputStream());
+ auto qemuErrorPos = merged.find("qemu:");
+ if (qemuErrorPos != std::string::npos) {
+ merged.resize(qemuErrorPos);
+ }
+ if (merged.length() != cmStrLen("HELO WRD!123") ||
+ merged.find('1') == std::string::npos ||
+ merged.find('2') == std::string::npos ||
+ merged.find('3') == std::string::npos) {
+ std::cout << "Expected output to contain '1', '2', and '3', was \""
+ << merged << "\"" << std::endl;
+ return false;
+ }
+ std::string output;
+ for (auto const& c : merged) {
+ if (c != '1' && c != '2' && c != '3') {
+ output += c;
+ }
+ }
+ if (output != "HELO WRD!") {
+ std::cout << "Output was \"" << output << "\", expected \"HELO WRD!\""
+ << std::endl;
+ return false;
+ }
+
+ return true;
+}
+
bool testUVProcessChainExternal(const char* helperCommand)
{
cmUVProcessChainBuilder builder;
@@ -314,6 +370,57 @@ bool testUVProcessChainNone(const char* helperCommand)
return true;
}
+bool testUVProcessChainCwdUnchanged(const char* helperCommand)
+{
+ cmUVProcessChainBuilder builder;
+ builder.AddCommand({ helperCommand, "pwd" })
+ .SetBuiltinStream(cmUVProcessChainBuilder::Stream_OUTPUT)
+ .SetBuiltinStream(cmUVProcessChainBuilder::Stream_ERROR);
+
+ auto chain = builder.Start();
+ chain.Wait();
+ if (chain.GetStatus().front()->ExitStatus != 0) {
+ std::cout << "Exit status was " << chain.GetStatus().front()->ExitStatus
+ << ", expecting 0" << std::endl;
+ return false;
+ }
+
+ auto cwd = getInput(*chain.OutputStream());
+ if (!cmHasLiteralSuffix(cwd, "/Tests/CMakeLib")) {
+ std::cout << "Working directory was \"" << cwd
+ << "\", expected to end in \"/Tests/CMakeLib\"" << std::endl;
+ return false;
+ }
+
+ return true;
+}
+
+bool testUVProcessChainCwdChanged(const char* helperCommand)
+{
+ cmUVProcessChainBuilder builder;
+ builder.AddCommand({ helperCommand, "pwd" })
+ .SetBuiltinStream(cmUVProcessChainBuilder::Stream_OUTPUT)
+ .SetBuiltinStream(cmUVProcessChainBuilder::Stream_ERROR)
+ .SetWorkingDirectory("..");
+
+ auto chain = builder.Start();
+ chain.Wait();
+ if (chain.GetStatus().front()->ExitStatus != 0) {
+ std::cout << "Exit status was " << chain.GetStatus().front()->ExitStatus
+ << ", expecting 0" << std::endl;
+ return false;
+ }
+
+ auto cwd = getInput(*chain.OutputStream());
+ if (!cmHasLiteralSuffix(cwd, "/Tests")) {
+ std::cout << "Working directory was \"" << cwd
+ << "\", expected to end in \"/Tests\"" << std::endl;
+ return false;
+ }
+
+ return true;
+}
+
int testUVProcessChain(int argc, char** const argv)
{
if (argc < 2) {
@@ -326,6 +433,11 @@ int testUVProcessChain(int argc, char** const argv)
return -1;
}
+ if (!testUVProcessChainBuiltinMerged(argv[1])) {
+ std::cout << "While executing testUVProcessChainBuiltinMerged().\n";
+ return -1;
+ }
+
if (!testUVProcessChainExternal(argv[1])) {
std::cout << "While executing testUVProcessChainExternal().\n";
return -1;
@@ -336,5 +448,15 @@ int testUVProcessChain(int argc, char** const argv)
return -1;
}
+ if (!testUVProcessChainCwdUnchanged(argv[1])) {
+ std::cout << "While executing testUVProcessChainCwdUnchanged().\n";
+ return -1;
+ }
+
+ if (!testUVProcessChainCwdChanged(argv[1])) {
+ std::cout << "While executing testUVProcessChainCwdChanged().\n";
+ return -1;
+ }
+
return 0;
}
diff --git a/Tests/CMakeLib/testUVProcessChainHelper.cxx b/Tests/CMakeLib/testUVProcessChainHelper.cxx
index bc0ef8e..82dafd2 100644
--- a/Tests/CMakeLib/testUVProcessChainHelper.cxx
+++ b/Tests/CMakeLib/testUVProcessChainHelper.cxx
@@ -7,6 +7,8 @@
#include <string>
#include <thread>
+#include "cmSystemTools.h"
+
static std::string getStdin()
{
char buffer[1024];
@@ -67,6 +69,11 @@ int main(int argc, char** argv)
std::abort();
#endif
}
+ if (command == "pwd") {
+ std::string cwd = cmSystemTools::GetCurrentWorkingDirectory();
+ std::cout << cwd << std::flush;
+ return 0;
+ }
return -1;
}
diff --git a/Tests/Cuda/Complex/CMakeLists.txt b/Tests/Cuda/Complex/CMakeLists.txt
index 63defdf..e252304 100644
--- a/Tests/Cuda/Complex/CMakeLists.txt
+++ b/Tests/Cuda/Complex/CMakeLists.txt
@@ -53,5 +53,6 @@ endif()
if(UNIX)
# Help the shared cuda runtime find libcudart as it is not located
# in a default system searched location
- set_property(TARGET CudaComplexMixedLib PROPERTY BUILD_RPATH ${CMAKE_CUDA_IMPLICIT_LINK_DIRECTORIES})
+ find_package(CUDAToolkit REQUIRED)
+ set_property(TARGET CudaComplexMixedLib PROPERTY BUILD_RPATH "${CUDAToolkit_LIBRARY_DIR}")
endif()
diff --git a/Tests/CudaOnly/SharedRuntimePlusToolkit/CMakeLists.txt b/Tests/CudaOnly/SharedRuntimePlusToolkit/CMakeLists.txt
index 0b01085..7dc919f 100644
--- a/Tests/CudaOnly/SharedRuntimePlusToolkit/CMakeLists.txt
+++ b/Tests/CudaOnly/SharedRuntimePlusToolkit/CMakeLists.txt
@@ -40,5 +40,6 @@ target_link_libraries(CudaOnlySharedRuntimePlusToolkit PRIVATE SharedToolkit
if(UNIX)
# Help the shared cuda runtime find libcudart as it is not located
# in a default system searched location
- set_property(TARGET CudaOnlySharedRuntimePlusToolkit PROPERTY BUILD_RPATH ${CMAKE_CUDA_IMPLICIT_LINK_DIRECTORIES})
+ find_package(CUDAToolkit REQUIRED)
+ set_property(TARGET CudaOnlySharedRuntimePlusToolkit PROPERTY BUILD_RPATH "${CUDAToolkit_LIBRARY_DIR}")
endif()
diff --git a/Tests/CudaOnly/SharedRuntimeViaCUDAFlags/CMakeLists.txt b/Tests/CudaOnly/SharedRuntimeViaCUDAFlags/CMakeLists.txt
index 24ff478..cf6eef2 100644
--- a/Tests/CudaOnly/SharedRuntimeViaCUDAFlags/CMakeLists.txt
+++ b/Tests/CudaOnly/SharedRuntimeViaCUDAFlags/CMakeLists.txt
@@ -11,5 +11,6 @@ add_executable(CudaOnlySharedRuntimeViaCUDAFlags main.cu)
if(UNIX)
# Help the shared cuda runtime find libcudart as it is not located
# in a default system searched location
- set_property(TARGET CudaOnlySharedRuntimeViaCUDAFlags PROPERTY BUILD_RPATH ${CMAKE_CUDA_IMPLICIT_LINK_DIRECTORIES})
+ find_package(CUDAToolkit REQUIRED)
+ set_property(TARGET CudaOnlySharedRuntimeViaCUDAFlags PROPERTY BUILD_RPATH "${CUDAToolkit_LIBRARY_DIR}")
endif()
diff --git a/Tests/CudaOnly/StaticRuntimePlusToolkit/CMakeLists.txt b/Tests/CudaOnly/StaticRuntimePlusToolkit/CMakeLists.txt
index ae03b66..8149060 100644
--- a/Tests/CudaOnly/StaticRuntimePlusToolkit/CMakeLists.txt
+++ b/Tests/CudaOnly/StaticRuntimePlusToolkit/CMakeLists.txt
@@ -39,5 +39,6 @@ target_link_libraries(CudaOnlyStaticRuntimePlusToolkit PRIVATE SharedToolkit
if(UNIX)
# Help the shared cuda runtime find libcurand and libnppif when they are not located
# in a default system searched location
- set_property(TARGET CudaOnlyStaticRuntimePlusToolkit PROPERTY BUILD_RPATH ${CMAKE_CUDA_IMPLICIT_LINK_DIRECTORIES})
+ find_package(CUDAToolkit REQUIRED)
+ set_property(TARGET CudaOnlyStaticRuntimePlusToolkit PROPERTY BUILD_RPATH "${CUDAToolkit_LIBRARY_DIR}")
endif()
diff --git a/Tests/ExternalProjectUpdate/CMakeLists.txt b/Tests/ExternalProjectUpdate/CMakeLists.txt
index 1b84ff3..e8c67b8 100644
--- a/Tests/ExternalProjectUpdate/CMakeLists.txt
+++ b/Tests/ExternalProjectUpdate/CMakeLists.txt
@@ -70,7 +70,9 @@ if(NOT TEST_GIT_TAG)
endif()
if(do_git_tests)
- set(local_git_repo "../../LocalRepositories/GIT")
+ cmake_path(SET local_git_repo NORMALIZE
+ "${CMAKE_CURRENT_BINARY_DIR}/LocalRepositories/GIT"
+ )
# Unzip/untar the git repository in our source folder so that other
# projects below may use it to test git args of ExternalProject_Add
@@ -79,6 +81,7 @@ if(do_git_tests)
ExternalProject_Add(${proj}
SOURCE_DIR ${CMAKE_CURRENT_BINARY_DIR}/LocalRepositories/GIT
URL ${CMAKE_CURRENT_SOURCE_DIR}/gitrepo.tgz
+ DOWNLOAD_EXTRACT_TIMESTAMP NO
BUILD_COMMAND ""
CONFIGURE_COMMAND "${GIT_EXECUTABLE}" --version
INSTALL_COMMAND ""
diff --git a/Tests/ExternalProjectUpdate/ExternalProjectUpdateTest.cmake b/Tests/ExternalProjectUpdate/ExternalProjectUpdateTest.cmake
index 394df87..08e533b 100644
--- a/Tests/ExternalProjectUpdate/ExternalProjectUpdateTest.cmake
+++ b/Tests/ExternalProjectUpdate/ExternalProjectUpdateTest.cmake
@@ -1,8 +1,14 @@
# Set the ExternalProject GIT_TAG to desired_tag, and make sure the
# resulting checked out version is resulting_sha and rebuild.
# This check's the correct behavior of the ExternalProject UPDATE_COMMAND.
-# Also verify that a fetch only occurs when fetch_expected is 1.
-macro(check_a_tag desired_tag resulting_sha fetch_expected update_strategy)
+# Also verify that a fetch only occurs when fetch_expected_tsX is 1.
+macro(check_a_tag
+ desired_tag
+ resulting_sha
+ fetch_expected_ts1 # TutorialStep1-GIT
+ fetch_expected_ts2 # TutorialStep2-GIT
+ update_strategy
+)
message( STATUS "Checking ExternalProjectUpdate to tag: ${desired_tag}" )
# Remove the FETCH_HEAD file, so we can check if it gets replaced with a 'git
@@ -12,7 +18,11 @@ macro(check_a_tag desired_tag resulting_sha fetch_expected update_strategy)
# Give ourselves a marker in the output. It is difficult to tell where we
# are up to without this
- message(STATUS "===> check_a_tag ${desired_tag} ${resulting_sha} ${fetch_expected} ${update_strategy}")
+ message(STATUS "===> check_a_tag: "
+ "${desired_tag} ${resulting_sha} "
+ "${fetch_expected_ts1} ${fetch_expected_ts2} "
+ "${update_strategy}"
+ )
# Configure
execute_process(COMMAND ${CMAKE_COMMAND}
@@ -58,10 +68,10 @@ was expected."
)
endif()
- if( NOT EXISTS ${FETCH_HEAD_file} AND ${fetch_expected})
+ if( NOT EXISTS ${FETCH_HEAD_file} AND ${fetch_expected_ts1})
message( FATAL_ERROR "Fetch did NOT occur when it was expected.")
endif()
- if( EXISTS ${FETCH_HEAD_file} AND NOT ${fetch_expected})
+ if( EXISTS ${FETCH_HEAD_file} AND NOT ${fetch_expected_ts1})
message( FATAL_ERROR "Fetch DID occur when it was not expected.")
endif()
@@ -154,10 +164,10 @@ was expected."
)
endif()
- if( NOT EXISTS ${FETCH_HEAD_file} AND ${fetch_expected})
+ if( NOT EXISTS ${FETCH_HEAD_file} AND ${fetch_expected_ts2})
message( FATAL_ERROR "Fetch did NOT occur when it was expected.")
endif()
- if( EXISTS ${FETCH_HEAD_file} AND NOT ${fetch_expected})
+ if( EXISTS ${FETCH_HEAD_file} AND NOT ${fetch_expected_ts2})
message( FATAL_ERROR "Fetch DID occur when it was not expected.")
endif()
endmacro()
@@ -179,16 +189,16 @@ endif()
file(REMOVE_RECURSE ${ExternalProjectUpdate_BINARY_DIR}/CMakeExternals)
if(do_git_tests)
- check_a_tag(origin/master b5752a26ae448410926b35c275af3c192a53722e 1 REBASE)
- check_a_tag(tag1 d1970730310fe8bc07e73f15dc570071f9f9654a 1 REBASE)
+ check_a_tag(origin/master b5752a26ae448410926b35c275af3c192a53722e 1 1 REBASE)
+ check_a_tag(tag1 d1970730310fe8bc07e73f15dc570071f9f9654a 1 0 REBASE)
# With the Git UPDATE_COMMAND performance patch, this will not require a
# 'git fetch'
- check_a_tag(tag1 d1970730310fe8bc07e73f15dc570071f9f9654a 0 REBASE)
- check_a_tag(tag2 5842b503ba4113976d9bb28d57b5aee1ad2736b7 1 REBASE)
- check_a_tag(d19707303 d1970730310fe8bc07e73f15dc570071f9f9654a 0 REBASE)
- check_a_tag(origin/master b5752a26ae448410926b35c275af3c192a53722e 1 REBASE)
+ check_a_tag(tag1 d1970730310fe8bc07e73f15dc570071f9f9654a 0 0 REBASE)
+ check_a_tag(tag2 5842b503ba4113976d9bb28d57b5aee1ad2736b7 1 0 REBASE)
+ check_a_tag(d19707303 d1970730310fe8bc07e73f15dc570071f9f9654a 0 0 REBASE)
+ check_a_tag(origin/master b5752a26ae448410926b35c275af3c192a53722e 1 1 REBASE)
# This is a remote symbolic ref, so it will always trigger a 'git fetch'
- check_a_tag(origin/master b5752a26ae448410926b35c275af3c192a53722e 1 REBASE)
+ check_a_tag(origin/master b5752a26ae448410926b35c275af3c192a53722e 1 1 REBASE)
foreach(strategy IN ITEMS CHECKOUT REBASE_CHECKOUT)
# Move local master back, then apply a change that will cause a conflict
@@ -222,7 +232,7 @@ if(do_git_tests)
message(FATAL_ERROR "Could not commit conflicting change.")
endif()
# This should discard our commit but leave behind an annotated tag
- check_a_tag(origin/master b5752a26ae448410926b35c275af3c192a53722e 1 ${strategy})
+ check_a_tag(origin/master b5752a26ae448410926b35c275af3c192a53722e 1 1 ${strategy})
endforeach()
# This file matches a .gitignore rule that the last commit defines. We can't
@@ -232,7 +242,7 @@ if(do_git_tests)
# doesn't choke on it.
set(ignoredFile ${ExternalProjectUpdate_BINARY_DIR}/CMakeExternals/Source/TutorialStep1-GIT/ignored_item)
file(TOUCH ${ignoredFile})
- check_a_tag(origin/master b5752a26ae448410926b35c275af3c192a53722e 1 REBASE)
+ check_a_tag(origin/master b5752a26ae448410926b35c275af3c192a53722e 1 1 REBASE)
if(NOT EXISTS ${ignoredFile})
message(FATAL_ERROR "Ignored file is missing")
endif()
diff --git a/Tests/FindOpenAL/Test/main.cxx b/Tests/FindOpenAL/Test/main.cxx
index 1396c60..27204fb 100644
--- a/Tests/FindOpenAL/Test/main.cxx
+++ b/Tests/FindOpenAL/Test/main.cxx
@@ -10,9 +10,10 @@
int main()
{
/* Reference an AL symbol without requiring a context at runtime. */
- printf("&alGetString = %p\n", &alGetString);
+ printf("AL_VERSION: %s\n", alGetString(AL_VERSION));
/* Reference an ALC symbol without requiring a context at runtime. */
- printf("&alcGetString = %p\n", &alcGetString);
+ printf("ALC_DEVICE_SPECIFIER: %s\n",
+ alcGetString(NULL, ALC_DEVICE_SPECIFIER));
return 0;
}
diff --git a/Tests/Module/ExternalData/Data1Check.cmake b/Tests/Module/ExternalData/Data1Check.cmake
index f60c209..7fe4389 100644
--- a/Tests/Module/ExternalData/Data1Check.cmake
+++ b/Tests/Module/ExternalData/Data1Check.cmake
@@ -1,24 +1,24 @@
file(STRINGS "${Data}" lines LIMIT_INPUT 1024)
if(NOT "x${lines}" STREQUAL "xInput file already transformed.")
- message(SEND_ERROR "Input file:\n ${Data}\ndoes not have expected content, but [[${lines}]]")
+ message(SEND_ERROR "Input file:\n ${Data}\n" "does not have expected content, but [[${lines}]]")
endif()
if(DEFINED DataSpace)
file(STRINGS "${DataSpace}" lines LIMIT_INPUT 1024)
if(NOT "x${lines}" STREQUAL "xInput file already transformed.")
- message(SEND_ERROR "Input file:\n ${DataSpace}\ndoes not have expected content, but [[${lines}]]")
+ message(SEND_ERROR "Input file:\n ${DataSpace}\n" "does not have expected content, but [[${lines}]]")
endif()
endif()
file(STRINGS "${DataScript}" lines LIMIT_INPUT 1024)
if(NOT "x${lines}" STREQUAL "xDataScript")
- message(SEND_ERROR "Input file:\n ${DataScript}\ndoes not have expected content, but [[${lines}]]")
+ message(SEND_ERROR "Input file:\n ${DataScript}\n" "does not have expected content, but [[${lines}]]")
endif()
file(STRINGS "${DataAlgoMapA}" lines LIMIT_INPUT 1024)
if(NOT "x${lines}" STREQUAL "xDataAlgoMap")
- message(SEND_ERROR "Input file:\n ${DataAlgoMapA}\ndoes not have expected content, but [[${lines}]]")
+ message(SEND_ERROR "Input file:\n ${DataAlgoMapA}\n" "does not have expected content, but [[${lines}]]")
endif()
file(STRINGS "${DataAlgoMapB}" lines LIMIT_INPUT 1024)
if(NOT "x${lines}" STREQUAL "xDataAlgoMap")
- message(SEND_ERROR "Input file:\n ${DataAlgoMapB}\ndoes not have expected content, but [[${lines}]]")
+ message(SEND_ERROR "Input file:\n ${DataAlgoMapB}\n" "does not have expected content, but [[${lines}]]")
endif()
if(DataMissing)
if(EXISTS "${DataMissing}")
@@ -54,7 +54,7 @@ foreach(s A B C D)
foreach(n "" ${Series${s}l})
string(REGEX REPLACE "\\.dat$" "${n}.dat" file "${Series${s}}")
if(NOT EXISTS "${file}")
- message(SEND_ERROR "Input file:\n ${file}\ndoes not exist!")
+ message(SEND_ERROR "Input file:\n ${file}\n" "does not exist!")
endif()
endforeach()
endforeach()
@@ -62,45 +62,45 @@ foreach(s A B C D)
foreach(n ${Series${s}l})
string(REGEX REPLACE "${Series${s}n1}$" "${n}.dat" file "${Series${s}n}")
if(NOT EXISTS "${file}")
- message(SEND_ERROR "Input file:\n ${file}\ndoes not exist!")
+ message(SEND_ERROR "Input file:\n ${file}\n" "does not exist!")
endif()
endforeach()
endforeach()
foreach(n .1 .2 .3 .4)
string(REGEX REPLACE "\\.1\\.dat$" "${n}.dat" file "${SeriesMixed}")
if(NOT EXISTS "${file}")
- message(SEND_ERROR "Input file:\n ${file}\ndoes not exist!")
+ message(SEND_ERROR "Input file:\n ${file}\n" "does not exist!")
endif()
endforeach()
foreach(n A B)
string(REGEX REPLACE "A\\.dat$" "${n}.dat" file "${Paired}")
if(NOT EXISTS "${file}")
- message(SEND_ERROR "Input file:\n ${file}\ndoes not exist!")
+ message(SEND_ERROR "Input file:\n ${file}\n" "does not exist!")
endif()
endforeach()
foreach(n Top A B C)
string(REGEX REPLACE "Top\\.dat$" "${n}.dat" file "${Meta}")
if(NOT EXISTS "${file}")
- message(SEND_ERROR "Input file:\n ${file}\ndoes not exist!")
+ message(SEND_ERROR "Input file:\n ${file}\n" "does not exist!")
endif()
endforeach()
foreach(n A B C)
set(file "${Directory}/${n}.dat")
if(NOT EXISTS "${file}")
- message(SEND_ERROR "Input file:\n ${file}\ndoes not exist!")
+ message(SEND_ERROR "Input file:\n ${file}\n" "does not exist!")
endif()
endforeach()
foreach(n A Sub1/A Sub2/Dir/A B Sub1/B Sub2/Dir/B C Sub1/C Sub2/Dir/C)
set(file "${DirRecurse}/${n}.dat")
if(NOT EXISTS "${file}")
- message(SEND_ERROR "Input file:\n ${file}\ndoes not exist!")
+ message(SEND_ERROR "Input file:\n ${file}\n" "does not exist!")
endif()
endforeach()
list(LENGTH Semicolons len)
if("${len}" EQUAL 2)
foreach(file ${Semicolons})
if(NOT EXISTS "${file}")
- message(SEND_ERROR "Input file:\n ${file}\ndoes not exist!")
+ message(SEND_ERROR "Input file:\n ${file}\n" "does not exist!")
endif()
endforeach()
else()
diff --git a/Tests/Module/ExternalData/Data2/Data2Check.cmake b/Tests/Module/ExternalData/Data2/Data2Check.cmake
index d5b0c7b..412593c 100644
--- a/Tests/Module/ExternalData/Data2/Data2Check.cmake
+++ b/Tests/Module/ExternalData/Data2/Data2Check.cmake
@@ -1,12 +1,12 @@
foreach(d "${Data2}" "${Data2b}")
file(STRINGS "${d}" lines LIMIT_INPUT 1024)
if(NOT "x${lines}" STREQUAL "xInput file already transformed.")
- message(SEND_ERROR "Input file:\n ${d}\ndoes not have expected content, but [[${lines}]]")
+ message(SEND_ERROR "Input file:\n ${d}\n" "does not have expected content, but [[${lines}]]")
endif()
endforeach()
foreach(n 1 2 3)
string(REGEX REPLACE "_1_\\.my\\.dat$" "_${n}_.my.dat" SeriesCFile "${SeriesC}")
if(NOT EXISTS "${SeriesCFile}")
- message(SEND_ERROR "Input file:\n ${SeriesCFile}\ndoes not exist!")
+ message(SEND_ERROR "Input file:\n ${SeriesCFile}\n" "does not exist!")
endif()
endforeach()
diff --git a/Tests/Module/ExternalData/Data3/Data3Check.cmake b/Tests/Module/ExternalData/Data3/Data3Check.cmake
index de98839..da79fdb 100644
--- a/Tests/Module/ExternalData/Data3/Data3Check.cmake
+++ b/Tests/Module/ExternalData/Data3/Data3Check.cmake
@@ -1,8 +1,8 @@
if(NOT EXISTS "${Data}")
- message(SEND_ERROR "Input file:\n ${Data}\ndoes not exist!")
+ message(SEND_ERROR "Input file:\n ${Data}\n" "does not exist!")
endif()
if(NOT EXISTS "${Other}")
- message(SEND_ERROR "Input file:\n ${Other}\ndoes not exist!")
+ message(SEND_ERROR "Input file:\n ${Other}\n" "does not exist!")
endif()
# Verify that the 'Data' object was found in the second store location left
# from Data1 target downloads and that the 'Other' object was downloaded to
diff --git a/Tests/Module/ExternalData/Data4/Data4Check.cmake b/Tests/Module/ExternalData/Data4/Data4Check.cmake
index e614cc4..a1d82d5 100644
--- a/Tests/Module/ExternalData/Data4/Data4Check.cmake
+++ b/Tests/Module/ExternalData/Data4/Data4Check.cmake
@@ -1,8 +1,8 @@
if(NOT EXISTS "${Data}")
- message(SEND_ERROR "Input file:\n ${Data}\ndoes not exist!")
+ message(SEND_ERROR "Input file:\n ${Data}\n" "does not exist!")
endif()
if(NOT EXISTS "${Other}")
- message(SEND_ERROR "Input file:\n ${Other}\ndoes not exist!")
+ message(SEND_ERROR "Input file:\n ${Other}\n" "does not exist!")
endif()
# Verify that the 'Data' object was found in the second store location left
# from Data1 target downloads and that the 'Other' object was found in the
diff --git a/Tests/Module/ExternalData/Data5/Data5Check.cmake b/Tests/Module/ExternalData/Data5/Data5Check.cmake
index 4dea9a4..79c2161 100644
--- a/Tests/Module/ExternalData/Data5/Data5Check.cmake
+++ b/Tests/Module/ExternalData/Data5/Data5Check.cmake
@@ -1,4 +1,4 @@
file(STRINGS "${Data5}" lines LIMIT_INPUT 1024)
if(NOT "x${lines}" STREQUAL "xInput file already transformed.")
- message(SEND_ERROR "Input file:\n ${Data5}\ndoes not have expected content, but [[${lines}]]")
+ message(SEND_ERROR "Input file:\n ${Data5}\n" "does not have expected content, but [[${lines}]]")
endif()
diff --git a/Tests/Module/ExternalData/DataNoSymlinks/DataNoSymlinksCheck.cmake b/Tests/Module/ExternalData/DataNoSymlinks/DataNoSymlinksCheck.cmake
index 2be3571..a73668a 100644
--- a/Tests/Module/ExternalData/DataNoSymlinks/DataNoSymlinksCheck.cmake
+++ b/Tests/Module/ExternalData/DataNoSymlinks/DataNoSymlinksCheck.cmake
@@ -1,5 +1,5 @@
if(NOT EXISTS "${Data}")
- message(SEND_ERROR "Input file:\n ${Data}\ndoes not exist!")
+ message(SEND_ERROR "Input file:\n ${Data}\n" "does not exist!")
endif()
if(IS_SYMLINK "${Data}")
message(SEND_ERROR "Input file:\n ${Data}\nis a symlink but should not be!")
diff --git a/Tests/QtAutogen/AutoMocGeneratedFile/CMakeLists.txt b/Tests/QtAutogen/AutoMocGeneratedFile/CMakeLists.txt
new file mode 100644
index 0000000..ce129a9
--- /dev/null
+++ b/Tests/QtAutogen/AutoMocGeneratedFile/CMakeLists.txt
@@ -0,0 +1,23 @@
+cmake_minimum_required(VERSION 3.26)
+project(AutoMocGeneratedFile)
+
+include("../AutogenCoreTest.cmake")
+
+file(GENERATE OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/myConfig.h
+ CONTENT
+ "
+#ifndef MYCONFIG_H
+#define MYCONFIG_H
+
+inline void foo() {}
+
+#endif
+
+"
+)
+
+add_executable(testTarget
+ main.cpp
+ ${CMAKE_CURRENT_BINARY_DIR}/myConfig.h)
+target_include_directories(testTarget PRIVATE ${CMAKE_CURRENT_BINARY_DIR})
+set_property(TARGET testTarget PROPERTY AUTOMOC ON)
diff --git a/Tests/QtAutogen/AutoMocGeneratedFile/main.cpp b/Tests/QtAutogen/AutoMocGeneratedFile/main.cpp
new file mode 100644
index 0000000..e30d889
--- /dev/null
+++ b/Tests/QtAutogen/AutoMocGeneratedFile/main.cpp
@@ -0,0 +1,7 @@
+#include "myConfig.h"
+
+int main()
+{
+ foo();
+ return 0;
+}
diff --git a/Tests/QtAutogen/Tests.cmake b/Tests/QtAutogen/Tests.cmake
index 3e4f04d..7dd9c84 100644
--- a/Tests/QtAutogen/Tests.cmake
+++ b/Tests/QtAutogen/Tests.cmake
@@ -2,6 +2,7 @@
ADD_AUTOGEN_TEST(AutogenOriginDependsOff autogenOriginDependsOff)
ADD_AUTOGEN_TEST(AutogenOriginDependsOn)
ADD_AUTOGEN_TEST(AutogenTargetDepends)
+ADD_AUTOGEN_TEST(AutoMocGeneratedFile)
ADD_AUTOGEN_TEST(Complex QtAutogen)
ADD_AUTOGEN_TEST(GlobalAutogenSystemUseInclude)
ADD_AUTOGEN_TEST(GlobalAutogenTarget)
diff --git a/Tests/RunCMake/CXXModules/examples/export-bmi-and-interface-build-stderr.txt b/Tests/RunCMake/CXXModules/examples/export-bmi-and-interface-build-stderr.txt
index 5e4392a..c8dbdcf 100644
--- a/Tests/RunCMake/CXXModules/examples/export-bmi-and-interface-build-stderr.txt
+++ b/Tests/RunCMake/CXXModules/examples/export-bmi-and-interface-build-stderr.txt
@@ -1,4 +1,4 @@
-CMake Warning \(dev\) at CMakeLists.txt:7 \(target_sources\):
+CMake Warning \(dev\) at CMakeLists.txt:[0-9]+ \(target_sources\):
CMake's C\+\+ module support is experimental. It is meant only for
experimentation and feedback to CMake developers.
This warning is for project developers. Use -Wno-dev to suppress it.
diff --git a/Tests/RunCMake/CXXModules/examples/export-bmi-and-interface-build/CMakeLists.txt b/Tests/RunCMake/CXXModules/examples/export-bmi-and-interface-build/CMakeLists.txt
index a450b7e..71e7b62 100644
--- a/Tests/RunCMake/CXXModules/examples/export-bmi-and-interface-build/CMakeLists.txt
+++ b/Tests/RunCMake/CXXModules/examples/export-bmi-and-interface-build/CMakeLists.txt
@@ -18,10 +18,14 @@ target_sources(export_bmi_and_interfaces
BASE_DIRS
"${CMAKE_CURRENT_SOURCE_DIR}"
FILES
- importable.cxx)
+ importable.cxx
+ subdir/importable.cxx
+ )
target_compile_features(export_bmi_and_interfaces PUBLIC cxx_std_20)
-install(TARGETS export_bmi_and_interfaces
+add_library(no_modules STATIC no_modules.cxx)
+
+install(TARGETS export_bmi_and_interfaces no_modules
EXPORT CXXModules
FILE_SET modules DESTINATION "lib/cxx/miu"
CXX_MODULES_BMI DESTINATION "lib/cxx/bmi")
diff --git a/Tests/RunCMake/CXXModules/examples/export-bmi-and-interface-build/no_modules.cxx b/Tests/RunCMake/CXXModules/examples/export-bmi-and-interface-build/no_modules.cxx
new file mode 100644
index 0000000..eea854f
--- /dev/null
+++ b/Tests/RunCMake/CXXModules/examples/export-bmi-and-interface-build/no_modules.cxx
@@ -0,0 +1,3 @@
+void no_modules()
+{
+}
diff --git a/Tests/RunCMake/CXXModules/examples/export-bmi-and-interface-build/subdir/importable.cxx b/Tests/RunCMake/CXXModules/examples/export-bmi-and-interface-build/subdir/importable.cxx
new file mode 100644
index 0000000..07d6af6
--- /dev/null
+++ b/Tests/RunCMake/CXXModules/examples/export-bmi-and-interface-build/subdir/importable.cxx
@@ -0,0 +1,6 @@
+export module subdir_importable;
+
+export int from_subdir()
+{
+ return 0;
+}
diff --git a/Tests/RunCMake/CXXModules/examples/export-bmi-and-interface-build/test/CMakeLists.txt b/Tests/RunCMake/CXXModules/examples/export-bmi-and-interface-build/test/CMakeLists.txt
index 2e37da2..3cb185c 100644
--- a/Tests/RunCMake/CXXModules/examples/export-bmi-and-interface-build/test/CMakeLists.txt
+++ b/Tests/RunCMake/CXXModules/examples/export-bmi-and-interface-build/test/CMakeLists.txt
@@ -14,19 +14,31 @@ get_property(file_sets TARGET CXXModules::export_bmi_and_interfaces
PROPERTY INTERFACE_CXX_MODULE_SETS)
if (NOT file_sets STREQUAL "modules")
message(FATAL_ERROR
- "Incorrect exported file sets in `CXXModules::export_bmi_and_interfaces`: `${file_sets}`")
+ "Incorrect exported file sets in CXXModules::export_bmi_and_interfaces:\n ${file_sets}")
endif ()
get_property(file_set_files TARGET CXXModules::export_bmi_and_interfaces
PROPERTY CXX_MODULE_SET_modules)
-if (NOT file_set_files STREQUAL "${expected_source_dir}/importable.cxx")
+set(expected_file_set_files
+ "${expected_source_dir}/importable.cxx"
+ "${expected_source_dir}/subdir/importable.cxx"
+ )
+if (NOT file_set_files STREQUAL "${expected_file_set_files}")
message(FATAL_ERROR
- "Incorrect exported file set paths in CXXModules::export_bmi_and_interfaces`: `${file_set_files}`")
+ "Incorrect exported file set paths in CXXModules::export_bmi_and_interfaces:\n ${file_set_files}")
endif ()
get_property(imported_modules TARGET CXXModules::export_bmi_and_interfaces
PROPERTY IMPORTED_CXX_MODULES_DEBUG)
-if (NOT imported_modules MATCHES "importable=${expected_source_dir}/importable.cxx,${expected_binary_dir}/CMakeFiles/export_bmi_and_interfaces.dir(/Debug)?/importable.(gcm|pcm|ifc)")
+set(expected_imported_modules
+ "importable=${expected_source_dir}/importable.cxx,${expected_binary_dir}/CMakeFiles/export_bmi_and_interfaces.dir(/Debug)?/importable.(gcm|pcm|ifc)"
+ "subdir_importable=${expected_source_dir}/subdir/importable.cxx,${expected_binary_dir}/CMakeFiles/export_bmi_and_interfaces.dir(/Debug)?/subdir_importable.(gcm|pcm|ifc)"
+ )
+if (NOT imported_modules MATCHES "^${expected_imported_modules}$")
message(FATAL_ERROR
- "Incorrect exported modules in CXXModules::export_bmi_and_interfaces`: `${imported_modules}`")
+ "Incorrect exported modules in CXXModules::export_bmi_and_interfaces:\n"
+ " ${imported_modules}\n"
+ "does not match:\n"
+ " ${expected_imported_modules}"
+ )
endif ()
diff --git a/Tests/RunCMake/CXXModules/examples/export-bmi-and-interface-install-stderr.txt b/Tests/RunCMake/CXXModules/examples/export-bmi-and-interface-install-stderr.txt
index 5e4392a..c8dbdcf 100644
--- a/Tests/RunCMake/CXXModules/examples/export-bmi-and-interface-install-stderr.txt
+++ b/Tests/RunCMake/CXXModules/examples/export-bmi-and-interface-install-stderr.txt
@@ -1,4 +1,4 @@
-CMake Warning \(dev\) at CMakeLists.txt:7 \(target_sources\):
+CMake Warning \(dev\) at CMakeLists.txt:[0-9]+ \(target_sources\):
CMake's C\+\+ module support is experimental. It is meant only for
experimentation and feedback to CMake developers.
This warning is for project developers. Use -Wno-dev to suppress it.
diff --git a/Tests/RunCMake/CXXModules/examples/export-bmi-and-interface-install/CMakeLists.txt b/Tests/RunCMake/CXXModules/examples/export-bmi-and-interface-install/CMakeLists.txt
index a5574fe..e675507 100644
--- a/Tests/RunCMake/CXXModules/examples/export-bmi-and-interface-install/CMakeLists.txt
+++ b/Tests/RunCMake/CXXModules/examples/export-bmi-and-interface-install/CMakeLists.txt
@@ -18,10 +18,14 @@ target_sources(export_bmi_and_interfaces
BASE_DIRS
"${CMAKE_CURRENT_SOURCE_DIR}"
FILES
- importable.cxx)
+ importable.cxx
+ subdir/importable.cxx
+ )
target_compile_features(export_bmi_and_interfaces PUBLIC cxx_std_20)
-install(TARGETS export_bmi_and_interfaces
+add_library(no_modules STATIC no_modules.cxx)
+
+install(TARGETS export_bmi_and_interfaces no_modules
EXPORT CXXModules
FILE_SET modules DESTINATION "lib/cxx/miu"
CXX_MODULES_BMI DESTINATION "lib/cxx/bmi")
diff --git a/Tests/RunCMake/CXXModules/examples/export-bmi-and-interface-install/no_modules.cxx b/Tests/RunCMake/CXXModules/examples/export-bmi-and-interface-install/no_modules.cxx
new file mode 100644
index 0000000..eea854f
--- /dev/null
+++ b/Tests/RunCMake/CXXModules/examples/export-bmi-and-interface-install/no_modules.cxx
@@ -0,0 +1,3 @@
+void no_modules()
+{
+}
diff --git a/Tests/RunCMake/CXXModules/examples/export-bmi-and-interface-install/subdir/importable.cxx b/Tests/RunCMake/CXXModules/examples/export-bmi-and-interface-install/subdir/importable.cxx
new file mode 100644
index 0000000..07d6af6
--- /dev/null
+++ b/Tests/RunCMake/CXXModules/examples/export-bmi-and-interface-install/subdir/importable.cxx
@@ -0,0 +1,6 @@
+export module subdir_importable;
+
+export int from_subdir()
+{
+ return 0;
+}
diff --git a/Tests/RunCMake/CXXModules/examples/export-bmi-and-interface-install/test/CMakeLists.txt b/Tests/RunCMake/CXXModules/examples/export-bmi-and-interface-install/test/CMakeLists.txt
index 1adccb3..7b36f8c 100644
--- a/Tests/RunCMake/CXXModules/examples/export-bmi-and-interface-install/test/CMakeLists.txt
+++ b/Tests/RunCMake/CXXModules/examples/export-bmi-and-interface-install/test/CMakeLists.txt
@@ -14,19 +14,31 @@ get_property(file_sets TARGET CXXModules::export_bmi_and_interfaces
PROPERTY INTERFACE_CXX_MODULE_SETS)
if (NOT file_sets STREQUAL "modules")
message(FATAL_ERROR
- "Incorrect exported file sets in `CXXModules::export_bmi_and_interfaces`: `${file_sets}`")
+ "Incorrect exported file sets in CXXModules::export_bmi_and_interfaces:\n ${file_sets}")
endif ()
get_property(file_set_files TARGET CXXModules::export_bmi_and_interfaces
PROPERTY CXX_MODULE_SET_modules)
-if (NOT file_set_files STREQUAL "${expected_source_dir}/importable.cxx")
+set(expected_file_set_files
+ "${expected_source_dir}/importable.cxx"
+ "${expected_source_dir}/subdir/importable.cxx"
+ )
+if (NOT file_set_files STREQUAL "${expected_file_set_files}")
message(FATAL_ERROR
- "Incorrect exported file set paths in CXXModules::export_bmi_and_interfaces`: `${file_set_files}`")
+ "Incorrect exported file set paths in CXXModules::export_bmi_and_interfaces:\n ${file_set_files}")
endif ()
get_property(imported_modules TARGET CXXModules::export_bmi_and_interfaces
PROPERTY IMPORTED_CXX_MODULES_DEBUG)
-if (NOT imported_modules MATCHES "importable=${expected_source_dir}/importable.cxx,${expected_binary_dir}/importable.(gcm|pcm|ifc)")
+set(expected_imported_modules
+ "importable=${expected_source_dir}/importable.cxx,${expected_binary_dir}/importable.(gcm|pcm|ifc)"
+ "subdir_importable=${expected_source_dir}/subdir/importable.cxx,${expected_binary_dir}/subdir_importable.(gcm|pcm|ifc)"
+ )
+if (NOT imported_modules MATCHES "^${expected_imported_modules}$")
message(FATAL_ERROR
- "Incorrect exported modules in CXXModules::export_bmi_and_interfaces`: `${imported_modules}`")
+ "Incorrect exported modules in CXXModules::export_bmi_and_interfaces:\n"
+ " ${imported_modules}\n"
+ "does not match:\n"
+ " ${expected_imported_modules}"
+ )
endif ()
diff --git a/Tests/RunCMake/CXXModules/examples/export-interface-build-stderr.txt b/Tests/RunCMake/CXXModules/examples/export-interface-build-stderr.txt
index 5e4392a..e318a34 100644
--- a/Tests/RunCMake/CXXModules/examples/export-interface-build-stderr.txt
+++ b/Tests/RunCMake/CXXModules/examples/export-interface-build-stderr.txt
@@ -1,4 +1,4 @@
-CMake Warning \(dev\) at CMakeLists.txt:7 \(target_sources\):
+CMake Warning \(dev\) at CMakeLists.txt:[0-9] \(target_sources\):
CMake's C\+\+ module support is experimental. It is meant only for
experimentation and feedback to CMake developers.
This warning is for project developers. Use -Wno-dev to suppress it.
diff --git a/Tests/RunCMake/CXXModules/examples/export-interface-build/CMakeLists.txt b/Tests/RunCMake/CXXModules/examples/export-interface-build/CMakeLists.txt
index 8584dce..136e885 100644
--- a/Tests/RunCMake/CXXModules/examples/export-interface-build/CMakeLists.txt
+++ b/Tests/RunCMake/CXXModules/examples/export-interface-build/CMakeLists.txt
@@ -18,10 +18,14 @@ target_sources(export_interfaces
BASE_DIRS
"${CMAKE_CURRENT_SOURCE_DIR}"
FILES
- importable.cxx)
+ importable.cxx
+ subdir/importable.cxx
+ )
target_compile_features(export_interfaces PUBLIC cxx_std_20)
-install(TARGETS export_interfaces
+add_library(no_modules STATIC no_modules.cxx)
+
+install(TARGETS export_interfaces no_modules
EXPORT CXXModules
FILE_SET modules DESTINATION "lib/cxx/miu")
export(EXPORT CXXModules
diff --git a/Tests/RunCMake/CXXModules/examples/export-interface-build/no_modules.cxx b/Tests/RunCMake/CXXModules/examples/export-interface-build/no_modules.cxx
new file mode 100644
index 0000000..eea854f
--- /dev/null
+++ b/Tests/RunCMake/CXXModules/examples/export-interface-build/no_modules.cxx
@@ -0,0 +1,3 @@
+void no_modules()
+{
+}
diff --git a/Tests/RunCMake/CXXModules/examples/export-interface-build/subdir/importable.cxx b/Tests/RunCMake/CXXModules/examples/export-interface-build/subdir/importable.cxx
new file mode 100644
index 0000000..07d6af6
--- /dev/null
+++ b/Tests/RunCMake/CXXModules/examples/export-interface-build/subdir/importable.cxx
@@ -0,0 +1,6 @@
+export module subdir_importable;
+
+export int from_subdir()
+{
+ return 0;
+}
diff --git a/Tests/RunCMake/CXXModules/examples/export-interface-build/test/CMakeLists.txt b/Tests/RunCMake/CXXModules/examples/export-interface-build/test/CMakeLists.txt
index 9949969..1874c97 100644
--- a/Tests/RunCMake/CXXModules/examples/export-interface-build/test/CMakeLists.txt
+++ b/Tests/RunCMake/CXXModules/examples/export-interface-build/test/CMakeLists.txt
@@ -14,19 +14,31 @@ get_property(file_sets TARGET CXXModules::export_interfaces
PROPERTY INTERFACE_CXX_MODULE_SETS)
if (NOT file_sets STREQUAL "modules")
message(FATAL_ERROR
- "Incorrect exported file sets in `CXXModules::export_interfaces`: `${file_sets}`")
+ "Incorrect exported file sets in CXXModules::export_interfaces:\n ${file_sets}")
endif ()
get_property(file_set_files TARGET CXXModules::export_interfaces
PROPERTY CXX_MODULE_SET_modules)
-if (NOT file_set_files STREQUAL "${expected_source_dir}/importable.cxx")
+set(expected_file_set_files
+ "${expected_source_dir}/importable.cxx"
+ "${expected_source_dir}/subdir/importable.cxx"
+ )
+if (NOT file_set_files STREQUAL "${expected_file_set_files}")
message(FATAL_ERROR
- "Incorrect exported file set paths in CXXModules::export_interfaces`: `${file_set_files}`")
+ "Incorrect exported file set paths in CXXModules::export_interfaces:\n ${file_set_files}")
endif ()
get_property(imported_modules TARGET CXXModules::export_interfaces
PROPERTY IMPORTED_CXX_MODULES_DEBUG)
-if (NOT imported_modules MATCHES "importable=${expected_source_dir}/importable.cxx,${expected_binary_dir}/CMakeFiles/export_interfaces.dir(/Debug)?/importable.(gcm|pcm|ifc)")
+set(expected_imported_modules
+ "importable=${expected_source_dir}/importable.cxx,${expected_binary_dir}/CMakeFiles/export_interfaces.dir(/Debug)?/importable.(gcm|pcm|ifc)"
+ "subdir_importable=${expected_source_dir}/subdir/importable.cxx,${expected_binary_dir}/CMakeFiles/export_interfaces.dir(/Debug)?/subdir_importable.(gcm|pcm|ifc)"
+ )
+if (NOT imported_modules MATCHES "^${expected_imported_modules}$")
message(FATAL_ERROR
- "Incorrect exported modules in CXXModules::export_interfaces`: `${imported_modules}`\n`importable=${expected_source_dir}/importable.cxx,${expected_binary_dir}/CMakeFiles/export_interfaces.dir(/Debug)?/importable.(gcm|pcm|ifc)`")
+ "Incorrect exported modules in CXXModules::export_interfaces:\n"
+ " ${imported_modules}\n"
+ "does not match:\n"
+ " ${expected_imported_modules}"
+ )
endif ()
diff --git a/Tests/RunCMake/CXXModules/examples/export-interface-install-stderr.txt b/Tests/RunCMake/CXXModules/examples/export-interface-install-stderr.txt
index 5e4392a..c8dbdcf 100644
--- a/Tests/RunCMake/CXXModules/examples/export-interface-install-stderr.txt
+++ b/Tests/RunCMake/CXXModules/examples/export-interface-install-stderr.txt
@@ -1,4 +1,4 @@
-CMake Warning \(dev\) at CMakeLists.txt:7 \(target_sources\):
+CMake Warning \(dev\) at CMakeLists.txt:[0-9]+ \(target_sources\):
CMake's C\+\+ module support is experimental. It is meant only for
experimentation and feedback to CMake developers.
This warning is for project developers. Use -Wno-dev to suppress it.
diff --git a/Tests/RunCMake/CXXModules/examples/export-interface-install/CMakeLists.txt b/Tests/RunCMake/CXXModules/examples/export-interface-install/CMakeLists.txt
index b5c6224..df87980 100644
--- a/Tests/RunCMake/CXXModules/examples/export-interface-install/CMakeLists.txt
+++ b/Tests/RunCMake/CXXModules/examples/export-interface-install/CMakeLists.txt
@@ -18,10 +18,14 @@ target_sources(export_interfaces
BASE_DIRS
"${CMAKE_CURRENT_SOURCE_DIR}"
FILES
- importable.cxx)
+ importable.cxx
+ subdir/importable.cxx
+ )
target_compile_features(export_interfaces PUBLIC cxx_std_20)
-install(TARGETS export_interfaces
+add_library(no_modules STATIC no_modules.cxx)
+
+install(TARGETS export_interfaces no_modules
EXPORT CXXModules
FILE_SET modules DESTINATION "lib/cxx/miu")
install(EXPORT CXXModules
diff --git a/Tests/RunCMake/CXXModules/examples/export-interface-install/no_modules.cxx b/Tests/RunCMake/CXXModules/examples/export-interface-install/no_modules.cxx
new file mode 100644
index 0000000..eea854f
--- /dev/null
+++ b/Tests/RunCMake/CXXModules/examples/export-interface-install/no_modules.cxx
@@ -0,0 +1,3 @@
+void no_modules()
+{
+}
diff --git a/Tests/RunCMake/CXXModules/examples/export-interface-install/subdir/importable.cxx b/Tests/RunCMake/CXXModules/examples/export-interface-install/subdir/importable.cxx
new file mode 100644
index 0000000..07d6af6
--- /dev/null
+++ b/Tests/RunCMake/CXXModules/examples/export-interface-install/subdir/importable.cxx
@@ -0,0 +1,6 @@
+export module subdir_importable;
+
+export int from_subdir()
+{
+ return 0;
+}
diff --git a/Tests/RunCMake/CXXModules/examples/export-interface-install/test/CMakeLists.txt b/Tests/RunCMake/CXXModules/examples/export-interface-install/test/CMakeLists.txt
index 7079256..78177ce 100644
--- a/Tests/RunCMake/CXXModules/examples/export-interface-install/test/CMakeLists.txt
+++ b/Tests/RunCMake/CXXModules/examples/export-interface-install/test/CMakeLists.txt
@@ -14,19 +14,31 @@ get_property(file_sets TARGET CXXModules::export_interfaces
PROPERTY INTERFACE_CXX_MODULE_SETS)
if (NOT file_sets STREQUAL "modules")
message(FATAL_ERROR
- "Incorrect exported file sets in `CXXModules::export_interfaces`: `${file_sets}`")
+ "Incorrect exported file sets in CXXModules::export_interfaces:\n ${file_sets}")
endif ()
get_property(file_set_files TARGET CXXModules::export_interfaces
PROPERTY CXX_MODULE_SET_modules)
-if (NOT file_set_files STREQUAL "${expected_source_dir}/importable.cxx")
+set(expected_file_set_files
+ "${expected_source_dir}/importable.cxx"
+ "${expected_source_dir}/subdir/importable.cxx"
+ )
+if (NOT file_set_files STREQUAL "${expected_file_set_files}")
message(FATAL_ERROR
- "Incorrect exported file set paths in CXXModules::export_interfaces`: `${file_set_files}`")
+ "Incorrect exported file set paths in CXXModules::export_interfaces:\n ${file_set_files}")
endif ()
get_property(imported_modules TARGET CXXModules::export_interfaces
PROPERTY IMPORTED_CXX_MODULES_DEBUG)
-if (NOT imported_modules STREQUAL "importable=${expected_source_dir}/importable.cxx")
+set(expected_imported_modules
+ "importable=${expected_source_dir}/importable.cxx"
+ "subdir_importable=${expected_source_dir}/subdir/importable.cxx"
+ )
+if (NOT imported_modules STREQUAL "${expected_imported_modules}")
message(FATAL_ERROR
- "Incorrect exported modules in CXXModules::export_interfaces`: `${imported_modules}`")
+ "Incorrect exported modules in CXXModules::export_interfaces:\n"
+ " ${imported_modules}\n"
+ "does not match:\n"
+ " ${expected_imported_modules}"
+ )
endif ()
diff --git a/Tests/RunCMake/CXXModules/examples/export-interface-no-properties-build-stderr.txt b/Tests/RunCMake/CXXModules/examples/export-interface-no-properties-build-stderr.txt
index 5e4392a..c8dbdcf 100644
--- a/Tests/RunCMake/CXXModules/examples/export-interface-no-properties-build-stderr.txt
+++ b/Tests/RunCMake/CXXModules/examples/export-interface-no-properties-build-stderr.txt
@@ -1,4 +1,4 @@
-CMake Warning \(dev\) at CMakeLists.txt:7 \(target_sources\):
+CMake Warning \(dev\) at CMakeLists.txt:[0-9]+ \(target_sources\):
CMake's C\+\+ module support is experimental. It is meant only for
experimentation and feedback to CMake developers.
This warning is for project developers. Use -Wno-dev to suppress it.
diff --git a/Tests/RunCMake/CXXModules/examples/export-interface-no-properties-build/CMakeLists.txt b/Tests/RunCMake/CXXModules/examples/export-interface-no-properties-build/CMakeLists.txt
index 7633bec..a93e3a4 100644
--- a/Tests/RunCMake/CXXModules/examples/export-interface-no-properties-build/CMakeLists.txt
+++ b/Tests/RunCMake/CXXModules/examples/export-interface-no-properties-build/CMakeLists.txt
@@ -18,10 +18,14 @@ target_sources(export_interfaces_no_properties
BASE_DIRS
"${CMAKE_CURRENT_SOURCE_DIR}"
FILES
- importable.cxx)
+ importable.cxx
+ subdir/importable.cxx
+ )
target_compile_features(export_interfaces_no_properties PUBLIC cxx_std_20)
-install(TARGETS export_interfaces_no_properties
+add_library(no_modules STATIC no_modules.cxx)
+
+install(TARGETS export_interfaces_no_properties no_modules
EXPORT CXXModules
FILE_SET modules DESTINATION "lib/cxx/miu")
export(EXPORT CXXModules
diff --git a/Tests/RunCMake/CXXModules/examples/export-interface-no-properties-build/no_modules.cxx b/Tests/RunCMake/CXXModules/examples/export-interface-no-properties-build/no_modules.cxx
new file mode 100644
index 0000000..eea854f
--- /dev/null
+++ b/Tests/RunCMake/CXXModules/examples/export-interface-no-properties-build/no_modules.cxx
@@ -0,0 +1,3 @@
+void no_modules()
+{
+}
diff --git a/Tests/RunCMake/CXXModules/examples/export-interface-no-properties-build/subdir/importable.cxx b/Tests/RunCMake/CXXModules/examples/export-interface-no-properties-build/subdir/importable.cxx
new file mode 100644
index 0000000..07d6af6
--- /dev/null
+++ b/Tests/RunCMake/CXXModules/examples/export-interface-no-properties-build/subdir/importable.cxx
@@ -0,0 +1,6 @@
+export module subdir_importable;
+
+export int from_subdir()
+{
+ return 0;
+}
diff --git a/Tests/RunCMake/CXXModules/examples/export-interface-no-properties-build/test/CMakeLists.txt b/Tests/RunCMake/CXXModules/examples/export-interface-no-properties-build/test/CMakeLists.txt
index 9cdc80a..18e933c 100644
--- a/Tests/RunCMake/CXXModules/examples/export-interface-no-properties-build/test/CMakeLists.txt
+++ b/Tests/RunCMake/CXXModules/examples/export-interface-no-properties-build/test/CMakeLists.txt
@@ -14,14 +14,18 @@ get_property(file_sets TARGET CXXModules::export_interfaces_no_properties
PROPERTY INTERFACE_CXX_MODULE_SETS)
if (NOT file_sets STREQUAL "modules")
message(FATAL_ERROR
- "Incorrect exported file sets in `CXXModules::export_interfaces_no_properties`: `${file_sets}`")
+ "Incorrect exported file sets in CXXModules::export_interfaces_no_properties:\n ${file_sets}")
endif ()
get_property(file_set_files TARGET CXXModules::export_interfaces_no_properties
PROPERTY CXX_MODULE_SET_modules)
-if (NOT file_set_files STREQUAL "${expected_dir}/importable.cxx")
+set(expected_file_set_files
+ "${expected_dir}/importable.cxx"
+ "${expected_dir}/subdir/importable.cxx"
+ )
+if (NOT file_set_files STREQUAL "${expected_file_set_files}")
message(FATAL_ERROR
- "Incorrect exported file set paths in CXXModules::export_interfaces_no_properties`: `${file_set_files}`")
+ "Incorrect exported file set paths in CXXModules::export_interfaces_no_properties:\n ${file_set_files}")
endif ()
get_property(imported_modules_set TARGET CXXModules::export_interfaces_no_properties
diff --git a/Tests/RunCMake/CXXModules/examples/export-interface-no-properties-install-stderr.txt b/Tests/RunCMake/CXXModules/examples/export-interface-no-properties-install-stderr.txt
index 5e4392a..c8dbdcf 100644
--- a/Tests/RunCMake/CXXModules/examples/export-interface-no-properties-install-stderr.txt
+++ b/Tests/RunCMake/CXXModules/examples/export-interface-no-properties-install-stderr.txt
@@ -1,4 +1,4 @@
-CMake Warning \(dev\) at CMakeLists.txt:7 \(target_sources\):
+CMake Warning \(dev\) at CMakeLists.txt:[0-9]+ \(target_sources\):
CMake's C\+\+ module support is experimental. It is meant only for
experimentation and feedback to CMake developers.
This warning is for project developers. Use -Wno-dev to suppress it.
diff --git a/Tests/RunCMake/CXXModules/examples/export-interface-no-properties-install/CMakeLists.txt b/Tests/RunCMake/CXXModules/examples/export-interface-no-properties-install/CMakeLists.txt
index 75f2440..99e67e7 100644
--- a/Tests/RunCMake/CXXModules/examples/export-interface-no-properties-install/CMakeLists.txt
+++ b/Tests/RunCMake/CXXModules/examples/export-interface-no-properties-install/CMakeLists.txt
@@ -18,10 +18,14 @@ target_sources(export_interfaces_no_properties
BASE_DIRS
"${CMAKE_CURRENT_SOURCE_DIR}"
FILES
- importable.cxx)
+ importable.cxx
+ subdir/importable.cxx
+ )
target_compile_features(export_interfaces_no_properties PUBLIC cxx_std_20)
-install(TARGETS export_interfaces_no_properties
+add_library(no_modules STATIC no_modules.cxx)
+
+install(TARGETS export_interfaces_no_properties no_modules
EXPORT CXXModules
FILE_SET modules DESTINATION "lib/cxx/miu")
install(EXPORT CXXModules
diff --git a/Tests/RunCMake/CXXModules/examples/export-interface-no-properties-install/no_modules.cxx b/Tests/RunCMake/CXXModules/examples/export-interface-no-properties-install/no_modules.cxx
new file mode 100644
index 0000000..eea854f
--- /dev/null
+++ b/Tests/RunCMake/CXXModules/examples/export-interface-no-properties-install/no_modules.cxx
@@ -0,0 +1,3 @@
+void no_modules()
+{
+}
diff --git a/Tests/RunCMake/CXXModules/examples/export-interface-no-properties-install/subdir/importable.cxx b/Tests/RunCMake/CXXModules/examples/export-interface-no-properties-install/subdir/importable.cxx
new file mode 100644
index 0000000..07d6af6
--- /dev/null
+++ b/Tests/RunCMake/CXXModules/examples/export-interface-no-properties-install/subdir/importable.cxx
@@ -0,0 +1,6 @@
+export module subdir_importable;
+
+export int from_subdir()
+{
+ return 0;
+}
diff --git a/Tests/RunCMake/CXXModules/examples/export-interface-no-properties-install/test/CMakeLists.txt b/Tests/RunCMake/CXXModules/examples/export-interface-no-properties-install/test/CMakeLists.txt
index 9cdc80a..18e933c 100644
--- a/Tests/RunCMake/CXXModules/examples/export-interface-no-properties-install/test/CMakeLists.txt
+++ b/Tests/RunCMake/CXXModules/examples/export-interface-no-properties-install/test/CMakeLists.txt
@@ -14,14 +14,18 @@ get_property(file_sets TARGET CXXModules::export_interfaces_no_properties
PROPERTY INTERFACE_CXX_MODULE_SETS)
if (NOT file_sets STREQUAL "modules")
message(FATAL_ERROR
- "Incorrect exported file sets in `CXXModules::export_interfaces_no_properties`: `${file_sets}`")
+ "Incorrect exported file sets in CXXModules::export_interfaces_no_properties:\n ${file_sets}")
endif ()
get_property(file_set_files TARGET CXXModules::export_interfaces_no_properties
PROPERTY CXX_MODULE_SET_modules)
-if (NOT file_set_files STREQUAL "${expected_dir}/importable.cxx")
+set(expected_file_set_files
+ "${expected_dir}/importable.cxx"
+ "${expected_dir}/subdir/importable.cxx"
+ )
+if (NOT file_set_files STREQUAL "${expected_file_set_files}")
message(FATAL_ERROR
- "Incorrect exported file set paths in CXXModules::export_interfaces_no_properties`: `${file_set_files}`")
+ "Incorrect exported file set paths in CXXModules::export_interfaces_no_properties:\n ${file_set_files}")
endif ()
get_property(imported_modules_set TARGET CXXModules::export_interfaces_no_properties
diff --git a/Tests/RunCMake/CheckModules/CheckStructHasMemberWrongKey-stderr.txt b/Tests/RunCMake/CheckModules/CheckStructHasMemberWrongKey-stderr.txt
index b9fbd38..4a3f601 100644
--- a/Tests/RunCMake/CheckModules/CheckStructHasMemberWrongKey-stderr.txt
+++ b/Tests/RunCMake/CheckModules/CheckStructHasMemberWrongKey-stderr.txt
@@ -1,7 +1,7 @@
CMake Error at .*/Modules/CheckStructHasMember.cmake:[0-9]+. \(message\):
Unknown arguments:
- LANGUAG;C
+ LANGUAG_;C
Call Stack \(most recent call first\):
CheckStructHasMemberWrongKey.cmake:[0-9]+ \(check_struct_has_member\)
diff --git a/Tests/RunCMake/CheckModules/CheckStructHasMemberWrongKey.cmake b/Tests/RunCMake/CheckModules/CheckStructHasMemberWrongKey.cmake
index 900eb0a..fea0eb0 100644
--- a/Tests/RunCMake/CheckModules/CheckStructHasMemberWrongKey.cmake
+++ b/Tests/RunCMake/CheckModules/CheckStructHasMemberWrongKey.cmake
@@ -1,2 +1,2 @@
include(CheckStructHasMember)
-check_struct_has_member("struct timeval" tv_sec sys/select.h HAVE_TIMEVAL_TV_SEC_K LANGUAG C)
+check_struct_has_member("struct timeval" tv_sec sys/select.h HAVE_TIMEVAL_TV_SEC_K LANGUAG_ C)
diff --git a/Tests/RunCMake/CheckModules/CheckTypeSizeUnknownArgument-stderr.txt b/Tests/RunCMake/CheckModules/CheckTypeSizeUnknownArgument-stderr.txt
index 085488e..9227cc3 100644
--- a/Tests/RunCMake/CheckModules/CheckTypeSizeUnknownArgument-stderr.txt
+++ b/Tests/RunCMake/CheckModules/CheckTypeSizeUnknownArgument-stderr.txt
@@ -1,7 +1,7 @@
CMake Error at .*/Modules/CheckTypeSize.cmake:[0-9]+. \(message\):
Unknown argument:
- LANGUAG
+ LANGUAG_
Call Stack \(most recent call first\):
CheckTypeSizeUnknownArgument.cmake:[0-9]+ \(check_type_size\)
diff --git a/Tests/RunCMake/CheckModules/CheckTypeSizeUnknownArgument.cmake b/Tests/RunCMake/CheckModules/CheckTypeSizeUnknownArgument.cmake
index 6f24ee1..cf6f0fc 100644
--- a/Tests/RunCMake/CheckModules/CheckTypeSizeUnknownArgument.cmake
+++ b/Tests/RunCMake/CheckModules/CheckTypeSizeUnknownArgument.cmake
@@ -1,2 +1,2 @@
include(CheckTypeSize)
-check_type_size(int SIZEOF_INT BUILTIN_TYPES_ONLY LANGUAG CXX)
+check_type_size(int SIZEOF_INT BUILTIN_TYPES_ONLY LANGUAG_ CXX)
diff --git a/Tests/RunCMake/CommandLine/DebuggerArgMissingDapLog-result.txt b/Tests/RunCMake/CommandLine/DebuggerArgMissingDapLog-result.txt
new file mode 100644
index 0000000..d00491f
--- /dev/null
+++ b/Tests/RunCMake/CommandLine/DebuggerArgMissingDapLog-result.txt
@@ -0,0 +1 @@
+1
diff --git a/Tests/RunCMake/CommandLine/DebuggerArgMissingDapLog-stderr.txt b/Tests/RunCMake/CommandLine/DebuggerArgMissingDapLog-stderr.txt
new file mode 100644
index 0000000..6269c19
--- /dev/null
+++ b/Tests/RunCMake/CommandLine/DebuggerArgMissingDapLog-stderr.txt
@@ -0,0 +1,2 @@
+^CMake Error: No file specified for --debugger-dap-log
+CMake Error: Run 'cmake --help' for all supported options\.$
diff --git a/Tests/RunCMake/CommandLine/DebuggerArgMissingDapLog.cmake b/Tests/RunCMake/CommandLine/DebuggerArgMissingDapLog.cmake
new file mode 100644
index 0000000..6ddce8b
--- /dev/null
+++ b/Tests/RunCMake/CommandLine/DebuggerArgMissingDapLog.cmake
@@ -0,0 +1 @@
+message(FATAL_ERROR "This should not be reached.")
diff --git a/Tests/RunCMake/CommandLine/DebuggerArgMissingPipe-result.txt b/Tests/RunCMake/CommandLine/DebuggerArgMissingPipe-result.txt
new file mode 100644
index 0000000..d00491f
--- /dev/null
+++ b/Tests/RunCMake/CommandLine/DebuggerArgMissingPipe-result.txt
@@ -0,0 +1 @@
+1
diff --git a/Tests/RunCMake/CommandLine/DebuggerArgMissingPipe-stderr.txt b/Tests/RunCMake/CommandLine/DebuggerArgMissingPipe-stderr.txt
new file mode 100644
index 0000000..947cb00
--- /dev/null
+++ b/Tests/RunCMake/CommandLine/DebuggerArgMissingPipe-stderr.txt
@@ -0,0 +1,2 @@
+^CMake Error: No path specified for --debugger-pipe
+CMake Error: Run 'cmake --help' for all supported options\.$
diff --git a/Tests/RunCMake/CommandLine/DebuggerArgMissingPipe.cmake b/Tests/RunCMake/CommandLine/DebuggerArgMissingPipe.cmake
new file mode 100644
index 0000000..6ddce8b
--- /dev/null
+++ b/Tests/RunCMake/CommandLine/DebuggerArgMissingPipe.cmake
@@ -0,0 +1 @@
+message(FATAL_ERROR "This should not be reached.")
diff --git a/Tests/RunCMake/CommandLine/DebuggerCapabilityInspect-check.cmake b/Tests/RunCMake/CommandLine/DebuggerCapabilityInspect-check.cmake
new file mode 100644
index 0000000..75769f2
--- /dev/null
+++ b/Tests/RunCMake/CommandLine/DebuggerCapabilityInspect-check.cmake
@@ -0,0 +1,5 @@
+if(actual_stdout MATCHES [["debugger" *: *true]])
+ set_property(DIRECTORY PROPERTY CMake_ENABLE_DEBUGGER 1)
+else()
+ set_property(DIRECTORY PROPERTY CMake_ENABLE_DEBUGGER 0)
+endif()
diff --git a/Tests/RunCMake/CommandLine/DebuggerNotSupported-result.txt b/Tests/RunCMake/CommandLine/DebuggerNotSupported-result.txt
new file mode 100644
index 0000000..d00491f
--- /dev/null
+++ b/Tests/RunCMake/CommandLine/DebuggerNotSupported-result.txt
@@ -0,0 +1 @@
+1
diff --git a/Tests/RunCMake/CommandLine/DebuggerNotSupported-stderr.txt b/Tests/RunCMake/CommandLine/DebuggerNotSupported-stderr.txt
new file mode 100644
index 0000000..5845bb3
--- /dev/null
+++ b/Tests/RunCMake/CommandLine/DebuggerNotSupported-stderr.txt
@@ -0,0 +1,2 @@
+^CMake Error: CMake was not built with support for --debugger
+CMake Error: Run 'cmake --help' for all supported options\.$
diff --git a/Tests/RunCMake/CommandLine/DebuggerNotSupported.cmake b/Tests/RunCMake/CommandLine/DebuggerNotSupported.cmake
new file mode 100644
index 0000000..6ddce8b
--- /dev/null
+++ b/Tests/RunCMake/CommandLine/DebuggerNotSupported.cmake
@@ -0,0 +1 @@
+message(FATAL_ERROR "This should not be reached.")
diff --git a/Tests/RunCMake/CommandLine/DebuggerNotSupportedDapLog-result.txt b/Tests/RunCMake/CommandLine/DebuggerNotSupportedDapLog-result.txt
new file mode 100644
index 0000000..d00491f
--- /dev/null
+++ b/Tests/RunCMake/CommandLine/DebuggerNotSupportedDapLog-result.txt
@@ -0,0 +1 @@
+1
diff --git a/Tests/RunCMake/CommandLine/DebuggerNotSupportedDapLog-stderr.txt b/Tests/RunCMake/CommandLine/DebuggerNotSupportedDapLog-stderr.txt
new file mode 100644
index 0000000..84c2200
--- /dev/null
+++ b/Tests/RunCMake/CommandLine/DebuggerNotSupportedDapLog-stderr.txt
@@ -0,0 +1,2 @@
+^CMake Error: CMake was not built with support for --debugger-dap-log
+CMake Error: Run 'cmake --help' for all supported options\.$
diff --git a/Tests/RunCMake/CommandLine/DebuggerNotSupportedDapLog.cmake b/Tests/RunCMake/CommandLine/DebuggerNotSupportedDapLog.cmake
new file mode 100644
index 0000000..6ddce8b
--- /dev/null
+++ b/Tests/RunCMake/CommandLine/DebuggerNotSupportedDapLog.cmake
@@ -0,0 +1 @@
+message(FATAL_ERROR "This should not be reached.")
diff --git a/Tests/RunCMake/CommandLine/DebuggerNotSupportedPipe-result.txt b/Tests/RunCMake/CommandLine/DebuggerNotSupportedPipe-result.txt
new file mode 100644
index 0000000..d00491f
--- /dev/null
+++ b/Tests/RunCMake/CommandLine/DebuggerNotSupportedPipe-result.txt
@@ -0,0 +1 @@
+1
diff --git a/Tests/RunCMake/CommandLine/DebuggerNotSupportedPipe-stderr.txt b/Tests/RunCMake/CommandLine/DebuggerNotSupportedPipe-stderr.txt
new file mode 100644
index 0000000..5684f4c
--- /dev/null
+++ b/Tests/RunCMake/CommandLine/DebuggerNotSupportedPipe-stderr.txt
@@ -0,0 +1,2 @@
+^CMake Error: CMake was not built with support for --debugger-pipe
+CMake Error: Run 'cmake --help' for all supported options\.$
diff --git a/Tests/RunCMake/CommandLine/DebuggerNotSupportedPipe.cmake b/Tests/RunCMake/CommandLine/DebuggerNotSupportedPipe.cmake
new file mode 100644
index 0000000..6ddce8b
--- /dev/null
+++ b/Tests/RunCMake/CommandLine/DebuggerNotSupportedPipe.cmake
@@ -0,0 +1 @@
+message(FATAL_ERROR "This should not be reached.")
diff --git a/Tests/RunCMake/CommandLine/E_capabilities-stdout.txt b/Tests/RunCMake/CommandLine/E_capabilities-stdout.txt
index 597dbd4..c01f414 100644
--- a/Tests/RunCMake/CommandLine/E_capabilities-stdout.txt
+++ b/Tests/RunCMake/CommandLine/E_capabilities-stdout.txt
@@ -1 +1 @@
-^{"fileApi":{"requests":\[{"kind":"codemodel","version":\[{"major":2,"minor":5}]},{"kind":"configureLog","version":\[{"major":1,"minor":0}]},{"kind":"cache","version":\[{"major":2,"minor":0}]},{"kind":"cmakeFiles","version":\[{"major":1,"minor":0}]},{"kind":"toolchains","version":\[{"major":1,"minor":0}]}]},"generators":\[.*\],"serverMode":false,"tls":(true|false),"version":{.*}}$
+^{"debugger":(true|false),"fileApi":{"requests":\[{"kind":"codemodel","version":\[{"major":2,"minor":6}]},{"kind":"configureLog","version":\[{"major":1,"minor":0}]},{"kind":"cache","version":\[{"major":2,"minor":0}]},{"kind":"cmakeFiles","version":\[{"major":1,"minor":0}]},{"kind":"toolchains","version":\[{"major":1,"minor":0}]}]},"generators":\[.*\],"serverMode":false,"tls":(true|false),"version":{.*}}$
diff --git a/Tests/RunCMake/CommandLine/RunCMakeTest.cmake b/Tests/RunCMake/CommandLine/RunCMakeTest.cmake
index 205949b..45b4c0e 100644
--- a/Tests/RunCMake/CommandLine/RunCMakeTest.cmake
+++ b/Tests/RunCMake/CommandLine/RunCMakeTest.cmake
@@ -125,6 +125,17 @@ run_cmake_command(cache-bad-entry
run_cmake_command(cache-empty-entry
${CMAKE_COMMAND} --build ${RunCMake_SOURCE_DIR}/cache-empty-entry/)
+run_cmake_command(DebuggerCapabilityInspect ${CMAKE_COMMAND} -E capabilities)
+get_property(CMake_ENABLE_DEBUGGER DIRECTORY PROPERTY CMake_ENABLE_DEBUGGER)
+if(CMake_ENABLE_DEBUGGER)
+ run_cmake_with_options(DebuggerArgMissingPipe --debugger-pipe)
+ run_cmake_with_options(DebuggerArgMissingDapLog --debugger-dap-log)
+else()
+ run_cmake_with_options(DebuggerNotSupported --debugger)
+ run_cmake_with_options(DebuggerNotSupportedPipe --debugger-pipe pipe)
+ run_cmake_with_options(DebuggerNotSupportedDapLog --debugger-dap-log dap-log)
+endif()
+
function(run_ExplicitDirs)
set(RunCMake_TEST_NO_CLEAN 1)
set(RunCMake_TEST_NO_SOURCE_DIR 1)
diff --git a/Tests/RunCMake/CompileFeatures/RunCMakeTest.cmake b/Tests/RunCMake/CompileFeatures/RunCMakeTest.cmake
index a001c5d..7b72ffe 100644
--- a/Tests/RunCMake/CompileFeatures/RunCMakeTest.cmake
+++ b/Tests/RunCMake/CompileFeatures/RunCMakeTest.cmake
@@ -130,7 +130,7 @@ endfunction()
function(test_cmp0128_warn_unset)
# For compilers that had CMAKE_<LANG>_EXTENSION_COMPILE_OPTION (only IAR)
- # there is no behavioural change and thus no warning.
+ # there is no behavioral change and thus no warning.
if(NOT "${${lang}_EXT_FLAG}" STREQUAL "")
return()
endif()
diff --git a/Tests/RunCMake/FileAPI/codemodel-v2-check.py b/Tests/RunCMake/FileAPI/codemodel-v2-check.py
index eb52975..b669543 100644
--- a/Tests/RunCMake/FileAPI/codemodel-v2-check.py
+++ b/Tests/RunCMake/FileAPI/codemodel-v2-check.py
@@ -12,7 +12,7 @@ def read_codemodel_json_data(filename):
def check_objects(o, g):
assert is_list(o)
assert len(o) == 1
- check_index_object(o[0], "codemodel", 2, 5, check_object_codemodel(g))
+ check_index_object(o[0], "codemodel", 2, 6, check_object_codemodel(g))
def check_backtrace(t, b, backtrace):
btg = t["backtraceGraph"]
@@ -578,6 +578,30 @@ def check_target(c):
missing_exception=lambda e: "Include path: %s" % e["path"],
extra_exception=lambda a: "Include path: %s" % a["path"])
+ if expected["frameworks"] is not None:
+ expected_keys.append("frameworks")
+
+ def check_include(actual, expected):
+ assert is_dict(actual)
+ expected_keys = ["path"]
+
+ if expected["isSystem"] is not None:
+ expected_keys.append("isSystem")
+ assert is_bool(actual["isSystem"], expected["isSystem"])
+
+ if expected["backtrace"] is not None:
+ expected_keys.append("backtrace")
+ check_backtrace(obj, actual["backtrace"], expected["backtrace"])
+
+ assert sorted(actual.keys()) == sorted(expected_keys)
+
+ check_list_match(lambda a, e: matches(a["path"], e["path"]),
+ actual["frameworks"], expected["frameworks"],
+ check=check_include,
+ check_exception=lambda a, e: "Framework path: %s" % a["path"],
+ missing_exception=lambda e: "Framework path: %s" % e["path"],
+ extra_exception=lambda a: "Framework path: %s" % a["path"])
+
if "precompileHeaders" in expected:
expected_keys.append("precompileHeaders")
@@ -693,6 +717,7 @@ def gen_check_directories(c, g):
read_codemodel_json_data("directories/external.json"),
read_codemodel_json_data("directories/fileset.json"),
read_codemodel_json_data("directories/subdir.json"),
+ read_codemodel_json_data("directories/framework.json"),
]
if matches(g["name"], "^Visual Studio "):
@@ -776,6 +801,12 @@ def gen_check_targets(c, g, inSource):
read_codemodel_json_data("targets/cxx_object_lib.json"),
read_codemodel_json_data("targets/cxx_object_exe.json"),
+ read_codemodel_json_data("targets/all_build_framework.json"),
+ read_codemodel_json_data("targets/zero_check_framework.json"),
+ read_codemodel_json_data("targets/static_framework.json"),
+ read_codemodel_json_data("targets/shared_framework.json"),
+ read_codemodel_json_data("targets/exe_framework.json"),
+
read_codemodel_json_data("targets/all_build_imported.json"),
read_codemodel_json_data("targets/zero_check_imported.json"),
read_codemodel_json_data("targets/link_imported_exe.json"),
@@ -800,6 +831,21 @@ def gen_check_targets(c, g, inSource):
read_codemodel_json_data("targets/c_headers_2.json"),
]
+ if sys.platform == "darwin":
+ for e in expected:
+ if e["name"] == "static_framework":
+ apple_static_framework = read_codemodel_json_data("targets/apple_static_framework.json")
+ e["artifacts"] = apple_static_framework["artifacts"]
+ e["nameOnDisk"] = apple_static_framework["nameOnDisk"]
+ elif e["name"] == "shared_framework":
+ apple_shared_framework = read_codemodel_json_data("targets/apple_shared_framework.json")
+ e["artifacts"] = apple_shared_framework["artifacts"]
+ e["nameOnDisk"] = apple_shared_framework["nameOnDisk"]
+ elif e["name"] == "exe_framework":
+ apple_exe_framework = read_codemodel_json_data("targets/apple_exe_framework.json")
+ e["compileGroups"] = apple_exe_framework["compileGroups"]
+ e["link"] = apple_exe_framework["link"]
+
if cxx_compiler_id in ['Clang', 'AppleClang', 'LCC', 'GNU', 'Intel', 'IntelLLVM', 'MSVC', 'Embarcadero', 'IBMClang'] and g["name"] != "Xcode":
for e in expected:
if e["name"] == "cxx_exe":
@@ -926,6 +972,21 @@ def gen_check_targets(c, g, inSource):
],
},
{
+ "path": "^framework/CMakeLists\\.txt$",
+ "isGenerated": None,
+ "fileSetName": None,
+ "sourceGroupName": "",
+ "compileGroupLanguage": None,
+ "backtrace": [
+ {
+ "file": "^CMakeLists\\.txt$",
+ "line": None,
+ "command": None,
+ "hasParent": False,
+ },
+ ],
+ },
+ {
"path": "^dir/CMakeLists\\.txt$",
"isGenerated": None,
"fileSetName": None,
@@ -1070,6 +1131,7 @@ def gen_check_targets(c, g, inSource):
"^codemodel-v2\\.cmake$",
"^custom/CMakeLists\\.txt$",
"^cxx/CMakeLists\\.txt$",
+ "^framework/CMakeLists\\.txt$",
"^dir/CMakeLists\\.txt$",
"^dir/dir/CMakeLists\\.txt$",
"^fileset/CMakeLists\\.txt$",
@@ -1144,6 +1206,7 @@ def gen_check_projects(c, g):
read_codemodel_json_data("projects/interface.json"),
read_codemodel_json_data("projects/custom.json"),
read_codemodel_json_data("projects/external.json"),
+ read_codemodel_json_data("projects/framework.json"),
]
if matches(g["name"], "^Visual Studio "):
diff --git a/Tests/RunCMake/FileAPI/codemodel-v2-data/directories/framework.json b/Tests/RunCMake/FileAPI/codemodel-v2-data/directories/framework.json
new file mode 100644
index 0000000..3affc02
--- /dev/null
+++ b/Tests/RunCMake/FileAPI/codemodel-v2-data/directories/framework.json
@@ -0,0 +1,17 @@
+{
+ "source": "^framework$",
+ "build": "^framework$",
+ "parentSource": "^\\.$",
+ "childSources": null,
+ "targetIds": [
+ "^ALL_BUILD::@217a96c3a62328a73ef4$",
+ "^ZERO_CHECK::@217a96c3a62328a73ef4$",
+ "^shared_framework::@217a96c3a62328a73ef4$",
+ "^static_framework::@217a96c3a62328a73ef4$",
+ "^exe_framework::@217a96c3a62328a73ef4$"
+ ],
+ "projectName": "Framework",
+ "minimumCMakeVersion": "3.13",
+ "hasInstallRule": null,
+ "installers": []
+}
diff --git a/Tests/RunCMake/FileAPI/codemodel-v2-data/directories/top.json b/Tests/RunCMake/FileAPI/codemodel-v2-data/directories/top.json
index aed07e2..a35d5e2 100644
--- a/Tests/RunCMake/FileAPI/codemodel-v2-data/directories/top.json
+++ b/Tests/RunCMake/FileAPI/codemodel-v2-data/directories/top.json
@@ -12,7 +12,8 @@
"^.*/Tests/RunCMake/FileAPIExternalSource$",
"^dir$",
"^fileset$",
- "^subdir$"
+ "^subdir$",
+ "^framework$"
],
"targetIds": [
"^ALL_BUILD::@6890427a1f51a3e7e1df$",
@@ -50,7 +51,7 @@
"backtrace": [
{
"file": "^codemodel-v2\\.cmake$",
- "line": 42,
+ "line": 43,
"command": "install",
"hasParent": true
},
@@ -95,7 +96,7 @@
"backtrace": [
{
"file": "^codemodel-v2\\.cmake$",
- "line": 45,
+ "line": 46,
"command": "install",
"hasParent": true
},
@@ -143,7 +144,7 @@
"backtrace": [
{
"file": "^codemodel-v2\\.cmake$",
- "line": 45,
+ "line": 46,
"command": "install",
"hasParent": true
},
@@ -188,7 +189,7 @@
"backtrace": [
{
"file": "^codemodel-v2\\.cmake$",
- "line": 45,
+ "line": 46,
"command": "install",
"hasParent": true
},
@@ -232,7 +233,7 @@
"backtrace": [
{
"file": "^codemodel-v2\\.cmake$",
- "line": 45,
+ "line": 46,
"command": "install",
"hasParent": true
},
@@ -276,7 +277,7 @@
"backtrace": [
{
"file": "^codemodel-v2\\.cmake$",
- "line": 50,
+ "line": 51,
"command": "install",
"hasParent": true
},
@@ -323,7 +324,7 @@
"backtrace": [
{
"file": "^codemodel-v2\\.cmake$",
- "line": 52,
+ "line": 53,
"command": "install",
"hasParent": true
},
@@ -368,7 +369,7 @@
"backtrace": [
{
"file": "^codemodel-v2\\.cmake$",
- "line": 53,
+ "line": 54,
"command": "install",
"hasParent": true
},
@@ -417,7 +418,7 @@
"backtrace": [
{
"file": "^codemodel-v2\\.cmake$",
- "line": 54,
+ "line": 55,
"command": "install",
"hasParent": true
},
@@ -469,7 +470,7 @@
"backtrace": [
{
"file": "^codemodel-v2\\.cmake$",
- "line": 55,
+ "line": 56,
"command": "install",
"hasParent": true
},
@@ -518,7 +519,7 @@
"backtrace": [
{
"file": "^codemodel-v2\\.cmake$",
- "line": 56,
+ "line": 57,
"command": "install",
"hasParent": true
},
@@ -560,7 +561,7 @@
"backtrace": [
{
"file": "^codemodel-v2\\.cmake$",
- "line": 57,
+ "line": 58,
"command": "install",
"hasParent": true
},
@@ -602,7 +603,7 @@
"backtrace": [
{
"file": "^codemodel-v2\\.cmake$",
- "line": 58,
+ "line": 59,
"command": "install",
"hasParent": true
},
diff --git a/Tests/RunCMake/FileAPI/codemodel-v2-data/projects/codemodel-v2.json b/Tests/RunCMake/FileAPI/codemodel-v2-data/projects/codemodel-v2.json
index 151c0a8..8d2712d 100644
--- a/Tests/RunCMake/FileAPI/codemodel-v2-data/projects/codemodel-v2.json
+++ b/Tests/RunCMake/FileAPI/codemodel-v2-data/projects/codemodel-v2.json
@@ -8,7 +8,8 @@
"Imported",
"Interface",
"Object",
- "External"
+ "External",
+ "Framework"
],
"directorySources": [
"^\\.$",
diff --git a/Tests/RunCMake/FileAPI/codemodel-v2-data/projects/framework.json b/Tests/RunCMake/FileAPI/codemodel-v2-data/projects/framework.json
new file mode 100644
index 0000000..259ead1
--- /dev/null
+++ b/Tests/RunCMake/FileAPI/codemodel-v2-data/projects/framework.json
@@ -0,0 +1,15 @@
+{
+ "name": "Framework",
+ "parentName": "codemodel-v2",
+ "childNames": null,
+ "directorySources": [
+ "^framework$"
+ ],
+ "targetIds": [
+ "^ALL_BUILD::@217a96c3a62328a73ef4$",
+ "^ZERO_CHECK::@217a96c3a62328a73ef4$",
+ "^shared_framework::@217a96c3a62328a73ef4$",
+ "^static_framework::@217a96c3a62328a73ef4$",
+ "^exe_framework::@217a96c3a62328a73ef4$"
+ ]
+}
diff --git a/Tests/RunCMake/FileAPI/codemodel-v2-data/targets/all_build_framework.json b/Tests/RunCMake/FileAPI/codemodel-v2-data/targets/all_build_framework.json
new file mode 100644
index 0000000..a4d806a
--- /dev/null
+++ b/Tests/RunCMake/FileAPI/codemodel-v2-data/targets/all_build_framework.json
@@ -0,0 +1,90 @@
+{
+ "name": "ALL_BUILD",
+ "id": "^ALL_BUILD::@217a96c3a62328a73ef4$",
+ "directorySource": "^framework$",
+ "projectName": "Framework",
+ "type": "UTILITY",
+ "isGeneratorProvided": true,
+ "fileSets": null,
+ "sources": [
+ {
+ "path": "^.*/Tests/RunCMake/FileAPI/codemodel-v2-build/framework/CMakeFiles/ALL_BUILD$",
+ "isGenerated": true,
+ "fileSetName": null,
+ "sourceGroupName": "",
+ "compileGroupLanguage": null,
+ "backtrace": [
+ {
+ "file": "^framework/CMakeLists\\.txt$",
+ "line": null,
+ "command": null,
+ "hasParent": false
+ }
+ ]
+ },
+ {
+ "path": "^.*/Tests/RunCMake/FileAPI/codemodel-v2-build/framework/CMakeFiles/ALL_BUILD\\.rule$",
+ "isGenerated": true,
+ "fileSetName": null,
+ "sourceGroupName": "CMake Rules",
+ "compileGroupLanguage": null,
+ "backtrace": [
+ {
+ "file": "^framework/CMakeLists\\.txt$",
+ "line": null,
+ "command": null,
+ "hasParent": false
+ }
+ ]
+ }
+ ],
+ "sourceGroups": [
+ {
+ "name": "",
+ "sourcePaths": [
+ "^.*/Tests/RunCMake/FileAPI/codemodel-v2-build/framework/CMakeFiles/ALL_BUILD$"
+ ]
+ },
+ {
+ "name": "CMake Rules",
+ "sourcePaths": [
+ "^.*/Tests/RunCMake/FileAPI/codemodel-v2-build/framework/CMakeFiles/ALL_BUILD\\.rule$"
+ ]
+ }
+ ],
+ "compileGroups": null,
+ "backtrace": [
+ {
+ "file": "^framework/CMakeLists\\.txt$",
+ "line": null,
+ "command": null,
+ "hasParent": false
+ }
+ ],
+ "folder": null,
+ "nameOnDisk": null,
+ "artifacts": null,
+ "build": "^framework$",
+ "source": "^framework$",
+ "install": null,
+ "link": null,
+ "archive": null,
+ "dependencies": [
+ {
+ "id": "^ZERO_CHECK::@217a96c3a62328a73ef4$",
+ "backtrace": null
+ },
+ {
+ "id": "^shared_framework::@217a96c3a62328a73ef4$",
+ "backtrace": null
+ },
+ {
+ "id": "^static_framework::@217a96c3a62328a73ef4$",
+ "backtrace": null
+ },
+ {
+ "id": "^exe_framework::@217a96c3a62328a73ef4$",
+ "backtrace": null
+ }
+ ]
+}
diff --git a/Tests/RunCMake/FileAPI/codemodel-v2-data/targets/all_build_top.json b/Tests/RunCMake/FileAPI/codemodel-v2-data/targets/all_build_top.json
index 46495ac..9d0007f 100644
--- a/Tests/RunCMake/FileAPI/codemodel-v2-data/targets/all_build_top.json
+++ b/Tests/RunCMake/FileAPI/codemodel-v2-data/targets/all_build_top.json
@@ -201,6 +201,18 @@
{
"id": "^c_headers_2::@6b8db101d64c125f29fe$",
"backtrace": null
+ },
+ {
+ "id": "^static_framework::@217a96c3a62328a73ef4$",
+ "backtrace": null
+ },
+ {
+ "id": "^shared_framework::@217a96c3a62328a73ef4$",
+ "backtrace": null
+ },
+ {
+ "id": "^exe_framework::@217a96c3a62328a73ef4$",
+ "backtrace": null
}
]
}
diff --git a/Tests/RunCMake/FileAPI/codemodel-v2-data/targets/apple_exe_framework.json b/Tests/RunCMake/FileAPI/codemodel-v2-data/targets/apple_exe_framework.json
new file mode 100644
index 0000000..6d320f4
--- /dev/null
+++ b/Tests/RunCMake/FileAPI/codemodel-v2-data/targets/apple_exe_framework.json
@@ -0,0 +1,79 @@
+{
+ "compileGroups":
+ [
+ {
+ "language": "CXX",
+ "sourcePaths": [
+ "^empty\\.cxx$"
+ ],
+ "includes": null,
+ "defines": null,
+ "frameworks":
+ [
+ {
+ "isSystem": null,
+ "path": "^.*/framework/((Debug|Release|RelWithDebInfo|MinSizeRel)/)?static_framework.framework",
+ "backtrace": null
+ },
+ {
+ "isSystem": true,
+ "path": "^.+/framework/((Debug|Release|RelWithDebInfo|MinSizeRel)/)?shared_framework.framework",
+ "backtrace": null
+ },
+ {
+ "isSystem": true,
+ "path": "/usr/Frameworks/Foo.framework",
+ "backtrace": null
+ }
+ ],
+ "compileCommandFragments": []
+ }
+ ],
+ "link": {
+ "language": "CXX",
+ "lto": null,
+ "commandFragments": [
+ {
+ "fragment": "-iframework .+/framework(/(Debug|Release|RelWithDebInfo|MinSizeRel))?\"? -iframework /usr/Frameworks$",
+ "role": "frameworkPath",
+ "backtrace": null
+ },
+ {
+ "fragment": ".*static_framework\\.framework/.+/static_framework",
+ "role": "libraries",
+ "backtrace": [
+ {
+ "file": "^framework/CMakeLists\\.txt$",
+ "line": 17,
+ "command": "target_link_libraries",
+ "hasParent": true
+ },
+ {
+ "file": "^framework/CMakeLists\\.txt$",
+ "line": null,
+ "command": null,
+ "hasParent": false
+ }
+ ]
+ },
+ {
+ "fragment": ".*shared_framework\\.framework/.+/shared_framework",
+ "role": "libraries",
+ "backtrace": [
+ {
+ "file": "^framework/CMakeLists\\.txt$",
+ "line": 17,
+ "command": "target_link_libraries",
+ "hasParent": true
+ },
+ {
+ "file": "^framework/CMakeLists\\.txt$",
+ "line": null,
+ "command": null,
+ "hasParent": false
+ }
+ ]
+ }
+ ]
+ }
+}
diff --git a/Tests/RunCMake/FileAPI/codemodel-v2-data/targets/apple_shared_framework.json b/Tests/RunCMake/FileAPI/codemodel-v2-data/targets/apple_shared_framework.json
new file mode 100644
index 0000000..31104cf
--- /dev/null
+++ b/Tests/RunCMake/FileAPI/codemodel-v2-data/targets/apple_shared_framework.json
@@ -0,0 +1,9 @@
+{
+ "nameOnDisk": "^shared_framework\\.framework/shared_framework$",
+ "artifacts": [
+ {
+ "path": "^framework/((Debug|Release|RelWithDebInfo|MinSizeRel)/)?shared_framework\\.framework/shared_framework$",
+ "_dllExtra": false
+ }
+ ]
+}
diff --git a/Tests/RunCMake/FileAPI/codemodel-v2-data/targets/apple_static_framework.json b/Tests/RunCMake/FileAPI/codemodel-v2-data/targets/apple_static_framework.json
new file mode 100644
index 0000000..25ffd1a
--- /dev/null
+++ b/Tests/RunCMake/FileAPI/codemodel-v2-data/targets/apple_static_framework.json
@@ -0,0 +1,9 @@
+{
+ "nameOnDisk": "^static_framework\\.framework/static_framework$",
+ "artifacts": [
+ {
+ "path": "^framework/((Debug|Release|RelWithDebInfo|MinSizeRel)/)?static_framework\\.framework/static_framework$",
+ "_dllExtra": false
+ }
+ ]
+}
diff --git a/Tests/RunCMake/FileAPI/codemodel-v2-data/targets/c_alias_exe.json b/Tests/RunCMake/FileAPI/codemodel-v2-data/targets/c_alias_exe.json
index a27d328..74b3287 100644
--- a/Tests/RunCMake/FileAPI/codemodel-v2-data/targets/c_alias_exe.json
+++ b/Tests/RunCMake/FileAPI/codemodel-v2-data/targets/c_alias_exe.json
@@ -45,6 +45,7 @@
],
"includes": null,
"defines": null,
+ "frameworks": null,
"compileCommandFragments": null
}
],
diff --git a/Tests/RunCMake/FileAPI/codemodel-v2-data/targets/c_exe.json b/Tests/RunCMake/FileAPI/codemodel-v2-data/targets/c_exe.json
index 7cfc0f2..c6ff37a 100644
--- a/Tests/RunCMake/FileAPI/codemodel-v2-data/targets/c_exe.json
+++ b/Tests/RunCMake/FileAPI/codemodel-v2-data/targets/c_exe.json
@@ -57,6 +57,7 @@
],
"includes": null,
"defines": null,
+ "frameworks": null,
"compileCommandFragments": null
}
],
diff --git a/Tests/RunCMake/FileAPI/codemodel-v2-data/targets/c_headers_1.json b/Tests/RunCMake/FileAPI/codemodel-v2-data/targets/c_headers_1.json
index 715514d..f6cfa9c 100644
--- a/Tests/RunCMake/FileAPI/codemodel-v2-data/targets/c_headers_1.json
+++ b/Tests/RunCMake/FileAPI/codemodel-v2-data/targets/c_headers_1.json
@@ -199,6 +199,7 @@
]
}
],
+ "frameworks": null,
"defines": null,
"compileCommandFragments": null
}
diff --git a/Tests/RunCMake/FileAPI/codemodel-v2-data/targets/c_headers_2.json b/Tests/RunCMake/FileAPI/codemodel-v2-data/targets/c_headers_2.json
index 4757a9c..591ba4f 100644
--- a/Tests/RunCMake/FileAPI/codemodel-v2-data/targets/c_headers_2.json
+++ b/Tests/RunCMake/FileAPI/codemodel-v2-data/targets/c_headers_2.json
@@ -51,6 +51,7 @@
"^fileset/empty\\.c$"
],
"includes": null,
+ "frameworks": null,
"defines": null,
"compileCommandFragments": null
}
diff --git a/Tests/RunCMake/FileAPI/codemodel-v2-data/targets/c_lib.json b/Tests/RunCMake/FileAPI/codemodel-v2-data/targets/c_lib.json
index 2bfc63f..dc74fdf 100644
--- a/Tests/RunCMake/FileAPI/codemodel-v2-data/targets/c_lib.json
+++ b/Tests/RunCMake/FileAPI/codemodel-v2-data/targets/c_lib.json
@@ -56,6 +56,7 @@
"^empty\\.c$"
],
"includes": null,
+ "frameworks": null,
"defines": null,
"compileCommandFragments": null
}
diff --git a/Tests/RunCMake/FileAPI/codemodel-v2-data/targets/c_object_exe.json b/Tests/RunCMake/FileAPI/codemodel-v2-data/targets/c_object_exe.json
index 6342191..3034e98 100644
--- a/Tests/RunCMake/FileAPI/codemodel-v2-data/targets/c_object_exe.json
+++ b/Tests/RunCMake/FileAPI/codemodel-v2-data/targets/c_object_exe.json
@@ -71,6 +71,7 @@
"^empty\\.c$"
],
"includes": null,
+ "frameworks": null,
"defines": null,
"compileCommandFragments": null
}
diff --git a/Tests/RunCMake/FileAPI/codemodel-v2-data/targets/c_object_lib.json b/Tests/RunCMake/FileAPI/codemodel-v2-data/targets/c_object_lib.json
index 3e1b03b..ec0fdc6 100644
--- a/Tests/RunCMake/FileAPI/codemodel-v2-data/targets/c_object_lib.json
+++ b/Tests/RunCMake/FileAPI/codemodel-v2-data/targets/c_object_lib.json
@@ -44,6 +44,7 @@
"^empty\\.c$"
],
"includes": null,
+ "frameworks": null,
"defines": null,
"compileCommandFragments": null
}
diff --git a/Tests/RunCMake/FileAPI/codemodel-v2-data/targets/c_shared_exe.json b/Tests/RunCMake/FileAPI/codemodel-v2-data/targets/c_shared_exe.json
index f7a8db4..5e92840 100644
--- a/Tests/RunCMake/FileAPI/codemodel-v2-data/targets/c_shared_exe.json
+++ b/Tests/RunCMake/FileAPI/codemodel-v2-data/targets/c_shared_exe.json
@@ -56,6 +56,7 @@
"^empty\\.c$"
],
"includes": null,
+ "frameworks": null,
"defines": null,
"compileCommandFragments": null
}
diff --git a/Tests/RunCMake/FileAPI/codemodel-v2-data/targets/c_shared_lib.json b/Tests/RunCMake/FileAPI/codemodel-v2-data/targets/c_shared_lib.json
index 9066053..85b5108 100644
--- a/Tests/RunCMake/FileAPI/codemodel-v2-data/targets/c_shared_lib.json
+++ b/Tests/RunCMake/FileAPI/codemodel-v2-data/targets/c_shared_lib.json
@@ -56,6 +56,7 @@
"^empty\\.c$"
],
"includes": null,
+ "frameworks": null,
"defines": [
{
"define": "c_shared_lib_EXPORTS",
@@ -117,7 +118,7 @@
"backtrace": [
{
"file": "^codemodel-v2\\.cmake$",
- "line": 45,
+ "line": 46,
"command": "install",
"hasParent": true
},
@@ -147,7 +148,7 @@
"backtrace": [
{
"file": "^codemodel-v2\\.cmake$",
- "line": 45,
+ "line": 46,
"command": "install",
"hasParent": true
},
@@ -177,7 +178,7 @@
"backtrace": [
{
"file": "^codemodel-v2\\.cmake$",
- "line": 50,
+ "line": 51,
"command": "install",
"hasParent": true
},
diff --git a/Tests/RunCMake/FileAPI/codemodel-v2-data/targets/c_static_exe.json b/Tests/RunCMake/FileAPI/codemodel-v2-data/targets/c_static_exe.json
index 46c5bfe..df43319 100644
--- a/Tests/RunCMake/FileAPI/codemodel-v2-data/targets/c_static_exe.json
+++ b/Tests/RunCMake/FileAPI/codemodel-v2-data/targets/c_static_exe.json
@@ -56,6 +56,7 @@
"^empty\\.c$"
],
"includes": null,
+ "frameworks": null,
"defines": null,
"compileCommandFragments": null
}
diff --git a/Tests/RunCMake/FileAPI/codemodel-v2-data/targets/c_static_lib.json b/Tests/RunCMake/FileAPI/codemodel-v2-data/targets/c_static_lib.json
index df28479..6a51295 100644
--- a/Tests/RunCMake/FileAPI/codemodel-v2-data/targets/c_static_lib.json
+++ b/Tests/RunCMake/FileAPI/codemodel-v2-data/targets/c_static_lib.json
@@ -56,6 +56,7 @@
"^empty\\.c$"
],
"includes": null,
+ "frameworks": null,
"defines": null,
"compileCommandFragments": null
}
diff --git a/Tests/RunCMake/FileAPI/codemodel-v2-data/targets/c_subdir.json b/Tests/RunCMake/FileAPI/codemodel-v2-data/targets/c_subdir.json
index 4fa62e3..362caf9 100644
--- a/Tests/RunCMake/FileAPI/codemodel-v2-data/targets/c_subdir.json
+++ b/Tests/RunCMake/FileAPI/codemodel-v2-data/targets/c_subdir.json
@@ -63,6 +63,7 @@
]
}
],
+ "frameworks": null,
"defines": [
{
"define": "SUBDIR",
diff --git a/Tests/RunCMake/FileAPI/codemodel-v2-data/targets/custom_exe.json b/Tests/RunCMake/FileAPI/codemodel-v2-data/targets/custom_exe.json
index 8d52ab8..449c261 100644
--- a/Tests/RunCMake/FileAPI/codemodel-v2-data/targets/custom_exe.json
+++ b/Tests/RunCMake/FileAPI/codemodel-v2-data/targets/custom_exe.json
@@ -44,6 +44,7 @@
"^empty\\.c$"
],
"includes": null,
+ "frameworks": null,
"defines": null,
"compileCommandFragments": null
}
diff --git a/Tests/RunCMake/FileAPI/codemodel-v2-data/targets/cxx_alias_exe.json b/Tests/RunCMake/FileAPI/codemodel-v2-data/targets/cxx_alias_exe.json
index b27fc5b..a2d3ca4 100644
--- a/Tests/RunCMake/FileAPI/codemodel-v2-data/targets/cxx_alias_exe.json
+++ b/Tests/RunCMake/FileAPI/codemodel-v2-data/targets/cxx_alias_exe.json
@@ -44,6 +44,7 @@
"^empty\\.cxx$"
],
"includes": null,
+ "frameworks": null,
"defines": null,
"compileCommandFragments": null
}
diff --git a/Tests/RunCMake/FileAPI/codemodel-v2-data/targets/cxx_exe.json b/Tests/RunCMake/FileAPI/codemodel-v2-data/targets/cxx_exe.json
index 12b2551..73f9346 100644
--- a/Tests/RunCMake/FileAPI/codemodel-v2-data/targets/cxx_exe.json
+++ b/Tests/RunCMake/FileAPI/codemodel-v2-data/targets/cxx_exe.json
@@ -44,6 +44,7 @@
"^empty\\.cxx$"
],
"includes": null,
+ "frameworks": null,
"defines": null,
"precompileHeaders": [
{
@@ -138,7 +139,7 @@
"backtrace": [
{
"file": "^codemodel-v2\\.cmake$",
- "line": 42,
+ "line": 43,
"command": "install",
"hasParent": true
},
diff --git a/Tests/RunCMake/FileAPI/codemodel-v2-data/targets/cxx_exe_precompileheader.json b/Tests/RunCMake/FileAPI/codemodel-v2-data/targets/cxx_exe_precompileheader.json
index 3251777..ac6a1c0 100644
--- a/Tests/RunCMake/FileAPI/codemodel-v2-data/targets/cxx_exe_precompileheader.json
+++ b/Tests/RunCMake/FileAPI/codemodel-v2-data/targets/cxx_exe_precompileheader.json
@@ -6,6 +6,7 @@
".*cmake_pch(_[^.]+)?(\\.hxx)?\\.cxx$"
],
"includes": null,
+ "frameworks": null,
"defines": null,
"precompileHeaders": [
{
@@ -52,6 +53,7 @@
"^empty\\.cxx$"
],
"includes": null,
+ "frameworks": null,
"defines": null,
"precompileHeaders": [
{
diff --git a/Tests/RunCMake/FileAPI/codemodel-v2-data/targets/cxx_exe_precompileheader_2arch.json b/Tests/RunCMake/FileAPI/codemodel-v2-data/targets/cxx_exe_precompileheader_2arch.json
index 0ac40c2..311fe7a 100644
--- a/Tests/RunCMake/FileAPI/codemodel-v2-data/targets/cxx_exe_precompileheader_2arch.json
+++ b/Tests/RunCMake/FileAPI/codemodel-v2-data/targets/cxx_exe_precompileheader_2arch.json
@@ -6,6 +6,7 @@
".*cmake_pch(_[^.]+)?(\\.hxx)?\\.cxx$"
],
"includes": null,
+ "frameworks": null,
"defines": null,
"precompileHeaders": [
{
@@ -52,6 +53,7 @@
".*cmake_pch(_[^.]+)?(\\.hxx)?\\.cxx$"
],
"includes": null,
+ "frameworks": null,
"defines": null,
"precompileHeaders": [
{
@@ -98,6 +100,7 @@
"^empty\\.cxx$"
],
"includes": null,
+ "frameworks": null,
"defines": null,
"precompileHeaders": [
{
diff --git a/Tests/RunCMake/FileAPI/codemodel-v2-data/targets/cxx_exe_precompileheader_multigen.json b/Tests/RunCMake/FileAPI/codemodel-v2-data/targets/cxx_exe_precompileheader_multigen.json
index 86168f1..adf979e 100644
--- a/Tests/RunCMake/FileAPI/codemodel-v2-data/targets/cxx_exe_precompileheader_multigen.json
+++ b/Tests/RunCMake/FileAPI/codemodel-v2-data/targets/cxx_exe_precompileheader_multigen.json
@@ -6,6 +6,7 @@
".*cmake_pch(_[^.]+)?(\\.hxx)?\\.cxx$"
],
"includes": null,
+ "frameworks": null,
"defines": null,
"precompileHeaders": [
{
@@ -52,6 +53,7 @@
"^empty\\.cxx$"
],
"includes": null,
+ "frameworks": null,
"defines": null,
"precompileHeaders": [
{
diff --git a/Tests/RunCMake/FileAPI/codemodel-v2-data/targets/cxx_lib.json b/Tests/RunCMake/FileAPI/codemodel-v2-data/targets/cxx_lib.json
index f665004..725cad9 100644
--- a/Tests/RunCMake/FileAPI/codemodel-v2-data/targets/cxx_lib.json
+++ b/Tests/RunCMake/FileAPI/codemodel-v2-data/targets/cxx_lib.json
@@ -44,6 +44,7 @@
"^empty\\.cxx$"
],
"includes": null,
+ "frameworks": null,
"defines": null,
"compileCommandFragments": null
}
diff --git a/Tests/RunCMake/FileAPI/codemodel-v2-data/targets/cxx_object_exe.json b/Tests/RunCMake/FileAPI/codemodel-v2-data/targets/cxx_object_exe.json
index 68c5dcc..6655215 100644
--- a/Tests/RunCMake/FileAPI/codemodel-v2-data/targets/cxx_object_exe.json
+++ b/Tests/RunCMake/FileAPI/codemodel-v2-data/targets/cxx_object_exe.json
@@ -71,6 +71,7 @@
"^empty\\.cxx$"
],
"includes": null,
+ "frameworks": null,
"defines": null,
"compileCommandFragments": null
}
diff --git a/Tests/RunCMake/FileAPI/codemodel-v2-data/targets/cxx_object_lib.json b/Tests/RunCMake/FileAPI/codemodel-v2-data/targets/cxx_object_lib.json
index 0438a49..cc2deeb 100644
--- a/Tests/RunCMake/FileAPI/codemodel-v2-data/targets/cxx_object_lib.json
+++ b/Tests/RunCMake/FileAPI/codemodel-v2-data/targets/cxx_object_lib.json
@@ -44,6 +44,7 @@
"^empty\\.cxx$"
],
"includes": null,
+ "frameworks": null,
"defines": null,
"compileCommandFragments": null
}
diff --git a/Tests/RunCMake/FileAPI/codemodel-v2-data/targets/cxx_shared_exe.json b/Tests/RunCMake/FileAPI/codemodel-v2-data/targets/cxx_shared_exe.json
index bb9989e..1858df7 100644
--- a/Tests/RunCMake/FileAPI/codemodel-v2-data/targets/cxx_shared_exe.json
+++ b/Tests/RunCMake/FileAPI/codemodel-v2-data/targets/cxx_shared_exe.json
@@ -44,6 +44,7 @@
"^empty\\.cxx$"
],
"includes": null,
+ "frameworks": null,
"defines": null,
"compileCommandFragments": null
}
diff --git a/Tests/RunCMake/FileAPI/codemodel-v2-data/targets/cxx_shared_lib.json b/Tests/RunCMake/FileAPI/codemodel-v2-data/targets/cxx_shared_lib.json
index d6d59a4..c92e573 100644
--- a/Tests/RunCMake/FileAPI/codemodel-v2-data/targets/cxx_shared_lib.json
+++ b/Tests/RunCMake/FileAPI/codemodel-v2-data/targets/cxx_shared_lib.json
@@ -44,6 +44,7 @@
"^empty\\.cxx$"
],
"includes": null,
+ "frameworks": null,
"defines": [
{
"define": "cxx_shared_lib_EXPORTS",
@@ -93,7 +94,7 @@
"backtrace": [
{
"file": "^codemodel-v2\\.cmake$",
- "line": 45,
+ "line": 46,
"command": "install",
"hasParent": true
},
@@ -123,7 +124,7 @@
"backtrace": [
{
"file": "^codemodel-v2\\.cmake$",
- "line": 45,
+ "line": 46,
"command": "install",
"hasParent": true
},
@@ -153,7 +154,7 @@
"backtrace": [
{
"file": "^codemodel-v2\\.cmake$",
- "line": 50,
+ "line": 51,
"command": "install",
"hasParent": true
},
diff --git a/Tests/RunCMake/FileAPI/codemodel-v2-data/targets/cxx_standard_compile_feature_exe.json b/Tests/RunCMake/FileAPI/codemodel-v2-data/targets/cxx_standard_compile_feature_exe.json
index a6bacf7..5b07d5a 100644
--- a/Tests/RunCMake/FileAPI/codemodel-v2-data/targets/cxx_standard_compile_feature_exe.json
+++ b/Tests/RunCMake/FileAPI/codemodel-v2-data/targets/cxx_standard_compile_feature_exe.json
@@ -64,6 +64,7 @@
"^empty\\.cxx$"
],
"includes": null,
+ "frameworks": null,
"defines": null,
"compileCommandFragments": null
}
diff --git a/Tests/RunCMake/FileAPI/codemodel-v2-data/targets/cxx_standard_exe.json b/Tests/RunCMake/FileAPI/codemodel-v2-data/targets/cxx_standard_exe.json
index fe884e0..d9554f1 100644
--- a/Tests/RunCMake/FileAPI/codemodel-v2-data/targets/cxx_standard_exe.json
+++ b/Tests/RunCMake/FileAPI/codemodel-v2-data/targets/cxx_standard_exe.json
@@ -64,6 +64,7 @@
"^empty\\.cxx$"
],
"includes": null,
+ "frameworks": null,
"defines": null,
"compileCommandFragments": null
}
diff --git a/Tests/RunCMake/FileAPI/codemodel-v2-data/targets/cxx_static_exe.json b/Tests/RunCMake/FileAPI/codemodel-v2-data/targets/cxx_static_exe.json
index d904bd9..001eb8d 100644
--- a/Tests/RunCMake/FileAPI/codemodel-v2-data/targets/cxx_static_exe.json
+++ b/Tests/RunCMake/FileAPI/codemodel-v2-data/targets/cxx_static_exe.json
@@ -44,6 +44,7 @@
"^empty\\.cxx$"
],
"includes": null,
+ "frameworks": null,
"defines": null,
"compileCommandFragments": null
}
diff --git a/Tests/RunCMake/FileAPI/codemodel-v2-data/targets/cxx_static_lib.json b/Tests/RunCMake/FileAPI/codemodel-v2-data/targets/cxx_static_lib.json
index bced68a..38790dd 100644
--- a/Tests/RunCMake/FileAPI/codemodel-v2-data/targets/cxx_static_lib.json
+++ b/Tests/RunCMake/FileAPI/codemodel-v2-data/targets/cxx_static_lib.json
@@ -44,6 +44,7 @@
"^empty\\.cxx$"
],
"includes": null,
+ "frameworks": null,
"defines": null,
"compileCommandFragments": null
}
diff --git a/Tests/RunCMake/FileAPI/codemodel-v2-data/targets/exe_framework.json b/Tests/RunCMake/FileAPI/codemodel-v2-data/targets/exe_framework.json
new file mode 100644
index 0000000..d5d6522
--- /dev/null
+++ b/Tests/RunCMake/FileAPI/codemodel-v2-data/targets/exe_framework.json
@@ -0,0 +1,164 @@
+{
+ "name": "exe_framework",
+ "id": "^exe_framework::@217a96c3a62328a73ef4$",
+ "directorySource": "^framework$",
+ "projectName": "Framework",
+ "type": "EXECUTABLE",
+ "isGeneratorProvided": null,
+ "fileSets": null,
+ "sources": [
+ {
+ "path": "^empty\\.cxx$",
+ "isGenerated": null,
+ "fileSetName": null,
+ "sourceGroupName": "Source Files",
+ "compileGroupLanguage": "CXX",
+ "backtrace": [
+ {
+ "file": "^framework/CMakeLists\\.txt$",
+ "line": 16,
+ "command": "add_executable",
+ "hasParent": true
+ },
+ {
+ "file": "^framework/CMakeLists\\.txt$",
+ "line": null,
+ "command": null,
+ "hasParent": false
+ }
+ ]
+ }
+ ],
+ "sourceGroups": [
+ {
+ "name": "Source Files",
+ "sourcePaths": [
+ "^empty\\.cxx$"
+ ]
+ }
+ ],
+ "compileGroups": [
+ {
+ "language": "CXX",
+ "sourcePaths": [
+ "^empty\\.cxx$"
+ ],
+ "includes": null,
+ "frameworks": null,
+ "defines": null,
+ "compileCommandFragments": null
+ }
+ ],
+ "backtrace": [
+ {
+ "file": "^framework/CMakeLists\\.txt$",
+ "line": 16,
+ "command": "add_executable",
+ "hasParent": true
+ },
+ {
+ "file": "^framework/CMakeLists\\.txt$",
+ "line": null,
+ "command": null,
+ "hasParent": false
+ }
+ ],
+ "folder": null,
+ "nameOnDisk": "^exe_framework(\\.exe)?$",
+ "artifacts": [
+ {
+ "path": "^framework/((Debug|Release|RelWithDebInfo|MinSizeRel)/)?exe_framework(\\.exe)?$",
+ "_dllExtra": false
+ },
+ {
+ "path": "^framework/((Debug|Release|RelWithDebInfo|MinSizeRel)/)?exe_framework\\.pdb$",
+ "_dllExtra": true
+ }
+ ],
+ "build": "^framework$",
+ "source": "^framework$",
+ "install": null,
+ "link": {
+ "language": "CXX",
+ "lto": null,
+ "commandFragments": [
+ {
+ "fragment": ".*static_framework.*",
+ "role": "libraries",
+ "backtrace": [
+ {
+ "file": "^framework/CMakeLists\\.txt$",
+ "line": 17,
+ "command": "target_link_libraries",
+ "hasParent": true
+ },
+ {
+ "file": "^framework/CMakeLists\\.txt$",
+ "line": null,
+ "command": null,
+ "hasParent": false
+ }
+ ]
+ },
+ {
+ "fragment": ".*shared_framework.*",
+ "role": "libraries",
+ "backtrace": [
+ {
+ "file": "^framework/CMakeLists\\.txt$",
+ "line": 17,
+ "command": "target_link_libraries",
+ "hasParent": true
+ },
+ {
+ "file": "^framework/CMakeLists\\.txt$",
+ "line": null,
+ "command": null,
+ "hasParent": false
+ }
+ ]
+ }
+ ]
+ },
+ "archive": null,
+ "dependencies": [
+ {
+ "id": "^static_framework::@217a96c3a62328a73ef4$",
+ "backtrace": [
+ {
+ "file": "^framework/CMakeLists\\.txt$",
+ "line": 17,
+ "command": "target_link_libraries",
+ "hasParent": true
+ },
+ {
+ "file": "^framework/CMakeLists\\.txt$",
+ "line": null,
+ "command": null,
+ "hasParent": false
+ }
+ ]
+ },
+ {
+ "id": "^shared_framework::@217a96c3a62328a73ef4$",
+ "backtrace": [
+ {
+ "file": "^framework/CMakeLists\\.txt$",
+ "line": 17,
+ "command": "target_link_libraries",
+ "hasParent": true
+ },
+ {
+ "file": "^framework/CMakeLists\\.txt$",
+ "line": null,
+ "command": null,
+ "hasParent": false
+ }
+ ]
+ },
+ {
+ "id": "^ZERO_CHECK::@217a96c3a62328a73ef4$",
+ "backtrace": null
+ }
+ ]
+}
diff --git a/Tests/RunCMake/FileAPI/codemodel-v2-data/targets/generated_exe.json b/Tests/RunCMake/FileAPI/codemodel-v2-data/targets/generated_exe.json
index 4b69682..f1ef8dd 100644
--- a/Tests/RunCMake/FileAPI/codemodel-v2-data/targets/generated_exe.json
+++ b/Tests/RunCMake/FileAPI/codemodel-v2-data/targets/generated_exe.json
@@ -108,6 +108,7 @@
]
}
],
+ "frameworks": null,
"defines": [
{
"define": "EMPTY_C=1",
@@ -223,6 +224,7 @@
]
}
],
+ "frameworks": null,
"defines": [
{
"define": "GENERATED_EXE=1",
diff --git a/Tests/RunCMake/FileAPI/codemodel-v2-data/targets/interface_exe.json b/Tests/RunCMake/FileAPI/codemodel-v2-data/targets/interface_exe.json
index c0c3e79..521e464 100644
--- a/Tests/RunCMake/FileAPI/codemodel-v2-data/targets/interface_exe.json
+++ b/Tests/RunCMake/FileAPI/codemodel-v2-data/targets/interface_exe.json
@@ -68,6 +68,7 @@
"^empty\\.c$"
],
"includes": null,
+ "frameworks": null,
"defines": [
{
"define": "interface_exe_EXPORTS",
diff --git a/Tests/RunCMake/FileAPI/codemodel-v2-data/targets/link_imported_exe.json b/Tests/RunCMake/FileAPI/codemodel-v2-data/targets/link_imported_exe.json
index 45fb0a5..531d8dc 100644
--- a/Tests/RunCMake/FileAPI/codemodel-v2-data/targets/link_imported_exe.json
+++ b/Tests/RunCMake/FileAPI/codemodel-v2-data/targets/link_imported_exe.json
@@ -44,6 +44,7 @@
"^empty\\.c$"
],
"includes": null,
+ "frameworks": null,
"defines": null,
"compileCommandFragments": null
}
diff --git a/Tests/RunCMake/FileAPI/codemodel-v2-data/targets/link_imported_interface_exe.json b/Tests/RunCMake/FileAPI/codemodel-v2-data/targets/link_imported_interface_exe.json
index 74c179c..691edff 100644
--- a/Tests/RunCMake/FileAPI/codemodel-v2-data/targets/link_imported_interface_exe.json
+++ b/Tests/RunCMake/FileAPI/codemodel-v2-data/targets/link_imported_interface_exe.json
@@ -44,6 +44,7 @@
"^empty\\.c$"
],
"includes": null,
+ "frameworks": null,
"defines": null,
"compileCommandFragments": null
}
diff --git a/Tests/RunCMake/FileAPI/codemodel-v2-data/targets/link_imported_object_exe.json b/Tests/RunCMake/FileAPI/codemodel-v2-data/targets/link_imported_object_exe.json
index 6771747..555accc 100644
--- a/Tests/RunCMake/FileAPI/codemodel-v2-data/targets/link_imported_object_exe.json
+++ b/Tests/RunCMake/FileAPI/codemodel-v2-data/targets/link_imported_object_exe.json
@@ -44,6 +44,7 @@
"^empty\\.c$"
],
"includes": null,
+ "frameworks": null,
"defines": null,
"compileCommandFragments": null
}
diff --git a/Tests/RunCMake/FileAPI/codemodel-v2-data/targets/link_imported_shared_exe.json b/Tests/RunCMake/FileAPI/codemodel-v2-data/targets/link_imported_shared_exe.json
index 659e3fb..ead2362 100644
--- a/Tests/RunCMake/FileAPI/codemodel-v2-data/targets/link_imported_shared_exe.json
+++ b/Tests/RunCMake/FileAPI/codemodel-v2-data/targets/link_imported_shared_exe.json
@@ -44,6 +44,7 @@
"^empty\\.c$"
],
"includes": null,
+ "frameworks": null,
"defines": null,
"compileCommandFragments": null
}
diff --git a/Tests/RunCMake/FileAPI/codemodel-v2-data/targets/link_imported_static_exe.json b/Tests/RunCMake/FileAPI/codemodel-v2-data/targets/link_imported_static_exe.json
index 7bdaffb..26dc9db 100644
--- a/Tests/RunCMake/FileAPI/codemodel-v2-data/targets/link_imported_static_exe.json
+++ b/Tests/RunCMake/FileAPI/codemodel-v2-data/targets/link_imported_static_exe.json
@@ -44,6 +44,7 @@
"^empty\\.c$"
],
"includes": null,
+ "frameworks": null,
"defines": null,
"compileCommandFragments": null
}
diff --git a/Tests/RunCMake/FileAPI/codemodel-v2-data/targets/shared_framework.json b/Tests/RunCMake/FileAPI/codemodel-v2-data/targets/shared_framework.json
new file mode 100644
index 0000000..41b5605
--- /dev/null
+++ b/Tests/RunCMake/FileAPI/codemodel-v2-data/targets/shared_framework.json
@@ -0,0 +1,102 @@
+{
+ "name": "shared_framework",
+ "id": "^shared_framework::@217a96c3a62328a73ef4$",
+ "directorySource": "^framework$",
+ "projectName": "Framework",
+ "type": "SHARED_LIBRARY",
+ "isGeneratorProvided": null,
+ "fileSets": null,
+ "sources": [
+ {
+ "path": "^empty\\.cxx$",
+ "isGenerated": null,
+ "fileSetName": null,
+ "sourceGroupName": "Source Files",
+ "compileGroupLanguage": "CXX",
+ "backtrace": [
+ {
+ "file": "^framework/CMakeLists\\.txt$",
+ "line": 7,
+ "command": "add_library",
+ "hasParent": true
+ },
+ {
+ "file": "^framework/CMakeLists\\.txt$",
+ "line": null,
+ "command": null,
+ "hasParent": false
+ }
+ ]
+ }
+ ],
+ "sourceGroups": [
+ {
+ "name": "Source Files",
+ "sourcePaths": [
+ "^empty\\.cxx$"
+ ]
+ }
+ ],
+ "compileGroups": [
+ {
+ "language": "CXX",
+ "sourcePaths": [
+ "^empty\\.cxx$"
+ ],
+ "includes": null,
+ "frameworks": null,
+ "defines": [
+ {
+ "define": "shared_framework_EXPORTS",
+ "backtrace": null
+ }
+ ],
+ "compileCommandFragments": null
+ }
+ ],
+ "backtrace": [
+ {
+ "file": "^framework/CMakeLists\\.txt$",
+ "line": 7,
+ "command": "add_library",
+ "hasParent": true
+ },
+ {
+ "file": "^framework/CMakeLists\\.txt$",
+ "line": null,
+ "command": null,
+ "hasParent": false
+ }
+ ],
+ "folder": null,
+ "nameOnDisk": "^(lib|cyg|msys-)?shared_framework\\.(so|dylib|dll)$",
+ "artifacts": [
+ {
+ "path": "^framework/((Debug|Release|RelWithDebInfo|MinSizeRel)/)?(lib|cyg|msys-)?shared_framework\\.(so|dylib|dll)$",
+ "_dllExtra": false
+ },
+ {
+ "path": "^framework/((Debug|Release|RelWithDebInfo|MinSizeRel)/)?(lib)?shared_framework\\.(dll\\.a|lib)$",
+ "_dllExtra": true
+ },
+ {
+ "path": "^framework/((Debug|Release|RelWithDebInfo|MinSizeRel)/)?(lib|cyg|msys-)?shared_framework\\.pdb$",
+ "_dllExtra": true
+ }
+ ],
+ "build": "^framework$",
+ "source": "^framework$",
+ "install": null,
+ "link": {
+ "language": "CXX",
+ "lto": null,
+ "commandFragments": null
+ },
+ "archive": null,
+ "dependencies": [
+ {
+ "id": "^ZERO_CHECK::@217a96c3a62328a73ef4$",
+ "backtrace": null
+ }
+ ]
+}
diff --git a/Tests/RunCMake/FileAPI/codemodel-v2-data/targets/static_framework.json b/Tests/RunCMake/FileAPI/codemodel-v2-data/targets/static_framework.json
new file mode 100644
index 0000000..00dd11e
--- /dev/null
+++ b/Tests/RunCMake/FileAPI/codemodel-v2-data/targets/static_framework.json
@@ -0,0 +1,87 @@
+{
+ "name": "static_framework",
+ "id": "^static_framework::@217a96c3a62328a73ef4$",
+ "directorySource": "^framework$",
+ "projectName": "Framework",
+ "type": "STATIC_LIBRARY",
+ "isGeneratorProvided": null,
+ "fileSets": null,
+ "sources": [
+ {
+ "path": "^empty\\.cxx$",
+ "isGenerated": null,
+ "fileSetName": null,
+ "sourceGroupName": "Source Files",
+ "compileGroupLanguage": "CXX",
+ "backtrace": [
+ {
+ "file": "^framework/CMakeLists\\.txt$",
+ "line": 4,
+ "command": "add_library",
+ "hasParent": true
+ },
+ {
+ "file": "^framework/CMakeLists\\.txt$",
+ "line": null,
+ "command": null,
+ "hasParent": false
+ }
+ ]
+ }
+ ],
+ "sourceGroups": [
+ {
+ "name": "Source Files",
+ "sourcePaths": [
+ "^empty\\.cxx$"
+ ]
+ }
+ ],
+ "compileGroups": [
+ {
+ "language": "CXX",
+ "sourcePaths": [
+ "^empty\\.cxx$"
+ ],
+ "includes": null,
+ "frameworks": null,
+ "defines": null,
+ "compileCommandFragments": null
+ }
+ ],
+ "backtrace": [
+ {
+ "file": "^framework/CMakeLists\\.txt$",
+ "line": 4,
+ "command": "add_library",
+ "hasParent": true
+ },
+ {
+ "file": "^framework/CMakeLists\\.txt$",
+ "line": null,
+ "command": null,
+ "hasParent": false
+ }
+ ],
+ "folder": null,
+ "nameOnDisk": "^(lib)?static_framework\\.(a|lib)$",
+ "artifacts": [
+ {
+ "path": "^framework/((Debug|Release|RelWithDebInfo|MinSizeRel)/)?(lib)?static_framework\\.(a|lib)$",
+ "_dllExtra": false
+ }
+ ],
+ "build": "^framework$",
+ "source": "^framework$",
+ "install": null,
+ "link": null,
+ "archive": {
+ "lto": null
+ },
+ "dependencies": [
+ {
+ "id": "^ZERO_CHECK::@217a96c3a62328a73ef4$",
+ "backtrace": null
+ }
+ ]
+}
diff --git a/Tests/RunCMake/FileAPI/codemodel-v2-data/targets/zero_check_framework.json b/Tests/RunCMake/FileAPI/codemodel-v2-data/targets/zero_check_framework.json
new file mode 100644
index 0000000..6206517
--- /dev/null
+++ b/Tests/RunCMake/FileAPI/codemodel-v2-data/targets/zero_check_framework.json
@@ -0,0 +1,73 @@
+{
+ "name": "ZERO_CHECK",
+ "id": "^ZERO_CHECK::@217a96c3a62328a73ef4$",
+ "directorySource": "^framework$",
+ "projectName": "Framework",
+ "type": "UTILITY",
+ "isGeneratorProvided": true,
+ "fileSets": null,
+ "sources": [
+ {
+ "path": "^.*/Tests/RunCMake/FileAPI/codemodel-v2-build/framework/CMakeFiles/ZERO_CHECK$",
+ "isGenerated": true,
+ "fileSetName": null,
+ "sourceGroupName": "",
+ "compileGroupLanguage": null,
+ "backtrace": [
+ {
+ "file": "^framework/CMakeLists\\.txt$",
+ "line": null,
+ "command": null,
+ "hasParent": false
+ }
+ ]
+ },
+ {
+ "path": "^.*/Tests/RunCMake/FileAPI/codemodel-v2-build/framework/CMakeFiles/ZERO_CHECK\\.rule$",
+ "isGenerated": true,
+ "fileSetName": null,
+ "sourceGroupName": "CMake Rules",
+ "compileGroupLanguage": null,
+ "backtrace": [
+ {
+ "file": "^framework/CMakeLists\\.txt$",
+ "line": null,
+ "command": null,
+ "hasParent": false
+ }
+ ]
+ }
+ ],
+ "sourceGroups": [
+ {
+ "name": "",
+ "sourcePaths": [
+ "^.*/Tests/RunCMake/FileAPI/codemodel-v2-build/framework/CMakeFiles/ZERO_CHECK$"
+ ]
+ },
+ {
+ "name": "CMake Rules",
+ "sourcePaths": [
+ "^.*/Tests/RunCMake/FileAPI/codemodel-v2-build/framework/CMakeFiles/ZERO_CHECK\\.rule$"
+ ]
+ }
+ ],
+ "compileGroups": null,
+ "backtrace": [
+ {
+ "file": "^framework/CMakeLists\\.txt$",
+ "line": null,
+ "command": null,
+ "hasParent": false
+ }
+ ],
+ "folder": null,
+ "nameOnDisk": null,
+ "artifacts": null,
+ "build": "^framework$",
+ "source": "^framework$",
+ "install": null,
+ "link": null,
+ "archive": null,
+ "dependencies": null
+}
diff --git a/Tests/RunCMake/FileAPI/codemodel-v2.cmake b/Tests/RunCMake/FileAPI/codemodel-v2.cmake
index 09db216..5f4019d 100644
--- a/Tests/RunCMake/FileAPI/codemodel-v2.cmake
+++ b/Tests/RunCMake/FileAPI/codemodel-v2.cmake
@@ -26,6 +26,7 @@ add_subdirectory(custom)
add_subdirectory("${CMAKE_CURRENT_SOURCE_DIR}/../FileAPIExternalSource" "${CMAKE_CURRENT_BINARY_DIR}/../FileAPIExternalBuild")
add_subdirectory(dir)
add_subdirectory(fileset)
+add_subdirectory(framework)
set_property(TARGET c_shared_lib PROPERTY LIBRARY_OUTPUT_DIRECTORY lib)
set_property(TARGET c_shared_lib PROPERTY RUNTIME_OUTPUT_DIRECTORY lib)
diff --git a/Tests/RunCMake/FileAPI/framework/CMakeLists.txt b/Tests/RunCMake/FileAPI/framework/CMakeLists.txt
new file mode 100644
index 0000000..d69efbb
--- /dev/null
+++ b/Tests/RunCMake/FileAPI/framework/CMakeLists.txt
@@ -0,0 +1,17 @@
+project(Framework)
+enable_language(CXX)
+
+add_library(static_framework STATIC ../empty.cxx)
+set_property(TARGET static_framework PROPERTY FRAMEWORK ON)
+
+add_library(shared_framework SHARED ../empty.cxx)
+set_property(TARGET shared_framework PROPERTY FRAMEWORK ON)
+set_property(TARGET shared_framework PROPERTY SYSTEM ON)
+
+add_library(import_framework SHARED IMPORTED)
+set_property(TARGET import_framework PROPERTY FRAMEWORK ON)
+set_property(TARGET import_framework PROPERTY IMPORTED_LOCATION /usr/Frameworks/Foo.framework/Foo)
+set_property(TARGET import_framework PROPERTY IMPORTED_IMPLIB /usr/Frameworks/Foo.framework/Foo.lib)
+
+add_executable(exe_framework ../empty.cxx)
+target_link_libraries(exe_framework PRIVATE static_framework shared_framework import_framework)
diff --git a/Tests/RunCMake/File_Generate/CMP0070-NEW-check.cmake b/Tests/RunCMake/File_Generate/CMP0070-NEW-check.cmake
index 05ec26e..6183635 100644
--- a/Tests/RunCMake/File_Generate/CMP0070-NEW-check.cmake
+++ b/Tests/RunCMake/File_Generate/CMP0070-NEW-check.cmake
@@ -5,7 +5,7 @@ foreach(f
if(EXISTS "${f}")
file(READ "${f}" content)
if(NOT content MATCHES "^relative-input-NEW[\r\n]*$")
- string(APPEND RunCMake_TEST_FAILED "File\n ${f}\ndoes not have expected content.\n")
+ string(APPEND RunCMake_TEST_FAILED "File\n ${f}\n" "does not have expected content.\n")
endif()
else()
string(APPEND RunCMake_TEST_FAILED "Missing\n ${f}\n")
diff --git a/Tests/RunCMake/File_Generate/CMP0070-OLD-check.cmake b/Tests/RunCMake/File_Generate/CMP0070-OLD-check.cmake
index a71d822..0f0fc09 100644
--- a/Tests/RunCMake/File_Generate/CMP0070-OLD-check.cmake
+++ b/Tests/RunCMake/File_Generate/CMP0070-OLD-check.cmake
@@ -5,7 +5,7 @@ foreach(f
if(EXISTS "${f}")
file(READ "${f}" content)
if(NOT content MATCHES "^relative-input-OLD[\r\n]*$")
- string(APPEND RunCMake_TEST_FAILED "File\n ${f}\ndoes not have expected content.\n")
+ string(APPEND RunCMake_TEST_FAILED "File\n ${f}\n" "does not have expected content.\n")
endif()
else()
string(APPEND RunCMake_TEST_FAILED "Missing\n ${f}\n")
diff --git a/Tests/RunCMake/File_Generate/CMP0070-WARN-check.cmake b/Tests/RunCMake/File_Generate/CMP0070-WARN-check.cmake
index 1488df0..0ee4a82 100644
--- a/Tests/RunCMake/File_Generate/CMP0070-WARN-check.cmake
+++ b/Tests/RunCMake/File_Generate/CMP0070-WARN-check.cmake
@@ -5,7 +5,7 @@ foreach(f
if(EXISTS "${f}")
file(READ "${f}" content)
if(NOT content MATCHES "^relative-input-WARN[\r\n]*$")
- string(APPEND RunCMake_TEST_FAILED "File\n ${f}\ndoes not have expected content.\n")
+ string(APPEND RunCMake_TEST_FAILED "File\n ${f}\n" "does not have expected content.\n")
endif()
else()
string(APPEND RunCMake_TEST_FAILED "Missing\n ${f}\n")
diff --git a/Tests/RunCMake/GenEx-LINK_LIBRARY/RunCMakeTest.cmake b/Tests/RunCMake/GenEx-LINK_LIBRARY/RunCMakeTest.cmake
index 7df0e80..2ad45ba 100644
--- a/Tests/RunCMake/GenEx-LINK_LIBRARY/RunCMakeTest.cmake
+++ b/Tests/RunCMake/GenEx-LINK_LIBRARY/RunCMakeTest.cmake
@@ -29,7 +29,7 @@ run_cmake(nested-compatible-features)
run_cmake(nested-incompatible-features)
run_cmake(only-targets)
-# testing target propertes LINK_LIBRARY_OVERRIDE and LINK_LIBRARY_OVERRIDE_<LIBRARY>
+# testing target properties LINK_LIBRARY_OVERRIDE and LINK_LIBRARY_OVERRIDE_<LIBRARY>
run_cmake(override-features1)
run_cmake(override-features2)
run_cmake(override-features3)
diff --git a/Tests/RunCMake/GeneratorToolset/TestToolsetCustomFlagTableDir-check.cmake b/Tests/RunCMake/GeneratorToolset/TestToolsetCustomFlagTableDir-check.cmake
index 79752b1..f95173b 100644
--- a/Tests/RunCMake/GeneratorToolset/TestToolsetCustomFlagTableDir-check.cmake
+++ b/Tests/RunCMake/GeneratorToolset/TestToolsetCustomFlagTableDir-check.cmake
@@ -1,6 +1,6 @@
set(vcProjectFile "${RunCMake_TEST_BINARY_DIR}/main.vcxproj")
if(NOT EXISTS "${vcProjectFile}")
- set(RunCMake_TEST_FAILED "Project file\n ${vcProjectFile}\ndoes not exist.")
+ string(CONCAT RunCMake_TEST_FAILED "Project file\n ${vcProjectFile}\n" "does not exist.")
return()
endif()
diff --git a/Tests/RunCMake/GoogleTest/GoogleTestXML.cmake b/Tests/RunCMake/GoogleTest/GoogleTestXML.cmake
index 53eedc0..308bdbf 100644
--- a/Tests/RunCMake/GoogleTest/GoogleTestXML.cmake
+++ b/Tests/RunCMake/GoogleTest/GoogleTestXML.cmake
@@ -5,13 +5,13 @@ enable_testing()
include(xcode_sign_adhoc.cmake)
-# This creates the folder structure for the paramterized tests
+# This creates the folder structure for the parameterized tests
# to avoid handling missing folders in C++
#
# This must match the match the name defined in xml_output.cpp
# for every instance of tests with GetParam.
#
-# The folder name is created fom the test name (output of the line
+# The folder name is created from the test name (output of the line
# without leading spaces: "GoogleTestXMLSpecial/cases.") and
# the parts until the last slash ("case/"). These parts are concatenated.
file(MAKE_DIRECTORY "${CMAKE_BINARY_DIR}/GoogleTestXMLSpecial/cases.case")
diff --git a/Tests/RunCMake/MacOSVersions/MacOSVersions-build-check.cmake b/Tests/RunCMake/MacOSVersions/MacOSVersions-build-check.cmake
index c4faa8b..3eff573 100644
--- a/Tests/RunCMake/MacOSVersions/MacOSVersions-build-check.cmake
+++ b/Tests/RunCMake/MacOSVersions/MacOSVersions-build-check.cmake
@@ -21,7 +21,7 @@ foreach(ver
[[compatibility version 2\.1\.0]]
)
if(NOT "${out}" MATCHES "( |\n)${ver}( |\n)")
- set(RunCMake_TEST_FAILED "Library file:\n ${lib}\ndoes not contain '${ver}'")
+ string(CONCAT RunCMake_TEST_FAILED "Library file:\n ${lib}\n" "does not contain '${ver}'")
return()
endif()
endforeach()
diff --git a/Tests/RunCMake/Ninja/CustomCommandDepfile-check.cmake b/Tests/RunCMake/Ninja/CustomCommandDepfile-check.cmake
index 51f4f52..edde0c0 100644
--- a/Tests/RunCMake/Ninja/CustomCommandDepfile-check.cmake
+++ b/Tests/RunCMake/Ninja/CustomCommandDepfile-check.cmake
@@ -3,8 +3,10 @@ file(READ "${log}" build_file)
set(RunCMake_TEST_FAILED)
if(NOT "${build_file}" MATCHES "depfile = test\\.d")
- list(APPEND RunCMake_TEST_FAILED "Log file:\n ${log}\ndoes not have expected line: depfile = test.d")
+ string(CONCAT no_test_d "Log file:\n ${log}\n" "does not have expected line: depfile = test.d")
+ list(APPEND RunCMake_TEST_FAILED "${no_test_d}")
endif()
if(NOT "${build_file}" MATCHES "depfile = test_Debug\\.d")
- list(APPEND RunCMake_TEST_FAILED "\nLog file:\n ${log}\ndoes not have expected line: depfile = test_Debug.d")
+ string(CONCAT no_test_Debug_d "\nLog file:\n ${log}\n" "does not have expected line: depfile = test_Debug.d")
+ list(APPEND RunCMake_TEST_FAILED "${no_test_Debug_d}")
endif()
diff --git a/Tests/RunCMake/Ninja/CustomCommandJobPool-check.cmake b/Tests/RunCMake/Ninja/CustomCommandJobPool-check.cmake
index 7f7fa33..793b5d2 100644
--- a/Tests/RunCMake/Ninja/CustomCommandJobPool-check.cmake
+++ b/Tests/RunCMake/Ninja/CustomCommandJobPool-check.cmake
@@ -1,8 +1,8 @@
set(log "${RunCMake_BINARY_DIR}/CustomCommandJobPool-build/build.ninja")
file(READ "${log}" build_file)
if(NOT "${build_file}" MATCHES "pool = custom_command_pool")
- set(RunCMake_TEST_FAILED "Log file:\n ${log}\ndoes not have expected line: pool = custom_command_pool")
+ string(CONCAT RunCMake_TEST_FAILED "Log file:\n ${log}\n" "does not have expected line: pool = custom_command_pool")
endif()
if(NOT "${build_file}" MATCHES "pool = custom_target_pool")
- set(RunCMake_TEST_FAILED "Log file:\n ${log}\ndoes not have expected line: pool = custom_target_pool")
+ string(CONCAT RunCMake_TEST_FAILED "Log file:\n ${log}\n" "does not have expected line: pool = custom_target_pool")
endif()
diff --git a/Tests/RunCMake/Ninja/VerboseBuild-nowork-stdout.txt b/Tests/RunCMake/Ninja/VerboseBuild-nowork-stdout.txt
index 60a9228..40b4527 100644
--- a/Tests/RunCMake/Ninja/VerboseBuild-nowork-stdout.txt
+++ b/Tests/RunCMake/Ninja/VerboseBuild-nowork-stdout.txt
@@ -1 +1 @@
-^ninja: no work to do
+ninja: no work to do
diff --git a/Tests/RunCMake/NinjaMultiConfig/CustomCommandDepfile-check.cmake b/Tests/RunCMake/NinjaMultiConfig/CustomCommandDepfile-check.cmake
index a7837ca..3674aba 100644
--- a/Tests/RunCMake/NinjaMultiConfig/CustomCommandDepfile-check.cmake
+++ b/Tests/RunCMake/NinjaMultiConfig/CustomCommandDepfile-check.cmake
@@ -3,8 +3,10 @@ file(READ "${log}" build_file)
set(RunCMake_TEST_FAILED)
if(NOT "${build_file}" MATCHES "depfile = test\\.d")
- list(APPEND RunCMake_TEST_FAILED "Log file:\n ${log}\ndoes not have expected line: depfile = test.d")
+ string(CONCAT no_test_d "Log file:\n ${log}\n" "does not have expected line: depfile = test.d")
+ list(APPEND RunCMake_TEST_FAILED "${no_test_d}")
endif()
if(NOT "${build_file}" MATCHES "depfile = test_Debug\\.d")
- list(APPEND RunCMake_TEST_FAILED "\nLog file:\n ${log}\ndoes not have expected line: depfile = test_Debug.d")
+ string(CONCAT no_test_Debug_d "\nLog file:\n ${log}\n" "does not have expected line: depfile = test_Debug.d")
+ list(APPEND RunCMake_TEST_FAILED "${no_test_Debug_d}")
endif()
diff --git a/Tests/RunCMake/ParseImplicitLinkInfo/ExcludeDirs.cmake b/Tests/RunCMake/ParseImplicitLinkInfo/ExcludeDirs.cmake
new file mode 100644
index 0000000..6cece68
--- /dev/null
+++ b/Tests/RunCMake/ParseImplicitLinkInfo/ExcludeDirs.cmake
@@ -0,0 +1,10 @@
+include("${info}")
+list(GET INFO_CMAKE_C_IMPLICIT_LINK_DIRECTORIES -1 last_dir)
+set(ENV{CMAKE_C_IMPLICIT_LINK_DIRECTORIES_EXCLUDE} "${last_dir}")
+enable_language(C)
+message(STATUS "INFO_CMAKE_C_IMPLICIT_LINK_DIRECTORIES=[${INFO_CMAKE_C_IMPLICIT_LINK_DIRECTORIES}]")
+message(STATUS "ENV{CMAKE_C_IMPLICIT_LINK_DIRECTORIES_EXCLUDE}=[$ENV{CMAKE_C_IMPLICIT_LINK_DIRECTORIES_EXCLUDE}]")
+message(STATUS "CMAKE_C_IMPLICIT_LINK_DIRECTORIES=[${CMAKE_C_IMPLICIT_LINK_DIRECTORIES}]")
+if("${last_dir}" IN_LIST CMAKE_C_IMPLICIT_LINK_DIRECTORIES)
+ message(FATAL_ERROR "${last_dir} was not excluded!")
+endif()
diff --git a/Tests/RunCMake/ParseImplicitLinkInfo/Inspect.cmake b/Tests/RunCMake/ParseImplicitLinkInfo/Inspect.cmake
new file mode 100644
index 0000000..42e1c67
--- /dev/null
+++ b/Tests/RunCMake/ParseImplicitLinkInfo/Inspect.cmake
@@ -0,0 +1,12 @@
+enable_language(C)
+
+set(info "")
+foreach(var
+ CMAKE_C_IMPLICIT_LINK_DIRECTORIES
+ )
+ if(DEFINED ${var})
+ string(APPEND info "set(INFO_${var} \"${${var}}\")\n")
+ endif()
+endforeach()
+
+file(WRITE "${CMAKE_CURRENT_BINARY_DIR}/info.cmake" "${info}")
diff --git a/Tests/RunCMake/ParseImplicitLinkInfo/RunCMakeTest.cmake b/Tests/RunCMake/ParseImplicitLinkInfo/RunCMakeTest.cmake
index 713e2e7..c7655d2 100644
--- a/Tests/RunCMake/ParseImplicitLinkInfo/RunCMakeTest.cmake
+++ b/Tests/RunCMake/ParseImplicitLinkInfo/RunCMakeTest.cmake
@@ -1,3 +1,11 @@
include(RunCMake)
run_cmake(ParseImplicitLinkInfo)
+
+run_cmake(Inspect)
+set(info "${RunCMake_BINARY_DIR}/Inspect-build/info.cmake")
+include("${info}")
+
+if(INFO_CMAKE_C_IMPLICIT_LINK_DIRECTORIES MATCHES ";")
+ run_cmake_with_options(ExcludeDirs "-Dinfo=${RunCMake_BINARY_DIR}/Inspect-build/info.cmake")
+endif()
diff --git a/Tests/RunCMake/ctest_memcheck/testAddressLeakSanitizer.cmake b/Tests/RunCMake/ctest_memcheck/testAddressLeakSanitizer.cmake
index 58c94d7..2b49bbb 100644
--- a/Tests/RunCMake/ctest_memcheck/testAddressLeakSanitizer.cmake
+++ b/Tests/RunCMake/ctest_memcheck/testAddressLeakSanitizer.cmake
@@ -23,7 +23,7 @@ file(APPEND "${LOG_FILE}.2343"
Direct leak of 4360 byte(s) in 1 object(s) allocated from:
#0 0x46c669 in operator new[](unsigned long) (/home/kitware/msan/a.out+0x46c669)
#1 0x4823b4 in main /home/kitware/msan/memcheck.cxx:12
- #2 0x7fa72bee476c in __libc_start_main /build/buildd/eglibc-2.15/csu/libc-start.c:226
+ #2 0x7fa72bee476c in __libc_start_main /build/eglibc-2.15/csu/libc-start.c:226
SUMMARY: AddressSanitizer: 4436 byte(s) leaked in 2 allocation(s).
")
@@ -35,13 +35,13 @@ Direct leak of 76 byte(s) in 1 object(s) allocated from:
#0 0x46c669 in operator new[](unsigned long) (/home/kitware/msan/a.out+0x46c669)
#1 0x4821b8 in foo() /home/kitware/msan/memcheck.cxx:4
#2 0x4823f2 in main /home/kitware/msan/memcheck.cxx:14
- #3 0x7fa72bee476c in __libc_start_main /build/buildd/eglibc-2.15/csu/libc-start.c:226
+ #3 0x7fa72bee476c in __libc_start_main /build/eglibc-2.15/csu/libc-start.c:226
Indirect leak of 76 byte(s) in 1 object(s) allocated from:
#0 0x46c669 in operator new[](unsigned long) (/home/kitware/msan/a.out+0x46c669)
#1 0x4821b8 in foo() /home/kitware/msan/memcheck.cxx:4
#2 0x4823f2 in main /home/kitware/msan/memcheck.cxx:14
- #3 0x7fa72bee476c in __libc_start_main /build/buildd/eglibc-2.15/csu/libc-start.c:226
+ #3 0x7fa72bee476c in __libc_start_main /build/eglibc-2.15/csu/libc-start.c:226
SUMMARY: AddressSanitizer: 4436 byte(s) leaked in 2 allocation(s).
")
diff --git a/Tests/RunCMake/ctest_memcheck/testAddressSanitizer.cmake b/Tests/RunCMake/ctest_memcheck/testAddressSanitizer.cmake
index 8f18cd0..6612375 100644
--- a/Tests/RunCMake/ctest_memcheck/testAddressSanitizer.cmake
+++ b/Tests/RunCMake/ctest_memcheck/testAddressSanitizer.cmake
@@ -42,7 +42,7 @@ Shadow byte legend (one shadow byte represents 8 application bytes):
Addressable: 00
Partially addressable: 01 02 03 04 05 06 07
Heap left redzone: fa
- Heap righ redzone: fb
+ Heap right redzone: fb
Freed Heap region: fd
Stack left redzone: f1
Stack mid redzone: f2
diff --git a/Tests/RunCMake/ctest_memcheck/testLeakSanitizer.cmake b/Tests/RunCMake/ctest_memcheck/testLeakSanitizer.cmake
index 4990792..45f3c45 100644
--- a/Tests/RunCMake/ctest_memcheck/testLeakSanitizer.cmake
+++ b/Tests/RunCMake/ctest_memcheck/testLeakSanitizer.cmake
@@ -23,7 +23,7 @@ file(APPEND "${LOG_FILE}.2343"
Direct leak of 4360 byte(s) in 1 object(s) allocated from:
#0 0x46c669 in operator new[](unsigned long) (/home/kitware/msan/a.out+0x46c669)
#1 0x4823b4 in main /home/kitware/msan/memcheck.cxx:12
- #2 0x7fa72bee476c in __libc_start_main /build/buildd/eglibc-2.15/csu/libc-start.c:226
+ #2 0x7fa72bee476c in __libc_start_main /build/eglibc-2.15/csu/libc-start.c:226
SUMMARY: LeakSanitizer: 4436 byte(s) leaked in 2 allocation(s).
")
@@ -35,13 +35,13 @@ Direct leak of 76 byte(s) in 1 object(s) allocated from:
#0 0x46c669 in operator new[](unsigned long) (/home/kitware/msan/a.out+0x46c669)
#1 0x4821b8 in foo() /home/kitware/msan/memcheck.cxx:4
#2 0x4823f2 in main /home/kitware/msan/memcheck.cxx:14
- #3 0x7fa72bee476c in __libc_start_main /build/buildd/eglibc-2.15/csu/libc-start.c:226
+ #3 0x7fa72bee476c in __libc_start_main /build/eglibc-2.15/csu/libc-start.c:226
Indirect leak of 76 byte(s) in 1 object(s) allocated from:
#0 0x46c669 in operator new[](unsigned long) (/home/kitware/msan/a.out+0x46c669)
#1 0x4821b8 in foo() /home/kitware/msan/memcheck.cxx:4
#2 0x4823f2 in main /home/kitware/msan/memcheck.cxx:14
- #3 0x7fa72bee476c in __libc_start_main /build/buildd/eglibc-2.15/csu/libc-start.c:226
+ #3 0x7fa72bee476c in __libc_start_main /build/eglibc-2.15/csu/libc-start.c:226
SUMMARY: LeakSanitizer: 4436 byte(s) leaked in 2 allocation(s).
")
diff --git a/Tests/RunCMake/ctest_memcheck/testMemorySanitizer.cmake b/Tests/RunCMake/ctest_memcheck/testMemorySanitizer.cmake
index 4a6adb1..4b5ef7e 100644
--- a/Tests/RunCMake/ctest_memcheck/testMemorySanitizer.cmake
+++ b/Tests/RunCMake/ctest_memcheck/testMemorySanitizer.cmake
@@ -19,7 +19,7 @@ file(APPEND "${LOG_FILE}.2343"
"=================================================================
==28423== WARNING: MemorySanitizer: use-of-uninitialized-value
#0 0x7f4364210dd9 in main (/home/kitware/msan/msan-bin/umr+0x7bdd9)
- #1 0x7f4362d9376c in __libc_start_main /build/buildd/eglibc-2.15/csu/libc-start.c:226
+ #1 0x7f4362d9376c in __libc_start_main /build/eglibc-2.15/csu/libc-start.c:226
#2 0x7f4364210b0c in _start (/home/kitware/msan/msan-bin/umr+0x7bb0c)
SUMMARY: MemorySanitizer: use-of-uninitialized-value ??:0 main
diff --git a/Tests/RunCMake/file/COPY_FILE-file-replace.cmake b/Tests/RunCMake/file/COPY_FILE-file-replace.cmake
index 40e4290..cdb06fa 100644
--- a/Tests/RunCMake/file/COPY_FILE-file-replace.cmake
+++ b/Tests/RunCMake/file/COPY_FILE-file-replace.cmake
@@ -5,5 +5,5 @@ file(WRITE "${newname}" "b")
file(COPY_FILE "${oldname}" "${newname}")
file(READ "${newname}" new)
if(NOT "${new}" STREQUAL "a")
- message(FATAL_ERROR "New name:\n ${newname}\ndoes not contain expected content 'a'.")
+ message(FATAL_ERROR "New name:\n ${newname}\n" "does not contain expected content 'a'.")
endif()
diff --git a/Tests/RunCMake/file/COPY_FILE-link-to-file.cmake b/Tests/RunCMake/file/COPY_FILE-link-to-file.cmake
index 93a0204..53a6b11 100644
--- a/Tests/RunCMake/file/COPY_FILE-link-to-file.cmake
+++ b/Tests/RunCMake/file/COPY_FILE-link-to-file.cmake
@@ -6,5 +6,5 @@ file(CREATE_LINK "${lnkname}" "${oldname}")
file(COPY_FILE "${oldname}" "${newname}")
file(READ "${newname}" new)
if(NOT "${new}" STREQUAL "a")
- message(FATAL_ERROR "New name:\n ${newname}\ndoes not contain expected content 'a'.")
+ message(FATAL_ERROR "New name:\n ${newname}\n" "does not contain expected content 'a'.")
endif()
diff --git a/Tests/RunCMake/file/LOCK-error-guard-incorrect-stderr.txt b/Tests/RunCMake/file/LOCK-error-guard-incorrect-stderr.txt
index 85136b4..815ab5b 100644
--- a/Tests/RunCMake/file/LOCK-error-guard-incorrect-stderr.txt
+++ b/Tests/RunCMake/file/LOCK-error-guard-incorrect-stderr.txt
@@ -1,6 +1,6 @@
CMake Error at LOCK-error-guard-incorrect\.cmake:[0-9]+ \(file\):
expected FUNCTION, FILE or PROCESS after GUARD, but got:
- "FUNCTIO"\.
+ "FUNCTIO_"\.
Call Stack \(most recent call first\):
CMakeLists.txt:[0-9]+ \(include\)
diff --git a/Tests/RunCMake/file/LOCK-error-guard-incorrect.cmake b/Tests/RunCMake/file/LOCK-error-guard-incorrect.cmake
index 51daa7c..dddd4c0 100644
--- a/Tests/RunCMake/file/LOCK-error-guard-incorrect.cmake
+++ b/Tests/RunCMake/file/LOCK-error-guard-incorrect.cmake
@@ -1 +1 @@
-file(LOCK "${CMAKE_CURRENT_BINARY_DIR}/file-to-lock" GUARD FUNCTIO)
+file(LOCK "${CMAKE_CURRENT_BINARY_DIR}/file-to-lock" GUARD FUNCTIO_)
diff --git a/Tests/RunCMake/file/RENAME-file-replace.cmake b/Tests/RunCMake/file/RENAME-file-replace.cmake
index efbfaed..454e27e 100644
--- a/Tests/RunCMake/file/RENAME-file-replace.cmake
+++ b/Tests/RunCMake/file/RENAME-file-replace.cmake
@@ -5,5 +5,5 @@ file(WRITE "${newname}" "b")
file(RENAME "${oldname}" "${newname}")
file(READ "${newname}" new)
if(NOT "${new}" STREQUAL "a")
- message(FATAL_ERROR "New name:\n ${newname}\ndoes not contain expected content 'a'.")
+ message(FATAL_ERROR "New name:\n ${newname}\n" "does not contain expected content 'a'.")
endif()
diff --git a/Tests/RunCMake/message/RunCMakeTest.cmake b/Tests/RunCMake/message/RunCMakeTest.cmake
index c54e8f2..786b49b 100644
--- a/Tests/RunCMake/message/RunCMakeTest.cmake
+++ b/Tests/RunCMake/message/RunCMakeTest.cmake
@@ -10,7 +10,7 @@ run_cmake(message-internal-warning)
run_cmake(nomessage-internal-warning)
run_cmake(warnmessage)
-# Have to explicitly give the command for the working dir to be honoured
+# Have to explicitly give the command for the working dir to be honored
set(RunCMake_TEST_COMMAND_WORKING_DIRECTORY /)
run_cmake_command(
warnmessage-rootdir
diff --git a/Utilities/ClangTidyModule/CMakeLists.txt b/Utilities/ClangTidyModule/CMakeLists.txt
index 97c176f..582d54a 100644
--- a/Utilities/ClangTidyModule/CMakeLists.txt
+++ b/Utilities/ClangTidyModule/CMakeLists.txt
@@ -6,11 +6,15 @@ project(CMakeClangTidyModule C CXX)
get_filename_component(tmp "${CMAKE_CURRENT_SOURCE_DIR}" PATH)
get_filename_component(CMake_SOURCE_DIR "${tmp}" PATH)
-set(CMAKE_CXX_STANDARD 14)
-set(CMAKE_CXX_STANDARD_REQUIRED ON)
-
find_package(Clang REQUIRED)
+if(LLVM_VERSION_MAJOR GREATER_EQUAL 16)
+ set(CMAKE_CXX_STANDARD 17)
+else()
+ set(CMAKE_CXX_STANDARD 14)
+endif()
+set(CMAKE_CXX_STANDARD_REQUIRED ON)
+
add_library(cmake-clang-tidy-module MODULE
Module.cxx
diff --git a/Utilities/ClangTidyModule/UsePragmaOnceCheck.cxx b/Utilities/ClangTidyModule/UsePragmaOnceCheck.cxx
index 7a42798..37ecd70 100644
--- a/Utilities/ClangTidyModule/UsePragmaOnceCheck.cxx
+++ b/Utilities/ClangTidyModule/UsePragmaOnceCheck.cxx
@@ -218,8 +218,6 @@ public:
this
->EndIfs[this->Ifndefs[MacroEntry.first.getIdentifierInfo()].first];
- StringRef CurHeaderGuard =
- MacroEntry.first.getIdentifierInfo()->getName();
std::vector<FixItHint> FixIts;
HeaderSearch& HeaderInfo = this->PP->getHeaderSearchInfo();
diff --git a/Utilities/IWYU/mapping.imp b/Utilities/IWYU/mapping.imp
index 366c517..6c12ada 100644
--- a/Utilities/IWYU/mapping.imp
+++ b/Utilities/IWYU/mapping.imp
@@ -22,6 +22,7 @@
# HACK: check whether this can be removed with next iwyu release.
{ include: [ "<bits/cxxabi_forced.h>", private, "<ctime>", public ] },
+ { include: [ "<bits/exception.h>", private, "<exception>", public ] },
{ include: [ "<bits/shared_ptr.h>", private, "<memory>", public ] },
{ include: [ "<bits/std_function.h>", private, "<functional>", public ] },
{ include: [ "<bits/refwrap.h>", private, "<functional>", public ] },
@@ -101,6 +102,7 @@
{ symbol: [ "__gnu_cxx::__enable_if<true, bool>::__type", private, "\"cmConfigure.h\"", public ] },
{ symbol: [ "std::remove_reference<std::basic_string<char, std::char_traits<char>, std::allocator<char> > &>::type", private, "\"cmConfigure.h\"", public ] },
{ symbol: [ "std::remove_reference<Defer &>::type", private, "\"cmConfigure.h\"", public ] },
+ { symbol: [ "std::remove_reference<dap::StoppedEvent &>::type", private, "\"cmConfigure.h\"", public ] },
# Wrappers for 3rd-party libraries
{ include: [ "@<.*curl/curlver.h>", private, "<cm3p/curl/curl.h>", public ] },
diff --git a/Utilities/Scripts/update-cppdap.bash b/Utilities/Scripts/update-cppdap.bash
new file mode 100755
index 0000000..fd4f8cb
--- /dev/null
+++ b/Utilities/Scripts/update-cppdap.bash
@@ -0,0 +1,30 @@
+#!/usr/bin/env bash
+
+set -e
+set -x
+shopt -s dotglob
+
+readonly name="cppdap"
+readonly ownership="cppdap Upstream <kwrobot@kitware.com>"
+readonly subtree="Utilities/cmcppdap"
+readonly repo="https://github.com/google/cppdap.git"
+readonly tag="03cc18678ed2ed8b2424ec99dee7e4655d876db5" # 2023-05-25
+readonly shortlog=false
+readonly paths="
+ LICENSE
+ include
+ src
+"
+
+extract_source () {
+ git_archive
+
+ pushd "${extractdir}/${name}-reduced"
+ echo "* -whitespace" > .gitattributes
+ fromdos LICENSE include/dap/* src/*
+ echo "" >> LICENSE
+ echo "" >> src/nlohmann_json_serializer.h
+ popd
+}
+
+. "${BASH_SOURCE%/*}/update-third-party.bash"
diff --git a/Utilities/cm3p/cppdap/dap.h b/Utilities/cm3p/cppdap/dap.h
new file mode 100644
index 0000000..84fd332
--- /dev/null
+++ b/Utilities/cm3p/cppdap/dap.h
@@ -0,0 +1,11 @@
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
+#pragma once
+
+/* Use the cppdap library configured for CMake. */
+#include "cmThirdParty.h"
+#ifdef CMAKE_USE_SYSTEM_CPPDAP
+# include <dap/dap.h> // IWYU pragma: export
+#else
+# include <cmcppdap/include/dap/dap.h> // IWYU pragma: export
+#endif
diff --git a/Utilities/cm3p/cppdap/future.h b/Utilities/cm3p/cppdap/future.h
new file mode 100644
index 0000000..ad45b6b
--- /dev/null
+++ b/Utilities/cm3p/cppdap/future.h
@@ -0,0 +1,11 @@
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
+#pragma once
+
+/* Use the cppdap library configured for CMake. */
+#include "cmThirdParty.h"
+#ifdef CMAKE_USE_SYSTEM_CPPDAP
+# include <dap/future.h> // IWYU pragma: export
+#else
+# include <cmcppdap/include/dap/future.h> // IWYU pragma: export
+#endif
diff --git a/Utilities/cm3p/cppdap/io.h b/Utilities/cm3p/cppdap/io.h
new file mode 100644
index 0000000..e0401f8
--- /dev/null
+++ b/Utilities/cm3p/cppdap/io.h
@@ -0,0 +1,11 @@
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
+#pragma once
+
+/* Use the cppdap library configured for CMake. */
+#include "cmThirdParty.h"
+#ifdef CMAKE_USE_SYSTEM_CPPDAP
+# include <dap/io.h> // IWYU pragma: export
+#else
+# include <cmcppdap/include/dap/io.h> // IWYU pragma: export
+#endif
diff --git a/Utilities/cm3p/cppdap/optional.h b/Utilities/cm3p/cppdap/optional.h
new file mode 100644
index 0000000..777184d
--- /dev/null
+++ b/Utilities/cm3p/cppdap/optional.h
@@ -0,0 +1,11 @@
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
+#pragma once
+
+/* Use the cppdap library configured for CMake. */
+#include "cmThirdParty.h"
+#ifdef CMAKE_USE_SYSTEM_CPPDAP
+# include <dap/optional.h> // IWYU pragma: export
+#else
+# include <cmcppdap/include/dap/optional.h> // IWYU pragma: export
+#endif
diff --git a/Utilities/cm3p/cppdap/protocol.h b/Utilities/cm3p/cppdap/protocol.h
new file mode 100644
index 0000000..da70369
--- /dev/null
+++ b/Utilities/cm3p/cppdap/protocol.h
@@ -0,0 +1,11 @@
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
+#pragma once
+
+/* Use the cppdap library configured for CMake. */
+#include "cmThirdParty.h"
+#ifdef CMAKE_USE_SYSTEM_CPPDAP
+# include <dap/protocol.h> // IWYU pragma: export
+#else
+# include <cmcppdap/include/dap/protocol.h> // IWYU pragma: export
+#endif
diff --git a/Utilities/cm3p/cppdap/session.h b/Utilities/cm3p/cppdap/session.h
new file mode 100644
index 0000000..d4468e7
--- /dev/null
+++ b/Utilities/cm3p/cppdap/session.h
@@ -0,0 +1,11 @@
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
+#pragma once
+
+/* Use the cppdap library configured for CMake. */
+#include "cmThirdParty.h"
+#ifdef CMAKE_USE_SYSTEM_CPPDAP
+# include <dap/session.h> // IWYU pragma: export
+#else
+# include <cmcppdap/include/dap/session.h> // IWYU pragma: export
+#endif
diff --git a/Utilities/cm3p/cppdap/types.h b/Utilities/cm3p/cppdap/types.h
new file mode 100644
index 0000000..3fc2a88
--- /dev/null
+++ b/Utilities/cm3p/cppdap/types.h
@@ -0,0 +1,11 @@
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
+#pragma once
+
+/* Use the cppdap library configured for CMake. */
+#include "cmThirdParty.h"
+#ifdef CMAKE_USE_SYSTEM_CPPDAP
+# include <dap/types.h> // IWYU pragma: export
+#else
+# include <cmcppdap/include/dap/types.h> // IWYU pragma: export
+#endif
diff --git a/Utilities/cm3p/json/forwards.h b/Utilities/cm3p/json/forwards.h
new file mode 100644
index 0000000..c55c5c1
--- /dev/null
+++ b/Utilities/cm3p/json/forwards.h
@@ -0,0 +1,11 @@
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
+#pragma once
+
+/* Use the jsoncpp library configured for CMake. */
+#include "cmThirdParty.h"
+#ifdef CMAKE_USE_SYSTEM_JSONCPP
+# include <json/forwards.h> // IWYU pragma: export
+#else
+# include <cmjsoncpp/include/json/forwards.h> // IWYU pragma: export
+#endif
diff --git a/Utilities/cm3p/json/json.h b/Utilities/cm3p/json/json.h
new file mode 100644
index 0000000..5671e91
--- /dev/null
+++ b/Utilities/cm3p/json/json.h
@@ -0,0 +1,11 @@
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
+#pragma once
+
+/* Use the jsoncpp library configured for CMake. */
+#include "cmThirdParty.h"
+#ifdef CMAKE_USE_SYSTEM_JSONCPP
+# include <json/json.h> // IWYU pragma: export
+#else
+# include <cmjsoncpp/include/json/json.h> // IWYU pragma: export
+#endif
diff --git a/Utilities/cmThirdParty.h.in b/Utilities/cmThirdParty.h.in
index bd0edb7..da325b1 100644
--- a/Utilities/cmThirdParty.h.in
+++ b/Utilities/cmThirdParty.h.in
@@ -3,6 +3,7 @@
#pragma once
/* Whether CMake is using its own utility libraries. */
+#cmakedefine CMAKE_USE_SYSTEM_CPPDAP
#cmakedefine CMAKE_USE_SYSTEM_CURL
#cmakedefine CMAKE_USE_SYSTEM_EXPAT
#cmakedefine CMAKE_USE_SYSTEM_KWIML
diff --git a/Utilities/cmbzip2/bzlib.c b/Utilities/cmbzip2/bzlib.c
index 2178655..af3673d 100644
--- a/Utilities/cmbzip2/bzlib.c
+++ b/Utilities/cmbzip2/bzlib.c
@@ -444,6 +444,10 @@ int BZ_API(BZ2_bzCompress) ( bz_stream *strm, int action )
if (s->avail_in_expect != s->strm->avail_in)
return BZ_SEQUENCE_ERROR;
progress = handle_compress ( strm );
+ #ifdef __clang_analyzer__
+ /* Tolerate deadcode.DeadStores to avoid modifying upstream. */
+ (void)progress;
+ #endif
if (s->avail_in_expect > 0 || !isempty_RL(s) ||
s->state_out_pos < s->numZ) return BZ_FLUSH_OK;
s->mode = BZ_M_RUNNING;
diff --git a/Utilities/cmbzip2/compress.c b/Utilities/cmbzip2/compress.c
index 5dfa002..a044c16 100644
--- a/Utilities/cmbzip2/compress.c
+++ b/Utilities/cmbzip2/compress.c
@@ -151,6 +151,10 @@ void generateMTFValues ( EState* s )
UChar* block = s->block;
UInt16* mtfv = s->mtfv;
+#ifdef __clang_analyzer__
+ memset(yy, 0, sizeof(yy));
+#endif
+
makeMaps_e ( s );
EOB = s->nInUse+1;
@@ -223,6 +227,10 @@ void generateMTFValues ( EState* s )
zPend = (zPend - 2) / 2;
};
zPend = 0;
+ #ifdef __clang_analyzer__
+ /* Tolerate deadcode.DeadStores to avoid modifying upstream. */
+ (void)zPend;
+ #endif
}
mtfv[wr] = EOB; wr++; s->mtfFreq[EOB]++;
diff --git a/Utilities/cmcppdap/.gitattributes b/Utilities/cmcppdap/.gitattributes
new file mode 100644
index 0000000..562b12e
--- /dev/null
+++ b/Utilities/cmcppdap/.gitattributes
@@ -0,0 +1 @@
+* -whitespace
diff --git a/Utilities/cmcppdap/CMakeLists.txt b/Utilities/cmcppdap/CMakeLists.txt
new file mode 100644
index 0000000..39f72a2
--- /dev/null
+++ b/Utilities/cmcppdap/CMakeLists.txt
@@ -0,0 +1,37 @@
+# Disable warnings to avoid changing 3rd party code.
+if(CMAKE_CXX_COMPILER_ID MATCHES
+ "^(GNU|LCC|Clang|AppleClang|IBMClang|XLClang|XL|VisualAge|SunPro|HP|Intel|IntelLLVM|NVHPC)$")
+ set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -w")
+elseif(CMAKE_CXX_COMPILER_ID STREQUAL "PathScale")
+ set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -woffall")
+endif()
+
+add_library(cmcppdap STATIC
+ src/content_stream.cpp
+ src/io.cpp
+ src/jsoncpp_json_serializer.cpp
+ src/network.cpp
+ src/null_json_serializer.cpp
+ src/protocol_events.cpp
+ src/protocol_requests.cpp
+ src/protocol_response.cpp
+ src/protocol_types.cpp
+ src/session.cpp
+ src/socket.cpp
+ src/typeinfo.cpp
+ src/typeof.cpp
+)
+
+target_compile_definitions(cmcppdap PRIVATE CPPDAP_JSON_JSONCPP=1)
+target_include_directories(cmcppdap PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/include)
+set_property(TARGET cmcppdap PROPERTY CXX_CLANG_TIDY "")
+set_property(TARGET cmcppdap PROPERTY CXX_INCLUDE_WHAT_YOU_USE "")
+
+target_link_libraries(cmcppdap PRIVATE JsonCpp::JsonCpp)
+if(WIN32)
+ target_link_libraries(cmcppdap PRIVATE ws2_32)
+elseif(NOT APPLE)
+ target_link_libraries(cmcppdap PRIVATE Threads::Threads)
+endif()
+
+install(FILES NOTICE DESTINATION ${CMAKE_DOC_DIR}/cmcppdap)
diff --git a/Utilities/cmcppdap/LICENSE b/Utilities/cmcppdap/LICENSE
new file mode 100644
index 0000000..d645695
--- /dev/null
+++ b/Utilities/cmcppdap/LICENSE
@@ -0,0 +1,202 @@
+
+ Apache License
+ Version 2.0, January 2004
+ http://www.apache.org/licenses/
+
+ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+ 1. Definitions.
+
+ "License" shall mean the terms and conditions for use, reproduction,
+ and distribution as defined by Sections 1 through 9 of this document.
+
+ "Licensor" shall mean the copyright owner or entity authorized by
+ the copyright owner that is granting the License.
+
+ "Legal Entity" shall mean the union of the acting entity and all
+ other entities that control, are controlled by, or are under common
+ control with that entity. For the purposes of this definition,
+ "control" means (i) the power, direct or indirect, to cause the
+ direction or management of such entity, whether by contract or
+ otherwise, or (ii) ownership of fifty percent (50%) or more of the
+ outstanding shares, or (iii) beneficial ownership of such entity.
+
+ "You" (or "Your") shall mean an individual or Legal Entity
+ exercising permissions granted by this License.
+
+ "Source" form shall mean the preferred form for making modifications,
+ including but not limited to software source code, documentation
+ source, and configuration files.
+
+ "Object" form shall mean any form resulting from mechanical
+ transformation or translation of a Source form, including but
+ not limited to compiled object code, generated documentation,
+ and conversions to other media types.
+
+ "Work" shall mean the work of authorship, whether in Source or
+ Object form, made available under the License, as indicated by a
+ copyright notice that is included in or attached to the work
+ (an example is provided in the Appendix below).
+
+ "Derivative Works" shall mean any work, whether in Source or Object
+ form, that is based on (or derived from) the Work and for which the
+ editorial revisions, annotations, elaborations, or other modifications
+ represent, as a whole, an original work of authorship. For the purposes
+ of this License, Derivative Works shall not include works that remain
+ separable from, or merely link (or bind by name) to the interfaces of,
+ the Work and Derivative Works thereof.
+
+ "Contribution" shall mean any work of authorship, including
+ the original version of the Work and any modifications or additions
+ to that Work or Derivative Works thereof, that is intentionally
+ submitted to Licensor for inclusion in the Work by the copyright owner
+ or by an individual or Legal Entity authorized to submit on behalf of
+ the copyright owner. For the purposes of this definition, "submitted"
+ means any form of electronic, verbal, or written communication sent
+ to the Licensor or its representatives, including but not limited to
+ communication on electronic mailing lists, source code control systems,
+ and issue tracking systems that are managed by, or on behalf of, the
+ Licensor for the purpose of discussing and improving the Work, but
+ excluding communication that is conspicuously marked or otherwise
+ designated in writing by the copyright owner as "Not a Contribution."
+
+ "Contributor" shall mean Licensor and any individual or Legal Entity
+ on behalf of whom a Contribution has been received by Licensor and
+ subsequently incorporated within the Work.
+
+ 2. Grant of Copyright License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ copyright license to reproduce, prepare Derivative Works of,
+ publicly display, publicly perform, sublicense, and distribute the
+ Work and such Derivative Works in Source or Object form.
+
+ 3. Grant of Patent License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ (except as stated in this section) patent license to make, have made,
+ use, offer to sell, sell, import, and otherwise transfer the Work,
+ where such license applies only to those patent claims licensable
+ by such Contributor that are necessarily infringed by their
+ Contribution(s) alone or by combination of their Contribution(s)
+ with the Work to which such Contribution(s) was submitted. If You
+ institute patent litigation against any entity (including a
+ cross-claim or counterclaim in a lawsuit) alleging that the Work
+ or a Contribution incorporated within the Work constitutes direct
+ or contributory patent infringement, then any patent licenses
+ granted to You under this License for that Work shall terminate
+ as of the date such litigation is filed.
+
+ 4. Redistribution. You may reproduce and distribute copies of the
+ Work or Derivative Works thereof in any medium, with or without
+ modifications, and in Source or Object form, provided that You
+ meet the following conditions:
+
+ (a) You must give any other recipients of the Work or
+ Derivative Works a copy of this License; and
+
+ (b) You must cause any modified files to carry prominent notices
+ stating that You changed the files; and
+
+ (c) You must retain, in the Source form of any Derivative Works
+ that You distribute, all copyright, patent, trademark, and
+ attribution notices from the Source form of the Work,
+ excluding those notices that do not pertain to any part of
+ the Derivative Works; and
+
+ (d) If the Work includes a "NOTICE" text file as part of its
+ distribution, then any Derivative Works that You distribute must
+ include a readable copy of the attribution notices contained
+ within such NOTICE file, excluding those notices that do not
+ pertain to any part of the Derivative Works, in at least one
+ of the following places: within a NOTICE text file distributed
+ as part of the Derivative Works; within the Source form or
+ documentation, if provided along with the Derivative Works; or,
+ within a display generated by the Derivative Works, if and
+ wherever such third-party notices normally appear. The contents
+ of the NOTICE file are for informational purposes only and
+ do not modify the License. You may add Your own attribution
+ notices within Derivative Works that You distribute, alongside
+ or as an addendum to the NOTICE text from the Work, provided
+ that such additional attribution notices cannot be construed
+ as modifying the License.
+
+ You may add Your own copyright statement to Your modifications and
+ may provide additional or different license terms and conditions
+ for use, reproduction, or distribution of Your modifications, or
+ for any such Derivative Works as a whole, provided Your use,
+ reproduction, and distribution of the Work otherwise complies with
+ the conditions stated in this License.
+
+ 5. Submission of Contributions. Unless You explicitly state otherwise,
+ any Contribution intentionally submitted for inclusion in the Work
+ by You to the Licensor shall be under the terms and conditions of
+ this License, without any additional terms or conditions.
+ Notwithstanding the above, nothing herein shall supersede or modify
+ the terms of any separate license agreement you may have executed
+ with Licensor regarding such Contributions.
+
+ 6. Trademarks. This License does not grant permission to use the trade
+ names, trademarks, service marks, or product names of the Licensor,
+ except as required for reasonable and customary use in describing the
+ origin of the Work and reproducing the content of the NOTICE file.
+
+ 7. Disclaimer of Warranty. Unless required by applicable law or
+ agreed to in writing, Licensor provides the Work (and each
+ Contributor provides its Contributions) on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+ implied, including, without limitation, any warranties or conditions
+ of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+ PARTICULAR PURPOSE. You are solely responsible for determining the
+ appropriateness of using or redistributing the Work and assume any
+ risks associated with Your exercise of permissions under this License.
+
+ 8. Limitation of Liability. In no event and under no legal theory,
+ whether in tort (including negligence), contract, or otherwise,
+ unless required by applicable law (such as deliberate and grossly
+ negligent acts) or agreed to in writing, shall any Contributor be
+ liable to You for damages, including any direct, indirect, special,
+ incidental, or consequential damages of any character arising as a
+ result of this License or out of the use or inability to use the
+ Work (including but not limited to damages for loss of goodwill,
+ work stoppage, computer failure or malfunction, or any and all
+ other commercial damages or losses), even if such Contributor
+ has been advised of the possibility of such damages.
+
+ 9. Accepting Warranty or Additional Liability. While redistributing
+ the Work or Derivative Works thereof, You may choose to offer,
+ and charge a fee for, acceptance of support, warranty, indemnity,
+ or other liability obligations and/or rights consistent with this
+ License. However, in accepting such obligations, You may act only
+ on Your own behalf and on Your sole responsibility, not on behalf
+ of any other Contributor, and only if You agree to indemnify,
+ defend, and hold each Contributor harmless for any liability
+ incurred by, or claims asserted against, such Contributor by reason
+ of your accepting any such warranty or additional liability.
+
+ END OF TERMS AND CONDITIONS
+
+ APPENDIX: How to apply the Apache License to your work.
+
+ To apply the Apache License to your work, attach the following
+ boilerplate notice, with the fields enclosed by brackets "[]"
+ replaced with your own identifying information. (Don't include
+ the brackets!) The text should be enclosed in the appropriate
+ comment syntax for the file format. We also recommend that a
+ file or class name and description of purpose be included on the
+ same "printed page" as the copyright notice for easier
+ identification within third-party archives.
+
+ Copyright [yyyy] [name of copyright owner]
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
diff --git a/Utilities/cmcppdap/NOTICE b/Utilities/cmcppdap/NOTICE
new file mode 100644
index 0000000..5ad206c
--- /dev/null
+++ b/Utilities/cmcppdap/NOTICE
@@ -0,0 +1,5 @@
+'cppdap' is a C++11 library implementation of the Debug Adapter Protocol.
+Version as of 2023-01-06
+Copyright Google LLC
+
+This product includes software developed at Google.
diff --git a/Utilities/cmcppdap/include/dap/any.h b/Utilities/cmcppdap/include/dap/any.h
new file mode 100644
index 0000000..b05f03d
--- /dev/null
+++ b/Utilities/cmcppdap/include/dap/any.h
@@ -0,0 +1,211 @@
+// Copyright 2019 Google LLC
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// https://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#ifndef dap_any_h
+#define dap_any_h
+
+#include "typeinfo.h"
+
+#include <assert.h>
+#include <stdint.h>
+
+namespace dap {
+
+template <typename T>
+struct TypeOf;
+class Deserializer;
+class Serializer;
+
+// any provides a type-safe container for values of any of dap type (boolean,
+// integer, number, array, variant, any, null, dap-structs).
+class any {
+ public:
+ // constructors
+ inline any() = default;
+ inline any(const any& other) noexcept;
+ inline any(any&& other) noexcept;
+
+ template <typename T>
+ inline any(const T& val);
+
+ // destructors
+ inline ~any();
+
+ // replaces the contained value with a null.
+ inline void reset();
+
+ // assignment
+ inline any& operator=(const any& rhs);
+ inline any& operator=(any&& rhs) noexcept;
+ template <typename T>
+ inline any& operator=(const T& val);
+ inline any& operator=(const std::nullptr_t& val);
+
+ // get() returns the contained value of the type T.
+ // If the any does not contain a value of type T, then get() will assert.
+ template <typename T>
+ inline T& get() const;
+
+ // is() returns true iff the contained value is of type T.
+ template <typename T>
+ inline bool is() const;
+
+ private:
+ friend class Deserializer;
+ friend class Serializer;
+
+ static inline void* alignUp(void* val, size_t alignment);
+ inline void alloc(size_t size, size_t align);
+ inline void free();
+ inline bool isInBuffer(void* ptr) const;
+
+ void* value = nullptr;
+ const TypeInfo* type = nullptr;
+ void* heap = nullptr; // heap allocation
+ uint8_t buffer[32]; // or internal allocation
+};
+
+inline any::~any() {
+ reset();
+}
+
+template <typename T>
+inline any::any(const T& val) {
+ *this = val;
+}
+
+any::any(const any& other) noexcept : type(other.type) {
+ if (other.value != nullptr) {
+ alloc(type->size(), type->alignment());
+ type->copyConstruct(value, other.value);
+ }
+}
+
+any::any(any&& other) noexcept : type(other.type) {
+ if (other.isInBuffer(other.value)) {
+ alloc(type->size(), type->alignment());
+ type->copyConstruct(value, other.value);
+ } else {
+ value = other.value;
+ }
+ other.value = nullptr;
+ other.type = nullptr;
+}
+
+void any::reset() {
+ if (value != nullptr) {
+ type->destruct(value);
+ free();
+ }
+ value = nullptr;
+ type = nullptr;
+}
+
+any& any::operator=(const any& rhs) {
+ reset();
+ type = rhs.type;
+ if (rhs.value != nullptr) {
+ alloc(type->size(), type->alignment());
+ type->copyConstruct(value, rhs.value);
+ }
+ return *this;
+}
+
+any& any::operator=(any&& rhs) noexcept {
+ reset();
+ type = rhs.type;
+ if (rhs.isInBuffer(rhs.value)) {
+ alloc(type->size(), type->alignment());
+ type->copyConstruct(value, rhs.value);
+ } else {
+ value = rhs.value;
+ }
+ rhs.value = nullptr;
+ rhs.type = nullptr;
+ return *this;
+}
+
+template <typename T>
+any& any::operator=(const T& val) {
+ if (!is<T>()) {
+ reset();
+ type = TypeOf<T>::type();
+ alloc(type->size(), type->alignment());
+ type->copyConstruct(value, &val);
+ } else {
+#ifdef __clang_analyzer__
+ assert(value != nullptr);
+#endif
+ *reinterpret_cast<T*>(value) = val;
+ }
+ return *this;
+}
+
+any& any::operator=(const std::nullptr_t&) {
+ reset();
+ return *this;
+}
+
+template <typename T>
+T& any::get() const {
+ static_assert(!std::is_same<T, std::nullptr_t>(),
+ "Cannot get nullptr from 'any'.");
+ assert(is<T>());
+ return *reinterpret_cast<T*>(value);
+}
+
+template <typename T>
+bool any::is() const {
+ return type == TypeOf<T>::type();
+}
+
+template <>
+inline bool any::is<std::nullptr_t>() const {
+ return value == nullptr;
+}
+
+void* any::alignUp(void* val, size_t alignment) {
+ auto ptr = reinterpret_cast<uintptr_t>(val);
+ return reinterpret_cast<void*>(alignment *
+ ((ptr + alignment - 1) / alignment));
+}
+
+void any::alloc(size_t size, size_t align) {
+ assert(value == nullptr);
+ value = alignUp(buffer, align);
+ if (isInBuffer(reinterpret_cast<uint8_t*>(value) + size - 1)) {
+ return;
+ }
+ heap = new uint8_t[size + align];
+ value = alignUp(heap, align);
+}
+
+void any::free() {
+ assert(value != nullptr);
+ if (heap != nullptr) {
+ delete[] reinterpret_cast<uint8_t*>(heap);
+ heap = nullptr;
+ }
+ value = nullptr;
+}
+
+bool any::isInBuffer(void* ptr) const {
+ auto addr = reinterpret_cast<uintptr_t>(ptr);
+ return addr >= reinterpret_cast<uintptr_t>(buffer) &&
+ addr < reinterpret_cast<uintptr_t>(buffer + sizeof(buffer));
+}
+
+} // namespace dap
+
+#endif // dap_any_h
diff --git a/Utilities/cmcppdap/include/dap/dap.h b/Utilities/cmcppdap/include/dap/dap.h
new file mode 100644
index 0000000..587e80c
--- /dev/null
+++ b/Utilities/cmcppdap/include/dap/dap.h
@@ -0,0 +1,35 @@
+// Copyright 2020 Google LLC
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// https://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#ifndef dap_dap_h
+#define dap_dap_h
+
+namespace dap {
+
+// Explicit library initialization and termination functions.
+//
+// cppdap automatically initializes and terminates its internal state using lazy
+// static initialization, and so will usually work fine without explicit calls
+// to these functions.
+// However, if you use cppdap types in global state, you may need to call these
+// functions to ensure that cppdap is not uninitialized before the last usage.
+//
+// Each call to initialize() must have a corresponding call to terminate().
+// It is undefined behaviour to call initialize() after terminate().
+void initialize();
+void terminate();
+
+} // namespace dap
+
+#endif // dap_dap_h
diff --git a/Utilities/cmcppdap/include/dap/future.h b/Utilities/cmcppdap/include/dap/future.h
new file mode 100644
index 0000000..af103c3
--- /dev/null
+++ b/Utilities/cmcppdap/include/dap/future.h
@@ -0,0 +1,179 @@
+// Copyright 2019 Google LLC
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// https://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#ifndef dap_future_h
+#define dap_future_h
+
+#include <condition_variable>
+#include <memory>
+#include <mutex>
+
+namespace dap {
+
+// internal functionality
+namespace detail {
+template <typename T>
+struct promise_state {
+ T val;
+ std::mutex mutex;
+ std::condition_variable cv;
+ bool hasVal = false;
+};
+} // namespace detail
+
+// forward declaration
+template <typename T>
+class promise;
+
+// future_status is the enumeration returned by future::wait_for and
+// future::wait_until.
+enum class future_status {
+ ready,
+ timeout,
+};
+
+// future is a minimal reimplementation of std::future, that does not suffer
+// from TSAN false positives. See:
+// https://gcc.gnu.org/bugzilla//show_bug.cgi?id=69204
+template <typename T>
+class future {
+ public:
+ using State = detail::promise_state<T>;
+
+ // constructors
+ inline future() = default;
+ inline future(future&&) = default;
+
+ // valid() returns true if the future has an internal state.
+ bool valid() const;
+
+ // get() blocks until the future has a valid result, and returns it.
+ // The future must have a valid internal state to call this method.
+ inline T get();
+
+ // wait() blocks until the future has a valid result.
+ // The future must have a valid internal state to call this method.
+ void wait() const;
+
+ // wait_for() blocks until the future has a valid result, or the timeout is
+ // reached.
+ // The future must have a valid internal state to call this method.
+ template <class Rep, class Period>
+ future_status wait_for(
+ const std::chrono::duration<Rep, Period>& timeout) const;
+
+ // wait_until() blocks until the future has a valid result, or the timeout is
+ // reached.
+ // The future must have a valid internal state to call this method.
+ template <class Clock, class Duration>
+ future_status wait_until(
+ const std::chrono::time_point<Clock, Duration>& timeout) const;
+
+ private:
+ friend promise<T>;
+ future(const future&) = delete;
+ inline future(const std::shared_ptr<State>& state);
+
+ std::shared_ptr<State> state = std::make_shared<State>();
+};
+
+template <typename T>
+future<T>::future(const std::shared_ptr<State>& s) : state(s) {}
+
+template <typename T>
+bool future<T>::valid() const {
+ return static_cast<bool>(state);
+}
+
+template <typename T>
+T future<T>::get() {
+ std::unique_lock<std::mutex> lock(state->mutex);
+ state->cv.wait(lock, [&] { return state->hasVal; });
+ return state->val;
+}
+
+template <typename T>
+void future<T>::wait() const {
+ std::unique_lock<std::mutex> lock(state->mutex);
+ state->cv.wait(lock, [&] { return state->hasVal; });
+}
+
+template <typename T>
+template <class Rep, class Period>
+future_status future<T>::wait_for(
+ const std::chrono::duration<Rep, Period>& timeout) const {
+ std::unique_lock<std::mutex> lock(state->mutex);
+ return state->cv.wait_for(lock, timeout, [&] { return state->hasVal; })
+ ? future_status::ready
+ : future_status::timeout;
+}
+
+template <typename T>
+template <class Clock, class Duration>
+future_status future<T>::wait_until(
+ const std::chrono::time_point<Clock, Duration>& timeout) const {
+ std::unique_lock<std::mutex> lock(state->mutex);
+ return state->cv.wait_until(lock, timeout, [&] { return state->hasVal; })
+ ? future_status::ready
+ : future_status::timeout;
+}
+
+// promise is a minimal reimplementation of std::promise, that does not suffer
+// from TSAN false positives. See:
+// https://gcc.gnu.org/bugzilla//show_bug.cgi?id=69204
+template <typename T>
+class promise {
+ public:
+ // constructors
+ inline promise() = default;
+ inline promise(promise&& other) = default;
+ inline promise(const promise& other) = default;
+
+ // set_value() stores value to the shared state.
+ // set_value() must only be called once.
+ inline void set_value(const T& value) const;
+ inline void set_value(T&& value) const;
+
+ // get_future() returns a future sharing this promise's state.
+ future<T> get_future();
+
+ private:
+ using State = detail::promise_state<T>;
+ std::shared_ptr<State> state = std::make_shared<State>();
+};
+
+template <typename T>
+future<T> promise<T>::get_future() {
+ return future<T>(state);
+}
+
+template <typename T>
+void promise<T>::set_value(const T& value) const {
+ std::unique_lock<std::mutex> lock(state->mutex);
+ state->val = value;
+ state->hasVal = true;
+ state->cv.notify_all();
+}
+
+template <typename T>
+void promise<T>::set_value(T&& value) const {
+ std::unique_lock<std::mutex> lock(state->mutex);
+ state->val = std::move(value);
+ state->hasVal = true;
+ state->cv.notify_all();
+}
+
+} // namespace dap
+
+#endif // dap_future_h
diff --git a/Utilities/cmcppdap/include/dap/io.h b/Utilities/cmcppdap/include/dap/io.h
new file mode 100644
index 0000000..61681cc
--- /dev/null
+++ b/Utilities/cmcppdap/include/dap/io.h
@@ -0,0 +1,97 @@
+// Copyright 2019 Google LLC
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// https://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#ifndef dap_io_h
+#define dap_io_h
+
+#include <stddef.h> // size_t
+#include <stdio.h> // FILE
+#include <memory> // std::unique_ptr
+#include <utility> // std::pair
+
+namespace dap {
+
+class Closable {
+ public:
+ virtual ~Closable() = default;
+
+ // isOpen() returns true if the stream has not been closed.
+ virtual bool isOpen() = 0;
+
+ // close() closes the stream.
+ virtual void close() = 0;
+};
+
+// Reader is an interface for reading from a byte stream.
+class Reader : virtual public Closable {
+ public:
+ // read() attempts to read at most n bytes into buffer, returning the number
+ // of bytes read.
+ // read() will block until the stream is closed or at least one byte is read.
+ virtual size_t read(void* buffer, size_t n) = 0;
+};
+
+// Writer is an interface for writing to a byte stream.
+class Writer : virtual public Closable {
+ public:
+ // write() writes n bytes from buffer into the stream.
+ // Returns true on success, or false if there was an error or the stream was
+ // closed.
+ virtual bool write(const void* buffer, size_t n) = 0;
+};
+
+// ReaderWriter is an interface that combines the Reader and Writer interfaces.
+class ReaderWriter : public Reader, public Writer {
+ public:
+ // create() returns a ReaderWriter that delegates the interface methods on to
+ // the provided Reader and Writer.
+ // isOpen() returns true if the Reader and Writer both return true for
+ // isOpen().
+ // close() closes both the Reader and Writer.
+ static std::shared_ptr<ReaderWriter> create(const std::shared_ptr<Reader>&,
+ const std::shared_ptr<Writer>&);
+};
+
+// pipe() returns a ReaderWriter where the Writer streams to the Reader.
+// Writes are internally buffered.
+// Calling close() on either the Reader or Writer will close both ends of the
+// stream.
+std::shared_ptr<ReaderWriter> pipe();
+
+// file() wraps file with a ReaderWriter.
+// If closable is false, then a call to ReaderWriter::close() will not close the
+// underlying file.
+std::shared_ptr<ReaderWriter> file(FILE* file, bool closable = true);
+
+// file() opens (or creates) the file with the given path.
+std::shared_ptr<ReaderWriter> file(const char* path);
+
+// spy() returns a Reader that copies all reads from the Reader r to the Writer
+// s, using the given optional prefix.
+std::shared_ptr<Reader> spy(const std::shared_ptr<Reader>& r,
+ const std::shared_ptr<Writer>& s,
+ const char* prefix = "\n->");
+
+// spy() returns a Writer that copies all writes to the Writer w to the Writer
+// s, using the given optional prefix.
+std::shared_ptr<Writer> spy(const std::shared_ptr<Writer>& w,
+ const std::shared_ptr<Writer>& s,
+ const char* prefix = "\n<-");
+
+// writef writes the printf style string to the writer w.
+bool writef(const std::shared_ptr<Writer>& w, const char* msg, ...);
+
+} // namespace dap
+
+#endif // dap_io_h
diff --git a/Utilities/cmcppdap/include/dap/network.h b/Utilities/cmcppdap/include/dap/network.h
new file mode 100644
index 0000000..9d14f6b
--- /dev/null
+++ b/Utilities/cmcppdap/include/dap/network.h
@@ -0,0 +1,62 @@
+// Copyright 2019 Google LLC
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// https://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#ifndef dap_network_h
+#define dap_network_h
+
+#include <functional>
+#include <memory>
+
+namespace dap {
+class ReaderWriter;
+
+namespace net {
+
+// connect() connects to the given TCP address and port.
+// If timeoutMillis is non-zero and no connection was made before timeoutMillis
+// milliseconds, then nullptr is returned.
+std::shared_ptr<ReaderWriter> connect(const char* addr,
+ int port,
+ uint32_t timeoutMillis = 0);
+
+// Server implements a basic TCP server.
+class Server {
+ // ignoreErrors() matches the OnError signature, and does nothing.
+ static inline void ignoreErrors(const char*) {}
+
+ public:
+ using OnError = std::function<void(const char*)>;
+ using OnConnect = std::function<void(const std::shared_ptr<ReaderWriter>&)>;
+
+ virtual ~Server() = default;
+
+ // create() constructs and returns a new Server.
+ static std::unique_ptr<Server> create();
+
+ // start() begins listening for connections on the given port.
+ // callback will be called for each connection.
+ // onError will be called for any connection errors.
+ virtual bool start(int port,
+ const OnConnect& callback,
+ const OnError& onError = ignoreErrors) = 0;
+
+ // stop() stops listening for connections.
+ // stop() is implicitly called on destruction.
+ virtual void stop() = 0;
+};
+
+} // namespace net
+} // namespace dap
+
+#endif // dap_network_h
diff --git a/Utilities/cmcppdap/include/dap/optional.h b/Utilities/cmcppdap/include/dap/optional.h
new file mode 100644
index 0000000..9a3d216
--- /dev/null
+++ b/Utilities/cmcppdap/include/dap/optional.h
@@ -0,0 +1,263 @@
+// Copyright 2019 Google LLC
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// https://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#ifndef dap_optional_h
+#define dap_optional_h
+
+#include <assert.h>
+#include <type_traits>
+#include <utility> // std::move, std::forward
+
+namespace dap {
+
+// optional holds an 'optional' contained value.
+// This is similar to C++17's std::optional.
+template <typename T>
+class optional {
+ template <typename U>
+ using IsConvertibleToT =
+ typename std::enable_if<std::is_convertible<U, T>::value>::type;
+
+ public:
+ using value_type = T;
+
+ // constructors
+ inline optional() = default;
+ inline optional(const optional& other);
+ inline optional(optional&& other);
+ template <typename U>
+ inline optional(const optional<U>& other);
+ template <typename U>
+ inline optional(optional<U>&& other);
+ template <typename U = value_type, typename = IsConvertibleToT<U>>
+ inline optional(U&& value);
+
+ // value() returns the contained value.
+ // If the optional does not contain a value, then value() will assert.
+ inline T& value();
+ inline const T& value() const;
+
+ // value() returns the contained value, or defaultValue if the optional does
+ // not contain a value.
+ inline const T& value(const T& defaultValue) const;
+
+ // operator bool() returns true if the optional contains a value.
+ inline explicit operator bool() const noexcept;
+
+ // has_value() returns true if the optional contains a value.
+ inline bool has_value() const;
+
+ // assignment
+ inline optional& operator=(const optional& other);
+ inline optional& operator=(optional&& other) noexcept;
+ template <typename U = T, typename = IsConvertibleToT<U>>
+ inline optional& operator=(U&& value);
+ template <typename U>
+ inline optional& operator=(const optional<U>& other);
+ template <typename U>
+ inline optional& operator=(optional<U>&& other);
+
+ // value access
+ inline const T* operator->() const;
+ inline T* operator->();
+ inline const T& operator*() const;
+ inline T& operator*();
+
+ private:
+ T val{};
+ bool set = false;
+};
+
+template <typename T>
+optional<T>::optional(const optional& other) : val(other.val), set(other.set) {}
+
+template <typename T>
+optional<T>::optional(optional&& other)
+ : val(std::move(other.val)), set(other.set) {}
+
+template <typename T>
+template <typename U>
+optional<T>::optional(const optional<U>& other) : set(other.has_value()) {
+ if (set) {
+ val = static_cast<T>(other.value());
+ }
+}
+
+template <typename T>
+template <typename U>
+optional<T>::optional(optional<U>&& other) : set(other.has_value()) {
+ if (set) {
+ val = static_cast<T>(std::move(other.value()));
+ }
+}
+
+template <typename T>
+template <typename U /*= T*/, typename>
+optional<T>::optional(U&& value) : val(std::forward<U>(value)), set(true) {}
+
+template <typename T>
+T& optional<T>::value() {
+ assert(set);
+ return val;
+}
+
+template <typename T>
+const T& optional<T>::value() const {
+ assert(set);
+ return val;
+}
+
+template <typename T>
+const T& optional<T>::value(const T& defaultValue) const {
+ if (!has_value()) {
+ return defaultValue;
+ }
+ return val;
+}
+
+template <typename T>
+optional<T>::operator bool() const noexcept {
+ return set;
+}
+
+template <typename T>
+bool optional<T>::has_value() const {
+ return set;
+}
+
+template <typename T>
+optional<T>& optional<T>::operator=(const optional& other) {
+ val = other.val;
+ set = other.set;
+ return *this;
+}
+
+template <typename T>
+optional<T>& optional<T>::operator=(optional&& other) noexcept {
+ val = std::move(other.val);
+ set = other.set;
+ return *this;
+}
+
+template <typename T>
+template <typename U /* = T */, typename>
+optional<T>& optional<T>::operator=(U&& value) {
+ val = std::forward<U>(value);
+ set = true;
+ return *this;
+}
+
+template <typename T>
+template <typename U>
+optional<T>& optional<T>::operator=(const optional<U>& other) {
+ val = other.val;
+ set = other.set;
+ return *this;
+}
+
+template <typename T>
+template <typename U>
+optional<T>& optional<T>::operator=(optional<U>&& other) {
+ val = std::move(other.val);
+ set = other.set;
+ return *this;
+}
+
+template <typename T>
+const T* optional<T>::operator->() const {
+ assert(set);
+ return &val;
+}
+
+template <typename T>
+T* optional<T>::operator->() {
+ assert(set);
+ return &val;
+}
+
+template <typename T>
+const T& optional<T>::operator*() const {
+ assert(set);
+ return val;
+}
+
+template <typename T>
+T& optional<T>::operator*() {
+ assert(set);
+ return val;
+}
+
+template <class T, class U>
+inline bool operator==(const optional<T>& lhs, const optional<U>& rhs) {
+ if (!lhs.has_value() && !rhs.has_value()) {
+ return true;
+ }
+ if (!lhs.has_value() || !rhs.has_value()) {
+ return false;
+ }
+ return lhs.value() == rhs.value();
+}
+
+template <class T, class U>
+inline bool operator!=(const optional<T>& lhs, const optional<U>& rhs) {
+ return !(lhs == rhs);
+}
+
+template <class T, class U>
+inline bool operator<(const optional<T>& lhs, const optional<U>& rhs) {
+ if (!rhs.has_value()) {
+ return false;
+ }
+ if (!lhs.has_value()) {
+ return true;
+ }
+ return lhs.value() < rhs.value();
+}
+
+template <class T, class U>
+inline bool operator<=(const optional<T>& lhs, const optional<U>& rhs) {
+ if (!lhs.has_value()) {
+ return true;
+ }
+ if (!rhs.has_value()) {
+ return false;
+ }
+ return lhs.value() <= rhs.value();
+}
+
+template <class T, class U>
+inline bool operator>(const optional<T>& lhs, const optional<U>& rhs) {
+ if (!lhs.has_value()) {
+ return false;
+ }
+ if (!rhs.has_value()) {
+ return true;
+ }
+ return lhs.value() > rhs.value();
+}
+
+template <class T, class U>
+inline bool operator>=(const optional<T>& lhs, const optional<U>& rhs) {
+ if (!rhs.has_value()) {
+ return true;
+ }
+ if (!lhs.has_value()) {
+ return false;
+ }
+ return lhs.value() >= rhs.value();
+}
+
+} // namespace dap
+
+#endif // dap_optional_h
diff --git a/Utilities/cmcppdap/include/dap/protocol.h b/Utilities/cmcppdap/include/dap/protocol.h
new file mode 100644
index 0000000..e4c479e
--- /dev/null
+++ b/Utilities/cmcppdap/include/dap/protocol.h
@@ -0,0 +1,2679 @@
+// Copyright 2019 Google LLC
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// https://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+// Generated with protocol_gen.go -- do not edit this file.
+// go run scripts/protocol_gen/protocol_gen.go
+//
+// DAP version 1.59.0
+
+#ifndef dap_protocol_h
+#define dap_protocol_h
+
+#include "optional.h"
+#include "typeinfo.h"
+#include "typeof.h"
+#include "variant.h"
+
+#include <string>
+#include <type_traits>
+#include <vector>
+
+namespace dap {
+
+struct Request {};
+struct Response {};
+struct Event {};
+
+// Response to `attach` request. This is just an acknowledgement, so no body
+// field is required.
+struct AttachResponse : public Response {};
+
+DAP_DECLARE_STRUCT_TYPEINFO(AttachResponse);
+
+// The `attach` request is sent from the client to the debug adapter to attach
+// to a debuggee that is already running. Since attaching is debugger/runtime
+// specific, the arguments for this request are not part of this specification.
+struct AttachRequest : public Request {
+ using Response = AttachResponse;
+ // Arbitrary data from the previous, restarted session.
+ // The data is sent as the `restart` attribute of the `terminated` event.
+ // The client should leave the data intact.
+ optional<variant<array<any>, boolean, integer, null, number, object, string>>
+ restart;
+};
+
+DAP_DECLARE_STRUCT_TYPEINFO(AttachRequest);
+
+// Names of checksum algorithms that may be supported by a debug adapter.
+//
+// Must be one of the following enumeration values:
+// 'MD5', 'SHA1', 'SHA256', 'timestamp'
+using ChecksumAlgorithm = string;
+
+// The checksum of an item calculated by the specified algorithm.
+struct Checksum {
+ // The algorithm used to calculate this checksum.
+ ChecksumAlgorithm algorithm = "MD5";
+ // Value of the checksum, encoded as a hexadecimal value.
+ string checksum;
+};
+
+DAP_DECLARE_STRUCT_TYPEINFO(Checksum);
+
+// A `Source` is a descriptor for source code.
+// It is returned from the debug adapter as part of a `StackFrame` and it is
+// used by clients when specifying breakpoints.
+struct Source {
+ // Additional data that a debug adapter might want to loop through the client.
+ // The client should leave the data intact and persist it across sessions. The
+ // client should not interpret the data.
+ optional<variant<array<any>, boolean, integer, null, number, object, string>>
+ adapterData;
+ // The checksums associated with this file.
+ optional<array<Checksum>> checksums;
+ // The short name of the source. Every source returned from the debug adapter
+ // has a name. When sending a source to the debug adapter this name is
+ // optional.
+ optional<string> name;
+ // The origin of this source. For example, 'internal module', 'inlined content
+ // from source map', etc.
+ optional<string> origin;
+ // The path of the source to be shown in the UI.
+ // It is only used to locate and load the content of the source if no
+ // `sourceReference` is specified (or its value is 0).
+ optional<string> path;
+ // A hint for how to present the source in the UI.
+ // A value of `deemphasize` can be used to indicate that the source is not
+ // available or that it is skipped on stepping.
+ //
+ // Must be one of the following enumeration values:
+ // 'normal', 'emphasize', 'deemphasize'
+ optional<string> presentationHint;
+ // If the value > 0 the contents of the source must be retrieved through the
+ // `source` request (even if a path is specified). Since a `sourceReference`
+ // is only valid for a session, it can not be used to persist a source. The
+ // value should be less than or equal to 2147483647 (2^31-1).
+ optional<integer> sourceReference;
+ // A list of sources that are related to this source. These may be the source
+ // that generated this source.
+ optional<array<Source>> sources;
+};
+
+DAP_DECLARE_STRUCT_TYPEINFO(Source);
+
+// Information about a breakpoint created in `setBreakpoints`,
+// `setFunctionBreakpoints`, `setInstructionBreakpoints`, or
+// `setDataBreakpoints` requests.
+struct Breakpoint {
+ // Start position of the source range covered by the breakpoint. It is
+ // measured in UTF-16 code units and the client capability `columnsStartAt1`
+ // determines whether it is 0- or 1-based.
+ optional<integer> column;
+ // End position of the source range covered by the breakpoint. It is measured
+ // in UTF-16 code units and the client capability `columnsStartAt1` determines
+ // whether it is 0- or 1-based. If no end line is given, then the end column
+ // is assumed to be in the start line.
+ optional<integer> endColumn;
+ // The end line of the actual range covered by the breakpoint.
+ optional<integer> endLine;
+ // The identifier for the breakpoint. It is needed if breakpoint events are
+ // used to update or remove breakpoints.
+ optional<integer> id;
+ // A memory reference to where the breakpoint is set.
+ optional<string> instructionReference;
+ // The start line of the actual range covered by the breakpoint.
+ optional<integer> line;
+ // A message about the state of the breakpoint.
+ // This is shown to the user and can be used to explain why a breakpoint could
+ // not be verified.
+ optional<string> message;
+ // The offset from the instruction reference.
+ // This can be negative.
+ optional<integer> offset;
+ // The source where the breakpoint is located.
+ optional<Source> source;
+ // If true, the breakpoint could be set (but not necessarily at the desired
+ // location).
+ boolean verified;
+};
+
+DAP_DECLARE_STRUCT_TYPEINFO(Breakpoint);
+
+// The event indicates that some information about a breakpoint has changed.
+struct BreakpointEvent : public Event {
+ // The `id` attribute is used to find the target breakpoint, the other
+ // attributes are used as the new values.
+ Breakpoint breakpoint;
+ // The reason for the event.
+ //
+ // May be one of the following enumeration values:
+ // 'changed', 'new', 'removed'
+ string reason;
+};
+
+DAP_DECLARE_STRUCT_TYPEINFO(BreakpointEvent);
+
+// Properties of a breakpoint location returned from the `breakpointLocations`
+// request.
+struct BreakpointLocation {
+ // The start position of a breakpoint location. Position is measured in UTF-16
+ // code units and the client capability `columnsStartAt1` determines whether
+ // it is 0- or 1-based.
+ optional<integer> column;
+ // The end position of a breakpoint location (if the location covers a range).
+ // Position is measured in UTF-16 code units and the client capability
+ // `columnsStartAt1` determines whether it is 0- or 1-based.
+ optional<integer> endColumn;
+ // The end line of breakpoint location if the location covers a range.
+ optional<integer> endLine;
+ // Start line of breakpoint location.
+ integer line;
+};
+
+DAP_DECLARE_STRUCT_TYPEINFO(BreakpointLocation);
+
+// Response to `breakpointLocations` request.
+// Contains possible locations for source breakpoints.
+struct BreakpointLocationsResponse : public Response {
+ // Sorted set of possible breakpoint locations.
+ array<BreakpointLocation> breakpoints;
+};
+
+DAP_DECLARE_STRUCT_TYPEINFO(BreakpointLocationsResponse);
+
+// The `breakpointLocations` request returns all possible locations for source
+// breakpoints in a given range. Clients should only call this request if the
+// corresponding capability `supportsBreakpointLocationsRequest` is true.
+struct BreakpointLocationsRequest : public Request {
+ using Response = BreakpointLocationsResponse;
+ // Start position within `line` to search possible breakpoint locations in. It
+ // is measured in UTF-16 code units and the client capability
+ // `columnsStartAt1` determines whether it is 0- or 1-based. If no column is
+ // given, the first position in the start line is assumed.
+ optional<integer> column;
+ // End position within `endLine` to search possible breakpoint locations in.
+ // It is measured in UTF-16 code units and the client capability
+ // `columnsStartAt1` determines whether it is 0- or 1-based. If no end column
+ // is given, the last position in the end line is assumed.
+ optional<integer> endColumn;
+ // End line of range to search possible breakpoint locations in. If no end
+ // line is given, then the end line is assumed to be the start line.
+ optional<integer> endLine;
+ // Start line of range to search possible breakpoint locations in. If only the
+ // line is specified, the request returns all possible locations in that line.
+ integer line;
+ // The source location of the breakpoints; either `source.path` or
+ // `source.reference` must be specified.
+ Source source;
+};
+
+DAP_DECLARE_STRUCT_TYPEINFO(BreakpointLocationsRequest);
+
+// Response to `cancel` request. This is just an acknowledgement, so no body
+// field is required.
+struct CancelResponse : public Response {};
+
+DAP_DECLARE_STRUCT_TYPEINFO(CancelResponse);
+
+// The `cancel` request is used by the client in two situations:
+// - to indicate that it is no longer interested in the result produced by a
+// specific request issued earlier
+// - to cancel a progress sequence. Clients should only call this request if the
+// corresponding capability `supportsCancelRequest` is true. This request has a
+// hint characteristic: a debug adapter can only be expected to make a 'best
+// effort' in honoring this request but there are no guarantees. The `cancel`
+// request may return an error if it could not cancel an operation but a client
+// should refrain from presenting this error to end users. The request that got
+// cancelled still needs to send a response back. This can either be a normal
+// result (`success` attribute true) or an error response (`success` attribute
+// false and the `message` set to `cancelled`). Returning partial results from a
+// cancelled request is possible but please note that a client has no generic
+// way for detecting that a response is partial or not. The progress that got
+// cancelled still needs to send a `progressEnd` event back.
+// A client should not assume that progress just got cancelled after sending
+// the `cancel` request.
+struct CancelRequest : public Request {
+ using Response = CancelResponse;
+ // The ID (attribute `progressId`) of the progress to cancel. If missing no
+ // progress is cancelled. Both a `requestId` and a `progressId` can be
+ // specified in one request.
+ optional<string> progressId;
+ // The ID (attribute `seq`) of the request to cancel. If missing no request is
+ // cancelled. Both a `requestId` and a `progressId` can be specified in one
+ // request.
+ optional<integer> requestId;
+};
+
+DAP_DECLARE_STRUCT_TYPEINFO(CancelRequest);
+
+// A `ColumnDescriptor` specifies what module attribute to show in a column of
+// the modules view, how to format it, and what the column's label should be. It
+// is only used if the underlying UI actually supports this level of
+// customization.
+struct ColumnDescriptor {
+ // Name of the attribute rendered in this column.
+ string attributeName;
+ // Format to use for the rendered values in this column. TBD how the format
+ // strings looks like.
+ optional<string> format;
+ // Header UI label of column.
+ string label;
+ // Datatype of values in this column. Defaults to `string` if not specified.
+ //
+ // Must be one of the following enumeration values:
+ // 'string', 'number', 'boolean', 'unixTimestampUTC'
+ optional<string> type;
+ // Width of this column in characters (hint only).
+ optional<integer> width;
+};
+
+DAP_DECLARE_STRUCT_TYPEINFO(ColumnDescriptor);
+
+// An `ExceptionBreakpointsFilter` is shown in the UI as an filter option for
+// configuring how exceptions are dealt with.
+struct ExceptionBreakpointsFilter {
+ // A help text providing information about the condition. This string is shown
+ // as the placeholder text for a text box and can be translated.
+ optional<string> conditionDescription;
+ // Initial value of the filter option. If not specified a value false is
+ // assumed.
+ optional<boolean> def;
+ // A help text providing additional information about the exception filter.
+ // This string is typically shown as a hover and can be translated.
+ optional<string> description;
+ // The internal ID of the filter option. This value is passed to the
+ // `setExceptionBreakpoints` request.
+ string filter;
+ // The name of the filter option. This is shown in the UI.
+ string label;
+ // Controls whether a condition can be specified for this filter option. If
+ // false or missing, a condition can not be set.
+ optional<boolean> supportsCondition;
+};
+
+DAP_DECLARE_STRUCT_TYPEINFO(ExceptionBreakpointsFilter);
+
+// Information about the capabilities of a debug adapter.
+struct Capabilities {
+ // The set of additional module information exposed by the debug adapter.
+ optional<array<ColumnDescriptor>> additionalModuleColumns;
+ // The set of characters that should trigger completion in a REPL. If not
+ // specified, the UI should assume the `.` character.
+ optional<array<string>> completionTriggerCharacters;
+ // Available exception filter options for the `setExceptionBreakpoints`
+ // request.
+ optional<array<ExceptionBreakpointsFilter>> exceptionBreakpointFilters;
+ // The debug adapter supports the `suspendDebuggee` attribute on the
+ // `disconnect` request.
+ optional<boolean> supportSuspendDebuggee;
+ // The debug adapter supports the `terminateDebuggee` attribute on the
+ // `disconnect` request.
+ optional<boolean> supportTerminateDebuggee;
+ // Checksum algorithms supported by the debug adapter.
+ optional<array<ChecksumAlgorithm>> supportedChecksumAlgorithms;
+ // The debug adapter supports the `breakpointLocations` request.
+ optional<boolean> supportsBreakpointLocationsRequest;
+ // The debug adapter supports the `cancel` request.
+ optional<boolean> supportsCancelRequest;
+ // The debug adapter supports the `clipboard` context value in the `evaluate`
+ // request.
+ optional<boolean> supportsClipboardContext;
+ // The debug adapter supports the `completions` request.
+ optional<boolean> supportsCompletionsRequest;
+ // The debug adapter supports conditional breakpoints.
+ optional<boolean> supportsConditionalBreakpoints;
+ // The debug adapter supports the `configurationDone` request.
+ optional<boolean> supportsConfigurationDoneRequest;
+ // The debug adapter supports data breakpoints.
+ optional<boolean> supportsDataBreakpoints;
+ // The debug adapter supports the delayed loading of parts of the stack, which
+ // requires that both the `startFrame` and `levels` arguments and the
+ // `totalFrames` result of the `stackTrace` request are supported.
+ optional<boolean> supportsDelayedStackTraceLoading;
+ // The debug adapter supports the `disassemble` request.
+ optional<boolean> supportsDisassembleRequest;
+ // The debug adapter supports a (side effect free) `evaluate` request for data
+ // hovers.
+ optional<boolean> supportsEvaluateForHovers;
+ // The debug adapter supports `filterOptions` as an argument on the
+ // `setExceptionBreakpoints` request.
+ optional<boolean> supportsExceptionFilterOptions;
+ // The debug adapter supports the `exceptionInfo` request.
+ optional<boolean> supportsExceptionInfoRequest;
+ // The debug adapter supports `exceptionOptions` on the
+ // `setExceptionBreakpoints` request.
+ optional<boolean> supportsExceptionOptions;
+ // The debug adapter supports function breakpoints.
+ optional<boolean> supportsFunctionBreakpoints;
+ // The debug adapter supports the `gotoTargets` request.
+ optional<boolean> supportsGotoTargetsRequest;
+ // The debug adapter supports breakpoints that break execution after a
+ // specified number of hits.
+ optional<boolean> supportsHitConditionalBreakpoints;
+ // The debug adapter supports adding breakpoints based on instruction
+ // references.
+ optional<boolean> supportsInstructionBreakpoints;
+ // The debug adapter supports the `loadedSources` request.
+ optional<boolean> supportsLoadedSourcesRequest;
+ // The debug adapter supports log points by interpreting the `logMessage`
+ // attribute of the `SourceBreakpoint`.
+ optional<boolean> supportsLogPoints;
+ // The debug adapter supports the `modules` request.
+ optional<boolean> supportsModulesRequest;
+ // The debug adapter supports the `readMemory` request.
+ optional<boolean> supportsReadMemoryRequest;
+ // The debug adapter supports restarting a frame.
+ optional<boolean> supportsRestartFrame;
+ // The debug adapter supports the `restart` request. In this case a client
+ // should not implement `restart` by terminating and relaunching the adapter
+ // but by calling the `restart` request.
+ optional<boolean> supportsRestartRequest;
+ // The debug adapter supports the `setExpression` request.
+ optional<boolean> supportsSetExpression;
+ // The debug adapter supports setting a variable to a value.
+ optional<boolean> supportsSetVariable;
+ // The debug adapter supports the `singleThread` property on the execution
+ // requests (`continue`, `next`, `stepIn`, `stepOut`, `reverseContinue`,
+ // `stepBack`).
+ optional<boolean> supportsSingleThreadExecutionRequests;
+ // The debug adapter supports stepping back via the `stepBack` and
+ // `reverseContinue` requests.
+ optional<boolean> supportsStepBack;
+ // The debug adapter supports the `stepInTargets` request.
+ optional<boolean> supportsStepInTargetsRequest;
+ // The debug adapter supports stepping granularities (argument `granularity`)
+ // for the stepping requests.
+ optional<boolean> supportsSteppingGranularity;
+ // The debug adapter supports the `terminate` request.
+ optional<boolean> supportsTerminateRequest;
+ // The debug adapter supports the `terminateThreads` request.
+ optional<boolean> supportsTerminateThreadsRequest;
+ // The debug adapter supports a `format` attribute on the `stackTrace`,
+ // `variables`, and `evaluate` requests.
+ optional<boolean> supportsValueFormattingOptions;
+ // The debug adapter supports the `writeMemory` request.
+ optional<boolean> supportsWriteMemoryRequest;
+};
+
+DAP_DECLARE_STRUCT_TYPEINFO(Capabilities);
+
+// The event indicates that one or more capabilities have changed.
+// Since the capabilities are dependent on the client and its UI, it might not
+// be possible to change that at random times (or too late). Consequently this
+// event has a hint characteristic: a client can only be expected to make a
+// 'best effort' in honoring individual capabilities but there are no
+// guarantees. Only changed capabilities need to be included, all other
+// capabilities keep their values.
+struct CapabilitiesEvent : public Event {
+ // The set of updated capabilities.
+ Capabilities capabilities;
+};
+
+DAP_DECLARE_STRUCT_TYPEINFO(CapabilitiesEvent);
+
+// Some predefined types for the CompletionItem. Please note that not all
+// clients have specific icons for all of them.
+//
+// Must be one of the following enumeration values:
+// 'method', 'function', 'constructor', 'field', 'variable', 'class',
+// 'interface', 'module', 'property', 'unit', 'value', 'enum', 'keyword',
+// 'snippet', 'text', 'color', 'file', 'reference', 'customcolor'
+using CompletionItemType = string;
+
+// `CompletionItems` are the suggestions returned from the `completions`
+// request.
+struct CompletionItem {
+ // A human-readable string with additional information about this item, like
+ // type or symbol information.
+ optional<string> detail;
+ // The label of this completion item. By default this is also the text that is
+ // inserted when selecting this completion.
+ string label;
+ // Length determines how many characters are overwritten by the completion
+ // text and it is measured in UTF-16 code units. If missing the value 0 is
+ // assumed which results in the completion text being inserted.
+ optional<integer> length;
+ // Determines the length of the new selection after the text has been inserted
+ // (or replaced) and it is measured in UTF-16 code units. The selection can
+ // not extend beyond the bounds of the completion text. If omitted the length
+ // is assumed to be 0.
+ optional<integer> selectionLength;
+ // Determines the start of the new selection after the text has been inserted
+ // (or replaced). `selectionStart` is measured in UTF-16 code units and must
+ // be in the range 0 and length of the completion text. If omitted the
+ // selection starts at the end of the completion text.
+ optional<integer> selectionStart;
+ // A string that should be used when comparing this item with other items. If
+ // not returned or an empty string, the `label` is used instead.
+ optional<string> sortText;
+ // Start position (within the `text` attribute of the `completions` request)
+ // where the completion text is added. The position is measured in UTF-16 code
+ // units and the client capability `columnsStartAt1` determines whether it is
+ // 0- or 1-based. If the start position is omitted the text is added at the
+ // location specified by the `column` attribute of the `completions` request.
+ optional<integer> start;
+ // If text is returned and not an empty string, then it is inserted instead of
+ // the label.
+ optional<string> text;
+ // The item's type. Typically the client uses this information to render the
+ // item in the UI with an icon.
+ optional<CompletionItemType> type;
+};
+
+DAP_DECLARE_STRUCT_TYPEINFO(CompletionItem);
+
+// Response to `completions` request.
+struct CompletionsResponse : public Response {
+ // The possible completions for .
+ array<CompletionItem> targets;
+};
+
+DAP_DECLARE_STRUCT_TYPEINFO(CompletionsResponse);
+
+// Returns a list of possible completions for a given caret position and text.
+// Clients should only call this request if the corresponding capability
+// `supportsCompletionsRequest` is true.
+struct CompletionsRequest : public Request {
+ using Response = CompletionsResponse;
+ // The position within `text` for which to determine the completion proposals.
+ // It is measured in UTF-16 code units and the client capability
+ // `columnsStartAt1` determines whether it is 0- or 1-based.
+ integer column;
+ // Returns completions in the scope of this stack frame. If not specified, the
+ // completions are returned for the global scope.
+ optional<integer> frameId;
+ // A line for which to determine the completion proposals. If missing the
+ // first line of the text is assumed.
+ optional<integer> line;
+ // One or more source lines. Typically this is the text users have typed into
+ // the debug console before they asked for completion.
+ string text;
+};
+
+DAP_DECLARE_STRUCT_TYPEINFO(CompletionsRequest);
+
+// Response to `configurationDone` request. This is just an acknowledgement, so
+// no body field is required.
+struct ConfigurationDoneResponse : public Response {};
+
+DAP_DECLARE_STRUCT_TYPEINFO(ConfigurationDoneResponse);
+
+// This request indicates that the client has finished initialization of the
+// debug adapter. So it is the last request in the sequence of configuration
+// requests (which was started by the `initialized` event). Clients should only
+// call this request if the corresponding capability
+// `supportsConfigurationDoneRequest` is true.
+struct ConfigurationDoneRequest : public Request {
+ using Response = ConfigurationDoneResponse;
+};
+
+DAP_DECLARE_STRUCT_TYPEINFO(ConfigurationDoneRequest);
+
+// Response to `continue` request.
+struct ContinueResponse : public Response {
+ // The value true (or a missing property) signals to the client that all
+ // threads have been resumed. The value false indicates that not all threads
+ // were resumed.
+ optional<boolean> allThreadsContinued;
+};
+
+DAP_DECLARE_STRUCT_TYPEINFO(ContinueResponse);
+
+// The request resumes execution of all threads. If the debug adapter supports
+// single thread execution (see capability
+// `supportsSingleThreadExecutionRequests`), setting the `singleThread` argument
+// to true resumes only the specified thread. If not all threads were resumed,
+// the `allThreadsContinued` attribute of the response should be set to false.
+struct ContinueRequest : public Request {
+ using Response = ContinueResponse;
+ // If this flag is true, execution is resumed only for the thread with given
+ // `threadId`.
+ optional<boolean> singleThread;
+ // Specifies the active thread. If the debug adapter supports single thread
+ // execution (see `supportsSingleThreadExecutionRequests`) and the argument
+ // `singleThread` is true, only the thread with this ID is resumed.
+ integer threadId;
+};
+
+DAP_DECLARE_STRUCT_TYPEINFO(ContinueRequest);
+
+// The event indicates that the execution of the debuggee has continued.
+// Please note: a debug adapter is not expected to send this event in response
+// to a request that implies that execution continues, e.g. `launch` or
+// `continue`. It is only necessary to send a `continued` event if there was no
+// previous request that implied this.
+struct ContinuedEvent : public Event {
+ // If `allThreadsContinued` is true, a debug adapter can announce that all
+ // threads have continued.
+ optional<boolean> allThreadsContinued;
+ // The thread which was continued.
+ integer threadId;
+};
+
+DAP_DECLARE_STRUCT_TYPEINFO(ContinuedEvent);
+
+// This enumeration defines all possible access types for data breakpoints.
+//
+// Must be one of the following enumeration values:
+// 'read', 'write', 'readWrite'
+using DataBreakpointAccessType = string;
+
+// Response to `dataBreakpointInfo` request.
+struct DataBreakpointInfoResponse : public Response {
+ // Attribute lists the available access types for a potential data breakpoint.
+ // A UI client could surface this information.
+ optional<array<DataBreakpointAccessType>> accessTypes;
+ // Attribute indicates that a potential data breakpoint could be persisted
+ // across sessions.
+ optional<boolean> canPersist;
+ // An identifier for the data on which a data breakpoint can be registered
+ // with the `setDataBreakpoints` request or null if no data breakpoint is
+ // available.
+ variant<string, null> dataId;
+ // UI string that describes on what data the breakpoint is set on or why a
+ // data breakpoint is not available.
+ string description;
+};
+
+DAP_DECLARE_STRUCT_TYPEINFO(DataBreakpointInfoResponse);
+
+// Obtains information on a possible data breakpoint that could be set on an
+// expression or variable. Clients should only call this request if the
+// corresponding capability `supportsDataBreakpoints` is true.
+struct DataBreakpointInfoRequest : public Request {
+ using Response = DataBreakpointInfoResponse;
+ // When `name` is an expression, evaluate it in the scope of this stack frame.
+ // If not specified, the expression is evaluated in the global scope. When
+ // `variablesReference` is specified, this property has no effect.
+ optional<integer> frameId;
+ // The name of the variable's child to obtain data breakpoint information for.
+ // If `variablesReference` isn't specified, this can be an expression.
+ string name;
+ // Reference to the variable container if the data breakpoint is requested for
+ // a child of the container. The `variablesReference` must have been obtained
+ // in the current suspended state. See 'Lifetime of Object References' in the
+ // Overview section for details.
+ optional<integer> variablesReference;
+};
+
+DAP_DECLARE_STRUCT_TYPEINFO(DataBreakpointInfoRequest);
+
+// Represents a single disassembled instruction.
+struct DisassembledInstruction {
+ // The address of the instruction. Treated as a hex value if prefixed with
+ // `0x`, or as a decimal value otherwise.
+ string address;
+ // The column within the line that corresponds to this instruction, if any.
+ optional<integer> column;
+ // The end column of the range that corresponds to this instruction, if any.
+ optional<integer> endColumn;
+ // The end line of the range that corresponds to this instruction, if any.
+ optional<integer> endLine;
+ // Text representing the instruction and its operands, in an
+ // implementation-defined format.
+ string instruction;
+ // Raw bytes representing the instruction and its operands, in an
+ // implementation-defined format.
+ optional<string> instructionBytes;
+ // The line within the source location that corresponds to this instruction,
+ // if any.
+ optional<integer> line;
+ // Source location that corresponds to this instruction, if any.
+ // Should always be set (if available) on the first instruction returned,
+ // but can be omitted afterwards if this instruction maps to the same source
+ // file as the previous instruction.
+ optional<Source> location;
+ // Name of the symbol that corresponds with the location of this instruction,
+ // if any.
+ optional<string> symbol;
+};
+
+DAP_DECLARE_STRUCT_TYPEINFO(DisassembledInstruction);
+
+// Response to `disassemble` request.
+struct DisassembleResponse : public Response {
+ // The list of disassembled instructions.
+ array<DisassembledInstruction> instructions;
+};
+
+DAP_DECLARE_STRUCT_TYPEINFO(DisassembleResponse);
+
+// Disassembles code stored at the provided location.
+// Clients should only call this request if the corresponding capability
+// `supportsDisassembleRequest` is true.
+struct DisassembleRequest : public Request {
+ using Response = DisassembleResponse;
+ // Number of instructions to disassemble starting at the specified location
+ // and offset. An adapter must return exactly this number of instructions -
+ // any unavailable instructions should be replaced with an
+ // implementation-defined 'invalid instruction' value.
+ integer instructionCount;
+ // Offset (in instructions) to be applied after the byte offset (if any)
+ // before disassembling. Can be negative.
+ optional<integer> instructionOffset;
+ // Memory reference to the base location containing the instructions to
+ // disassemble.
+ string memoryReference;
+ // Offset (in bytes) to be applied to the reference location before
+ // disassembling. Can be negative.
+ optional<integer> offset;
+ // If true, the adapter should attempt to resolve memory addresses and other
+ // values to symbolic names.
+ optional<boolean> resolveSymbols;
+};
+
+DAP_DECLARE_STRUCT_TYPEINFO(DisassembleRequest);
+
+// Response to `disconnect` request. This is just an acknowledgement, so no body
+// field is required.
+struct DisconnectResponse : public Response {};
+
+DAP_DECLARE_STRUCT_TYPEINFO(DisconnectResponse);
+
+// The `disconnect` request asks the debug adapter to disconnect from the
+// debuggee (thus ending the debug session) and then to shut down itself (the
+// debug adapter). In addition, the debug adapter must terminate the debuggee if
+// it was started with the `launch` request. If an `attach` request was used to
+// connect to the debuggee, then the debug adapter must not terminate the
+// debuggee. This implicit behavior of when to terminate the debuggee can be
+// overridden with the `terminateDebuggee` argument (which is only supported by
+// a debug adapter if the corresponding capability `supportTerminateDebuggee` is
+// true).
+struct DisconnectRequest : public Request {
+ using Response = DisconnectResponse;
+ // A value of true indicates that this `disconnect` request is part of a
+ // restart sequence.
+ optional<boolean> restart;
+ // Indicates whether the debuggee should stay suspended when the debugger is
+ // disconnected. If unspecified, the debuggee should resume execution. The
+ // attribute is only honored by a debug adapter if the corresponding
+ // capability `supportSuspendDebuggee` is true.
+ optional<boolean> suspendDebuggee;
+ // Indicates whether the debuggee should be terminated when the debugger is
+ // disconnected. If unspecified, the debug adapter is free to do whatever it
+ // thinks is best. The attribute is only honored by a debug adapter if the
+ // corresponding capability `supportTerminateDebuggee` is true.
+ optional<boolean> terminateDebuggee;
+};
+
+DAP_DECLARE_STRUCT_TYPEINFO(DisconnectRequest);
+
+// A structured message object. Used to return errors from requests.
+struct Message {
+ // A format string for the message. Embedded variables have the form `{name}`.
+ // If variable name starts with an underscore character, the variable does not
+ // contain user data (PII) and can be safely used for telemetry purposes.
+ string format;
+ // Unique (within a debug adapter implementation) identifier for the message.
+ // The purpose of these error IDs is to help extension authors that have the
+ // requirement that every user visible error message needs a corresponding
+ // error number, so that users or customer support can find information about
+ // the specific error more easily.
+ integer id;
+ // If true send to telemetry.
+ optional<boolean> sendTelemetry;
+ // If true show user.
+ optional<boolean> showUser;
+ // A url where additional information about this message can be found.
+ optional<string> url;
+ // A label that is presented to the user as the UI for opening the url.
+ optional<string> urlLabel;
+ // An object used as a dictionary for looking up the variables in the format
+ // string.
+ optional<object> variables;
+};
+
+DAP_DECLARE_STRUCT_TYPEINFO(Message);
+
+// On error (whenever `success` is false), the body can provide more details.
+struct ErrorResponse : public Response {
+ // A structured error message.
+ optional<Message> error;
+};
+
+DAP_DECLARE_STRUCT_TYPEINFO(ErrorResponse);
+
+// Properties of a variable that can be used to determine how to render the
+// variable in the UI.
+struct VariablePresentationHint {
+ // Set of attributes represented as an array of strings. Before introducing
+ // additional values, try to use the listed values.
+ optional<array<string>> attributes;
+ // The kind of variable. Before introducing additional values, try to use the
+ // listed values.
+ //
+ // May be one of the following enumeration values:
+ // 'property', 'method', 'class', 'data', 'event', 'baseClass', 'innerClass',
+ // 'interface', 'mostDerivedClass', 'virtual', 'dataBreakpoint'
+ optional<string> kind;
+ // If true, clients can present the variable with a UI that supports a
+ // specific gesture to trigger its evaluation. This mechanism can be used for
+ // properties that require executing code when retrieving their value and
+ // where the code execution can be expensive and/or produce side-effects. A
+ // typical example are properties based on a getter function. Please note that
+ // in addition to the `lazy` flag, the variable's `variablesReference` is
+ // expected to refer to a variable that will provide the value through another
+ // `variable` request.
+ optional<boolean> lazy;
+ // Visibility of variable. Before introducing additional values, try to use
+ // the listed values.
+ //
+ // May be one of the following enumeration values:
+ // 'public', 'private', 'protected', 'internal', 'final'
+ optional<string> visibility;
+};
+
+DAP_DECLARE_STRUCT_TYPEINFO(VariablePresentationHint);
+
+// Response to `evaluate` request.
+struct EvaluateResponse : public Response {
+ // The number of indexed child variables.
+ // The client can use this information to present the variables in a paged UI
+ // and fetch them in chunks. The value should be less than or equal to
+ // 2147483647 (2^31-1).
+ optional<integer> indexedVariables;
+ // A memory reference to a location appropriate for this result.
+ // For pointer type eval results, this is generally a reference to the memory
+ // address contained in the pointer. This attribute should be returned by a
+ // debug adapter if corresponding capability `supportsMemoryReferences` is
+ // true.
+ optional<string> memoryReference;
+ // The number of named child variables.
+ // The client can use this information to present the variables in a paged UI
+ // and fetch them in chunks. The value should be less than or equal to
+ // 2147483647 (2^31-1).
+ optional<integer> namedVariables;
+ // Properties of an evaluate result that can be used to determine how to
+ // render the result in the UI.
+ optional<VariablePresentationHint> presentationHint;
+ // The result of the evaluate request.
+ string result;
+ // The type of the evaluate result.
+ // This attribute should only be returned by a debug adapter if the
+ // corresponding capability `supportsVariableType` is true.
+ optional<string> type;
+ // If `variablesReference` is > 0, the evaluate result is structured and its
+ // children can be retrieved by passing `variablesReference` to the
+ // `variables` request as long as execution remains suspended. See 'Lifetime
+ // of Object References' in the Overview section for details.
+ integer variablesReference;
+};
+
+DAP_DECLARE_STRUCT_TYPEINFO(EvaluateResponse);
+
+// Provides formatting information for a value.
+struct ValueFormat {
+ // Display the value in hex.
+ optional<boolean> hex;
+};
+
+DAP_DECLARE_STRUCT_TYPEINFO(ValueFormat);
+
+// Evaluates the given expression in the context of the topmost stack frame.
+// The expression has access to any variables and arguments that are in scope.
+struct EvaluateRequest : public Request {
+ using Response = EvaluateResponse;
+ // The context in which the evaluate request is used.
+ //
+ // May be one of the following enumeration values:
+ // 'watch', 'repl', 'hover', 'clipboard', 'variables'
+ optional<string> context;
+ // The expression to evaluate.
+ string expression;
+ // Specifies details on how to format the result.
+ // The attribute is only honored by a debug adapter if the corresponding
+ // capability `supportsValueFormattingOptions` is true.
+ optional<ValueFormat> format;
+ // Evaluate the expression in the scope of this stack frame. If not specified,
+ // the expression is evaluated in the global scope.
+ optional<integer> frameId;
+};
+
+DAP_DECLARE_STRUCT_TYPEINFO(EvaluateRequest);
+
+// This enumeration defines all possible conditions when a thrown exception
+// should result in a break. never: never breaks, always: always breaks,
+// unhandled: breaks when exception unhandled,
+// userUnhandled: breaks if the exception is not handled by user code.
+//
+// Must be one of the following enumeration values:
+// 'never', 'always', 'unhandled', 'userUnhandled'
+using ExceptionBreakMode = string;
+
+// Detailed information about an exception that has occurred.
+struct ExceptionDetails {
+ // An expression that can be evaluated in the current scope to obtain the
+ // exception object.
+ optional<string> evaluateName;
+ // Fully-qualified type name of the exception object.
+ optional<string> fullTypeName;
+ // Details of the exception contained by this exception, if any.
+ optional<array<ExceptionDetails>> innerException;
+ // Message contained in the exception.
+ optional<string> message;
+ // Stack trace at the time the exception was thrown.
+ optional<string> stackTrace;
+ // Short type name of the exception object.
+ optional<string> typeName;
+};
+
+DAP_DECLARE_STRUCT_TYPEINFO(ExceptionDetails);
+
+// Response to `exceptionInfo` request.
+struct ExceptionInfoResponse : public Response {
+ // Mode that caused the exception notification to be raised.
+ ExceptionBreakMode breakMode = "never";
+ // Descriptive text for the exception.
+ optional<string> description;
+ // Detailed information about the exception.
+ optional<ExceptionDetails> details;
+ // ID of the exception that was thrown.
+ string exceptionId;
+};
+
+DAP_DECLARE_STRUCT_TYPEINFO(ExceptionInfoResponse);
+
+// Retrieves the details of the exception that caused this event to be raised.
+// Clients should only call this request if the corresponding capability
+// `supportsExceptionInfoRequest` is true.
+struct ExceptionInfoRequest : public Request {
+ using Response = ExceptionInfoResponse;
+ // Thread for which exception information should be retrieved.
+ integer threadId;
+};
+
+DAP_DECLARE_STRUCT_TYPEINFO(ExceptionInfoRequest);
+
+// The event indicates that the debuggee has exited and returns its exit code.
+struct ExitedEvent : public Event {
+ // The exit code returned from the debuggee.
+ integer exitCode;
+};
+
+DAP_DECLARE_STRUCT_TYPEINFO(ExitedEvent);
+
+// Response to `goto` request. This is just an acknowledgement, so no body field
+// is required.
+struct GotoResponse : public Response {};
+
+DAP_DECLARE_STRUCT_TYPEINFO(GotoResponse);
+
+// The request sets the location where the debuggee will continue to run.
+// This makes it possible to skip the execution of code or to execute code
+// again. The code between the current location and the goto target is not
+// executed but skipped. The debug adapter first sends the response and then a
+// `stopped` event with reason `goto`. Clients should only call this request if
+// the corresponding capability `supportsGotoTargetsRequest` is true (because
+// only then goto targets exist that can be passed as arguments).
+struct GotoRequest : public Request {
+ using Response = GotoResponse;
+ // The location where the debuggee will continue to run.
+ integer targetId;
+ // Set the goto target for this thread.
+ integer threadId;
+};
+
+DAP_DECLARE_STRUCT_TYPEINFO(GotoRequest);
+
+// A `GotoTarget` describes a code location that can be used as a target in the
+// `goto` request. The possible goto targets can be determined via the
+// `gotoTargets` request.
+struct GotoTarget {
+ // The column of the goto target.
+ optional<integer> column;
+ // The end column of the range covered by the goto target.
+ optional<integer> endColumn;
+ // The end line of the range covered by the goto target.
+ optional<integer> endLine;
+ // Unique identifier for a goto target. This is used in the `goto` request.
+ integer id;
+ // A memory reference for the instruction pointer value represented by this
+ // target.
+ optional<string> instructionPointerReference;
+ // The name of the goto target (shown in the UI).
+ string label;
+ // The line of the goto target.
+ integer line;
+};
+
+DAP_DECLARE_STRUCT_TYPEINFO(GotoTarget);
+
+// Response to `gotoTargets` request.
+struct GotoTargetsResponse : public Response {
+ // The possible goto targets of the specified location.
+ array<GotoTarget> targets;
+};
+
+DAP_DECLARE_STRUCT_TYPEINFO(GotoTargetsResponse);
+
+// This request retrieves the possible goto targets for the specified source
+// location. These targets can be used in the `goto` request. Clients should
+// only call this request if the corresponding capability
+// `supportsGotoTargetsRequest` is true.
+struct GotoTargetsRequest : public Request {
+ using Response = GotoTargetsResponse;
+ // The position within `line` for which the goto targets are determined. It is
+ // measured in UTF-16 code units and the client capability `columnsStartAt1`
+ // determines whether it is 0- or 1-based.
+ optional<integer> column;
+ // The line location for which the goto targets are determined.
+ integer line;
+ // The source location for which the goto targets are determined.
+ Source source;
+};
+
+DAP_DECLARE_STRUCT_TYPEINFO(GotoTargetsRequest);
+
+// Response to `initialize` request.
+struct InitializeResponse : public Response {
+ // The set of additional module information exposed by the debug adapter.
+ optional<array<ColumnDescriptor>> additionalModuleColumns;
+ // The set of characters that should trigger completion in a REPL. If not
+ // specified, the UI should assume the `.` character.
+ optional<array<string>> completionTriggerCharacters;
+ // Available exception filter options for the `setExceptionBreakpoints`
+ // request.
+ optional<array<ExceptionBreakpointsFilter>> exceptionBreakpointFilters;
+ // The debug adapter supports the `suspendDebuggee` attribute on the
+ // `disconnect` request.
+ optional<boolean> supportSuspendDebuggee;
+ // The debug adapter supports the `terminateDebuggee` attribute on the
+ // `disconnect` request.
+ optional<boolean> supportTerminateDebuggee;
+ // Checksum algorithms supported by the debug adapter.
+ optional<array<ChecksumAlgorithm>> supportedChecksumAlgorithms;
+ // The debug adapter supports the `breakpointLocations` request.
+ optional<boolean> supportsBreakpointLocationsRequest;
+ // The debug adapter supports the `cancel` request.
+ optional<boolean> supportsCancelRequest;
+ // The debug adapter supports the `clipboard` context value in the `evaluate`
+ // request.
+ optional<boolean> supportsClipboardContext;
+ // The debug adapter supports the `completions` request.
+ optional<boolean> supportsCompletionsRequest;
+ // The debug adapter supports conditional breakpoints.
+ optional<boolean> supportsConditionalBreakpoints;
+ // The debug adapter supports the `configurationDone` request.
+ optional<boolean> supportsConfigurationDoneRequest;
+ // The debug adapter supports data breakpoints.
+ optional<boolean> supportsDataBreakpoints;
+ // The debug adapter supports the delayed loading of parts of the stack, which
+ // requires that both the `startFrame` and `levels` arguments and the
+ // `totalFrames` result of the `stackTrace` request are supported.
+ optional<boolean> supportsDelayedStackTraceLoading;
+ // The debug adapter supports the `disassemble` request.
+ optional<boolean> supportsDisassembleRequest;
+ // The debug adapter supports a (side effect free) `evaluate` request for data
+ // hovers.
+ optional<boolean> supportsEvaluateForHovers;
+ // The debug adapter supports `filterOptions` as an argument on the
+ // `setExceptionBreakpoints` request.
+ optional<boolean> supportsExceptionFilterOptions;
+ // The debug adapter supports the `exceptionInfo` request.
+ optional<boolean> supportsExceptionInfoRequest;
+ // The debug adapter supports `exceptionOptions` on the
+ // `setExceptionBreakpoints` request.
+ optional<boolean> supportsExceptionOptions;
+ // The debug adapter supports function breakpoints.
+ optional<boolean> supportsFunctionBreakpoints;
+ // The debug adapter supports the `gotoTargets` request.
+ optional<boolean> supportsGotoTargetsRequest;
+ // The debug adapter supports breakpoints that break execution after a
+ // specified number of hits.
+ optional<boolean> supportsHitConditionalBreakpoints;
+ // The debug adapter supports adding breakpoints based on instruction
+ // references.
+ optional<boolean> supportsInstructionBreakpoints;
+ // The debug adapter supports the `loadedSources` request.
+ optional<boolean> supportsLoadedSourcesRequest;
+ // The debug adapter supports log points by interpreting the `logMessage`
+ // attribute of the `SourceBreakpoint`.
+ optional<boolean> supportsLogPoints;
+ // The debug adapter supports the `modules` request.
+ optional<boolean> supportsModulesRequest;
+ // The debug adapter supports the `readMemory` request.
+ optional<boolean> supportsReadMemoryRequest;
+ // The debug adapter supports restarting a frame.
+ optional<boolean> supportsRestartFrame;
+ // The debug adapter supports the `restart` request. In this case a client
+ // should not implement `restart` by terminating and relaunching the adapter
+ // but by calling the `restart` request.
+ optional<boolean> supportsRestartRequest;
+ // The debug adapter supports the `setExpression` request.
+ optional<boolean> supportsSetExpression;
+ // The debug adapter supports setting a variable to a value.
+ optional<boolean> supportsSetVariable;
+ // The debug adapter supports the `singleThread` property on the execution
+ // requests (`continue`, `next`, `stepIn`, `stepOut`, `reverseContinue`,
+ // `stepBack`).
+ optional<boolean> supportsSingleThreadExecutionRequests;
+ // The debug adapter supports stepping back via the `stepBack` and
+ // `reverseContinue` requests.
+ optional<boolean> supportsStepBack;
+ // The debug adapter supports the `stepInTargets` request.
+ optional<boolean> supportsStepInTargetsRequest;
+ // The debug adapter supports stepping granularities (argument `granularity`)
+ // for the stepping requests.
+ optional<boolean> supportsSteppingGranularity;
+ // The debug adapter supports the `terminate` request.
+ optional<boolean> supportsTerminateRequest;
+ // The debug adapter supports the `terminateThreads` request.
+ optional<boolean> supportsTerminateThreadsRequest;
+ // The debug adapter supports a `format` attribute on the `stackTrace`,
+ // `variables`, and `evaluate` requests.
+ optional<boolean> supportsValueFormattingOptions;
+ // The debug adapter supports the `writeMemory` request.
+ optional<boolean> supportsWriteMemoryRequest;
+};
+
+DAP_DECLARE_STRUCT_TYPEINFO(InitializeResponse);
+
+// The `initialize` request is sent as the first request from the client to the
+// debug adapter in order to configure it with client capabilities and to
+// retrieve capabilities from the debug adapter. Until the debug adapter has
+// responded with an `initialize` response, the client must not send any
+// additional requests or events to the debug adapter. In addition the debug
+// adapter is not allowed to send any requests or events to the client until it
+// has responded with an `initialize` response. The `initialize` request may
+// only be sent once.
+struct InitializeRequest : public Request {
+ using Response = InitializeResponse;
+ // The ID of the debug adapter.
+ string adapterID;
+ // The ID of the client using this adapter.
+ optional<string> clientID;
+ // The human-readable name of the client using this adapter.
+ optional<string> clientName;
+ // If true all column numbers are 1-based (default).
+ optional<boolean> columnsStartAt1;
+ // If true all line numbers are 1-based (default).
+ optional<boolean> linesStartAt1;
+ // The ISO-639 locale of the client using this adapter, e.g. en-US or de-CH.
+ optional<string> locale;
+ // Determines in what format paths are specified. The default is `path`, which
+ // is the native format.
+ //
+ // May be one of the following enumeration values:
+ // 'path', 'uri'
+ optional<string> pathFormat;
+ // Client supports the `argsCanBeInterpretedByShell` attribute on the
+ // `runInTerminal` request.
+ optional<boolean> supportsArgsCanBeInterpretedByShell;
+ // Client supports the `invalidated` event.
+ optional<boolean> supportsInvalidatedEvent;
+ // Client supports the `memory` event.
+ optional<boolean> supportsMemoryEvent;
+ // Client supports memory references.
+ optional<boolean> supportsMemoryReferences;
+ // Client supports progress reporting.
+ optional<boolean> supportsProgressReporting;
+ // Client supports the `runInTerminal` request.
+ optional<boolean> supportsRunInTerminalRequest;
+ // Client supports the `startDebugging` request.
+ optional<boolean> supportsStartDebuggingRequest;
+ // Client supports the paging of variables.
+ optional<boolean> supportsVariablePaging;
+ // Client supports the `type` attribute for variables.
+ optional<boolean> supportsVariableType;
+};
+
+DAP_DECLARE_STRUCT_TYPEINFO(InitializeRequest);
+
+// This event indicates that the debug adapter is ready to accept configuration
+// requests (e.g. `setBreakpoints`, `setExceptionBreakpoints`). A debug adapter
+// is expected to send this event when it is ready to accept configuration
+// requests (but not before the `initialize` request has finished). The sequence
+// of events/requests is as follows:
+// - adapters sends `initialized` event (after the `initialize` request has
+// returned)
+// - client sends zero or more `setBreakpoints` requests
+// - client sends one `setFunctionBreakpoints` request (if corresponding
+// capability `supportsFunctionBreakpoints` is true)
+// - client sends a `setExceptionBreakpoints` request if one or more
+// `exceptionBreakpointFilters` have been defined (or if
+// `supportsConfigurationDoneRequest` is not true)
+// - client sends other future configuration requests
+// - client sends one `configurationDone` request to indicate the end of the
+// configuration.
+struct InitializedEvent : public Event {};
+
+DAP_DECLARE_STRUCT_TYPEINFO(InitializedEvent);
+
+// Logical areas that can be invalidated by the `invalidated` event.
+using InvalidatedAreas = string;
+
+// This event signals that some state in the debug adapter has changed and
+// requires that the client needs to re-render the data snapshot previously
+// requested. Debug adapters do not have to emit this event for runtime changes
+// like stopped or thread events because in that case the client refetches the
+// new state anyway. But the event can be used for example to refresh the UI
+// after rendering formatting has changed in the debug adapter. This event
+// should only be sent if the corresponding capability
+// `supportsInvalidatedEvent` is true.
+struct InvalidatedEvent : public Event {
+ // Set of logical areas that got invalidated. This property has a hint
+ // characteristic: a client can only be expected to make a 'best effort' in
+ // honoring the areas but there are no guarantees. If this property is
+ // missing, empty, or if values are not understood, the client should assume a
+ // single value `all`.
+ optional<array<InvalidatedAreas>> areas;
+ // If specified, the client only needs to refetch data related to this stack
+ // frame (and the `threadId` is ignored).
+ optional<integer> stackFrameId;
+ // If specified, the client only needs to refetch data related to this thread.
+ optional<integer> threadId;
+};
+
+DAP_DECLARE_STRUCT_TYPEINFO(InvalidatedEvent);
+
+// Response to `launch` request. This is just an acknowledgement, so no body
+// field is required.
+struct LaunchResponse : public Response {};
+
+DAP_DECLARE_STRUCT_TYPEINFO(LaunchResponse);
+
+// This launch request is sent from the client to the debug adapter to start the
+// debuggee with or without debugging (if `noDebug` is true). Since launching is
+// debugger/runtime specific, the arguments for this request are not part of
+// this specification.
+struct LaunchRequest : public Request {
+ using Response = LaunchResponse;
+ // Arbitrary data from the previous, restarted session.
+ // The data is sent as the `restart` attribute of the `terminated` event.
+ // The client should leave the data intact.
+ optional<variant<array<any>, boolean, integer, null, number, object, string>>
+ restart;
+ // If true, the launch request should launch the program without enabling
+ // debugging.
+ optional<boolean> noDebug;
+};
+
+DAP_DECLARE_STRUCT_TYPEINFO(LaunchRequest);
+
+// The event indicates that some source has been added, changed, or removed from
+// the set of all loaded sources.
+struct LoadedSourceEvent : public Event {
+ // The reason for the event.
+ //
+ // Must be one of the following enumeration values:
+ // 'new', 'changed', 'removed'
+ string reason = "new";
+ // The new, changed, or removed source.
+ Source source;
+};
+
+DAP_DECLARE_STRUCT_TYPEINFO(LoadedSourceEvent);
+
+// Response to `loadedSources` request.
+struct LoadedSourcesResponse : public Response {
+ // Set of loaded sources.
+ array<Source> sources;
+};
+
+DAP_DECLARE_STRUCT_TYPEINFO(LoadedSourcesResponse);
+
+// Retrieves the set of all sources currently loaded by the debugged process.
+// Clients should only call this request if the corresponding capability
+// `supportsLoadedSourcesRequest` is true.
+struct LoadedSourcesRequest : public Request {
+ using Response = LoadedSourcesResponse;
+};
+
+DAP_DECLARE_STRUCT_TYPEINFO(LoadedSourcesRequest);
+
+// This event indicates that some memory range has been updated. It should only
+// be sent if the corresponding capability `supportsMemoryEvent` is true.
+// Clients typically react to the event by re-issuing a `readMemory` request if
+// they show the memory identified by the `memoryReference` and if the updated
+// memory range overlaps the displayed range. Clients should not make
+// assumptions how individual memory references relate to each other, so they
+// should not assume that they are part of a single continuous address range and
+// might overlap. Debug adapters can use this event to indicate that the
+// contents of a memory range has changed due to some other request like
+// `setVariable` or `setExpression`. Debug adapters are not expected to emit
+// this event for each and every memory change of a running program, because
+// that information is typically not available from debuggers and it would flood
+// clients with too many events.
+struct MemoryEvent : public Event {
+ // Number of bytes updated.
+ integer count;
+ // Memory reference of a memory range that has been updated.
+ string memoryReference;
+ // Starting offset in bytes where memory has been updated. Can be negative.
+ integer offset;
+};
+
+DAP_DECLARE_STRUCT_TYPEINFO(MemoryEvent);
+
+// A Module object represents a row in the modules view.
+// The `id` attribute identifies a module in the modules view and is used in a
+// `module` event for identifying a module for adding, updating or deleting. The
+// `name` attribute is used to minimally render the module in the UI.
+//
+// Additional attributes can be added to the module. They show up in the module
+// view if they have a corresponding `ColumnDescriptor`.
+//
+// To avoid an unnecessary proliferation of additional attributes with similar
+// semantics but different names, we recommend to re-use attributes from the
+// 'recommended' list below first, and only introduce new attributes if nothing
+// appropriate could be found.
+struct Module {
+ // Address range covered by this module.
+ optional<string> addressRange;
+ // Module created or modified, encoded as a RFC 3339 timestamp.
+ optional<string> dateTimeStamp;
+ // Unique identifier for the module.
+ variant<integer, string> id;
+ // True if the module is optimized.
+ optional<boolean> isOptimized;
+ // True if the module is considered 'user code' by a debugger that supports
+ // 'Just My Code'.
+ optional<boolean> isUserCode;
+ // A name of the module.
+ string name;
+ // Logical full path to the module. The exact definition is implementation
+ // defined, but usually this would be a full path to the on-disk file for the
+ // module.
+ optional<string> path;
+ // Logical full path to the symbol file. The exact definition is
+ // implementation defined.
+ optional<string> symbolFilePath;
+ // User-understandable description of if symbols were found for the module
+ // (ex: 'Symbols Loaded', 'Symbols not found', etc.)
+ optional<string> symbolStatus;
+ // Version of Module.
+ optional<string> version;
+};
+
+DAP_DECLARE_STRUCT_TYPEINFO(Module);
+
+// The event indicates that some information about a module has changed.
+struct ModuleEvent : public Event {
+ // The new, changed, or removed module. In case of `removed` only the module
+ // id is used.
+ Module module;
+ // The reason for the event.
+ //
+ // Must be one of the following enumeration values:
+ // 'new', 'changed', 'removed'
+ string reason = "new";
+};
+
+DAP_DECLARE_STRUCT_TYPEINFO(ModuleEvent);
+
+// Response to `modules` request.
+struct ModulesResponse : public Response {
+ // All modules or range of modules.
+ array<Module> modules;
+ // The total number of modules available.
+ optional<integer> totalModules;
+};
+
+DAP_DECLARE_STRUCT_TYPEINFO(ModulesResponse);
+
+// Modules can be retrieved from the debug adapter with this request which can
+// either return all modules or a range of modules to support paging. Clients
+// should only call this request if the corresponding capability
+// `supportsModulesRequest` is true.
+struct ModulesRequest : public Request {
+ using Response = ModulesResponse;
+ // The number of modules to return. If `moduleCount` is not specified or 0,
+ // all modules are returned.
+ optional<integer> moduleCount;
+ // The index of the first module to return; if omitted modules start at 0.
+ optional<integer> startModule;
+};
+
+DAP_DECLARE_STRUCT_TYPEINFO(ModulesRequest);
+
+// Response to `next` request. This is just an acknowledgement, so no body field
+// is required.
+struct NextResponse : public Response {};
+
+DAP_DECLARE_STRUCT_TYPEINFO(NextResponse);
+
+// The granularity of one 'step' in the stepping requests `next`, `stepIn`,
+// `stepOut`, and `stepBack`.
+//
+// Must be one of the following enumeration values:
+// 'statement', 'line', 'instruction'
+using SteppingGranularity = string;
+
+// The request executes one step (in the given granularity) for the specified
+// thread and allows all other threads to run freely by resuming them. If the
+// debug adapter supports single thread execution (see capability
+// `supportsSingleThreadExecutionRequests`), setting the `singleThread` argument
+// to true prevents other suspended threads from resuming. The debug adapter
+// first sends the response and then a `stopped` event (with reason `step`)
+// after the step has completed.
+struct NextRequest : public Request {
+ using Response = NextResponse;
+ // Stepping granularity. If no granularity is specified, a granularity of
+ // `statement` is assumed.
+ optional<SteppingGranularity> granularity;
+ // If this flag is true, all other suspended threads are not resumed.
+ optional<boolean> singleThread;
+ // Specifies the thread for which to resume execution for one step (of the
+ // given granularity).
+ integer threadId;
+};
+
+DAP_DECLARE_STRUCT_TYPEINFO(NextRequest);
+
+// The event indicates that the target has produced some output.
+struct OutputEvent : public Event {
+ // The output category. If not specified or if the category is not understood
+ // by the client, `console` is assumed.
+ //
+ // May be one of the following enumeration values:
+ // 'console', 'important', 'stdout', 'stderr', 'telemetry'
+ optional<string> category;
+ // The position in `line` where the output was produced. It is measured in
+ // UTF-16 code units and the client capability `columnsStartAt1` determines
+ // whether it is 0- or 1-based.
+ optional<integer> column;
+ // Additional data to report. For the `telemetry` category the data is sent to
+ // telemetry, for the other categories the data is shown in JSON format.
+ optional<variant<array<any>, boolean, integer, null, number, object, string>>
+ data;
+ // Support for keeping an output log organized by grouping related messages.
+ //
+ // Must be one of the following enumeration values:
+ // 'start', 'startCollapsed', 'end'
+ optional<string> group;
+ // The source location's line where the output was produced.
+ optional<integer> line;
+ // The output to report.
+ string output;
+ // The source location where the output was produced.
+ optional<Source> source;
+ // If an attribute `variablesReference` exists and its value is > 0, the
+ // output contains objects which can be retrieved by passing
+ // `variablesReference` to the `variables` request as long as execution
+ // remains suspended. See 'Lifetime of Object References' in the Overview
+ // section for details.
+ optional<integer> variablesReference;
+};
+
+DAP_DECLARE_STRUCT_TYPEINFO(OutputEvent);
+
+// Response to `pause` request. This is just an acknowledgement, so no body
+// field is required.
+struct PauseResponse : public Response {};
+
+DAP_DECLARE_STRUCT_TYPEINFO(PauseResponse);
+
+// The request suspends the debuggee.
+// The debug adapter first sends the response and then a `stopped` event (with
+// reason `pause`) after the thread has been paused successfully.
+struct PauseRequest : public Request {
+ using Response = PauseResponse;
+ // Pause execution for this thread.
+ integer threadId;
+};
+
+DAP_DECLARE_STRUCT_TYPEINFO(PauseRequest);
+
+// The event indicates that the debugger has begun debugging a new process.
+// Either one that it has launched, or one that it has attached to.
+struct ProcessEvent : public Event {
+ // If true, the process is running on the same computer as the debug adapter.
+ optional<boolean> isLocalProcess;
+ // The logical name of the process. This is usually the full path to process's
+ // executable file. Example: /home/example/myproj/program.js.
+ string name;
+ // The size of a pointer or address for this process, in bits. This value may
+ // be used by clients when formatting addresses for display.
+ optional<integer> pointerSize;
+ // Describes how the debug engine started debugging this process.
+ //
+ // Must be one of the following enumeration values:
+ // 'launch', 'attach', 'attachForSuspendedLaunch'
+ optional<string> startMethod;
+ // The system process id of the debugged process. This property is missing for
+ // non-system processes.
+ optional<integer> systemProcessId;
+};
+
+DAP_DECLARE_STRUCT_TYPEINFO(ProcessEvent);
+
+// The event signals the end of the progress reporting with a final message.
+// This event should only be sent if the corresponding capability
+// `supportsProgressReporting` is true.
+struct ProgressEndEvent : public Event {
+ // More detailed progress message. If omitted, the previous message (if any)
+ // is used.
+ optional<string> message;
+ // The ID that was introduced in the initial `ProgressStartEvent`.
+ string progressId;
+};
+
+DAP_DECLARE_STRUCT_TYPEINFO(ProgressEndEvent);
+
+// The event signals that a long running operation is about to start and
+// provides additional information for the client to set up a corresponding
+// progress and cancellation UI. The client is free to delay the showing of the
+// UI in order to reduce flicker. This event should only be sent if the
+// corresponding capability `supportsProgressReporting` is true.
+struct ProgressStartEvent : public Event {
+ // If true, the request that reports progress may be cancelled with a `cancel`
+ // request. So this property basically controls whether the client should use
+ // UX that supports cancellation. Clients that don't support cancellation are
+ // allowed to ignore the setting.
+ optional<boolean> cancellable;
+ // More detailed progress message.
+ optional<string> message;
+ // Progress percentage to display (value range: 0 to 100). If omitted no
+ // percentage is shown.
+ optional<number> percentage;
+ // An ID that can be used in subsequent `progressUpdate` and `progressEnd`
+ // events to make them refer to the same progress reporting. IDs must be
+ // unique within a debug session.
+ string progressId;
+ // The request ID that this progress report is related to. If specified a
+ // debug adapter is expected to emit progress events for the long running
+ // request until the request has been either completed or cancelled. If the
+ // request ID is omitted, the progress report is assumed to be related to some
+ // general activity of the debug adapter.
+ optional<integer> requestId;
+ // Short title of the progress reporting. Shown in the UI to describe the long
+ // running operation.
+ string title;
+};
+
+DAP_DECLARE_STRUCT_TYPEINFO(ProgressStartEvent);
+
+// The event signals that the progress reporting needs to be updated with a new
+// message and/or percentage. The client does not have to update the UI
+// immediately, but the clients needs to keep track of the message and/or
+// percentage values. This event should only be sent if the corresponding
+// capability `supportsProgressReporting` is true.
+struct ProgressUpdateEvent : public Event {
+ // More detailed progress message. If omitted, the previous message (if any)
+ // is used.
+ optional<string> message;
+ // Progress percentage to display (value range: 0 to 100). If omitted no
+ // percentage is shown.
+ optional<number> percentage;
+ // The ID that was introduced in the initial `progressStart` event.
+ string progressId;
+};
+
+DAP_DECLARE_STRUCT_TYPEINFO(ProgressUpdateEvent);
+
+// Response to `readMemory` request.
+struct ReadMemoryResponse : public Response {
+ // The address of the first byte of data returned.
+ // Treated as a hex value if prefixed with `0x`, or as a decimal value
+ // otherwise.
+ string address;
+ // The bytes read from memory, encoded using base64. If the decoded length of
+ // `data` is less than the requested `count` in the original `readMemory`
+ // request, and `unreadableBytes` is zero or omitted, then the client should
+ // assume it's reached the end of readable memory.
+ optional<string> data;
+ // The number of unreadable bytes encountered after the last successfully read
+ // byte. This can be used to determine the number of bytes that should be
+ // skipped before a subsequent `readMemory` request succeeds.
+ optional<integer> unreadableBytes;
+};
+
+DAP_DECLARE_STRUCT_TYPEINFO(ReadMemoryResponse);
+
+// Reads bytes from memory at the provided location.
+// Clients should only call this request if the corresponding capability
+// `supportsReadMemoryRequest` is true.
+struct ReadMemoryRequest : public Request {
+ using Response = ReadMemoryResponse;
+ // Number of bytes to read at the specified location and offset.
+ integer count;
+ // Memory reference to the base location from which data should be read.
+ string memoryReference;
+ // Offset (in bytes) to be applied to the reference location before reading
+ // data. Can be negative.
+ optional<integer> offset;
+};
+
+DAP_DECLARE_STRUCT_TYPEINFO(ReadMemoryRequest);
+
+// Response to `restartFrame` request. This is just an acknowledgement, so no
+// body field is required.
+struct RestartFrameResponse : public Response {};
+
+DAP_DECLARE_STRUCT_TYPEINFO(RestartFrameResponse);
+
+// The request restarts execution of the specified stack frame.
+// The debug adapter first sends the response and then a `stopped` event (with
+// reason `restart`) after the restart has completed. Clients should only call
+// this request if the corresponding capability `supportsRestartFrame` is true.
+struct RestartFrameRequest : public Request {
+ using Response = RestartFrameResponse;
+ // Restart the stack frame identified by `frameId`. The `frameId` must have
+ // been obtained in the current suspended state. See 'Lifetime of Object
+ // References' in the Overview section for details.
+ integer frameId;
+};
+
+DAP_DECLARE_STRUCT_TYPEINFO(RestartFrameRequest);
+
+// Response to `restart` request. This is just an acknowledgement, so no body
+// field is required.
+struct RestartResponse : public Response {};
+
+DAP_DECLARE_STRUCT_TYPEINFO(RestartResponse);
+
+// Restarts a debug session. Clients should only call this request if the
+// corresponding capability `supportsRestartRequest` is true. If the capability
+// is missing or has the value false, a typical client emulates `restart` by
+// terminating the debug adapter first and then launching it anew.
+struct RestartRequest : public Request {
+ using Response = RestartResponse;
+ // The latest version of the `launch` or `attach` configuration.
+ optional<object> arguments;
+};
+
+DAP_DECLARE_STRUCT_TYPEINFO(RestartRequest);
+
+// Response to `reverseContinue` request. This is just an acknowledgement, so no
+// body field is required.
+struct ReverseContinueResponse : public Response {};
+
+DAP_DECLARE_STRUCT_TYPEINFO(ReverseContinueResponse);
+
+// The request resumes backward execution of all threads. If the debug adapter
+// supports single thread execution (see capability
+// `supportsSingleThreadExecutionRequests`), setting the `singleThread` argument
+// to true resumes only the specified thread. If not all threads were resumed,
+// the `allThreadsContinued` attribute of the response should be set to false.
+// Clients should only call this request if the corresponding capability
+// `supportsStepBack` is true.
+struct ReverseContinueRequest : public Request {
+ using Response = ReverseContinueResponse;
+ // If this flag is true, backward execution is resumed only for the thread
+ // with given `threadId`.
+ optional<boolean> singleThread;
+ // Specifies the active thread. If the debug adapter supports single thread
+ // execution (see `supportsSingleThreadExecutionRequests`) and the
+ // `singleThread` argument is true, only the thread with this ID is resumed.
+ integer threadId;
+};
+
+DAP_DECLARE_STRUCT_TYPEINFO(ReverseContinueRequest);
+
+// Response to `runInTerminal` request.
+struct RunInTerminalResponse : public Response {
+ // The process ID. The value should be less than or equal to 2147483647
+ // (2^31-1).
+ optional<integer> processId;
+ // The process ID of the terminal shell. The value should be less than or
+ // equal to 2147483647 (2^31-1).
+ optional<integer> shellProcessId;
+};
+
+DAP_DECLARE_STRUCT_TYPEINFO(RunInTerminalResponse);
+
+// This request is sent from the debug adapter to the client to run a command in
+// a terminal. This is typically used to launch the debuggee in a terminal
+// provided by the client. This request should only be called if the
+// corresponding client capability `supportsRunInTerminalRequest` is true.
+// Client implementations of `runInTerminal` are free to run the command however
+// they choose including issuing the command to a command line interpreter (aka
+// 'shell'). Argument strings passed to the `runInTerminal` request must arrive
+// verbatim in the command to be run. As a consequence, clients which use a
+// shell are responsible for escaping any special shell characters in the
+// argument strings to prevent them from being interpreted (and modified) by the
+// shell. Some users may wish to take advantage of shell processing in the
+// argument strings. For clients which implement `runInTerminal` using an
+// intermediary shell, the `argsCanBeInterpretedByShell` property can be set to
+// true. In this case the client is requested not to escape any special shell
+// characters in the argument strings.
+struct RunInTerminalRequest : public Request {
+ using Response = RunInTerminalResponse;
+ // List of arguments. The first argument is the command to run.
+ array<string> args;
+ // This property should only be set if the corresponding capability
+ // `supportsArgsCanBeInterpretedByShell` is true. If the client uses an
+ // intermediary shell to launch the application, then the client must not
+ // attempt to escape characters with special meanings for the shell. The user
+ // is fully responsible for escaping as needed and that arguments using
+ // special characters may not be portable across shells.
+ optional<boolean> argsCanBeInterpretedByShell;
+ // Working directory for the command. For non-empty, valid paths this
+ // typically results in execution of a change directory command.
+ string cwd;
+ // Environment key-value pairs that are added to or removed from the default
+ // environment.
+ optional<object> env;
+ // What kind of terminal to launch. Defaults to `integrated` if not specified.
+ //
+ // Must be one of the following enumeration values:
+ // 'integrated', 'external'
+ optional<string> kind;
+ // Title of the terminal.
+ optional<string> title;
+};
+
+DAP_DECLARE_STRUCT_TYPEINFO(RunInTerminalRequest);
+
+// A `Scope` is a named container for variables. Optionally a scope can map to a
+// source or a range within a source.
+struct Scope {
+ // Start position of the range covered by the scope. It is measured in UTF-16
+ // code units and the client capability `columnsStartAt1` determines whether
+ // it is 0- or 1-based.
+ optional<integer> column;
+ // End position of the range covered by the scope. It is measured in UTF-16
+ // code units and the client capability `columnsStartAt1` determines whether
+ // it is 0- or 1-based.
+ optional<integer> endColumn;
+ // The end line of the range covered by this scope.
+ optional<integer> endLine;
+ // If true, the number of variables in this scope is large or expensive to
+ // retrieve.
+ boolean expensive;
+ // The number of indexed variables in this scope.
+ // The client can use this information to present the variables in a paged UI
+ // and fetch them in chunks.
+ optional<integer> indexedVariables;
+ // The start line of the range covered by this scope.
+ optional<integer> line;
+ // Name of the scope such as 'Arguments', 'Locals', or 'Registers'. This
+ // string is shown in the UI as is and can be translated.
+ string name;
+ // The number of named variables in this scope.
+ // The client can use this information to present the variables in a paged UI
+ // and fetch them in chunks.
+ optional<integer> namedVariables;
+ // A hint for how to present this scope in the UI. If this attribute is
+ // missing, the scope is shown with a generic UI.
+ //
+ // May be one of the following enumeration values:
+ // 'arguments', 'locals', 'registers'
+ optional<string> presentationHint;
+ // The source for this scope.
+ optional<Source> source;
+ // The variables of this scope can be retrieved by passing the value of
+ // `variablesReference` to the `variables` request as long as execution
+ // remains suspended. See 'Lifetime of Object References' in the Overview
+ // section for details.
+ integer variablesReference;
+};
+
+DAP_DECLARE_STRUCT_TYPEINFO(Scope);
+
+// Response to `scopes` request.
+struct ScopesResponse : public Response {
+ // The scopes of the stack frame. If the array has length zero, there are no
+ // scopes available.
+ array<Scope> scopes;
+};
+
+DAP_DECLARE_STRUCT_TYPEINFO(ScopesResponse);
+
+// The request returns the variable scopes for a given stack frame ID.
+struct ScopesRequest : public Request {
+ using Response = ScopesResponse;
+ // Retrieve the scopes for the stack frame identified by `frameId`. The
+ // `frameId` must have been obtained in the current suspended state. See
+ // 'Lifetime of Object References' in the Overview section for details.
+ integer frameId;
+};
+
+DAP_DECLARE_STRUCT_TYPEINFO(ScopesRequest);
+
+// Response to `setBreakpoints` request.
+// Returned is information about each breakpoint created by this request.
+// This includes the actual code location and whether the breakpoint could be
+// verified. The breakpoints returned are in the same order as the elements of
+// the `breakpoints` (or the deprecated `lines`) array in the arguments.
+struct SetBreakpointsResponse : public Response {
+ // Information about the breakpoints.
+ // The array elements are in the same order as the elements of the
+ // `breakpoints` (or the deprecated `lines`) array in the arguments.
+ array<Breakpoint> breakpoints;
+};
+
+DAP_DECLARE_STRUCT_TYPEINFO(SetBreakpointsResponse);
+
+// Properties of a breakpoint or logpoint passed to the `setBreakpoints`
+// request.
+struct SourceBreakpoint {
+ // Start position within source line of the breakpoint or logpoint. It is
+ // measured in UTF-16 code units and the client capability `columnsStartAt1`
+ // determines whether it is 0- or 1-based.
+ optional<integer> column;
+ // The expression for conditional breakpoints.
+ // It is only honored by a debug adapter if the corresponding capability
+ // `supportsConditionalBreakpoints` is true.
+ optional<string> condition;
+ // The expression that controls how many hits of the breakpoint are ignored.
+ // The debug adapter is expected to interpret the expression as needed.
+ // The attribute is only honored by a debug adapter if the corresponding
+ // capability `supportsHitConditionalBreakpoints` is true. If both this
+ // property and `condition` are specified, `hitCondition` should be evaluated
+ // only if the `condition` is met, and the debug adapter should stop only if
+ // both conditions are met.
+ optional<string> hitCondition;
+ // The source line of the breakpoint or logpoint.
+ integer line;
+ // If this attribute exists and is non-empty, the debug adapter must not
+ // 'break' (stop) but log the message instead. Expressions within `{}` are
+ // interpolated. The attribute is only honored by a debug adapter if the
+ // corresponding capability `supportsLogPoints` is true. If either
+ // `hitCondition` or `condition` is specified, then the message should only be
+ // logged if those conditions are met.
+ optional<string> logMessage;
+};
+
+DAP_DECLARE_STRUCT_TYPEINFO(SourceBreakpoint);
+
+// Sets multiple breakpoints for a single source and clears all previous
+// breakpoints in that source. To clear all breakpoint for a source, specify an
+// empty array. When a breakpoint is hit, a `stopped` event (with reason
+// `breakpoint`) is generated.
+struct SetBreakpointsRequest : public Request {
+ using Response = SetBreakpointsResponse;
+ // The code locations of the breakpoints.
+ optional<array<SourceBreakpoint>> breakpoints;
+ // Deprecated: The code locations of the breakpoints.
+ optional<array<integer>> lines;
+ // The source location of the breakpoints; either `source.path` or
+ // `source.sourceReference` must be specified.
+ Source source;
+ // A value of true indicates that the underlying source has been modified
+ // which results in new breakpoint locations.
+ optional<boolean> sourceModified;
+};
+
+DAP_DECLARE_STRUCT_TYPEINFO(SetBreakpointsRequest);
+
+// Response to `setDataBreakpoints` request.
+// Returned is information about each breakpoint created by this request.
+struct SetDataBreakpointsResponse : public Response {
+ // Information about the data breakpoints. The array elements correspond to
+ // the elements of the input argument `breakpoints` array.
+ array<Breakpoint> breakpoints;
+};
+
+DAP_DECLARE_STRUCT_TYPEINFO(SetDataBreakpointsResponse);
+
+// Properties of a data breakpoint passed to the `setDataBreakpoints` request.
+struct DataBreakpoint {
+ // The access type of the data.
+ optional<DataBreakpointAccessType> accessType;
+ // An expression for conditional breakpoints.
+ optional<string> condition;
+ // An id representing the data. This id is returned from the
+ // `dataBreakpointInfo` request.
+ string dataId;
+ // An expression that controls how many hits of the breakpoint are ignored.
+ // The debug adapter is expected to interpret the expression as needed.
+ optional<string> hitCondition;
+};
+
+DAP_DECLARE_STRUCT_TYPEINFO(DataBreakpoint);
+
+// Replaces all existing data breakpoints with new data breakpoints.
+// To clear all data breakpoints, specify an empty array.
+// When a data breakpoint is hit, a `stopped` event (with reason `data
+// breakpoint`) is generated. Clients should only call this request if the
+// corresponding capability `supportsDataBreakpoints` is true.
+struct SetDataBreakpointsRequest : public Request {
+ using Response = SetDataBreakpointsResponse;
+ // The contents of this array replaces all existing data breakpoints. An empty
+ // array clears all data breakpoints.
+ array<DataBreakpoint> breakpoints;
+};
+
+DAP_DECLARE_STRUCT_TYPEINFO(SetDataBreakpointsRequest);
+
+// Response to `setExceptionBreakpoints` request.
+// The response contains an array of `Breakpoint` objects with information about
+// each exception breakpoint or filter. The `Breakpoint` objects are in the same
+// order as the elements of the `filters`, `filterOptions`, `exceptionOptions`
+// arrays given as arguments. If both `filters` and `filterOptions` are given,
+// the returned array must start with `filters` information first, followed by
+// `filterOptions` information. The `verified` property of a `Breakpoint` object
+// signals whether the exception breakpoint or filter could be successfully
+// created and whether the condition or hit count expressions are valid. In case
+// of an error the `message` property explains the problem. The `id` property
+// can be used to introduce a unique ID for the exception breakpoint or filter
+// so that it can be updated subsequently by sending breakpoint events. For
+// backward compatibility both the `breakpoints` array and the enclosing `body`
+// are optional. If these elements are missing a client is not able to show
+// problems for individual exception breakpoints or filters.
+struct SetExceptionBreakpointsResponse : public Response {
+ // Information about the exception breakpoints or filters.
+ // The breakpoints returned are in the same order as the elements of the
+ // `filters`, `filterOptions`, `exceptionOptions` arrays in the arguments. If
+ // both `filters` and `filterOptions` are given, the returned array must start
+ // with `filters` information first, followed by `filterOptions` information.
+ optional<array<Breakpoint>> breakpoints;
+};
+
+DAP_DECLARE_STRUCT_TYPEINFO(SetExceptionBreakpointsResponse);
+
+// An `ExceptionPathSegment` represents a segment in a path that is used to
+// match leafs or nodes in a tree of exceptions. If a segment consists of more
+// than one name, it matches the names provided if `negate` is false or missing,
+// or it matches anything except the names provided if `negate` is true.
+struct ExceptionPathSegment {
+ // Depending on the value of `negate` the names that should match or not
+ // match.
+ array<string> names;
+ // If false or missing this segment matches the names provided, otherwise it
+ // matches anything except the names provided.
+ optional<boolean> negate;
+};
+
+DAP_DECLARE_STRUCT_TYPEINFO(ExceptionPathSegment);
+
+// An `ExceptionOptions` assigns configuration options to a set of exceptions.
+struct ExceptionOptions {
+ // Condition when a thrown exception should result in a break.
+ ExceptionBreakMode breakMode = "never";
+ // A path that selects a single or multiple exceptions in a tree. If `path` is
+ // missing, the whole tree is selected. By convention the first segment of the
+ // path is a category that is used to group exceptions in the UI.
+ optional<array<ExceptionPathSegment>> path;
+};
+
+DAP_DECLARE_STRUCT_TYPEINFO(ExceptionOptions);
+
+// An `ExceptionFilterOptions` is used to specify an exception filter together
+// with a condition for the `setExceptionBreakpoints` request.
+struct ExceptionFilterOptions {
+ // An expression for conditional exceptions.
+ // The exception breaks into the debugger if the result of the condition is
+ // true.
+ optional<string> condition;
+ // ID of an exception filter returned by the `exceptionBreakpointFilters`
+ // capability.
+ string filterId;
+};
+
+DAP_DECLARE_STRUCT_TYPEINFO(ExceptionFilterOptions);
+
+// The request configures the debugger's response to thrown exceptions.
+// If an exception is configured to break, a `stopped` event is fired (with
+// reason `exception`). Clients should only call this request if the
+// corresponding capability `exceptionBreakpointFilters` returns one or more
+// filters.
+struct SetExceptionBreakpointsRequest : public Request {
+ using Response = SetExceptionBreakpointsResponse;
+ // Configuration options for selected exceptions.
+ // The attribute is only honored by a debug adapter if the corresponding
+ // capability `supportsExceptionOptions` is true.
+ optional<array<ExceptionOptions>> exceptionOptions;
+ // Set of exception filters and their options. The set of all possible
+ // exception filters is defined by the `exceptionBreakpointFilters`
+ // capability. This attribute is only honored by a debug adapter if the
+ // corresponding capability `supportsExceptionFilterOptions` is true. The
+ // `filter` and `filterOptions` sets are additive.
+ optional<array<ExceptionFilterOptions>> filterOptions;
+ // Set of exception filters specified by their ID. The set of all possible
+ // exception filters is defined by the `exceptionBreakpointFilters`
+ // capability. The `filter` and `filterOptions` sets are additive.
+ array<string> filters;
+};
+
+DAP_DECLARE_STRUCT_TYPEINFO(SetExceptionBreakpointsRequest);
+
+// Response to `setExpression` request.
+struct SetExpressionResponse : public Response {
+ // The number of indexed child variables.
+ // The client can use this information to present the variables in a paged UI
+ // and fetch them in chunks. The value should be less than or equal to
+ // 2147483647 (2^31-1).
+ optional<integer> indexedVariables;
+ // The number of named child variables.
+ // The client can use this information to present the variables in a paged UI
+ // and fetch them in chunks. The value should be less than or equal to
+ // 2147483647 (2^31-1).
+ optional<integer> namedVariables;
+ // Properties of a value that can be used to determine how to render the
+ // result in the UI.
+ optional<VariablePresentationHint> presentationHint;
+ // The type of the value.
+ // This attribute should only be returned by a debug adapter if the
+ // corresponding capability `supportsVariableType` is true.
+ optional<string> type;
+ // The new value of the expression.
+ string value;
+ // If `variablesReference` is > 0, the evaluate result is structured and its
+ // children can be retrieved by passing `variablesReference` to the
+ // `variables` request as long as execution remains suspended. See 'Lifetime
+ // of Object References' in the Overview section for details.
+ optional<integer> variablesReference;
+};
+
+DAP_DECLARE_STRUCT_TYPEINFO(SetExpressionResponse);
+
+// Evaluates the given `value` expression and assigns it to the `expression`
+// which must be a modifiable l-value. The expressions have access to any
+// variables and arguments that are in scope of the specified frame. Clients
+// should only call this request if the corresponding capability
+// `supportsSetExpression` is true. If a debug adapter implements both
+// `setExpression` and `setVariable`, a client uses `setExpression` if the
+// variable has an `evaluateName` property.
+struct SetExpressionRequest : public Request {
+ using Response = SetExpressionResponse;
+ // The l-value expression to assign to.
+ string expression;
+ // Specifies how the resulting value should be formatted.
+ optional<ValueFormat> format;
+ // Evaluate the expressions in the scope of this stack frame. If not
+ // specified, the expressions are evaluated in the global scope.
+ optional<integer> frameId;
+ // The value expression to assign to the l-value expression.
+ string value;
+};
+
+DAP_DECLARE_STRUCT_TYPEINFO(SetExpressionRequest);
+
+// Response to `setFunctionBreakpoints` request.
+// Returned is information about each breakpoint created by this request.
+struct SetFunctionBreakpointsResponse : public Response {
+ // Information about the breakpoints. The array elements correspond to the
+ // elements of the `breakpoints` array.
+ array<Breakpoint> breakpoints;
+};
+
+DAP_DECLARE_STRUCT_TYPEINFO(SetFunctionBreakpointsResponse);
+
+// Properties of a breakpoint passed to the `setFunctionBreakpoints` request.
+struct FunctionBreakpoint {
+ // An expression for conditional breakpoints.
+ // It is only honored by a debug adapter if the corresponding capability
+ // `supportsConditionalBreakpoints` is true.
+ optional<string> condition;
+ // An expression that controls how many hits of the breakpoint are ignored.
+ // The debug adapter is expected to interpret the expression as needed.
+ // The attribute is only honored by a debug adapter if the corresponding
+ // capability `supportsHitConditionalBreakpoints` is true.
+ optional<string> hitCondition;
+ // The name of the function.
+ string name;
+};
+
+DAP_DECLARE_STRUCT_TYPEINFO(FunctionBreakpoint);
+
+// Replaces all existing function breakpoints with new function breakpoints.
+// To clear all function breakpoints, specify an empty array.
+// When a function breakpoint is hit, a `stopped` event (with reason `function
+// breakpoint`) is generated. Clients should only call this request if the
+// corresponding capability `supportsFunctionBreakpoints` is true.
+struct SetFunctionBreakpointsRequest : public Request {
+ using Response = SetFunctionBreakpointsResponse;
+ // The function names of the breakpoints.
+ array<FunctionBreakpoint> breakpoints;
+};
+
+DAP_DECLARE_STRUCT_TYPEINFO(SetFunctionBreakpointsRequest);
+
+// Response to `setInstructionBreakpoints` request
+struct SetInstructionBreakpointsResponse : public Response {
+ // Information about the breakpoints. The array elements correspond to the
+ // elements of the `breakpoints` array.
+ array<Breakpoint> breakpoints;
+};
+
+DAP_DECLARE_STRUCT_TYPEINFO(SetInstructionBreakpointsResponse);
+
+// Properties of a breakpoint passed to the `setInstructionBreakpoints` request
+struct InstructionBreakpoint {
+ // An expression for conditional breakpoints.
+ // It is only honored by a debug adapter if the corresponding capability
+ // `supportsConditionalBreakpoints` is true.
+ optional<string> condition;
+ // An expression that controls how many hits of the breakpoint are ignored.
+ // The debug adapter is expected to interpret the expression as needed.
+ // The attribute is only honored by a debug adapter if the corresponding
+ // capability `supportsHitConditionalBreakpoints` is true.
+ optional<string> hitCondition;
+ // The instruction reference of the breakpoint.
+ // This should be a memory or instruction pointer reference from an
+ // `EvaluateResponse`, `Variable`, `StackFrame`, `GotoTarget`, or
+ // `Breakpoint`.
+ string instructionReference;
+ // The offset from the instruction reference.
+ // This can be negative.
+ optional<integer> offset;
+};
+
+DAP_DECLARE_STRUCT_TYPEINFO(InstructionBreakpoint);
+
+// Replaces all existing instruction breakpoints. Typically, instruction
+// breakpoints would be set from a disassembly window. To clear all instruction
+// breakpoints, specify an empty array. When an instruction breakpoint is hit, a
+// `stopped` event (with reason `instruction breakpoint`) is generated. Clients
+// should only call this request if the corresponding capability
+// `supportsInstructionBreakpoints` is true.
+struct SetInstructionBreakpointsRequest : public Request {
+ using Response = SetInstructionBreakpointsResponse;
+ // The instruction references of the breakpoints
+ array<InstructionBreakpoint> breakpoints;
+};
+
+DAP_DECLARE_STRUCT_TYPEINFO(SetInstructionBreakpointsRequest);
+
+// Response to `setVariable` request.
+struct SetVariableResponse : public Response {
+ // The number of indexed child variables.
+ // The client can use this information to present the variables in a paged UI
+ // and fetch them in chunks. The value should be less than or equal to
+ // 2147483647 (2^31-1).
+ optional<integer> indexedVariables;
+ // The number of named child variables.
+ // The client can use this information to present the variables in a paged UI
+ // and fetch them in chunks. The value should be less than or equal to
+ // 2147483647 (2^31-1).
+ optional<integer> namedVariables;
+ // The type of the new value. Typically shown in the UI when hovering over the
+ // value.
+ optional<string> type;
+ // The new value of the variable.
+ string value;
+ // If `variablesReference` is > 0, the new value is structured and its
+ // children can be retrieved by passing `variablesReference` to the
+ // `variables` request as long as execution remains suspended. See 'Lifetime
+ // of Object References' in the Overview section for details.
+ optional<integer> variablesReference;
+};
+
+DAP_DECLARE_STRUCT_TYPEINFO(SetVariableResponse);
+
+// Set the variable with the given name in the variable container to a new
+// value. Clients should only call this request if the corresponding capability
+// `supportsSetVariable` is true. If a debug adapter implements both
+// `setVariable` and `setExpression`, a client will only use `setExpression` if
+// the variable has an `evaluateName` property.
+struct SetVariableRequest : public Request {
+ using Response = SetVariableResponse;
+ // Specifies details on how to format the response value.
+ optional<ValueFormat> format;
+ // The name of the variable in the container.
+ string name;
+ // The value of the variable.
+ string value;
+ // The reference of the variable container. The `variablesReference` must have
+ // been obtained in the current suspended state. See 'Lifetime of Object
+ // References' in the Overview section for details.
+ integer variablesReference;
+};
+
+DAP_DECLARE_STRUCT_TYPEINFO(SetVariableRequest);
+
+// Response to `source` request.
+struct SourceResponse : public Response {
+ // Content of the source reference.
+ string content;
+ // Content type (MIME type) of the source.
+ optional<string> mimeType;
+};
+
+DAP_DECLARE_STRUCT_TYPEINFO(SourceResponse);
+
+// The request retrieves the source code for a given source reference.
+struct SourceRequest : public Request {
+ using Response = SourceResponse;
+ // Specifies the source content to load. Either `source.path` or
+ // `source.sourceReference` must be specified.
+ optional<Source> source;
+ // The reference to the source. This is the same as `source.sourceReference`.
+ // This is provided for backward compatibility since old clients do not
+ // understand the `source` attribute.
+ integer sourceReference;
+};
+
+DAP_DECLARE_STRUCT_TYPEINFO(SourceRequest);
+
+// A Stackframe contains the source location.
+struct StackFrame {
+ // Indicates whether this frame can be restarted with the `restart` request.
+ // Clients should only use this if the debug adapter supports the `restart`
+ // request and the corresponding capability `supportsRestartRequest` is true.
+ // If a debug adapter has this capability, then `canRestart` defaults to
+ // `true` if the property is absent.
+ optional<boolean> canRestart;
+ // Start position of the range covered by the stack frame. It is measured in
+ // UTF-16 code units and the client capability `columnsStartAt1` determines
+ // whether it is 0- or 1-based. If attribute `source` is missing or doesn't
+ // exist, `column` is 0 and should be ignored by the client.
+ integer column;
+ // End position of the range covered by the stack frame. It is measured in
+ // UTF-16 code units and the client capability `columnsStartAt1` determines
+ // whether it is 0- or 1-based.
+ optional<integer> endColumn;
+ // The end line of the range covered by the stack frame.
+ optional<integer> endLine;
+ // An identifier for the stack frame. It must be unique across all threads.
+ // This id can be used to retrieve the scopes of the frame with the `scopes`
+ // request or to restart the execution of a stack frame.
+ integer id;
+ // A memory reference for the current instruction pointer in this frame.
+ optional<string> instructionPointerReference;
+ // The line within the source of the frame. If the source attribute is missing
+ // or doesn't exist, `line` is 0 and should be ignored by the client.
+ integer line;
+ // The module associated with this frame, if any.
+ optional<variant<integer, string>> moduleId;
+ // The name of the stack frame, typically a method name.
+ string name;
+ // A hint for how to present this frame in the UI.
+ // A value of `label` can be used to indicate that the frame is an artificial
+ // frame that is used as a visual label or separator. A value of `subtle` can
+ // be used to change the appearance of a frame in a 'subtle' way.
+ //
+ // Must be one of the following enumeration values:
+ // 'normal', 'label', 'subtle'
+ optional<string> presentationHint;
+ // The source of the frame.
+ optional<Source> source;
+};
+
+DAP_DECLARE_STRUCT_TYPEINFO(StackFrame);
+
+// Response to `stackTrace` request.
+struct StackTraceResponse : public Response {
+ // The frames of the stack frame. If the array has length zero, there are no
+ // stack frames available. This means that there is no location information
+ // available.
+ array<StackFrame> stackFrames;
+ // The total number of frames available in the stack. If omitted or if
+ // `totalFrames` is larger than the available frames, a client is expected to
+ // request frames until a request returns less frames than requested (which
+ // indicates the end of the stack). Returning monotonically increasing
+ // `totalFrames` values for subsequent requests can be used to enforce paging
+ // in the client.
+ optional<integer> totalFrames;
+};
+
+DAP_DECLARE_STRUCT_TYPEINFO(StackTraceResponse);
+
+// Provides formatting information for a stack frame.
+struct StackFrameFormat : public ValueFormat {
+ // Includes all stack frames, including those the debug adapter might
+ // otherwise hide.
+ optional<boolean> includeAll;
+ // Displays the line number of the stack frame.
+ optional<boolean> line;
+ // Displays the module of the stack frame.
+ optional<boolean> module;
+ // Displays the names of parameters for the stack frame.
+ optional<boolean> parameterNames;
+ // Displays the types of parameters for the stack frame.
+ optional<boolean> parameterTypes;
+ // Displays the values of parameters for the stack frame.
+ optional<boolean> parameterValues;
+ // Displays parameters for the stack frame.
+ optional<boolean> parameters;
+};
+
+DAP_DECLARE_STRUCT_TYPEINFO(StackFrameFormat);
+
+// The request returns a stacktrace from the current execution state of a given
+// thread. A client can request all stack frames by omitting the startFrame and
+// levels arguments. For performance-conscious clients and if the corresponding
+// capability `supportsDelayedStackTraceLoading` is true, stack frames can be
+// retrieved in a piecemeal way with the `startFrame` and `levels` arguments.
+// The response of the `stackTrace` request may contain a `totalFrames` property
+// that hints at the total number of frames in the stack. If a client needs this
+// total number upfront, it can issue a request for a single (first) frame and
+// depending on the value of `totalFrames` decide how to proceed. In any case a
+// client should be prepared to receive fewer frames than requested, which is an
+// indication that the end of the stack has been reached.
+struct StackTraceRequest : public Request {
+ using Response = StackTraceResponse;
+ // Specifies details on how to format the stack frames.
+ // The attribute is only honored by a debug adapter if the corresponding
+ // capability `supportsValueFormattingOptions` is true.
+ optional<StackFrameFormat> format;
+ // The maximum number of frames to return. If levels is not specified or 0,
+ // all frames are returned.
+ optional<integer> levels;
+ // The index of the first frame to return; if omitted frames start at 0.
+ optional<integer> startFrame;
+ // Retrieve the stacktrace for this thread.
+ integer threadId;
+};
+
+DAP_DECLARE_STRUCT_TYPEINFO(StackTraceRequest);
+
+// Response to `startDebugging` request. This is just an acknowledgement, so no
+// body field is required.
+struct StartDebuggingResponse : public Response {};
+
+DAP_DECLARE_STRUCT_TYPEINFO(StartDebuggingResponse);
+
+// This request is sent from the debug adapter to the client to start a new
+// debug session of the same type as the caller. This request should only be
+// sent if the corresponding client capability `supportsStartDebuggingRequest`
+// is true. A client implementation of `startDebugging` should start a new debug
+// session (of the same type as the caller) in the same way that the caller's
+// session was started. If the client supports hierarchical debug sessions, the
+// newly created session can be treated as a child of the caller session.
+struct StartDebuggingRequest : public Request {
+ using Response = StartDebuggingResponse;
+ // Arguments passed to the new debug session. The arguments must only contain
+ // properties understood by the `launch` or `attach` requests of the debug
+ // adapter and they must not contain any client-specific properties (e.g.
+ // `type`) or client-specific features (e.g. substitutable 'variables').
+ object configuration;
+ // Indicates whether the new debug session should be started with a `launch`
+ // or `attach` request.
+ //
+ // Must be one of the following enumeration values:
+ // 'launch', 'attach'
+ string request = "launch";
+};
+
+DAP_DECLARE_STRUCT_TYPEINFO(StartDebuggingRequest);
+
+// Response to `stepBack` request. This is just an acknowledgement, so no body
+// field is required.
+struct StepBackResponse : public Response {};
+
+DAP_DECLARE_STRUCT_TYPEINFO(StepBackResponse);
+
+// The request executes one backward step (in the given granularity) for the
+// specified thread and allows all other threads to run backward freely by
+// resuming them. If the debug adapter supports single thread execution (see
+// capability `supportsSingleThreadExecutionRequests`), setting the
+// `singleThread` argument to true prevents other suspended threads from
+// resuming. The debug adapter first sends the response and then a `stopped`
+// event (with reason `step`) after the step has completed. Clients should only
+// call this request if the corresponding capability `supportsStepBack` is true.
+struct StepBackRequest : public Request {
+ using Response = StepBackResponse;
+ // Stepping granularity to step. If no granularity is specified, a granularity
+ // of `statement` is assumed.
+ optional<SteppingGranularity> granularity;
+ // If this flag is true, all other suspended threads are not resumed.
+ optional<boolean> singleThread;
+ // Specifies the thread for which to resume execution for one step backwards
+ // (of the given granularity).
+ integer threadId;
+};
+
+DAP_DECLARE_STRUCT_TYPEINFO(StepBackRequest);
+
+// Response to `stepIn` request. This is just an acknowledgement, so no body
+// field is required.
+struct StepInResponse : public Response {};
+
+DAP_DECLARE_STRUCT_TYPEINFO(StepInResponse);
+
+// The request resumes the given thread to step into a function/method and
+// allows all other threads to run freely by resuming them. If the debug adapter
+// supports single thread execution (see capability
+// `supportsSingleThreadExecutionRequests`), setting the `singleThread` argument
+// to true prevents other suspended threads from resuming. If the request cannot
+// step into a target, `stepIn` behaves like the `next` request. The debug
+// adapter first sends the response and then a `stopped` event (with reason
+// `step`) after the step has completed. If there are multiple function/method
+// calls (or other targets) on the source line, the argument `targetId` can be
+// used to control into which target the `stepIn` should occur. The list of
+// possible targets for a given source line can be retrieved via the
+// `stepInTargets` request.
+struct StepInRequest : public Request {
+ using Response = StepInResponse;
+ // Stepping granularity. If no granularity is specified, a granularity of
+ // `statement` is assumed.
+ optional<SteppingGranularity> granularity;
+ // If this flag is true, all other suspended threads are not resumed.
+ optional<boolean> singleThread;
+ // Id of the target to step into.
+ optional<integer> targetId;
+ // Specifies the thread for which to resume execution for one step-into (of
+ // the given granularity).
+ integer threadId;
+};
+
+DAP_DECLARE_STRUCT_TYPEINFO(StepInRequest);
+
+// A `StepInTarget` can be used in the `stepIn` request and determines into
+// which single target the `stepIn` request should step.
+struct StepInTarget {
+ // Start position of the range covered by the step in target. It is measured
+ // in UTF-16 code units and the client capability `columnsStartAt1` determines
+ // whether it is 0- or 1-based.
+ optional<integer> column;
+ // End position of the range covered by the step in target. It is measured in
+ // UTF-16 code units and the client capability `columnsStartAt1` determines
+ // whether it is 0- or 1-based.
+ optional<integer> endColumn;
+ // The end line of the range covered by the step-in target.
+ optional<integer> endLine;
+ // Unique identifier for a step-in target.
+ integer id;
+ // The name of the step-in target (shown in the UI).
+ string label;
+ // The line of the step-in target.
+ optional<integer> line;
+};
+
+DAP_DECLARE_STRUCT_TYPEINFO(StepInTarget);
+
+// Response to `stepInTargets` request.
+struct StepInTargetsResponse : public Response {
+ // The possible step-in targets of the specified source location.
+ array<StepInTarget> targets;
+};
+
+DAP_DECLARE_STRUCT_TYPEINFO(StepInTargetsResponse);
+
+// This request retrieves the possible step-in targets for the specified stack
+// frame. These targets can be used in the `stepIn` request. Clients should only
+// call this request if the corresponding capability
+// `supportsStepInTargetsRequest` is true.
+struct StepInTargetsRequest : public Request {
+ using Response = StepInTargetsResponse;
+ // The stack frame for which to retrieve the possible step-in targets.
+ integer frameId;
+};
+
+DAP_DECLARE_STRUCT_TYPEINFO(StepInTargetsRequest);
+
+// Response to `stepOut` request. This is just an acknowledgement, so no body
+// field is required.
+struct StepOutResponse : public Response {};
+
+DAP_DECLARE_STRUCT_TYPEINFO(StepOutResponse);
+
+// The request resumes the given thread to step out (return) from a
+// function/method and allows all other threads to run freely by resuming them.
+// If the debug adapter supports single thread execution (see capability
+// `supportsSingleThreadExecutionRequests`), setting the `singleThread` argument
+// to true prevents other suspended threads from resuming. The debug adapter
+// first sends the response and then a `stopped` event (with reason `step`)
+// after the step has completed.
+struct StepOutRequest : public Request {
+ using Response = StepOutResponse;
+ // Stepping granularity. If no granularity is specified, a granularity of
+ // `statement` is assumed.
+ optional<SteppingGranularity> granularity;
+ // If this flag is true, all other suspended threads are not resumed.
+ optional<boolean> singleThread;
+ // Specifies the thread for which to resume execution for one step-out (of the
+ // given granularity).
+ integer threadId;
+};
+
+DAP_DECLARE_STRUCT_TYPEINFO(StepOutRequest);
+
+// The event indicates that the execution of the debuggee has stopped due to
+// some condition. This can be caused by a breakpoint previously set, a stepping
+// request has completed, by executing a debugger statement etc.
+struct StoppedEvent : public Event {
+ // If `allThreadsStopped` is true, a debug adapter can announce that all
+ // threads have stopped.
+ // - The client should use this information to enable that all threads can be
+ // expanded to access their stacktraces.
+ // - If the attribute is missing or false, only the thread with the given
+ // `threadId` can be expanded.
+ optional<boolean> allThreadsStopped;
+ // The full reason for the event, e.g. 'Paused on exception'. This string is
+ // shown in the UI as is and can be translated.
+ optional<string> description;
+ // Ids of the breakpoints that triggered the event. In most cases there is
+ // only a single breakpoint but here are some examples for multiple
+ // breakpoints:
+ // - Different types of breakpoints map to the same location.
+ // - Multiple source breakpoints get collapsed to the same instruction by the
+ // compiler/runtime.
+ // - Multiple function breakpoints with different function names map to the
+ // same location.
+ optional<array<integer>> hitBreakpointIds;
+ // A value of true hints to the client that this event should not change the
+ // focus.
+ optional<boolean> preserveFocusHint;
+ // The reason for the event.
+ // For backward compatibility this string is shown in the UI if the
+ // `description` attribute is missing (but it must not be translated).
+ //
+ // May be one of the following enumeration values:
+ // 'step', 'breakpoint', 'exception', 'pause', 'entry', 'goto', 'function
+ // breakpoint', 'data breakpoint', 'instruction breakpoint'
+ string reason;
+ // Additional information. E.g. if reason is `exception`, text contains the
+ // exception name. This string is shown in the UI.
+ optional<string> text;
+ // The thread which was stopped.
+ optional<integer> threadId;
+};
+
+DAP_DECLARE_STRUCT_TYPEINFO(StoppedEvent);
+
+// Response to `terminate` request. This is just an acknowledgement, so no body
+// field is required.
+struct TerminateResponse : public Response {};
+
+DAP_DECLARE_STRUCT_TYPEINFO(TerminateResponse);
+
+// The `terminate` request is sent from the client to the debug adapter in order
+// to shut down the debuggee gracefully. Clients should only call this request
+// if the capability `supportsTerminateRequest` is true. Typically a debug
+// adapter implements `terminate` by sending a software signal which the
+// debuggee intercepts in order to clean things up properly before terminating
+// itself. Please note that this request does not directly affect the state of
+// the debug session: if the debuggee decides to veto the graceful shutdown for
+// any reason by not terminating itself, then the debug session just continues.
+// Clients can surface the `terminate` request as an explicit command or they
+// can integrate it into a two stage Stop command that first sends `terminate`
+// to request a graceful shutdown, and if that fails uses `disconnect` for a
+// forceful shutdown.
+struct TerminateRequest : public Request {
+ using Response = TerminateResponse;
+ // A value of true indicates that this `terminate` request is part of a
+ // restart sequence.
+ optional<boolean> restart;
+};
+
+DAP_DECLARE_STRUCT_TYPEINFO(TerminateRequest);
+
+// Response to `terminateThreads` request. This is just an acknowledgement, no
+// body field is required.
+struct TerminateThreadsResponse : public Response {};
+
+DAP_DECLARE_STRUCT_TYPEINFO(TerminateThreadsResponse);
+
+// The request terminates the threads with the given ids.
+// Clients should only call this request if the corresponding capability
+// `supportsTerminateThreadsRequest` is true.
+struct TerminateThreadsRequest : public Request {
+ using Response = TerminateThreadsResponse;
+ // Ids of threads to be terminated.
+ optional<array<integer>> threadIds;
+};
+
+DAP_DECLARE_STRUCT_TYPEINFO(TerminateThreadsRequest);
+
+// The event indicates that debugging of the debuggee has terminated. This does
+// **not** mean that the debuggee itself has exited.
+struct TerminatedEvent : public Event {
+ // A debug adapter may set `restart` to true (or to an arbitrary object) to
+ // request that the client restarts the session. The value is not interpreted
+ // by the client and passed unmodified as an attribute `__restart` to the
+ // `launch` and `attach` requests.
+ optional<variant<array<any>, boolean, integer, null, number, object, string>>
+ restart;
+};
+
+DAP_DECLARE_STRUCT_TYPEINFO(TerminatedEvent);
+
+// The event indicates that a thread has started or exited.
+struct ThreadEvent : public Event {
+ // The reason for the event.
+ //
+ // May be one of the following enumeration values:
+ // 'started', 'exited'
+ string reason;
+ // The identifier of the thread.
+ integer threadId;
+};
+
+DAP_DECLARE_STRUCT_TYPEINFO(ThreadEvent);
+
+// A Thread
+struct Thread {
+ // Unique identifier for the thread.
+ integer id;
+ // The name of the thread.
+ string name;
+};
+
+DAP_DECLARE_STRUCT_TYPEINFO(Thread);
+
+// Response to `threads` request.
+struct ThreadsResponse : public Response {
+ // All threads.
+ array<Thread> threads;
+};
+
+DAP_DECLARE_STRUCT_TYPEINFO(ThreadsResponse);
+
+// The request retrieves a list of all threads.
+struct ThreadsRequest : public Request {
+ using Response = ThreadsResponse;
+};
+
+DAP_DECLARE_STRUCT_TYPEINFO(ThreadsRequest);
+
+// A Variable is a name/value pair.
+// The `type` attribute is shown if space permits or when hovering over the
+// variable's name. The `kind` attribute is used to render additional properties
+// of the variable, e.g. different icons can be used to indicate that a variable
+// is public or private. If the value is structured (has children), a handle is
+// provided to retrieve the children with the `variables` request. If the number
+// of named or indexed children is large, the numbers should be returned via the
+// `namedVariables` and `indexedVariables` attributes. The client can use this
+// information to present the children in a paged UI and fetch them in chunks.
+struct Variable {
+ // The evaluatable name of this variable which can be passed to the `evaluate`
+ // request to fetch the variable's value.
+ optional<string> evaluateName;
+ // The number of indexed child variables.
+ // The client can use this information to present the children in a paged UI
+ // and fetch them in chunks.
+ optional<integer> indexedVariables;
+ // The memory reference for the variable if the variable represents executable
+ // code, such as a function pointer. This attribute is only required if the
+ // corresponding capability `supportsMemoryReferences` is true.
+ optional<string> memoryReference;
+ // The variable's name.
+ string name;
+ // The number of named child variables.
+ // The client can use this information to present the children in a paged UI
+ // and fetch them in chunks.
+ optional<integer> namedVariables;
+ // Properties of a variable that can be used to determine how to render the
+ // variable in the UI.
+ optional<VariablePresentationHint> presentationHint;
+ // The type of the variable's value. Typically shown in the UI when hovering
+ // over the value. This attribute should only be returned by a debug adapter
+ // if the corresponding capability `supportsVariableType` is true.
+ optional<string> type;
+ // The variable's value.
+ // This can be a multi-line text, e.g. for a function the body of a function.
+ // For structured variables (which do not have a simple value), it is
+ // recommended to provide a one-line representation of the structured object.
+ // This helps to identify the structured object in the collapsed state when
+ // its children are not yet visible. An empty string can be used if no value
+ // should be shown in the UI.
+ string value;
+ // If `variablesReference` is > 0, the variable is structured and its children
+ // can be retrieved by passing `variablesReference` to the `variables` request
+ // as long as execution remains suspended. See 'Lifetime of Object References'
+ // in the Overview section for details.
+ integer variablesReference;
+};
+
+DAP_DECLARE_STRUCT_TYPEINFO(Variable);
+
+// Response to `variables` request.
+struct VariablesResponse : public Response {
+ // All (or a range) of variables for the given variable reference.
+ array<Variable> variables;
+};
+
+DAP_DECLARE_STRUCT_TYPEINFO(VariablesResponse);
+
+// Retrieves all child variables for the given variable reference.
+// A filter can be used to limit the fetched children to either named or indexed
+// children.
+struct VariablesRequest : public Request {
+ using Response = VariablesResponse;
+ // The number of variables to return. If count is missing or 0, all variables
+ // are returned.
+ optional<integer> count;
+ // Filter to limit the child variables to either named or indexed. If omitted,
+ // both types are fetched.
+ //
+ // Must be one of the following enumeration values:
+ // 'indexed', 'named'
+ optional<string> filter;
+ // Specifies details on how to format the Variable values.
+ // The attribute is only honored by a debug adapter if the corresponding
+ // capability `supportsValueFormattingOptions` is true.
+ optional<ValueFormat> format;
+ // The index of the first variable to return; if omitted children start at 0.
+ optional<integer> start;
+ // The variable for which to retrieve its children. The `variablesReference`
+ // must have been obtained in the current suspended state. See 'Lifetime of
+ // Object References' in the Overview section for details.
+ integer variablesReference;
+};
+
+DAP_DECLARE_STRUCT_TYPEINFO(VariablesRequest);
+
+// Response to `writeMemory` request.
+struct WriteMemoryResponse : public Response {
+ // Property that should be returned when `allowPartial` is true to indicate
+ // the number of bytes starting from address that were successfully written.
+ optional<integer> bytesWritten;
+ // Property that should be returned when `allowPartial` is true to indicate
+ // the offset of the first byte of data successfully written. Can be negative.
+ optional<integer> offset;
+};
+
+DAP_DECLARE_STRUCT_TYPEINFO(WriteMemoryResponse);
+
+// Writes bytes to memory at the provided location.
+// Clients should only call this request if the corresponding capability
+// `supportsWriteMemoryRequest` is true.
+struct WriteMemoryRequest : public Request {
+ using Response = WriteMemoryResponse;
+ // Property to control partial writes. If true, the debug adapter should
+ // attempt to write memory even if the entire memory region is not writable.
+ // In such a case the debug adapter should stop after hitting the first byte
+ // of memory that cannot be written and return the number of bytes written in
+ // the response via the `offset` and `bytesWritten` properties. If false or
+ // missing, a debug adapter should attempt to verify the region is writable
+ // before writing, and fail the response if it is not.
+ optional<boolean> allowPartial;
+ // Bytes to write, encoded using base64.
+ string data;
+ // Memory reference to the base location to which data should be written.
+ string memoryReference;
+ // Offset (in bytes) to be applied to the reference location before writing
+ // data. Can be negative.
+ optional<integer> offset;
+};
+
+DAP_DECLARE_STRUCT_TYPEINFO(WriteMemoryRequest);
+
+} // namespace dap
+
+#endif // dap_protocol_h
diff --git a/Utilities/cmcppdap/include/dap/serialization.h b/Utilities/cmcppdap/include/dap/serialization.h
new file mode 100644
index 0000000..c7d4c5e
--- /dev/null
+++ b/Utilities/cmcppdap/include/dap/serialization.h
@@ -0,0 +1,253 @@
+// Copyright 2019 Google LLC
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// https://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#ifndef dap_serialization_h
+#define dap_serialization_h
+
+#include "typeof.h"
+#include "types.h"
+
+#include <cstddef> // ptrdiff_t
+#include <type_traits>
+
+namespace dap {
+
+// Field describes a single field of a struct.
+struct Field {
+ std::string name; // name of the field
+ ptrdiff_t offset; // offset of the field to the base of the struct
+ const TypeInfo* type; // type of the field
+};
+
+////////////////////////////////////////////////////////////////////////////////
+// Deserializer
+////////////////////////////////////////////////////////////////////////////////
+
+// Deserializer is the interface used to decode data from structured storage.
+// Methods that return a bool use this to indicate success.
+class Deserializer {
+ public:
+ virtual ~Deserializer() = default;
+
+ // deserialization methods for simple data types.
+ // If the stored object is not of the correct type, then these function will
+ // return false.
+ virtual bool deserialize(boolean*) const = 0;
+ virtual bool deserialize(integer*) const = 0;
+ virtual bool deserialize(number*) const = 0;
+ virtual bool deserialize(string*) const = 0;
+ virtual bool deserialize(object*) const = 0;
+ virtual bool deserialize(any*) const = 0;
+
+ // count() returns the number of elements in the array object referenced by
+ // this Deserializer.
+ virtual size_t count() const = 0;
+
+ // array() calls the provided std::function for deserializing each array
+ // element in the array object referenced by this Deserializer.
+ virtual bool array(const std::function<bool(Deserializer*)>&) const = 0;
+
+ // field() calls the provided std::function for deserializing the field with
+ // the given name from the struct object referenced by this Deserializer.
+ virtual bool field(const std::string& name,
+ const std::function<bool(Deserializer*)>&) const = 0;
+
+ // deserialize() delegates to TypeOf<T>::type()->deserialize().
+ template <typename T,
+ typename = std::enable_if<TypeOf<T>::has_custom_serialization>>
+ inline bool deserialize(T*) const;
+
+ // deserialize() decodes an array.
+ template <typename T>
+ inline bool deserialize(dap::array<T>*) const;
+
+ // deserialize() decodes an optional.
+ template <typename T>
+ inline bool deserialize(dap::optional<T>*) const;
+
+ // deserialize() decodes an variant.
+ template <typename T0, typename... Types>
+ inline bool deserialize(dap::variant<T0, Types...>*) const;
+
+ // deserialize() decodes the struct field f with the given name.
+ template <typename T>
+ inline bool field(const std::string& name, T* f) const;
+};
+
+template <typename T, typename>
+bool Deserializer::deserialize(T* ptr) const {
+ return TypeOf<T>::type()->deserialize(this, ptr);
+}
+
+template <typename T>
+bool Deserializer::deserialize(dap::array<T>* vec) const {
+ auto n = count();
+ vec->resize(n);
+ size_t i = 0;
+ if (!array([&](Deserializer* d) { return d->deserialize(&(*vec)[i++]); })) {
+ return false;
+ }
+ return true;
+}
+
+template <typename T>
+bool Deserializer::deserialize(dap::optional<T>* opt) const {
+ T v;
+ if (deserialize(&v)) {
+ *opt = v;
+ }
+ return true;
+}
+
+template <typename T0, typename... Types>
+bool Deserializer::deserialize(dap::variant<T0, Types...>* var) const {
+ return deserialize(&var->value);
+}
+
+template <typename T>
+bool Deserializer::field(const std::string& name, T* v) const {
+ return this->field(name,
+ [&](const Deserializer* d) { return d->deserialize(v); });
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// Serializer
+////////////////////////////////////////////////////////////////////////////////
+class FieldSerializer;
+
+// Serializer is the interface used to encode data to structured storage.
+// A Serializer is associated with a single storage object, whos type and value
+// is assigned by a call to serialize().
+// If serialize() is called multiple times on the same Serializer instance,
+// the last type and value is stored.
+// Methods that return a bool use this to indicate success.
+class Serializer {
+ public:
+ virtual ~Serializer() = default;
+
+ // serialization methods for simple data types.
+ virtual bool serialize(boolean) = 0;
+ virtual bool serialize(integer) = 0;
+ virtual bool serialize(number) = 0;
+ virtual bool serialize(const string&) = 0;
+ virtual bool serialize(const dap::object&) = 0;
+ virtual bool serialize(const any&) = 0;
+
+ // array() encodes count array elements to the array object referenced by this
+ // Serializer. The std::function will be called count times, each time with a
+ // Serializer that should be used to encode the n'th array element's data.
+ virtual bool array(size_t count, const std::function<bool(Serializer*)>&) = 0;
+
+ // object() begins encoding the object referenced by this Serializer.
+ // The std::function will be called with a FieldSerializer to serialize the
+ // object's fields.
+ virtual bool object(const std::function<bool(dap::FieldSerializer*)>&) = 0;
+
+ // remove() deletes the object referenced by this Serializer.
+ // remove() can be used to serialize optionals with no value assigned.
+ virtual void remove() = 0;
+
+ // serialize() delegates to TypeOf<T>::type()->serialize().
+ template <typename T,
+ typename = std::enable_if<TypeOf<T>::has_custom_serialization>>
+ inline bool serialize(const T&);
+
+ // serialize() encodes the given array.
+ template <typename T>
+ inline bool serialize(const dap::array<T>&);
+
+ // serialize() encodes the given optional.
+ template <typename T>
+ inline bool serialize(const dap::optional<T>& v);
+
+ // serialize() encodes the given variant.
+ template <typename T0, typename... Types>
+ inline bool serialize(const dap::variant<T0, Types...>&);
+
+ // deserialize() encodes the given string.
+ inline bool serialize(const char* v);
+ protected:
+ static inline const TypeInfo* get_any_type(const any&);
+ static inline const void* get_any_val(const any&);
+};
+
+inline const TypeInfo* Serializer::get_any_type(const any& a){
+ return a.type;
+}
+const void* Serializer::get_any_val(const any& a) {
+ return a.value;
+}
+
+template <typename T, typename>
+bool Serializer::serialize(const T& object) {
+ return TypeOf<T>::type()->serialize(this, &object);
+}
+
+template <typename T>
+bool Serializer::serialize(const dap::array<T>& vec) {
+ auto it = vec.begin();
+ return array(vec.size(), [&](Serializer* s) { return s->serialize(*it++); });
+}
+
+template <typename T>
+bool Serializer::serialize(const dap::optional<T>& opt) {
+ if (!opt.has_value()) {
+ remove();
+ return true;
+ }
+ return serialize(opt.value());
+}
+
+template <typename T0, typename... Types>
+bool Serializer::serialize(const dap::variant<T0, Types...>& var) {
+ return serialize(var.value);
+}
+
+bool Serializer::serialize(const char* v) {
+ return serialize(std::string(v));
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// FieldSerializer
+////////////////////////////////////////////////////////////////////////////////
+
+// FieldSerializer is the interface used to serialize fields of an object.
+class FieldSerializer {
+ public:
+ using SerializeFunc = std::function<bool(Serializer*)>;
+ template <typename T>
+ using IsSerializeFunc = std::is_convertible<T, SerializeFunc>;
+
+ virtual ~FieldSerializer() = default;
+
+ // field() encodes a field to the struct object referenced by this Serializer.
+ // The SerializeFunc will be called with a Serializer used to encode the
+ // field's data.
+ virtual bool field(const std::string& name, const SerializeFunc&) = 0;
+
+ // field() encodes the field with the given name and value.
+ template <
+ typename T,
+ typename = typename std::enable_if<!IsSerializeFunc<T>::value>::type>
+ inline bool field(const std::string& name, const T& v);
+};
+
+template <typename T, typename>
+bool FieldSerializer::field(const std::string& name, const T& v) {
+ return this->field(name, [&](Serializer* s) { return s->serialize(v); });
+}
+
+} // namespace dap
+
+#endif // dap_serialization_h
diff --git a/Utilities/cmcppdap/include/dap/session.h b/Utilities/cmcppdap/include/dap/session.h
new file mode 100644
index 0000000..3933886
--- /dev/null
+++ b/Utilities/cmcppdap/include/dap/session.h
@@ -0,0 +1,449 @@
+// Copyright 2019 Google LLC
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// https://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#ifndef dap_session_h
+#define dap_session_h
+
+#include "future.h"
+#include "io.h"
+#include "traits.h"
+#include "typeinfo.h"
+#include "typeof.h"
+
+#include <functional>
+
+namespace dap {
+
+// Forward declarations
+struct Request;
+struct Response;
+struct Event;
+
+////////////////////////////////////////////////////////////////////////////////
+// Error
+////////////////////////////////////////////////////////////////////////////////
+
+// Error represents an error message in response to a DAP request.
+struct Error {
+ Error() = default;
+ Error(const std::string& error);
+ Error(const char* msg, ...);
+
+ // operator bool() returns true if there is an error.
+ inline operator bool() const { return message.size() > 0; }
+
+ std::string message; // empty represents success.
+};
+
+////////////////////////////////////////////////////////////////////////////////
+// ResponseOrError<T>
+////////////////////////////////////////////////////////////////////////////////
+
+// ResponseOrError holds either the response to a DAP request or an error
+// message.
+template <typename T>
+struct ResponseOrError {
+ using Request = T;
+
+ inline ResponseOrError() = default;
+ inline ResponseOrError(const T& response);
+ inline ResponseOrError(T&& response);
+ inline ResponseOrError(const Error& error);
+ inline ResponseOrError(Error&& error);
+ inline ResponseOrError(const ResponseOrError& other);
+ inline ResponseOrError(ResponseOrError&& other);
+
+ inline ResponseOrError& operator=(const ResponseOrError& other);
+ inline ResponseOrError& operator=(ResponseOrError&& other);
+
+ T response;
+ Error error; // empty represents success.
+};
+
+template <typename T>
+ResponseOrError<T>::ResponseOrError(const T& resp) : response(resp) {}
+template <typename T>
+ResponseOrError<T>::ResponseOrError(T&& resp) : response(std::move(resp)) {}
+template <typename T>
+ResponseOrError<T>::ResponseOrError(const Error& err) : error(err) {}
+template <typename T>
+ResponseOrError<T>::ResponseOrError(Error&& err) : error(std::move(err)) {}
+template <typename T>
+ResponseOrError<T>::ResponseOrError(const ResponseOrError& other)
+ : response(other.response), error(other.error) {}
+template <typename T>
+ResponseOrError<T>::ResponseOrError(ResponseOrError&& other)
+ : response(std::move(other.response)), error(std::move(other.error)) {}
+template <typename T>
+ResponseOrError<T>& ResponseOrError<T>::operator=(
+ const ResponseOrError& other) {
+ response = other.response;
+ error = other.error;
+ return *this;
+}
+template <typename T>
+ResponseOrError<T>& ResponseOrError<T>::operator=(ResponseOrError&& other) {
+ response = std::move(other.response);
+ error = std::move(other.error);
+ return *this;
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// Session
+////////////////////////////////////////////////////////////////////////////////
+
+// Session implements a DAP client or server endpoint.
+// The general usage is as follows:
+// (1) Create a session with Session::create().
+// (2) Register request and event handlers with registerHandler().
+// (3) Optionally register a protocol error handler with onError().
+// (3) Bind the session to the remote endpoint with bind().
+// (4) Send requests or events with send().
+class Session {
+ template <typename F, int N>
+ using ParamType = traits::ParameterType<F, N>;
+
+ template <typename T>
+ using IsRequest = traits::EnableIfIsType<dap::Request, T>;
+
+ template <typename T>
+ using IsEvent = traits::EnableIfIsType<dap::Event, T>;
+
+ template <typename F>
+ using IsRequestHandlerWithoutCallback = traits::EnableIf<
+ traits::CompatibleWith<F, std::function<void(dap::Request)>>::value>;
+
+ template <typename F, typename CallbackType>
+ using IsRequestHandlerWithCallback = traits::EnableIf<traits::CompatibleWith<
+ F,
+ std::function<void(dap::Request, std::function<void(CallbackType)>)>>::
+ value>;
+
+ public:
+ virtual ~Session();
+
+ // ErrorHandler is the type of callback function used for reporting protocol
+ // errors.
+ using ErrorHandler = std::function<void(const char*)>;
+
+ // ClosedHandler is the type of callback function used to signal that a
+ // connected endpoint has closed.
+ using ClosedHandler = std::function<void()>;
+
+ // create() constructs and returns a new Session.
+ static std::unique_ptr<Session> create();
+
+ // onError() registers a error handler that will be called whenever a protocol
+ // error is encountered.
+ // Only one error handler can be bound at any given time, and later calls
+ // will replace the existing error handler.
+ virtual void onError(const ErrorHandler&) = 0;
+
+ // registerHandler() registers a request handler for a specific request type.
+ // The function F must have one of the following signatures:
+ // ResponseOrError<ResponseType>(const RequestType&)
+ // ResponseType(const RequestType&)
+ // Error(const RequestType&)
+ template <typename F, typename RequestType = ParamType<F, 0>>
+ inline IsRequestHandlerWithoutCallback<F> registerHandler(F&& handler);
+
+ // registerHandler() registers a request handler for a specific request type.
+ // The handler has a response callback function for the second argument of the
+ // handler function. This callback may be called after the handler has
+ // returned.
+ // The function F must have the following signature:
+ // void(const RequestType& request,
+ // std::function<void(ResponseType)> response)
+ template <typename F,
+ typename RequestType = ParamType<F, 0>,
+ typename ResponseType = typename RequestType::Response>
+ inline IsRequestHandlerWithCallback<F, ResponseType> registerHandler(
+ F&& handler);
+
+ // registerHandler() registers a request handler for a specific request type.
+ // The handler has a response callback function for the second argument of the
+ // handler function. This callback may be called after the handler has
+ // returned.
+ // The function F must have the following signature:
+ // void(const RequestType& request,
+ // std::function<void(ResponseOrError<ResponseType>)> response)
+ template <typename F,
+ typename RequestType = ParamType<F, 0>,
+ typename ResponseType = typename RequestType::Response>
+ inline IsRequestHandlerWithCallback<F, ResponseOrError<ResponseType>>
+ registerHandler(F&& handler);
+
+ // registerHandler() registers a event handler for a specific event type.
+ // The function F must have the following signature:
+ // void(const EventType&)
+ template <typename F, typename EventType = ParamType<F, 0>>
+ inline IsEvent<EventType> registerHandler(F&& handler);
+
+ // registerSentHandler() registers the function F to be called when a response
+ // of the specific type has been sent.
+ // The function F must have the following signature:
+ // void(const ResponseOrError<ResponseType>&)
+ template <typename F,
+ typename ResponseType = typename ParamType<F, 0>::Request>
+ inline void registerSentHandler(F&& handler);
+
+ // send() sends the request to the connected endpoint and returns a
+ // future that is assigned the request response or error.
+ template <typename T, typename = IsRequest<T>>
+ future<ResponseOrError<typename T::Response>> send(const T& request);
+
+ // send() sends the event to the connected endpoint.
+ template <typename T, typename = IsEvent<T>>
+ void send(const T& event);
+
+ // bind() connects this Session to an endpoint using connect(), and then
+ // starts processing incoming messages with startProcessingMessages().
+ // onClose is the optional callback which will be called when the session
+ // endpoint has been closed.
+ inline void bind(const std::shared_ptr<Reader>& reader,
+ const std::shared_ptr<Writer>& writer,
+ const ClosedHandler& onClose);
+ inline void bind(const std::shared_ptr<ReaderWriter>& readerWriter,
+ const ClosedHandler& onClose);
+
+ //////////////////////////////////////////////////////////////////////////////
+ // Note:
+ // Methods and members below this point are for advanced usage, and are more
+ // likely to change signature than the methods above.
+ // The methods above this point should be sufficient for most use cases.
+ //////////////////////////////////////////////////////////////////////////////
+
+ // connect() connects this Session to an endpoint.
+ // connect() can only be called once. Repeated calls will raise an error, but
+ // otherwise will do nothing.
+ // Note: This method is used for explicit control over message handling.
+ // Most users will use bind() instead of calling this method directly.
+ virtual void connect(const std::shared_ptr<Reader>&,
+ const std::shared_ptr<Writer>&) = 0;
+ inline void connect(const std::shared_ptr<ReaderWriter>&);
+
+ // startProcessingMessages() starts a new thread to receive and dispatch
+ // incoming messages.
+ // onClose is the optional callback which will be called when the session
+ // endpoint has been closed.
+ // Note: This method is used for explicit control over message handling.
+ // Most users will use bind() instead of calling this method directly.
+ virtual void startProcessingMessages(const ClosedHandler& onClose = {}) = 0;
+
+ // getPayload() blocks until the next incoming message is received, returning
+ // the payload or an empty function if the connection was lost. The returned
+ // payload is function that can be called on any thread to dispatch the
+ // message to the Session handler.
+ // Note: This method is used for explicit control over message handling.
+ // Most users will use bind() instead of calling this method directly.
+ virtual std::function<void()> getPayload() = 0;
+
+ // The callback function type called when a request handler is invoked, and
+ // the request returns a successful result.
+ // 'responseTypeInfo' is the type information of the response data structure.
+ // 'responseData' is a pointer to response payload data.
+ using RequestHandlerSuccessCallback =
+ std::function<void(const TypeInfo* responseTypeInfo,
+ const void* responseData)>;
+
+ // The callback function type used to notify when a DAP request fails.
+ // 'responseTypeInfo' is the type information of the response data structure.
+ // 'message' is the error message
+ using RequestHandlerErrorCallback =
+ std::function<void(const TypeInfo* responseTypeInfo,
+ const Error& message)>;
+
+ // The callback function type used to invoke a request handler.
+ // 'request' is a pointer to the request data structure
+ // 'onSuccess' is the function to call if the request completed succesfully.
+ // 'onError' is the function to call if the request failed.
+ // For each call of the request handler, 'onSuccess' or 'onError' must be
+ // called exactly once.
+ using GenericRequestHandler =
+ std::function<void(const void* request,
+ const RequestHandlerSuccessCallback& onSuccess,
+ const RequestHandlerErrorCallback& onError)>;
+
+ // The callback function type used to handle a response to a request.
+ // 'response' is a pointer to the response data structure. May be nullptr.
+ // 'error' is a pointer to the reponse error message. May be nullptr.
+ // One of 'data' or 'error' will be nullptr.
+ using GenericResponseHandler =
+ std::function<void(const void* response, const Error* error)>;
+
+ // The callback function type used to handle an event.
+ // 'event' is a pointer to the event data structure.
+ using GenericEventHandler = std::function<void(const void* event)>;
+
+ // The callback function type used to notify when a response has been sent
+ // from this session endpoint.
+ // 'response' is a pointer to the response data structure.
+ // 'error' is a pointer to the reponse error message. May be nullptr.
+ using GenericResponseSentHandler =
+ std::function<void(const void* response, const Error* error)>;
+
+ // registerHandler() registers 'handler' as the request handler callback for
+ // requests of the type 'typeinfo'.
+ virtual void registerHandler(const TypeInfo* typeinfo,
+ const GenericRequestHandler& handler) = 0;
+
+ // registerHandler() registers 'handler' as the event handler callback for
+ // events of the type 'typeinfo'.
+ virtual void registerHandler(const TypeInfo* typeinfo,
+ const GenericEventHandler& handler) = 0;
+
+ // registerHandler() registers 'handler' as the response-sent handler function
+ // which is called whenever a response of the type 'typeinfo' is sent from
+ // this session endpoint.
+ virtual void registerHandler(const TypeInfo* typeinfo,
+ const GenericResponseSentHandler& handler) = 0;
+
+ // send() sends a request to the remote endpoint.
+ // 'requestTypeInfo' is the type info of the request data structure.
+ // 'requestTypeInfo' is the type info of the response data structure.
+ // 'request' is a pointer to the request data structure.
+ // 'responseHandler' is the handler function for the response.
+ virtual bool send(const dap::TypeInfo* requestTypeInfo,
+ const dap::TypeInfo* responseTypeInfo,
+ const void* request,
+ const GenericResponseHandler& responseHandler) = 0;
+
+ // send() sends an event to the remote endpoint.
+ // 'eventTypeInfo' is the type info for the event data structure.
+ // 'event' is a pointer to the event data structure.
+ virtual bool send(const TypeInfo* eventTypeInfo, const void* event) = 0;
+};
+
+template <typename F, typename RequestType>
+Session::IsRequestHandlerWithoutCallback<F> Session::registerHandler(
+ F&& handler) {
+ using ResponseType = typename RequestType::Response;
+ const TypeInfo* typeinfo = TypeOf<RequestType>::type();
+ registerHandler(typeinfo,
+ [handler](const void* args,
+ const RequestHandlerSuccessCallback& onSuccess,
+ const RequestHandlerErrorCallback& onError) {
+ ResponseOrError<ResponseType> res =
+ handler(*reinterpret_cast<const RequestType*>(args));
+ if (res.error) {
+ onError(TypeOf<ResponseType>::type(), res.error);
+ } else {
+ onSuccess(TypeOf<ResponseType>::type(), &res.response);
+ }
+ });
+}
+
+template <typename F, typename RequestType, typename ResponseType>
+Session::IsRequestHandlerWithCallback<F, ResponseType> Session::registerHandler(
+ F&& handler) {
+ using CallbackType = ParamType<F, 1>;
+ registerHandler(
+ TypeOf<RequestType>::type(),
+ [handler](const void* args,
+ const RequestHandlerSuccessCallback& onSuccess,
+ const RequestHandlerErrorCallback&) {
+ CallbackType responseCallback = [onSuccess](const ResponseType& res) {
+ onSuccess(TypeOf<ResponseType>::type(), &res);
+ };
+ handler(*reinterpret_cast<const RequestType*>(args), responseCallback);
+ });
+}
+
+template <typename F, typename RequestType, typename ResponseType>
+Session::IsRequestHandlerWithCallback<F, ResponseOrError<ResponseType>>
+Session::registerHandler(F&& handler) {
+ using CallbackType = ParamType<F, 1>;
+ registerHandler(
+ TypeOf<RequestType>::type(),
+ [handler](const void* args,
+ const RequestHandlerSuccessCallback& onSuccess,
+ const RequestHandlerErrorCallback& onError) {
+ CallbackType responseCallback =
+ [onError, onSuccess](const ResponseOrError<ResponseType>& res) {
+ if (res.error) {
+ onError(TypeOf<ResponseType>::type(), res.error);
+ } else {
+ onSuccess(TypeOf<ResponseType>::type(), &res.response);
+ }
+ };
+ handler(*reinterpret_cast<const RequestType*>(args), responseCallback);
+ });
+}
+
+template <typename F, typename T>
+Session::IsEvent<T> Session::registerHandler(F&& handler) {
+ auto cb = [handler](const void* args) {
+ handler(*reinterpret_cast<const T*>(args));
+ };
+ const TypeInfo* typeinfo = TypeOf<T>::type();
+ registerHandler(typeinfo, cb);
+}
+
+template <typename F, typename T>
+void Session::registerSentHandler(F&& handler) {
+ auto cb = [handler](const void* response, const Error* error) {
+ if (error != nullptr) {
+ handler(ResponseOrError<T>(*error));
+ } else {
+ handler(ResponseOrError<T>(*reinterpret_cast<const T*>(response)));
+ }
+ };
+ const TypeInfo* typeinfo = TypeOf<T>::type();
+ registerHandler(typeinfo, cb);
+}
+
+template <typename T, typename>
+future<ResponseOrError<typename T::Response>> Session::send(const T& request) {
+ using Response = typename T::Response;
+ promise<ResponseOrError<Response>> promise;
+ auto sent = send(TypeOf<T>::type(), TypeOf<Response>::type(), &request,
+ [=](const void* result, const Error* error) {
+ if (error != nullptr) {
+ promise.set_value(ResponseOrError<Response>(*error));
+ } else {
+ promise.set_value(ResponseOrError<Response>(
+ *reinterpret_cast<const Response*>(result)));
+ }
+ });
+ if (!sent) {
+ promise.set_value(Error("Failed to send request"));
+ }
+ return promise.get_future();
+}
+
+template <typename T, typename>
+void Session::send(const T& event) {
+ const TypeInfo* typeinfo = TypeOf<T>::type();
+ send(typeinfo, &event);
+}
+
+void Session::connect(const std::shared_ptr<ReaderWriter>& rw) {
+ connect(rw, rw);
+}
+
+void Session::bind(const std::shared_ptr<dap::Reader>& r,
+ const std::shared_ptr<dap::Writer>& w,
+ const ClosedHandler& onClose = {}) {
+ connect(r, w);
+ startProcessingMessages(onClose);
+}
+
+void Session::bind(const std::shared_ptr<ReaderWriter>& rw,
+ const ClosedHandler& onClose = {}) {
+ bind(rw, rw, onClose);
+}
+
+} // namespace dap
+
+#endif // dap_session_h
diff --git a/Utilities/cmcppdap/include/dap/traits.h b/Utilities/cmcppdap/include/dap/traits.h
new file mode 100644
index 0000000..6a0c20d
--- /dev/null
+++ b/Utilities/cmcppdap/include/dap/traits.h
@@ -0,0 +1,159 @@
+// Copyright 2021 Google LLC
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// https://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#ifndef dap_traits_h
+#define dap_traits_h
+
+#include <tuple>
+#include <type_traits>
+
+namespace dap {
+namespace traits {
+
+// NthTypeOf returns the `N`th type in `Types`
+template <int N, typename... Types>
+using NthTypeOf = typename std::tuple_element<N, std::tuple<Types...>>::type;
+
+// `IsTypeOrDerived<BASE, T>::value` is true iff `T` is of type `BASE`, or
+// derives from `BASE`.
+template <typename BASE, typename T>
+using IsTypeOrDerived = std::integral_constant<
+ bool,
+ std::is_base_of<BASE, typename std::decay<T>::type>::value ||
+ std::is_same<BASE, typename std::decay<T>::type>::value>;
+
+// `EachIsTypeOrDerived<N, BASES, TYPES>::value` is true iff all of the types in
+// the std::tuple `TYPES` is of, or derives from the corresponding indexed type
+// in the std::tuple `BASES`.
+// `N` must be equal to the number of types in both the std::tuple `BASES` and
+// `TYPES`.
+template <int N, typename BASES, typename TYPES>
+struct EachIsTypeOrDerived {
+ using base = typename std::tuple_element<N - 1, BASES>::type;
+ using type = typename std::tuple_element<N - 1, TYPES>::type;
+ using last_matches = IsTypeOrDerived<base, type>;
+ using others_match = EachIsTypeOrDerived<N - 1, BASES, TYPES>;
+ static constexpr bool value = last_matches::value && others_match::value;
+};
+
+// EachIsTypeOrDerived specialization for N = 1
+template <typename BASES, typename TYPES>
+struct EachIsTypeOrDerived<1, BASES, TYPES> {
+ using base = typename std::tuple_element<0, BASES>::type;
+ using type = typename std::tuple_element<0, TYPES>::type;
+ static constexpr bool value = IsTypeOrDerived<base, type>::value;
+};
+
+// EachIsTypeOrDerived specialization for N = 0
+template <typename BASES, typename TYPES>
+struct EachIsTypeOrDerived<0, BASES, TYPES> {
+ static constexpr bool value = true;
+};
+
+// Signature describes the signature of a function.
+template <typename RETURN, typename... PARAMETERS>
+struct Signature {
+ // The return type of the function signature
+ using ret = RETURN;
+ // The parameters of the function signature held in a std::tuple
+ using parameters = std::tuple<PARAMETERS...>;
+ // The type of the Nth parameter of function signature
+ template <std::size_t N>
+ using parameter = NthTypeOf<N, PARAMETERS...>;
+ // The total number of parameters
+ static constexpr std::size_t parameter_count = sizeof...(PARAMETERS);
+};
+
+// SignatureOf is a traits helper that infers the signature of the function,
+// method, static method, lambda, or function-like object `F`.
+template <typename F>
+struct SignatureOf {
+ // The signature of the function-like object `F`
+ using type = typename SignatureOf<decltype(&F::operator())>::type;
+};
+
+// SignatureOf specialization for a regular function or static method.
+template <typename R, typename... ARGS>
+struct SignatureOf<R (*)(ARGS...)> {
+ // The signature of the function-like object `F`
+ using type = Signature<typename std::decay<R>::type,
+ typename std::decay<ARGS>::type...>;
+};
+
+// SignatureOf specialization for a non-static method.
+template <typename R, typename C, typename... ARGS>
+struct SignatureOf<R (C::*)(ARGS...)> {
+ // The signature of the function-like object `F`
+ using type = Signature<typename std::decay<R>::type,
+ typename std::decay<ARGS>::type...>;
+};
+
+// SignatureOf specialization for a non-static, const method.
+template <typename R, typename C, typename... ARGS>
+struct SignatureOf<R (C::*)(ARGS...) const> {
+ // The signature of the function-like object `F`
+ using type = Signature<typename std::decay<R>::type,
+ typename std::decay<ARGS>::type...>;
+};
+
+// SignatureOfT is an alias to `typename SignatureOf<F>::type`.
+template <typename F>
+using SignatureOfT = typename SignatureOf<F>::type;
+
+// ParameterType is an alias to `typename SignatureOf<F>::type::parameter<N>`.
+template <typename F, std::size_t N>
+using ParameterType = typename SignatureOfT<F>::template parameter<N>;
+
+// `HasSignature<F, S>::value` is true iff the function-like `F` has a matching
+// signature to the function-like `S`.
+template <typename F, typename S>
+using HasSignature = std::integral_constant<
+ bool,
+ std::is_same<SignatureOfT<F>, SignatureOfT<S>>::value>;
+
+// `Min<A, B>::value` resolves to the smaller value of A and B.
+template <std::size_t A, std::size_t B>
+using Min = std::integral_constant<std::size_t, (A < B ? A : B)>;
+
+// `CompatibleWith<F, S>::value` is true iff the function-like `F`
+// can be called with the argument types of the function-like `S`. Return type
+// of the two functions are not considered.
+template <typename F, typename S>
+using CompatibleWith = std::integral_constant<
+ bool,
+ (SignatureOfT<S>::parameter_count == SignatureOfT<F>::parameter_count) &&
+ EachIsTypeOrDerived<Min<SignatureOfT<S>::parameter_count,
+ SignatureOfT<F>::parameter_count>::value,
+ typename SignatureOfT<S>::parameters,
+ typename SignatureOfT<F>::parameters>::value>;
+
+// If `CONDITION` is true then EnableIf resolves to type T, otherwise an
+// invalid type.
+template <bool CONDITION, typename T = void>
+using EnableIf = typename std::enable_if<CONDITION, T>::type;
+
+// If `BASE` is a base of `T` then EnableIfIsType resolves to type `TRUE_TY`,
+// otherwise an invalid type.
+template <typename BASE, typename T, typename TRUE_TY = void>
+using EnableIfIsType = EnableIf<IsTypeOrDerived<BASE, T>::value, TRUE_TY>;
+
+// If the function-like `F` has a matching signature to the function-like `S`
+// then EnableIfHasSignature resolves to type `TRUE_TY`, otherwise an invalid type.
+template <typename F, typename S, typename TRUE_TY = void>
+using EnableIfHasSignature = EnableIf<HasSignature<F, S>::value, TRUE_TY>;
+
+} // namespace traits
+} // namespace dap
+
+#endif // dap_traits_h
diff --git a/Utilities/cmcppdap/include/dap/typeinfo.h b/Utilities/cmcppdap/include/dap/typeinfo.h
new file mode 100644
index 0000000..d99f277
--- /dev/null
+++ b/Utilities/cmcppdap/include/dap/typeinfo.h
@@ -0,0 +1,59 @@
+// Copyright 2019 Google LLC
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// https://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#ifndef dap_typeinfo_h
+#define dap_typeinfo_h
+
+#include <functional>
+#include <string>
+
+namespace dap {
+
+class any;
+class Deserializer;
+class Serializer;
+
+// The TypeInfo interface provides basic runtime type information about DAP
+// types. TypeInfo is used by the serialization system to encode and decode DAP
+// requests, responses, events and structs.
+struct TypeInfo {
+ virtual ~TypeInfo();
+ virtual std::string name() const = 0;
+ virtual size_t size() const = 0;
+ virtual size_t alignment() const = 0;
+ virtual void construct(void*) const = 0;
+ virtual void copyConstruct(void* dst, const void* src) const = 0;
+ virtual void destruct(void*) const = 0;
+ virtual bool deserialize(const Deserializer*, void*) const = 0;
+ virtual bool serialize(Serializer*, const void*) const = 0;
+
+ // create() allocates and constructs the TypeInfo of type T, registers the
+ // pointer for deletion on cppdap library termination, and returns the pointer
+ // to T.
+ template <typename T, typename... ARGS>
+ static T* create(ARGS&&... args) {
+ auto typeinfo = new T(std::forward<ARGS>(args)...);
+ deleteOnExit(typeinfo);
+ return typeinfo;
+ }
+
+ private:
+ // deleteOnExit() ensures that the TypeInfo is destructed and deleted on
+ // library termination.
+ static void deleteOnExit(TypeInfo*);
+};
+
+} // namespace dap
+
+#endif // dap_typeinfo_h
diff --git a/Utilities/cmcppdap/include/dap/typeof.h b/Utilities/cmcppdap/include/dap/typeof.h
new file mode 100644
index 0000000..803bb8d
--- /dev/null
+++ b/Utilities/cmcppdap/include/dap/typeof.h
@@ -0,0 +1,266 @@
+// Copyright 2019 Google LLC
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// https://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#ifndef dap_typeof_h
+#define dap_typeof_h
+
+#include "typeinfo.h"
+#include "types.h"
+
+#include "serialization.h"
+
+namespace dap {
+
+// BasicTypeInfo is an implementation of the TypeInfo interface for the simple
+// template type T.
+template <typename T>
+struct BasicTypeInfo : public TypeInfo {
+ constexpr BasicTypeInfo(std::string&& name) : name_(std::move(name)) {}
+
+ // TypeInfo compliance
+ inline std::string name() const override { return name_; }
+ inline size_t size() const override { return sizeof(T); }
+ inline size_t alignment() const override { return alignof(T); }
+ inline void construct(void* ptr) const override { new (ptr) T(); }
+ inline void copyConstruct(void* dst, const void* src) const override {
+ new (dst) T(*reinterpret_cast<const T*>(src));
+ }
+ inline void destruct(void* ptr) const override {
+ reinterpret_cast<T*>(ptr)->~T();
+ }
+ inline bool deserialize(const Deserializer* d, void* ptr) const override {
+ return d->deserialize(reinterpret_cast<T*>(ptr));
+ }
+ inline bool serialize(Serializer* s, const void* ptr) const override {
+ return s->serialize(*reinterpret_cast<const T*>(ptr));
+ }
+
+ private:
+ std::string name_;
+};
+
+// TypeOf has a template specialization for each DAP type, each declaring a
+// const TypeInfo* type() static member function that describes type T.
+template <typename T>
+struct TypeOf {};
+
+template <>
+struct TypeOf<boolean> {
+ static const TypeInfo* type();
+};
+
+template <>
+struct TypeOf<string> {
+ static const TypeInfo* type();
+};
+
+template <>
+struct TypeOf<integer> {
+ static const TypeInfo* type();
+};
+
+template <>
+struct TypeOf<number> {
+ static const TypeInfo* type();
+};
+
+template <>
+struct TypeOf<object> {
+ static const TypeInfo* type();
+};
+
+template <>
+struct TypeOf<any> {
+ static const TypeInfo* type();
+};
+
+template <>
+struct TypeOf<null> {
+ static const TypeInfo* type();
+};
+
+template <typename T>
+struct TypeOf<array<T>> {
+ static inline const TypeInfo* type() {
+ static auto typeinfo = TypeInfo::create<BasicTypeInfo<array<T>>>(
+ "array<" + TypeOf<T>::type()->name() + ">");
+ return typeinfo;
+ }
+};
+
+template <typename T0, typename... Types>
+struct TypeOf<variant<T0, Types...>> {
+ static inline const TypeInfo* type() {
+ static auto typeinfo =
+ TypeInfo::create<BasicTypeInfo<variant<T0, Types...>>>("variant");
+ return typeinfo;
+ }
+};
+
+template <typename T>
+struct TypeOf<optional<T>> {
+ static inline const TypeInfo* type() {
+ static auto typeinfo = TypeInfo::create<BasicTypeInfo<optional<T>>>(
+ "optional<" + TypeOf<T>::type()->name() + ">");
+ return typeinfo;
+ }
+};
+
+// DAP_OFFSETOF() macro is a generalization of the offsetof() macro defined in
+// <cstddef>. It evaluates to the offset of the given field, with fewer
+// restrictions than offsetof(). We cast the address '32' and subtract it again,
+// because null-dereference is undefined behavior.
+#define DAP_OFFSETOF(s, m) \
+ ((int)(size_t) & reinterpret_cast<const volatile char&>((((s*)32)->m)) - 32)
+
+// internal functionality
+namespace detail {
+template <class T, class M>
+M member_type(M T::*);
+} // namespace detail
+
+// DAP_TYPEOF() returns the type of the struct (s) member (m).
+#define DAP_TYPEOF(s, m) decltype(detail::member_type(&s::m))
+
+// DAP_FIELD() declares a structure field for the DAP_IMPLEMENT_STRUCT_TYPEINFO
+// macro.
+// FIELD is the name of the struct field.
+// NAME is the serialized name of the field, as described by the DAP
+// specification.
+#define DAP_FIELD(FIELD, NAME) \
+ ::dap::Field { \
+ NAME, DAP_OFFSETOF(StructTy, FIELD), \
+ TypeOf<DAP_TYPEOF(StructTy, FIELD)>::type(), \
+ }
+
+// DAP_DECLARE_STRUCT_TYPEINFO() declares a TypeOf<> specialization for STRUCT.
+// Must be used within the 'dap' namespace.
+#define DAP_DECLARE_STRUCT_TYPEINFO(STRUCT) \
+ template <> \
+ struct TypeOf<STRUCT> { \
+ static constexpr bool has_custom_serialization = true; \
+ static const TypeInfo* type(); \
+ static bool deserializeFields(const Deserializer*, void* obj); \
+ static bool serializeFields(FieldSerializer*, const void* obj); \
+ }
+
+// DAP_IMPLEMENT_STRUCT_FIELD_SERIALIZATION() implements the deserializeFields()
+// and serializeFields() static methods of a TypeOf<> specialization. Used
+// internally by DAP_IMPLEMENT_STRUCT_TYPEINFO() and
+// DAP_IMPLEMENT_STRUCT_TYPEINFO_EXT().
+// You probably do not want to use this directly.
+#define DAP_IMPLEMENT_STRUCT_FIELD_SERIALIZATION(STRUCT, NAME, ...) \
+ bool TypeOf<STRUCT>::deserializeFields(const Deserializer* fd, void* obj) { \
+ using StructTy = STRUCT; \
+ (void)sizeof(StructTy); /* avoid unused 'using' warning */ \
+ for (auto field : std::initializer_list<Field>{__VA_ARGS__}) { \
+ if (!fd->field(field.name, [&](Deserializer* d) { \
+ auto ptr = reinterpret_cast<uint8_t*>(obj) + field.offset; \
+ return field.type->deserialize(d, ptr); \
+ })) { \
+ return false; \
+ } \
+ } \
+ return true; \
+ } \
+ bool TypeOf<STRUCT>::serializeFields(FieldSerializer* fs, const void* obj) {\
+ using StructTy = STRUCT; \
+ (void)sizeof(StructTy); /* avoid unused 'using' warning */ \
+ for (auto field : std::initializer_list<Field>{__VA_ARGS__}) { \
+ if (!fs->field(field.name, [&](Serializer* s) { \
+ auto ptr = reinterpret_cast<const uint8_t*>(obj) + field.offset; \
+ return field.type->serialize(s, ptr); \
+ })) { \
+ return false; \
+ } \
+ } \
+ return true; \
+ }
+
+// DAP_IMPLEMENT_STRUCT_TYPEINFO() implements the type() member function for the
+// TypeOf<> specialization for STRUCT.
+// STRUCT is the structure typename.
+// NAME is the serialized name of the structure, as described by the DAP
+// specification. The variadic (...) parameters should be a repeated list of
+// DAP_FIELD()s, one for each field of the struct.
+// Must be used within the 'dap' namespace.
+#define DAP_IMPLEMENT_STRUCT_TYPEINFO(STRUCT, NAME, ...) \
+ DAP_IMPLEMENT_STRUCT_FIELD_SERIALIZATION(STRUCT, NAME, __VA_ARGS__) \
+ const ::dap::TypeInfo* TypeOf<STRUCT>::type() { \
+ struct TI : BasicTypeInfo<STRUCT> { \
+ TI() : BasicTypeInfo<STRUCT>(NAME) {} \
+ bool deserialize(const Deserializer* d, void* obj) const override { \
+ return deserializeFields(d, obj); \
+ } \
+ bool serialize(Serializer* s, const void* obj) const override { \
+ return s->object( \
+ [&](FieldSerializer* fs) { return serializeFields(fs, obj); }); \
+ } \
+ }; \
+ static TI typeinfo; \
+ return &typeinfo; \
+ }
+
+// DAP_STRUCT_TYPEINFO() is a helper for declaring and implementing a TypeOf<>
+// specialization for STRUCT in a single statement.
+// Must be used within the 'dap' namespace.
+#define DAP_STRUCT_TYPEINFO(STRUCT, NAME, ...) \
+ DAP_DECLARE_STRUCT_TYPEINFO(STRUCT); \
+ DAP_IMPLEMENT_STRUCT_TYPEINFO(STRUCT, NAME, __VA_ARGS__)
+
+// DAP_IMPLEMENT_STRUCT_TYPEINFO_EXT() implements the type() member function for
+// the TypeOf<> specialization for STRUCT that derives from BASE.
+// STRUCT is the structure typename.
+// BASE is the base structure typename.
+// NAME is the serialized name of the structure, as described by the DAP
+// specification. The variadic (...) parameters should be a repeated list of
+// DAP_FIELD()s, one for each field of the struct.
+// Must be used within the 'dap' namespace.
+#define DAP_IMPLEMENT_STRUCT_TYPEINFO_EXT(STRUCT, BASE, NAME, ...) \
+ static_assert(std::is_base_of<BASE, STRUCT>::value, \
+ #STRUCT " does not derive from " #BASE); \
+ DAP_IMPLEMENT_STRUCT_FIELD_SERIALIZATION(STRUCT, NAME, __VA_ARGS__) \
+ const ::dap::TypeInfo* TypeOf<STRUCT>::type() { \
+ struct TI : BasicTypeInfo<STRUCT> { \
+ TI() : BasicTypeInfo<STRUCT>(NAME) {} \
+ bool deserialize(const Deserializer* d, void* obj) const override { \
+ auto derived = static_cast<STRUCT*>(obj); \
+ auto base = static_cast<BASE*>(obj); \
+ return TypeOf<BASE>::deserializeFields(d, base) && \
+ deserializeFields(d, derived); \
+ } \
+ bool serialize(Serializer* s, const void* obj) const override { \
+ return s->object([&](FieldSerializer* fs) { \
+ auto derived = static_cast<const STRUCT*>(obj); \
+ auto base = static_cast<const BASE*>(obj); \
+ return TypeOf<BASE>::serializeFields(fs, base) && \
+ serializeFields(fs, derived); \
+ }); \
+ } \
+ }; \
+ static TI typeinfo; \
+ return &typeinfo; \
+ }
+
+// DAP_STRUCT_TYPEINFO_EXT() is a helper for declaring and implementing a
+// TypeOf<> specialization for STRUCT that derives from BASE in a single
+// statement.
+// Must be used within the 'dap' namespace.
+#define DAP_STRUCT_TYPEINFO_EXT(STRUCT, BASE, NAME, ...) \
+ DAP_DECLARE_STRUCT_TYPEINFO(STRUCT); \
+ DAP_IMPLEMENT_STRUCT_TYPEINFO_EXT(STRUCT, BASE, NAME, __VA_ARGS__)
+
+} // namespace dap
+
+#endif // dap_typeof_h
diff --git a/Utilities/cmcppdap/include/dap/types.h b/Utilities/cmcppdap/include/dap/types.h
new file mode 100644
index 0000000..7954e87
--- /dev/null
+++ b/Utilities/cmcppdap/include/dap/types.h
@@ -0,0 +1,104 @@
+// Copyright 2019 Google LLC
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// https://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+// This file holds the basic serializable types used by the debug adapter
+// protocol.
+
+#ifndef dap_types_h
+#define dap_types_h
+
+#include "any.h"
+#include "optional.h"
+#include "variant.h"
+
+#include <unordered_map>
+#include <vector>
+
+#include <stdint.h>
+
+namespace dap {
+
+// string is a sequence of characters.
+// string defaults to an empty string.
+using string = std::string;
+
+// boolean holds a true or false value.
+// boolean defaults to false.
+class boolean {
+ public:
+ inline boolean() : val(false) {}
+ inline boolean(bool i) : val(i) {}
+ inline operator bool() const { return val; }
+ inline boolean& operator=(bool i) {
+ val = i;
+ return *this;
+ }
+
+ private:
+ bool val;
+};
+
+// integer holds a whole signed number.
+// integer defaults to 0.
+class integer {
+ public:
+ inline integer() : val(0) {}
+ inline integer(int64_t i) : val(i) {}
+ inline operator int64_t() const { return val; }
+ inline integer& operator=(int64_t i) {
+ val = i;
+ return *this;
+ }
+ inline integer operator++(int) {
+ auto copy = *this;
+ val++;
+ return copy;
+ }
+
+ private:
+ int64_t val;
+};
+
+// number holds a 64-bit floating point number.
+// number defaults to 0.
+class number {
+ public:
+ inline number() : val(0.0) {}
+ inline number(double i) : val(i) {}
+ inline operator double() const { return val; }
+ inline number& operator=(double i) {
+ val = i;
+ return *this;
+ }
+
+ private:
+ double val;
+};
+
+// array is a list of items of type T.
+// array defaults to an empty list.
+template <typename T>
+using array = std::vector<T>;
+
+// object is a map of string to any.
+// object defaults to an empty map.
+using object = std::unordered_map<string, any>;
+
+// null represents no value.
+// null is used by any to check for no-value.
+using null = std::nullptr_t;
+
+} // namespace dap
+
+#endif // dap_types_h
diff --git a/Utilities/cmcppdap/include/dap/variant.h b/Utilities/cmcppdap/include/dap/variant.h
new file mode 100644
index 0000000..96e57c2
--- /dev/null
+++ b/Utilities/cmcppdap/include/dap/variant.h
@@ -0,0 +1,108 @@
+// Copyright 2019 Google LLC
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// https://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#ifndef dap_variant_h
+#define dap_variant_h
+
+#include "any.h"
+
+namespace dap {
+
+// internal functionality
+namespace detail {
+template <typename T, typename...>
+struct TypeIsIn {
+ static constexpr bool value = false;
+};
+
+template <typename T, typename List0, typename... ListN>
+struct TypeIsIn<T, List0, ListN...> {
+ static constexpr bool value =
+ std::is_same<T, List0>::value || TypeIsIn<T, ListN...>::value;
+};
+} // namespace detail
+
+// variant represents a type-safe union of DAP types.
+// variant can hold a value of any of the template argument types.
+// variant defaults to a default-constructed T0.
+template <typename T0, typename... Types>
+class variant {
+ public:
+ // constructors
+ inline variant();
+ template <typename T>
+ inline variant(const T& val);
+
+ // assignment
+ template <typename T>
+ inline variant& operator=(const T& val);
+
+ // get() returns the contained value of the type T.
+ // If the any does not contain a value of type T, then get() will assert.
+ template <typename T>
+ inline T& get() const;
+
+ // is() returns true iff the contained value is of type T.
+ template <typename T>
+ inline bool is() const;
+
+ // accepts() returns true iff the variant accepts values of type T.
+ template <typename T>
+ static constexpr bool accepts();
+
+ private:
+ friend class Serializer;
+ friend class Deserializer;
+ any value;
+};
+
+template <typename T0, typename... Types>
+variant<T0, Types...>::variant() : value(T0()) {}
+
+template <typename T0, typename... Types>
+template <typename T>
+variant<T0, Types...>::variant(const T& v) : value(v) {
+ static_assert(accepts<T>(), "variant does not accept template type T");
+}
+
+template <typename T0, typename... Types>
+template <typename T>
+variant<T0, Types...>& variant<T0, Types...>::operator=(const T& v) {
+ static_assert(accepts<T>(), "variant does not accept template type T");
+ value = v;
+ return *this;
+}
+
+template <typename T0, typename... Types>
+template <typename T>
+T& variant<T0, Types...>::get() const {
+ static_assert(accepts<T>(), "variant does not accept template type T");
+ return value.get<T>();
+}
+
+template <typename T0, typename... Types>
+template <typename T>
+bool variant<T0, Types...>::is() const {
+ return value.is<T>();
+}
+
+template <typename T0, typename... Types>
+template <typename T>
+constexpr bool variant<T0, Types...>::accepts() {
+ return detail::TypeIsIn<T, T0, Types...>::value;
+}
+
+} // namespace dap
+
+#endif // dap_variant_h
diff --git a/Utilities/cmcppdap/src/any_test.cpp b/Utilities/cmcppdap/src/any_test.cpp
new file mode 100644
index 0000000..7dfb73c
--- /dev/null
+++ b/Utilities/cmcppdap/src/any_test.cpp
@@ -0,0 +1,262 @@
+// Copyright 2019 Google LLC
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// https://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#include "dap/any.h"
+#include "dap/typeof.h"
+#include "dap/types.h"
+
+#include "gmock/gmock.h"
+#include "gtest/gtest.h"
+
+namespace dap {
+
+struct AnyTestObject {
+ dap::integer i;
+ dap::number n;
+};
+
+DAP_STRUCT_TYPEINFO(AnyTestObject,
+ "AnyTestObject",
+ DAP_FIELD(i, "i"),
+ DAP_FIELD(n, "n"));
+
+inline bool operator==(const AnyTestObject& a, const AnyTestObject& b) {
+ return a.i == b.i && a.n == b.n;
+}
+
+} // namespace dap
+
+namespace {
+
+template <typename T>
+struct TestValue {};
+
+template <>
+struct TestValue<dap::null> {
+ static const dap::null value;
+};
+template <>
+struct TestValue<dap::integer> {
+ static const dap::integer value;
+};
+template <>
+struct TestValue<dap::boolean> {
+ static const dap::boolean value;
+};
+template <>
+struct TestValue<dap::number> {
+ static const dap::number value;
+};
+template <>
+struct TestValue<dap::string> {
+ static const dap::string value;
+};
+template <>
+struct TestValue<dap::array<dap::string>> {
+ static const dap::array<dap::string> value;
+};
+template <>
+struct TestValue<dap::AnyTestObject> {
+ static const dap::AnyTestObject value;
+};
+
+const dap::null TestValue<dap::null>::value = nullptr;
+const dap::integer TestValue<dap::integer>::value = 20;
+const dap::boolean TestValue<dap::boolean>::value = true;
+const dap::number TestValue<dap::number>::value = 123.45;
+const dap::string TestValue<dap::string>::value = "hello world";
+const dap::array<dap::string> TestValue<dap::array<dap::string>>::value = {
+ "one", "two", "three"};
+const dap::AnyTestObject TestValue<dap::AnyTestObject>::value = {10, 20.30};
+
+} // namespace
+
+TEST(Any, EmptyConstruct) {
+ dap::any any;
+ ASSERT_TRUE(any.is<dap::null>());
+ ASSERT_FALSE(any.is<dap::boolean>());
+ ASSERT_FALSE(any.is<dap::integer>());
+ ASSERT_FALSE(any.is<dap::number>());
+ ASSERT_FALSE(any.is<dap::object>());
+ ASSERT_FALSE(any.is<dap::string>());
+ ASSERT_FALSE(any.is<dap::array<dap::integer>>());
+ ASSERT_FALSE(any.is<dap::AnyTestObject>());
+}
+
+TEST(Any, Boolean) {
+ dap::any any(dap::boolean(true));
+ ASSERT_TRUE(any.is<dap::boolean>());
+ ASSERT_EQ(any.get<dap::boolean>(), dap::boolean(true));
+}
+
+TEST(Any, Integer) {
+ dap::any any(dap::integer(10));
+ ASSERT_TRUE(any.is<dap::integer>());
+ ASSERT_EQ(any.get<dap::integer>(), dap::integer(10));
+}
+
+TEST(Any, Number) {
+ dap::any any(dap::number(123.0f));
+ ASSERT_TRUE(any.is<dap::number>());
+ ASSERT_EQ(any.get<dap::number>(), dap::number(123.0f));
+}
+
+TEST(Any, String) {
+ dap::any any(dap::string("hello world"));
+ ASSERT_TRUE(any.is<dap::string>());
+ ASSERT_EQ(any.get<dap::string>(), dap::string("hello world"));
+}
+
+TEST(Any, Array) {
+ using array = dap::array<dap::integer>;
+ dap::any any(array({10, 20, 30}));
+ ASSERT_TRUE(any.is<array>());
+ ASSERT_EQ(any.get<array>(), array({10, 20, 30}));
+}
+
+TEST(Any, Object) {
+ dap::object o;
+ o["one"] = dap::integer(1);
+ o["two"] = dap::integer(2);
+ o["three"] = dap::integer(3);
+ dap::any any(o);
+ ASSERT_TRUE(any.is<dap::object>());
+ if (any.is<dap::object>()) {
+ auto got = any.get<dap::object>();
+ ASSERT_EQ(got.size(), 3U);
+ ASSERT_EQ(got.count("one"), 1U);
+ ASSERT_EQ(got.count("two"), 1U);
+ ASSERT_EQ(got.count("three"), 1U);
+ ASSERT_TRUE(got["one"].is<dap::integer>());
+ ASSERT_TRUE(got["two"].is<dap::integer>());
+ ASSERT_TRUE(got["three"].is<dap::integer>());
+ ASSERT_EQ(got["one"].get<dap::integer>(), dap::integer(1));
+ ASSERT_EQ(got["two"].get<dap::integer>(), dap::integer(2));
+ ASSERT_EQ(got["three"].get<dap::integer>(), dap::integer(3));
+ }
+}
+
+TEST(Any, TestObject) {
+ dap::any any(dap::AnyTestObject{5, 3.0});
+ ASSERT_TRUE(any.is<dap::AnyTestObject>());
+ ASSERT_EQ(any.get<dap::AnyTestObject>().i, 5);
+ ASSERT_EQ(any.get<dap::AnyTestObject>().n, 3.0);
+}
+
+template <typename T>
+class AnyT : public ::testing::Test {
+ protected:
+ template <typename T0,
+ typename = std::enable_if<std::is_same<T, T0>::value &&
+ !std::is_same<T0, dap::null>::value>>
+ void check_val(const dap::any& any, const T0& expect) {
+ ASSERT_EQ(any.is<T>(), any.is<T0>());
+ ASSERT_EQ(any.get<T>(), expect);
+ }
+
+ // Special case for Null assignment, as we can assign nullptr_t to any but
+ // can't `get()` it
+ template <typename = dap::null>
+ void check_val(const dap::any& any, const dap::null& expect) {
+ ASSERT_EQ(nullptr, expect);
+ ASSERT_TRUE(any.is<dap::null>());
+ }
+
+ void check_type(const dap::any& any) {
+ ASSERT_EQ(any.is<dap::null>(), (std::is_same<T, dap::null>::value));
+ ASSERT_EQ(any.is<dap::integer>(), (std::is_same<T, dap::integer>::value));
+ ASSERT_EQ(any.is<dap::boolean>(), (std::is_same<T, dap::boolean>::value));
+ ASSERT_EQ(any.is<dap::number>(), (std::is_same<T, dap::number>::value));
+ ASSERT_EQ(any.is<dap::string>(), (std::is_same<T, dap::string>::value));
+ ASSERT_EQ(any.is<dap::array<dap::string>>(),
+ (std::is_same<T, dap::array<dap::string>>::value));
+ ASSERT_EQ(any.is<dap::AnyTestObject>(),
+ (std::is_same<T, dap::AnyTestObject>::value));
+ }
+};
+TYPED_TEST_SUITE_P(AnyT);
+
+TYPED_TEST_P(AnyT, CopyConstruct) {
+ auto val = TestValue<TypeParam>::value;
+ dap::any any(val);
+ this->check_type(any);
+ this->check_val(any, val);
+}
+
+TYPED_TEST_P(AnyT, MoveConstruct) {
+ auto val = TestValue<TypeParam>::value;
+ dap::any any(std::move(val));
+ this->check_type(any);
+ this->check_val(any, val);
+}
+
+TYPED_TEST_P(AnyT, Assign) {
+ auto val = TestValue<TypeParam>::value;
+ dap::any any;
+ any = val;
+ this->check_type(any);
+ this->check_val(any, val);
+}
+
+TYPED_TEST_P(AnyT, MoveAssign) {
+ auto val = TestValue<TypeParam>::value;
+ dap::any any;
+ any = std::move(val);
+ this->check_type(any);
+ this->check_val(any, val);
+}
+
+TYPED_TEST_P(AnyT, RepeatedAssign) {
+ dap::string str = "hello world";
+ auto val = TestValue<TypeParam>::value;
+ dap::any any;
+ any = str;
+ any = val;
+ this->check_type(any);
+ this->check_val(any, val);
+}
+
+TYPED_TEST_P(AnyT, RepeatedMoveAssign) {
+ dap::string str = "hello world";
+ auto val = TestValue<TypeParam>::value;
+ dap::any any;
+ any = std::move(str);
+ any = std::move(val);
+ this->check_type(any);
+ this->check_val(any, val);
+}
+
+REGISTER_TYPED_TEST_SUITE_P(AnyT,
+ CopyConstruct,
+ MoveConstruct,
+ Assign,
+ MoveAssign,
+ RepeatedAssign,
+ RepeatedMoveAssign);
+
+using AnyTypes = ::testing::Types<dap::null,
+ dap::integer,
+ dap::boolean,
+ dap::number,
+ dap::string,
+ dap::array<dap::string>,
+ dap::AnyTestObject>;
+INSTANTIATE_TYPED_TEST_SUITE_P(T, AnyT, AnyTypes);
+
+TEST(Any, Reset) {
+ dap::any any(dap::integer(10));
+ ASSERT_TRUE(any.is<dap::integer>());
+ any.reset();
+ ASSERT_FALSE(any.is<dap::integer>());
+}
diff --git a/Utilities/cmcppdap/src/chan.h b/Utilities/cmcppdap/src/chan.h
new file mode 100644
index 0000000..f2345e9
--- /dev/null
+++ b/Utilities/cmcppdap/src/chan.h
@@ -0,0 +1,90 @@
+// Copyright 2019 Google LLC
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// https://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#ifndef dap_chan_h
+#define dap_chan_h
+
+#include "dap/optional.h"
+
+#include <condition_variable>
+#include <mutex>
+#include <queue>
+
+namespace dap {
+
+template <typename T>
+struct Chan {
+ public:
+ void reset();
+ void close();
+ optional<T> take();
+ void put(T&& in);
+ void put(const T& in);
+
+ private:
+ bool closed = false;
+ std::queue<T> queue;
+ std::condition_variable cv;
+ std::mutex mutex;
+};
+
+template <typename T>
+void Chan<T>::reset() {
+ std::unique_lock<std::mutex> lock(mutex);
+ queue = {};
+ closed = false;
+}
+
+template <typename T>
+void Chan<T>::close() {
+ std::unique_lock<std::mutex> lock(mutex);
+ closed = true;
+ cv.notify_all();
+}
+
+template <typename T>
+optional<T> Chan<T>::take() {
+ std::unique_lock<std::mutex> lock(mutex);
+ cv.wait(lock, [&] { return queue.size() > 0 || closed; });
+ if (queue.size() == 0) {
+ return optional<T>();
+ }
+ auto out = std::move(queue.front());
+ queue.pop();
+ return optional<T>(std::move(out));
+}
+
+template <typename T>
+void Chan<T>::put(T&& in) {
+ std::unique_lock<std::mutex> lock(mutex);
+ auto notify = queue.size() == 0 && !closed;
+ queue.push(std::move(in));
+ if (notify) {
+ cv.notify_all();
+ }
+}
+
+template <typename T>
+void Chan<T>::put(const T& in) {
+ std::unique_lock<std::mutex> lock(mutex);
+ auto notify = queue.size() == 0 && !closed;
+ queue.push(in);
+ if (notify) {
+ cv.notify_all();
+ }
+}
+
+} // namespace dap
+
+#endif // dap_chan_h
diff --git a/Utilities/cmcppdap/src/chan_test.cpp b/Utilities/cmcppdap/src/chan_test.cpp
new file mode 100644
index 0000000..4d7e0a4
--- /dev/null
+++ b/Utilities/cmcppdap/src/chan_test.cpp
@@ -0,0 +1,35 @@
+// Copyright 2019 Google LLC
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// https://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#include "chan.h"
+
+#include "gmock/gmock.h"
+#include "gtest/gtest.h"
+
+#include <thread>
+
+TEST(ChanTest, PutTakeClose) {
+ dap::Chan<int> chan;
+ auto thread = std::thread([&] {
+ chan.put(10);
+ chan.put(20);
+ chan.put(30);
+ chan.close();
+ });
+ EXPECT_EQ(chan.take(), dap::optional<int>(10));
+ EXPECT_EQ(chan.take(), dap::optional<int>(20));
+ EXPECT_EQ(chan.take(), dap::optional<int>(30));
+ EXPECT_EQ(chan.take(), dap::optional<int>());
+ thread.join();
+}
diff --git a/Utilities/cmcppdap/src/content_stream.cpp b/Utilities/cmcppdap/src/content_stream.cpp
new file mode 100644
index 0000000..05d7f47
--- /dev/null
+++ b/Utilities/cmcppdap/src/content_stream.cpp
@@ -0,0 +1,189 @@
+// Copyright 2019 Google LLC
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// https://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#include "content_stream.h"
+
+#include "dap/io.h"
+
+#include <string.h> // strlen
+#include <algorithm> // std::min
+
+namespace dap {
+
+////////////////////////////////////////////////////////////////////////////////
+// ContentReader
+////////////////////////////////////////////////////////////////////////////////
+ContentReader::ContentReader(const std::shared_ptr<Reader>& reader)
+ : reader(reader) {}
+
+ContentReader& ContentReader::operator=(ContentReader&& rhs) noexcept {
+ buf = std::move(rhs.buf);
+ reader = std::move(rhs.reader);
+ return *this;
+}
+
+bool ContentReader::isOpen() {
+ return reader ? reader->isOpen() : false;
+}
+
+void ContentReader::close() {
+ if (reader) {
+ reader->close();
+ }
+}
+
+std::string ContentReader::read() {
+ matched_idx = 0;
+
+ // Find Content-Length header prefix
+ if (!scan("Content-Length:")) {
+ return "";
+ }
+
+ // Skip whitespace and tabs
+ while (matchAny(" \t")) {
+ }
+
+ // Parse length
+ size_t len = 0;
+ while (true) {
+ auto c = matchAny("0123456789");
+ if (c == 0) {
+ break;
+ }
+ len *= 10;
+ len += size_t(c) - size_t('0');
+ }
+ if (len == 0) {
+ return "";
+ }
+ // Expect \r\n\r\n
+ if (!match("\r\n\r\n")) {
+ return "";
+ }
+
+ // Read message
+ if (!buffer(len + matched_idx)) {
+ return "";
+ }
+
+ for (size_t i = 0; i < matched_idx; i++) {
+ buf.pop_front();
+ }
+
+ std::string out;
+ out.reserve(len);
+ for (size_t i = 0; i < len; i++) {
+ out.push_back(static_cast<char>(buf.front()));
+ buf.pop_front();
+ }
+ return out;
+}
+
+bool ContentReader::scan(const uint8_t* seq, size_t len) {
+ while (buffer(len)) {
+ if (match(seq, len)) {
+ return true;
+ }
+ buf.pop_front();
+ }
+ return false;
+}
+
+bool ContentReader::scan(const char* str) {
+ auto len = strlen(str);
+ return scan(reinterpret_cast<const uint8_t*>(str), len);
+}
+
+bool ContentReader::match(const uint8_t* seq, size_t len) {
+ if (!buffer(len + matched_idx)) {
+ return false;
+ }
+ auto it = matched_idx;
+ for (size_t i = 0; i < len; i++, it++) {
+ if (buf[it] != seq[i]) {
+ return false;
+ }
+ }
+
+ matched_idx += len;
+ return true;
+}
+
+bool ContentReader::match(const char* str) {
+ auto len = strlen(str);
+ return match(reinterpret_cast<const uint8_t*>(str), len);
+}
+
+char ContentReader::matchAny(const char* chars) {
+ if (!buffer(1 + matched_idx)) {
+ return false;
+ }
+ int c = buf[matched_idx];
+ if (auto p = strchr(chars, c)) {
+ matched_idx++;
+ return *p;
+ }
+ return 0;
+}
+
+bool ContentReader::buffer(size_t bytes) {
+ if (bytes < buf.size()) {
+ return true;
+ }
+ bytes -= buf.size();
+ while (bytes > 0) {
+ uint8_t chunk[256];
+ auto numWant = std::min(sizeof(chunk), bytes);
+ auto numGot = reader->read(chunk, numWant);
+ if (numGot == 0) {
+ return false;
+ }
+ for (size_t i = 0; i < numGot; i++) {
+ buf.push_back(chunk[i]);
+ }
+ bytes -= numGot;
+ }
+ return true;
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// ContentWriter
+////////////////////////////////////////////////////////////////////////////////
+ContentWriter::ContentWriter(const std::shared_ptr<Writer>& rhs)
+ : writer(rhs) {}
+
+ContentWriter& ContentWriter::operator=(ContentWriter&& rhs) noexcept {
+ writer = std::move(rhs.writer);
+ return *this;
+}
+
+bool ContentWriter::isOpen() {
+ return writer ? writer->isOpen() : false;
+}
+
+void ContentWriter::close() {
+ if (writer) {
+ writer->close();
+ }
+}
+
+bool ContentWriter::write(const std::string& msg) const {
+ auto header =
+ std::string("Content-Length: ") + std::to_string(msg.size()) + "\r\n\r\n";
+ return writer->write(header.data(), header.size()) &&
+ writer->write(msg.data(), msg.size());
+}
+
+} // namespace dap
diff --git a/Utilities/cmcppdap/src/content_stream.h b/Utilities/cmcppdap/src/content_stream.h
new file mode 100644
index 0000000..1fd0849
--- /dev/null
+++ b/Utilities/cmcppdap/src/content_stream.h
@@ -0,0 +1,69 @@
+// Copyright 2019 Google LLC
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// https://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#ifndef dap_content_stream_h
+#define dap_content_stream_h
+
+#include <deque>
+#include <memory>
+#include <string>
+
+#include <stdint.h>
+
+namespace dap {
+
+// Forward declarations
+class Reader;
+class Writer;
+
+class ContentReader {
+ public:
+ ContentReader() = default;
+ ContentReader(const std::shared_ptr<Reader>&);
+ ContentReader& operator=(ContentReader&&) noexcept;
+
+ bool isOpen();
+ void close();
+ std::string read();
+
+ private:
+ bool scan(const uint8_t* seq, size_t len);
+ bool scan(const char* str);
+ bool match(const uint8_t* seq, size_t len);
+ bool match(const char* str);
+ char matchAny(const char* chars);
+ bool buffer(size_t bytes);
+
+ std::shared_ptr<Reader> reader;
+ std::deque<uint8_t> buf;
+ uint32_t matched_idx = 0;
+};
+
+class ContentWriter {
+ public:
+ ContentWriter() = default;
+ ContentWriter(const std::shared_ptr<Writer>&);
+ ContentWriter& operator=(ContentWriter&&) noexcept;
+
+ bool isOpen();
+ void close();
+ bool write(const std::string&) const;
+
+ private:
+ std::shared_ptr<Writer> writer;
+};
+
+} // namespace dap
+
+#endif // dap_content_stream_h
diff --git a/Utilities/cmcppdap/src/content_stream_test.cpp b/Utilities/cmcppdap/src/content_stream_test.cpp
new file mode 100644
index 0000000..80939a8
--- /dev/null
+++ b/Utilities/cmcppdap/src/content_stream_test.cpp
@@ -0,0 +1,99 @@
+// Copyright 2019 Google LLC
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// https://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#include "content_stream.h"
+
+#include "string_buffer.h"
+
+#include "gmock/gmock.h"
+#include "gtest/gtest.h"
+
+#include <memory>
+
+namespace {
+
+// SingleByteReader wraps a dap::Reader to only provide a single byte for each
+// read() call, regardless of the number of bytes actually requested.
+class SingleByteReader : public dap::Reader {
+ public:
+ SingleByteReader(std::unique_ptr<dap::Reader>&& inner)
+ : inner(std::move(inner)) {}
+
+ bool isOpen() override { return inner->isOpen(); }
+ void close() override { return inner->close(); }
+ size_t read(void* buffer, size_t) override { return inner->read(buffer, 1); };
+
+ private:
+ std::unique_ptr<dap::Reader> inner;
+};
+
+} // namespace
+
+TEST(ContentStreamTest, Write) {
+ auto sb = dap::StringBuffer::create();
+ auto ptr = sb.get();
+ dap::ContentWriter cw(std::move(sb));
+ cw.write("Content payload number one");
+ cw.write("Content payload number two");
+ cw.write("Content payload number three");
+ ASSERT_EQ(ptr->string(),
+ "Content-Length: 26\r\n\r\nContent payload number one"
+ "Content-Length: 26\r\n\r\nContent payload number two"
+ "Content-Length: 28\r\n\r\nContent payload number three");
+}
+
+TEST(ContentStreamTest, Read) {
+ auto sb = dap::StringBuffer::create();
+ sb->write("Content-Length: 26\r\n\r\nContent payload number one");
+ sb->write("some unrecognised garbage");
+ sb->write("Content-Length: 26\r\n\r\nContent payload number two");
+ sb->write("some more unrecognised garbage");
+ sb->write("Content-Length: 28\r\n\r\nContent payload number three");
+ dap::ContentReader cs(std::move(sb));
+ ASSERT_EQ(cs.read(), "Content payload number one");
+ ASSERT_EQ(cs.read(), "Content payload number two");
+ ASSERT_EQ(cs.read(), "Content payload number three");
+ ASSERT_EQ(cs.read(), "");
+}
+
+TEST(ContentStreamTest, ShortRead) {
+ auto sb = dap::StringBuffer::create();
+ sb->write("Content-Length: 26\r\n\r\nContent payload number one");
+ sb->write("some unrecognised garbage");
+ sb->write("Content-Length: 26\r\n\r\nContent payload number two");
+ sb->write("some more unrecognised garbage");
+ sb->write("Content-Length: 28\r\n\r\nContent payload number three");
+ dap::ContentReader cs(
+ std::unique_ptr<SingleByteReader>(new SingleByteReader(std::move(sb))));
+ ASSERT_EQ(cs.read(), "Content payload number one");
+ ASSERT_EQ(cs.read(), "Content payload number two");
+ ASSERT_EQ(cs.read(), "Content payload number three");
+ ASSERT_EQ(cs.read(), "");
+}
+
+TEST(ContentStreamTest, PartialReadAndParse) {
+ auto sb = std::make_shared<dap::StringBuffer>();
+ dap::ContentReader cs(sb);
+ sb->write("Content");
+ ASSERT_EQ(cs.read(), "");
+ sb->write("-Length: ");
+ ASSERT_EQ(cs.read(), "");
+ sb->write("26");
+ ASSERT_EQ(cs.read(), "");
+ sb->write("\r\n\r\n");
+ ASSERT_EQ(cs.read(), "");
+ sb->write("Content payload number one");
+ ASSERT_EQ(cs.read(), "Content payload number one");
+ ASSERT_EQ(cs.read(), "");
+}
diff --git a/Utilities/cmcppdap/src/dap_test.cpp b/Utilities/cmcppdap/src/dap_test.cpp
new file mode 100644
index 0000000..f31be46
--- /dev/null
+++ b/Utilities/cmcppdap/src/dap_test.cpp
@@ -0,0 +1,72 @@
+// Copyright 2019 Google LLC
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// https://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#include "dap/dap.h"
+
+#include "gmock/gmock.h"
+#include "gtest/gtest.h"
+
+#include <condition_variable>
+#include <mutex>
+#include <thread>
+#include <vector>
+
+int main(int argc, char** argv) {
+ ::testing::InitGoogleTest(&argc, argv);
+ return RUN_ALL_TESTS();
+}
+
+TEST(DAP, PairedInitializeTerminate) {
+ dap::initialize();
+ dap::terminate();
+}
+
+TEST(DAP, NestedInitializeTerminate) {
+ dap::initialize();
+ dap::initialize();
+ dap::initialize();
+ dap::terminate();
+ dap::terminate();
+ dap::terminate();
+}
+
+TEST(DAP, MultiThreadedInitializeTerminate) {
+ const size_t numThreads = 64;
+
+ std::mutex mutex;
+ std::condition_variable cv;
+ size_t numInits = 0;
+
+ std::vector<std::thread> threads;
+ threads.reserve(numThreads);
+ for (size_t i = 0; i < numThreads; i++) {
+ threads.emplace_back([&] {
+ dap::initialize();
+ {
+ std::unique_lock<std::mutex> lock(mutex);
+ numInits++;
+ if (numInits == numThreads) {
+ cv.notify_all();
+ } else {
+ cv.wait(lock, [&] { return numInits == numThreads; });
+ }
+ }
+ dap::terminate();
+ });
+ }
+
+ for (auto& thread : threads) {
+ thread.join();
+ }
+}
diff --git a/Utilities/cmcppdap/src/io.cpp b/Utilities/cmcppdap/src/io.cpp
new file mode 100644
index 0000000..b4133e5
--- /dev/null
+++ b/Utilities/cmcppdap/src/io.cpp
@@ -0,0 +1,258 @@
+// Copyright 2019 Google LLC
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// https://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#include "dap/io.h"
+
+#include <atomic>
+#include <condition_variable>
+#include <cstdarg>
+#include <cstdio>
+#include <cstring> // strlen
+#include <deque>
+#include <mutex>
+#include <string>
+
+namespace {
+
+class Pipe : public dap::ReaderWriter {
+ public:
+ // dap::ReaderWriter compliance
+ bool isOpen() override {
+ std::unique_lock<std::mutex> lock(mutex);
+ return !closed;
+ }
+
+ void close() override {
+ std::unique_lock<std::mutex> lock(mutex);
+ closed = true;
+ cv.notify_all();
+ }
+
+ size_t read(void* buffer, size_t bytes) override {
+ std::unique_lock<std::mutex> lock(mutex);
+ auto out = reinterpret_cast<uint8_t*>(buffer);
+ size_t n = 0;
+ while (true) {
+ cv.wait(lock, [&] { return closed || data.size() > 0; });
+ if (closed) {
+ return n;
+ }
+ for (; n < bytes && data.size() > 0; n++) {
+ out[n] = data.front();
+ data.pop_front();
+ }
+ if (n == bytes) {
+ return n;
+ }
+ }
+ }
+
+ bool write(const void* buffer, size_t bytes) override {
+ std::unique_lock<std::mutex> lock(mutex);
+ if (closed) {
+ return false;
+ }
+ if (bytes == 0) {
+ return true;
+ }
+ auto notify = data.size() == 0;
+ auto src = reinterpret_cast<const uint8_t*>(buffer);
+ for (size_t i = 0; i < bytes; i++) {
+ data.emplace_back(src[i]);
+ }
+ if (notify) {
+ cv.notify_all();
+ }
+ return true;
+ }
+
+ private:
+ std::mutex mutex;
+ std::condition_variable cv;
+ std::deque<uint8_t> data;
+ bool closed = false;
+};
+
+class RW : public dap::ReaderWriter {
+ public:
+ RW(const std::shared_ptr<Reader>& r, const std::shared_ptr<Writer>& w)
+ : r(r), w(w) {}
+
+ // dap::ReaderWriter compliance
+ bool isOpen() override { return r->isOpen() && w->isOpen(); }
+ void close() override {
+ r->close();
+ w->close();
+ }
+ size_t read(void* buffer, size_t n) override { return r->read(buffer, n); }
+ bool write(const void* buffer, size_t n) override {
+ return w->write(buffer, n);
+ }
+
+ private:
+ const std::shared_ptr<dap::Reader> r;
+ const std::shared_ptr<dap::Writer> w;
+};
+
+class File : public dap::ReaderWriter {
+ public:
+ File(FILE* f, bool closable) : f(f), closable(closable) {}
+
+ ~File() { close(); }
+
+ // dap::ReaderWriter compliance
+ bool isOpen() override { return !closed; }
+ void close() override {
+ if (closable) {
+ if (!closed.exchange(true)) {
+ fclose(f);
+ }
+ }
+ }
+ size_t read(void* buffer, size_t n) override {
+ std::unique_lock<std::mutex> lock(readMutex);
+ auto out = reinterpret_cast<char*>(buffer);
+ for (size_t i = 0; i < n; i++) {
+ int c = fgetc(f);
+ if (c == EOF) {
+ return i;
+ }
+ out[i] = char(c);
+ }
+ return n;
+ }
+ bool write(const void* buffer, size_t n) override {
+ std::unique_lock<std::mutex> lock(writeMutex);
+ if (fwrite(buffer, 1, n, f) == n) {
+ fflush(f);
+ return true;
+ }
+ return false;
+ }
+
+ private:
+ FILE* const f;
+ const bool closable;
+ std::mutex readMutex;
+ std::mutex writeMutex;
+ std::atomic<bool> closed = {false};
+};
+
+class ReaderSpy : public dap::Reader {
+ public:
+ ReaderSpy(const std::shared_ptr<dap::Reader>& r,
+ const std::shared_ptr<dap::Writer>& s,
+ const std::string& prefix)
+ : r(r), s(s), prefix(prefix) {}
+
+ // dap::Reader compliance
+ bool isOpen() override { return r->isOpen(); }
+ void close() override { r->close(); }
+ size_t read(void* buffer, size_t n) override {
+ auto c = r->read(buffer, n);
+ if (c > 0) {
+ auto chars = reinterpret_cast<const char*>(buffer);
+ std::string buf = prefix;
+ buf.append(chars, chars + c);
+ s->write(buf.data(), buf.size());
+ }
+ return c;
+ }
+
+ private:
+ const std::shared_ptr<dap::Reader> r;
+ const std::shared_ptr<dap::Writer> s;
+ const std::string prefix;
+};
+
+class WriterSpy : public dap::Writer {
+ public:
+ WriterSpy(const std::shared_ptr<dap::Writer>& w,
+ const std::shared_ptr<dap::Writer>& s,
+ const std::string& prefix)
+ : w(w), s(s), prefix(prefix) {}
+
+ // dap::Writer compliance
+ bool isOpen() override { return w->isOpen(); }
+ void close() override { w->close(); }
+ bool write(const void* buffer, size_t n) override {
+ if (!w->write(buffer, n)) {
+ return false;
+ }
+ auto chars = reinterpret_cast<const char*>(buffer);
+ std::string buf = prefix;
+ buf.append(chars, chars + n);
+ s->write(buf.data(), buf.size());
+ return true;
+ }
+
+ private:
+ const std::shared_ptr<dap::Writer> w;
+ const std::shared_ptr<dap::Writer> s;
+ const std::string prefix;
+};
+
+} // anonymous namespace
+
+namespace dap {
+
+std::shared_ptr<ReaderWriter> ReaderWriter::create(
+ const std::shared_ptr<Reader>& r,
+ const std::shared_ptr<Writer>& w) {
+ return std::make_shared<RW>(r, w);
+}
+
+std::shared_ptr<ReaderWriter> pipe() {
+ return std::make_shared<Pipe>();
+}
+
+std::shared_ptr<ReaderWriter> file(FILE* f, bool closable /* = true */) {
+ return std::make_shared<File>(f, closable);
+}
+
+std::shared_ptr<ReaderWriter> file(const char* path) {
+ if (auto f = fopen(path, "wb")) {
+ return std::make_shared<File>(f, true);
+ }
+ return nullptr;
+}
+
+// spy() returns a Reader that copies all reads from the Reader r to the Writer
+// s, using the given optional prefix.
+std::shared_ptr<Reader> spy(const std::shared_ptr<Reader>& r,
+ const std::shared_ptr<Writer>& s,
+ const char* prefix /* = "\n<-" */) {
+ return std::make_shared<ReaderSpy>(r, s, prefix);
+}
+
+// spy() returns a Writer that copies all writes to the Writer w to the Writer
+// s, using the given optional prefix.
+std::shared_ptr<Writer> spy(const std::shared_ptr<Writer>& w,
+ const std::shared_ptr<Writer>& s,
+ const char* prefix /* = "\n->" */) {
+ return std::make_shared<WriterSpy>(w, s, prefix);
+}
+
+bool writef(const std::shared_ptr<Writer>& w, const char* msg, ...) {
+ char buf[2048];
+
+ va_list vararg;
+ va_start(vararg, msg);
+ vsnprintf(buf, sizeof(buf), msg, vararg);
+ va_end(vararg);
+
+ return w->write(buf, strlen(buf));
+}
+
+} // namespace dap
diff --git a/Utilities/cmcppdap/src/json_serializer.h b/Utilities/cmcppdap/src/json_serializer.h
new file mode 100644
index 0000000..32a7ce4
--- /dev/null
+++ b/Utilities/cmcppdap/src/json_serializer.h
@@ -0,0 +1,47 @@
+// Copyright 2020 Google LLC
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// https://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#ifndef dap_json_serializer_h
+#define dap_json_serializer_h
+
+#if defined(CPPDAP_JSON_NLOHMANN)
+#include "nlohmann_json_serializer.h"
+#elif defined(CPPDAP_JSON_RAPID)
+#include "rapid_json_serializer.h"
+#elif defined(CPPDAP_JSON_JSONCPP)
+#include "jsoncpp_json_serializer.h"
+#else
+#error "Unrecognised cppdap JSON library"
+#endif
+
+namespace dap {
+namespace json {
+
+#if defined(CPPDAP_JSON_NLOHMANN)
+using Deserializer = NlohmannDeserializer;
+using Serializer = NlohmannSerializer;
+#elif defined(CPPDAP_JSON_RAPID)
+using Deserializer = RapidDeserializer;
+using Serializer = RapidSerializer;
+#elif defined(CPPDAP_JSON_JSONCPP)
+using Deserializer = JsonCppDeserializer;
+using Serializer = JsonCppSerializer;
+#else
+#error "Unrecognised cppdap JSON library"
+#endif
+
+} // namespace json
+} // namespace dap
+
+#endif // dap_json_serializer_h
diff --git a/Utilities/cmcppdap/src/json_serializer_test.cpp b/Utilities/cmcppdap/src/json_serializer_test.cpp
new file mode 100644
index 0000000..3416cd9
--- /dev/null
+++ b/Utilities/cmcppdap/src/json_serializer_test.cpp
@@ -0,0 +1,266 @@
+// Copyright 2019 Google LLC
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// https://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#include "json_serializer.h"
+
+#include "dap/typeinfo.h"
+#include "dap/typeof.h"
+
+#include "gmock/gmock.h"
+#include "gtest/gtest.h"
+
+namespace dap {
+
+struct JSONInnerTestObject {
+ integer i;
+};
+
+DAP_STRUCT_TYPEINFO(JSONInnerTestObject,
+ "json-inner-test-object",
+ DAP_FIELD(i, "i"));
+
+struct JSONTestObject {
+ boolean b;
+ integer i;
+ number n;
+ array<integer> a;
+ object o;
+ string s;
+ optional<integer> o1;
+ optional<integer> o2;
+ JSONInnerTestObject inner;
+};
+
+DAP_STRUCT_TYPEINFO(JSONTestObject,
+ "json-test-object",
+ DAP_FIELD(b, "b"),
+ DAP_FIELD(i, "i"),
+ DAP_FIELD(n, "n"),
+ DAP_FIELD(a, "a"),
+ DAP_FIELD(o, "o"),
+ DAP_FIELD(s, "s"),
+ DAP_FIELD(o1, "o1"),
+ DAP_FIELD(o2, "o2"),
+ DAP_FIELD(inner, "inner"));
+
+struct JSONObjectNoFields {};
+
+DAP_STRUCT_TYPEINFO(JSONObjectNoFields, "json-object-no-fields");
+
+struct SimpleJSONTestObject {
+ boolean b;
+ integer i;
+};
+DAP_STRUCT_TYPEINFO(SimpleJSONTestObject,
+ "simple-json-test-object",
+ DAP_FIELD(b, "b"),
+ DAP_FIELD(i, "i"));
+
+} // namespace dap
+
+class JSONSerializer : public testing::Test {
+ protected:
+ static dap::object GetSimpleObject() {
+ return dap::object({{"one", dap::integer(1)},
+ {"two", dap::number(2)},
+ {"three", dap::string("three")},
+ {"four", dap::boolean(true)}});
+ }
+ void TEST_SIMPLE_OBJECT(const dap::object& obj) {
+ NESTED_TEST_FAILED = true;
+ auto ref_obj = GetSimpleObject();
+ ASSERT_EQ(obj.size(), ref_obj.size());
+ ASSERT_TRUE(obj.at("one").is<dap::integer>());
+ ASSERT_TRUE(obj.at("two").is<dap::number>());
+ ASSERT_TRUE(obj.at("three").is<dap::string>());
+ ASSERT_TRUE(obj.at("four").is<dap::boolean>());
+
+ ASSERT_EQ(ref_obj.at("one").get<dap::integer>(),
+ obj.at("one").get<dap::integer>());
+ ASSERT_EQ(ref_obj.at("two").get<dap::number>(),
+ obj.at("two").get<dap::number>());
+ ASSERT_EQ(ref_obj.at("three").get<dap::string>(),
+ obj.at("three").get<dap::string>());
+ ASSERT_EQ(ref_obj.at("four").get<dap::boolean>(),
+ obj.at("four").get<dap::boolean>());
+ NESTED_TEST_FAILED = false;
+ }
+ template <typename T>
+ void TEST_SERIALIZING_DESERIALIZING(const T& encoded, T& decoded) {
+ NESTED_TEST_FAILED = true;
+ dap::json::Serializer s;
+ ASSERT_TRUE(s.serialize(encoded));
+ dap::json::Deserializer d(s.dump());
+ ASSERT_TRUE(d.deserialize(&decoded));
+ NESTED_TEST_FAILED = false;
+ }
+ bool NESTED_TEST_FAILED = false;
+#define _ASSERT_PASS(NESTED_TEST) \
+ NESTED_TEST; \
+ ASSERT_FALSE(NESTED_TEST_FAILED);
+};
+
+TEST_F(JSONSerializer, SerializeDeserialize) {
+ dap::JSONTestObject encoded;
+ encoded.b = true;
+ encoded.i = 32;
+ encoded.n = 123.456;
+ encoded.a = {2, 4, 6, 8, 0x100000000, -2, -4, -6, -8, -0x100000000};
+ encoded.o["one"] = dap::integer(1);
+ encoded.o["two"] = dap::number(2);
+ encoded.s = "hello world";
+ encoded.o2 = 42;
+ encoded.inner.i = 70;
+
+ dap::json::Serializer s;
+ ASSERT_TRUE(s.serialize(encoded));
+
+ dap::JSONTestObject decoded;
+ dap::json::Deserializer d(s.dump());
+ ASSERT_TRUE(d.deserialize(&decoded));
+
+ ASSERT_EQ(encoded.b, decoded.b);
+ ASSERT_EQ(encoded.i, decoded.i);
+ ASSERT_EQ(encoded.n, decoded.n);
+ ASSERT_EQ(encoded.a, decoded.a);
+ ASSERT_EQ(encoded.o["one"].get<dap::integer>(),
+ decoded.o["one"].get<dap::integer>());
+ ASSERT_EQ(encoded.o["two"].get<dap::number>(),
+ decoded.o["two"].get<dap::number>());
+ ASSERT_EQ(encoded.s, decoded.s);
+ ASSERT_EQ(encoded.o2, decoded.o2);
+ ASSERT_EQ(encoded.inner.i, decoded.inner.i);
+}
+
+TEST_F(JSONSerializer, SerializeObjectNoFields) {
+ dap::JSONObjectNoFields obj;
+ dap::json::Serializer s;
+ ASSERT_TRUE(s.serialize(obj));
+ ASSERT_EQ(s.dump(), "{}");
+}
+
+TEST_F(JSONSerializer, SerializeDeserializeObject) {
+ dap::object encoded = GetSimpleObject();
+ dap::object decoded;
+ _ASSERT_PASS(TEST_SERIALIZING_DESERIALIZING(encoded, decoded));
+ _ASSERT_PASS(TEST_SIMPLE_OBJECT(decoded));
+}
+
+TEST_F(JSONSerializer, SerializeDeserializeEmbeddedObject) {
+ dap::object encoded;
+ dap::object decoded;
+ // object nested inside object
+ dap::object encoded_embed_obj = GetSimpleObject();
+ dap::object decoded_embed_obj;
+ encoded["embed_obj"] = encoded_embed_obj;
+ _ASSERT_PASS(TEST_SERIALIZING_DESERIALIZING(encoded, decoded));
+ ASSERT_TRUE(decoded["embed_obj"].is<dap::object>());
+ decoded_embed_obj = decoded["embed_obj"].get<dap::object>();
+ _ASSERT_PASS(TEST_SIMPLE_OBJECT(decoded_embed_obj));
+}
+
+TEST_F(JSONSerializer, SerializeDeserializeEmbeddedStruct) {
+ dap::object encoded;
+ dap::object decoded;
+ // object nested inside object
+ dap::SimpleJSONTestObject encoded_embed_struct;
+ encoded_embed_struct.b = true;
+ encoded_embed_struct.i = 50;
+ encoded["embed_struct"] = encoded_embed_struct;
+
+ dap::object decoded_embed_obj;
+ _ASSERT_PASS(TEST_SERIALIZING_DESERIALIZING(encoded, decoded));
+ ASSERT_TRUE(decoded["embed_struct"].is<dap::object>());
+ decoded_embed_obj = decoded["embed_struct"].get<dap::object>();
+ ASSERT_TRUE(decoded_embed_obj.at("b").is<dap::boolean>());
+ ASSERT_TRUE(decoded_embed_obj.at("i").is<dap::integer>());
+
+ ASSERT_EQ(encoded_embed_struct.b, decoded_embed_obj["b"].get<dap::boolean>());
+ ASSERT_EQ(encoded_embed_struct.i, decoded_embed_obj["i"].get<dap::integer>());
+}
+
+TEST_F(JSONSerializer, SerializeDeserializeEmbeddedIntArray) {
+ dap::object encoded;
+ dap::object decoded;
+ // array nested inside object
+ dap::array<dap::integer> encoded_embed_arr = {1, 2, 3, 4};
+ dap::array<dap::any> decoded_embed_arr;
+
+ encoded["embed_arr"] = encoded_embed_arr;
+
+ _ASSERT_PASS(TEST_SERIALIZING_DESERIALIZING(encoded, decoded));
+ // TODO: Deserializing array should infer basic member types
+ ASSERT_TRUE(decoded["embed_arr"].is<dap::array<dap::any>>());
+ decoded_embed_arr = decoded["embed_arr"].get<dap::array<dap::any>>();
+ ASSERT_EQ(encoded_embed_arr.size(), decoded_embed_arr.size());
+ for (std::size_t i = 0; i < decoded_embed_arr.size(); i++) {
+ ASSERT_TRUE(decoded_embed_arr[i].is<dap::integer>());
+ ASSERT_EQ(encoded_embed_arr[i], decoded_embed_arr[i].get<dap::integer>());
+ }
+}
+
+TEST_F(JSONSerializer, SerializeDeserializeEmbeddedObjectArray) {
+ dap::object encoded;
+ dap::object decoded;
+
+ dap::array<dap::object> encoded_embed_arr = {GetSimpleObject(),
+ GetSimpleObject()};
+ dap::array<dap::any> decoded_embed_arr;
+
+ encoded["embed_arr"] = encoded_embed_arr;
+
+ _ASSERT_PASS(TEST_SERIALIZING_DESERIALIZING(encoded, decoded));
+ // TODO: Deserializing array should infer basic member types
+ ASSERT_TRUE(decoded["embed_arr"].is<dap::array<dap::any>>());
+ decoded_embed_arr = decoded["embed_arr"].get<dap::array<dap::any>>();
+ ASSERT_EQ(encoded_embed_arr.size(), decoded_embed_arr.size());
+ for (std::size_t i = 0; i < decoded_embed_arr.size(); i++) {
+ ASSERT_TRUE(decoded_embed_arr[i].is<dap::object>());
+ _ASSERT_PASS(TEST_SIMPLE_OBJECT(decoded_embed_arr[i].get<dap::object>()));
+ }
+}
+
+TEST_F(JSONSerializer, DeserializeSerializeEmptyObject) {
+ auto empty_obj = "{}";
+ dap::object decoded;
+ dap::json::Deserializer d(empty_obj);
+ ASSERT_TRUE(d.deserialize(&decoded));
+ dap::json::Serializer s;
+ ASSERT_TRUE(s.serialize(decoded));
+ ASSERT_EQ(s.dump(), empty_obj);
+}
+
+TEST_F(JSONSerializer, SerializeDeserializeEmbeddedEmptyObject) {
+ dap::object encoded_empty_obj;
+ dap::object encoded = {{"empty_obj", encoded_empty_obj}};
+ dap::object decoded;
+
+ _ASSERT_PASS(TEST_SERIALIZING_DESERIALIZING(encoded, decoded));
+ ASSERT_TRUE(decoded["empty_obj"].is<dap::object>());
+ dap::object decoded_empty_obj = decoded["empty_obj"].get<dap::object>();
+ ASSERT_EQ(encoded_empty_obj.size(), decoded_empty_obj.size());
+}
+
+TEST_F(JSONSerializer, SerializeDeserializeObjectWithNulledField) {
+ auto thing = dap::any(dap::null());
+ dap::object encoded;
+ encoded["nulled_field"] = dap::null();
+ dap::json::Serializer s;
+ ASSERT_TRUE(s.serialize(encoded));
+ dap::object decoded;
+ auto dump = s.dump();
+ dap::json::Deserializer d(dump);
+ ASSERT_TRUE(d.deserialize(&decoded));
+ ASSERT_TRUE(encoded["nulled_field"].is<dap::null>());
+}
diff --git a/Utilities/cmcppdap/src/jsoncpp_json_serializer.cpp b/Utilities/cmcppdap/src/jsoncpp_json_serializer.cpp
new file mode 100644
index 0000000..0d037a9
--- /dev/null
+++ b/Utilities/cmcppdap/src/jsoncpp_json_serializer.cpp
@@ -0,0 +1,272 @@
+// Copyright 2023 Google LLC
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// https://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#include "jsoncpp_json_serializer.h"
+
+#include "null_json_serializer.h"
+
+#include <cm3p/json/json.h>
+#include <cstdlib>
+#include <memory>
+
+namespace dap {
+namespace json {
+
+JsonCppDeserializer::JsonCppDeserializer(const std::string& str)
+ : json(new Json::Value(JsonCppDeserializer::parse(str))), ownsJson(true) {}
+
+JsonCppDeserializer::JsonCppDeserializer(const Json::Value* json)
+ : json(json), ownsJson(false) {}
+
+JsonCppDeserializer::~JsonCppDeserializer() {
+ if (ownsJson) {
+ delete json;
+ }
+}
+
+bool JsonCppDeserializer::deserialize(dap::boolean* v) const {
+ if (!json->isBool()) {
+ return false;
+ }
+ *v = json->asBool();
+ return true;
+}
+
+bool JsonCppDeserializer::deserialize(dap::integer* v) const {
+ if (!json->isInt64()) {
+ return false;
+ }
+ *v = json->asInt64();
+ return true;
+}
+
+bool JsonCppDeserializer::deserialize(dap::number* v) const {
+ if (!json->isNumeric()) {
+ return false;
+ }
+ *v = json->asDouble();
+ return true;
+}
+
+bool JsonCppDeserializer::deserialize(dap::string* v) const {
+ if (!json->isString()) {
+ return false;
+ }
+ *v = json->asString();
+ return true;
+}
+
+bool JsonCppDeserializer::deserialize(dap::object* v) const {
+ v->reserve(json->size());
+ for (auto i = json->begin(); i != json->end(); i++) {
+ JsonCppDeserializer d(&*i);
+ dap::any val;
+ if (!d.deserialize(&val)) {
+ return false;
+ }
+ (*v)[i.name()] = val;
+ }
+ return true;
+}
+
+bool JsonCppDeserializer::deserialize(dap::any* v) const {
+ if (json->isBool()) {
+ *v = dap::boolean(json->asBool());
+ } else if (json->type() == Json::ValueType::realValue) {
+ // json->isDouble() returns true for integers as well, so we need to
+ // explicitly look for the realValue type.
+ *v = dap::number(json->asDouble());
+ } else if (json->isInt64()) {
+ *v = dap::integer(json->asInt64());
+ } else if (json->isString()) {
+ *v = json->asString();
+ } else if (json->isObject()) {
+ dap::object obj;
+ if (!deserialize(&obj)) {
+ return false;
+ }
+ *v = obj;
+ } else if (json->isArray()) {
+ dap::array<any> arr;
+ if (!deserialize(&arr)) {
+ return false;
+ }
+ *v = arr;
+ } else if (json->isNull()) {
+ *v = null();
+ } else {
+ return false;
+ }
+ return true;
+}
+
+size_t JsonCppDeserializer::count() const {
+ return json->size();
+}
+
+bool JsonCppDeserializer::array(
+ const std::function<bool(dap::Deserializer*)>& cb) const {
+ if (!json->isArray()) {
+ return false;
+ }
+ for (const auto& value : *json) {
+ JsonCppDeserializer d(&value);
+ if (!cb(&d)) {
+ return false;
+ }
+ }
+ return true;
+}
+
+bool JsonCppDeserializer::field(
+ const std::string& name,
+ const std::function<bool(dap::Deserializer*)>& cb) const {
+ if (!json->isObject()) {
+ return false;
+ }
+ auto value = json->find(name.data(), name.data() + name.size());
+ if (value == nullptr) {
+ return cb(&NullDeserializer::instance);
+ }
+ JsonCppDeserializer d(value);
+ return cb(&d);
+}
+
+Json::Value JsonCppDeserializer::parse(const std::string& text) {
+ Json::CharReaderBuilder builder;
+ auto jsonReader = std::unique_ptr<Json::CharReader>(builder.newCharReader());
+ Json::Value json;
+ std::string error;
+ if (!jsonReader->parse(text.data(), text.data() + text.size(), &json,
+ &error)) {
+ // cppdap expects that the JSON layer does not throw exceptions.
+ std::abort();
+ }
+ return json;
+}
+
+JsonCppSerializer::JsonCppSerializer()
+ : json(new Json::Value()), ownsJson(true) {}
+
+JsonCppSerializer::JsonCppSerializer(Json::Value* json)
+ : json(json), ownsJson(false) {}
+
+JsonCppSerializer::~JsonCppSerializer() {
+ if (ownsJson) {
+ delete json;
+ }
+}
+
+std::string JsonCppSerializer::dump() const {
+ Json::StreamWriterBuilder writer;
+ return Json::writeString(writer, *json);
+}
+
+bool JsonCppSerializer::serialize(dap::boolean v) {
+ *json = (bool)v;
+ return true;
+}
+
+bool JsonCppSerializer::serialize(dap::integer v) {
+ *json = (Json::LargestInt)v;
+ return true;
+}
+
+bool JsonCppSerializer::serialize(dap::number v) {
+ *json = (double)v;
+ return true;
+}
+
+bool JsonCppSerializer::serialize(const dap::string& v) {
+ *json = v;
+ return true;
+}
+
+bool JsonCppSerializer::serialize(const dap::object& v) {
+ if (!json->isObject()) {
+ *json = Json::Value(Json::objectValue);
+ }
+ for (auto& it : v) {
+ JsonCppSerializer s(&(*json)[it.first]);
+ if (!s.serialize(it.second)) {
+ return false;
+ }
+ }
+ return true;
+}
+
+bool JsonCppSerializer::serialize(const dap::any& v) {
+ if (v.is<dap::boolean>()) {
+ *json = (bool)v.get<dap::boolean>();
+ } else if (v.is<dap::integer>()) {
+ *json = (Json::LargestInt)v.get<dap::integer>();
+ } else if (v.is<dap::number>()) {
+ *json = (double)v.get<dap::number>();
+ } else if (v.is<dap::string>()) {
+ *json = v.get<dap::string>();
+ } else if (v.is<dap::object>()) {
+ // reachable if dap::object nested is inside other dap::object
+ return serialize(v.get<dap::object>());
+ } else if (v.is<dap::null>()) {
+ } else {
+ // reachable if array or custom serialized type is nested inside other
+ auto type = get_any_type(v);
+ auto value = get_any_val(v);
+ if (type && value) {
+ return type->serialize(this, value);
+ }
+ return false;
+ }
+ return true;
+}
+
+bool JsonCppSerializer::array(size_t count,
+ const std::function<bool(dap::Serializer*)>& cb) {
+ *json = Json::Value(Json::arrayValue);
+ for (size_t i = 0; i < count; i++) {
+ JsonCppSerializer s(&(*json)[Json::Value::ArrayIndex(i)]);
+ if (!cb(&s)) {
+ return false;
+ }
+ }
+ return true;
+}
+
+bool JsonCppSerializer::object(
+ const std::function<bool(dap::FieldSerializer*)>& cb) {
+ struct FS : public FieldSerializer {
+ Json::Value* const json;
+
+ FS(Json::Value* json) : json(json) {}
+ bool field(const std::string& name, const SerializeFunc& cb) override {
+ JsonCppSerializer s(&(*json)[name]);
+ auto res = cb(&s);
+ if (s.removed) {
+ json->removeMember(name);
+ }
+ return res;
+ }
+ };
+
+ *json = Json::Value(Json::objectValue);
+ FS fs{json};
+ return cb(&fs);
+}
+
+void JsonCppSerializer::remove() {
+ removed = true;
+}
+
+} // namespace json
+} // namespace dap
diff --git a/Utilities/cmcppdap/src/jsoncpp_json_serializer.h b/Utilities/cmcppdap/src/jsoncpp_json_serializer.h
new file mode 100644
index 0000000..93c510b
--- /dev/null
+++ b/Utilities/cmcppdap/src/jsoncpp_json_serializer.h
@@ -0,0 +1,134 @@
+// Copyright 2023 Google LLC
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// https://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#ifndef dap_jsoncpp_json_serializer_h
+#define dap_jsoncpp_json_serializer_h
+
+#include "dap/protocol.h"
+#include "dap/serialization.h"
+#include "dap/types.h"
+
+#include <cm3p/json/forwards.h>
+
+namespace dap {
+namespace json {
+
+struct JsonCppDeserializer : public dap::Deserializer {
+ explicit JsonCppDeserializer(const std::string&);
+ ~JsonCppDeserializer();
+
+ // dap::Deserializer compliance
+ bool deserialize(boolean* v) const override;
+ bool deserialize(integer* v) const override;
+ bool deserialize(number* v) const override;
+ bool deserialize(string* v) const override;
+ bool deserialize(object* v) const override;
+ bool deserialize(any* v) const override;
+ size_t count() const override;
+ bool array(const std::function<bool(dap::Deserializer*)>&) const override;
+ bool field(const std::string& name,
+ const std::function<bool(dap::Deserializer*)>&) const override;
+
+ // Unhide base overloads
+ template <typename T>
+ inline bool field(const std::string& name, T* v) {
+ return dap::Deserializer::field(name, v);
+ }
+
+ template <typename T,
+ typename = std::enable_if<TypeOf<T>::has_custom_serialization>>
+ inline bool deserialize(T* v) const {
+ return dap::Deserializer::deserialize(v);
+ }
+
+ template <typename T>
+ inline bool deserialize(dap::array<T>* v) const {
+ return dap::Deserializer::deserialize(v);
+ }
+
+ template <typename T>
+ inline bool deserialize(dap::optional<T>* v) const {
+ return dap::Deserializer::deserialize(v);
+ }
+
+ template <typename T0, typename... Types>
+ inline bool deserialize(dap::variant<T0, Types...>* v) const {
+ return dap::Deserializer::deserialize(v);
+ }
+
+ template <typename T>
+ inline bool field(const std::string& name, T* v) const {
+ return dap::Deserializer::deserialize(name, v);
+ }
+
+ private:
+ JsonCppDeserializer(const Json::Value*);
+ static Json::Value parse(const std::string& text);
+ const Json::Value* const json;
+ const bool ownsJson;
+};
+
+struct JsonCppSerializer : public dap::Serializer {
+ JsonCppSerializer();
+ ~JsonCppSerializer();
+
+ std::string dump() const;
+
+ // dap::Serializer compliance
+ bool serialize(boolean v) override;
+ bool serialize(integer v) override;
+ bool serialize(number v) override;
+ bool serialize(const string& v) override;
+ bool serialize(const dap::object& v) override;
+ bool serialize(const any& v) override;
+ bool array(size_t count,
+ const std::function<bool(dap::Serializer*)>&) override;
+ bool object(const std::function<bool(dap::FieldSerializer*)>&) override;
+ void remove() override;
+
+ // Unhide base overloads
+ template <typename T,
+ typename = std::enable_if<TypeOf<T>::has_custom_serialization>>
+ inline bool serialize(const T& v) {
+ return dap::Serializer::serialize(v);
+ }
+
+ template <typename T>
+ inline bool serialize(const dap::array<T>& v) {
+ return dap::Serializer::serialize(v);
+ }
+
+ template <typename T>
+ inline bool serialize(const dap::optional<T>& v) {
+ return dap::Serializer::serialize(v);
+ }
+
+ template <typename T0, typename... Types>
+ inline bool serialize(const dap::variant<T0, Types...>& v) {
+ return dap::Serializer::serialize(v);
+ }
+
+ inline bool serialize(const char* v) { return dap::Serializer::serialize(v); }
+
+ private:
+ JsonCppSerializer(Json::Value*);
+ Json::Value* const json;
+ const bool ownsJson;
+ bool removed = false;
+};
+
+} // namespace json
+} // namespace dap
+
+#endif // dap_jsoncpp_json_serializer_h
diff --git a/Utilities/cmcppdap/src/network.cpp b/Utilities/cmcppdap/src/network.cpp
new file mode 100644
index 0000000..613c234
--- /dev/null
+++ b/Utilities/cmcppdap/src/network.cpp
@@ -0,0 +1,100 @@
+// Copyright 2019 Google LLC
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// https://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#include "dap/network.h"
+
+#include "socket.h"
+
+#include <atomic>
+#include <mutex>
+#include <string>
+#include <thread>
+
+namespace {
+
+class Impl : public dap::net::Server {
+ public:
+ Impl() : stopped{true} {}
+
+ ~Impl() { stop(); }
+
+ bool start(int port,
+ const OnConnect& onConnect,
+ const OnError& onError) override {
+ std::unique_lock<std::mutex> lock(mutex);
+ stopWithLock();
+ socket = std::unique_ptr<dap::Socket>(
+ new dap::Socket("localhost", std::to_string(port).c_str()));
+
+ if (!socket->isOpen()) {
+ onError("Failed to open socket");
+ return false;
+ }
+
+ stopped = false;
+ thread = std::thread([=] {
+ while (true) {
+ if (auto rw = socket->accept()) {
+ onConnect(rw);
+ continue;
+ }
+ if (!stopped) {
+ onError("Failed to accept connection");
+ }
+ break;
+ };
+ });
+
+ return true;
+ }
+
+ void stop() override {
+ std::unique_lock<std::mutex> lock(mutex);
+ stopWithLock();
+ }
+
+ private:
+ bool isRunning() { return !stopped; }
+
+ void stopWithLock() {
+ if (!stopped.exchange(true)) {
+ socket->close();
+ thread.join();
+ }
+ }
+
+ std::mutex mutex;
+ std::thread thread;
+ std::unique_ptr<dap::Socket> socket;
+ std::atomic<bool> stopped;
+ OnError errorHandler;
+};
+
+} // anonymous namespace
+
+namespace dap {
+namespace net {
+
+std::unique_ptr<Server> Server::create() {
+ return std::unique_ptr<Server>(new Impl());
+}
+
+std::shared_ptr<ReaderWriter> connect(const char* addr,
+ int port,
+ uint32_t timeoutMillis) {
+ return Socket::connect(addr, std::to_string(port).c_str(), timeoutMillis);
+}
+
+} // namespace net
+} // namespace dap
diff --git a/Utilities/cmcppdap/src/network_test.cpp b/Utilities/cmcppdap/src/network_test.cpp
new file mode 100644
index 0000000..57bb0a9
--- /dev/null
+++ b/Utilities/cmcppdap/src/network_test.cpp
@@ -0,0 +1,110 @@
+// Copyright 2019 Google LLC
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// https://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#include "dap/network.h"
+#include "dap/io.h"
+
+#include "chan.h"
+
+#include "gmock/gmock.h"
+#include "gtest/gtest.h"
+
+#include <chrono>
+#include <thread>
+
+namespace {
+
+constexpr int port = 19021;
+
+bool write(const std::shared_ptr<dap::Writer>& w, const std::string& s) {
+ return w->write(s.data(), s.size()) && w->write("\0", 1);
+}
+
+std::string read(const std::shared_ptr<dap::Reader>& r) {
+ char c;
+ std::string s;
+ while (r->read(&c, sizeof(c)) > 0) {
+ if (c == '\0') {
+ return s;
+ }
+ s += c;
+ }
+ return r->isOpen() ? "<read failed>" : "<stream closed>";
+}
+
+} // anonymous namespace
+
+TEST(Network, ClientServer) {
+ dap::Chan<bool> done;
+ auto server = dap::net::Server::create();
+ if (!server->start(
+ port,
+ [&](const std::shared_ptr<dap::ReaderWriter>& rw) {
+ ASSERT_EQ(read(rw), "client to server");
+ ASSERT_TRUE(write(rw, "server to client"));
+ done.put(true);
+ },
+ [&](const char* err) { FAIL() << "Server error: " << err; })) {
+ FAIL() << "Couldn't start server";
+ return;
+ }
+
+ for (int i = 0; i < 5; i++) {
+ auto client = dap::net::connect("localhost", port);
+ ASSERT_NE(client, nullptr) << "Failed to connect client " << i;
+ ASSERT_TRUE(write(client, "client to server"));
+ ASSERT_EQ(read(client), "server to client");
+ done.take();
+ std::this_thread::sleep_for(std::chrono::seconds(1));
+ }
+
+ server.reset();
+}
+
+TEST(Network, ServerRepeatStopAndRestart) {
+ dap::Chan<bool> done;
+ auto onConnect = [&](const std::shared_ptr<dap::ReaderWriter>& rw) {
+ ASSERT_EQ(read(rw), "client to server");
+ ASSERT_TRUE(write(rw, "server to client"));
+ done.put(true);
+ };
+ auto onError = [&](const char* err) { FAIL() << "Server error: " << err; };
+
+ auto server = dap::net::Server::create();
+ if (!server->start(port, onConnect, onError)) {
+ FAIL() << "Couldn't start server";
+ return;
+ }
+
+ server->stop();
+ server->stop();
+ server->stop();
+
+ if (!server->start(port, onConnect, onError)) {
+ FAIL() << "Couldn't restart server";
+ return;
+ }
+
+ auto client = dap::net::connect("localhost", port);
+ ASSERT_NE(client, nullptr) << "Failed to connect";
+ ASSERT_TRUE(write(client, "client to server"));
+ ASSERT_EQ(read(client), "server to client");
+ done.take();
+
+ server->stop();
+ server->stop();
+ server->stop();
+
+ server.reset();
+}
diff --git a/Utilities/cmcppdap/src/nlohmann_json_serializer.cpp b/Utilities/cmcppdap/src/nlohmann_json_serializer.cpp
new file mode 100644
index 0000000..7834230
--- /dev/null
+++ b/Utilities/cmcppdap/src/nlohmann_json_serializer.cpp
@@ -0,0 +1,260 @@
+// Copyright 2019 Google LLC
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// https://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#include "nlohmann_json_serializer.h"
+
+#include "null_json_serializer.h"
+
+// Disable JSON exceptions. We should be guarding against any exceptions being
+// fired in this file.
+#define JSON_NOEXCEPTION 1
+#include <nlohmann/json.hpp>
+
+namespace dap {
+namespace json {
+
+NlohmannDeserializer::NlohmannDeserializer(const std::string& str)
+ : json(new nlohmann::json(nlohmann::json::parse(str, nullptr, false))),
+ ownsJson(true) {}
+
+NlohmannDeserializer::NlohmannDeserializer(const nlohmann::json* json)
+ : json(json), ownsJson(false) {}
+
+NlohmannDeserializer::~NlohmannDeserializer() {
+ if (ownsJson) {
+ delete json;
+ }
+}
+
+bool NlohmannDeserializer::deserialize(dap::boolean* v) const {
+ if (!json->is_boolean()) {
+ return false;
+ }
+ *v = json->get<bool>();
+ return true;
+}
+
+bool NlohmannDeserializer::deserialize(dap::integer* v) const {
+ if (!json->is_number_integer()) {
+ return false;
+ }
+ *v = json->get<int64_t>();
+ return true;
+}
+
+bool NlohmannDeserializer::deserialize(dap::number* v) const {
+ if (!json->is_number()) {
+ return false;
+ }
+ *v = json->get<double>();
+ return true;
+}
+
+bool NlohmannDeserializer::deserialize(dap::string* v) const {
+ if (!json->is_string()) {
+ return false;
+ }
+ *v = json->get<std::string>();
+ return true;
+}
+
+bool NlohmannDeserializer::deserialize(dap::object* v) const {
+ v->reserve(json->size());
+ for (auto& el : json->items()) {
+ NlohmannDeserializer d(&el.value());
+ dap::any val;
+ if (!d.deserialize(&val)) {
+ return false;
+ }
+ (*v)[el.key()] = val;
+ }
+ return true;
+}
+
+bool NlohmannDeserializer::deserialize(dap::any* v) const {
+ if (json->is_boolean()) {
+ *v = dap::boolean(json->get<bool>());
+ } else if (json->is_number_float()) {
+ *v = dap::number(json->get<double>());
+ } else if (json->is_number_integer()) {
+ *v = dap::integer(json->get<int64_t>());
+ } else if (json->is_string()) {
+ *v = json->get<std::string>();
+ } else if (json->is_object()) {
+ dap::object obj;
+ if (!deserialize(&obj)) {
+ return false;
+ }
+ *v = obj;
+ } else if (json->is_array()) {
+ dap::array<any> arr;
+ if (!deserialize(&arr)) {
+ return false;
+ }
+ *v = arr;
+ } else if (json->is_null()) {
+ *v = null();
+ } else {
+ return false;
+ }
+ return true;
+}
+
+size_t NlohmannDeserializer::count() const {
+ return json->size();
+}
+
+bool NlohmannDeserializer::array(
+ const std::function<bool(dap::Deserializer*)>& cb) const {
+ if (!json->is_array()) {
+ return false;
+ }
+ for (size_t i = 0; i < json->size(); i++) {
+ NlohmannDeserializer d(&(*json)[i]);
+ if (!cb(&d)) {
+ return false;
+ }
+ }
+ return true;
+}
+
+bool NlohmannDeserializer::field(
+ const std::string& name,
+ const std::function<bool(dap::Deserializer*)>& cb) const {
+ if (!json->is_structured()) {
+ return false;
+ }
+ auto it = json->find(name);
+ if (it == json->end()) {
+ return cb(&NullDeserializer::instance);
+ }
+ auto obj = *it;
+ NlohmannDeserializer d(&obj);
+ return cb(&d);
+}
+
+NlohmannSerializer::NlohmannSerializer()
+ : json(new nlohmann::json()), ownsJson(true) {}
+
+NlohmannSerializer::NlohmannSerializer(nlohmann::json* json)
+ : json(json), ownsJson(false) {}
+
+NlohmannSerializer::~NlohmannSerializer() {
+ if (ownsJson) {
+ delete json;
+ }
+}
+
+std::string NlohmannSerializer::dump() const {
+ return json->dump();
+}
+
+bool NlohmannSerializer::serialize(dap::boolean v) {
+ *json = (bool)v;
+ return true;
+}
+
+bool NlohmannSerializer::serialize(dap::integer v) {
+ *json = (int64_t)v;
+ return true;
+}
+
+bool NlohmannSerializer::serialize(dap::number v) {
+ *json = (double)v;
+ return true;
+}
+
+bool NlohmannSerializer::serialize(const dap::string& v) {
+ *json = v;
+ return true;
+}
+
+bool NlohmannSerializer::serialize(const dap::object& v) {
+ if (!json->is_object()) {
+ *json = nlohmann::json::object();
+ }
+ for (auto& it : v) {
+ NlohmannSerializer s(&(*json)[it.first]);
+ if (!s.serialize(it.second)) {
+ return false;
+ }
+ }
+ return true;
+}
+
+bool NlohmannSerializer::serialize(const dap::any& v) {
+ if (v.is<dap::boolean>()) {
+ *json = (bool)v.get<dap::boolean>();
+ } else if (v.is<dap::integer>()) {
+ *json = (int64_t)v.get<dap::integer>();
+ } else if (v.is<dap::number>()) {
+ *json = (double)v.get<dap::number>();
+ } else if (v.is<dap::string>()) {
+ *json = v.get<dap::string>();
+ } else if (v.is<dap::object>()) {
+ // reachable if dap::object nested is inside other dap::object
+ return serialize(v.get<dap::object>());
+ } else if (v.is<dap::null>()) {
+ } else {
+ // reachable if array or custom serialized type is nested inside other
+ auto type = get_any_type(v);
+ auto value = get_any_val(v);
+ if (type && value) {
+ return type->serialize(this, value);
+ }
+ return false;
+ }
+ return true;
+}
+
+bool NlohmannSerializer::array(
+ size_t count,
+ const std::function<bool(dap::Serializer*)>& cb) {
+ *json = std::vector<int>();
+ for (size_t i = 0; i < count; i++) {
+ NlohmannSerializer s(&(*json)[i]);
+ if (!cb(&s)) {
+ return false;
+ }
+ }
+ return true;
+}
+
+bool NlohmannSerializer::object(
+ const std::function<bool(dap::FieldSerializer*)>& cb) {
+ struct FS : public FieldSerializer {
+ nlohmann::json* const json;
+
+ FS(nlohmann::json* json) : json(json) {}
+ bool field(const std::string& name, const SerializeFunc& cb) override {
+ NlohmannSerializer s(&(*json)[name]);
+ auto res = cb(&s);
+ if (s.removed) {
+ json->erase(name);
+ }
+ return res;
+ }
+ };
+
+ *json = nlohmann::json({}, false, nlohmann::json::value_t::object);
+ FS fs{json};
+ return cb(&fs);
+}
+
+void NlohmannSerializer::remove() {
+ removed = true;
+}
+
+} // namespace json
+} // namespace dap
diff --git a/Utilities/cmcppdap/src/nlohmann_json_serializer.h b/Utilities/cmcppdap/src/nlohmann_json_serializer.h
new file mode 100644
index 0000000..38e47c9
--- /dev/null
+++ b/Utilities/cmcppdap/src/nlohmann_json_serializer.h
@@ -0,0 +1,133 @@
+// Copyright 2019 Google LLC
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// https://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#ifndef dap_nlohmann_json_serializer_h
+#define dap_nlohmann_json_serializer_h
+
+#include "dap/protocol.h"
+#include "dap/serialization.h"
+#include "dap/types.h"
+
+#include <nlohmann/json_fwd.hpp>
+
+namespace dap {
+namespace json {
+
+struct NlohmannDeserializer : public dap::Deserializer {
+ explicit NlohmannDeserializer(const std::string&);
+ ~NlohmannDeserializer();
+
+ // dap::Deserializer compliance
+ bool deserialize(boolean* v) const override;
+ bool deserialize(integer* v) const override;
+ bool deserialize(number* v) const override;
+ bool deserialize(string* v) const override;
+ bool deserialize(object* v) const override;
+ bool deserialize(any* v) const override;
+ size_t count() const override;
+ bool array(const std::function<bool(dap::Deserializer*)>&) const override;
+ bool field(const std::string& name,
+ const std::function<bool(dap::Deserializer*)>&) const override;
+
+ // Unhide base overloads
+ template <typename T>
+ inline bool field(const std::string& name, T* v) {
+ return dap::Deserializer::field(name, v);
+ }
+
+ template <typename T,
+ typename = std::enable_if<TypeOf<T>::has_custom_serialization>>
+ inline bool deserialize(T* v) const {
+ return dap::Deserializer::deserialize(v);
+ }
+
+ template <typename T>
+ inline bool deserialize(dap::array<T>* v) const {
+ return dap::Deserializer::deserialize(v);
+ }
+
+ template <typename T>
+ inline bool deserialize(dap::optional<T>* v) const {
+ return dap::Deserializer::deserialize(v);
+ }
+
+ template <typename T0, typename... Types>
+ inline bool deserialize(dap::variant<T0, Types...>* v) const {
+ return dap::Deserializer::deserialize(v);
+ }
+
+ template <typename T>
+ inline bool field(const std::string& name, T* v) const {
+ return dap::Deserializer::deserialize(name, v);
+ }
+
+ private:
+ NlohmannDeserializer(const nlohmann::json*);
+ const nlohmann::json* const json;
+ const bool ownsJson;
+};
+
+struct NlohmannSerializer : public dap::Serializer {
+ NlohmannSerializer();
+ ~NlohmannSerializer();
+
+ std::string dump() const;
+
+ // dap::Serializer compliance
+ bool serialize(boolean v) override;
+ bool serialize(integer v) override;
+ bool serialize(number v) override;
+ bool serialize(const string& v) override;
+ bool serialize(const dap::object& v) override;
+ bool serialize(const any& v) override;
+ bool array(size_t count,
+ const std::function<bool(dap::Serializer*)>&) override;
+ bool object(const std::function<bool(dap::FieldSerializer*)>&) override;
+ void remove() override;
+
+ // Unhide base overloads
+ template <typename T,
+ typename = std::enable_if<TypeOf<T>::has_custom_serialization>>
+ inline bool serialize(const T& v) {
+ return dap::Serializer::serialize(v);
+ }
+
+ template <typename T>
+ inline bool serialize(const dap::array<T>& v) {
+ return dap::Serializer::serialize(v);
+ }
+
+ template <typename T>
+ inline bool serialize(const dap::optional<T>& v) {
+ return dap::Serializer::serialize(v);
+ }
+
+ template <typename T0, typename... Types>
+ inline bool serialize(const dap::variant<T0, Types...>& v) {
+ return dap::Serializer::serialize(v);
+ }
+
+ inline bool serialize(const char* v) { return dap::Serializer::serialize(v); }
+
+ private:
+ NlohmannSerializer(nlohmann::json*);
+ nlohmann::json* const json;
+ const bool ownsJson;
+ bool removed = false;
+};
+
+} // namespace json
+} // namespace dap
+
+#endif // dap_nlohmann_json_serializer_h
diff --git a/Utilities/cmcppdap/src/null_json_serializer.cpp b/Utilities/cmcppdap/src/null_json_serializer.cpp
new file mode 100644
index 0000000..5aa5a03
--- /dev/null
+++ b/Utilities/cmcppdap/src/null_json_serializer.cpp
@@ -0,0 +1,23 @@
+// Copyright 2020 Google LLC
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// https://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#include "null_json_serializer.h"
+
+namespace dap {
+namespace json {
+
+NullDeserializer NullDeserializer::instance;
+
+} // namespace json
+} // namespace dap
diff --git a/Utilities/cmcppdap/src/null_json_serializer.h b/Utilities/cmcppdap/src/null_json_serializer.h
new file mode 100644
index 0000000..c92b99a
--- /dev/null
+++ b/Utilities/cmcppdap/src/null_json_serializer.h
@@ -0,0 +1,47 @@
+// Copyright 2020 Google LLC
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// https://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#ifndef dap_null_json_serializer_h
+#define dap_null_json_serializer_h
+
+#include "dap/protocol.h"
+#include "dap/serialization.h"
+#include "dap/types.h"
+
+namespace dap {
+namespace json {
+
+struct NullDeserializer : public dap::Deserializer {
+ static NullDeserializer instance;
+
+ bool deserialize(dap::boolean*) const override { return false; }
+ bool deserialize(dap::integer*) const override { return false; }
+ bool deserialize(dap::number*) const override { return false; }
+ bool deserialize(dap::string*) const override { return false; }
+ bool deserialize(dap::object*) const override { return false; }
+ bool deserialize(dap::any*) const override { return false; }
+ size_t count() const override { return 0; }
+ bool array(const std::function<bool(dap::Deserializer*)>&) const override {
+ return false;
+ }
+ bool field(const std::string&,
+ const std::function<bool(dap::Deserializer*)>&) const override {
+ return false;
+ }
+};
+
+} // namespace json
+} // namespace dap
+
+#endif // dap_null_json_serializer_h
diff --git a/Utilities/cmcppdap/src/optional_test.cpp b/Utilities/cmcppdap/src/optional_test.cpp
new file mode 100644
index 0000000..b2590fc
--- /dev/null
+++ b/Utilities/cmcppdap/src/optional_test.cpp
@@ -0,0 +1,169 @@
+// Copyright 2019 Google LLC
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// https://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#include "dap/optional.h"
+
+#include "gmock/gmock.h"
+#include "gtest/gtest.h"
+
+#include <string>
+
+TEST(Optional, EmptyConstruct) {
+ dap::optional<std::string> opt;
+ ASSERT_FALSE(opt);
+ ASSERT_FALSE(opt.has_value());
+}
+
+TEST(Optional, ValueConstruct) {
+ dap::optional<int> opt(10);
+ ASSERT_TRUE(opt);
+ ASSERT_TRUE(opt.has_value());
+ ASSERT_EQ(opt.value(), 10);
+}
+
+TEST(Optional, CopyConstruct) {
+ dap::optional<std::string> a("meow");
+ dap::optional<std::string> b(a);
+ ASSERT_EQ(a, b);
+ ASSERT_EQ(a.value(), "meow");
+ ASSERT_EQ(b.value(), "meow");
+}
+
+TEST(Optional, CopyCastConstruct) {
+ dap::optional<int> a(10);
+ dap::optional<uint16_t> b(a);
+ ASSERT_EQ(a, b);
+ ASSERT_EQ(b.value(), (uint16_t)10);
+}
+
+TEST(Optional, MoveConstruct) {
+ dap::optional<std::string> a("meow");
+ dap::optional<std::string> b(std::move(a));
+ ASSERT_EQ(b.value(), "meow");
+}
+
+TEST(Optional, MoveCastConstruct) {
+ dap::optional<int> a(10);
+ dap::optional<uint16_t> b(std::move(a));
+ ASSERT_EQ(b.value(), (uint16_t)10);
+}
+
+TEST(Optional, AssignValue) {
+ dap::optional<std::string> a;
+ std::string b = "meow";
+ a = b;
+ ASSERT_EQ(a.value(), "meow");
+ ASSERT_EQ(b, "meow");
+}
+
+TEST(Optional, AssignOptional) {
+ dap::optional<std::string> a;
+ dap::optional<std::string> b("meow");
+ a = b;
+ ASSERT_EQ(a.value(), "meow");
+ ASSERT_EQ(b.value(), "meow");
+}
+
+TEST(Optional, MoveAssignOptional) {
+ dap::optional<std::string> a;
+ dap::optional<std::string> b("meow");
+ a = std::move(b);
+ ASSERT_EQ(a.value(), "meow");
+}
+
+TEST(Optional, StarDeref) {
+ dap::optional<std::string> a("meow");
+ ASSERT_EQ(*a, "meow");
+}
+
+TEST(Optional, StarDerefConst) {
+ const dap::optional<std::string> a("meow");
+ ASSERT_EQ(*a, "meow");
+}
+
+TEST(Optional, ArrowDeref) {
+ struct S {
+ int i;
+ };
+ dap::optional<S> a(S{10});
+ ASSERT_EQ(a->i, 10);
+}
+
+TEST(Optional, ArrowDerefConst) {
+ struct S {
+ int i;
+ };
+ const dap::optional<S> a(S{10});
+ ASSERT_EQ(a->i, 10);
+}
+
+TEST(Optional, Value) {
+ const dap::optional<std::string> a("meow");
+ ASSERT_EQ(a.value(), "meow");
+}
+
+TEST(Optional, ValueDefault) {
+ const dap::optional<std::string> a;
+ const dap::optional<std::string> b("woof");
+ ASSERT_EQ(a.value("meow"), "meow");
+ ASSERT_EQ(b.value("meow"), "woof");
+}
+
+TEST(Optional, CompareLT) {
+ ASSERT_FALSE(dap::optional<int>(5) < dap::optional<int>(3));
+ ASSERT_FALSE(dap::optional<int>(5) < dap::optional<int>(5));
+ ASSERT_TRUE(dap::optional<int>(5) < dap::optional<int>(10));
+ ASSERT_TRUE(dap::optional<int>() < dap::optional<int>(10));
+ ASSERT_FALSE(dap::optional<int>() < dap::optional<int>());
+}
+
+TEST(Optional, CompareLE) {
+ ASSERT_FALSE(dap::optional<int>(5) <= dap::optional<int>(3));
+ ASSERT_TRUE(dap::optional<int>(5) <= dap::optional<int>(5));
+ ASSERT_TRUE(dap::optional<int>(5) <= dap::optional<int>(10));
+ ASSERT_TRUE(dap::optional<int>() <= dap::optional<int>(10));
+ ASSERT_TRUE(dap::optional<int>() <= dap::optional<int>());
+}
+
+TEST(Optional, CompareGT) {
+ ASSERT_TRUE(dap::optional<int>(5) > dap::optional<int>(3));
+ ASSERT_FALSE(dap::optional<int>(5) > dap::optional<int>(5));
+ ASSERT_FALSE(dap::optional<int>(5) > dap::optional<int>(10));
+ ASSERT_FALSE(dap::optional<int>() > dap::optional<int>(10));
+ ASSERT_FALSE(dap::optional<int>() > dap::optional<int>());
+}
+
+TEST(Optional, CompareGE) {
+ ASSERT_TRUE(dap::optional<int>(5) >= dap::optional<int>(3));
+ ASSERT_TRUE(dap::optional<int>(5) >= dap::optional<int>(5));
+ ASSERT_FALSE(dap::optional<int>(5) >= dap::optional<int>(10));
+ ASSERT_FALSE(dap::optional<int>() >= dap::optional<int>(10));
+ ASSERT_TRUE(dap::optional<int>() >= dap::optional<int>());
+}
+
+TEST(Optional, CompareEQ) {
+ ASSERT_FALSE(dap::optional<int>(5) == dap::optional<int>(3));
+ ASSERT_TRUE(dap::optional<int>(5) == dap::optional<int>(5));
+ ASSERT_FALSE(dap::optional<int>(5) == dap::optional<int>(10));
+ ASSERT_FALSE(dap::optional<int>() == dap::optional<int>(10));
+ ASSERT_TRUE(dap::optional<int>() == dap::optional<int>());
+}
+
+TEST(Optional, CompareNEQ) {
+ ASSERT_TRUE(dap::optional<int>(5) != dap::optional<int>(3));
+ ASSERT_FALSE(dap::optional<int>(5) != dap::optional<int>(5));
+ ASSERT_TRUE(dap::optional<int>(5) != dap::optional<int>(10));
+ ASSERT_TRUE(dap::optional<int>() != dap::optional<int>(10));
+ ASSERT_FALSE(dap::optional<int>() != dap::optional<int>());
+}
diff --git a/Utilities/cmcppdap/src/protocol_events.cpp b/Utilities/cmcppdap/src/protocol_events.cpp
new file mode 100644
index 0000000..9deb85f
--- /dev/null
+++ b/Utilities/cmcppdap/src/protocol_events.cpp
@@ -0,0 +1,126 @@
+// Copyright 2019 Google LLC
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// https://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+// Generated with protocol_gen.go -- do not edit this file.
+// go run scripts/protocol_gen/protocol_gen.go
+//
+// DAP version 1.59.0
+
+#include "dap/protocol.h"
+
+namespace dap {
+
+DAP_IMPLEMENT_STRUCT_TYPEINFO(BreakpointEvent,
+ "breakpoint",
+ DAP_FIELD(breakpoint, "breakpoint"),
+ DAP_FIELD(reason, "reason"));
+
+DAP_IMPLEMENT_STRUCT_TYPEINFO(CapabilitiesEvent,
+ "capabilities",
+ DAP_FIELD(capabilities, "capabilities"));
+
+DAP_IMPLEMENT_STRUCT_TYPEINFO(ContinuedEvent,
+ "continued",
+ DAP_FIELD(allThreadsContinued,
+ "allThreadsContinued"),
+ DAP_FIELD(threadId, "threadId"));
+
+DAP_IMPLEMENT_STRUCT_TYPEINFO(ExitedEvent,
+ "exited",
+ DAP_FIELD(exitCode, "exitCode"));
+
+DAP_IMPLEMENT_STRUCT_TYPEINFO(InitializedEvent, "initialized");
+
+DAP_IMPLEMENT_STRUCT_TYPEINFO(InvalidatedEvent,
+ "invalidated",
+ DAP_FIELD(areas, "areas"),
+ DAP_FIELD(stackFrameId, "stackFrameId"),
+ DAP_FIELD(threadId, "threadId"));
+
+DAP_IMPLEMENT_STRUCT_TYPEINFO(LoadedSourceEvent,
+ "loadedSource",
+ DAP_FIELD(reason, "reason"),
+ DAP_FIELD(source, "source"));
+
+DAP_IMPLEMENT_STRUCT_TYPEINFO(MemoryEvent,
+ "memory",
+ DAP_FIELD(count, "count"),
+ DAP_FIELD(memoryReference, "memoryReference"),
+ DAP_FIELD(offset, "offset"));
+
+DAP_IMPLEMENT_STRUCT_TYPEINFO(ModuleEvent,
+ "module",
+ DAP_FIELD(module, "module"),
+ DAP_FIELD(reason, "reason"));
+
+DAP_IMPLEMENT_STRUCT_TYPEINFO(OutputEvent,
+ "output",
+ DAP_FIELD(category, "category"),
+ DAP_FIELD(column, "column"),
+ DAP_FIELD(data, "data"),
+ DAP_FIELD(group, "group"),
+ DAP_FIELD(line, "line"),
+ DAP_FIELD(output, "output"),
+ DAP_FIELD(source, "source"),
+ DAP_FIELD(variablesReference,
+ "variablesReference"));
+
+DAP_IMPLEMENT_STRUCT_TYPEINFO(ProcessEvent,
+ "process",
+ DAP_FIELD(isLocalProcess, "isLocalProcess"),
+ DAP_FIELD(name, "name"),
+ DAP_FIELD(pointerSize, "pointerSize"),
+ DAP_FIELD(startMethod, "startMethod"),
+ DAP_FIELD(systemProcessId, "systemProcessId"));
+
+DAP_IMPLEMENT_STRUCT_TYPEINFO(ProgressEndEvent,
+ "progressEnd",
+ DAP_FIELD(message, "message"),
+ DAP_FIELD(progressId, "progressId"));
+
+DAP_IMPLEMENT_STRUCT_TYPEINFO(ProgressStartEvent,
+ "progressStart",
+ DAP_FIELD(cancellable, "cancellable"),
+ DAP_FIELD(message, "message"),
+ DAP_FIELD(percentage, "percentage"),
+ DAP_FIELD(progressId, "progressId"),
+ DAP_FIELD(requestId, "requestId"),
+ DAP_FIELD(title, "title"));
+
+DAP_IMPLEMENT_STRUCT_TYPEINFO(ProgressUpdateEvent,
+ "progressUpdate",
+ DAP_FIELD(message, "message"),
+ DAP_FIELD(percentage, "percentage"),
+ DAP_FIELD(progressId, "progressId"));
+
+DAP_IMPLEMENT_STRUCT_TYPEINFO(StoppedEvent,
+ "stopped",
+ DAP_FIELD(allThreadsStopped, "allThreadsStopped"),
+ DAP_FIELD(description, "description"),
+ DAP_FIELD(hitBreakpointIds, "hitBreakpointIds"),
+ DAP_FIELD(preserveFocusHint, "preserveFocusHint"),
+ DAP_FIELD(reason, "reason"),
+ DAP_FIELD(text, "text"),
+ DAP_FIELD(threadId, "threadId"));
+
+DAP_IMPLEMENT_STRUCT_TYPEINFO(TerminatedEvent,
+ "terminated",
+ DAP_FIELD(restart, "restart"));
+
+DAP_IMPLEMENT_STRUCT_TYPEINFO(ThreadEvent,
+ "thread",
+ DAP_FIELD(reason, "reason"),
+ DAP_FIELD(threadId, "threadId"));
+
+} // namespace dap
diff --git a/Utilities/cmcppdap/src/protocol_requests.cpp b/Utilities/cmcppdap/src/protocol_requests.cpp
new file mode 100644
index 0000000..a3b33ec
--- /dev/null
+++ b/Utilities/cmcppdap/src/protocol_requests.cpp
@@ -0,0 +1,281 @@
+// Copyright 2019 Google LLC
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// https://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+// Generated with protocol_gen.go -- do not edit this file.
+// go run scripts/protocol_gen/protocol_gen.go
+//
+// DAP version 1.59.0
+
+#include "dap/protocol.h"
+
+namespace dap {
+
+DAP_IMPLEMENT_STRUCT_TYPEINFO(AttachRequest,
+ "attach",
+ DAP_FIELD(restart, "__restart"));
+
+DAP_IMPLEMENT_STRUCT_TYPEINFO(BreakpointLocationsRequest,
+ "breakpointLocations",
+ DAP_FIELD(column, "column"),
+ DAP_FIELD(endColumn, "endColumn"),
+ DAP_FIELD(endLine, "endLine"),
+ DAP_FIELD(line, "line"),
+ DAP_FIELD(source, "source"));
+
+DAP_IMPLEMENT_STRUCT_TYPEINFO(CancelRequest,
+ "cancel",
+ DAP_FIELD(progressId, "progressId"),
+ DAP_FIELD(requestId, "requestId"));
+
+DAP_IMPLEMENT_STRUCT_TYPEINFO(CompletionsRequest,
+ "completions",
+ DAP_FIELD(column, "column"),
+ DAP_FIELD(frameId, "frameId"),
+ DAP_FIELD(line, "line"),
+ DAP_FIELD(text, "text"));
+
+DAP_IMPLEMENT_STRUCT_TYPEINFO(ConfigurationDoneRequest, "configurationDone");
+
+DAP_IMPLEMENT_STRUCT_TYPEINFO(ContinueRequest,
+ "continue",
+ DAP_FIELD(singleThread, "singleThread"),
+ DAP_FIELD(threadId, "threadId"));
+
+DAP_IMPLEMENT_STRUCT_TYPEINFO(DataBreakpointInfoRequest,
+ "dataBreakpointInfo",
+ DAP_FIELD(frameId, "frameId"),
+ DAP_FIELD(name, "name"),
+ DAP_FIELD(variablesReference,
+ "variablesReference"));
+
+DAP_IMPLEMENT_STRUCT_TYPEINFO(DisassembleRequest,
+ "disassemble",
+ DAP_FIELD(instructionCount, "instructionCount"),
+ DAP_FIELD(instructionOffset, "instructionOffset"),
+ DAP_FIELD(memoryReference, "memoryReference"),
+ DAP_FIELD(offset, "offset"),
+ DAP_FIELD(resolveSymbols, "resolveSymbols"));
+
+DAP_IMPLEMENT_STRUCT_TYPEINFO(DisconnectRequest,
+ "disconnect",
+ DAP_FIELD(restart, "restart"),
+ DAP_FIELD(suspendDebuggee, "suspendDebuggee"),
+ DAP_FIELD(terminateDebuggee,
+ "terminateDebuggee"));
+
+DAP_IMPLEMENT_STRUCT_TYPEINFO(EvaluateRequest,
+ "evaluate",
+ DAP_FIELD(context, "context"),
+ DAP_FIELD(expression, "expression"),
+ DAP_FIELD(format, "format"),
+ DAP_FIELD(frameId, "frameId"));
+
+DAP_IMPLEMENT_STRUCT_TYPEINFO(ExceptionInfoRequest,
+ "exceptionInfo",
+ DAP_FIELD(threadId, "threadId"));
+
+DAP_IMPLEMENT_STRUCT_TYPEINFO(GotoRequest,
+ "goto",
+ DAP_FIELD(targetId, "targetId"),
+ DAP_FIELD(threadId, "threadId"));
+
+DAP_IMPLEMENT_STRUCT_TYPEINFO(GotoTargetsRequest,
+ "gotoTargets",
+ DAP_FIELD(column, "column"),
+ DAP_FIELD(line, "line"),
+ DAP_FIELD(source, "source"));
+
+DAP_IMPLEMENT_STRUCT_TYPEINFO(
+ InitializeRequest,
+ "initialize",
+ DAP_FIELD(adapterID, "adapterID"),
+ DAP_FIELD(clientID, "clientID"),
+ DAP_FIELD(clientName, "clientName"),
+ DAP_FIELD(columnsStartAt1, "columnsStartAt1"),
+ DAP_FIELD(linesStartAt1, "linesStartAt1"),
+ DAP_FIELD(locale, "locale"),
+ DAP_FIELD(pathFormat, "pathFormat"),
+ DAP_FIELD(supportsArgsCanBeInterpretedByShell,
+ "supportsArgsCanBeInterpretedByShell"),
+ DAP_FIELD(supportsInvalidatedEvent, "supportsInvalidatedEvent"),
+ DAP_FIELD(supportsMemoryEvent, "supportsMemoryEvent"),
+ DAP_FIELD(supportsMemoryReferences, "supportsMemoryReferences"),
+ DAP_FIELD(supportsProgressReporting, "supportsProgressReporting"),
+ DAP_FIELD(supportsRunInTerminalRequest, "supportsRunInTerminalRequest"),
+ DAP_FIELD(supportsStartDebuggingRequest, "supportsStartDebuggingRequest"),
+ DAP_FIELD(supportsVariablePaging, "supportsVariablePaging"),
+ DAP_FIELD(supportsVariableType, "supportsVariableType"));
+
+DAP_IMPLEMENT_STRUCT_TYPEINFO(LaunchRequest,
+ "launch",
+ DAP_FIELD(restart, "__restart"),
+ DAP_FIELD(noDebug, "noDebug"));
+
+DAP_IMPLEMENT_STRUCT_TYPEINFO(LoadedSourcesRequest, "loadedSources");
+
+DAP_IMPLEMENT_STRUCT_TYPEINFO(ModulesRequest,
+ "modules",
+ DAP_FIELD(moduleCount, "moduleCount"),
+ DAP_FIELD(startModule, "startModule"));
+
+DAP_IMPLEMENT_STRUCT_TYPEINFO(NextRequest,
+ "next",
+ DAP_FIELD(granularity, "granularity"),
+ DAP_FIELD(singleThread, "singleThread"),
+ DAP_FIELD(threadId, "threadId"));
+
+DAP_IMPLEMENT_STRUCT_TYPEINFO(PauseRequest,
+ "pause",
+ DAP_FIELD(threadId, "threadId"));
+
+DAP_IMPLEMENT_STRUCT_TYPEINFO(ReadMemoryRequest,
+ "readMemory",
+ DAP_FIELD(count, "count"),
+ DAP_FIELD(memoryReference, "memoryReference"),
+ DAP_FIELD(offset, "offset"));
+
+DAP_IMPLEMENT_STRUCT_TYPEINFO(RestartFrameRequest,
+ "restartFrame",
+ DAP_FIELD(frameId, "frameId"));
+
+DAP_IMPLEMENT_STRUCT_TYPEINFO(RestartRequest,
+ "restart",
+ DAP_FIELD(arguments, "arguments"));
+
+DAP_IMPLEMENT_STRUCT_TYPEINFO(ReverseContinueRequest,
+ "reverseContinue",
+ DAP_FIELD(singleThread, "singleThread"),
+ DAP_FIELD(threadId, "threadId"));
+
+DAP_IMPLEMENT_STRUCT_TYPEINFO(RunInTerminalRequest,
+ "runInTerminal",
+ DAP_FIELD(args, "args"),
+ DAP_FIELD(argsCanBeInterpretedByShell,
+ "argsCanBeInterpretedByShell"),
+ DAP_FIELD(cwd, "cwd"),
+ DAP_FIELD(env, "env"),
+ DAP_FIELD(kind, "kind"),
+ DAP_FIELD(title, "title"));
+
+DAP_IMPLEMENT_STRUCT_TYPEINFO(ScopesRequest,
+ "scopes",
+ DAP_FIELD(frameId, "frameId"));
+
+DAP_IMPLEMENT_STRUCT_TYPEINFO(SetBreakpointsRequest,
+ "setBreakpoints",
+ DAP_FIELD(breakpoints, "breakpoints"),
+ DAP_FIELD(lines, "lines"),
+ DAP_FIELD(source, "source"),
+ DAP_FIELD(sourceModified, "sourceModified"));
+
+DAP_IMPLEMENT_STRUCT_TYPEINFO(SetDataBreakpointsRequest,
+ "setDataBreakpoints",
+ DAP_FIELD(breakpoints, "breakpoints"));
+
+DAP_IMPLEMENT_STRUCT_TYPEINFO(SetExceptionBreakpointsRequest,
+ "setExceptionBreakpoints",
+ DAP_FIELD(exceptionOptions, "exceptionOptions"),
+ DAP_FIELD(filterOptions, "filterOptions"),
+ DAP_FIELD(filters, "filters"));
+
+DAP_IMPLEMENT_STRUCT_TYPEINFO(SetExpressionRequest,
+ "setExpression",
+ DAP_FIELD(expression, "expression"),
+ DAP_FIELD(format, "format"),
+ DAP_FIELD(frameId, "frameId"),
+ DAP_FIELD(value, "value"));
+
+DAP_IMPLEMENT_STRUCT_TYPEINFO(SetFunctionBreakpointsRequest,
+ "setFunctionBreakpoints",
+ DAP_FIELD(breakpoints, "breakpoints"));
+
+DAP_IMPLEMENT_STRUCT_TYPEINFO(SetInstructionBreakpointsRequest,
+ "setInstructionBreakpoints",
+ DAP_FIELD(breakpoints, "breakpoints"));
+
+DAP_IMPLEMENT_STRUCT_TYPEINFO(SetVariableRequest,
+ "setVariable",
+ DAP_FIELD(format, "format"),
+ DAP_FIELD(name, "name"),
+ DAP_FIELD(value, "value"),
+ DAP_FIELD(variablesReference,
+ "variablesReference"));
+
+DAP_IMPLEMENT_STRUCT_TYPEINFO(SourceRequest,
+ "source",
+ DAP_FIELD(source, "source"),
+ DAP_FIELD(sourceReference, "sourceReference"));
+
+DAP_IMPLEMENT_STRUCT_TYPEINFO(StackTraceRequest,
+ "stackTrace",
+ DAP_FIELD(format, "format"),
+ DAP_FIELD(levels, "levels"),
+ DAP_FIELD(startFrame, "startFrame"),
+ DAP_FIELD(threadId, "threadId"));
+
+DAP_IMPLEMENT_STRUCT_TYPEINFO(StartDebuggingRequest,
+ "startDebugging",
+ DAP_FIELD(configuration, "configuration"),
+ DAP_FIELD(request, "request"));
+
+DAP_IMPLEMENT_STRUCT_TYPEINFO(StepBackRequest,
+ "stepBack",
+ DAP_FIELD(granularity, "granularity"),
+ DAP_FIELD(singleThread, "singleThread"),
+ DAP_FIELD(threadId, "threadId"));
+
+DAP_IMPLEMENT_STRUCT_TYPEINFO(StepInRequest,
+ "stepIn",
+ DAP_FIELD(granularity, "granularity"),
+ DAP_FIELD(singleThread, "singleThread"),
+ DAP_FIELD(targetId, "targetId"),
+ DAP_FIELD(threadId, "threadId"));
+
+DAP_IMPLEMENT_STRUCT_TYPEINFO(StepInTargetsRequest,
+ "stepInTargets",
+ DAP_FIELD(frameId, "frameId"));
+
+DAP_IMPLEMENT_STRUCT_TYPEINFO(StepOutRequest,
+ "stepOut",
+ DAP_FIELD(granularity, "granularity"),
+ DAP_FIELD(singleThread, "singleThread"),
+ DAP_FIELD(threadId, "threadId"));
+
+DAP_IMPLEMENT_STRUCT_TYPEINFO(TerminateRequest,
+ "terminate",
+ DAP_FIELD(restart, "restart"));
+
+DAP_IMPLEMENT_STRUCT_TYPEINFO(TerminateThreadsRequest,
+ "terminateThreads",
+ DAP_FIELD(threadIds, "threadIds"));
+
+DAP_IMPLEMENT_STRUCT_TYPEINFO(ThreadsRequest, "threads");
+
+DAP_IMPLEMENT_STRUCT_TYPEINFO(VariablesRequest,
+ "variables",
+ DAP_FIELD(count, "count"),
+ DAP_FIELD(filter, "filter"),
+ DAP_FIELD(format, "format"),
+ DAP_FIELD(start, "start"),
+ DAP_FIELD(variablesReference,
+ "variablesReference"));
+
+DAP_IMPLEMENT_STRUCT_TYPEINFO(WriteMemoryRequest,
+ "writeMemory",
+ DAP_FIELD(allowPartial, "allowPartial"),
+ DAP_FIELD(data, "data"),
+ DAP_FIELD(memoryReference, "memoryReference"),
+ DAP_FIELD(offset, "offset"));
+
+} // namespace dap
diff --git a/Utilities/cmcppdap/src/protocol_response.cpp b/Utilities/cmcppdap/src/protocol_response.cpp
new file mode 100644
index 0000000..bab8ebb
--- /dev/null
+++ b/Utilities/cmcppdap/src/protocol_response.cpp
@@ -0,0 +1,243 @@
+// Copyright 2019 Google LLC
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// https://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+// Generated with protocol_gen.go -- do not edit this file.
+// go run scripts/protocol_gen/protocol_gen.go
+//
+// DAP version 1.59.0
+
+#include "dap/protocol.h"
+
+namespace dap {
+
+DAP_IMPLEMENT_STRUCT_TYPEINFO(AttachResponse, "");
+
+DAP_IMPLEMENT_STRUCT_TYPEINFO(BreakpointLocationsResponse,
+ "",
+ DAP_FIELD(breakpoints, "breakpoints"));
+
+DAP_IMPLEMENT_STRUCT_TYPEINFO(CancelResponse, "");
+
+DAP_IMPLEMENT_STRUCT_TYPEINFO(CompletionsResponse,
+ "",
+ DAP_FIELD(targets, "targets"));
+
+DAP_IMPLEMENT_STRUCT_TYPEINFO(ConfigurationDoneResponse, "");
+
+DAP_IMPLEMENT_STRUCT_TYPEINFO(ContinueResponse,
+ "",
+ DAP_FIELD(allThreadsContinued,
+ "allThreadsContinued"));
+
+DAP_IMPLEMENT_STRUCT_TYPEINFO(DataBreakpointInfoResponse,
+ "",
+ DAP_FIELD(accessTypes, "accessTypes"),
+ DAP_FIELD(canPersist, "canPersist"),
+ DAP_FIELD(dataId, "dataId"),
+ DAP_FIELD(description, "description"));
+
+DAP_IMPLEMENT_STRUCT_TYPEINFO(DisassembleResponse,
+ "",
+ DAP_FIELD(instructions, "instructions"));
+
+DAP_IMPLEMENT_STRUCT_TYPEINFO(DisconnectResponse, "");
+
+DAP_IMPLEMENT_STRUCT_TYPEINFO(ErrorResponse, "", DAP_FIELD(error, "error"));
+
+DAP_IMPLEMENT_STRUCT_TYPEINFO(EvaluateResponse,
+ "",
+ DAP_FIELD(indexedVariables, "indexedVariables"),
+ DAP_FIELD(memoryReference, "memoryReference"),
+ DAP_FIELD(namedVariables, "namedVariables"),
+ DAP_FIELD(presentationHint, "presentationHint"),
+ DAP_FIELD(result, "result"),
+ DAP_FIELD(type, "type"),
+ DAP_FIELD(variablesReference,
+ "variablesReference"));
+
+DAP_IMPLEMENT_STRUCT_TYPEINFO(ExceptionInfoResponse,
+ "",
+ DAP_FIELD(breakMode, "breakMode"),
+ DAP_FIELD(description, "description"),
+ DAP_FIELD(details, "details"),
+ DAP_FIELD(exceptionId, "exceptionId"));
+
+DAP_IMPLEMENT_STRUCT_TYPEINFO(GotoResponse, "");
+
+DAP_IMPLEMENT_STRUCT_TYPEINFO(GotoTargetsResponse,
+ "",
+ DAP_FIELD(targets, "targets"));
+
+DAP_IMPLEMENT_STRUCT_TYPEINFO(
+ InitializeResponse,
+ "",
+ DAP_FIELD(additionalModuleColumns, "additionalModuleColumns"),
+ DAP_FIELD(completionTriggerCharacters, "completionTriggerCharacters"),
+ DAP_FIELD(exceptionBreakpointFilters, "exceptionBreakpointFilters"),
+ DAP_FIELD(supportSuspendDebuggee, "supportSuspendDebuggee"),
+ DAP_FIELD(supportTerminateDebuggee, "supportTerminateDebuggee"),
+ DAP_FIELD(supportedChecksumAlgorithms, "supportedChecksumAlgorithms"),
+ DAP_FIELD(supportsBreakpointLocationsRequest,
+ "supportsBreakpointLocationsRequest"),
+ DAP_FIELD(supportsCancelRequest, "supportsCancelRequest"),
+ DAP_FIELD(supportsClipboardContext, "supportsClipboardContext"),
+ DAP_FIELD(supportsCompletionsRequest, "supportsCompletionsRequest"),
+ DAP_FIELD(supportsConditionalBreakpoints, "supportsConditionalBreakpoints"),
+ DAP_FIELD(supportsConfigurationDoneRequest,
+ "supportsConfigurationDoneRequest"),
+ DAP_FIELD(supportsDataBreakpoints, "supportsDataBreakpoints"),
+ DAP_FIELD(supportsDelayedStackTraceLoading,
+ "supportsDelayedStackTraceLoading"),
+ DAP_FIELD(supportsDisassembleRequest, "supportsDisassembleRequest"),
+ DAP_FIELD(supportsEvaluateForHovers, "supportsEvaluateForHovers"),
+ DAP_FIELD(supportsExceptionFilterOptions, "supportsExceptionFilterOptions"),
+ DAP_FIELD(supportsExceptionInfoRequest, "supportsExceptionInfoRequest"),
+ DAP_FIELD(supportsExceptionOptions, "supportsExceptionOptions"),
+ DAP_FIELD(supportsFunctionBreakpoints, "supportsFunctionBreakpoints"),
+ DAP_FIELD(supportsGotoTargetsRequest, "supportsGotoTargetsRequest"),
+ DAP_FIELD(supportsHitConditionalBreakpoints,
+ "supportsHitConditionalBreakpoints"),
+ DAP_FIELD(supportsInstructionBreakpoints, "supportsInstructionBreakpoints"),
+ DAP_FIELD(supportsLoadedSourcesRequest, "supportsLoadedSourcesRequest"),
+ DAP_FIELD(supportsLogPoints, "supportsLogPoints"),
+ DAP_FIELD(supportsModulesRequest, "supportsModulesRequest"),
+ DAP_FIELD(supportsReadMemoryRequest, "supportsReadMemoryRequest"),
+ DAP_FIELD(supportsRestartFrame, "supportsRestartFrame"),
+ DAP_FIELD(supportsRestartRequest, "supportsRestartRequest"),
+ DAP_FIELD(supportsSetExpression, "supportsSetExpression"),
+ DAP_FIELD(supportsSetVariable, "supportsSetVariable"),
+ DAP_FIELD(supportsSingleThreadExecutionRequests,
+ "supportsSingleThreadExecutionRequests"),
+ DAP_FIELD(supportsStepBack, "supportsStepBack"),
+ DAP_FIELD(supportsStepInTargetsRequest, "supportsStepInTargetsRequest"),
+ DAP_FIELD(supportsSteppingGranularity, "supportsSteppingGranularity"),
+ DAP_FIELD(supportsTerminateRequest, "supportsTerminateRequest"),
+ DAP_FIELD(supportsTerminateThreadsRequest,
+ "supportsTerminateThreadsRequest"),
+ DAP_FIELD(supportsValueFormattingOptions, "supportsValueFormattingOptions"),
+ DAP_FIELD(supportsWriteMemoryRequest, "supportsWriteMemoryRequest"));
+
+DAP_IMPLEMENT_STRUCT_TYPEINFO(LaunchResponse, "");
+
+DAP_IMPLEMENT_STRUCT_TYPEINFO(LoadedSourcesResponse,
+ "",
+ DAP_FIELD(sources, "sources"));
+
+DAP_IMPLEMENT_STRUCT_TYPEINFO(ModulesResponse,
+ "",
+ DAP_FIELD(modules, "modules"),
+ DAP_FIELD(totalModules, "totalModules"));
+
+DAP_IMPLEMENT_STRUCT_TYPEINFO(NextResponse, "");
+
+DAP_IMPLEMENT_STRUCT_TYPEINFO(PauseResponse, "");
+
+DAP_IMPLEMENT_STRUCT_TYPEINFO(ReadMemoryResponse,
+ "",
+ DAP_FIELD(address, "address"),
+ DAP_FIELD(data, "data"),
+ DAP_FIELD(unreadableBytes, "unreadableBytes"));
+
+DAP_IMPLEMENT_STRUCT_TYPEINFO(RestartFrameResponse, "");
+
+DAP_IMPLEMENT_STRUCT_TYPEINFO(RestartResponse, "");
+
+DAP_IMPLEMENT_STRUCT_TYPEINFO(ReverseContinueResponse, "");
+
+DAP_IMPLEMENT_STRUCT_TYPEINFO(RunInTerminalResponse,
+ "",
+ DAP_FIELD(processId, "processId"),
+ DAP_FIELD(shellProcessId, "shellProcessId"));
+
+DAP_IMPLEMENT_STRUCT_TYPEINFO(ScopesResponse, "", DAP_FIELD(scopes, "scopes"));
+
+DAP_IMPLEMENT_STRUCT_TYPEINFO(SetBreakpointsResponse,
+ "",
+ DAP_FIELD(breakpoints, "breakpoints"));
+
+DAP_IMPLEMENT_STRUCT_TYPEINFO(SetDataBreakpointsResponse,
+ "",
+ DAP_FIELD(breakpoints, "breakpoints"));
+
+DAP_IMPLEMENT_STRUCT_TYPEINFO(SetExceptionBreakpointsResponse,
+ "",
+ DAP_FIELD(breakpoints, "breakpoints"));
+
+DAP_IMPLEMENT_STRUCT_TYPEINFO(SetExpressionResponse,
+ "",
+ DAP_FIELD(indexedVariables, "indexedVariables"),
+ DAP_FIELD(namedVariables, "namedVariables"),
+ DAP_FIELD(presentationHint, "presentationHint"),
+ DAP_FIELD(type, "type"),
+ DAP_FIELD(value, "value"),
+ DAP_FIELD(variablesReference,
+ "variablesReference"));
+
+DAP_IMPLEMENT_STRUCT_TYPEINFO(SetFunctionBreakpointsResponse,
+ "",
+ DAP_FIELD(breakpoints, "breakpoints"));
+
+DAP_IMPLEMENT_STRUCT_TYPEINFO(SetInstructionBreakpointsResponse,
+ "",
+ DAP_FIELD(breakpoints, "breakpoints"));
+
+DAP_IMPLEMENT_STRUCT_TYPEINFO(SetVariableResponse,
+ "",
+ DAP_FIELD(indexedVariables, "indexedVariables"),
+ DAP_FIELD(namedVariables, "namedVariables"),
+ DAP_FIELD(type, "type"),
+ DAP_FIELD(value, "value"),
+ DAP_FIELD(variablesReference,
+ "variablesReference"));
+
+DAP_IMPLEMENT_STRUCT_TYPEINFO(SourceResponse,
+ "",
+ DAP_FIELD(content, "content"),
+ DAP_FIELD(mimeType, "mimeType"));
+
+DAP_IMPLEMENT_STRUCT_TYPEINFO(StackTraceResponse,
+ "",
+ DAP_FIELD(stackFrames, "stackFrames"),
+ DAP_FIELD(totalFrames, "totalFrames"));
+
+DAP_IMPLEMENT_STRUCT_TYPEINFO(StartDebuggingResponse, "");
+
+DAP_IMPLEMENT_STRUCT_TYPEINFO(StepBackResponse, "");
+
+DAP_IMPLEMENT_STRUCT_TYPEINFO(StepInResponse, "");
+
+DAP_IMPLEMENT_STRUCT_TYPEINFO(StepInTargetsResponse,
+ "",
+ DAP_FIELD(targets, "targets"));
+
+DAP_IMPLEMENT_STRUCT_TYPEINFO(StepOutResponse, "");
+
+DAP_IMPLEMENT_STRUCT_TYPEINFO(TerminateResponse, "");
+
+DAP_IMPLEMENT_STRUCT_TYPEINFO(TerminateThreadsResponse, "");
+
+DAP_IMPLEMENT_STRUCT_TYPEINFO(ThreadsResponse,
+ "",
+ DAP_FIELD(threads, "threads"));
+
+DAP_IMPLEMENT_STRUCT_TYPEINFO(VariablesResponse,
+ "",
+ DAP_FIELD(variables, "variables"));
+
+DAP_IMPLEMENT_STRUCT_TYPEINFO(WriteMemoryResponse,
+ "",
+ DAP_FIELD(bytesWritten, "bytesWritten"),
+ DAP_FIELD(offset, "offset"));
+
+} // namespace dap
diff --git a/Utilities/cmcppdap/src/protocol_types.cpp b/Utilities/cmcppdap/src/protocol_types.cpp
new file mode 100644
index 0000000..d9a9e36
--- /dev/null
+++ b/Utilities/cmcppdap/src/protocol_types.cpp
@@ -0,0 +1,316 @@
+// Copyright 2019 Google LLC
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// https://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+// Generated with protocol_gen.go -- do not edit this file.
+// go run scripts/protocol_gen/protocol_gen.go
+//
+// DAP version 1.59.0
+
+#include "dap/protocol.h"
+
+namespace dap {
+
+DAP_IMPLEMENT_STRUCT_TYPEINFO(Checksum,
+ "",
+ DAP_FIELD(algorithm, "algorithm"),
+ DAP_FIELD(checksum, "checksum"));
+
+DAP_IMPLEMENT_STRUCT_TYPEINFO(Source,
+ "",
+ DAP_FIELD(adapterData, "adapterData"),
+ DAP_FIELD(checksums, "checksums"),
+ DAP_FIELD(name, "name"),
+ DAP_FIELD(origin, "origin"),
+ DAP_FIELD(path, "path"),
+ DAP_FIELD(presentationHint, "presentationHint"),
+ DAP_FIELD(sourceReference, "sourceReference"),
+ DAP_FIELD(sources, "sources"));
+
+DAP_IMPLEMENT_STRUCT_TYPEINFO(Breakpoint,
+ "",
+ DAP_FIELD(column, "column"),
+ DAP_FIELD(endColumn, "endColumn"),
+ DAP_FIELD(endLine, "endLine"),
+ DAP_FIELD(id, "id"),
+ DAP_FIELD(instructionReference,
+ "instructionReference"),
+ DAP_FIELD(line, "line"),
+ DAP_FIELD(message, "message"),
+ DAP_FIELD(offset, "offset"),
+ DAP_FIELD(source, "source"),
+ DAP_FIELD(verified, "verified"));
+
+DAP_IMPLEMENT_STRUCT_TYPEINFO(BreakpointLocation,
+ "",
+ DAP_FIELD(column, "column"),
+ DAP_FIELD(endColumn, "endColumn"),
+ DAP_FIELD(endLine, "endLine"),
+ DAP_FIELD(line, "line"));
+
+DAP_IMPLEMENT_STRUCT_TYPEINFO(ColumnDescriptor,
+ "",
+ DAP_FIELD(attributeName, "attributeName"),
+ DAP_FIELD(format, "format"),
+ DAP_FIELD(label, "label"),
+ DAP_FIELD(type, "type"),
+ DAP_FIELD(width, "width"));
+
+DAP_IMPLEMENT_STRUCT_TYPEINFO(ExceptionBreakpointsFilter,
+ "",
+ DAP_FIELD(conditionDescription,
+ "conditionDescription"),
+ DAP_FIELD(def, "default"),
+ DAP_FIELD(description, "description"),
+ DAP_FIELD(filter, "filter"),
+ DAP_FIELD(label, "label"),
+ DAP_FIELD(supportsCondition,
+ "supportsCondition"));
+
+DAP_IMPLEMENT_STRUCT_TYPEINFO(
+ Capabilities,
+ "",
+ DAP_FIELD(additionalModuleColumns, "additionalModuleColumns"),
+ DAP_FIELD(completionTriggerCharacters, "completionTriggerCharacters"),
+ DAP_FIELD(exceptionBreakpointFilters, "exceptionBreakpointFilters"),
+ DAP_FIELD(supportSuspendDebuggee, "supportSuspendDebuggee"),
+ DAP_FIELD(supportTerminateDebuggee, "supportTerminateDebuggee"),
+ DAP_FIELD(supportedChecksumAlgorithms, "supportedChecksumAlgorithms"),
+ DAP_FIELD(supportsBreakpointLocationsRequest,
+ "supportsBreakpointLocationsRequest"),
+ DAP_FIELD(supportsCancelRequest, "supportsCancelRequest"),
+ DAP_FIELD(supportsClipboardContext, "supportsClipboardContext"),
+ DAP_FIELD(supportsCompletionsRequest, "supportsCompletionsRequest"),
+ DAP_FIELD(supportsConditionalBreakpoints, "supportsConditionalBreakpoints"),
+ DAP_FIELD(supportsConfigurationDoneRequest,
+ "supportsConfigurationDoneRequest"),
+ DAP_FIELD(supportsDataBreakpoints, "supportsDataBreakpoints"),
+ DAP_FIELD(supportsDelayedStackTraceLoading,
+ "supportsDelayedStackTraceLoading"),
+ DAP_FIELD(supportsDisassembleRequest, "supportsDisassembleRequest"),
+ DAP_FIELD(supportsEvaluateForHovers, "supportsEvaluateForHovers"),
+ DAP_FIELD(supportsExceptionFilterOptions, "supportsExceptionFilterOptions"),
+ DAP_FIELD(supportsExceptionInfoRequest, "supportsExceptionInfoRequest"),
+ DAP_FIELD(supportsExceptionOptions, "supportsExceptionOptions"),
+ DAP_FIELD(supportsFunctionBreakpoints, "supportsFunctionBreakpoints"),
+ DAP_FIELD(supportsGotoTargetsRequest, "supportsGotoTargetsRequest"),
+ DAP_FIELD(supportsHitConditionalBreakpoints,
+ "supportsHitConditionalBreakpoints"),
+ DAP_FIELD(supportsInstructionBreakpoints, "supportsInstructionBreakpoints"),
+ DAP_FIELD(supportsLoadedSourcesRequest, "supportsLoadedSourcesRequest"),
+ DAP_FIELD(supportsLogPoints, "supportsLogPoints"),
+ DAP_FIELD(supportsModulesRequest, "supportsModulesRequest"),
+ DAP_FIELD(supportsReadMemoryRequest, "supportsReadMemoryRequest"),
+ DAP_FIELD(supportsRestartFrame, "supportsRestartFrame"),
+ DAP_FIELD(supportsRestartRequest, "supportsRestartRequest"),
+ DAP_FIELD(supportsSetExpression, "supportsSetExpression"),
+ DAP_FIELD(supportsSetVariable, "supportsSetVariable"),
+ DAP_FIELD(supportsSingleThreadExecutionRequests,
+ "supportsSingleThreadExecutionRequests"),
+ DAP_FIELD(supportsStepBack, "supportsStepBack"),
+ DAP_FIELD(supportsStepInTargetsRequest, "supportsStepInTargetsRequest"),
+ DAP_FIELD(supportsSteppingGranularity, "supportsSteppingGranularity"),
+ DAP_FIELD(supportsTerminateRequest, "supportsTerminateRequest"),
+ DAP_FIELD(supportsTerminateThreadsRequest,
+ "supportsTerminateThreadsRequest"),
+ DAP_FIELD(supportsValueFormattingOptions, "supportsValueFormattingOptions"),
+ DAP_FIELD(supportsWriteMemoryRequest, "supportsWriteMemoryRequest"));
+
+DAP_IMPLEMENT_STRUCT_TYPEINFO(CompletionItem,
+ "",
+ DAP_FIELD(detail, "detail"),
+ DAP_FIELD(label, "label"),
+ DAP_FIELD(length, "length"),
+ DAP_FIELD(selectionLength, "selectionLength"),
+ DAP_FIELD(selectionStart, "selectionStart"),
+ DAP_FIELD(sortText, "sortText"),
+ DAP_FIELD(start, "start"),
+ DAP_FIELD(text, "text"),
+ DAP_FIELD(type, "type"));
+
+DAP_IMPLEMENT_STRUCT_TYPEINFO(DisassembledInstruction,
+ "",
+ DAP_FIELD(address, "address"),
+ DAP_FIELD(column, "column"),
+ DAP_FIELD(endColumn, "endColumn"),
+ DAP_FIELD(endLine, "endLine"),
+ DAP_FIELD(instruction, "instruction"),
+ DAP_FIELD(instructionBytes, "instructionBytes"),
+ DAP_FIELD(line, "line"),
+ DAP_FIELD(location, "location"),
+ DAP_FIELD(symbol, "symbol"));
+
+DAP_IMPLEMENT_STRUCT_TYPEINFO(Message,
+ "",
+ DAP_FIELD(format, "format"),
+ DAP_FIELD(id, "id"),
+ DAP_FIELD(sendTelemetry, "sendTelemetry"),
+ DAP_FIELD(showUser, "showUser"),
+ DAP_FIELD(url, "url"),
+ DAP_FIELD(urlLabel, "urlLabel"),
+ DAP_FIELD(variables, "variables"));
+
+DAP_IMPLEMENT_STRUCT_TYPEINFO(VariablePresentationHint,
+ "",
+ DAP_FIELD(attributes, "attributes"),
+ DAP_FIELD(kind, "kind"),
+ DAP_FIELD(lazy, "lazy"),
+ DAP_FIELD(visibility, "visibility"));
+
+DAP_IMPLEMENT_STRUCT_TYPEINFO(ValueFormat, "", DAP_FIELD(hex, "hex"));
+
+DAP_IMPLEMENT_STRUCT_TYPEINFO(ExceptionDetails,
+ "",
+ DAP_FIELD(evaluateName, "evaluateName"),
+ DAP_FIELD(fullTypeName, "fullTypeName"),
+ DAP_FIELD(innerException, "innerException"),
+ DAP_FIELD(message, "message"),
+ DAP_FIELD(stackTrace, "stackTrace"),
+ DAP_FIELD(typeName, "typeName"));
+
+DAP_IMPLEMENT_STRUCT_TYPEINFO(GotoTarget,
+ "",
+ DAP_FIELD(column, "column"),
+ DAP_FIELD(endColumn, "endColumn"),
+ DAP_FIELD(endLine, "endLine"),
+ DAP_FIELD(id, "id"),
+ DAP_FIELD(instructionPointerReference,
+ "instructionPointerReference"),
+ DAP_FIELD(label, "label"),
+ DAP_FIELD(line, "line"));
+
+DAP_IMPLEMENT_STRUCT_TYPEINFO(Module,
+ "",
+ DAP_FIELD(addressRange, "addressRange"),
+ DAP_FIELD(dateTimeStamp, "dateTimeStamp"),
+ DAP_FIELD(id, "id"),
+ DAP_FIELD(isOptimized, "isOptimized"),
+ DAP_FIELD(isUserCode, "isUserCode"),
+ DAP_FIELD(name, "name"),
+ DAP_FIELD(path, "path"),
+ DAP_FIELD(symbolFilePath, "symbolFilePath"),
+ DAP_FIELD(symbolStatus, "symbolStatus"),
+ DAP_FIELD(version, "version"));
+
+DAP_IMPLEMENT_STRUCT_TYPEINFO(Scope,
+ "",
+ DAP_FIELD(column, "column"),
+ DAP_FIELD(endColumn, "endColumn"),
+ DAP_FIELD(endLine, "endLine"),
+ DAP_FIELD(expensive, "expensive"),
+ DAP_FIELD(indexedVariables, "indexedVariables"),
+ DAP_FIELD(line, "line"),
+ DAP_FIELD(name, "name"),
+ DAP_FIELD(namedVariables, "namedVariables"),
+ DAP_FIELD(presentationHint, "presentationHint"),
+ DAP_FIELD(source, "source"),
+ DAP_FIELD(variablesReference,
+ "variablesReference"));
+
+DAP_IMPLEMENT_STRUCT_TYPEINFO(SourceBreakpoint,
+ "",
+ DAP_FIELD(column, "column"),
+ DAP_FIELD(condition, "condition"),
+ DAP_FIELD(hitCondition, "hitCondition"),
+ DAP_FIELD(line, "line"),
+ DAP_FIELD(logMessage, "logMessage"));
+
+DAP_IMPLEMENT_STRUCT_TYPEINFO(DataBreakpoint,
+ "",
+ DAP_FIELD(accessType, "accessType"),
+ DAP_FIELD(condition, "condition"),
+ DAP_FIELD(dataId, "dataId"),
+ DAP_FIELD(hitCondition, "hitCondition"));
+
+DAP_IMPLEMENT_STRUCT_TYPEINFO(ExceptionPathSegment,
+ "",
+ DAP_FIELD(names, "names"),
+ DAP_FIELD(negate, "negate"));
+
+DAP_IMPLEMENT_STRUCT_TYPEINFO(ExceptionOptions,
+ "",
+ DAP_FIELD(breakMode, "breakMode"),
+ DAP_FIELD(path, "path"));
+
+DAP_IMPLEMENT_STRUCT_TYPEINFO(ExceptionFilterOptions,
+ "",
+ DAP_FIELD(condition, "condition"),
+ DAP_FIELD(filterId, "filterId"));
+
+DAP_IMPLEMENT_STRUCT_TYPEINFO(FunctionBreakpoint,
+ "",
+ DAP_FIELD(condition, "condition"),
+ DAP_FIELD(hitCondition, "hitCondition"),
+ DAP_FIELD(name, "name"));
+
+DAP_IMPLEMENT_STRUCT_TYPEINFO(InstructionBreakpoint,
+ "",
+ DAP_FIELD(condition, "condition"),
+ DAP_FIELD(hitCondition, "hitCondition"),
+ DAP_FIELD(instructionReference,
+ "instructionReference"),
+ DAP_FIELD(offset, "offset"));
+
+DAP_IMPLEMENT_STRUCT_TYPEINFO(StackFrame,
+ "",
+ DAP_FIELD(canRestart, "canRestart"),
+ DAP_FIELD(column, "column"),
+ DAP_FIELD(endColumn, "endColumn"),
+ DAP_FIELD(endLine, "endLine"),
+ DAP_FIELD(id, "id"),
+ DAP_FIELD(instructionPointerReference,
+ "instructionPointerReference"),
+ DAP_FIELD(line, "line"),
+ DAP_FIELD(moduleId, "moduleId"),
+ DAP_FIELD(name, "name"),
+ DAP_FIELD(presentationHint, "presentationHint"),
+ DAP_FIELD(source, "source"));
+
+DAP_IMPLEMENT_STRUCT_TYPEINFO(StackFrameFormat,
+ "",
+ DAP_FIELD(includeAll, "includeAll"),
+ DAP_FIELD(line, "line"),
+ DAP_FIELD(module, "module"),
+ DAP_FIELD(parameterNames, "parameterNames"),
+ DAP_FIELD(parameterTypes, "parameterTypes"),
+ DAP_FIELD(parameterValues, "parameterValues"),
+ DAP_FIELD(parameters, "parameters"));
+
+DAP_IMPLEMENT_STRUCT_TYPEINFO(StepInTarget,
+ "",
+ DAP_FIELD(column, "column"),
+ DAP_FIELD(endColumn, "endColumn"),
+ DAP_FIELD(endLine, "endLine"),
+ DAP_FIELD(id, "id"),
+ DAP_FIELD(label, "label"),
+ DAP_FIELD(line, "line"));
+
+DAP_IMPLEMENT_STRUCT_TYPEINFO(Thread,
+ "",
+ DAP_FIELD(id, "id"),
+ DAP_FIELD(name, "name"));
+
+DAP_IMPLEMENT_STRUCT_TYPEINFO(Variable,
+ "",
+ DAP_FIELD(evaluateName, "evaluateName"),
+ DAP_FIELD(indexedVariables, "indexedVariables"),
+ DAP_FIELD(memoryReference, "memoryReference"),
+ DAP_FIELD(name, "name"),
+ DAP_FIELD(namedVariables, "namedVariables"),
+ DAP_FIELD(presentationHint, "presentationHint"),
+ DAP_FIELD(type, "type"),
+ DAP_FIELD(value, "value"),
+ DAP_FIELD(variablesReference,
+ "variablesReference"));
+
+} // namespace dap
diff --git a/Utilities/cmcppdap/src/rapid_json_serializer.cpp b/Utilities/cmcppdap/src/rapid_json_serializer.cpp
new file mode 100644
index 0000000..178db99
--- /dev/null
+++ b/Utilities/cmcppdap/src/rapid_json_serializer.cpp
@@ -0,0 +1,289 @@
+// Copyright 2019 Google LLC
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// https://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#include "rapid_json_serializer.h"
+
+#include "null_json_serializer.h"
+
+#include <rapidjson/document.h>
+#include <rapidjson/prettywriter.h>
+
+namespace dap {
+namespace json {
+
+RapidDeserializer::RapidDeserializer(const std::string& str)
+ : doc(new rapidjson::Document()) {
+ doc->Parse(str.c_str());
+}
+
+RapidDeserializer::RapidDeserializer(rapidjson::Value* json) : val(json) {}
+
+RapidDeserializer::~RapidDeserializer() {
+ delete doc;
+}
+
+bool RapidDeserializer::deserialize(dap::boolean* v) const {
+ if (!json()->IsBool()) {
+ return false;
+ }
+ *v = json()->GetBool();
+ return true;
+}
+
+bool RapidDeserializer::deserialize(dap::integer* v) const {
+ if (json()->IsInt()) {
+ *v = json()->GetInt();
+ return true;
+ } else if (json()->IsUint()) {
+ *v = static_cast<int64_t>(json()->GetUint());
+ return true;
+ } else if (json()->IsInt64()) {
+ *v = json()->GetInt64();
+ return true;
+ } else if (json()->IsUint64()) {
+ *v = static_cast<int64_t>(json()->GetUint64());
+ return true;
+ }
+ return false;
+}
+
+bool RapidDeserializer::deserialize(dap::number* v) const {
+ if (!json()->IsNumber()) {
+ return false;
+ }
+ *v = json()->GetDouble();
+ return true;
+}
+
+bool RapidDeserializer::deserialize(dap::string* v) const {
+ if (!json()->IsString()) {
+ return false;
+ }
+ *v = json()->GetString();
+ return true;
+}
+
+bool RapidDeserializer::deserialize(dap::object* v) const {
+ v->reserve(json()->MemberCount());
+ for (auto el = json()->MemberBegin(); el != json()->MemberEnd(); el++) {
+ dap::any el_val;
+ RapidDeserializer d(&(el->value));
+ if (!d.deserialize(&el_val)) {
+ return false;
+ }
+ (*v)[el->name.GetString()] = el_val;
+ }
+ return true;
+}
+
+bool RapidDeserializer::deserialize(dap::any* v) const {
+ if (json()->IsBool()) {
+ *v = dap::boolean(json()->GetBool());
+ } else if (json()->IsDouble()) {
+ *v = dap::number(json()->GetDouble());
+ } else if (json()->IsInt()) {
+ *v = dap::integer(json()->GetInt());
+ } else if (json()->IsString()) {
+ *v = dap::string(json()->GetString());
+ } else if (json()->IsNull()) {
+ *v = null();
+ } else if (json()->IsObject()) {
+ dap::object obj;
+ if (!deserialize(&obj)) {
+ return false;
+ }
+ *v = obj;
+ } else if (json()->IsArray()){
+ dap::array<any> arr;
+ if (!deserialize(&arr)){
+ return false;
+ }
+ *v = arr;
+ } else {
+ return false;
+ }
+ return true;
+}
+
+size_t RapidDeserializer::count() const {
+ return json()->Size();
+}
+
+bool RapidDeserializer::array(
+ const std::function<bool(dap::Deserializer*)>& cb) const {
+ if (!json()->IsArray()) {
+ return false;
+ }
+ for (uint32_t i = 0; i < json()->Size(); i++) {
+ RapidDeserializer d(&(*json())[i]);
+ if (!cb(&d)) {
+ return false;
+ }
+ }
+ return true;
+}
+
+bool RapidDeserializer::field(
+ const std::string& name,
+ const std::function<bool(dap::Deserializer*)>& cb) const {
+ if (!json()->IsObject()) {
+ return false;
+ }
+ auto it = json()->FindMember(name.c_str());
+ if (it == json()->MemberEnd()) {
+ return cb(&NullDeserializer::instance);
+ }
+ RapidDeserializer d(&(it->value));
+ return cb(&d);
+}
+
+RapidSerializer::RapidSerializer()
+ : doc(new rapidjson::Document(rapidjson::kObjectType)),
+ allocator(doc->GetAllocator()) {}
+
+RapidSerializer::RapidSerializer(rapidjson::Value* json,
+ rapidjson::Document::AllocatorType& allocator)
+ : val(json), allocator(allocator) {}
+
+RapidSerializer::~RapidSerializer() {
+ delete doc;
+}
+
+std::string RapidSerializer::dump() const {
+ rapidjson::StringBuffer sb;
+ rapidjson::PrettyWriter<rapidjson::StringBuffer> writer(sb);
+ json()->Accept(writer);
+ return sb.GetString();
+}
+
+bool RapidSerializer::serialize(dap::boolean v) {
+ json()->SetBool(v);
+ return true;
+}
+
+bool RapidSerializer::serialize(dap::integer v) {
+ json()->SetInt64(v);
+ return true;
+}
+
+bool RapidSerializer::serialize(dap::number v) {
+ json()->SetDouble(v);
+ return true;
+}
+
+bool RapidSerializer::serialize(const dap::string& v) {
+ json()->SetString(v.data(), static_cast<uint32_t>(v.length()), allocator);
+ return true;
+}
+
+bool RapidSerializer::serialize(const dap::object& v) {
+ if (!json()->IsObject()) {
+ json()->SetObject();
+ }
+ for (auto& it : v) {
+ if (!json()->HasMember(it.first.c_str())) {
+ rapidjson::Value name_value{it.first.c_str(), allocator};
+ json()->AddMember(name_value, rapidjson::Value(), allocator);
+ }
+ rapidjson::Value& member = (*json())[it.first.c_str()];
+ RapidSerializer s(&member, allocator);
+ if (!s.serialize(it.second)) {
+ return false;
+ }
+ }
+ return true;
+}
+
+bool RapidSerializer::serialize(const dap::any& v) {
+ if (v.is<dap::boolean>()) {
+ json()->SetBool((bool)v.get<dap::boolean>());
+ } else if (v.is<dap::integer>()) {
+ json()->SetInt64(v.get<dap::integer>());
+ } else if (v.is<dap::number>()) {
+ json()->SetDouble((double)v.get<dap::number>());
+ } else if (v.is<dap::string>()) {
+ auto s = v.get<dap::string>();
+ json()->SetString(s.data(), static_cast<uint32_t>(s.length()), allocator);
+ } else if (v.is<dap::object>()) {
+ // reachable if dap::object nested is inside other dap::object
+ return serialize(v.get<dap::object>());
+ } else if (v.is<dap::null>()) {
+ } else {
+ // reachable if array or custom serialized type is nested inside other dap::object
+ auto type = get_any_type(v);
+ auto value = get_any_val(v);
+ if (type && value) {
+ return type->serialize(this, value);
+ }
+ return false;
+ }
+
+ return true;
+}
+
+bool RapidSerializer::array(size_t count,
+ const std::function<bool(dap::Serializer*)>& cb) {
+ if (!json()->IsArray()) {
+ json()->SetArray();
+ }
+
+ while (count > json()->Size()) {
+ json()->PushBack(rapidjson::Value(), allocator);
+ }
+
+ for (uint32_t i = 0; i < count; i++) {
+ RapidSerializer s(&(*json())[i], allocator);
+ if (!cb(&s)) {
+ return false;
+ }
+ }
+ return true;
+}
+
+bool RapidSerializer::object(
+ const std::function<bool(dap::FieldSerializer*)>& cb) {
+ struct FS : public FieldSerializer {
+ rapidjson::Value* const json;
+ rapidjson::Document::AllocatorType& allocator;
+
+ FS(rapidjson::Value* json, rapidjson::Document::AllocatorType& allocator)
+ : json(json), allocator(allocator) {}
+ bool field(const std::string& name, const SerializeFunc& cb) override {
+ if (!json->HasMember(name.c_str())) {
+ rapidjson::Value name_value{name.c_str(), allocator};
+ json->AddMember(name_value, rapidjson::Value(), allocator);
+ }
+ rapidjson::Value& member = (*json)[name.c_str()];
+ RapidSerializer s(&member, allocator);
+ auto res = cb(&s);
+ if (s.removed) {
+ json->RemoveMember(name.c_str());
+ }
+ return res;
+ }
+ };
+
+ if (!json()->IsObject()) {
+ json()->SetObject();
+ }
+ FS fs{json(), allocator};
+ return cb(&fs);
+}
+
+void RapidSerializer::remove() {
+ removed = true;
+}
+
+} // namespace json
+} // namespace dap
diff --git a/Utilities/cmcppdap/src/rapid_json_serializer.h b/Utilities/cmcppdap/src/rapid_json_serializer.h
new file mode 100644
index 0000000..6e83384
--- /dev/null
+++ b/Utilities/cmcppdap/src/rapid_json_serializer.h
@@ -0,0 +1,138 @@
+// Copyright 2019 Google LLC
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// https://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#ifndef dap_rapid_json_serializer_h
+#define dap_rapid_json_serializer_h
+
+#include "dap/protocol.h"
+#include "dap/serialization.h"
+#include "dap/types.h"
+
+#include <rapidjson/document.h>
+
+namespace dap {
+namespace json {
+
+struct RapidDeserializer : public dap::Deserializer {
+ explicit RapidDeserializer(const std::string&);
+ ~RapidDeserializer();
+
+ // dap::Deserializer compliance
+ bool deserialize(boolean* v) const override;
+ bool deserialize(integer* v) const override;
+ bool deserialize(number* v) const override;
+ bool deserialize(string* v) const override;
+ bool deserialize(object* v) const override;
+ bool deserialize(any* v) const override;
+ size_t count() const override;
+ bool array(const std::function<bool(dap::Deserializer*)>&) const override;
+ bool field(const std::string& name,
+ const std::function<bool(dap::Deserializer*)>&) const override;
+
+ // Unhide base overloads
+ template <typename T>
+ inline bool field(const std::string& name, T* v) {
+ return dap::Deserializer::field(name, v);
+ }
+
+ template <typename T,
+ typename = std::enable_if<TypeOf<T>::has_custom_serialization>>
+ inline bool deserialize(T* v) const {
+ return dap::Deserializer::deserialize(v);
+ }
+
+ template <typename T>
+ inline bool deserialize(dap::array<T>* v) const {
+ return dap::Deserializer::deserialize(v);
+ }
+
+ template <typename T>
+ inline bool deserialize(dap::optional<T>* v) const {
+ return dap::Deserializer::deserialize(v);
+ }
+
+ template <typename T0, typename... Types>
+ inline bool deserialize(dap::variant<T0, Types...>* v) const {
+ return dap::Deserializer::deserialize(v);
+ }
+
+ template <typename T>
+ inline bool field(const std::string& name, T* v) const {
+ return dap::Deserializer::deserialize(name, v);
+ }
+
+ inline rapidjson::Value* json() const { return (val == nullptr) ? doc : val; }
+
+ private:
+ RapidDeserializer(rapidjson::Value*);
+ rapidjson::Document* const doc = nullptr;
+ rapidjson::Value* const val = nullptr;
+};
+
+struct RapidSerializer : public dap::Serializer {
+ RapidSerializer();
+ ~RapidSerializer();
+
+ std::string dump() const;
+
+ // dap::Serializer compliance
+ bool serialize(boolean v) override;
+ bool serialize(integer v) override;
+ bool serialize(number v) override;
+ bool serialize(const string& v) override;
+ bool serialize(const dap::object& v) override;
+ bool serialize(const any& v) override;
+ bool array(size_t count,
+ const std::function<bool(dap::Serializer*)>&) override;
+ bool object(const std::function<bool(dap::FieldSerializer*)>&) override;
+ void remove() override;
+
+ // Unhide base overloads
+ template <typename T,
+ typename = std::enable_if<TypeOf<T>::has_custom_serialization>>
+ inline bool serialize(const T& v) {
+ return dap::Serializer::serialize(v);
+ }
+
+ template <typename T>
+ inline bool serialize(const dap::array<T>& v) {
+ return dap::Serializer::serialize(v);
+ }
+
+ template <typename T>
+ inline bool serialize(const dap::optional<T>& v) {
+ return dap::Serializer::serialize(v);
+ }
+
+ template <typename T0, typename... Types>
+ inline bool serialize(const dap::variant<T0, Types...>& v) {
+ return dap::Serializer::serialize(v);
+ }
+
+ inline bool serialize(const char* v) { return dap::Serializer::serialize(v); }
+
+ inline rapidjson::Value* json() const { return (val == nullptr) ? doc : val; }
+
+ private:
+ RapidSerializer(rapidjson::Value*, rapidjson::Document::AllocatorType&);
+ rapidjson::Document* const doc = nullptr;
+ rapidjson::Value* const val = nullptr;
+ rapidjson::Document::AllocatorType& allocator;
+ bool removed = false;
+};
+
+} // namespace json
+} // namespace dap
+
+#endif // dap_rapid_json_serializer_h
diff --git a/Utilities/cmcppdap/src/rwmutex.h b/Utilities/cmcppdap/src/rwmutex.h
new file mode 100644
index 0000000..9e85891
--- /dev/null
+++ b/Utilities/cmcppdap/src/rwmutex.h
@@ -0,0 +1,172 @@
+// Copyright 2020 Google LLC
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// https://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#ifndef dap_rwmutex_h
+#define dap_rwmutex_h
+
+#include <condition_variable>
+#include <mutex>
+
+namespace dap {
+
+////////////////////////////////////////////////////////////////////////////////
+// RWMutex
+////////////////////////////////////////////////////////////////////////////////
+
+// A RWMutex is a reader/writer mutual exclusion lock.
+// The lock can be held by an arbitrary number of readers or a single writer.
+// Also known as a shared mutex.
+class RWMutex {
+ public:
+ inline RWMutex() = default;
+
+ // lockReader() locks the mutex for reading.
+ // Multiple read locks can be held while there are no writer locks.
+ inline void lockReader();
+
+ // unlockReader() unlocks the mutex for reading.
+ inline void unlockReader();
+
+ // lockWriter() locks the mutex for writing.
+ // If the lock is already locked for reading or writing, lockWriter blocks
+ // until the lock is available.
+ inline void lockWriter();
+
+ // unlockWriter() unlocks the mutex for writing.
+ inline void unlockWriter();
+
+ private:
+ RWMutex(const RWMutex&) = delete;
+ RWMutex& operator=(const RWMutex&) = delete;
+
+ int readLocks = 0;
+ int pendingWriteLocks = 0;
+ std::mutex mutex;
+ std::condition_variable cv;
+};
+
+void RWMutex::lockReader() {
+ std::unique_lock<std::mutex> lock(mutex);
+ readLocks++;
+}
+
+void RWMutex::unlockReader() {
+ std::unique_lock<std::mutex> lock(mutex);
+ readLocks--;
+ if (readLocks == 0 && pendingWriteLocks > 0) {
+ cv.notify_one();
+ }
+}
+
+void RWMutex::lockWriter() {
+ std::unique_lock<std::mutex> lock(mutex);
+ if (readLocks > 0) {
+ pendingWriteLocks++;
+ cv.wait(lock, [&] { return readLocks == 0; });
+ pendingWriteLocks--;
+ }
+ lock.release(); // Keep lock held
+}
+
+void RWMutex::unlockWriter() {
+ if (pendingWriteLocks > 0) {
+ cv.notify_one();
+ }
+ mutex.unlock();
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// RLock
+////////////////////////////////////////////////////////////////////////////////
+
+// RLock is a RAII read lock helper for a RWMutex.
+class RLock {
+ public:
+ inline RLock(RWMutex& mutex);
+ inline ~RLock();
+
+ inline RLock(RLock&&);
+ inline RLock& operator=(RLock&&);
+
+ private:
+ RLock(const RLock&) = delete;
+ RLock& operator=(const RLock&) = delete;
+
+ RWMutex* m;
+};
+
+RLock::RLock(RWMutex& mutex) : m(&mutex) {
+ m->lockReader();
+}
+
+RLock::~RLock() {
+ if (m != nullptr) {
+ m->unlockReader();
+ }
+}
+
+RLock::RLock(RLock&& other) {
+ m = other.m;
+ other.m = nullptr;
+}
+
+RLock& RLock::operator=(RLock&& other) {
+ m = other.m;
+ other.m = nullptr;
+ return *this;
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// WLock
+////////////////////////////////////////////////////////////////////////////////
+
+// WLock is a RAII write lock helper for a RWMutex.
+class WLock {
+ public:
+ inline WLock(RWMutex& mutex);
+ inline ~WLock();
+
+ inline WLock(WLock&&);
+ inline WLock& operator=(WLock&&);
+
+ private:
+ WLock(const WLock&) = delete;
+ WLock& operator=(const WLock&) = delete;
+
+ RWMutex* m;
+};
+
+WLock::WLock(RWMutex& mutex) : m(&mutex) {
+ m->lockWriter();
+}
+
+WLock::~WLock() {
+ if (m != nullptr) {
+ m->unlockWriter();
+ }
+}
+
+WLock::WLock(WLock&& other) {
+ m = other.m;
+ other.m = nullptr;
+}
+
+WLock& WLock::operator=(WLock&& other) {
+ m = other.m;
+ other.m = nullptr;
+ return *this;
+}
+} // namespace dap
+
+#endif
diff --git a/Utilities/cmcppdap/src/rwmutex_test.cpp b/Utilities/cmcppdap/src/rwmutex_test.cpp
new file mode 100644
index 0000000..944ed77
--- /dev/null
+++ b/Utilities/cmcppdap/src/rwmutex_test.cpp
@@ -0,0 +1,113 @@
+// Copyright 2020 Google LLC
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// https://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#include "rwmutex.h"
+
+#include "gmock/gmock.h"
+#include "gtest/gtest.h"
+
+#include <array>
+#include <thread>
+#include <vector>
+
+namespace {
+constexpr const size_t NumThreads = 8;
+}
+
+// Check that WLock behaves like regular mutex.
+TEST(RWMutex, WLock) {
+ dap::RWMutex rwmutex;
+ int counter = 0;
+
+ std::vector<std::thread> threads;
+ for (size_t i = 0; i < NumThreads; i++) {
+ threads.emplace_back([&] {
+ for (int j = 0; j < 1000; j++) {
+ dap::WLock lock(rwmutex);
+ counter++;
+ EXPECT_EQ(counter, 1);
+ counter--;
+ }
+ });
+ }
+
+ for (auto& thread : threads) {
+ thread.join();
+ }
+
+ EXPECT_EQ(counter, 0);
+}
+
+TEST(RWMutex, NoRLockWithWLock) {
+ dap::RWMutex rwmutex;
+
+ std::vector<std::thread> threads;
+ std::array<int, NumThreads> counters = {};
+
+ { // With WLock held...
+ dap::WLock wlock(rwmutex);
+
+ for (size_t i = 0; i < counters.size(); i++) {
+ int* counter = &counters[i];
+ threads.emplace_back([&rwmutex, counter] {
+ dap::RLock lock(rwmutex);
+ for (int j = 0; j < 1000; j++) {
+ (*counter)++;
+ }
+ });
+ }
+
+ // RLocks should block
+ for (int counter : counters) {
+ EXPECT_EQ(counter, 0);
+ }
+ }
+
+ for (auto& thread : threads) {
+ thread.join();
+ }
+
+ for (int counter : counters) {
+ EXPECT_EQ(counter, 1000);
+ }
+}
+
+TEST(RWMutex, NoWLockWithRLock) {
+ dap::RWMutex rwmutex;
+
+ std::vector<std::thread> threads;
+ size_t counter = 0;
+
+ { // With RLocks held...
+ dap::RLock rlockA(rwmutex);
+ dap::RLock rlockB(rwmutex);
+ dap::RLock rlockC(rwmutex);
+
+ for (size_t i = 0; i < NumThreads; i++) {
+ threads.emplace_back(std::thread([&] {
+ dap::WLock lock(rwmutex);
+ counter++;
+ }));
+ }
+
+ // ... WLocks should block
+ EXPECT_EQ(counter, 0U);
+ }
+
+ for (auto& thread : threads) {
+ thread.join();
+ }
+
+ EXPECT_EQ(counter, NumThreads);
+}
diff --git a/Utilities/cmcppdap/src/session.cpp b/Utilities/cmcppdap/src/session.cpp
new file mode 100644
index 0000000..d88a697
--- /dev/null
+++ b/Utilities/cmcppdap/src/session.cpp
@@ -0,0 +1,516 @@
+// Copyright 2019 Google LLC
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// https://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#include "content_stream.h"
+
+#include "dap/any.h"
+#include "dap/session.h"
+
+#include "chan.h"
+#include "json_serializer.h"
+#include "socket.h"
+
+#include <stdarg.h>
+#include <stdio.h>
+#include <atomic>
+#include <deque>
+#include <memory>
+#include <mutex>
+#include <thread>
+#include <unordered_map>
+#include <vector>
+
+namespace {
+
+class Impl : public dap::Session {
+ public:
+ void onError(const ErrorHandler& handler) override { handlers.put(handler); }
+
+ void registerHandler(const dap::TypeInfo* typeinfo,
+ const GenericRequestHandler& handler) override {
+ handlers.put(typeinfo, handler);
+ }
+
+ void registerHandler(const dap::TypeInfo* typeinfo,
+ const GenericEventHandler& handler) override {
+ handlers.put(typeinfo, handler);
+ }
+
+ void registerHandler(const dap::TypeInfo* typeinfo,
+ const GenericResponseSentHandler& handler) override {
+ handlers.put(typeinfo, handler);
+ }
+
+ std::function<void()> getPayload() override {
+ auto request = reader.read();
+ if (request.size() > 0) {
+ if (auto payload = processMessage(request)) {
+ return payload;
+ }
+ }
+ return {};
+ }
+
+ void connect(const std::shared_ptr<dap::Reader>& r,
+ const std::shared_ptr<dap::Writer>& w) override {
+ if (isBound.exchange(true)) {
+ handlers.error("Session::connect called twice");
+ return;
+ }
+
+ reader = dap::ContentReader(r);
+ writer = dap::ContentWriter(w);
+ }
+
+ void startProcessingMessages(
+ const ClosedHandler& onClose /* = {} */) override {
+ if (isProcessingMessages.exchange(true)) {
+ handlers.error("Session::startProcessingMessages() called twice");
+ return;
+ }
+ recvThread = std::thread([this, onClose] {
+ while (reader.isOpen()) {
+ if (auto payload = getPayload()) {
+ inbox.put(std::move(payload));
+ }
+ }
+ if (onClose) {
+ onClose();
+ }
+ });
+
+ dispatchThread = std::thread([this] {
+ while (auto payload = inbox.take()) {
+ payload.value()();
+ }
+ });
+ }
+
+ bool send(const dap::TypeInfo* requestTypeInfo,
+ const dap::TypeInfo* responseTypeInfo,
+ const void* request,
+ const GenericResponseHandler& responseHandler) override {
+ int seq = nextSeq++;
+
+ handlers.put(seq, responseTypeInfo, responseHandler);
+
+ dap::json::Serializer s;
+ if (!s.object([&](dap::FieldSerializer* fs) {
+ return fs->field("seq", dap::integer(seq)) &&
+ fs->field("type", "request") &&
+ fs->field("command", requestTypeInfo->name()) &&
+ fs->field("arguments", [&](dap::Serializer* s) {
+ return requestTypeInfo->serialize(s, request);
+ });
+ })) {
+ return false;
+ }
+ return send(s.dump());
+ }
+
+ bool send(const dap::TypeInfo* typeinfo, const void* event) override {
+ dap::json::Serializer s;
+ if (!s.object([&](dap::FieldSerializer* fs) {
+ return fs->field("seq", dap::integer(nextSeq++)) &&
+ fs->field("type", "event") &&
+ fs->field("event", typeinfo->name()) &&
+ fs->field("body", [&](dap::Serializer* s) {
+ return typeinfo->serialize(s, event);
+ });
+ })) {
+ return false;
+ }
+ return send(s.dump());
+ }
+
+ ~Impl() {
+ inbox.close();
+ reader.close();
+ writer.close();
+ if (recvThread.joinable()) {
+ recvThread.join();
+ }
+ if (dispatchThread.joinable()) {
+ dispatchThread.join();
+ }
+ }
+
+ private:
+ using Payload = std::function<void()>;
+
+ class EventHandlers {
+ public:
+ void put(const ErrorHandler& handler) {
+ std::unique_lock<std::mutex> lock(errorMutex);
+ errorHandler = handler;
+ }
+
+ void error(const char* format, ...) {
+ va_list vararg;
+ va_start(vararg, format);
+ std::unique_lock<std::mutex> lock(errorMutex);
+ errorLocked(format, vararg);
+ va_end(vararg);
+ }
+
+ std::pair<const dap::TypeInfo*, GenericRequestHandler> request(
+ const std::string& name) {
+ std::unique_lock<std::mutex> lock(requestMutex);
+ auto it = requestMap.find(name);
+ return (it != requestMap.end()) ? it->second : decltype(it->second){};
+ }
+
+ void put(const dap::TypeInfo* typeinfo,
+ const GenericRequestHandler& handler) {
+ std::unique_lock<std::mutex> lock(requestMutex);
+ auto added =
+ requestMap
+ .emplace(typeinfo->name(), std::make_pair(typeinfo, handler))
+ .second;
+ if (!added) {
+ errorfLocked("Request handler for '%s' already registered",
+ typeinfo->name().c_str());
+ }
+ }
+
+ std::pair<const dap::TypeInfo*, GenericResponseHandler> response(
+ int64_t seq) {
+ std::unique_lock<std::mutex> lock(responseMutex);
+ auto responseIt = responseMap.find(seq);
+ if (responseIt == responseMap.end()) {
+ errorfLocked("Unknown response with sequence %d", seq);
+ return {};
+ }
+ auto out = std::move(responseIt->second);
+ responseMap.erase(seq);
+ return out;
+ }
+
+ void put(int seq,
+ const dap::TypeInfo* typeinfo,
+ const GenericResponseHandler& handler) {
+ std::unique_lock<std::mutex> lock(responseMutex);
+ auto added =
+ responseMap.emplace(seq, std::make_pair(typeinfo, handler)).second;
+ if (!added) {
+ errorfLocked("Response handler for sequence %d already registered",
+ seq);
+ }
+ }
+
+ std::pair<const dap::TypeInfo*, GenericEventHandler> event(
+ const std::string& name) {
+ std::unique_lock<std::mutex> lock(eventMutex);
+ auto it = eventMap.find(name);
+ return (it != eventMap.end()) ? it->second : decltype(it->second){};
+ }
+
+ void put(const dap::TypeInfo* typeinfo,
+ const GenericEventHandler& handler) {
+ std::unique_lock<std::mutex> lock(eventMutex);
+ auto added =
+ eventMap.emplace(typeinfo->name(), std::make_pair(typeinfo, handler))
+ .second;
+ if (!added) {
+ errorfLocked("Event handler for '%s' already registered",
+ typeinfo->name().c_str());
+ }
+ }
+
+ GenericResponseSentHandler responseSent(const dap::TypeInfo* typeinfo) {
+ std::unique_lock<std::mutex> lock(responseSentMutex);
+ auto it = responseSentMap.find(typeinfo);
+ return (it != responseSentMap.end()) ? it->second
+ : decltype(it->second){};
+ }
+
+ void put(const dap::TypeInfo* typeinfo,
+ const GenericResponseSentHandler& handler) {
+ std::unique_lock<std::mutex> lock(responseSentMutex);
+ auto added = responseSentMap.emplace(typeinfo, handler).second;
+ if (!added) {
+ errorfLocked("Response sent handler for '%s' already registered",
+ typeinfo->name().c_str());
+ }
+ }
+
+ private:
+ void errorfLocked(const char* format, ...) {
+ va_list vararg;
+ va_start(vararg, format);
+ errorLocked(format, vararg);
+ va_end(vararg);
+ }
+
+ void errorLocked(const char* format, va_list args) {
+ char buf[2048];
+ vsnprintf(buf, sizeof(buf), format, args);
+ if (errorHandler) {
+ errorHandler(buf);
+ }
+ }
+
+ std::mutex errorMutex;
+ ErrorHandler errorHandler;
+
+ std::mutex requestMutex;
+ std::unordered_map<std::string,
+ std::pair<const dap::TypeInfo*, GenericRequestHandler>>
+ requestMap;
+
+ std::mutex responseMutex;
+ std::unordered_map<int64_t,
+ std::pair<const dap::TypeInfo*, GenericResponseHandler>>
+ responseMap;
+
+ std::mutex eventMutex;
+ std::unordered_map<std::string,
+ std::pair<const dap::TypeInfo*, GenericEventHandler>>
+ eventMap;
+
+ std::mutex responseSentMutex;
+ std::unordered_map<const dap::TypeInfo*, GenericResponseSentHandler>
+ responseSentMap;
+ }; // EventHandlers
+
+ Payload processMessage(const std::string& str) {
+ auto d = dap::json::Deserializer(str);
+ dap::string type;
+ if (!d.field("type", &type)) {
+ handlers.error("Message missing string 'type' field");
+ return {};
+ }
+
+ dap::integer sequence = 0;
+ if (!d.field("seq", &sequence)) {
+ handlers.error("Message missing number 'seq' field");
+ return {};
+ }
+
+ if (type == "request") {
+ return processRequest(&d, sequence);
+ } else if (type == "event") {
+ return processEvent(&d);
+ } else if (type == "response") {
+ processResponse(&d);
+ return {};
+ } else {
+ handlers.error("Unknown message type '%s'", type.c_str());
+ }
+
+ return {};
+ }
+
+ Payload processRequest(dap::json::Deserializer* d, dap::integer sequence) {
+ dap::string command;
+ if (!d->field("command", &command)) {
+ handlers.error("Request missing string 'command' field");
+ return {};
+ }
+
+ const dap::TypeInfo* typeinfo;
+ GenericRequestHandler handler;
+ std::tie(typeinfo, handler) = handlers.request(command);
+ if (!typeinfo) {
+ handlers.error("No request handler registered for command '%s'",
+ command.c_str());
+ return {};
+ }
+
+ auto data = new uint8_t[typeinfo->size()];
+ typeinfo->construct(data);
+
+ if (!d->field("arguments", [&](dap::Deserializer* d) {
+ return typeinfo->deserialize(d, data);
+ })) {
+ handlers.error("Failed to deserialize request");
+ typeinfo->destruct(data);
+ delete[] data;
+ return {};
+ }
+
+ return [=] {
+ handler(
+ data,
+ [=](const dap::TypeInfo* typeinfo, const void* data) {
+ // onSuccess
+ dap::json::Serializer s;
+ s.object([&](dap::FieldSerializer* fs) {
+ return fs->field("seq", dap::integer(nextSeq++)) &&
+ fs->field("type", "response") &&
+ fs->field("request_seq", sequence) &&
+ fs->field("success", dap::boolean(true)) &&
+ fs->field("command", command) &&
+ fs->field("body", [&](dap::Serializer* s) {
+ return typeinfo->serialize(s, data);
+ });
+ });
+ send(s.dump());
+
+ if (auto handler = handlers.responseSent(typeinfo)) {
+ handler(data, nullptr);
+ }
+ },
+ [=](const dap::TypeInfo* typeinfo, const dap::Error& error) {
+ // onError
+ dap::json::Serializer s;
+ s.object([&](dap::FieldSerializer* fs) {
+ return fs->field("seq", dap::integer(nextSeq++)) &&
+ fs->field("type", "response") &&
+ fs->field("request_seq", sequence) &&
+ fs->field("success", dap::boolean(false)) &&
+ fs->field("command", command) &&
+ fs->field("message", error.message);
+ });
+ send(s.dump());
+
+ if (auto handler = handlers.responseSent(typeinfo)) {
+ handler(nullptr, &error);
+ }
+ });
+ typeinfo->destruct(data);
+ delete[] data;
+ };
+ }
+
+ Payload processEvent(dap::json::Deserializer* d) {
+ dap::string event;
+ if (!d->field("event", &event)) {
+ handlers.error("Event missing string 'event' field");
+ return {};
+ }
+
+ const dap::TypeInfo* typeinfo;
+ GenericEventHandler handler;
+ std::tie(typeinfo, handler) = handlers.event(event);
+ if (!typeinfo) {
+ handlers.error("No event handler registered for event '%s'",
+ event.c_str());
+ return {};
+ }
+
+ auto data = new uint8_t[typeinfo->size()];
+ typeinfo->construct(data);
+
+ // "body" is an optional field for some events, such as "Terminated Event".
+ bool body_ok = true;
+ d->field("body", [&](dap::Deserializer* d) {
+ if (!typeinfo->deserialize(d, data)) {
+ body_ok = false;
+ }
+ return true;
+ });
+
+ if (!body_ok) {
+ handlers.error("Failed to deserialize event '%s' body", event.c_str());
+ typeinfo->destruct(data);
+ delete[] data;
+ return {};
+ }
+
+ return [=] {
+ handler(data);
+ typeinfo->destruct(data);
+ delete[] data;
+ };
+ }
+
+ void processResponse(const dap::Deserializer* d) {
+ dap::integer requestSeq = 0;
+ if (!d->field("request_seq", &requestSeq)) {
+ handlers.error("Response missing int 'request_seq' field");
+ return;
+ }
+
+ const dap::TypeInfo* typeinfo;
+ GenericResponseHandler handler;
+ std::tie(typeinfo, handler) = handlers.response(requestSeq);
+ if (!typeinfo) {
+ handlers.error("Unknown response with sequence %d", requestSeq);
+ return;
+ }
+
+ dap::boolean success = false;
+ if (!d->field("success", &success)) {
+ handlers.error("Response missing int 'success' field");
+ return;
+ }
+
+ if (success) {
+ auto data = std::unique_ptr<uint8_t[]>(new uint8_t[typeinfo->size()]);
+ typeinfo->construct(data.get());
+
+ // "body" field in Response is an optional field.
+ d->field("body", [&](const dap::Deserializer* d) {
+ return typeinfo->deserialize(d, data.get());
+ });
+
+ handler(data.get(), nullptr);
+ typeinfo->destruct(data.get());
+ } else {
+ std::string message;
+ if (!d->field("message", &message)) {
+ handlers.error("Failed to deserialize message");
+ return;
+ }
+ auto error = dap::Error("%s", message.c_str());
+ handler(nullptr, &error);
+ }
+ }
+
+ bool send(const std::string& s) {
+ std::unique_lock<std::mutex> lock(sendMutex);
+ if (!writer.isOpen()) {
+ handlers.error("Send failed as the writer is closed");
+ return false;
+ }
+ return writer.write(s);
+ }
+
+ std::atomic<bool> isBound = {false};
+ std::atomic<bool> isProcessingMessages = {false};
+ dap::ContentReader reader;
+ dap::ContentWriter writer;
+
+ std::atomic<bool> shutdown = {false};
+ EventHandlers handlers;
+ std::thread recvThread;
+ std::thread dispatchThread;
+ dap::Chan<Payload> inbox;
+ std::atomic<uint32_t> nextSeq = {1};
+ std::mutex sendMutex;
+};
+
+} // anonymous namespace
+
+namespace dap {
+
+Error::Error(const std::string& message) : message(message) {}
+
+Error::Error(const char* msg, ...) {
+ char buf[2048];
+ va_list vararg;
+ va_start(vararg, msg);
+ vsnprintf(buf, sizeof(buf), msg, vararg);
+ va_end(vararg);
+ message = buf;
+}
+
+Session::~Session() = default;
+
+std::unique_ptr<Session> Session::create() {
+ return std::unique_ptr<Session>(new Impl());
+}
+
+} // namespace dap
diff --git a/Utilities/cmcppdap/src/session_test.cpp b/Utilities/cmcppdap/src/session_test.cpp
new file mode 100644
index 0000000..361152e
--- /dev/null
+++ b/Utilities/cmcppdap/src/session_test.cpp
@@ -0,0 +1,625 @@
+// Copyright 2019 Google LLC
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// https://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#include "dap/session.h"
+#include "dap/io.h"
+#include "dap/protocol.h"
+
+#include "chan.h"
+
+#include "gmock/gmock.h"
+#include "gtest/gtest.h"
+
+#include <array>
+#include <atomic>
+#include <condition_variable>
+#include <mutex>
+#include <thread>
+
+namespace dap {
+
+struct TestResponse : public Response {
+ boolean b;
+ integer i;
+ number n;
+ array<integer> a;
+ object o;
+ string s;
+ optional<integer> o1;
+ optional<integer> o2;
+};
+
+DAP_STRUCT_TYPEINFO(TestResponse,
+ "test-response",
+ DAP_FIELD(b, "res_b"),
+ DAP_FIELD(i, "res_i"),
+ DAP_FIELD(n, "res_n"),
+ DAP_FIELD(a, "res_a"),
+ DAP_FIELD(o, "res_o"),
+ DAP_FIELD(s, "res_s"),
+ DAP_FIELD(o1, "res_o1"),
+ DAP_FIELD(o2, "res_o2"));
+
+struct TestRequest : public Request {
+ using Response = TestResponse;
+
+ boolean b;
+ integer i;
+ number n;
+ array<integer> a;
+ object o;
+ string s;
+ optional<integer> o1;
+ optional<integer> o2;
+};
+
+DAP_STRUCT_TYPEINFO(TestRequest,
+ "test-request",
+ DAP_FIELD(b, "req_b"),
+ DAP_FIELD(i, "req_i"),
+ DAP_FIELD(n, "req_n"),
+ DAP_FIELD(a, "req_a"),
+ DAP_FIELD(o, "req_o"),
+ DAP_FIELD(s, "req_s"),
+ DAP_FIELD(o1, "req_o1"),
+ DAP_FIELD(o2, "req_o2"));
+
+struct TestEvent : public Event {
+ boolean b;
+ integer i;
+ number n;
+ array<integer> a;
+ object o;
+ string s;
+ optional<integer> o1;
+ optional<integer> o2;
+};
+
+DAP_STRUCT_TYPEINFO(TestEvent,
+ "test-event",
+ DAP_FIELD(b, "evt_b"),
+ DAP_FIELD(i, "evt_i"),
+ DAP_FIELD(n, "evt_n"),
+ DAP_FIELD(a, "evt_a"),
+ DAP_FIELD(o, "evt_o"),
+ DAP_FIELD(s, "evt_s"),
+ DAP_FIELD(o1, "evt_o1"),
+ DAP_FIELD(o2, "evt_o2"));
+
+}; // namespace dap
+
+namespace {
+
+dap::TestRequest createRequest() {
+ dap::TestRequest request;
+ request.b = false;
+ request.i = 72;
+ request.n = 9.87;
+ request.a = {2, 5, 7, 8};
+ request.o = {
+ std::make_pair("a", dap::integer(1)),
+ std::make_pair("b", dap::number(2)),
+ std::make_pair("c", dap::string("3")),
+ };
+ request.s = "request";
+ request.o2 = 42;
+ return request;
+}
+
+dap::TestResponse createResponse() {
+ dap::TestResponse response;
+ response.b = true;
+ response.i = 99;
+ response.n = 123.456;
+ response.a = {5, 4, 3, 2, 1};
+ response.o = {
+ std::make_pair("one", dap::integer(1)),
+ std::make_pair("two", dap::number(2)),
+ std::make_pair("three", dap::string("3")),
+ };
+ response.s = "ROGER";
+ response.o1 = 50;
+ return response;
+}
+
+dap::TestEvent createEvent() {
+ dap::TestEvent event;
+ event.b = false;
+ event.i = 72;
+ event.n = 9.87;
+ event.a = {2, 5, 7, 8};
+ event.o = {
+ std::make_pair("a", dap::integer(1)),
+ std::make_pair("b", dap::number(2)),
+ std::make_pair("c", dap::string("3")),
+ };
+ event.s = "event";
+ event.o2 = 42;
+ return event;
+}
+
+} // anonymous namespace
+
+class SessionTest : public testing::Test {
+ public:
+ void bind() {
+ auto client2server = dap::pipe();
+ auto server2client = dap::pipe();
+ client->bind(server2client, client2server);
+ server->bind(client2server, server2client);
+ }
+
+ std::unique_ptr<dap::Session> client = dap::Session::create();
+ std::unique_ptr<dap::Session> server = dap::Session::create();
+};
+
+TEST_F(SessionTest, Request) {
+ dap::TestRequest received;
+ server->registerHandler([&](const dap::TestRequest& req) {
+ received = req;
+ return createResponse();
+ });
+
+ bind();
+
+ auto request = createRequest();
+ client->send(request).get();
+
+ // Check request was received correctly.
+ ASSERT_EQ(received.b, request.b);
+ ASSERT_EQ(received.i, request.i);
+ ASSERT_EQ(received.n, request.n);
+ ASSERT_EQ(received.a, request.a);
+ ASSERT_EQ(received.o.size(), 3U);
+ ASSERT_EQ(received.o["a"].get<dap::integer>(),
+ request.o["a"].get<dap::integer>());
+ ASSERT_EQ(received.o["b"].get<dap::number>(),
+ request.o["b"].get<dap::number>());
+ ASSERT_EQ(received.o["c"].get<dap::string>(),
+ request.o["c"].get<dap::string>());
+ ASSERT_EQ(received.s, request.s);
+ ASSERT_EQ(received.o1, request.o1);
+ ASSERT_EQ(received.o2, request.o2);
+}
+
+TEST_F(SessionTest, RequestResponseSuccess) {
+ server->registerHandler(
+ [&](const dap::TestRequest&) { return createResponse(); });
+
+ bind();
+
+ auto request = createRequest();
+ auto response = client->send(request);
+
+ auto got = response.get();
+
+ // Check response was received correctly.
+ ASSERT_EQ(got.error, false);
+ ASSERT_EQ(got.response.b, dap::boolean(true));
+ ASSERT_EQ(got.response.i, dap::integer(99));
+ ASSERT_EQ(got.response.n, dap::number(123.456));
+ ASSERT_EQ(got.response.a, dap::array<dap::integer>({5, 4, 3, 2, 1}));
+ ASSERT_EQ(got.response.o.size(), 3U);
+ ASSERT_EQ(got.response.o["one"].get<dap::integer>(), dap::integer(1));
+ ASSERT_EQ(got.response.o["two"].get<dap::number>(), dap::number(2));
+ ASSERT_EQ(got.response.o["three"].get<dap::string>(), dap::string("3"));
+ ASSERT_EQ(got.response.s, "ROGER");
+ ASSERT_EQ(got.response.o1, dap::optional<dap::integer>(50));
+ ASSERT_FALSE(got.response.o2.has_value());
+}
+
+TEST_F(SessionTest, BreakPointRequestResponseSuccess) {
+ server->registerHandler([&](const dap::SetBreakpointsRequest&) {
+ dap::SetBreakpointsResponse response;
+ dap::Breakpoint bp;
+ bp.line = 2;
+ response.breakpoints.emplace_back(std::move(bp));
+ return response;
+ });
+
+ bind();
+
+ auto got = client->send(dap::SetBreakpointsRequest{}).get();
+
+ // Check response was received correctly.
+ ASSERT_EQ(got.error, false);
+ ASSERT_EQ(got.response.breakpoints.size(), 1U);
+}
+
+TEST_F(SessionTest, RequestResponseOrError) {
+ server->registerHandler(
+ [&](const dap::TestRequest&) -> dap::ResponseOrError<dap::TestResponse> {
+ return dap::Error("Oh noes!");
+ });
+
+ bind();
+
+ auto response = client->send(createRequest());
+
+ auto got = response.get();
+
+ // Check response was received correctly.
+ ASSERT_EQ(got.error, true);
+ ASSERT_EQ(got.error.message, "Oh noes!");
+}
+
+TEST_F(SessionTest, RequestResponseError) {
+ server->registerHandler(
+ [&](const dap::TestRequest&) { return dap::Error("Oh noes!"); });
+
+ bind();
+
+ auto response = client->send(createRequest());
+
+ auto got = response.get();
+
+ // Check response was received correctly.
+ ASSERT_EQ(got.error, true);
+ ASSERT_EQ(got.error.message, "Oh noes!");
+}
+
+TEST_F(SessionTest, RequestCallbackResponse) {
+ using ResponseCallback = std::function<void(dap::SetBreakpointsResponse)>;
+
+ server->registerHandler(
+ [&](const dap::SetBreakpointsRequest&, const ResponseCallback& callback) {
+ dap::SetBreakpointsResponse response;
+ dap::Breakpoint bp;
+ bp.line = 2;
+ response.breakpoints.emplace_back(std::move(bp));
+ callback(response);
+ });
+
+ bind();
+
+ auto got = client->send(dap::SetBreakpointsRequest{}).get();
+
+ // Check response was received correctly.
+ ASSERT_EQ(got.error, false);
+ ASSERT_EQ(got.response.breakpoints.size(), 1U);
+}
+
+TEST_F(SessionTest, RequestCallbackResponseOrError) {
+ using ResponseCallback =
+ std::function<void(dap::ResponseOrError<dap::SetBreakpointsResponse>)>;
+
+ server->registerHandler(
+ [&](const dap::SetBreakpointsRequest&, const ResponseCallback& callback) {
+ dap::SetBreakpointsResponse response;
+ dap::Breakpoint bp;
+ bp.line = 2;
+ response.breakpoints.emplace_back(std::move(bp));
+ callback(response);
+ });
+
+ bind();
+
+ auto got = client->send(dap::SetBreakpointsRequest{}).get();
+
+ // Check response was received correctly.
+ ASSERT_EQ(got.error, false);
+ ASSERT_EQ(got.response.breakpoints.size(), 1U);
+}
+
+TEST_F(SessionTest, RequestCallbackError) {
+ using ResponseCallback =
+ std::function<void(dap::ResponseOrError<dap::SetBreakpointsResponse>)>;
+
+ server->registerHandler(
+ [&](const dap::SetBreakpointsRequest&, const ResponseCallback& callback) {
+ callback(dap::Error("Oh noes!"));
+ });
+
+ bind();
+
+ auto got = client->send(dap::SetBreakpointsRequest{}).get();
+
+ // Check response was received correctly.
+ ASSERT_EQ(got.error, true);
+ ASSERT_EQ(got.error.message, "Oh noes!");
+}
+
+TEST_F(SessionTest, RequestCallbackSuccessAfterReturn) {
+ using ResponseCallback =
+ std::function<void(dap::ResponseOrError<dap::SetBreakpointsResponse>)>;
+
+ ResponseCallback callback;
+ std::mutex mutex;
+ std::condition_variable cv;
+
+ server->registerHandler(
+ [&](const dap::SetBreakpointsRequest&, const ResponseCallback& cb) {
+ std::unique_lock<std::mutex> lock(mutex);
+ callback = cb;
+ cv.notify_all();
+ });
+
+ bind();
+
+ auto future = client->send(dap::SetBreakpointsRequest{});
+
+ {
+ dap::SetBreakpointsResponse response;
+ dap::Breakpoint bp;
+ bp.line = 2;
+ response.breakpoints.emplace_back(std::move(bp));
+
+ // Wait for the handler to be called.
+ std::unique_lock<std::mutex> lock(mutex);
+ cv.wait(lock, [&] { return static_cast<bool>(callback); });
+
+ // Issue the callback
+ callback(response);
+ }
+
+ auto got = future.get();
+
+ // Check response was received correctly.
+ ASSERT_EQ(got.error, false);
+ ASSERT_EQ(got.response.breakpoints.size(), 1U);
+}
+
+TEST_F(SessionTest, RequestCallbackErrorAfterReturn) {
+ using ResponseCallback =
+ std::function<void(dap::ResponseOrError<dap::SetBreakpointsResponse>)>;
+
+ ResponseCallback callback;
+ std::mutex mutex;
+ std::condition_variable cv;
+
+ server->registerHandler(
+ [&](const dap::SetBreakpointsRequest&, const ResponseCallback& cb) {
+ std::unique_lock<std::mutex> lock(mutex);
+ callback = cb;
+ cv.notify_all();
+ });
+
+ bind();
+
+ auto future = client->send(dap::SetBreakpointsRequest{});
+
+ {
+ // Wait for the handler to be called.
+ std::unique_lock<std::mutex> lock(mutex);
+ cv.wait(lock, [&] { return static_cast<bool>(callback); });
+
+ // Issue the callback
+ callback(dap::Error("Oh noes!"));
+ }
+
+ auto got = future.get();
+
+ // Check response was received correctly.
+ ASSERT_EQ(got.error, true);
+ ASSERT_EQ(got.error.message, "Oh noes!");
+}
+
+TEST_F(SessionTest, ResponseSentHandlerSuccess) {
+ const auto response = createResponse();
+
+ dap::Chan<dap::ResponseOrError<dap::TestResponse>> chan;
+ server->registerHandler([&](const dap::TestRequest&) { return response; });
+ server->registerSentHandler(
+ [&](const dap::ResponseOrError<dap::TestResponse> r) { chan.put(r); });
+
+ bind();
+
+ client->send(createRequest());
+
+ auto got = chan.take().value();
+ ASSERT_EQ(got.error, false);
+ ASSERT_EQ(got.response.b, dap::boolean(true));
+ ASSERT_EQ(got.response.i, dap::integer(99));
+ ASSERT_EQ(got.response.n, dap::number(123.456));
+ ASSERT_EQ(got.response.a, dap::array<dap::integer>({5, 4, 3, 2, 1}));
+ ASSERT_EQ(got.response.o.size(), 3U);
+ ASSERT_EQ(got.response.o["one"].get<dap::integer>(), dap::integer(1));
+ ASSERT_EQ(got.response.o["two"].get<dap::number>(), dap::number(2));
+ ASSERT_EQ(got.response.o["three"].get<dap::string>(), dap::string("3"));
+ ASSERT_EQ(got.response.s, "ROGER");
+ ASSERT_EQ(got.response.o1, dap::optional<dap::integer>(50));
+ ASSERT_FALSE(got.response.o2.has_value());
+}
+
+TEST_F(SessionTest, ResponseSentHandlerError) {
+ dap::Chan<dap::ResponseOrError<dap::TestResponse>> chan;
+ server->registerHandler(
+ [&](const dap::TestRequest&) { return dap::Error("Oh noes!"); });
+ server->registerSentHandler(
+ [&](const dap::ResponseOrError<dap::TestResponse> r) { chan.put(r); });
+
+ bind();
+
+ client->send(createRequest());
+
+ auto got = chan.take().value();
+ ASSERT_EQ(got.error, true);
+ ASSERT_EQ(got.error.message, "Oh noes!");
+}
+
+TEST_F(SessionTest, Event) {
+ dap::Chan<dap::TestEvent> received;
+ server->registerHandler([&](const dap::TestEvent& e) { received.put(e); });
+
+ bind();
+
+ auto event = createEvent();
+ client->send(event);
+
+ // Check event was received correctly.
+ auto got = received.take().value();
+
+ ASSERT_EQ(got.b, event.b);
+ ASSERT_EQ(got.i, event.i);
+ ASSERT_EQ(got.n, event.n);
+ ASSERT_EQ(got.a, event.a);
+ ASSERT_EQ(got.o.size(), 3U);
+ ASSERT_EQ(got.o["a"].get<dap::integer>(), event.o["a"].get<dap::integer>());
+ ASSERT_EQ(got.o["b"].get<dap::number>(), event.o["b"].get<dap::number>());
+ ASSERT_EQ(got.o["c"].get<dap::string>(), event.o["c"].get<dap::string>());
+ ASSERT_EQ(got.s, event.s);
+ ASSERT_EQ(got.o1, event.o1);
+ ASSERT_EQ(got.o2, event.o2);
+}
+
+TEST_F(SessionTest, RegisterHandlerFunction) {
+ struct S {
+ static dap::TestResponse requestA(const dap::TestRequest&) { return {}; }
+ static dap::Error requestB(const dap::TestRequest&) { return {}; }
+ static dap::ResponseOrError<dap::TestResponse> requestC(
+ const dap::TestRequest&) {
+ return dap::Error();
+ }
+ static void event(const dap::TestEvent&) {}
+ static void sent(const dap::ResponseOrError<dap::TestResponse>&) {}
+ };
+ client->registerHandler(&S::requestA);
+ client->registerHandler(&S::requestB);
+ client->registerHandler(&S::requestC);
+ client->registerHandler(&S::event);
+ client->registerSentHandler(&S::sent);
+}
+
+TEST_F(SessionTest, SendRequestNoBind) {
+ bool errored = false;
+ client->onError([&](const std::string&) { errored = true; });
+ auto res = client->send(createRequest()).get();
+ ASSERT_TRUE(errored);
+ ASSERT_TRUE(res.error);
+}
+
+TEST_F(SessionTest, SendEventNoBind) {
+ bool errored = false;
+ client->onError([&](const std::string&) { errored = true; });
+ client->send(createEvent());
+ ASSERT_TRUE(errored);
+}
+
+TEST_F(SessionTest, SingleThread) {
+ server->registerHandler(
+ [&](const dap::TestRequest&) { return createResponse(); });
+
+ // Explicitly connect and process request on this test thread instead of
+ // calling bind() which inturn starts processing messages immediately on a new
+ // thread.
+ auto client2server = dap::pipe();
+ auto server2client = dap::pipe();
+ client->connect(server2client, client2server);
+ server->connect(client2server, server2client);
+
+ auto request = createRequest();
+ auto response = client->send(request);
+
+ // Process request and response on this thread
+ if (auto payload = server->getPayload()) {
+ payload();
+ }
+ if (auto payload = client->getPayload()) {
+ payload();
+ }
+
+ auto got = response.get();
+ // Check response was received correctly.
+ ASSERT_EQ(got.error, false);
+ ASSERT_EQ(got.response.b, dap::boolean(true));
+ ASSERT_EQ(got.response.i, dap::integer(99));
+ ASSERT_EQ(got.response.n, dap::number(123.456));
+ ASSERT_EQ(got.response.a, dap::array<dap::integer>({5, 4, 3, 2, 1}));
+ ASSERT_EQ(got.response.o.size(), 3U);
+ ASSERT_EQ(got.response.o["one"].get<dap::integer>(), dap::integer(1));
+ ASSERT_EQ(got.response.o["two"].get<dap::number>(), dap::number(2));
+ ASSERT_EQ(got.response.o["three"].get<dap::string>(), dap::string("3"));
+ ASSERT_EQ(got.response.s, "ROGER");
+ ASSERT_EQ(got.response.o1, dap::optional<dap::integer>(50));
+ ASSERT_FALSE(got.response.o2.has_value());
+}
+
+TEST_F(SessionTest, Concurrency) {
+ std::atomic<int> numEventsHandled = {0};
+ std::atomic<bool> done = {false};
+
+ server->registerHandler(
+ [](const dap::TestRequest&) { return dap::TestResponse(); });
+
+ server->registerHandler([&](const dap::TestEvent&) {
+ if (numEventsHandled++ > 10000) {
+ done = true;
+ }
+ });
+
+ bind();
+
+ constexpr int numThreads = 32;
+ std::array<std::thread, numThreads> threads;
+
+ for (int i = 0; i < numThreads; i++) {
+ threads[i] = std::thread([&] {
+ while (!done) {
+ client->send(createEvent());
+ client->send(createRequest());
+ }
+ });
+ }
+
+ for (int i = 0; i < numThreads; i++) {
+ threads[i].join();
+ }
+
+ client.reset();
+ server.reset();
+}
+
+TEST_F(SessionTest, OnClientClosed) {
+ std::mutex mutex;
+ std::condition_variable cv;
+ bool clientClosed = false;
+
+ auto client2server = dap::pipe();
+ auto server2client = dap::pipe();
+
+ client->bind(server2client, client2server);
+ server->bind(client2server, server2client, [&] {
+ std::unique_lock<std::mutex> lock(mutex);
+ clientClosed = true;
+ cv.notify_all();
+ });
+
+ client.reset();
+
+ // Wait for the client closed handler to be called.
+ std::unique_lock<std::mutex> lock(mutex);
+ cv.wait(lock, [&] { return static_cast<bool>(clientClosed); });
+}
+
+TEST_F(SessionTest, OnServerClosed) {
+ std::mutex mutex;
+ std::condition_variable cv;
+ bool serverClosed = false;
+
+ auto client2server = dap::pipe();
+ auto server2client = dap::pipe();
+
+ client->bind(server2client, client2server, [&] {
+ std::unique_lock<std::mutex> lock(mutex);
+ serverClosed = true;
+ cv.notify_all();
+ });
+ server->bind(client2server, server2client);
+
+ server.reset();
+
+ // Wait for the client closed handler to be called.
+ std::unique_lock<std::mutex> lock(mutex);
+ cv.wait(lock, [&] { return static_cast<bool>(serverClosed); });
+}
diff --git a/Utilities/cmcppdap/src/socket.cpp b/Utilities/cmcppdap/src/socket.cpp
new file mode 100644
index 0000000..1211310
--- /dev/null
+++ b/Utilities/cmcppdap/src/socket.cpp
@@ -0,0 +1,333 @@
+// Copyright 2019 Google LLC
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// https://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#include "socket.h"
+
+#include "rwmutex.h"
+
+#if defined(_WIN32)
+#include <winsock2.h>
+#include <ws2tcpip.h>
+#else
+#include <netdb.h>
+#include <netinet/in.h>
+#include <netinet/tcp.h>
+#include <sys/select.h>
+#include <sys/socket.h>
+#include <unistd.h>
+#endif
+
+#if defined(_WIN32)
+#include <atomic>
+namespace {
+std::atomic<int> wsaInitCount = {0};
+} // anonymous namespace
+#else
+#include <fcntl.h>
+#include <unistd.h>
+namespace {
+using SOCKET = int;
+} // anonymous namespace
+#endif
+
+namespace {
+constexpr SOCKET InvalidSocket = static_cast<SOCKET>(-1);
+void init() {
+#if defined(_WIN32)
+ if (wsaInitCount++ == 0) {
+ WSADATA winsockData;
+ (void)WSAStartup(MAKEWORD(2, 2), &winsockData);
+ }
+#endif
+}
+
+void term() {
+#if defined(_WIN32)
+ if (--wsaInitCount == 0) {
+ WSACleanup();
+ }
+#endif
+}
+
+bool setBlocking(SOCKET s, bool blocking) {
+#if defined(_WIN32)
+ u_long mode = blocking ? 0 : 1;
+ return ioctlsocket(s, FIONBIO, &mode) == NO_ERROR;
+#else
+ auto arg = fcntl(s, F_GETFL, nullptr);
+ if (arg < 0) {
+ return false;
+ }
+ arg = blocking ? (arg & ~O_NONBLOCK) : (arg | O_NONBLOCK);
+ return fcntl(s, F_SETFL, arg) >= 0;
+#endif
+}
+
+bool errored(SOCKET s) {
+ if (s == InvalidSocket) {
+ return true;
+ }
+ char error = 0;
+ socklen_t len = sizeof(error);
+ getsockopt(s, SOL_SOCKET, SO_ERROR, &error, &len);
+ return error != 0;
+}
+
+} // anonymous namespace
+
+class dap::Socket::Shared : public dap::ReaderWriter {
+ public:
+ static std::shared_ptr<Shared> create(const char* address, const char* port) {
+ init();
+
+ addrinfo hints = {};
+ hints.ai_family = AF_INET;
+ hints.ai_socktype = SOCK_STREAM;
+ hints.ai_protocol = IPPROTO_TCP;
+ hints.ai_flags = AI_PASSIVE;
+
+ addrinfo* info = nullptr;
+ getaddrinfo(address, port, &hints, &info);
+
+ if (info) {
+ auto socket =
+ ::socket(info->ai_family, info->ai_socktype, info->ai_protocol);
+ auto out = std::make_shared<Shared>(info, socket);
+ out->setOptions();
+ return out;
+ }
+
+ freeaddrinfo(info);
+ term();
+ return nullptr;
+ }
+
+ Shared(SOCKET socket) : info(nullptr), s(socket) {}
+ Shared(addrinfo* info, SOCKET socket) : info(info), s(socket) {}
+
+ ~Shared() {
+ freeaddrinfo(info);
+ close();
+ term();
+ }
+
+ template <typename FUNCTION>
+ void lock(FUNCTION&& f) {
+ RLock l(mutex);
+ f(s, info);
+ }
+
+ void setOptions() {
+ RLock l(mutex);
+ if (s == InvalidSocket) {
+ return;
+ }
+
+ int enable = 1;
+
+#if !defined(_WIN32)
+ // Prevent sockets lingering after process termination, causing
+ // reconnection issues on the same port.
+ setsockopt(s, SOL_SOCKET, SO_REUSEADDR, (char*)&enable, sizeof(enable));
+
+ struct {
+ int l_onoff; /* linger active */
+ int l_linger; /* how many seconds to linger for */
+ } linger = {false, 0};
+ setsockopt(s, SOL_SOCKET, SO_LINGER, (char*)&linger, sizeof(linger));
+#endif // !defined(_WIN32)
+
+ // Enable TCP_NODELAY.
+ // DAP usually consists of small packet requests, with small packet
+ // responses. When there are many frequent, blocking requests made,
+ // Nagle's algorithm can dramatically limit the request->response rates.
+ setsockopt(s, IPPROTO_TCP, TCP_NODELAY, (char*)&enable, sizeof(enable));
+ }
+
+ // dap::ReaderWriter compliance
+ bool isOpen() {
+ {
+ RLock l(mutex);
+ if ((s != InvalidSocket) && !errored(s)) {
+ return true;
+ }
+ }
+ WLock lock(mutex);
+ s = InvalidSocket;
+ return false;
+ }
+
+ void close() {
+ {
+ RLock l(mutex);
+ if (s != InvalidSocket) {
+#if defined(_WIN32)
+ closesocket(s);
+#elif __APPLE__
+ // ::shutdown() *should* be sufficient to unblock ::accept(), but
+ // apparently on macos it can return ENOTCONN and ::accept() continues
+ // to block indefinitely.
+ // Note: There is a race here. Calling ::close() frees the socket ID,
+ // which may be reused before `s` is assigned InvalidSocket.
+ ::shutdown(s, SHUT_RDWR);
+ ::close(s);
+#else
+ // ::shutdown() to unblock ::accept(). We'll actually close the socket
+ // under lock below.
+ ::shutdown(s, SHUT_RDWR);
+#endif
+ }
+ }
+
+ WLock l(mutex);
+ if (s != InvalidSocket) {
+#if !defined(_WIN32) && !defined(__APPLE__)
+ ::close(s);
+#endif
+ s = InvalidSocket;
+ }
+ }
+
+ size_t read(void* buffer, size_t bytes) {
+ RLock lock(mutex);
+ if (s == InvalidSocket) {
+ return 0;
+ }
+ auto len =
+ recv(s, reinterpret_cast<char*>(buffer), static_cast<int>(bytes), 0);
+ return (len < 0) ? 0 : len;
+ }
+
+ bool write(const void* buffer, size_t bytes) {
+ RLock lock(mutex);
+ if (s == InvalidSocket) {
+ return false;
+ }
+ if (bytes == 0) {
+ return true;
+ }
+ return ::send(s, reinterpret_cast<const char*>(buffer),
+ static_cast<int>(bytes), 0) > 0;
+ }
+
+ private:
+ addrinfo* const info;
+ SOCKET s = InvalidSocket;
+ RWMutex mutex;
+};
+
+namespace dap {
+
+Socket::Socket(const char* address, const char* port)
+ : shared(Shared::create(address, port)) {
+ if (shared) {
+ shared->lock([&](SOCKET socket, const addrinfo* info) {
+ if (bind(socket, info->ai_addr, (int)info->ai_addrlen) != 0) {
+ shared.reset();
+ return;
+ }
+
+ if (listen(socket, 0) != 0) {
+ shared.reset();
+ return;
+ }
+ });
+ }
+}
+
+std::shared_ptr<ReaderWriter> Socket::accept() const {
+ std::shared_ptr<Shared> out;
+ if (shared) {
+ shared->lock([&](SOCKET socket, const addrinfo*) {
+ if (socket != InvalidSocket && !errored(socket)) {
+ init();
+ auto accepted = ::accept(socket, 0, 0);
+ if (accepted != InvalidSocket) {
+ out = std::make_shared<Shared>(accepted);
+ out->setOptions();
+ }
+ }
+ });
+ }
+ return out;
+}
+
+bool Socket::isOpen() const {
+ if (shared) {
+ return shared->isOpen();
+ }
+ return false;
+}
+
+void Socket::close() const {
+ if (shared) {
+ shared->close();
+ }
+}
+
+std::shared_ptr<ReaderWriter> Socket::connect(const char* address,
+ const char* port,
+ uint32_t timeoutMillis) {
+ auto shared = Shared::create(address, port);
+ if (!shared) {
+ return nullptr;
+ }
+
+ std::shared_ptr<ReaderWriter> out;
+ shared->lock([&](SOCKET socket, const addrinfo* info) {
+ if (socket == InvalidSocket) {
+ return;
+ }
+
+ if (timeoutMillis == 0) {
+ if (::connect(socket, info->ai_addr, (int)info->ai_addrlen) == 0) {
+ out = shared;
+ }
+ return;
+ }
+
+ if (!setBlocking(socket, false)) {
+ return;
+ }
+
+ auto res = ::connect(socket, info->ai_addr, (int)info->ai_addrlen);
+ if (res == 0) {
+ if (setBlocking(socket, true)) {
+ out = shared;
+ }
+ } else {
+ const auto microseconds = timeoutMillis * 1000;
+
+ fd_set fdset;
+ FD_ZERO(&fdset);
+ FD_SET(socket, &fdset);
+
+ timeval tv;
+ tv.tv_sec = microseconds / 1000000;
+ tv.tv_usec = microseconds - static_cast<uint32_t>(tv.tv_sec * 1000000);
+ res = select(static_cast<int>(socket + 1), nullptr, &fdset, nullptr, &tv);
+ if (res > 0 && !errored(socket) && setBlocking(socket, true)) {
+ out = shared;
+ }
+ }
+ });
+
+ if (!out) {
+ return nullptr;
+ }
+
+ return out->isOpen() ? out : nullptr;
+}
+
+} // namespace dap
diff --git a/Utilities/cmcppdap/src/socket.h b/Utilities/cmcppdap/src/socket.h
new file mode 100644
index 0000000..ec5b0df
--- /dev/null
+++ b/Utilities/cmcppdap/src/socket.h
@@ -0,0 +1,47 @@
+// Copyright 2019 Google LLC
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// https://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#ifndef dap_socket_h
+#define dap_socket_h
+
+#include "dap/io.h"
+
+#include <atomic>
+#include <memory>
+
+namespace dap {
+
+class Socket {
+ public:
+ class Shared;
+
+ // connect() connects to the given TCP address and port.
+ // If timeoutMillis is non-zero and no connection was made before
+ // timeoutMillis milliseconds, then nullptr is returned.
+ static std::shared_ptr<ReaderWriter> connect(const char* address,
+ const char* port,
+ uint32_t timeoutMillis);
+
+ Socket(const char* address, const char* port);
+ bool isOpen() const;
+ std::shared_ptr<ReaderWriter> accept() const;
+ void close() const;
+
+ private:
+ std::shared_ptr<Shared> shared;
+};
+
+} // namespace dap
+
+#endif // dap_socket_h
diff --git a/Utilities/cmcppdap/src/socket_test.cpp b/Utilities/cmcppdap/src/socket_test.cpp
new file mode 100644
index 0000000..186fd9a
--- /dev/null
+++ b/Utilities/cmcppdap/src/socket_test.cpp
@@ -0,0 +1,104 @@
+// Copyright 2019 Google LLC
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// https://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#include "socket.h"
+
+#include "gmock/gmock.h"
+#include "gtest/gtest.h"
+
+#include <chrono>
+#include <thread>
+#include <vector>
+
+// Basic socket send & receive test
+TEST(Socket, SendRecv) {
+ const char* port = "19021";
+
+ auto server = dap::Socket("localhost", port);
+
+ auto client = dap::Socket::connect("localhost", port, 0);
+ ASSERT_TRUE(client != nullptr);
+
+ const std::string expect = "Hello World!";
+ std::string read;
+
+ auto thread = std::thread([&] {
+ auto conn = server.accept();
+ ASSERT_TRUE(conn != nullptr);
+ char c;
+ while (conn->read(&c, 1) != 0) {
+ read += c;
+ }
+ });
+
+ ASSERT_TRUE(client->write(expect.data(), expect.size()));
+
+ client->close();
+ thread.join();
+
+ ASSERT_EQ(read, expect);
+}
+
+// See https://github.com/google/cppdap/issues/37
+TEST(Socket, CloseOnDifferentThread) {
+ const char* port = "19021";
+
+ auto server = dap::Socket("localhost", port);
+
+ auto client = dap::Socket::connect("localhost", port, 0);
+ ASSERT_TRUE(client != nullptr);
+
+ auto conn = server.accept();
+
+ auto thread = std::thread([&] {
+ // Closing client on different thread should unblock client->read().
+ client->close();
+ });
+
+ char c;
+ while (client->read(&c, 1) != 0) {
+ }
+
+ thread.join();
+}
+
+TEST(Socket, ConnectTimeout) {
+ const char* port = "19021";
+ const int timeoutMillis = 200;
+ const int maxAttempts = 1024;
+
+ using namespace std::chrono;
+
+ auto server = dap::Socket("localhost", port);
+
+ std::vector<std::shared_ptr<dap::ReaderWriter>> connections;
+
+ for (int i = 0; i < maxAttempts; i++) {
+ auto start = system_clock::now();
+ auto connection = dap::Socket::connect("localhost", port, timeoutMillis);
+ auto end = system_clock::now();
+
+ if (!connection) {
+ auto timeTakenMillis = duration_cast<milliseconds>(end - start).count();
+ ASSERT_GE(timeTakenMillis + 20, // +20ms for a bit of timing wiggle room
+ timeoutMillis);
+ return;
+ }
+
+ // Keep hold of the connections to saturate any incoming socket buffers.
+ connections.emplace_back(std::move(connection));
+ }
+
+ FAIL() << "Failed to test timeout after " << maxAttempts << " attempts";
+}
diff --git a/Utilities/cmcppdap/src/string_buffer.h b/Utilities/cmcppdap/src/string_buffer.h
new file mode 100644
index 0000000..cdd6c41
--- /dev/null
+++ b/Utilities/cmcppdap/src/string_buffer.h
@@ -0,0 +1,85 @@
+// Copyright 2019 Google LLC
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// https://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#ifndef dap_string_buffer_h
+#define dap_string_buffer_h
+
+#include "dap/io.h"
+
+#include <algorithm> // std::min
+#include <cstring> // memcpy
+#include <memory> // std::unique_ptr
+#include <string>
+
+namespace dap {
+
+class StringBuffer : public virtual Reader, public virtual Writer {
+ public:
+ static inline std::unique_ptr<StringBuffer> create();
+
+ inline bool write(const std::string& s);
+ inline std::string string() const;
+
+ // Reader / Writer compilance
+ inline bool isOpen() override;
+ inline void close() override;
+ inline size_t read(void* buffer, size_t bytes) override;
+ inline bool write(const void* buffer, size_t bytes) override;
+
+ private:
+ std::string str;
+ bool closed = false;
+};
+
+bool StringBuffer::isOpen() {
+ return !closed;
+}
+void StringBuffer::close() {
+ closed = true;
+}
+
+std::unique_ptr<StringBuffer> StringBuffer::create() {
+ return std::unique_ptr<StringBuffer>(new StringBuffer());
+}
+
+bool StringBuffer::write(const std::string& s) {
+ return write(s.data(), s.size());
+}
+
+std::string StringBuffer::string() const {
+ return str;
+}
+
+size_t StringBuffer::read(void* buffer, size_t bytes) {
+ if (closed || bytes == 0 || str.size() == 0) {
+ return 0;
+ }
+ auto len = std::min(bytes, str.size());
+ memcpy(buffer, str.data(), len);
+ str = std::string(str.begin() + len, str.end());
+ return len;
+}
+
+bool StringBuffer::write(const void* buffer, size_t bytes) {
+ if (closed) {
+ return false;
+ }
+ auto chars = reinterpret_cast<const char*>(buffer);
+ str.append(chars, chars + bytes);
+ return true;
+}
+
+} // namespace dap
+
+#endif // dap_string_buffer_h
diff --git a/Utilities/cmcppdap/src/traits_test.cpp b/Utilities/cmcppdap/src/traits_test.cpp
new file mode 100644
index 0000000..aafca04
--- /dev/null
+++ b/Utilities/cmcppdap/src/traits_test.cpp
@@ -0,0 +1,387 @@
+// Copyright 2021 Google LLC
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// https://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#include "dap/traits.h"
+
+#include "gmock/gmock.h"
+#include "gtest/gtest.h"
+
+namespace dap {
+namespace traits {
+
+namespace {
+struct S {};
+struct E : S {};
+void F1(S) {}
+void F3(int, S, float) {}
+void E1(E) {}
+void E3(int, E, float) {}
+} // namespace
+
+TEST(ParameterType, Function) {
+ F1({}); // Avoid unused method warning
+ F3(0, {}, 0); // Avoid unused method warning
+ static_assert(std::is_same<ParameterType<decltype(&F1), 0>, S>::value, "");
+ static_assert(std::is_same<ParameterType<decltype(&F3), 0>, int>::value, "");
+ static_assert(std::is_same<ParameterType<decltype(&F3), 1>, S>::value, "");
+ static_assert(std::is_same<ParameterType<decltype(&F3), 2>, float>::value,
+ "");
+}
+
+TEST(ParameterType, Method) {
+ class C {
+ public:
+ void F1(S) {}
+ void F3(int, S, float) {}
+ };
+ C().F1({}); // Avoid unused method warning
+ C().F3(0, {}, 0); // Avoid unused method warning
+ static_assert(std::is_same<ParameterType<decltype(&C::F1), 0>, S>::value, "");
+ static_assert(std::is_same<ParameterType<decltype(&C::F3), 0>, int>::value,
+ "");
+ static_assert(std::is_same<ParameterType<decltype(&C::F3), 1>, S>::value, "");
+ static_assert(std::is_same<ParameterType<decltype(&C::F3), 2>, float>::value,
+ "");
+}
+
+TEST(ParameterType, ConstMethod) {
+ class C {
+ public:
+ void F1(S) const {}
+ void F3(int, S, float) const {}
+ };
+ C().F1({}); // Avoid unused method warning
+ C().F3(0, {}, 0); // Avoid unused method warning
+ static_assert(std::is_same<ParameterType<decltype(&C::F1), 0>, S>::value, "");
+ static_assert(std::is_same<ParameterType<decltype(&C::F3), 0>, int>::value,
+ "");
+ static_assert(std::is_same<ParameterType<decltype(&C::F3), 1>, S>::value, "");
+ static_assert(std::is_same<ParameterType<decltype(&C::F3), 2>, float>::value,
+ "");
+}
+
+TEST(ParameterType, StaticMethod) {
+ class C {
+ public:
+ static void F1(S) {}
+ static void F3(int, S, float) {}
+ };
+ C::F1({}); // Avoid unused method warning
+ C::F3(0, {}, 0); // Avoid unused method warning
+ static_assert(std::is_same<ParameterType<decltype(&C::F1), 0>, S>::value, "");
+ static_assert(std::is_same<ParameterType<decltype(&C::F3), 0>, int>::value,
+ "");
+ static_assert(std::is_same<ParameterType<decltype(&C::F3), 1>, S>::value, "");
+ static_assert(std::is_same<ParameterType<decltype(&C::F3), 2>, float>::value,
+ "");
+}
+
+TEST(ParameterType, FunctionLike) {
+ using F1 = std::function<void(S)>;
+ using F3 = std::function<void(int, S, float)>;
+ static_assert(std::is_same<ParameterType<F1, 0>, S>::value, "");
+ static_assert(std::is_same<ParameterType<F3, 0>, int>::value, "");
+ static_assert(std::is_same<ParameterType<F3, 1>, S>::value, "");
+ static_assert(std::is_same<ParameterType<F3, 2>, float>::value, "");
+}
+
+TEST(ParameterType, Lambda) {
+ auto l1 = [](S) {};
+ auto l3 = [](int, S, float) {};
+ static_assert(std::is_same<ParameterType<decltype(l1), 0>, S>::value, "");
+ static_assert(std::is_same<ParameterType<decltype(l3), 0>, int>::value, "");
+ static_assert(std::is_same<ParameterType<decltype(l3), 1>, S>::value, "");
+ static_assert(std::is_same<ParameterType<decltype(l3), 2>, float>::value, "");
+}
+
+TEST(HasSignature, Function) {
+ F1({}); // Avoid unused method warning
+ F3(0, {}, 0); // Avoid unused method warning
+ static_assert(HasSignature<decltype(&F1), decltype(&F1)>::value, "");
+ static_assert(HasSignature<decltype(&F3), decltype(&F3)>::value, "");
+ static_assert(HasSignature<decltype(&F3), decltype(&F3)>::value, "");
+ static_assert(HasSignature<decltype(&F3), decltype(&F3)>::value, "");
+ static_assert(!HasSignature<decltype(&F1), decltype(&F3)>::value, "");
+ static_assert(!HasSignature<decltype(&F3), decltype(&F1)>::value, "");
+ static_assert(!HasSignature<decltype(&F3), decltype(&F1)>::value, "");
+ static_assert(!HasSignature<decltype(&F3), decltype(&F1)>::value, "");
+}
+
+TEST(HasSignature, Method) {
+ class C {
+ public:
+ void F1(S) {}
+ void F3(int, S, float) {}
+ };
+ C().F1({}); // Avoid unused method warning
+ C().F3(0, {}, 0); // Avoid unused method warning
+
+ static_assert(HasSignature<decltype(&C::F1), decltype(&F1)>::value, "");
+ static_assert(HasSignature<decltype(&C::F3), decltype(&F3)>::value, "");
+ static_assert(HasSignature<decltype(&C::F3), decltype(&F3)>::value, "");
+ static_assert(HasSignature<decltype(&C::F3), decltype(&F3)>::value, "");
+ static_assert(!HasSignature<decltype(&C::F1), decltype(&F3)>::value, "");
+ static_assert(!HasSignature<decltype(&C::F3), decltype(&F1)>::value, "");
+ static_assert(!HasSignature<decltype(&C::F3), decltype(&F1)>::value, "");
+ static_assert(!HasSignature<decltype(&C::F3), decltype(&F1)>::value, "");
+}
+
+TEST(HasSignature, ConstMethod) {
+ class C {
+ public:
+ void F1(S) const {}
+ void F3(int, S, float) const {}
+ };
+ C().F1({}); // Avoid unused method warning
+ C().F3(0, {}, 0); // Avoid unused method warning
+
+ static_assert(HasSignature<decltype(&C::F1), decltype(&F1)>::value, "");
+ static_assert(HasSignature<decltype(&C::F3), decltype(&F3)>::value, "");
+ static_assert(HasSignature<decltype(&C::F3), decltype(&F3)>::value, "");
+ static_assert(HasSignature<decltype(&C::F3), decltype(&F3)>::value, "");
+ static_assert(!HasSignature<decltype(&C::F1), decltype(&F3)>::value, "");
+ static_assert(!HasSignature<decltype(&C::F3), decltype(&F1)>::value, "");
+ static_assert(!HasSignature<decltype(&C::F3), decltype(&F1)>::value, "");
+ static_assert(!HasSignature<decltype(&C::F3), decltype(&F1)>::value, "");
+}
+
+TEST(HasSignature, StaticMethod) {
+ class C {
+ public:
+ static void F1(S) {}
+ static void F3(int, S, float) {}
+ };
+ C::F1({}); // Avoid unused method warning
+ C::F3(0, {}, 0); // Avoid unused method warning
+
+ static_assert(HasSignature<decltype(&C::F1), decltype(&F1)>::value, "");
+ static_assert(HasSignature<decltype(&C::F3), decltype(&F3)>::value, "");
+ static_assert(HasSignature<decltype(&C::F3), decltype(&F3)>::value, "");
+ static_assert(HasSignature<decltype(&C::F3), decltype(&F3)>::value, "");
+ static_assert(!HasSignature<decltype(&C::F1), decltype(&F3)>::value, "");
+ static_assert(!HasSignature<decltype(&C::F3), decltype(&F1)>::value, "");
+ static_assert(!HasSignature<decltype(&C::F3), decltype(&F1)>::value, "");
+ static_assert(!HasSignature<decltype(&C::F3), decltype(&F1)>::value, "");
+}
+
+TEST(HasSignature, FunctionLike) {
+ using f1 = std::function<void(S)>;
+ using f3 = std::function<void(int, S, float)>;
+ static_assert(HasSignature<f1, decltype(&F1)>::value, "");
+ static_assert(HasSignature<f3, decltype(&F3)>::value, "");
+ static_assert(HasSignature<f3, decltype(&F3)>::value, "");
+ static_assert(HasSignature<f3, decltype(&F3)>::value, "");
+ static_assert(!HasSignature<f1, decltype(&F3)>::value, "");
+ static_assert(!HasSignature<f3, decltype(&F1)>::value, "");
+ static_assert(!HasSignature<f3, decltype(&F1)>::value, "");
+ static_assert(!HasSignature<f3, decltype(&F1)>::value, "");
+}
+
+TEST(HasSignature, Lambda) {
+ auto l1 = [](S) {};
+ auto l3 = [](int, S, float) {};
+ static_assert(HasSignature<decltype(l1), decltype(&F1)>::value, "");
+ static_assert(HasSignature<decltype(l3), decltype(&F3)>::value, "");
+ static_assert(HasSignature<decltype(l3), decltype(&F3)>::value, "");
+ static_assert(HasSignature<decltype(l3), decltype(&F3)>::value, "");
+ static_assert(!HasSignature<decltype(l1), decltype(&F3)>::value, "");
+ static_assert(!HasSignature<decltype(l3), decltype(&F1)>::value, "");
+ static_assert(!HasSignature<decltype(l3), decltype(&F1)>::value, "");
+ static_assert(!HasSignature<decltype(l3), decltype(&F1)>::value, "");
+}
+
+////
+
+TEST(CompatibleWith, Function) {
+ F1({}); // Avoid unused method warning
+ F3(0, {}, 0); // Avoid unused method warning
+ E1({}); // Avoid unused method warning
+ E3(0, {}, 0); // Avoid unused method warning
+ static_assert(CompatibleWith<decltype(&F1), decltype(&F1)>::value, "");
+ static_assert(CompatibleWith<decltype(&F3), decltype(&F3)>::value, "");
+ static_assert(CompatibleWith<decltype(&F3), decltype(&F3)>::value, "");
+ static_assert(CompatibleWith<decltype(&F3), decltype(&F3)>::value, "");
+
+ static_assert(!CompatibleWith<decltype(&F1), decltype(&F3)>::value, "");
+ static_assert(!CompatibleWith<decltype(&F3), decltype(&F1)>::value, "");
+ static_assert(!CompatibleWith<decltype(&F3), decltype(&F1)>::value, "");
+ static_assert(!CompatibleWith<decltype(&F3), decltype(&F1)>::value, "");
+
+ static_assert(CompatibleWith<decltype(&E1), decltype(&F1)>::value, "");
+ static_assert(CompatibleWith<decltype(&E3), decltype(&F3)>::value, "");
+ static_assert(CompatibleWith<decltype(&E3), decltype(&F3)>::value, "");
+ static_assert(CompatibleWith<decltype(&E3), decltype(&F3)>::value, "");
+
+ static_assert(!CompatibleWith<decltype(&F1), decltype(&E1)>::value, "");
+ static_assert(!CompatibleWith<decltype(&F3), decltype(&E3)>::value, "");
+ static_assert(!CompatibleWith<decltype(&F3), decltype(&E3)>::value, "");
+ static_assert(!CompatibleWith<decltype(&F3), decltype(&E3)>::value, "");
+}
+
+TEST(CompatibleWith, Method) {
+ class C {
+ public:
+ void F1(S) {}
+ void F3(int, S, float) {}
+ void E1(E) {}
+ void E3(int, E, float) {}
+ };
+ C().F1({}); // Avoid unused method warning
+ C().F3(0, {}, 0); // Avoid unused method warning
+ C().E1({}); // Avoid unused method warning
+ C().E3(0, {}, 0); // Avoid unused method warning
+
+ static_assert(CompatibleWith<decltype(&C::F1), decltype(&F1)>::value, "");
+ static_assert(CompatibleWith<decltype(&C::F3), decltype(&F3)>::value, "");
+ static_assert(CompatibleWith<decltype(&C::F3), decltype(&F3)>::value, "");
+ static_assert(CompatibleWith<decltype(&C::F3), decltype(&F3)>::value, "");
+
+ static_assert(!CompatibleWith<decltype(&C::F1), decltype(&F3)>::value, "");
+ static_assert(!CompatibleWith<decltype(&C::F3), decltype(&F1)>::value, "");
+ static_assert(!CompatibleWith<decltype(&C::F3), decltype(&F1)>::value, "");
+ static_assert(!CompatibleWith<decltype(&C::F3), decltype(&F1)>::value, "");
+
+ static_assert(CompatibleWith<decltype(&C::E1), decltype(&C::F1)>::value, "");
+ static_assert(CompatibleWith<decltype(&C::E3), decltype(&C::F3)>::value, "");
+ static_assert(CompatibleWith<decltype(&C::E3), decltype(&C::F3)>::value, "");
+ static_assert(CompatibleWith<decltype(&C::E3), decltype(&C::F3)>::value, "");
+
+ static_assert(!CompatibleWith<decltype(&C::F1), decltype(&C::E1)>::value, "");
+ static_assert(!CompatibleWith<decltype(&C::F3), decltype(&C::E3)>::value, "");
+ static_assert(!CompatibleWith<decltype(&C::F3), decltype(&C::E3)>::value, "");
+ static_assert(!CompatibleWith<decltype(&C::F3), decltype(&C::E3)>::value, "");
+}
+
+TEST(CompatibleWith, ConstMethod) {
+ class C {
+ public:
+ void F1(S) const {}
+ void F3(int, S, float) const {}
+ void E1(E) const {}
+ void E3(int, E, float) const {}
+ };
+ C().F1({}); // Avoid unused method warning
+ C().F3(0, {}, 0); // Avoid unused method warning
+ C().E1({}); // Avoid unused method warning
+ C().E3(0, {}, 0); // Avoid unused method warning
+
+ static_assert(CompatibleWith<decltype(&C::F1), decltype(&F1)>::value, "");
+ static_assert(CompatibleWith<decltype(&C::F3), decltype(&F3)>::value, "");
+ static_assert(CompatibleWith<decltype(&C::F3), decltype(&F3)>::value, "");
+ static_assert(CompatibleWith<decltype(&C::F3), decltype(&F3)>::value, "");
+
+ static_assert(!CompatibleWith<decltype(&C::F1), decltype(&F3)>::value, "");
+ static_assert(!CompatibleWith<decltype(&C::F3), decltype(&F1)>::value, "");
+ static_assert(!CompatibleWith<decltype(&C::F3), decltype(&F1)>::value, "");
+ static_assert(!CompatibleWith<decltype(&C::F3), decltype(&F1)>::value, "");
+
+ static_assert(CompatibleWith<decltype(&C::E1), decltype(&C::F1)>::value, "");
+ static_assert(CompatibleWith<decltype(&C::E3), decltype(&C::F3)>::value, "");
+ static_assert(CompatibleWith<decltype(&C::E3), decltype(&C::F3)>::value, "");
+ static_assert(CompatibleWith<decltype(&C::E3), decltype(&C::F3)>::value, "");
+
+ static_assert(!CompatibleWith<decltype(&C::F1), decltype(&C::E1)>::value, "");
+ static_assert(!CompatibleWith<decltype(&C::F3), decltype(&C::E3)>::value, "");
+ static_assert(!CompatibleWith<decltype(&C::F3), decltype(&C::E3)>::value, "");
+ static_assert(!CompatibleWith<decltype(&C::F3), decltype(&C::E3)>::value, "");
+}
+
+TEST(CompatibleWith, StaticMethod) {
+ class C {
+ public:
+ static void F1(S) {}
+ static void F3(int, S, float) {}
+ static void E1(E) {}
+ static void E3(int, E, float) {}
+ };
+ C::F1({}); // Avoid unused method warning
+ C::F3(0, {}, 0); // Avoid unused method warning
+ C::E1({}); // Avoid unused method warning
+ C::E3(0, {}, 0); // Avoid unused method warning
+
+ static_assert(CompatibleWith<decltype(&C::F1), decltype(&F1)>::value, "");
+ static_assert(CompatibleWith<decltype(&C::F3), decltype(&F3)>::value, "");
+ static_assert(CompatibleWith<decltype(&C::F3), decltype(&F3)>::value, "");
+ static_assert(CompatibleWith<decltype(&C::F3), decltype(&F3)>::value, "");
+
+ static_assert(!CompatibleWith<decltype(&C::F1), decltype(&F3)>::value, "");
+ static_assert(!CompatibleWith<decltype(&C::F3), decltype(&F1)>::value, "");
+ static_assert(!CompatibleWith<decltype(&C::F3), decltype(&F1)>::value, "");
+ static_assert(!CompatibleWith<decltype(&C::F3), decltype(&F1)>::value, "");
+
+ static_assert(CompatibleWith<decltype(&C::E1), decltype(&C::F1)>::value, "");
+ static_assert(CompatibleWith<decltype(&C::E3), decltype(&C::F3)>::value, "");
+ static_assert(CompatibleWith<decltype(&C::E3), decltype(&C::F3)>::value, "");
+ static_assert(CompatibleWith<decltype(&C::E3), decltype(&C::F3)>::value, "");
+
+ static_assert(!CompatibleWith<decltype(&C::F1), decltype(&C::E1)>::value, "");
+ static_assert(!CompatibleWith<decltype(&C::F3), decltype(&C::E3)>::value, "");
+ static_assert(!CompatibleWith<decltype(&C::F3), decltype(&C::E3)>::value, "");
+ static_assert(!CompatibleWith<decltype(&C::F3), decltype(&C::E3)>::value, "");
+}
+
+TEST(CompatibleWith, FunctionLike) {
+ using f1 = std::function<void(S)>;
+ using f3 = std::function<void(int, S, float)>;
+ using e1 = std::function<void(E)>;
+ using e3 = std::function<void(int, E, float)>;
+ static_assert(CompatibleWith<f1, decltype(&F1)>::value, "");
+ static_assert(CompatibleWith<f3, decltype(&F3)>::value, "");
+ static_assert(CompatibleWith<f3, decltype(&F3)>::value, "");
+ static_assert(CompatibleWith<f3, decltype(&F3)>::value, "");
+
+ static_assert(!CompatibleWith<f1, decltype(&F3)>::value, "");
+ static_assert(!CompatibleWith<f3, decltype(&F1)>::value, "");
+ static_assert(!CompatibleWith<f3, decltype(&F1)>::value, "");
+ static_assert(!CompatibleWith<f3, decltype(&F1)>::value, "");
+
+ static_assert(CompatibleWith<e1, f1>::value, "");
+ static_assert(CompatibleWith<e3, f3>::value, "");
+ static_assert(CompatibleWith<e3, f3>::value, "");
+ static_assert(CompatibleWith<e3, f3>::value, "");
+
+ static_assert(!CompatibleWith<f1, e1>::value, "");
+ static_assert(!CompatibleWith<f3, e3>::value, "");
+ static_assert(!CompatibleWith<f3, e3>::value, "");
+ static_assert(!CompatibleWith<f3, e3>::value, "");
+}
+
+TEST(CompatibleWith, Lambda) {
+ auto f1 = [](S) {};
+ auto f3 = [](int, S, float) {};
+ auto e1 = [](E) {};
+ auto e3 = [](int, E, float) {};
+ static_assert(CompatibleWith<decltype(f1), decltype(&F1)>::value, "");
+ static_assert(CompatibleWith<decltype(f3), decltype(&F3)>::value, "");
+ static_assert(CompatibleWith<decltype(f3), decltype(&F3)>::value, "");
+ static_assert(CompatibleWith<decltype(f3), decltype(&F3)>::value, "");
+
+ static_assert(!CompatibleWith<decltype(f1), decltype(&F3)>::value, "");
+ static_assert(!CompatibleWith<decltype(f3), decltype(&F1)>::value, "");
+ static_assert(!CompatibleWith<decltype(f3), decltype(&F1)>::value, "");
+ static_assert(!CompatibleWith<decltype(f3), decltype(&F1)>::value, "");
+
+ static_assert(CompatibleWith<decltype(e1), decltype(f1)>::value, "");
+ static_assert(CompatibleWith<decltype(e3), decltype(f3)>::value, "");
+ static_assert(CompatibleWith<decltype(e3), decltype(f3)>::value, "");
+ static_assert(CompatibleWith<decltype(e3), decltype(f3)>::value, "");
+
+ static_assert(!CompatibleWith<decltype(f1), decltype(e1)>::value, "");
+ static_assert(!CompatibleWith<decltype(f3), decltype(e3)>::value, "");
+ static_assert(!CompatibleWith<decltype(f3), decltype(e3)>::value, "");
+ static_assert(!CompatibleWith<decltype(f3), decltype(e3)>::value, "");
+}
+
+} // namespace traits
+} // namespace dap
diff --git a/Utilities/cmcppdap/src/typeinfo.cpp b/Utilities/cmcppdap/src/typeinfo.cpp
new file mode 100644
index 0000000..dda481f
--- /dev/null
+++ b/Utilities/cmcppdap/src/typeinfo.cpp
@@ -0,0 +1,21 @@
+// Copyright 2020 Google LLC
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// https://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#include "dap/typeinfo.h"
+
+namespace dap {
+
+TypeInfo::~TypeInfo() = default;
+
+} // namespace dap
diff --git a/Utilities/cmcppdap/src/typeinfo_test.cpp b/Utilities/cmcppdap/src/typeinfo_test.cpp
new file mode 100644
index 0000000..23d5793
--- /dev/null
+++ b/Utilities/cmcppdap/src/typeinfo_test.cpp
@@ -0,0 +1,65 @@
+// Copyright 2020 Google LLC
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// https://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#include "dap/typeof.h"
+#include "dap/types.h"
+#include "json_serializer.h"
+
+#include "gmock/gmock.h"
+#include "gtest/gtest.h"
+
+namespace dap {
+
+struct BaseStruct {
+ dap::integer i;
+ dap::number n;
+};
+
+DAP_STRUCT_TYPEINFO(BaseStruct,
+ "BaseStruct",
+ DAP_FIELD(i, "i"),
+ DAP_FIELD(n, "n"));
+
+struct DerivedStruct : public BaseStruct {
+ dap::string s;
+ dap::boolean b;
+};
+
+DAP_STRUCT_TYPEINFO_EXT(DerivedStruct,
+ BaseStruct,
+ "DerivedStruct",
+ DAP_FIELD(s, "s"),
+ DAP_FIELD(b, "b"));
+
+} // namespace dap
+
+TEST(TypeInfo, Derived) {
+ dap::DerivedStruct in;
+ in.s = "hello world";
+ in.b = true;
+ in.i = 42;
+ in.n = 3.14;
+
+ dap::json::Serializer s;
+ ASSERT_TRUE(s.serialize(in));
+
+ dap::DerivedStruct out;
+ dap::json::Deserializer d(s.dump());
+ ASSERT_TRUE(d.deserialize(&out)) << "Failed to deserialize\n" << s.dump();
+
+ ASSERT_EQ(out.s, "hello world");
+ ASSERT_EQ(out.b, true);
+ ASSERT_EQ(out.i, 42);
+ ASSERT_EQ(out.n, 3.14);
+}
diff --git a/Utilities/cmcppdap/src/typeof.cpp b/Utilities/cmcppdap/src/typeof.cpp
new file mode 100644
index 0000000..055421c
--- /dev/null
+++ b/Utilities/cmcppdap/src/typeof.cpp
@@ -0,0 +1,144 @@
+// Copyright 2019 Google LLC
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// https://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#include "dap/typeof.h"
+
+#include <atomic>
+#include <memory>
+#include <vector>
+
+namespace {
+
+// TypeInfos owns all the dap::TypeInfo instances.
+struct TypeInfos {
+ // get() returns the TypeInfos singleton pointer.
+ // TypeInfos is constructed with an internal reference count of 1.
+ static TypeInfos* get();
+
+ // reference() increments the TypeInfos reference count.
+ inline void reference() {
+ assert(refcount.load() > 0);
+ refcount++;
+ }
+
+ // release() decrements the TypeInfos reference count.
+ // If the reference count becomes 0, then the TypeInfos is destructed.
+ inline void release() {
+ if (--refcount == 0) {
+ this->~TypeInfos();
+ }
+ }
+
+ struct NullTI : public dap::TypeInfo {
+ using null = dap::null;
+ inline std::string name() const override { return "null"; }
+ inline size_t size() const override { return sizeof(null); }
+ inline size_t alignment() const override { return alignof(null); }
+ inline void construct(void* ptr) const override { new (ptr) null(); }
+ inline void copyConstruct(void* dst, const void* src) const override {
+ new (dst) null(*reinterpret_cast<const null*>(src));
+ }
+ inline void destruct(void* ptr) const override {
+ reinterpret_cast<null*>(ptr)->~null();
+ }
+ inline bool deserialize(const dap::Deserializer*, void*) const override {
+ return true;
+ }
+ inline bool serialize(dap::Serializer*, const void*) const override {
+ return true;
+ }
+ };
+
+ dap::BasicTypeInfo<dap::boolean> boolean = {"boolean"};
+ dap::BasicTypeInfo<dap::string> string = {"string"};
+ dap::BasicTypeInfo<dap::integer> integer = {"integer"};
+ dap::BasicTypeInfo<dap::number> number = {"number"};
+ dap::BasicTypeInfo<dap::object> object = {"object"};
+ dap::BasicTypeInfo<dap::any> any = {"any"};
+ NullTI null;
+ std::vector<std::unique_ptr<dap::TypeInfo>> types;
+
+ private:
+ TypeInfos() = default;
+ ~TypeInfos() = default;
+ std::atomic<uint64_t> refcount = {1};
+};
+
+// aligned_storage() is a replacement for std::aligned_storage that isn't busted
+// on older versions of MSVC.
+template <size_t SIZE, size_t ALIGNMENT>
+struct aligned_storage {
+ struct alignas(ALIGNMENT) type {
+ unsigned char data[SIZE];
+ };
+};
+
+TypeInfos* TypeInfos::get() {
+ static aligned_storage<sizeof(TypeInfos), alignof(TypeInfos)>::type memory;
+
+ struct Instance {
+ TypeInfos* ptr() { return reinterpret_cast<TypeInfos*>(memory.data); }
+ Instance() { new (ptr()) TypeInfos(); }
+ ~Instance() { ptr()->release(); }
+ };
+
+ static Instance instance;
+ return instance.ptr();
+}
+
+} // namespace
+
+namespace dap {
+
+const TypeInfo* TypeOf<boolean>::type() {
+ return &TypeInfos::get()->boolean;
+}
+
+const TypeInfo* TypeOf<string>::type() {
+ return &TypeInfos::get()->string;
+}
+
+const TypeInfo* TypeOf<integer>::type() {
+ return &TypeInfos::get()->integer;
+}
+
+const TypeInfo* TypeOf<number>::type() {
+ return &TypeInfos::get()->number;
+}
+
+const TypeInfo* TypeOf<object>::type() {
+ return &TypeInfos::get()->object;
+}
+
+const TypeInfo* TypeOf<any>::type() {
+ return &TypeInfos::get()->any;
+}
+
+const TypeInfo* TypeOf<null>::type() {
+ return &TypeInfos::get()->null;
+}
+
+void TypeInfo::deleteOnExit(TypeInfo* ti) {
+ TypeInfos::get()->types.emplace_back(std::unique_ptr<TypeInfo>(ti));
+}
+
+void initialize() {
+ TypeInfos::get()->reference();
+}
+
+void terminate() {
+ TypeInfos::get()->release();
+}
+
+} // namespace dap
diff --git a/Utilities/cmcppdap/src/variant_test.cpp b/Utilities/cmcppdap/src/variant_test.cpp
new file mode 100644
index 0000000..5a1f4eb
--- /dev/null
+++ b/Utilities/cmcppdap/src/variant_test.cpp
@@ -0,0 +1,94 @@
+// Copyright 2019 Google LLC
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// https://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#include "dap/variant.h"
+#include "dap/typeof.h"
+#include "dap/types.h"
+
+#include "gmock/gmock.h"
+#include "gtest/gtest.h"
+
+namespace dap {
+
+struct VariantTestObject {
+ dap::integer i;
+ dap::number n;
+};
+
+DAP_STRUCT_TYPEINFO(VariantTestObject,
+ "VariantTestObject",
+ DAP_FIELD(i, "i"),
+ DAP_FIELD(n, "n"));
+
+} // namespace dap
+
+TEST(Variant, EmptyConstruct) {
+ dap::variant<dap::integer, dap::boolean, dap::VariantTestObject> variant;
+ ASSERT_TRUE(variant.is<dap::integer>());
+ ASSERT_FALSE(variant.is<dap::boolean>());
+ ASSERT_FALSE(variant.is<dap::VariantTestObject>());
+}
+
+TEST(Variant, Boolean) {
+ dap::variant<dap::integer, dap::boolean, dap::VariantTestObject> variant(
+ dap::boolean(true));
+ ASSERT_TRUE(variant.is<dap::boolean>());
+ ASSERT_EQ(variant.get<dap::boolean>(), dap::boolean(true));
+}
+
+TEST(Variant, Integer) {
+ dap::variant<dap::integer, dap::boolean, dap::VariantTestObject> variant(
+ dap::integer(10));
+ ASSERT_TRUE(variant.is<dap::integer>());
+ ASSERT_EQ(variant.get<dap::integer>(), dap::integer(10));
+}
+
+TEST(Variant, TestObject) {
+ dap::variant<dap::integer, dap::boolean, dap::VariantTestObject> variant(
+ dap::VariantTestObject{5, 3.0});
+ ASSERT_TRUE(variant.is<dap::VariantTestObject>());
+ ASSERT_EQ(variant.get<dap::VariantTestObject>().i, 5);
+ ASSERT_EQ(variant.get<dap::VariantTestObject>().n, 3.0);
+}
+
+TEST(Variant, Assign) {
+ dap::variant<dap::integer, dap::boolean, dap::VariantTestObject> variant(
+ dap::integer(10));
+ variant = dap::integer(10);
+ ASSERT_TRUE(variant.is<dap::integer>());
+ ASSERT_FALSE(variant.is<dap::boolean>());
+ ASSERT_FALSE(variant.is<dap::VariantTestObject>());
+ ASSERT_EQ(variant.get<dap::integer>(), dap::integer(10));
+ variant = dap::boolean(true);
+ ASSERT_FALSE(variant.is<dap::integer>());
+ ASSERT_TRUE(variant.is<dap::boolean>());
+ ASSERT_FALSE(variant.is<dap::VariantTestObject>());
+ ASSERT_EQ(variant.get<dap::boolean>(), dap::boolean(true));
+ variant = dap::VariantTestObject{5, 3.0};
+ ASSERT_FALSE(variant.is<dap::integer>());
+ ASSERT_FALSE(variant.is<dap::boolean>());
+ ASSERT_TRUE(variant.is<dap::VariantTestObject>());
+ ASSERT_EQ(variant.get<dap::VariantTestObject>().i, 5);
+ ASSERT_EQ(variant.get<dap::VariantTestObject>().n, 3.0);
+}
+
+TEST(Variant, Accepts) {
+ using variant =
+ dap::variant<dap::integer, dap::boolean, dap::VariantTestObject>;
+ ASSERT_TRUE(variant::accepts<dap::integer>());
+ ASSERT_TRUE(variant::accepts<dap::boolean>());
+ ASSERT_TRUE(variant::accepts<dap::VariantTestObject>());
+ ASSERT_FALSE(variant::accepts<dap::number>());
+ ASSERT_FALSE(variant::accepts<dap::string>());
+}
diff --git a/Utilities/cmcurl/curltest.c b/Utilities/cmcurl/curltest.c
index f80e758..cb87fce 100644
--- a/Utilities/cmcurl/curltest.c
+++ b/Utilities/cmcurl/curltest.c
@@ -10,21 +10,24 @@ int test_curl(const char* url)
CURLcode r;
char proxy[1024];
int proxy_type = 0;
+ const char* env_HTTP_PROXY = getenv("HTTP_PROXY");
- if (getenv("HTTP_PROXY")) {
+ if (env_HTTP_PROXY) {
+ const char* env_HTTP_PROXY_PORT = getenv("HTTP_PROXY_PORT");
+ const char* env_HTTP_PROXY_TYPE = getenv("HTTP_PROXY_TYPE");
proxy_type = 1;
- if (getenv("HTTP_PROXY_PORT")) {
- sprintf(proxy, "%s:%s", getenv("HTTP_PROXY"), getenv("HTTP_PROXY_PORT"));
+ if (env_HTTP_PROXY_PORT) {
+ sprintf(proxy, "%s:%s", env_HTTP_PROXY, env_HTTP_PROXY_PORT);
} else {
- sprintf(proxy, "%s", getenv("HTTP_PROXY"));
+ sprintf(proxy, "%s", env_HTTP_PROXY);
}
- if (getenv("HTTP_PROXY_TYPE")) {
+ if (env_HTTP_PROXY_TYPE) {
/* HTTP/SOCKS4/SOCKS5 */
- if (strcmp(getenv("HTTP_PROXY_TYPE"), "HTTP") == 0) {
+ if (strcmp(env_HTTP_PROXY_TYPE, "HTTP") == 0) {
proxy_type = 1;
- } else if (strcmp(getenv("HTTP_PROXY_TYPE"), "SOCKS4") == 0) {
+ } else if (strcmp(env_HTTP_PROXY_TYPE, "SOCKS4") == 0) {
proxy_type = 2;
- } else if (strcmp(getenv("HTTP_PROXY_TYPE"), "SOCKS5") == 0) {
+ } else if (strcmp(env_HTTP_PROXY_TYPE, "SOCKS5") == 0) {
proxy_type = 3;
}
}
diff --git a/Utilities/cmlibarchive/libarchive/archive_acl.c b/Utilities/cmlibarchive/libarchive/archive_acl.c
index ead7e36..da471a5 100644
--- a/Utilities/cmlibarchive/libarchive/archive_acl.c
+++ b/Utilities/cmlibarchive/libarchive/archive_acl.c
@@ -37,6 +37,10 @@ __FBSDID("$FreeBSD$");
#include <wchar.h>
#endif
+#ifdef __clang_analyzer__
+#include <assert.h>
+#endif
+
#include "archive_acl_private.h"
#include "archive_entry.h"
#include "archive_private.h"
@@ -1209,6 +1213,9 @@ archive_acl_from_text_w(struct archive_acl *acl, const wchar_t *text,
* to "user::rwx", etc. valid only for first field
*/
s = field[0].start;
+ #ifdef __clang_analyzer__
+ assert(s);
+ #endif
len = field[0].end - field[0].start;
if (*s == L'd' && (len == 1 || (len >= 7
&& wmemcmp((s + 1), L"efault", 6) == 0))) {
@@ -1692,6 +1699,9 @@ archive_acl_from_text_l(struct archive_acl *acl, const char *text,
* to "user::rwx", etc. valid only for first field
*/
s = field[0].start;
+ #ifdef __clang_analyzer__
+ assert(s);
+ #endif
len = field[0].end - field[0].start;
if (*s == 'd' && (len == 1 || (len >= 7
&& memcmp((s + 1), "efault", 6) == 0))) {
diff --git a/Utilities/cmlibarchive/libarchive/archive_match.c b/Utilities/cmlibarchive/libarchive/archive_match.c
index 04747b1..2de0045 100644
--- a/Utilities/cmlibarchive/libarchive/archive_match.c
+++ b/Utilities/cmlibarchive/libarchive/archive_match.c
@@ -606,6 +606,10 @@ add_pattern_from_file(struct archive_match *a, struct match_list *mlist,
return (ARCHIVE_FATAL);
}
r = archive_read_support_format_raw(ar);
+#ifdef __clang_analyzer__
+ /* Tolerate deadcode.DeadStores to avoid modifying upstream. */
+ (void)r;
+#endif
r = archive_read_support_format_empty(ar);
if (r != ARCHIVE_OK) {
archive_copy_error(&(a->archive), ar);
diff --git a/Utilities/cmlibarchive/libarchive/archive_ppmd8.c b/Utilities/cmlibarchive/libarchive/archive_ppmd8.c
index d177939..272ca4c 100644
--- a/Utilities/cmlibarchive/libarchive/archive_ppmd8.c
+++ b/Utilities/cmlibarchive/libarchive/archive_ppmd8.c
@@ -4,6 +4,10 @@ This code is based on PPMd var.I (2002): Dmitry Shkarin : Public domain */
#include "archive_platform.h"
+#ifdef __clang_analyzer__
+#include <assert.h>
+#endif
+
#include <string.h>
#include "archive_ppmd8_private.h"
@@ -337,6 +341,9 @@ static void ExpandTextArea(CPpmd8 *p)
static void SetSuccessor(CPpmd_State *p, CPpmd_Void_Ref v)
{
+ #ifdef __clang_analyzer__
+ assert(p);
+ #endif
(p)->SuccessorLow = (UInt16)((UInt32)(v) & 0xFFFF);
(p)->SuccessorHigh = (UInt16)(((UInt32)(v) >> 16) & 0xFFFF);
}
@@ -616,6 +623,11 @@ static CTX_PTR CreateSuccessors(CPpmd8 *p, Bool skip, CPpmd_State *s1, CTX_PTR c
/* fixed over Shkarin's code. Maybe it could work without + 1 too. */
CPpmd_State *ps[PPMD8_MAX_ORDER + 1];
unsigned numPs = 0;
+
+#ifdef __clang_analyzer__
+ memset(ps, 0, sizeof(ps));
+#endif
+
if (!skip)
ps[numPs++] = p->FoundState;
diff --git a/Utilities/cmlibarchive/libarchive/archive_read_disk_posix.c b/Utilities/cmlibarchive/libarchive/archive_read_disk_posix.c
index 5a94ec5..c964d3f 100644
--- a/Utilities/cmlibarchive/libarchive/archive_read_disk_posix.c
+++ b/Utilities/cmlibarchive/libarchive/archive_read_disk_posix.c
@@ -92,6 +92,10 @@ __FBSDID("$FreeBSD$");
#include <sys/ioctl.h>
#endif
+#ifdef __clang_analyzer__
+#include <assert.h>
+#endif
+
#include "archive.h"
#include "archive_string.h"
#include "archive_entry.h"
@@ -742,6 +746,10 @@ _archive_read_data_block(struct archive *_a, const void **buff,
else if (errno == EPERM)
flags &= ~O_NOATIME;
}
+#ifdef __clang_analyzer__
+ /* Tolerate deadcode.DeadStores to avoid modifying upstream. */
+ (void)flags;
+#endif
#endif
if (t->entry_fd < 0) {
archive_set_error(&a->archive, errno,
@@ -2347,6 +2355,9 @@ tree_pop(struct tree *t)
if (t->stack == t->current && t->current != NULL)
t->current = t->current->parent;
te = t->stack;
+ #ifdef __clang_analyzer__
+ assert(te);
+ #endif
t->stack = te->next;
t->dirname_length = te->dirname_length;
t->basename = t->path.s + t->dirname_length;
diff --git a/Utilities/cmlibarchive/libarchive/archive_read_support_filter_uu.c b/Utilities/cmlibarchive/libarchive/archive_read_support_filter_uu.c
index 209b2a1..c66c247 100644
--- a/Utilities/cmlibarchive/libarchive/archive_read_support_filter_uu.c
+++ b/Utilities/cmlibarchive/libarchive/archive_read_support_filter_uu.c
@@ -36,6 +36,10 @@ __FBSDID("$FreeBSD$");
#include <string.h>
#endif
+#ifdef __clang_analyzer__
+#include <assert.h>
+#endif
+
#include "archive.h"
#include "archive_private.h"
#include "archive_read_private.h"
@@ -467,6 +471,9 @@ read_more:
if (ensure_in_buff_size(self, uudecode,
avail_in + uudecode->in_cnt) != ARCHIVE_OK)
return (ARCHIVE_FATAL);
+ #ifdef __clang_analyzer__
+ assert(d);
+ #endif
memcpy(uudecode->in_buff + uudecode->in_cnt,
d, avail_in);
d = uudecode->in_buff;
diff --git a/Utilities/cmlibarchive/libarchive/archive_read_support_format_7zip.c b/Utilities/cmlibarchive/libarchive/archive_read_support_format_7zip.c
index 722edf1..a4d9dcf 100644
--- a/Utilities/cmlibarchive/libarchive/archive_read_support_format_7zip.c
+++ b/Utilities/cmlibarchive/libarchive/archive_read_support_format_7zip.c
@@ -42,6 +42,10 @@ __FBSDID("$FreeBSD$");
#include <cm3p/zlib.h>
#endif
+#ifdef __clang_analyzer__
+#include <assert.h>
+#endif
+
#include "archive.h"
#include "archive_entry.h"
#include "archive_entry_locale.h"
@@ -757,6 +761,9 @@ archive_read_format_7zip_read_header(struct archive_read *a,
return (ARCHIVE_FATAL);
}
symname = mem;
+ #ifdef __clang_analyzer__
+ assert(buff);
+ #endif
memcpy(symname+symsize, buff, size);
symsize += size;
}
@@ -2500,6 +2507,9 @@ read_Header(struct archive_read *a, struct _7z_header_info *h,
if ((p = header_bytes(a, 1)) == NULL)
return (-1);
ll--;
+ #ifdef __clang_analyzer__
+ (void)*p;
+ #endif
if ((ll & 1) || ll < zip->numFiles * 4)
return (-1);
diff --git a/Utilities/cmlibarchive/libarchive/archive_read_support_format_iso9660.c b/Utilities/cmlibarchive/libarchive/archive_read_support_format_iso9660.c
index 380cbb8..91b9187 100644
--- a/Utilities/cmlibarchive/libarchive/archive_read_support_format_iso9660.c
+++ b/Utilities/cmlibarchive/libarchive/archive_read_support_format_iso9660.c
@@ -3015,6 +3015,7 @@ heap_add_entry(struct archive_read *a, struct heap_queue *heap,
uint64_t file_key, parent_key;
int hole, parent;
+#ifndef __clang_analyzer__ /* It cannot see heap->files remains populated. */
/* Expand our pending files list as necessary. */
if (heap->used >= heap->allocated) {
struct file_info **new_pending_files;
@@ -3042,6 +3043,7 @@ heap_add_entry(struct archive_read *a, struct heap_queue *heap,
heap->files = new_pending_files;
heap->allocated = new_size;
}
+#endif
file_key = file->key = key;
diff --git a/Utilities/cmlibarchive/libarchive/archive_read_support_format_rar.c b/Utilities/cmlibarchive/libarchive/archive_read_support_format_rar.c
index 1c9a057..41d6cb2 100644
--- a/Utilities/cmlibarchive/libarchive/archive_read_support_format_rar.c
+++ b/Utilities/cmlibarchive/libarchive/archive_read_support_format_rar.c
@@ -35,6 +35,8 @@
#include <cm3p/zlib.h> /* crc32 */
#endif
+#include <assert.h>
+
#include "archive.h"
#ifndef HAVE_ZLIB_H
#include "archive_crc32.h"
@@ -3215,6 +3217,7 @@ parse_filter(struct archive_read *a, const uint8_t *bytes, uint16_t length, uint
num = filters->lastfilternum;
prog = filters->progs;
+ assert(num <= numprogs);
for (i = 0; i < num; i++)
prog = prog->next;
if (prog)
@@ -3320,8 +3323,10 @@ create_filter(struct rar_program_code *prog, const uint8_t *globaldata, uint32_t
filter->prog = prog;
filter->globaldatalen = globaldatalen > PROGRAM_SYSTEM_GLOBAL_SIZE ? globaldatalen : PROGRAM_SYSTEM_GLOBAL_SIZE;
filter->globaldata = calloc(1, filter->globaldatalen);
- if (!filter->globaldata)
+ if (!filter->globaldata) {
+ free(filter);
return NULL;
+ }
if (globaldata)
memcpy(filter->globaldata, globaldata, globaldatalen);
if (registers)
diff --git a/Utilities/cmlibarchive/libarchive/archive_read_support_format_rar5.c b/Utilities/cmlibarchive/libarchive/archive_read_support_format_rar5.c
index 548da4e..aa7b861 100644
--- a/Utilities/cmlibarchive/libarchive/archive_read_support_format_rar5.c
+++ b/Utilities/cmlibarchive/libarchive/archive_read_support_format_rar5.c
@@ -388,7 +388,7 @@ static int cdeque_init(struct cdeque* d, int max_capacity_power_of_2) {
return CDE_PARAM;
cdeque_clear(d);
- d->arr = malloc(sizeof(void*) * max_capacity_power_of_2);
+ d->arr = malloc(sizeof(*d->arr) * max_capacity_power_of_2);
return d->arr ? CDE_OK : CDE_ALLOC;
}
@@ -2942,12 +2942,23 @@ static int parse_filter(struct archive_read* ar, const uint8_t* p) {
if(filter_type == FILTER_DELTA) {
int channels;
- if(ARCHIVE_OK != (ret = read_consume_bits(ar, rar, p, 5, &channels)))
+ if(ARCHIVE_OK != (ret = read_consume_bits(ar, rar, p, 5, &channels))) {
+ #ifdef __clang_analyzer__
+ /* Tell clang-analyzer that 'filt' does not leak.
+ add_new_filter passes off ownership. */
+ free(filt);
+ #endif
return ret;
+ }
filt->channels = channels + 1;
}
+ #ifdef __clang_analyzer__
+ /* Tell clang-analyzer that 'filt' does not leak.
+ add_new_filter passes off ownership. */
+ free(filt);
+ #endif
return ARCHIVE_OK;
}
diff --git a/Utilities/cmlibarchive/libarchive/archive_write_set_format_iso9660.c b/Utilities/cmlibarchive/libarchive/archive_write_set_format_iso9660.c
index 3190b46..ebd33c5 100644
--- a/Utilities/cmlibarchive/libarchive/archive_write_set_format_iso9660.c
+++ b/Utilities/cmlibarchive/libarchive/archive_write_set_format_iso9660.c
@@ -50,6 +50,10 @@
#include <cm3p/zlib.h>
#endif
+#ifdef __clang_analyzer__
+#include <assert.h>
+#endif
+
#include "archive.h"
#include "archive_endian.h"
#include "archive_entry.h"
@@ -6626,6 +6630,11 @@ isoent_collect_dirs(struct vdd *vdd, struct isoent *rootent, int depth)
rootent = vdd->rootent;
np = rootent;
do {
+ #ifdef __clang_analyzer__
+ /* Tell clang-analyzer that pathtbl[depth] is in bounds. */
+ assert(depth < vdd->max_depth);
+ #endif
+
/* Register current directory to pathtable. */
path_table_add_entry(&(vdd->pathtbl[depth]), np);
diff --git a/Utilities/cmliblzma/liblzma/common/index.c b/Utilities/cmliblzma/liblzma/common/index.c
index a41e8f3..4c463ec 100644
--- a/Utilities/cmliblzma/liblzma/common/index.c
+++ b/Utilities/cmliblzma/liblzma/common/index.c
@@ -263,6 +263,9 @@ index_tree_append(index_tree *tree, index_tree_node *node)
up = ctz32(tree->count) + 2;
do {
node = node->parent;
+ #ifdef __clang_analyzer__
+ assert(node);
+ #endif
} while (--up > 0);
// Rotate left using node as the rotation root.
diff --git a/Utilities/cmliblzma/liblzma/common/index_encoder.c b/Utilities/cmliblzma/liblzma/common/index_encoder.c
index ac97d0c..5e822cb 100644
--- a/Utilities/cmliblzma/liblzma/common/index_encoder.c
+++ b/Utilities/cmliblzma/liblzma/common/index_encoder.c
@@ -237,12 +237,15 @@ lzma_index_buffer_encode(const lzma_index *i,
// Do the actual encoding. This should never fail, but store
// the original *out_pos just in case.
+#ifndef __clang_analyzer__ // Hide unreachable code from clang-analyzer.
const size_t out_start = *out_pos;
+#endif
lzma_ret ret = index_encode(&coder, NULL, NULL, NULL, 0,
out, out_pos, out_size, LZMA_RUN);
if (ret == LZMA_STREAM_END) {
ret = LZMA_OK;
+#ifndef __clang_analyzer__ // Hide unreachable code from clang-analyzer.
} else {
// We should never get here, but just in case, restore the
// output position and set the error accordingly if something
@@ -250,6 +253,7 @@ lzma_index_buffer_encode(const lzma_index *i,
assert(0);
*out_pos = out_start;
ret = LZMA_PROG_ERROR;
+#endif
}
return ret;
diff --git a/Utilities/cmlibrhash/librhash/hex.c b/Utilities/cmlibrhash/librhash/hex.c
index f0bbf04..cfd5892 100644
--- a/Utilities/cmlibrhash/librhash/hex.c
+++ b/Utilities/cmlibrhash/librhash/hex.c
@@ -110,6 +110,9 @@ size_t rhash_base64_url_encoded_helper(char* dst, const unsigned char* src, size
{
#define B64_CHUNK_SIZE 120
char buffer[164];
+ #ifdef __clang_analyzer__
+ memset(buffer, 0, sizeof(buffer));
+ #endif
assert((BASE64_LENGTH(B64_CHUNK_SIZE) + 4) <= sizeof(buffer));
assert((B64_CHUNK_SIZE % 6) == 0);
if (url_encode) {
diff --git a/Utilities/cmlibuv/src/unix/tty.c b/Utilities/cmlibuv/src/unix/tty.c
index 44fdb9c..d794bd5 100644
--- a/Utilities/cmlibuv/src/unix/tty.c
+++ b/Utilities/cmlibuv/src/unix/tty.c
@@ -354,6 +354,10 @@ uv_handle_type uv_guess_handle(uv_file file) {
socklen_t len;
int type;
+ #ifdef __clang_analyzer__
+ memset(&ss, 0, sizeof(ss));
+ #endif
+
if (file < 0)
return UV_UNKNOWN_HANDLE;
diff --git a/Utilities/cmlibuv/src/unix/udp.c b/Utilities/cmlibuv/src/unix/udp.c
index 4d985b8..83acf13 100644
--- a/Utilities/cmlibuv/src/unix/udp.c
+++ b/Utilities/cmlibuv/src/unix/udp.c
@@ -194,6 +194,12 @@ static int uv__udp_recvmmsg(uv_udp_t* handle, uv_buf_t* buf) {
int flags;
size_t k;
+ #ifdef __clang_analyzer__
+ /* Tell clang-analyzer the array is initialized.
+ The part we use is initialized below. */
+ memset(iov, 0, sizeof(iov));
+ #endif
+
/* prepare structures for recvmmsg */
chunks = buf->len / UV__UDP_DGRAM_MAXSIZE;
if (chunks > ARRAY_SIZE(iov))
diff --git a/Utilities/cmnghttp2/lib/nghttp2_buf.c b/Utilities/cmnghttp2/lib/nghttp2_buf.c
index a328447..ce51251 100644
--- a/Utilities/cmnghttp2/lib/nghttp2_buf.c
+++ b/Utilities/cmnghttp2/lib/nghttp2_buf.c
@@ -26,6 +26,10 @@
#include <stdio.h>
+#ifdef __clang_analyzer__
+#include <assert.h>
+#endif
+
#include "nghttp2_helper.h"
#include "nghttp2_debug.h"
@@ -386,6 +390,10 @@ int nghttp2_bufs_addb(nghttp2_bufs *bufs, uint8_t b) {
return rv;
}
+#ifdef __clang_analyzer__
+ assert(bufs->cur->buf.last);
+#endif
+
*bufs->cur->buf.last++ = b;
return 0;
@@ -399,6 +407,10 @@ int nghttp2_bufs_addb_hold(nghttp2_bufs *bufs, uint8_t b) {
return rv;
}
+#ifdef __clang_analyzer__
+ assert(bufs->cur->buf.last);
+#endif
+
*bufs->cur->buf.last = b;
return 0;
@@ -412,6 +424,10 @@ int nghttp2_bufs_orb(nghttp2_bufs *bufs, uint8_t b) {
return rv;
}
+#ifdef __clang_analyzer__
+ assert(bufs->cur->buf.last);
+#endif
+
*bufs->cur->buf.last++ |= b;
return 0;
diff --git a/Utilities/cmzlib/gzread.c b/Utilities/cmzlib/gzread.c
index 22052dd..e3519e6 100644
--- a/Utilities/cmzlib/gzread.c
+++ b/Utilities/cmzlib/gzread.c
@@ -434,6 +434,12 @@ z_size_t ZEXPORT gzfread(buf, size, nitems, file)
return 0;
}
+#ifdef __clang_analyzer__
+ /* clang-analyzer does not see size==0 through len==0 below. */
+ if (!size)
+ return 0;
+#endif
+
/* read len or fewer bytes to buf, return the number of full items read */
return len ? gz_read(state, buf, len) / size : 0;
}
diff --git a/Utilities/cmzlib/gzwrite.c b/Utilities/cmzlib/gzwrite.c
index a8ffc8f..33f4949 100644
--- a/Utilities/cmzlib/gzwrite.c
+++ b/Utilities/cmzlib/gzwrite.c
@@ -305,6 +305,12 @@ z_size_t ZEXPORT gzfwrite(buf, size, nitems, file)
return 0;
}
+#ifdef __clang_analyzer__
+ /* clang-analyzer does not see size==0 through len==0 below. */
+ if (!size)
+ return 0;
+#endif
+
/* write len bytes to buf, return the number of full items written */
return len ? gz_write(state, buf, len) / size : 0;
}
diff --git a/Utilities/cmzstd/lib/common/bitstream.h b/Utilities/cmzstd/lib/common/bitstream.h
index 2e5a933..136a188 100644
--- a/Utilities/cmzstd/lib/common/bitstream.h
+++ b/Utilities/cmzstd/lib/common/bitstream.h
@@ -14,6 +14,8 @@
#ifndef BITSTREAM_H_MODULE
#define BITSTREAM_H_MODULE
+#include <assert.h>
+
#if defined (__cplusplus)
extern "C" {
#endif
diff --git a/Utilities/cmzstd/lib/compress/fse_compress.c b/Utilities/cmzstd/lib/compress/fse_compress.c
index b4297ec..1b6a076 100644
--- a/Utilities/cmzstd/lib/compress/fse_compress.c
+++ b/Utilities/cmzstd/lib/compress/fse_compress.c
@@ -646,6 +646,10 @@ size_t FSE_compress_wksp (void* dst, size_t dstSize, const void* src, size_t src
void* scratchBuffer = (void*)(CTable + CTableSize);
size_t const scratchBufferSize = wkspSize - (CTableSize * sizeof(FSE_CTable));
+#ifdef __clang_analyzer__
+ memset(norm, 0, sizeof(norm));
+#endif
+
/* init conditions */
if (wkspSize < FSE_COMPRESS_WKSP_SIZE_U32(tableLog, maxSymbolValue)) return ERROR(tableLog_tooLarge);
if (srcSize <= 1) return 0; /* Not compressible */
diff --git a/Utilities/cmzstd/lib/dictBuilder/divsufsort.c b/Utilities/cmzstd/lib/dictBuilder/divsufsort.c
index a2870fb..8d52b18 100644
--- a/Utilities/cmzstd/lib/dictBuilder/divsufsort.c
+++ b/Utilities/cmzstd/lib/dictBuilder/divsufsort.c
@@ -40,6 +40,10 @@
#include <stdio.h>
#include <stdlib.h>
+#ifdef __clang_analyzer__
+#include <string.h>
+#endif
+
#include "divsufsort.h"
/*- Constants -*/
@@ -1119,6 +1123,9 @@ tr_copy(int *ISA, const int *SA,
v = b - SA - 1;
for(c = first, d = a - 1; c <= d; ++c) {
+ #ifdef __clang_analyzer__
+ assert(c);
+ #endif
if((0 <= (s = *c - depth)) && (ISA[s] == v)) {
*++d = s;
ISA[s] = d - SA;
@@ -1184,6 +1191,10 @@ tr_introsort(int *ISA, const int *ISAd,
int limit, next;
int ssize, trlink = -1;
+ #ifdef __clang_analyzer__
+ memset(stack, 0, sizeof(stack));
+ #endif
+
for(ssize = 0, limit = tr_ilg(last - first);;) {
if(limit < 0) {
diff --git a/bootstrap b/bootstrap
index a056edf..109e450 100755
--- a/bootstrap
+++ b/bootstrap
@@ -80,6 +80,7 @@ cmake_init_file=""
cmake_bootstrap_system_libs=""
cmake_bootstrap_qt_gui=""
cmake_bootstrap_qt_qmake=""
+cmake_bootstrap_debugger=""
cmake_sphinx_info=""
cmake_sphinx_man=""
cmake_sphinx_html=""
@@ -697,6 +698,9 @@ Configuration:
--no-qt-gui do not build the Qt-based GUI (default)
--qt-qmake=<qmake> use <qmake> as the qmake executable to find Qt
+ --debugger enable debugger support (default if supported)
+ --no-debugger disable debugger support
+
--sphinx-info build Info manual with Sphinx
--sphinx-man build man pages with Sphinx
--sphinx-html build html help with Sphinx
@@ -962,6 +966,8 @@ while test $# != 0; do
--qt-gui) cmake_bootstrap_qt_gui="1" ;;
--no-qt-gui) cmake_bootstrap_qt_gui="0" ;;
--qt-qmake=*) cmake_bootstrap_qt_qmake=`cmake_arg "$1"` ;;
+ --debugger) cmake_bootstrap_debugger="1" ;;
+ --no-debugger) cmake_bootstrap_debugger="0" ;;
--sphinx-info) cmake_sphinx_info="1" ;;
--sphinx-man) cmake_sphinx_man="1" ;;
--sphinx-html) cmake_sphinx_html="1" ;;
@@ -1987,6 +1993,11 @@ if test "x${cmake_bootstrap_qt_qmake}" != "x"; then
set (QT_QMAKE_EXECUTABLE "'"${cmake_bootstrap_qt_qmake}"'" CACHE FILEPATH "Location of Qt qmake" FORCE)
' >> "${cmake_bootstrap_dir}/InitialCacheFlags.cmake"
fi
+if test "x${cmake_bootstrap_debugger}" != "x"; then
+ echo '
+set (CMake_ENABLE_DEBUGGER '"${cmake_bootstrap_debugger}"' CACHE BOOL "Enable CMake debugger support" FORCE)
+' >> "${cmake_bootstrap_dir}/InitialCacheFlags.cmake"
+fi
if test "x${cmake_sphinx_info}" != "x"; then
echo '
set (SPHINX_INFO "'"${cmake_sphinx_info}"'" CACHE BOOL "Build Info manual with Sphinx" FORCE)
7@}้yc][2b8 0=G3O;TI]Z#ԴPҪV% ZKm#"m՚2 jѦC^'evƶ@(9W(r`JC k4xt..KCl y' EQ4Nr-U쒯P5:R;bV|C1p`; #Cg%yriyjPPtNzCԌU32JX A!@h[jBBV@J-K 'xN_7>o5iݳ yG$ 4JI~(AO ;x?iVunOA('$ ~`0ėC*1NlMaD%Vb&%zY1ha}r~QBxjqȕ&);C-:#83CډԀ04%*!]SJ%M R($"J#d`6|:}f"C  (Rzub᫚4r`߸>c 1MJ uj?{bs㻙<^8?{Fͤe4 P Xlr׫7E]>j 37_0l;|9{0;kaaHԅg)Ҩ~꽥9҂9Xu*յ0n2P%1PRҢB E55(UK h(xxxc"xas1=AE9E Z>w9j"M+ɝ}$8Aٿ=ᫌ*d K^C^P`{y($F*U-VoνU'KZH LúC[nOwy<W5揳&/ XF(- )]]@iQ-*1 ZtFBڅ1H@WTZBbXҵ #'"DWDbd2DH6ŴTX*BŨ5hƱDjFыZThZjEh,kMMFQlcbE&1EQŤ*ɂh؉ #Q%m i4(IĆ+$ Fa% -((fUQFEFjM+"ƠXETY(ThZƍ-!Q db1clbmE65QmcAcEFFض1Y6*ɪMjME0ehiъ14lMQƣj#IFIck&bرV(6j-ɩ(Ţ4hфFU J%*4B%!K@RJ*@*4 cZhѭEUЪ 4 H% PH*R HVƵ6Tm+JJ P (R#H (ljFbjDhhU ()JRBJAiF @)TBUJi(hQ(DPZjmcTQZ65UlVkmѢ Z D@)D((UPh DJ)[ڱTmZ*-TZ-mUJTiZTZ E(DJ)T)P(A )@Pi%T(b T RbATiFVhZhTiTJEV)DiP D(PJQBBZRkh-JV D(T Vh U)BQmQVmFQ*@RJR- AH(P RRJ+T" @(*  "P"%HP RP"J҅ +I)@ +J)@"*JE4@R)B "4ЭլUQ-X6ŲDR  `h(6+dj+jѬmh,[QVhJTD(FXFVֶت +T"J*҈R("-- H- "4P (P!H@CQV6b[QZ 4!J " Amlh+Q(ZA(ThZPQh*Q dMelLypA-}>"P@"*%@(PE%}EUT*@$ {zjeT(RD TQQ(R@*lU[FRD5FJ( "FRU"(QJJhh)R"Ѷ)"jET hQFI4eU*aJ&lwݘ O=}qGoN|A}y#}/͎ix*TZRZ*A %lm4MiJ0֒IAHE+lUPThD5*%&f2+YQ5`ZPQ"Til2֔ Z@c!Zj*٠P&%JP&ڨBmT%Kkhm `*TRR@jU)H)J(>GTUf6m|}}f4U5mi{Zam}*Hl{p}q=}rvWsC>jv :w/][jZͤSl1ڴ.Kim@7{qan^1<]|CT0l{KUHIJ+dރzGVDقRPvwty+lY<Y$Ty$1$U&ڕfdf}Ϡ>NyPo rG]+6ۇʆR`%R@R퍰٠PZ 6LՖva꾹>Gw޸=^`'=|ҏԺ8P%l3ʰj(kh44Hb*m\>τ>*7#}78F=Qk9[@hTfxd-#*fwk,9 =5;Շ#` zDŽ;bxf"^|/5YjԔ(X2-tv܎sϱ5y}'x{|/=T_, EF)(۸wzeJU iJ[-a-lحݭ9'ZSm=O8Ol}x}﷧}>>>ϧC>}W`T* " O@J?&"R@5OA5J%)=T6QS$*<ũk,?"̑d".@e.\2b,&ز Պg7VUΤv35nFRMDnV̢i-iV1K5Znvs-2L>CF >}j0l5blZ,S,M)PFե2ʰaȾUD*C1__TMV4jXYY W{|>%e_բahCUbҲh45b4Z_}+j )Ń4ML%% >TƪɈid&CR-KKCUKUb2>2ijbj242bdi}>V+IFLYZX45}C+&F,ZaC+S> Xh&44+KVSLeeL5Z1k#FV-25FLXYZ5Yhf&Z̭}>dk+2c+b֫Z5]v3TmZŲ3U3RS_ ŭ#ZMS,VɬjiX5]RmFѭض5vsRmj-EEZ-E-lJl>e&ʏ|Dڙo}})FjRؖdMmSe6Fi6Fɚdm T%XXwlkrI͹j6\X-K^mkQW1b1r0Gm#4Y1Tۤ™6rm՜lo$fړd-hO*,liFFحk XcjѱEQFmc%TFŠV5DIcDRjJfZm\F0I\憡˲gwW.Fn]wq6-rqvmݺ Iu'rj;97w]λ]u{Ā$ff\ۻ;^FhvNsQrQu=yhnfW9fӻ\sn]nc%. a\\.7Fyzz\]-w\ۜ,1kD0R l`tsۍzipwrwcwJȹ\@TV!3qxU繰hͣb krys!W5r[*刷- wQ˭b*2j7+kͻd5\] rnBJ7McG7ۜRh˺vʽ.ti]+rJ6=.ZCNu&9&i˲\ \훪 뻼zvAl¹vQD5sq۔r;+%ʻuE%n6)9k$bE)stE= r#!mt7uw\ym6܍N5 &ۼT=rrc͍5rܣ&"6湮^]{ܨ5wEH5ۑ ݳ- LI" uW4F˵cQDlZ5p Z( ZzhRr0b(eʸ̑u&ɗv1ahK"ek40F=oԘQ%btK2bء+yhEdRbbJClW5&b7|> IX37MV#b40jM;XIK6lVB5QFE-v+dؠ&2`XY,QF.h۪yzcM,!EEbR[N)(z{Ո1a15 IQ+Z同޽ IXmXI+\j.ң{Ȥ,&J( X)AF ռTQ&k0Z*r[ةhgR 7kE) جj4djH6D{y"I&@Q`bHZ+{OvŐzѲi-I ˆfTHckF&#";{RllHFɒcRch"UF!&6,!mbX dQԄ3nѢMvmDfb5l hTAF)2I\BѣQbui LZZ 4QQh(ԘTPU l&Dm fRl-$"hE#Zr&[͈4-mKfZ,f+EQN#%ۚ&hcLlm1rm&6HҎ0Z(L3EDjE ܒ6&IQX>z|h5W$V(ܺEb h ThтkN(+ H$5b CIk棫I᤬!mFc,`EdɊ1RDY(1LlF޷I bZSY4Im4BlE&H%#F6(1Rm Qh1bڙXjFQ0Q]lbTȓnۘ@ urb4QF**C1Q-E7TIEE@@mPQF(!ib 5&f$)hm&1Fcj I/j,TɨH^PE&ؑ 2E 51"*4h D^t6lh"EV 5,h ĕAEܴhBgQ Q5 Ơ&Ʌ,WUQ +Eh؍ E$U3J$urBQQ6ō$S.h!K0`cIQŤ`ۭ4L#IE1h$kcJU< 4)FIli lł1L-ME2 -->EmI Lh*:J1I`6I"km [uX`$Z4`خjd.[Xۙ7уH(ش+%obX\() 1b#E-1 FKF1Q5Ff F6*&W$f綼XԅZKLѺHZ4l4UEub$IPjcllAhm$$S&j(hEh,k#55zAAhI(5Z1rIQI: FJLQEh*#F6[]h"6"FDXHa d5Z܈TX+ -6jE$JtAQh+$XѨЖ1[Y64dPѤ#2hޭа$Y5EۖѶLU Al-ծ  ;֚V6"5-,b1&QXBI!ѬQFҔEHTh;[(1h0Xkemm>[2AIF$TV;UQ [r1),FIQIPieܔ LU&6 ML5EY*,3cdJ"hchJub-dJ'Qڍ0 &؊-EXL)F] b"miLlRvOvd׵r6$3j撲lPPۚ*(iY4hb& Y2h"6ɘ114-+um14mvj bD@#|j4EI%E$+QX+rJ)5$M2v%IEEF$ 6XZEmڹTbdcI p5捚cbBbJShH Fĉ],b#QP{U)F*ε D:&bd(#IIA6#ʉ"Q̵-&"JnQ2[cT$-kb6-H2Fo2lQ"b F(]6Ah5S #^ּ$#"تLlE5%)kDFu阬2Mb ĬFY GnZ$4XI޷#E1&+6dɌWE #$*6$5E!F"4SEH2Wk3Rj4hFTFr,Ih7o45&0LQA4oj(KFE܊"BXH͓FDXDlcFչHYK DuW*id4h+&&VY(#hC%Jj dɢB6]zTEL{]62`S2bݭAh5$TuQ`4`v1M-4b]m&McE&(7W*#QdEj`# ۵DF4hu5%DTyi22 FĚ/jQcFzF#L2щZ `1ջ) 4XuI%J 'QI"1M/mv4X z{Z)"Fב#Tib1]#`ڒ;W 1Dvېk&I ܢ4& cIRE*,[]M4jF+unPh{Mw,hH,V Al&&F2łksA lbFغI"AѦWj%0E]3Hѓmֽ((-z6Ahgm^f1X7ْb,i 5.1E2QۖMIb(vQ&ƤLq4 -꫘Al#cw*"C֮lEHk#Raur`1IY1uF4F-ݶѱmH)*12g+K0okp-"A@;DF1(]TRTR)Qni blM&ѢF[&[6,UI6]RLE6;jEbILKmӫB%kI4VKk!A"̎lVhJ 6\lTn4QE3nljMܢI*dR\1L[EkMR! XŤ(MSڢMbu) $c\&6"`4]t$Fm MdK#vQnJQ616vRIEi4LծPM-iۑuF HZKvۑn`ɴY1Qu\(bLŃaJfk{^2JK$$Qz͝XcF,QNfUUpi 1AF:TI 1n6ZdRlFNlD]"L&Ě QEk4-&ɺ#n-T]٣"ָHi64m&%]#F"b#7X6)niI,)0Q-%b&7hgkH b(1Xs[t1F",nss\F1I":LYQ#QL6.mddXNܬYֱ2Tc(Q$HTcniDfE%FQ֤ BQA(MڹEu BF4EK5hI;DFtب1,ĊĚH'h ƍ]DfX,lWkncFEE.ֺFыSt^')2ƞHi4%-(*1Bm)XN\IL-kj-AAT'nYդ&llHQ&m;]rLɧEW$hhcnN-iƨ]sbhz(HGjѨMծd,fF,4)GVERj1w4VbB$Zi[纈3*,J(W\,F64hZV4b&TV"2u6ƦOc$H uh(6,;iĨl+]2vlF:ֺFQbĆD')ծh*6Hlkۺ(1%ޛIPXOGV鍒(6R]`LQlYuM&FY-1,SSc@FcmjJ5vV3crFLNzBh,cLOk gNSF,cxFcH-hĆeonvh BX*" ZL0ʌe,KFN[ E"gSUȣHQjA&#@TFNʄ/]6 nk-0,n[EMD({FGnXAnEIUt 5={nE4In]A 2v(ō A.lnEJHAzo4lMy ňhݭ䁑 3b"hlhcIQ,bFفm٘"hꔰZ1IhԄd0Fkb,D(DFL[b 6b4!ӪbŠQhƈB@]6FU(`1!QF \XɶJCC(CD lh)%ED2bCbki[be6M[X,T$ѩwUҍFKchZ cX6MQQKrFls] #@hƈT-h+)llPXѤe$Ěɴ%*!"4m@QEnłh]Y Ei-FlTQ5fѲcQR.]si,fL1`F*aBc`Ei%>v{ ؐ PRl0FKDb]w|sIllRb*)#AF`M'uShJQQEDEcS*dQwh-ϗm F!4QVFMbuzQ2آ IIPQ2FK]r;\6#Qh4w]0بŠF-F뭂(|\؈K3RI"-ң$Q"K(&h6dɮ*(cRQc%F"(5 E, cA ںTūDESF-5DkӖ1*)4j65*,\yvh$(j ۜkb޸ut*4EccihF3W3ӋjcF؍%5P&̴E.I2],r&84bF(dW{[,V0`he띮XQ4F5 ݒ nY75ʍm 宆hhF\5(Qb "i $]NMS1Kݮh\j o[QZK IRV4F6FT_>\`X:Y10cM@yFu\5%dEF7S6Mc`Dh>wkm:f4HW+W"Bj1\ŰX] F4ca-G7]\1ddW"؍\q&jM^rdRkח1i,^Dl6E1=V5չBgή9WI1ț, XM&5ӺylW.m ;+r7 ǻƮڊ1r1\V9sQ+ۑ;rX]-s^L")4l[[^cQdv {3$Ƌ鬔,Mڹdł0"TM1^`ȉWnWwlm |o|pI1s\Wf˹h{E/sqhƹAҹ%hנ[tEyWwW+IRT=1!Q/71\;;7]֒ەwtF] i^ scQ\مgvrr^wvH7N'.vw;su]݊nzsxnrqҝ\.r\\w;uݺ5ˎ΋WWvJL\s3;nǷ\^\\پi& vqݑ:vNSwF滺ܝ:w]tgn8Tr泻Rm˖4I˲w]34d7MPKwtwpG\;e݇Et'nT뎤nw7]ۧ;2\ng!ݙsvN봗4wP5u^ך#cFwVFnsQ&h6 PFj#h%L`˫IFűEE1TbfDjM+ݺ @6"4k2#IcVB 4X!Qj,[,bB*+%Hƌ[cQʘiA5FD cTF(*fKXKm6bɌDbb*B&jFfMAb$TX5lXɦ[Dc$VTdF5j,V$165+ (1LRiFb J2H@&#JXI%LZ6" ƤITERlj61n{#Q&D- i5+d&0b"2U &lQdT5h3\h(QchQIfmXh jK6ܹI`̱$P,Fb $FZ 4Eܱ TMc#l#DX(ű&EE65PF,b6( $҆F6FV5&0lPPW^ci5œRcY6-$R1т-ŋhL1*iXE ѨRTcT!4X7F"ErR!ĕcX0TlZ#dRXɍiLMJ#QZ-ŹnJ$زFM,FZdFj#lFZ*64͓bH]-\4Xh-%F؋AFɪDX1$EZ((4m+MEIƍ khĐQF 1LōhZ06,d&uF"F,bţɢ$(PVŌQ́c&1F12h$i)#Z*M3EFVs\MYF,FQؤ F(XIXXƱi*Fb5!chPFԑlm2  ,cEeclclF*0DFME(Tl+%dэF1+PQ&Ʌ4LL-ƱF66"Ѭj5r4#d( AEKF$J%-&MA bc&)60cRlbLL6HH1Q"m6KF6fF j1MjJ`HU)"Q]3-5&Ti(؊,5bCX" *#Xh)%DL-‣)+&FEљ1S(MX1 6*QlRXV65RbEF\TFYm% QM&B(+j6,m514XFU%cFTrܲQ&5cQQlS6+&f 6Y RDUlQPF Q%V#c"3hcIKX)K%XŃhb5$Qbf*-lXQj0)cdhR$$PL!Mc X"j@bƊzZ6)"F)(M6i,@b ȑmHшb $Q#cDTd*Meb$؈ѴQ!Q((#h#Tkj( X62!X(EF0PFm "cIi-$"(6(5(QlE[4$XƈLFI!d*#lQFl 2$i4jLъ#W!5U 4[$J"Y104cQRhIIfj5IFj*D%,%nbBDQ 5`Li &4%24#2HLݔmѱ4j!b5(%I) i4HhYƆi6Ɖ#EF21k6 4XdmbMC b6(эlPX([F(bDFKd5ie4j)EBPhb5!c%F**ɋ̩ѴkfōQh1IQIFD`j$clEa ؍ IS*,cFBHƊ1iKFhIֺEbHFY1d4ѨEh#J +%Ѣ,Vdf6BF Fν{k%$l"X2hTQaCj4m5l[hIsh1 FTZB(2cDRIa-Fh* "%3#dƒ%cbɢ5(dF6Z,RQTZb5%ъŒFƊ AQ$0"LEPAf3FUTTl$KIZY$5h$63()51*ȉEԦ6J63jɍ-FKclL@ʢ Z `Jih 4XƢ5ы؈`"bIX1EQ Zb0S6RlQFfѲHb Dزh-)4DDIH45BnFъC65[dXkѢ,XH[4THVM#cZKyzR6 $Fؤ=."#DE+26,h(1c&& #b̬QDb)(ƣlaEb1`hi*,b EI4`ŀԖ"1ƒAD!hb5d1lh[E-Q#AQ5&%ڸjLXŢ$dLSlP`lm4Hm$RFƦ3Xi*5kI$̣PPi4cTjJLXɨIhh%X3b61 E;hmFLh(*hQ JLhBV ƋFBJ#Q#h$(زF&Q@%Q%m"D*`b̍64lA%b,Qi#Qh4AX$4PX4Flj+E(&!"h4ILu{UȤLbd0e0+QF*$Ѣ&&mF؍!&ٔѢHldd6I&A4lXDH,#6 m0E*)M(EF5Vуa @-(بƋb$رXQ16I(,LouI,T6Hh6j$1 HE4h6))-$V5""EQQDXK6"Q%&b(,&S) bѨdƱ2@$jHcb1bH4kIb*4đٛcEHhŲVBTRb*-4h F\Y52ѱ4j)&1PAl&Ŧ(!TX(11"KE4&X 6mc%E&Tc hTR PljD,FdcFQI*4Xm6%PdShbA4QQ0&"Ѩ1X]PdQwm#((`\rwEɌ׫W'GWpw5˷a]&K+;N]]gT$UU $DcR4MZPfb5RlʓU&эbDMZ5b66TV6[BMblسV6m Aڡ6 d b6SiPքٲPlڭқI6AmUlf2[$)U[-l&-X(Qȶ#j6mlmShUlV¶-6mbFjͫjYF&-6lAJmmI6 eTdȭڍMjKj!CZ6"lUتؙmF[ 5kBm+Z-5 4VKjmU6J6!mImmKj [3 jb3%fQj-F(1hV6a6ƴU&Z5mm[B6fVe6m-jb֕m-I QMYڪ[ڢk b[ڕ+b6m+elU[ 6V["mPAFlh-[Th#h[*4aVh 66MR6Kj+e&­+bT66حjح& ŲV[S1FѰ2AS5mA&&1Y+FZkZKE6IEfхIQ5AYEf1lMC5 ղKX-5L[ 4VҚҙږ6(mSi3%mCbV6XҚVcmmŪ5ZZa-lU+djQ,M3T*Uk-[%ԍjm&lQ*̆i[%3E̦[T-Fi6kk2ѬmIj66QMk6ثT&ѭ3bj*6ѵiK-b*6Q$ڡMQRڶVhљ*mH6,͵FTjMdl-̬ڱkFmlmV,Z66+U5FEFj Qm,-DTS5m%IT)bZMJIXڣj+K%--FZlj5I65%h̊,j*m,Ih2Xlkcd4VVM%E!Qƒ1e33[i ɓF̵i $գHiFTf[m2iHK3)iL+Z6f,fJQ3h , Xfͣ%i&֣*2[BQJLm3a2iif52(Փ$TUAEFi50IVDD6 &31mh&3eқ 4(RdQD6"b)3bQ2662E&0mYRF 4Z3!dYJV%`S2%&FIHMP 3KF(fŒ$3I&&3XLEդlihjfŕji,b)Uih6aRЩ%6*$imRfffm*%d"JM#IJM**bB+m1JQfZiMMRU[M#E$cf &Zb02bZ&e$2mZlIJE,hM[5Ռjece%I1-m,4i,bllbmfLŲmVS4EcV+fkF5F6XZZTbQ[iEQQTm SFM)-- k3iU,TE%#c[m#Q*2k62V4bьR2cIEIiZ-m#hЕ%&Ѷ5f ZbQV5m5[E[MԚHmIQmeb))*զ[cIAdi6mTѴXf-Z&Յ5ŶZ6KE!D IJ(ѱFm،ij*52ѥJjlBccbh[l65VEƍ6 -XBVhj4ڨPDQVAXMMj6ViMjdm0l6Yԭ `ci3)[a Yhk%DYS#mKUQQlֳmEFKjѩVȉYS ,6mfVɥkE"*ʍjl3M)6iY V6Cd%bSRdQ6IMj6jm#Ue IY6Uj-Fd1mCE`0[IjV5+EeMP4CIdFhL#(X-#1LU0ؙ&C$ҰM% X)hUZ+TVDʰ&&5&U,h1&ʫRh-&Rbj)dMJU-I0#HY-eHiUhēJLFTm,i# @cdeQ,lV`Җ-XmSJL (-S4fY) J,VbM)fم0e&i2VD+TVKTZM%5ZD6Сd *bRS+R4UaM+A6fV5K @b,Uj5C+Ij#R-*bj`VEjZMUajV ԲFTiMJj4dC+R5X&Zm Q42Rkc VLJa0dLj&)5,i&m,dBe5+CI5-™X+ELL(*a-V1`MK#Aae0#I5L+dԫ[KJ11ԲUVMKS+CF,dZ&M&ji512ڭ66 &L٦ZZSk5KVMƩ E[Lflecbڲ+d)EɱjeeKjF6UTڭ2I[I[F-mbJj³)mh[+eKdګjmBڣi!khf666&b,e `m&Mlam%hl6j[TM#d5j blb2E-*l6TFm*mY4 ꢈ'{_^7WŸw C{a#L ^֙#hikKnkx&`"~kCM?L-܌< ji0V>'B$?NV dmFkD\nlr2kwQ~gG`!i +!H+J5Q mJGFkfΎ0䛭My)̚yL{@5G`99PM lCmE(a|plW7r$.9,~p|iu|)t r8R:9G;AUdS,7Hae' Qa)p6V's>5yR2 Yc=hHD:ç)xq' Î;Y3>qIwPzQ̺c>Lb[-`ϱD'K1XZ,j>ຄ+[yd!bLM!39E\YsJGT aQQ9Bφk\nPrSw$ՃqS&}z/Y_E5DW͑hVTQVR~V Ϙg:ܘmfF`oc;0dP2q.CH/ZysHDgۃ$jC 3va=Te<ݏ [[,ڑpcdcf5y|p"I1| ^x}D2d(yq!ZƔ$?Wί8Ujq2TٳLrg&ev,J)Vd$!WM0;!jHwe!o;8浅H7.ŷ@΄9hok}FVhD 8E *ne!t]#F|'E;PC/8[vKTHd@[hcX:j\r ^B\-ULuEKh4)i?vpA}S셒 v@>w$E$Jy@d 'JI ] v1HNtj3] %t L]qˣ-rsqN:Glxɗ#:>N]}\;s8{}}89xe'qu+P8.+P3]Odžouʊ8q9M[6jFȶ?VunJ^^=,tn)=n479X}2aU9麬}h]1g";Rx&2;I{$`5,uٱ|'4t`wZޥ9:MUWH˼XTbHd]bdT<֊mSnݓzkvb;jÏUKonYRֲL y[뙙 쾱] |3:pfm)VL1NwZ~&W|DML6x[2<HN 'Kׇ8 8t";Iɷ;4J] <'-Lr˨_{\:YNZIv3/ %α^rGeC3(|i"n ZmlZkeSsU#\wǥ)aXnR5ci?5Fq9^Cҽ{Ӧ 1sit=Fz1W˪nl\ۜ/F@B#u4_P(pM兛&C[fxG*˸!*EY𰄼(νZIÒ"/yULn̔2ŶທvyrQy8Ѥ"`UFaBQLklpnSւY iƘp|w.!_@?d3Ήf@J#t,|Avx",5\oYA| J TCsyԛ6y@ݞn">k sU6f삥XP+.W\x]6ي곚c9ח:;Gs >;A05o@gfݐgr05ټk,Ѝf /.ҩ`tmRB:o]X滃4#7s=L93D]SưUShY,S!`"Д珼~Su9)hޜOU靋]OWwVCGN{O q9PBlSjXj* ieΘ+Dn=M^e'7ܣڢQzsޞ*s]qe9L{UOU҄{[\#6FECB{ez ]ɟ {5c.4^d>=IW<ʻhyePT"s: wy=&A<mh>z)рgo5: O᧏Tf#ouG3ׅ b:NnaIUl8Fz)WIQM,RbոVqnt;قmw]WJ-˝ RA*=GH5j>}h e\r[zanLv ]+s5ڹIw,G -'j:Te׀=zUysr3c*0wwEL$.9;%g6ߐG[B\ϱ/p\-T4Wxgy龯{=,,MkB: 2( s}c3זqiw\+O9(g{: {ǴvwaIf9MyWqwqb kΏk9sϴ4g ,,u7"܊`[-=rHN,5lg"_ƲY;ޭkUJ8'T ܫ\HRS3TT)) S8vHu-}pN|w|6fԓgsqmW9(`E`dii^0EQKҦص.4BrSY~mίUb[݈QB0oEq4}nȖF"pDb6 ,2fSP6 k{jJ_%ݐbdB Q́,кrfZ/'^)ѭ<_J6S/uK'E%̾(u˘2C]u0tw.xW}E#k=d"fp= ٢E;\Á{jjN]}zAئqJέ(,M=ZvƍMHXlj=ź}l.}\7iB,B$2vINWpp̴d+t&*T6>]z ޺{-v2mOOJ:R3|zgGxOTq򇄵c5+s^]pG3BMK:ycC$fӮZmk͒j:M/p.Y[+nc|M4`~S|}Mw^*g丌MXsM> a7kKʙ5$9s%2w.I79nFUs'sYyݐSeI;Kl嬒~FgpʷN^e'LեqvxUYݡ;[| c7/jF:52Ճ=eix!;^rsmw`c;|8Op*z.T qѶJy3&go~(Uݩp5۔Ku6MX/.7bgE4uWv+SvM{wWLnC_=mKљٞW/O 𣏕)4XS= #c馏1CsUj4F(=ދtS-+ lxSǸl5X>.6uj˻j(QXɂm3eGx;q*!vCwu[Ӽc6=qMHi%W]nw%]@;xhhXigln9~hظ{ŸN횋(aK;wE2y8難+ۥpȲڳt"Viɲ }{clrL7_l/neES|S֝ܕ׍p69F>'b< \*ݢ뷟#~3rΛIs6U-OHUmhv'm5bL)Dr; ܧ,׺Fr}z\<̎)**QJFT9TwˏPK:쾸׏.U7]p\&Œ(M>'dOJIh^gCN繐hKjtGD._gEz;ڙ-noc»E W`'h36[z.GJ깛Ukm]Æ+-VzBY ʫoRW mtc+ ݳ, 0㖷ۛtm}GC푕:t A|-36tu8OFL/1wih9YjS}};y~=\kwxza5L5w^=aDM;yl 5|&]z F-WXz_Zb8m{tm3b{ ,ٖRј]靓nGqrzhGIFFX xnsz+Gnح GREۯ 8WfvBgWfcS;Xʃr+/X/-,'uf5򺙦>|e'Vjzɲh0U,]9VaQSվ]: ּu de7-DqWժ j!:񹓒sBTR\/<;օ5VbZ右oʠk܎aWR ;6օCi/0KZ5&76NŻX'7p1pT!7k=wzY4\<jl.˳w]Ty ϳ;I2XcNl3v4ڹ'Kw`,`5==wqn Oj]|qrYrL&ݚ{hOn-1e1\iXvɳ n3V^?ZtffNrחw.\׉tl-:yL5:f+^X^KZK7; dW5*nRi;Ip7I꾧oW}eXWNژ(ʚ.8E[6T9KAY/V:^Pijʩي74P;Lvw&/Rӽ;WgautT::$ba"L]$t2^]EW:7i诶h7byf9(%CYFUHrSG'tNՕnJ Xxgjƍ J.dzcA<6vY/%Gڂޚrn߫t+jv'grNMۇx꽹AdYA7an\5;Yͪx/=zs|˽o6۔*Z*`k04 I::PlXnΝ#ٞ|Ϩ)բq}mOB@o}8e>/7A\'Yr659^`U>TUq "YmjJΖrGi<) Y2QF.9a1"}CU)LlQyw (L]䗳kE zz‘ەDeid܉P0+$>Y;ea2rH[Y7k x疲7h&\'cˡ9wt!Oϲ> })Uևab巷ԅ{|sʝ&̬^nueX=+6&Tۘ}5Ef[YXnZzIҥsK#F]VSŽtj~a}:5 F K\՝*WsvvRxUyt΅o&m|^׃sr7f nq+շe7ؓT\b*{{wn)'&i ىljX6Աlӹts7徬RTT9΁^Muxu.XK @wk,on2u3w{]9Et5AJh1+كv {kT>Ul[Y g2nh/R;jnm|eSz3Ousraԑ&t՛ ) vxp4vIr+&;E^K o+J&dO=w <5&z5]ui9|u;›1%;$`sՊa8[ 9Te]CzNߞI|+k2?L| bx6ALj}xԧ"\^Yᆧ2^u+R~OjnÎHoeD F  z!}XzsnzK0ޞWzA.wK9Z9쾩\k ^No&]gnvy9D @ ?7y{ġUΔ|rϣZ_szVUoMPG֓K(_\={0>FҲkMX}e.l;92l}di_)r#d:6)IUq%m_(vh {]NIyjMABaГ @3۽8 3 N|L/2Hor#A}I,PPw"_}r  n2wzWkzߞkp3p\Mg7T:^u{G 4> ROK5ՠDVQp=moiطVRPz͟#!| hamYÇ FzMzw|HY8lq}Vhe'mEݟST֤c'TX̱|$#!QyVVUrU8gd%!]DZyCYkZ@=fQT"WL#Xۻ%m=ϓoJbp+(}m?UG҇|N,m{`a[XJ# F.Wil)ۘ7BTylp[SrCfNGmGbǵd&I!#ZE:UqS_4,Cfq zxc

5o_Mz};Kf3VMb 4"Vx}aQU༂$ܠCC!DʝK;UMYgS (bbbMɘUnKvqwސ/ĕx-0G!AQJ:|`d=a򷘋Y#u)/7=sVdF*j6@jȓÑ9$9Q,@OEI;EGKlW}wUS:k~XIHG¾IHN5ߐciﯟGWGCw^eè3箎}|rwa,nNN[8sGKs.|<=0~>rm6*XOiRIw]v F-qH3 oFu G\>7N㰷0b .BG_u*pY|R4`fU:Î0br3ii=froYÿ5P=!Hp vT*deKQ;S,S6EO@> Ib~9[~OʜD1a2}|pt\N:^G\=u]\9zϯ\9:'aC$Q*>e&OKV? ^w9vl뫬2ĵ[kxk`ZIמ]zχӶ'9kWWsӏמ:;N\?SK_~9}  dEG:@R|ΛK?Z,l yA4@:Qa,+T$< T כLzF7jۅDfɬnRv{Ҭ)g+ wcm.iϽ*?O>#PF췗^)c~.HU߬_j5\@ H/!REkTUHDTG!ժHsFbhjۆ9 ޻׫yU.}6N^yz:\{]:Ξ^^NkxǞ^0٨ קvPtD;؀\+T9Vd;%Dgr t2فa:E\ǘdBІ `E8x+ɲJ77^ssn]˦2H8.W]]=I{I3%wݯ'$ :>*H.~_/:m_]վ]߷4ɟΜ*~>ʪSĝs].N\:zGW]];yˮz:{\s멂IV[t) ☇7A^^pCk !5(D0wcq8mD18eMªQ~vT@ ^ ~ FH4Tu!mo$ŶU*H%HH-9si MjfvYmP%MrWvp>σy !Cd}Oom_./{**/م xfGthhﳗ/sW>jwsΎ;˾ӧ:w]ˇ8r뛹WG}i˗۹N\s8qˎ)e5N&ǧ=z*"KǷ; \ :i:PnBǪa=$ sßc)>*fAjL@!?U*RyC_IOizk@]h!Xߑmw[a:͹-iHd_T>%=A5s oE~.Z/Tr_n*2`&&c8aNwwu:9DU$<ǖȄ2ztϜ:]t-˻*00q1U%rTx.|g.s Μ^w;={ד1;Pdpd*ΔA_S; aMAUNrY;UN IVqdbAagNTj&!گX人̢ϙG{,^ 3X?$1r~YB.TÒ>Pm%ϓҊ$M=d*TW*]Q 'S רFz.*/og`bb{auWͣ秺ue˥=ܺO\sGS==rrrtu^^}w\ C1]PMCA짃&v{;Cɨz\;#ФeSOpSqevvËso zfd9ݧG{V@$egsM_8>Xts͞bٰ'״ܑݭ CNc^5m2 =Gr{f_xp{su3^`7/CY;J}*S=T5!2e,(=Ȃ|(Pvom7o9aEuVXgQ6H7l:~4.o[+='LˎTݨGe*mڥJLx<0o}~/Ƽ&:A;eU0V[wVcls!vesyWMx!]Ҫ%x][ufZZyF% SXU]ո画w-àRchN狓Iٝ Gϳ~T[jk:]qFΌ2f:#]W-M3{t"j6Z0{|͵ i*2u7t뱄6IV[4#`?edk6oT}4bbfXШt(xNHrĺfٷVTtmb,l;Ph+\kSrq7mnU.QPz=閅KI8ǓwodǓ+'@fz#8[v[aNȺoG1 .o }n볹ؘ*rcknHݓ•,}Yvfa*bmn߉)O.Iɗ]ۑR`-a+}}$H޸yvݞ *s dZnym߱)<rBy]NA.ta̓gD]v۲vf9;HX=/QwUNw:qw&¡nݬ}*-bꂃݷD\x_Ã*Zʾv{HZ`L"㗼_;;[yK<חY9k5کg21ro)293nws~DwN9&543S⚉jQݯb&ڙ"XZDuW\-Z҉DŽ;*|\q>=+t5sI =śe *ܤ;CQSEU\sfk5y7|= QјI32ڛ";3V7I.qwp'_:H*@RBf1nd=ZXоjoRGob_k?sz%QM}R")m9q ^w}3"Y%k~}>ZvusEsc5w];{'כQ'7T(װ{_رnl3T\u]\9bhV-8[LY3{wk\)6֕Qd4l7%{enQ?w>|!S8KƻfZbE\G/e;< cZ6? ƸGr%TsdKRb,Udl`TOTfGQ ep5*fY4o9t]/Y2k!&%lh*h*Ѥvr%BTI bB+Z/xtߜ.soG"^A2ܲpnV-;d((2iwV1~h^%+PsnX)OxEeV{=kK+] Ζ)Ӆ%xC.c=nc7Dl[=5uyVv8.q9z =vĠj Uk:b3HX3)4Qv]jNcйWqz~nxfݳC`^>tZuܭʲܓqUA8ݍ`N[|! ӹb'x5N#DƆe[$W9~>rTR,~A}2S.[-ܜY:#:iǘ܄׻=$AKêߦ&RаxGp\޷$<n>BW]FW87'%FrvQmf؆LkR^|[' RvK)Xv@zu$pB*T;ĻҺmt;.e. w]zd3J7ftocᘺ_ٟݿNڵ]@{&6v`| bbvT )nGV׍VK=rvu1]׮13Z®Q |هtf:E762jjk sԴoVag?YGt %Ip}7BH5Yվdrdhش|N~NnuTU(cV.MMkbL tdMJU*]]ћn٪z[EGfK #=Џ [~d5eӍ<[)YR_Ȋخn{rK^7Ŕ:=tTO͗Y8mkWijTk8Ff2-y zH̔HxOϯ#V0?_i˶%9qWn İtW+h[:-' SMH2&`7NY߂!p<;xAݗ|z)Z޵xv1L4c¦zdr] ugã9nVYᶺD9Ha w-x[͢)!.=_Įo 9xbqÒX~ *$RU(}_G&nyꌗg'xޙeuoO֎r5ֲ lˠqr{M؉wp"$a#w{fqaN22sf뀇+bKh=犓69C PtA;7m#ƿy b;4aO4dzԈ׮=msD "7ѭSQo=̏ O`ޥDz;йaC| J,+}k]bV7RJo27JbV L(oy5S")/h_f<"߅8M{e5Ez] =Z]۰Yrܽk=zOD*`;<51Z͙N1Y nwbV Kչhql;,ц'ǰwĶs`gH-ns9".qPLfӡ"*jCա)_wFr6rW70F:Ub+]HcY3f-|gmcu8mzvPXN k`0an1y\ӕ/.z!=L2;p^2utUnu_!dQƬR3'g8vJ7;~{Whɫ\ǔxsC1P{n8`5ݵֱѳ6]YI;lG9n40;:%eji-X(/,܃ v B;*/?)!FEsG"QEnG̵GA)Չ=wtGu){do v3ҽ9:˂{O CT/C+GM5Y҈cerˬj<^TbsN-.UMB7(Uis22ؠo L p]ŹsHDG2agAtI{8"sP{ "ion~Ú\{AlWX] 6:O>rj3,n|n…Nf dY%*1!N7W6sv+5-GtG;Cئ/ߺxASr= zF_(!{1{\ O6y w:ѯ+XԡƓP%06gW%[YfQQeDՀ͘r9w;KNZn[{'LEQͯx ym8w' x[;cy'{NJr7g(^lӄݻ,Ն3!*-װ*jsm׷hνse^c7Ai YC)xXu[at[̲`۳G'1=c1L+Vقt>kۋ֩}(ZW4MD˭j3S'eVS[J!"9D>uL}KElNe0qN%cb̽xφ5|zr$G ~ yi #NY7޿?W7gU2S 88ϩ\0e\ri?M}WC QՖEjqX8^d( g*oy1oΙ=Ƞjvzw9HةIjFK]ʯ'D{/x*"Q|j tJuS 57|/_}qAIveM/-UB0e Ǒޚ ]Zx"ρ8߭*HVXkg.5LNV5ھn+Yvv*-,MlVq9qa.w}‰}>~J.⾗`;ڱtƫV"ygft.p-|{AyTIvYm8 vft}ܵU4Ht^ZRdYHQ9z]U]xUzXֱt0eV,N)lEնg2pU}o[G͝nHw;bǻʶ7.ʴK[[ӪnSv֤hwZn5D+Zc&{YfOlk֘SqnLvuM,w)ibLΑjC֮H.ƭ8&NYc.I#ڂuۄ;b}dŃo'f$ywT}uӎyY7H[TE]])ΗBUJSf{| AiLYE©{uhH̶i`%tpO!ѧ85,1zhF^h8f价hxw7eF׏SYׂW]E`Hyuىí`֛7rg77.N9/QfcW7J@̉r3f5G+wdd·w.,)aj≺P83a._iHh} ^߽c}xYMjDhf-c"ᵨEv3.ܖhr[NgTs[c0eG:((ug!O3Ş~yݦT*e: wsKube'| moC tl9X.nUW7W[˜5XJ3{pdY>nscݑ9{2&dS`vw*2޽;df^vMܻF=  ;ui*ۘ\J)I׸Lz9$Mnد:e6x(+9Roe1f5 GFG1yM1YkǬy3vy75,|x(6r6{BKnP3ްVG<;/_I쭫XpSXf!r̭/lzDՃi]-=i bp¹ٴ7gzvf\w/6cFՓvRqGQss##c8FԎFoBw6QI蟺ΧGJBwNJo_fm=Wx,Je){XVm7x;|0WP/tQm u10RUedTf;NS5tQC\<2&8ejÉۊūٝN" n{~Fբ;7N}C|5Yw.Li[gF"|Xgr2..f,n^)6dKoUc:9"![ug…72Hwyݸ-UN{b"|*Ǧ*;̅0΃a{|ׇ h`Ǡ⮐e;Ɍ4q'e[:o&EneL2!pl0]6A=ncm2q(gFBehuVr7q a@ި.PDviwEb7bؗL7{39`Od|!wBs^pLgTLl".ZĝXgnVq{+XN&]#Q Qɽ|jNhBv䭉_rpΪmqGKYNf'gBG1]vv-MΥX՗"]Q`,z &{4ZZfGs~\*QZݎ|{_#"z]-WkX6-KpAy%Ռ(dt]:ҽhM Ss5a^Yz^Jm 0ƱNoc:![+}.otM!1Յ)֐f5lk^Dw/jsmNeWfeuvAꆍTǗT^&oad]-eu܅X0f~|APiA]YCѡ1ᆗbk]^/2;['M2 BN'&d=-1]][bhV/{[:=0g/1p]M,{pM;EPCFJS96A|Jޱ3&^>9Zɶ=U ,Bjˁ1:e&Z} Px cof.e'rzf'5zq3ڛ#¨a&_5囝*yxs=~֒WԇsOZ&z0x<,jiu,=ƊqO Qr}It>)f#ުf;om?Jiw7muJ.]Ev¥NgsT7-dNDh&{n* 9\53B y1l֢]T!H::fL`e>fR畛he 3Kd¯аz$^ҝĹ0R`wF~<3E\u|xW9Pm7N{壬U3sxܒbP>Ŗe7mnӖɬnaۈڷӶN!}-|w\VgEм¼fݽ:%JUZdz%Y2tۺˍQ>2@8o싒λu۸~]pbP^!%v1Q}0nQnYpvh-TR}4sswVp-lua}5nd_M6нϋl_cfr}u|"oUWiPˋ)..5@Y :>Bz&3ÝC^\U&B^ft4< -}cQ> Ӥj^]T }-dڻ=ȧ;mXo73. 2{Xs`YC9%>C/y廸:j;g[Yxٙ-FiGjDHN]t06\~P3tu*螫nW Dgajɬ.F85= wIկ ;-s`,*}9혳fb0Y̻{勉rWWJPc\2 Rwi_qX2dZ`>O:lX+W&Uw4sK\ӝ;ogɧz9)[3Wsnǫ2x:X7dv>^:1kIm7mk-;I:s 'hm;3+J:w MbZv^d| 'K0]sn$K'9#}E;mn /=IQ8Q޵KݽI krWYmw`5ROiޝreN^ݚNcdgC)li뀸quÅO ]PpBnV_&VKa5k{w/`3=xZ.͐y jӺ~5.H rSwM캐NuHU4m+7o]2ypd]T|X﫜Xu~ sκO{AB/TsǂiͰC]"o7fMկ4:I=*rONw׃0>,ɷ| |]ԥ!rw;ȹ3WG^[ du /ƏUjo-R륑x;P0+TZs"X^t\Vv=yfD*b F2yݫ/eq *dn.0.-8[Z&s&Q]Όk;= ӖsÏ {&{q:)lk62kUqHXmDܮ`ͽGA>~BԺ3.#*mGs]`e۝i3VyPKsvO8BvaMCwr: 0{c&܉{<=:N}(uɝ%u l%[iF]ev6]TMTwLe{Wnhwp4y;=ZԆDSFk ›w0몴k Gkz\ת˵:5KɷnmʷKRթWv-<68MFXr+Zt9_^R=NTp%~1`vwPj;ŇӭCf+p,CO OhA][ӎjt2M \| ޒ0)+ g{axw gz~v?9I`jRsU@mW {#jVW=d4?uCGonb+tʧ]B)~Ȟe}-H9S.92bjg4gױc6w@(˻J%YЖ 6]kf#ґ{vshJ[O_09K*޼BSTr{^Wpm{.jZj-]\(}*&Jed+o \e^'kL[ZWxz+vRkKrSYzX\%w$sv}b-V3oJu'UDZ5g2gH<{}哕,{S뵔]iIw{+'mOS{s7Iow<5fN 9cѧ^R79Ҧu٨ΙF3A(%~W/5!tSmd !cXr=!IhA݋;C {3M~ t{rq>y.vhv֬`] QzWe],a׹M-uۯ~62Eu'>nJ~O \!pޞI,+ {dm{gXGY{,hX.z'"*UӼ Nnj;hޓg tíɣ\>:cwv)کxEtIsK{- Yφd8KWzفJM rrwI#vq/; : ӯqS::l/%:RVlO4m"F3(Cj2NH"ЙVP٤5 0c UjU$E8\ 5}9D[VU k&om`2]-FKZ{>?YԘ;MaT,>ܷ@٢vFOfB9|n9Sx8*] <^CG'= Vc'!м%8㬹z۶Pyy-w֭}^n[UYYS.,9`=gRvp#piX4U.#j"êL&Dnnky  {VAʕ3m/ֲ| Gjo{dRAr1Idr_@qʖiy r.voEŸ1x*yJzJhLʩ]4dQ ٸE7ӄ"UWQ s1=z Tsr=lQzPU72oq6R7ٝ{[,v69 ^ OY]s?WMVGy2' Ԇ(p퇨h|6k9jb+8x&:r;XJW7ys}6f%׏ KqZ4mQW/:aP;|On̰e:852zDL0y/rx7ϰZN@=G7l{~ ERX{Q,Xwv˙t2Ĵ]͡W8C뾹XTV .E7h=KoW{}MJ3xԗs PwC=:V+E,PQ3yW'TxL˙xo3Sj6)Dx^۝.tcO'0.٧_u×8{<[Fθg_U2e*f?Z0NB/ +:g)˓]0CF']*N{1Ɵ~3GVwZeP**{ہ~TWWWnzR|uqwOn\X05 oed@s" a{Q, {p{QlkNNj[<8u1soiA[xBtEnŭl8ȅbGCo3m)3<ϋIkNiWx9 vTh[ hlfT^v囫:n#yJ畍І^ZQ!GNJ7}wp> JBfʒ4jƒӘW5OK7EWpIF}-_+p1Mv3]R>g=\Sܲ>fI옲n!^p=9jqc::בGSȨF]֎"%:76Ъro: V1 ©Qo,q1.*{Mf=ۛ;՝+սl:I` z:=ߺGdoV*%Џ_n4#]8-A˺O3azlsGfXv \֊gAA]kIh8 |fl&W V{0ѢV=#ܑ@Hۆ>9, v ʐw[e r(7zKVVmnAfk쨫܍Kw6V khɒ[ml7ՕNց0׺3QˬֱztKsLȷ'uPANzUnyuımQ=.2^%kjFc`{ckIp6$ o#uuɽ6vڲg=9uT$(VT[ZH盌]y+-Ewx0o.d!;Ԝyį{nu+{ZYd#C쳾zO`3q'2NFrҝU'R"au\G-r}䓦1B/U9-xsٝ} )f g t݉obٹȥ^wMVB+WuQG݋T$vÆ61wKsVGP::}KOK_N!=39،t!i~keKL|l*\rlsuQ,(lzrQl! vޛ|Kyhk1 Umaq|FLcq+y#:zEDsѲz_U4ٽ[t6usvOeNۯrvu5]CNJgy`wB㷻J11eHhcٱdKʜ$b վu}t8]SU׍YGӖvRj mbW6rKZ]#쇰i`&>Ha1d>ɷ6G ̊6t⼶fJZ[:ovd^Su׼Z^ zZS[pL5Huy1Å\O<ۇDg! JPWXmzCjreJ0ǻГj n_/j\gI hfBݕk *ͯu n^S*vh}FA{]қ 2ɽ=SV\MΟIU-1XU6XK dlWv'w]T s%FmF{ḍbwIR խnJqwfc-a/k+g$Yy=gNYGnizc`ЮS՞ߴVD y5~vAz s#sE|vTö.gR28.ir,V/pw!8:h[r;!S1PhLֽܼ_[:LuȺ-o#K!mY 2ìW}d[+}KT۶3Ӽ>zu4S˧4хXuUX{&UK#0u^\щzgrھlܬb*hD3.̪Yێ2Q%N"UYaM?QKTLSf?6G#ċDq5sPO`yyq:DR]=Ҽ.Ʌ;n5H,UD4JW!mւǍHeFjvMл}۴i3c5-eQ ]2]nd nMC"uW!&X>]HC)`{jvt+[\].Uz;.260#{{h0` ts)T05:;26&tթxfΫCm+w$" ]y;}k g#%OFꮣqK[!Yye.t8 u{\߷<"tY0.t9ށg-#4LR.6p{nm:]LW<YqiV:PX(ny[KA2A'{6{]fAۈ^%|a ={/{&Y^3n|9×9n3 ]DqNGhet٢ `e,f_H߷vek7b w28{uVO\w#4\1:[-kGm%lj;;MԖǼgv-;nhV<:)iS|lSWǡ{]o̧0NiFpk.CNmf̣< ddZ3ԼOked1?(}Z]Y9ֻ ! F$1N?n{X@(~@9IUG}U2j{ϩfFjh1)P*Ѫb횖6շS2nØV@vϗ5zimtf|qOuJ߄΍Ky *0hCa[y-]wSZ]R^e&Ǐa4L撙hezD ͞+(Ou76XjN%"ລ,\W1C{(vv^Bl$_s~3]A_̀Vu X^zEyO|/ )U발}@V(>ݲz̚Vg:o[/$Dٛc2󙷕u/i3)g/5|aZOU[풲S콆h&vf릗BZqW\Ѿ62h4*c4MuI˞Tߎl}ЉfNǎ{ԮC;w;Uזո57&Emqsuw%'U쇏$s-Y*æ{;0pQ5*;-?נG5U2&{4o]u32NIm(K!N>᭕-Nu=nOT',siC=wSRϵ;PH9Sz nP:͡A|)#k2! /y5QD왈pFUJ˶Ps[Cx9Boa#a˳ |9 xIR,s m A=/]* >sESfkˌgfG%S_T7݃,1Ӳx=8ݖ𔳞Z̤j<^4UR1R!lg`,ꏃ:nduZMKS\@);wޮb J}ٓ'+M5waMih!\<}bPaa@Ӈ ֡XrA t` LֻxqXg=ET|l-܈cӾt^ `o8Ccx 3I pGSk剄znz ` |iCU{.'r!ƟG -yzA7T=S9xy>*K n6wk0|A'Ś 8̔pNՇK5H9gkuE(g} #nwU0U̚_6TNspl:TͬNdN{X6q nPV4;aMC{q}Ȑ5-M wq$y=Mw:)[-L@uc~5B2b\9fy3g;f] #zyj+cMM g*P܌[`ӔT8K19 Hz_nʄu1evؐ., ץڽ5PB+oMιl]ϯuy=)$d;ǰS+gz[$y/NCȔP9MmiY+,˝]3ncX8NhegO ј\uy}Wz_@nkɚ0.9׾xѣ$o!9 \Bͣ'.CWqc'9Yld]އ}%K‚n855s0s$G׼,gf{zvx&Nu<2ˑe Sz}݂uDDlHR={A`8#6xC&w|8|M%}^o E2qg(g\Sqx:﫫yW~0RiV *X}U=b=&L4J5L3g 315TZZ8+.=;,_Mj^cA[/+';˔sGr=Kkڹ 'vsUذӶ ޙu.UbN1dܒL]'qn,nAVk'X&,Qw[ww* M&ZBm6^Yu!XF+.K@Ǝ{x.*T()ˌ*u;NRġr9ۗH@xk4T9Vɝw9^ދO2,E|V !zQ(ka]W:Ӎ|En+J&(R_ 7ήg7A jKY.'t#r>`b"5{qdFg,e#s9wqO(8g %tГ|n{ mKnߎʳ7]{x)8liqfӼE]\Ǜpn#mL{8߂غo+DqUu;9x62 ]da WT ,) }y~iŚ؟g88gK#)S:Z⹮VdЬ9u*U3jMXjWU6tEF<ݼ,hVTc u,V'Ckxՙ\x߻$Aw/q[&N,irL̹ :RL.x}6RG֭a&Aŧ A2Ppjo:v:c+b,;/G۔}JzMj}{ȟ+GGJ (jM&z^fc:x= VHjHMwaBeU<fEokXiUw44ރ/r;Sw}3g TFc6w Sw~A_§XNαQ=x,^\"ủ^yl˨t,5_[ӯ o}ۣuqZ5vՏb5"E %`vzu$6Y$[5$ގ\*w:hN[@\UIMuV6Ycj֔ј8V\@Z?Xl,e=dXfZG$Q#W/< )C`wɎcHu/udv1_^ou382+ɞw\a&znl#'4bdI*vܹ>P w/32t3>ymח$gM$`: s oXUEmW*E:2~BCAߜR`[uˣ=~MNL"{ecDuPls NDž'DR)MK 7꦳R(26ф]B>P{ğ/H}GG93bh`rrϼ/eB7X@kPֱ$Ҏ/Xcc ?gE\%sk"򗙑b)kl|x 3DƐ#l D!E2= aPMtH""IniT8o6Cǘo>E .}DN˫:KKMEU]6?qč*Q8A8{fE4}m4u Da$ U9j٘DDŶf2"@Ќ0zkVt^S2vgrUc]L>n)S7'1Bb,P krPK2ZpmϤ]|!;Q$mye~ٝu'QId,DujUjJJDJ>s0̤ \OzYxlڑը)>up?)M)S0*EK)TD=)F1#M ϑ8\5l)Wɐ傯 \]X`Ml;<9)W i;j+jگJuy)LgȄNx!5^u!hyg|xmQ&x '\.k|[s[u#?!X6k&m!\$t;ڦ]&*()y9V:m('sc~o }##eD՘cX_jY5mf&K0WBb$y̞&7|tsyVIsxʺu<ܻvCP*ּ@{}Tқna"^**hdY{fس7{$}TP8(^]>Ų􉎎̒5 EvՠRv)3-Q58_?3GǼƽT&y 凡Q,v=Z+?^+2ɖxއy;kSv͓Flj{%’);x[V<ZΩaOm܅΀P5Ms } q|Z#G/ʠ^iTI}mpk{]J;̪թ@-/6\s Jr n4r͚r2=v rmUVl" WlԧE}&! pvz{ tܼ{ #E.XғG*adY2B6Ċ%WPWfN9MVx=Wyy v :I\RDh}y>9yǣ~G&Ԫ9CMJ :l @[u7]80h@݀w03qwMqw X|s3b.ڱ Ɨ7ʕKrCf=zspdOO{_A+m]޻73&;uټo/W%nm[8ZɌg^zRzK[qSȪa:}~./O?]G!Cq yfFUUGoBɭ xK7 g~k~Ar 6SIk_6^qWӰB8rf sw"M.YaCW4"ifX -] $_"4}bm!7]k0֨u3o3`%}&€?̊aT3x~aW!${qIG`ȵάd>3.-5j.OEMz ֈuNsњ]~<=;8nevQuOh>k"1"OBe6miS}s9mcT;U[Ґ]Py B"\C.5O# _I~~h[h>tߘ3߷7~o0 T' 0&0At͚Zڶb8n+_OЯ֓ii8cjZuU 5tӶ];ퟝzz~:hkɦ}S T/,686?kkz9Ʋ 3`AH~ѫ?C~!NEЪ}"Ќ, " 言P"V=@"{p2eT!jwYE c4[8?@<%':UBQXu 8h;zuz4gŽ~i"z2vx5Fy=uܱx_z:(bjHnciˇSzn:5PM7)mM4u/ԥwVu߿r`C߾N=$D;-U$l_OVw TfS'Eoč:/tUr{W!`BEH{{=OjͶ:D7r' n*ERPDu_nOv]C.y8 ">*=+5ӵAy'O&chYku,ѡа4uE2WM],44pu]1̵A GP W$I`h*8n::kh(n%: +"|?~z @=kc_~Eo.4=Lj8>=F>gS~L9w. ({1]+*ɐRݾ<k⚅R$Cyz=3馆P@4B\CU7w2h8뮚`8UPb??,ˇ_\\:ܺ?J.~wa"k# j:'Dʊҩ]{Spz'\s~~:jؖԴ>¿}Vӗ{UzΊ3T[]9X0_h!O?9U`#Q-*]Y= ^ӥQ]:qSXڷN=׋RXΙSiዉ*q<@g%zN}@_^;kK_];ә'bnp?wx뫉fi`&!*n8`i4(jښ.mL1u@M 4PLw2q5MSDw偸e @BʥGץGAקp\L$>4sk"~%_7הs9;08o͆^DAIȜ5>aaAF7ˆ#6D+b2RԞjLlNىPHpPDE~^wqC?jmߺ!~L>;]]!:f~Akʁ`u;p~Wߨ?us]\_u0L h nbrpRusq9St~??::NQD1L*+.jȡMORrBHT!p(z*$|b.(P|qG}W`8m:{{ͦy|ӝ}'}(Uܪ vd$o%%]nqkvVH1sU$#U_Jup) SS>*z9iJt!xʒSͺKFk'^lby d>]mz{~eS>oͺ Cy sP>YU JYhuˈJ!>" ,̿qMx<&.+hCwXОqyψbUơ9c{sԋNp9qjU1"&f؄k8!p#3>JRm\3qj8< ^g 9΃/tu\x|sz/#…lTɕ)k`7ם\z::1(#fUks%]ed Ξp\髖ݡ=tlί0{豕jG}w׏]6~,ߓ>'Y'">:T=~tqpdL1GUCt˔(_˾d'+\8_KãS*70q, *(`98:҃߿.b+k,uЋZQkSYۨyMzibw$Tcv"ً}0 })u x2 ۏnLnjN4-+2g'KWomM9+R|AftǛuSfCKQflYt+=,l['eg7.OqBx +ke>ǰC~$P4z=_d,:!J<<;,v,F!8;B: ǒ=m^[Yw5_n]\|UEAH+&n&*R ]dEU!Ա_LrK]Yřnޒ@1Ïq0%FZ>A{W6pyfu,+{.A S}#Emy+3v3YIרV s9SFK3ICNҪcUJq$vry*]QwN Ԅ쬹]DqegS{`-2H_w'sz:l}#y/$zZۇ9zG'Չֹn\\ gf<(vEugdJ59?=(*9D0*o,Dt9Y )S}{m uY+yJIamsaCNZ`yF4 \ '[BK6"Cw^{x5#Y%^u3)ydX7HxV7J=y%P!R,L2ōse؞_q=%I<Ę'uƄ%YG*Rg$ʳåm.N/NѬ߆ dbXXQ0^1rI7GCD.u"A{þNLPӂxxU팢C:^YI#`-P}N|nԾEG҇;yn!6ӷ6ݢG;b\ݷќt^mjqiG\xW2Emk>W>܂ǯ e9Qi>S/\K{x$T <,W|At#ET(~">+m6\qpg-#3>+ۥq{3"_йRvXyͷu6V.ltS0R4懰2WThz&2l:_e4u} <{`q-$]QzβONvoaUC~6ԬrnÄ=I0 0GW Zm{_̒Br6Q.܅{qD8Uޞ~ZFG<ܰ\M'v:Lt|Hy+jz'Б,Aͦ6jeT v Ku 6u{9׈UunAR>'DFH*ÏD~ t] }WS^ҏS4qWW)ᡩG>4)S-}ɼ9Ӕ))f9Rx3ڕbx L-!وd=o} ]p|a^z!R. ;=6 :)xP\"t1qN@p'.%>Ͻ"5=n|T 7CBмx?\ `GQ͘Ĥ6Z)cbYPpT0iZJ C]CL…Ժfa jۨg!A37iz/QyCP^{$ B(ȁL $O.. eɳ,Nd˗v|/?9͎4%_Z*ԪZkj\BfU(gO aƳW;$8 \ U<_SurCZH ښhn` `n& U h߃ΦEH)ͪ w N @P|(w?7d&fifE0~B R44MZAz珠̄b%~E"MrNTwe-'l0w<;<r>d>*@t-܁bj9#hh~9z?UE u K5 GAP - PWt M1 &."АE; "G#gC *9;gfBc-KKl^=oe;wU}7rDQ~DO6'}\wqD { G  \<2zU/^P<< 7j[j~MA]&JZ ATXji`~?ϣU{~zgJΎ\uahKCu 3MMS@ Cr?_*oV1XcU}GNt:7aF C@_}M oE/?1!σ>> .9I!B AӀIԵp%ɁqL?rZ;}H>@ cWYvձt/w osȺ$x]x0=l{(K  σ']/~i#);8!&(\PZ~~s'r+O6K.&饀X"X(b`TCb Pv :2o gC301q#}߼zҹޘ[i yO .h<P9{FC`&I.\rBGl ʈ~FlcW>jc]펬ͳ,&pYtFVd>@J!_TH@gh+X_~}5??!.sU9pA@28 ç.?I<8E6Q]7mK]7t-m -M t WM=QV P)PKW%DΣà3ʃUaouPb6úa{(\:{$I1KNK%W-}AڧR4K-Z0H*Y aQNig ^}^(#9. 9P G  , BsQPpP4]wmm7DT>wwc) jb88v(:ꆂjjK:(:r*2NvIGZ]:څ*!ݎKI~jtg/}{~JP*x7(mK}48خ" TT˃X厘 O0bߑ:Ƚ[VRϨ@n/ L7l_2CcM]bH[*vo:~DLZAԵ7USt,BW@45P1q CMETWG\ C\G5AM -TA@д-uL PCGtе[ 44u\.^_(H=^.^Eh83~9'd2.<xtz(Q BH[;"Hir-:T~P-="~()\V 31(Y%$~!UL.j-#RU$'O*ar&ӧR%Y.w6 'qMB8mo ^d !6qTϧm%דi65kڼVKL2'!G'X: y]}_AvV |'KRz%c)܊v$$J5RuQ=)zs yGW 6Ϯ8R_J+M,iD5>i#^nj4$,qIQ5&~u 9bp"MU9x)l.GIWLR0(7#d0"F9^'0Ud;JXBXT!O"[0Ie؁sSFl844Fhd'æ12Zy?DIR:R]j1m>c6V>IQE*УZO$M pnڎ!L 51%9Zq PDF[bg _4>%R"ELxշ%E*MKS4˩tb1h:z1Ʊg1 sȌ,c*)t TTW!wQ\DkF꾙5 q9=4HLpF(!YSVk"Ԋ3oؠS(/LXA:?X /nm}IW8%MDQ}Sn:m㵗8MamSj\,q6_nߔϛ8%k|%H)[~hZ,U2 'S0)>jL6=<&잵nR#c"S6iÃzC.JD$d)`th3l/qT )\. ّ\b'rk>L"] [Ϊe! AL&VjbJ| - K'6iYikj&[[!ՊU\83p3)Oz@H ݝ~ IްL. ԝ t_.Oއ.~r`j`8j(4:jZH & n+-v首غ &-"]кPܘG%je+ ogjUp%j=_K&s)fk1<ǒ'G}#!l~x:6.ϕUmVV>f7}r_he5^ۺW^ݜOKvK5Zx XfC[Ԭ^ùUp={L~ 홟OD WN[v/ow61;akYVs& ^oY95:=chUqI4hُUYIy˰co sl394'EЋ ?)5_1B[^̾2^G->\j α1)˵Gf`JSBI+/s0yw˶ S_/_M0g7;-jaj14s&a;99{ 05y}qr7Tx+edM\:ltBj:53/IQĊ8-qx%ew f97j"׍'*k&Cti͆,Ϯp.2eދ3_xs{Gxfv+#$<+NXvh>F`wY<;v>o(am7ۣO#yUs4qVۗ0ng.x˲(cD;a;Nu`u];JF^LuޯvTW:ICb|Kܳ{'.f\˙-4,V$`,Z)Kvv=sIms{bhlm:=o!-fE={|]~k]zgY^]f.=Ak [۶5Ÿ7xG({+8GPwt۞9&Ba;zD#n1FnƸJ篅EqKoH+śH5}xf3؍VElWcM܅9iS1b3ZcQpqZʌŧ!׺O5OzVǴ,䣡_Y}|^(b A;˕HS8ЫyPa 0#v+n6x i Y35g/}Jc_" _qǎV*gl{fc8iN &dU:!C*d?oVW{$Ti_ >=k~k?Hc=W^!gzqy}-5\n85AU{ƯQ~RE^T&]A4Qi˾4o+;(0ƾ|ܞ>HSC:ѺSAviw|}-/Wz9R$dGHY]b8ȧ)˰q!# XgsD? > WҴCH56;n3~x dx)˲=`J滛%iTÁ╇5~'MhaZcmT'ּlگFҝT!W~D֑{l"j@N7Z;,DB%f@QЎVݍ yKi1%J8eo?mx s2]J JGvW񜸮Ab~V+ި.E;zӴK-}kF\W9c5݉˦B`Qln:x wc?zu績 3ӡ>a t҇ɻ|}X 'A/fṊU7tg_s A쾑=u.j*U?Cv%>Cĝ\JgGσd"> k`f~?b9`h"ekI;Z:L0L4Ap7( ҔX::Hke+F& 2+I)c~CK_N'ӱ $ϥN[йہ7h(^|?9_]l*VUܱ0 )F dc`HEVѶ}\R1MOHfH2ւkSI.ڳ|iogV_L| Nu=<S`NrRy. `i &&he;fHE%Pk;Ihk Hi@ WFxnb E^ |?*%u3$R$%ngeGnACl'Cywhg J>THg[m4Q!mױV#B%Ú(3/73"B2L{Ⱦcuny1.8`hL }'cSm_'CMx<]?)uο'S.Z_uKBE0mnMMf blȉHi `i!e#f`:(2A>t~|5n vD6 R ؇j(Į`N-m‰D6\8F֋LJ ˌdnldd UwwVBe} QnWpܶi_߰-“eo$Ah ~8GyJɃCǃׇ_ɔp@[15lM5Ա M 0mQ 6Mp\L1woǨǓ\>pQ4 CR7@W~#~;w"%*=$j"+\GGz*g(t;j }'_G.mkaF(;d]x3uEh4_+mmԏ)zH3٪{(t^ow2\ɵv֟ZЪ^F/z x='{l)!;%"RUX 0qPnM̤ 4,5 WVC]U 7KDGCwqG3 C]"17PDAuO|ߚPm/dI]eWsu#.@=Oʂ>ùf{.y s4ORT.ҡ!RG?#J"HIg n aܮqpOb=_) /&u8ޓK :}'w6B֕'(ۋ .[6);A!ZXb`fa#`h鮖e&.j(kbI.88jnb* ꎁWNOob wR(\d"]U'sݰ1nDvRaʣ~]^ ϼ&.S džrI NL2 T#t%ڼ}}w$$Aqs| 8~2b kxh4!N`}pv>JH>~Q4ԁOOD w4wtQ4,i kc) m54p4pTTwSQ\@AUPU54 8Hpd⼅U@xJKWC)CU?Q;˾f([UM87t<=w [JFNN~\HY6"¦4PswQW f€ ^ѥjLnHy} Nsx -[$ ynX`"Z8&& .it9E˯I\;~?E wMq\MT ٫8:*$>yP,ʜ*' TACuCj]b%t:bɁ=x>$v/qiWK'th0'Yݦ2"I}T5rE*W dMtqz?r=ԊrkݞӞtX<G]Wb /DURBoG!CФ( h? ږ !'_ӗ!'z_.J~_SASp-K $WQSu5vn)t~~q;z~6!ߑ,wEk8t|*|T$9*~ˣŖ(Qny:$GMQ]P "S sW9L&=:LDqA0/]ފ@g)oP: > ГS`j>md hgF4n*5)jjF,KEJ!^*a`wzBŮi=e[rU8*;d+.kÊ^-mNmc!;$Om (Z\ tN컔nk O]!c#yo%ڙy"Hs/7aD!O&NxWLt\"\W֌PFl툗7%Ui5Eu$LN(T꯫ºmB +|ϚjT DK:iRSl+̹s#4Tm`ॕ"]9L45䬕CcLae]=Cv7~lsGžϩ"6`!sĎvaHj,k= oo 5յlRܡϡ1MyI|"(s=6Y"\qדq I|YUt*w$S>9&a">4=`ILYf(dl[>Kj›*Iuyvp|'>?8VcAl5+[cYqK9U* 2fg Z7ݖmSM3I֩˗F5}M ^ڻz{uWnq뭉P$<}! ؉^|-ba_@qv$EfmmR2u- xdz}S-,Ӿl4 iC=exk<_T& sPG$Wi/Ft=!@s\\l[1Zm >;Mw5FaPyC`.o4y؊;&OW_j1b5*]l _3Xjg$Βx@PyIڡ̘Iu\sJ̀}f{_Lop`8fB:NnK~IUǪxۥCRǩҔ{Ի5+A4cNjmV$Ns0o`/u.f,S_輋/;bȫxB8 #8hx [S/nշَӤ%v*lJz+eY2XJ^:dwBop:~>'myz-Z 7,G#t1ȣґݐ]OO)*}I7cY梚,:4/`8ѣH'΄lMgOCT|wY/'v1n1)vS1vۯTa̾Qg+GgˬO4n7F :<}m4S=:sd/Ŭg_`l}ET5tprNO#Jܑ YoFV ކ Ge x)UXUUR=]T'sIlqi=_KhQ5}6쮨YRoeW\Jkxj£ޔo<}2קo8wx;eb M_?4J/RVXt(BvaQMd^HFq7>S4ȠذƀWo ->oho"1u̗sW^hh4T6bX;İUЌ:(-d%)M]~&F"]sbY7BJ!iza2|.aUCFhncg5n M8sf|~Jv5sXB׷UgW1 }Fw|Wb[ZUlivW уW{6k[۲>!m5 ~-&86-8Îݵ~9lyOYdah( vmܪ!5f"gxZ}x?|g/sBr8ܝp;7^I4LY ,i|,CK #0&.=U{쿿*a3A$"Fh':|dҡS_;hÂwf "p`!;ۯߞfw]\W:ƔGY'v‹f42D(&.C»S {ǽʚC*G3DG pG9ps gzzPLSW@Mqq1T4 PEp @4hZ$4Q4wԱM4 7Sq1 4MCOr:"C#8΁S g[VxP?} I_h*apXpOzH@ΪX/&^)ξS: (ŭQ#]D3k^kC%ᫀ=ν}mޏߨڌ?69{9;@~u_WP }(w$c $@yѪu+ i C=?8`>  10  !DIbmtc@ģC^j4IA'Tr䄦>ܕ5t7]k1ʤzi嶳w.]Ll{܃pCtxCJ&T;ϑzןK랟ʏQDz4q]|N9|s\|9Qv%pb?F|! ȃ2NkMĨfǔu-"/7&{}[UU)1yB@0wҀœqB蚩"5~(Q! bnkSIu`l话wuε1oZY]Qd<'i:l9ʻ@ S,upg~8n^yaX }*5mأ=°yzJA2xO1蝕(Ց:*^3҅(!9K/&Y-%!AvR_$4V?r*6Qq[ޗ[ HkXn4$W ʏ]:Vjگh Jƪ CT"ic|6|=?|[I=@/?6(4 vQgQ~r;j9s)+cm,)׽:UD =Q]سԹ'\#x|f}$y.z ׿DO!3 OTH A-5̥ K 5A57 ,4M.`n!nkHAR8tUS&4}8~/y"!"8Tt0*xR"xOM/ T(Ck}#:<>{thkĐV j1}P殔LrdھS~M,On:ml;-H8xz]'@|'|.P_R>|g >!caqi4,Kl7ACM6ı Ҡ;GSQB 1˥+]Pw VF]@CQ7`0t<}A ª$@(Wl; nqv[n;O}= J[[5 po=ͮ\q$mqBs2,[A!Go g㇟9ޣd}+ %Kݫfz,éΞ IeW%nf'{ '*N!C%H/.JT :׷xض#`w#}_CC2Yň> 3(^phWsqWiۤx ޲C 'a302mΜcì3n84u+FQHMSIcqo[*&f5+*sJ; NETկ\sQn*<y/ 3z* dғ&z Ƣp'3Kī;.mrT_bZl%z8s.|m*iGYF9{hPW"~b}Sj/2%oh|&ez?NWECV jS75J5+Sn\@pR|&vI1-j4/V+AԖ!b m$)>X."8@xVذFQ52,m9oζʢ8жC!z-yc#81,M"(;B(UB pxǍΟd[O:G(Ij)aϫ#1tV]JkYf4԰mr-HA8o`p!d]qo.w/N|qYeܧ)4Cm+3%=!2~ 8|YP~L,m'"R}DJRۃغߦh )a1v,1gm|M2LIFaEq;v1{0؋ĸlͻWs4tfXY0 ds-YWkԭ jl)o[j\|gqQ|2?>Xa-Ӯ X^i!2A$`YqT$>0`ŪaT$J狝˵-a"0$wzQ_70N[i$y;8_TBg RA/|H3b$'=^ X=O,=@0u-7ETв)`%)m :4FPWL Ku7L5;=Y{h8]%'ŬJVf;h0YnUJ5pvM809\"B6]eຩ >8ɽ'܃lǓž V'U:ĮL츛mzwf7 wxeIޙ+;mj3􅼬@Z.s^cp{zZQA.YQ)̹x%Ď2+t ƠoYy25ٔpS|} {dﯫU/rh&|:‰ʌQ0DEU)J}}O;QbȻBϼ\x^oݲ.d2ʱldAjꄐӋq xhfXyڤ 6dvrbdxRrtKRV{ecn#1ӊ?pZ{81+Q$4lEPqq ݜƝ ELF-ei^Q#Y}StyzkRQG1,Q;5yսrjŗ7"mf5M J5KfWW}n)jr֤2ΨniIEE]==Ͷ<Dz,3fѪ+B+ka0 ȵh7kt{ V}!}ٚ3Q޵v&~Y7٪$dάeCWFmuj,K܍+Nٙu ~7{8+jl;;,M2}P3>'WX~un{sJnrvݔ%@a dLq^qΘŅU{V˛wivsC{%.Z]JDƐjvk[k}ck!DThv^Q;1G__O ܼ{&)a]v1l}<1e}P9(J -0Ke{OWCM+,~|u|Yw2&FtEyƼ4$ hF[a>Tݹӗ=Z$YWL-q%H߱kR_KsGHqa4lӚ4w|9f,)9*{.mIv*ޘ\:K ӁSnodg_fvsUupL?]yE}/uM>d^T>Xq~m^VsKlwHt[>iW.ϔ|̊oN9kSnDw #f;^&wI-$GkŰq$痹CD!KXTe{,nj>6L8;Q."feYI-}7>g~ *G14HuVEйF\ܽg:}|JNG j>hvvւ ?*/oڧ6flzk?>iA#甤Svէ]#Y=pd57bj >dP4!]bCôd"Z0p3(벅$mxgd C!GkkZb R>35R:jR$)$6m ˲T |gTN]珮fNⰗSHMzΠ0Ɔc\8>‰ M.݅dX*pUg; T*{n|sj~*tO `Ѳ@!$d8~J&:+BQU[J'%u ᠒wp8 l6 ˺ =;U; r iEJW*j˳Id׬xu7274NyY*@$Gi}Cx[}^NRf%XYj}wBhh`euׇrCף唡IZi#WVAwǎ{lo;N@!(|^!ic={N{ۺU.T'hӦ/!f]]2t|p{݃Umn{|,J^u}pfaBPk D hhYKSCw}?r9D*"^ r) !W ӽA hFzP|w*zQ!y A O5~gasK[)d䮱:YUxUdikQ&m$\T bi`A<|j\F01O罄:q0%z㴛V"DRZWe"T#n驂[HRd}'eqקN)ÏyQS PEy!d8UH4P ~O߻~OJ7ۏ* o P,Ÿ0Y%.υ R?5L l鴭{ mYǢ"W ;ԯBrDC_>$I@"Dȵ  xҔ <>?r;Ll)H^;?>k!q rURe.H_<\7ٓ8Il!mGsKRcUbo- {"grP6Ma\a~tzT+}r$N> 4?4!F WCMq5C] b\s lw@5Rl(Z21, ’`eiMWW~o9d.XN۝s]Zg>Ґ;}_~GA ,eE9FpzKD~F׹yk" x7pm>ҡ#Z{ G+N@9λ.D-}v'C#'x뻏K`ᅀZ]& mwt8|6sNu<~?HuGb/JktLr;JZ_y6">V[\1a0Xuw*xӼ4Jo 'ت-\Zz3OQqW1cH\GN22fɝ:{].PON1xlO\})(< !3< &+DG jDtаA3Pۺ p,%Vs{ۼQMjn4T`+?~:t: @J&PzwG$h[qX=a 2Uw:T˽6UT0O+>a?5/޳fO y~.Q{;~)j)[O)pqKOZq}qz:z)xk-r]`ׇuׯΣIp{yʁުX~"Ij6'Dݱ %{CN&a1}Q-  P쌈IBj6-sU}2~iX9p x]_#҈?|R\kbϵ=/X>k5OSn|FuSxH]b6q9о67gIHRfJ!yQ0E ~yt6ܒ?1Kn\EJyQJi|H6ێɕiξIIlI Eԋ͏x77ޚDe;:Y.8 MI7/ )*[#c"5n^aU}(🉈Zt+-J|u3GT̯j8?u{s ܾ}-9,`j/jt'0,KdmbTYl|}b+e54WEs7R>u.81H2FEq6m%j]w~` 1<mD>so!)% ʕJ6zWRNLBB-6BaMҪx&ˈZVA1xV`riuQhR xg/MJG^S?NNH#,7EO*O5]x^<# E圶Ezº(ѦQ*AQn[[HFH$0istwԕҗ~leQz@#gvCwG;cx9`*@H 6:~±N#eA{˳Jb3NԶp5ڭIUEÁ"dN0U\</ >xj/[_+ I -ݏKa407x=2T\Й^ccTmB<͐Ӵ!%w哦Ԫ[eH@ų !Edϭ[bk(n}1f׳N#8`<$"H7 Yy]*wwwL{)8`V)ԙXʚzYtER޵l;iKʪW>oJƔ)!oߗo-?&$BlUYM*i0sv[ļj"X=?/Z¢B'̧=j+KQ7̚fF)Kʞ{91Fcs+^L͜6T{ܒydΕWfKirL*!6mxP[2[sȹ Z,RM4ZӪߦun٭ YX7ڴG]oVn>Obrdh][ce=F: 2L{EJ،EMnoMUy:5=>,dϲ}0Z_sgW_wP A27 v*õ&dʮ"pAub־Tc[{Mymq[}0"dnlP4y'f#+F,#=j6o"҈-ݭiYdsx/LsJǹK/1r t'ҡyGwu=.eޝ&/+=FKSٛ>[Ua)w{Tf:vS&Θ٨;D-գ]VըN8MMUXqc/o38IڎlݩNk.-xa{#u,}vJu>}ֿ7s}_T/?y}6E*h^6ʼkܓۺ^r?ۋ!L+\/T۾IuOwv#bM-lrB3{ ˬ0a,ﳛ{MbُYN㯱Yu~n܌yQH׸c"<88y4Bmk<|^ (!ݸem? c(go1HiM!YH ?25qdM|= <iO>J{t,n h3M w ?(߲^_jמVLٕdzsތP1xÌt8xB -9f^l0 z]ۏq}٥]Ԃrl.!ZUzuY[^B{inqC6^*xP-1Ǐ@p!f"^[٥k^J"Jd,˙t }}Bٲf얮ZY5}%$# :G.@T?K 9a 3d,.0i~s%btν6Q[FN ԆyMޕTr,4̈iӦ45EoyzGP`"d{a˱Sy=b\`qNt^B;pTD;򱵊{Gx}yN@#YekSCi (3c-W;>N YQӪeAw62.L4'0SXxzD}uXu P2ݹ[\8)r!¾nm7~9{2W`q[, @I]*תQSxtcnfn=!5k`G6}B? B|1^E$Rr9.ڒ^tsXE+f &LX݃i鋒޲aEsw \q5mrRϜEDn~zOЂO$D2Ho 8@*'WӡRŶ@,,[L3:Irw ~Ӽf<{_wܿ[˥KrGmtڛwOZ6T*#ȆG%b띮os=:|sNK|ъy|é y#<G'x(sx{z.^u/^W]ܼ^|y9\{ϡ8q:}~i-)д })!  H~Atd m~+9L,w+2}sbh۷,Yugry~ĝAu"}:C{9)lg𗖣 )|xHr>_/.]'9KAi2OzN_qbYaHccbji%Ժ痔wO=+^}N.N¦woL"bb=dBո@a2U=p'{ڮz] {¶ {#+Wzd8w]D Og,u>b~/E T/8]Bx$ :ODTH{%C^*OzORT/ΘR4.{<;xrK^zf:swt={˧>4835~ C%{暔tQ'Q9WQ!Kuxu?\2\P7|Nܪ욁@/O N$OX iq*WH뺰V6YLحChpɼ4dh?JWe5= ='O)'OB,8mӥ4}]O=;=:8yt힏{޽uuمm)JPRS@윪zZ 5 d>ޑ]s8P=X+>!ͤy(9u11fPܘ&d.:~ ^s?-v鶛x6UdaP!Jk#9mu[uc1R č{us\ ϯHvyD}'J.1%x!ϏfwxyT8: ۸G%$H><'~GLBL `C8xxwq%v?P4#NގN6C/p8}FʾnE΁_aDH>sbI76}sڞ.]OCu9κzO#aivaBq0zN'DW;ʅP#ۗ7|UWr{4zp߾{*`ABГ|{JGd. 5 ݸ8'c'{(v:j1U/B/uI?'MUeSQNA&T9OEٌa*~L,hfz`#̖ݳ،~їq b*meykbDس$Q]}^zA] Qq TQ@ѷp}ڽx& #i=&i@jt2xWI7TpW1'zmJՒtJ\}PMpfk#.گ^m(:~ӓUlZo&+uXԀК/,tNhCm5~qzu[hRԅm47&y$U)IT* R$~u1uV|!zOQf!R¤os;Tf\ 32XĆ#uXH8t,{^ V3($nBM6ϏESgZz-1X%*t܊@ ch:~wڣ֕.+N>6gD.<咪D":3beIM^aIx[eo*YL{#~ w /I47fg~0j!0ۥBRQDΏ LϚ!M7Z?sZ@{p'& 8j,&^syT:))¾e Zv9m`YS↉9OwMM7NMt,Ym%قaM㪼g|f&CF2?23B dRݝruz $pS=M81vƬzDg^KUN=g]&H|&#]MtM7R[ ,˞.OJ1QfWrwOx{՞gك,q7|0^d.|MBI c܂>Y(ʥ{Ozb} AԽ⑏|#b@ y/ciNnhsMNEAJۘ|xL^3ׄ5{'0ZgXUD0$ow/x`Ў$^&B6žaQCVܒS'OTm4sYR*p)_e5`-'{SޞfsЋHEy3$"yCщ5w}Z6o_6;ݹsͯ^Wx=<9G^^yɍGKq .J8o x{+~Y&`pv=|#tM:ȑ DYut[l̻Um++ohܲ귽gT*K\GC=&js=}{ۚ#ܬjwܽRYN'9;P"!I#р2R$83Nzm6t Q! |} Q:>VX*aݨk*84i~LjIuvQA_e?|(ki6Ҏ-)\A'0!vD!kܜq]fJCfU a fWmNѿa޼f%盧}^3d,Sفj!#Ιzr7^Yxݻs[.6lԸoM ٕ33]VU[\:峞)DSuP#ܓ0eҚ:z fdڅ6(aeOJdɇS{3PBl [)͢9T..멷kfeYűxoOEE9H#dvkn}4oL{%HzvI[j'^Gj߹eDt(+VD{xμ{rAjyVk6+۫˨n ؎!KYR:|t$9 t;mMrN٦c33WW9' o?9nL+ըR{ÏBb䳟tm;Rl,{[5o՜u;Nj/Cb^DWf(xc: 0nG}ٓqZ.R/}UR*0||/xYhZsRR HpDj/8DuX5^+_J;];NLUlx,ULKJ-%;iC)[^JNrjӧޭqzog~s]ả'Amd>Z+l<6vkpڍ(񮚯!=>,{[N8(.8y워VFvC2\@ޡðqcV)jfܒO|EtJ劾"Ԅo׻6Igώ Y ,զ7߳mxLVb}"V+bzu'뛑>&>gsN~sd^+PJeֽiY4Nfz%N:C*nd7rj۶ğ_ir"F;e`$  yR6ek5So 7wwsGTm珵oiu-ƣ~,kmGm-ir>]UP޻B07%u# t8{Tq׊ge:h|󤙔-{9lUY{UD^},m >'uO$'7*,tsqQ!Imklf4ĉ>ڀǣ!OZRo |;B;aU!I X~HJ\8fq4Pj& u7'!Y>Q圴Wu1v eȽG{Ę'PT&*CUB`xڔ;ja8-*Gu_z0Z jL9T/`ZU_jGE}}x`u7#'Ϯ򱙭"`șHDĸ9 wkI3 7,Qݎf^{> SSǯB@C%*u CF;2BAAӯ*X fq5x;7  M]s j/DF|Ս N$h>m,'1RTs5e{AϙăO/:~ 0W- r"u^+q{ j$ $Xy '_ѯ x+.Q'Mj.Hac׼2qӣFףwSz^W磇,۴N:&C_ƿg48`HI_2 SUt;*wkv@̒G ;97n>ou0SsC@FĒ@( T(s˲A>30Uザ#ğ>ίu9tDf 9f~0g>8zN=ژ>zGC$OHxk?^ǽӜs'N..}]Kܸz^Wt=^rh|ߺ(^=;TVH4pz5P\8vԴ;6\9ۗop g6'GvC_(?>m:j){%ۣRn!N\K% 0:,dVAN*)^gnv(z]##CԑzA:rס\pu8G]+kb' W]~'[bUA* *'n@t;Ζ-3$  ;*Ӱ3.Hȑ21o;SO: wޗu!$F&^Zؖ'CtmJCqJ32$St]L0̵t]) 5-11ͱ,-47Th}񟣽Q IS"v{%@_)JM&\Tg4NPf9{}#$}Y 70.dKvکTQ٧@}֛x }9,>^\+9(HR7P\l^M'{Wa`$u1:4t]qu 1,uSuh(5pJ2QwlKl,7@BCCSMF3 C35l-, uץ#TUPugz``቟ry(5n}DHpUT'ʾ{(e 2ĥv@bx}5T>3}qTz>~6U f2砆8e " uNĨQ;A]TA"IH{ߕ̡44M=zzz>L:p:sˮwӋu:jv<DHbb4M~,WW/ ?A*쿓'V=D݋7սh _ÇQ JNژ$ ,@xP sߑ.Y:PN!Ҫ]#6TIо _{ܼ@BUNxA >;'wT߃CSC B C ,0,n]x^z{uyu;;y].uͧp]sx:];/OSpm+ܨH"t@@ R5SdCzY^";*q1[Ժ(Hc(mbF(_zVL$3B)>0CyDlɃpBG,رALa14 7txM8lj(qaq}n-驪QB*Ӫvg W[=Pu]?c{rCOrN!#,jW{NڨI Krin}ě<٢>K}x8.=b5ooFq­+N}Z i񮈃7j"N:z2DJ$&-KOx@N`+Y84]t3H3aq4Ir7n15BAwE¡7mHdi?s2*%J*|1t*ztˬ*NoffLiJ6;iM ~3 w"/G^k&?Tp4:eGwKaaeb v%sai 3gi28Ot2U⢿{ğ@yCq:n[m '_{7*0UXo!3`u'hlo0/xprpjO0,>Y!CrJM6 U:mQ5ނhqKl!mWվ•La`Aben$|bt]{Y7J0m? lk!#]dfo';NNh-܏[cW;>ߥ(>U 6}Q+V2'v(I."EBY3 o Z{jqϟ) )Y;mY Mى r̈!^ 2? k>]$7GyӦF,b荹,i(ߚp@6 s iS+&sUTO&r(_mH+T=בT.l[9WNf@o'V dwxi ) =y)%Yd)1 zh3UcQ.+O*۩K =طͨʗ@w U^r LB]]l`5B-k3˽ n~m|n%w-O⇄ps,{YgR`\C֏\oqCxbZvB :\~528>y &y־:Ggzhm3d8v_!] +]TY+=́gMRrfZ×P mMt (t;+w͔XZ<{g9%1&ܱ/,+SC!v7'3["CYTvp\/L+Ia6zzʿ9nnHӶ!\4wuSCglwstC"zU^Nne^p7jOC {ܣUUXR,TƮK|n+p)Qݶ)<#黢"I}#f)#3cEݺd<NW`޾Laws(^N 7ݾokВȋL׮z&St'XܙN6Xvn#L<,͓\@ ;îrm62)M:aQɬd2ƶ8tHX7rQrŧȪJܞ,f1]Λz>.s7&dRSWzSsrmv}3cV]g67*ѨYbx,{Ļ*rMkkzco @ҭqozAgWVyѾ{FFVg,lZNyJܲÕiczKe坳o*e۸* %kth6 ې.d;չmR$Jw̍][_!gIzD=>53į?38ѝuɜ8(`aﻮY[%85r :cWOx'{bk󢍷2\cE@UhiV@?q?IS([CH6d<WjF OGmp;xV++֞Ζr@EG<N$j#Wtmzq̸N=1lG!P2#5ZKm!`߽9NOlyz!樎ʇ'n::ܚ׎ .{ "L:9@a2U;7*=NEVvr^Y+'"54h:ʪg {?uJBKvX8TNpy=!SWmɞ[97<ԤkTCx߮TU :𒙷[k+OcSQf5XMLҩTxt*ֵ`|@0^]R,?uCփB9hK< .m~{+fI*mBDj%B9 |B)Z]Oqژt^VsصeUPdHhDuO2qݽ[k=n sMwԭ{ 3N4xyQ{F!tF. $Ňϱgm*B~uBN,#όL\ bZ C6wC #"fi E @Q^ȸˍ # ldiU`eشiY<ö0e>ldGˆ$Џ(@p}qMEx*>EW4 v{׿bH^Gv˜zW/mzz9\z=w:^zx\㾧.μ<8{Χrӽ}OL0 O!~BI h\C\p `zL}J;|w'AN 36 PćCtiSJ 3D;מ~Tf?qrwp] 霎Y4:N1^_Pw!HH=E HK'=qKB=L I\U]}}wGNyO<|>ys׎WcO9I `4Duv%Qߒp-[صj`V|Q$ :=;bǮm+Hng3,#N!'INKM6~GP}P]g=14fnDY85&6\]BܞUxWx|OTbQ!OQTT rB/_[ R %g>׎t㫧}.^=;^yqy^y|u}޿NHTʊ@%tӧJR~p0=. B/FM\yy}6sˇ9z<;N]WqzkckchX#Sb]~@ݗ} ;9 @lz27 lG:-ao FK>:(kR" ܑIڏSC֧i54ׁ$.=OaOZb{@3{d\N.Tvzm߂i !t;~C=PBpJ=v'_b\A&FJR6"uׯs닏$G'dlHCyBc ʕBulIσS=:'8s(J$;ϦS찌S*+jvꑎ ؘzYm{Kp9ʰ|c-P9/矞]W $uƯƾU~mͯzK㙷ܺT$ =KȄrGb`y]'ޏ/^]N;I|uckm"`1􉿊EG"5jH=) j|'N[^ uL30P`/"79yI2X`?=>> wҠ}!$IU]"0'J5wWR[UH}2gKSB#N]/^9;^s˗y|Nyp]t>Gxqsӹv@=~3:"d"H! \LCZuyB_H8vu=W[,C{ Zgo<%Mr}of&ݡsڹ>]\:tz=8ussWåN;js׋ä\s1V =s6v·t{ߧo8Y>pnUtN tOz}N@XNlN̅ wӣjZ6~U#ƱUVOhZ^sߩ=qFTA,!"f-uG)4I"ϻV)!y&$VCөm(zV0MV!* @gL*[U7DکRSGf||<{k.1c>U?M@\qpz/?qY{fy0iGnA ngVy*)x'_wΡAU@Cs9W:τ8Ԛ By@$oE?&ոz"RL G!HY4+xcT[[Nɴ|q&…)$X͐Z*󪵕 \W#3MMֵu?:L|S<& : ޙGC2(pTխTذVH\{讯I,I80f+@`S]#8dEAkMƌ"`{ٱ jCD+[0wM9LPl(ʾX+ѱwe^Xi,[x]0'>橂h7_HVfc :]Ͻ6m[3yAۺg#XAE\ద`?(" ]ǬWN5QʞVZNt6ԃM3RuK[Ė7 -J^}#," \c1A;=Pis2Ob=vsMh7 T4pNeZ4"@p##XqEשtt[/q=:JE%˕Yկ͓*CS>;U}M^yD6 AɆshܝS2 ṔާN@7(T$ t>o *}wS6w3֎gteإLdZW}I~(Cz?B xQ# I~n!P= +rlA!M}*QHI"E|_B E?î㼽6{ӕ/Kw|twtx_]^:;+ S@L1wo,vp;V\Y,Ե2B;30 ӘZCX#ӵ:{~E, NCn׵a17!A%Yn.}w*,ץc;RtQtM/gu{f]bm57d^yp]X=Gٺdi[EXv7}=1[]7HeVҒ5"l+ykBhe kI+ɈXstOYY%%ɻ]yq=JEE՝xz޲^caD>exPjH4 #[ W(ⵗX7f]"!3~_eߴ<|}MW޿ <ǖ E1!= 80*xy + ָ>󞗽r ӘjNd?.mO jQ&bGRYz2GtkS1wX.\4zPWtTK- dbQ&ɵeTu2vyI zn^C4Kh-J½n{E2v} 㬤Y;,hν6MenX֞^v{EΗW>c!Y}L k۷V giUma-AVLh]D+RкwQYmzΓ .ѳnaܜ wz x=vcTsC) RAg//xe]O1^E0ο<5a>>zU!-ybg39C?{We`rdHrp;as/ EK Mc9Ո 2]!Þ1}{tyy^ٝr; {†‡ ثmE,Ve#Zb}nkŏUĸ9}U=O32ՏMK`&E "%Vǯ*+3uX )یOVc9E^|׻{֢SY{&CNṃr◸ӲstІ#ishܤ'[I8:uwVn*y/1wdU#wdrvXǬ}9ɝ6JTmoDRE Lu:n8TYc]<:^I`$ n>UFH*0rCs\C `" Rt־-a{+c}čʴ_UYĺFUsә徴7VF="!PsQV*TWj*'RH$HiCc`S+wbRs<},96w\  ;bCtnO:*3Tl%7(ޥ¼ $BQ9t|sM~;*j$H?}5gn4D")ء3[ ]VD6`C+!]AwC 6R  "G2#2,U ^Q\с>)w;:u}oeowlz_]O ׊R}Dq5K6oڂ0u sp?`ji|Dg3q'p)g">1g BHޠc%]oG0H˕̝f]d_8!Y xa88pEQA!UGfu䩇BOM}Ṕo3~uI<]({5_yzp{秧Ws\'ﺺqtsOӮw×-]q'ȇCn '~w!TZ}F:%_EAgkoxb銗j} ~"yƞűƐ G+C{ > [CW*VEʝ_:SABX0{ym>+oÄ4Qpm6s}Gw^OTҁjrmTkA[PA 7|{ 3R.9emb9WsN8YrܺqsruG:q9g'( zHPP'{Tmմ(On5b{oۣhr 1R=y83*赵G}H 2ܻ~˒BN,()fw0SLaXC<2RoVmMU)@o56f2Ы<~@)o_?A +.2IxI$?ol{ _DZW9m*xY.2=n;p>K_RNϪ!:=*NU}{m : ɔ}"W}|dsvaH{>'@}qvm~z]^+cF22?WE9\Im}?Mjy;O^9N']y|\'өsu.|:p||ws3h3㟈llBAC*% :eut֍bZ23HL%}m}+Q!B)y<>==]eAE}>6ώ"WO洞{4Q5Utt[oAۤ;ʒQ Oz\ќW}Kkh T@U'g Bm=2 |9Ax ^vxyʐoԤ|}%D. ᯠ\}Rr濆1# =pOPUZW\뛪߯v奊?H/::<U!ReVy;”zײiÌMТ{~fNVXK&zfw )Kn ''aUQ#Qrտv=fERF !>-'QDZH zW MM(hLB1׃qy=<^.u8xyz^OSus8zW|ڽWq:yz'ʿCK~^$}z |P+S{LNv[ν е Pp`aUMUN\=҈*w4Oj//<"\$_M1r޵msxa'cyoܳf"-W8Go}Tdbdvxo7N\TAq2Pm~#mW饯W͒ O(*}<=Qx^\rzf.:uup{i=Kqr^m+Ҹ8GW^U˜tpy:u:y^aYɳkdڳY-bh*hQR5Q4Qb (Y dHBщ,Y+QV h XֶT­bhhiMڠIm$m*Sd 66F6l -[ ʋdVɰ#i6l$ړjM6lll-ړiյJmUmUMmUJBMKj6QclhmQhFXj#lV*AThl j%[ږ66jFbPڕP[U[E*@m$h+almMME6Th̉im Rl-mVVjղj6I[Ki)[*- (ڒڤUEm"ڛPmmV6+bțm6Cim hVlShlmڥ[P@l$m#iQEV,cZeTjѭTEU6m*ji CeFlb[E6JlڦMlDm"R-lMm)-%&)-lCdDe-lAm mFڋUQXmlMSj%&(l[Cj5֢cm"4Vfm  mEP6 M!(MKh"ڔFPm)+jڶ bSb[Tm*l6-T6B6l3*mV͉hыlj+ƱmB6 m"؛U6M-i,j"KTlmcDcX1hj( Q-mFe-V­6VҔj%e5аDDו +(*$P E *A TEP( @P@@{}΁QR" PT 6*=`׏QJ$R QB(T$%U %)T*+BQ!  QPE$D)(*A%($ TBQJ Uv%!TC'ָ];yޓ;B+u^s*M}W^.e^ ^{OX]˸wpSJO Fl*=ʗ,%"Zk(^{:zܽpp$۸e 9`Kw{O.ª4UDR@n);mX͚ !$;X=nOzPӸnp%.Kͧ%TBiD촱EUpºu S-A6g rܾ^p%sJ 6=6T,4co& ;lw[V4۾$b4FvuJPY5s7N%7 >}gv_<]h``EU$ TdD@S@IRꪘ!DiJPLMF}?n9UZXU]UF()!*DP5K]s0LEptJ+]в2;nb(W"&,b#nQui\DܨF%QjkMy׭QhFr#]{bŧBźZRU*W˚m@2!(J@`SA[# A+ͱʥESik+DIFfSIRR %HF0 VPmPML! Y\qISE(% ]BRQ@ ` L@7@4 RXIHRI 0eI$1RYXR%%!ad!qp @! fʥKRTKK* 5uRBe6GtCP %FRB  `a7w@ea% `$I$ d$e1%0R Iaa$%```XqpCfKL2vR )`0$K5]Re`e  d*Jl&]nڝʔ2F6,md5+eޯ{6h6!)L*L6 #2ImƤm6ܲjV*vnkI:pR0LAa!R҉ƐHII`X@$B@H M5IP$2h4FI eY`rWw1P $Cp$h qBJ$dV\$v!pFFTed6WdYҫj乊Qm5rJZ˅ʮvѦh.mƳ[fT;Zov[m]+Y&ID]v-t +Jrf@iwQI`BnFɆ(Y(-}:Iw7nF͢܎6vM2oĮӑs2uF^AB %"R%!2 6V)Q@@(T2QEL ]B)PrPk ƱrFűX› (PNZV+%6䡒P.EcFwU9KvAR!RF-ʍb7n ƞ_JwWnywq%Ixi&ߏIMN!~v/e%黴ry$ۚW;IΘr.]9w;\wA8';q]іt:wfnpz7]t]Gq̕0EG-o5(cAtw8cnj6.k A+yěn9w^9wuN]#MEnmu1a9Nr(w^]mЊ rܸȸ;짽;蹸ӹ˝.ӝ]wuq nƸР]AwDt׮.Cw"Ӯ$ninwo#=sqӜBu,sgv3.;:H68pGwnrsrnG9wW71 n͎n5콗 ݗM0\wm"09t`&5:Hz=ܯ&bW;\뺺9.E;"sXPF*&yv2NG.ۻk"9kr6kͼqιN뛝utk®spp2[‹IswoU;1:].X35%EG6칻rH1r4&6K+\!sE Ӄ8gu󉯗pc&(\\\Es.4nY)wn*E%E`cWwX hKzjJ]N\X^٦r-tb1r]m{L"1޼)764@"˘,6-E@k4QZ1342EhaDÏk͒NkX9W4kL\;m 0Id 6],j2mʌXnEm2"1X5!bV&ZFJ{ +1DhcWM05\|7ڹ;-,Y2sn':_gvܮ(RTj!+ss n[`v"/m#lT%Ѳ:m$; onj Y,.ch\sNՌTN]*wn!.sL*mۚ)1{^j#hkFJ#$nW6,F,wh2h "nVJ̌%]#GUs X2X&H=y(ђ5ADjJIMQyDA&,1Pf u"I T=\Q$4j &o+h1Q`¾Dsspcb"6#hI6@F#!,u5'˲rHgw"J 6mo%6B RX"JZlTDYX(Jꋴf̨ԛBhWMM:EIIsW#Bm]W#%b#h뛔lRUMDi#Dlj#vۚ1Q1owFH$LQַ򒍌DC1E׵ks"Q2G9ڸ̈Cutѱ(ưHIj7W\Q2bR}EliHwZukFJ,nwfB5&Q "QIQĖe;RE%+Ez{EEtb%VKXCn0Q F bJ*Ž\`XK!h,XuT"FKokȈѢ10 [)m\ط͹zEst#h WZ6bd DѨJuj#S-vDj5&Mn, oU|6H*MQ[dDi$-&0Q W(шKͱCQ1j`D XH4hd2zRXѬ`%llAN@hLJ1Pvv6.Ʀ[(L])"yFfd4b^r@ɱ ${-!FQ$6סlT2##da5WHQG[QF(F6}P[r6Z$Qyo1B%wrbF.vY ڼ !;nj((ooJQ׽tPQ2WdRX0h+t4mumHy$iF(JWW4_wcX"A*uAlF&5]&kS1%ЅrɴL2b\("BQ ^nŠ4kb &aRlTcb\`ƞsFlTeJj=kj$f# A!bULE4̅i2Xa]L(1j) Tjn7^ITMnhDcIڹb#R*CIC]RF]VX1"n$N娣$hAti EWȴ[!X1;YS:EIQ Ҕ[5E&M-6W4h؜PQ( !cQ2 *DQQFь`( 1F#llQIiդ e$$FX_/,FDj4[ZWV椣%\F$-nZ4bW#rIEFv9lh2l5QD3dHnys2+)NZMFdl" A:J(،lTXTX&kQŹrr$1:@d$̓a$Ɉ2YdI4X aEF0Db$ōl[\ŃchnPdŊKƓ)b.u±F4Z4gr&nbш( ]i XQ4u*%$ cFō:[vJ2Z rCBnlRV32Uڮ Fa`]nhE&ƻ[xb1RFK15'jF-]+FӭC vXF(ZDlchP׶dj&,Z65\@DdE$!ldԙ:HѬ݊DѮcHjq3ɍIQܬ[R Gm7\EFbozIc[DA9XX6[%ݙ5%QM]hMbwM6>UI ^i$Ni+&2v`um&s$'[r%h`Er1F(uRI% 颋ErdJAtDTLnr,2uiأR@'WCT: cF%)!!,\)UVB+DFC2",WUЍnQ% nQm)!DZ1mܢ Q)ڡMunk] &d0F65زNEv%BɰQz׳sG4&[GȖQܣcui,vkX\-bѠD\!A%LQK0H kW+L"{F+11]Q\řMkW4ڀ[cE]-3FurMh\(qDQF{o[vi D"E^hbJۄk錙I(o4u M:sNhj붤)n]Xј&ͷD&nE\*wgXĒF:PB2MDD"KBR\Fѣ]W dia*ιDFMD:Ḷu\Wn (wz$,uEQ^n[]`Ͻs0dWۮ1#bUQ]l&4nnbo+\6vZ0M0rmQcE8Ω"CQ3aTQ^ػxj#F!C@:,Q$bkGkre {WzJj4EոbVĩԝ¨)4PnvIDRbݸva!&4NhI1 h]HJ]s[#]j=4c$Aܓr1HLnبMusQ"/msQA#w-ֺL rd6!uȊW1b2Nޮb(\ K$,GiHh0&Uȷi\MvLѹ`X K\EJkcBTܻn͋&kwÝ<U͓$]Mnivj1DWYQ-vڹVSW d;Ra6.ͯ1$M]r6 (>\!һQ]Evl$nW1F& u\$ΧmFduI6eX( [&!mtnҮTX@u*,Qآ-hwm"ۑI$TV* ׶vY(m hך1Qhh ٭] F4'WJzb/Zjђ5ƋBE>-0ynIۨQL'.kںj1'꒬A-"h WH\4XՃ%$V@ C%{ni0XjwuM ZHL5%b*)(DT4:c/Q[mL41Ƣ&ncFI,%n$TcI+0CQAEAŠQna6N5̼怍lƒ/,j,eXۭlb1"j,F4ɓF!b 3r$Q$;Q ت+Q,b2Z4Q&FF@ _*yFLE601&)+d4XI7mr(-jBŠƋ-Ww6-%uaٚ tBlQ`RF#Eb%dn$$PZ$ѓQ̕"b˜HDTT2i)16iŒɂѴ3z&*S,\QDQQIm,`ܠA1)lFLjIdh(ͱ3ȜF+ D*4hخ,4d+$6Dbh+hi7o/X ,FlQ#fdłR%A∊5^X͠ ",lk&k&K I&R QdK\t%3IE&5%,5%6}ݣ^dTD[i B*,Ql#QlmVf1[LܵlJZ`hiyyjE.,iFr2bKhEX *LlF24TFlhĚI6Mv\ѤcdآBH jEkr1E!%DAMQ٢IH#cb"DE ˦KsH%$b`@6,Z(rW.\-QI %5yWW+sl`4gb۷Cj 6KJi7\ vS4Z*v(XެjsF s$j5&Y4XMF3t#&1QnX4";IMdAb$S٥ݗܺuVu$3Nce JTllE j 24[&XMAcFF,[&9+&`A%IyL˺FGsQwTQ6#ʼnrw t^\.Xѣ5tW %Xh{mJ5"pZJhD 1W R]m'tm N] ZY$JJt幫a v\w]`&0Tb5vdלFPc\˸4FH/mviΈ2FMo76EsF,AFkENnNJ Id"gk!EQ:LtoNW5ai}HJi1\+ޱ\9cΰ@o;4G-ȍ0y{E.gKʺh ͮVJݸs ^Ź ΓndL{d8E;w\ 6(R\ԝ#V-ۖ]#IQrtWKnA4nbW/JTt:G9EȈ%nH irr69͋u.\\[\gwrW*2Xp췱t-ҺunLb5sӜFnmĽt+pN;ܳ'v9lmFآ|wG%ݮ; Ş͈r]\ιuPcs۝ZJF'N7.Wvhײۻ.sq|3"DĮGMtz42]wrg[&vwn뱷 &9v+ur9r9pN'Mnkgs ˎCzIt3rru4ݗu9tw5ȑ;(ct:7^Ɠmn8#9tNDspǡkNg;]uts\wSAv.rpwsrw&rn)w]t'us9nw^svW]qr帜9IFw%7w\q:qӣwwqЉ]nw:fK..uwv"1Dan7;sw;wsv{ۻKλq%n%/ws.w'u\w;xn8du˜뮁9tλsvNqNzwusiO;g\ە鷚vP.λ18\+r.DcN0l%ץ/Zt 7`5҇=믮nn{q\/yb9;+vLjK0z^^k.ss]w[rkH,Xwro-똱owm٢]wYӎ{}_"3ΙnF뺁wveXelMXwrѻ6e}]:svӻup睕]qۘw7ua&f&eYLjlݎ뻩E˻s}y:u=s\sy{ w)% ˙j(%R&~I-$3ԓl,sr hץr ڹ幋 64S)L2L۔"9Q,bTE50Asb,k{^@%`REA%Erъ5rFɬ]3!򮘆TII]u9DiuJ4bȵcQrj JXONTTgw"XأDh-EKnk1^Ɠh7-Enhr,Z:6Q$( K66*sجh66+ h b4hC%}{{6,b X#h-If`)*(Mhk&1IFMLX&Ӻ1T$j1JJ7w%i6']lQXIF2DQzW2FQr2lg]"-Ѡa3$*b)5!"Emv gm`5aI-Blm2F 5cj Ť,Q4S2&AbFj6Ƌ-J)+,FQF#E@(ѲY6# PM\LXW.Elj!4Eqj"--V1,U!E1XEwtFœXhF0QTc.DFɂ  b,,AkICF%cLM4Z*McXI*5bڂ#%XPkIfQ[Rhɶ%h#3m(ئ[2f6*L!Il"id*B)1owkWJ$4&ili,XH&j M%1QXԊ*fZ#XE\lIbD[6ƣ+B*-6IT)1Y 5RhT QI86LlhōFIdư6db F Ѫ#$(c!Rc6(&4a"d#$DXDkуX%hHɱTl%PTZ ZBA%2ѐETbJcTj-Ɣ(TbmDmJ 4CE3L1"aF֢h@ML4EFبj-3FmE`IhQQFddԚMcIBRb-BR&lkQ05"3PP,Xƍ`ɌD%FTA&PI6$b)6H6ɣE &FIAb4c3( lV11h%+&ĘѶ* R *L5![1EɬhҔ%2bi)%L4stؤ Q%dԘ &h64h,a =TXؤE16ѤɴLc%4R2T^r1FɱHF& " d(fkd(-`ѩsbPD*JFFQw\(cj(EE,Q4PZKE2Sc2Qld*1F6bɍb4d+V,YbѤIkbZ,d&10$DY,hj1YFRXam4FJ2ƊL)22$T RQFI6CXPX،hZ1Di6E` Z̋iŒTY,ЦV-,1Z#cUb6*q"abT3Qb,cDm 3\5S"* &̉ j6P*$`QBQdA5cQTZ@#E` 66%1 bDi-,ZJb“QƨcݹX&$ƣi6 Qf2C XʈJ#3i 2PQ$TlRT@m(IHhAw[X *hت4m)V,h$Ҍ 25b&mAi*B- h$31EfZ!,XҕfAIbRlXjĚdlhTlj&dKA6M36(dbM@ld({zcI}}-FԕIEJLJB%FĚѰdRM,QIXQTE(466J613Z1CccElIhhѢCI2Wenh ,D2mŋ2ѢE",lXC%&X!Rmъk77LѬh2Ii4bѤѱk$Z %E%64b-Y*LX"2AI ԛa !"6"6 ih$(IA5SX e gnd*4h-ICdE TbѨi"؊i1cY6di1[&XѴbhشY5#D lbѤ6kDEMEF+CBED` Ɗe&b$#`#`UE2TQ6E!XQY1jdZ4Z4T&J1D"mcJQ6mAl&TXh$(2(̋,3d2BEllm3& kd4ZJ#$cA+&i6Q5E$mբ*( EH6di0$21)52!C ذLŋa -(э%&(C))1d`7j(be M#XEmEƵ!IPj2m 0hƭB(i J)4Dd45Icbh,BHUcc`F(fhF(&j&bY1LXBAF"mQ5Ai$A&1kbCDUɌ4T!VDIci `-e Ŋ$4$F`FbJlQHIRhReEQb1`QF46M@4(65Dkl2Zm3hEHj(6446a,TmL$Ԛ"Ж34^U̚+3-ԅCcR+&6*-)4T-JIIFHŴlF)b׽W62,i4!XЛEP 6ƋFhfd FѬmLRk+HCFQ+LF2,&$Z ԑ2b6EIƍIQDlXؤAFl.[\,3hь`Fj5i#Hdi,F g.l hMтcKE&6,@&Q6ьcd4ZJ0jd XD1@mZf 4jɀ"Ąl2Cl$#B ERhƍQbJ2mh $c& (#вD( a1!Fi) A&, iȕ b,d e Ad,QF`B5%(ь5R% (ذXfE)F5l&4bѱ 2Zbb1"`!?Vу`FV SfHBRcmcQh(D(fBZ-Eb FU+&آhI!a6fTTY XFИ(c#13BcBF cQQh1X+$%F-[lXj2ll&b2m&*X(i1a!bɱ\b%F)*1`,dbܸB E^c1I ۅ jJ(&cPDE&1mQ& X& $b2T M((1Uر, klV1bfTj#F̭4F(Ѥ"*"LAQdфd!F-DE65*cF(&(E&hlMRLh-DVA%m$C5Fƣ3!CECIF4QZ LE& h4QdJȁwtQ˻9Y*n;vƺs@{̮ySӛy$osu1]_ݶ٦<, HT*h%$$߆n7\^boXtȱ=^;w/(^޻nwt\}}½5qӗrw\\G5wwy#AsӻN;ru܉s]牠wFYF_( UP @TU1QE-@LbfRfVbI6T[lK[dJű(XŚ[,,mdeeY he ,6EfL٘M4mkEh*TV6EFѩ6ƒUkbmHlZ5[Qbɦ[lZk-V KRR[cZ*dTm&Z” %""4 AmQڊUZ*ִUh6ƪ*MZTVb-[FAJ IQ(mUFj-kdbbѵFZm-U%cVQ*+EEJQUaJDPV Rm5[Fڊ*b-TjQhQjcQQmjƨjՋQkA@R#JD)J)J0 ҄JҔJ2R!@BĉKZMV*QcZUQj-*dkbڋdcjR#VVUTkQUQX5VVQѨV-hEcQUFl&[%Rm)V*Y6m%S5)Id62Қ54Z$ %ū%*fQidiFmBZdk&5dQjƱJcbRj1XֱckEbѶZ5kj-EU %((R%F6Mj5+j+dڊ̵jűi-MXZQ-XURe(Re(5[i1mlj(D RXiEJVZhBEV+,UIh-hՋj*6mJhmEQjU5[lTm"a@XVB (&Q`V Vj*5jMEF(ƶfQ3FRƨ[XũJjMԕKQJ 4c RiҖ-hXJU Ba EڔMEAJP ,@,H"ĨMF%TUQM*2A*@*"@ *KEZeUmbB$J$­HJ4%Z53jƪ-Z1hblV+iTkYXJDiRJA(T"ŨX-6E()PiJJDW%b6-TmZJm)Z%U+UQmXZ-EmLƪYձmclVemIkXƍ[QZ(EV5BAhHFQ+Qjƪmb5QT66,cUTUlQDVVi,QQ EkIX6HړjhImhek*jD1md"FHd0͵$V b6[*4QbRZV2 j[fLک1hhlm0FFA0JC*DĚ"ե&[jIdZ$m 6Bm5[@mMZdFRC)kc& S`ULT[6M1MjR#jDKjEl 4eVY[LbjmPTLA*ȱeZDX͵1TfVњTemKbQfT[f-i5j")k"ĨdhkR¢% hVT!jVjZRViIVF@$XB!X!R!IeFEda A X$RE(D!@!HBP$@  (@dJҭiQb5)#)*,@ Ȍ @2"ʲ(R@0H )*J(+(AH(E" 2B  HЄ’ (B!H0(@R @ B  $2 *D!* Ȱ @(@H#  @Ȍ"0"B,"H  20$0  $B ʒ 3H*H0 ȡ!""B!"*H H 22 B JJ@ H!(H T$2("R5 JȒ( JJ22 JJ,0¢@K02$ *J+# )(@+ B#,# )#*BB$!* ”P !HH$ ) #!(BH J)( "!"HHHȌ 20 B*Jʃ @$Ȩ0$ TұiVYZRXښb020$P3TIjPk2U! Ff$&!e iHEQ66BQ&XթH2֊Ah֓hlITEEb-EEfm*ɫImi1kh JcV-f-bUX0BK@ҊS1jZ56Z-Qj-F-H JP4AH̢RFUVlj2)ĴJRPDTEXճ5Y5h%jJkmAFڍIbj-FѶ-a`PiEQiCQh$Z5*6"X+Fɶ5kXE[maJT(JFAZtkZIf 44JR+BD6ɭRѵFmHiTZQk""- J UU6ړjljm)66ѣi6UQ**CS5-fͦV5l*ii F6hl&mmF6S%M)i YͤmlV56Fٛd3D20uAH( _Z+nO]Em|l횭JչQɰC1sfw,1n  q7>x^C55[UsѪ 9pXc X>WݐٵʮS&zڛMR]OT*5,i.㢉M9@#8H=nXf/D7Y=LijKo o(̤߹RdэnRfwv嗹ݜ.*G6O;5ʹь=];eY2IĶ،OZ]6թVfd[zB%ba5N+57~Tk\&%¶5 n8!Si 鼴4rm-0GeдXMS} |lZΥDnNF{pml.hI-8C3%Ϊ>](p9Sx¢v4"wK9f tÅ\`Spm J5on'|.2!f9V+,Ybmib[nhkиLu5jqTZC~rPbӶ@` {)$Ff4&Cf!_I[Tq@yb X)acq S␰*+CV&,`Q WQ .# 2bb`xSAeMA5,!jYp UC3Ocw /M]NMGrx?wRw ٺ͢*U>R\yԚ!yL=PVtr$69LZl`ͻ4.ٞαzw-S:"Aw,u~'-J;bP;ɖ]>:rTڔZ2pafls9kX}SJgyLUY֍+j΋;v8[I|ePX-ڇPWMrWOf "l7QeENmF_UjtiۺSslPRʅuUQUpD/Ya''&k{½. z?{0r<J,(߳e6Mrv䋊uo+*F|[.Lѝ(Z. Y͆nhV(̍ƷݰwIC;zrШPbr2u%üҎo͏'Hh2H&_+fiXWF2Xy&3IM]ܑ.h)T4OA11KMB.m`=@̹"ˈqf@OvquƂʩy-|?L(qz].PNwrd'K>bR%'}Rl pV:hU;+<244rԩ\Ã0qos8 C;}TBQnGrݾRZ,5ԕB!v7w-P}{uz KڊjG݂fzW׬kwq݈=QIzkNh9ZT#/pl{&qb=XTW Fjzb&hr"簚v)fJ3N3n$]'|1Z:l;ڎ𻰁:e(Ӈ]մP1)9AqeDf]HG)gaޝϦÜ-⩹^Ŗ䱇 e=*Vܝ]<;>0W_|uM~|M\hTv{6\2 2pu)s^kOA:ǝŧPN >yj}MכI+#ǘV:;6G#\خzC-cY}gP[xpp:ږfދ5{ߺ|]OS^,;49-Mݫg>%@tpl~U674*a59# vum3D'ūSGTރ`T5\a&7`Uܩa]-tSs;34!mTnՊgN;9AқRZzjmx-lA=^&,єb m,ݱl\q26^^ < NM\:z>hgi8 _c3b褽ܳnfi'&^JVtcW3ӥvU1Ŏ/>7vn/LGVm&:poz»aJC9nvVbւ9}%Uo鸊 wL;`^SAuG!}d.xYNvJ\';mQtuV_%nvJС&spF{j*WZBҦNnc:s#;Erkv;޻. BIeo]:TyOցct)6bKoӞ<;&-Ц @E֩;9dBVRw vq%JJe>r3q.Pt4ꂯi}еLܳW>2b7NXzgsl i3:m졁 GVeB]TF2n7Bq@h3fj">П!^ bHEEe6:w< M0ߪtg˞o7^{VTmkmE\0t5:0dZhJk\aZ{r?QUoHԛUz΁JlnM4&eqP$EuwsjC UݱTZUPM(7gT=Zuo "eQ˃U 1uزwfp+|8+%/G̿z诼 jAPE ,s'M$s]̖^7iwumYik5q}J¼:7=Uy0NrN RL*g{a |B>7;w"u&n>::9^t~G`+G$mwwQӾ>~ˮ6md32 1zޠ-bkT n}Ql=F̫ b< b+9]/sc[^k+tpQOvJE:f.=nZJz1O{){#B4]K.f ݾ7ɄR:-XpWYĚ(u=O-1&kL5m)ƻ(WE/.k{.N_\x_)kںnn&WI{-9Fԇ^s7n;LYP8Un,4360u:n>2noI 嶎щ$Mk޺{aOeͪTYu)7F'x{ڏwpVo<%qV@軯2 Fd̆]".uAȠ}wI]wed䭟'Lz6x\Mg{^$to#giW݁`6)} K[㧖}jjnђ!n$ {bᏊ*"nu &vnTy*Cݢ_W! j;{Y±I\Na#uį#l~n7{_!-MRġy $vBp\F}2;POauRɌٺxXd2Z:^Y&;\!f mNAU:C-7;c"ZðwN+7I/z)Lag*)q%g smw·msybFxJ aӲ Уc{8kؼHwǰ8t5gKB+(I!JͩQ58*XfN!\խ^J0eۣJ\e^_vSq  Nxf0 e[AGn1Q:Ƣx;w ْERyW2ڬ=.ܜtdbb*DeH>?j+5OEJsϽ<#kOǕ{4߀Ӊur^k=Z3uQYkQ{lN>yqԕl5zsU֋1]Pޣ1l^[mfSɜT2J*2|! Xpt$xvH bLzf{HG_;h>Cf/Gd߽CƩ#]/GCICݡLRܦQXi]mDL؎ew8s!I_wX{}2Z˜MҶTR'[(mhb. _Hs411Wff{J1oˎ}&ۑ} O{5 !g ;fxZX[g5)&Ru6Lhٵ;Z:_wA5&[sfn꽛fʙJIbBUnC]{QM}+XzKDk^Ly2>UD 3彫ccwWY]kFЄN8[\W>uQq.ɃaS]7C=r][%Ʃ:jcw zUۭxmǢۛYK۫0%. p˲Э*jQ{3\R=׃JSz` V(ަa}[YawǬ%@ﻰ^!Fv q -3@ƍ!Jn4ڭFo3;zPd‹7T.9M:f{Sק}\wՒ"Ya'9\_$xj3xb0 m V/A^|ϴm.b74"OvokB(/?:{qʽv3!3ۻF&yVnggkpgen:tSxm~g<۽18v#hcG7zx '$܅MAiXit 5Ih|#Bҩϰ\fz<:+7t2fas3!~:\#2 !TVrӵoqf'FVk:L:Y/W}mʦVc˚izd/Z9G=˳wS=7h5G`,n%޵9 WɻU*\פJ!I-7 ݒM\iʺiuUndNoV.0Rފ=wooWh?<ޚLaw&Lbάtt,h22ҳôE[s;ǘ6n;zyO&yZּ.Qyl/9e\+6 6:IXijH:GؖS~4y7np{3f5^&8}rDF( 醙t_Ahc;JbW}]uezs $2x3K5-7) b閭eu0i#&ma-jjIUUdxqp3hL&კ@亱c=]OcnC3rqEٞx(5b'cд^U2ѕya|;jMu0-@u+k{ .E-EB -5ޮ{t tXRsptjcNd/\;*Fuvm,^x 0o90h\o.2C =0q 4}NQZߘ7 kx۝V렌4f` yNJ%}YFK8&>\0>f谨EKYOuSOJF'HSSfZM_oj] uҲdƺ<`zljGeAhF1;[Nbho2ҫ)7vׇ^wAMFzcy-t:o]YKmGF]j.(ܸ2u-gb7lee]/%En!"Z| _~#DŽp}Q<Hqj6瘂RmKWCxr쬵ΙXy;hXtyJzQOx{rx6N\gvz,bC# iɬt^z7`ڭ!tG}~լe*\ҪWrDچV[ZQlWlɶ&IVkеhӖN,Ι7jcqeN:5 毉0;KwTҺ>STyL`5AJ9gs@sUlK6-jҖ¦淀Ғ>y 7:= 6snU5{D }5C%:}[h+nf<n $W8]=xZ.s[ӗ\E*]}jNmyƅY]rwvpxT֜|ݷnwRnk}kcPGr#y]TLD|{|Ѳri{m h!p=sn{oiQ:VyS}w|`{F#DkEW۟7j_Ͻ7HzL/םYTDb iĽQ-Ce%F>pL#ǬصIX׺zY_=a(KVMEt9@M=FBU!cViFۻeOǁ`Ds˸o֭{ %(PT Pw%:剡obőt^Ԕ GG0CĕV3Js77GES.6^|N-uJpc{; 6갓&2ɷy'o otB;*6w_x70DFRlSxm08+9SM{$xnT]9'Sv7l^2I9يGXp6 m=j 1;=2Rv;-V u1u)gfL͹ZÈ8 j1uu(B)GB{qcwZq8` lb$B-Y{cMh3k% 1 mZVy%kۀ4iߙO@^ͤ/ *SiV} P_zXZJO"}V1k+:z)vy1s {-W͝,cm' &]Vg5{=? zv^SZQh~A{lOoЭddut__6h~ ϨP.B[}.rPfw:!ǷЦN1 :auV6(2=ƓU[ Ub_5詸.G{1fqj 9mӢёLyf.3[5X['¡c=5+-;D>'v(W$x *YiTʋ >[qyU@R>H=D̥;b hX_:v}~YVSLW1 nBoΦp,3?}8cv 2{RgĒ'YvfO# q Ȫߠ4O_ʈ<3/@>{byt621< K!üЁۜ6) R#19f]3!X]vh6cT0 '7T^cZ(wmqtnSeB(`eo9sA<s(+jz}Ӝ9vxW@}M!9Q|e@߮smcmgѠm['ק:;`| XYi, B$" L*‚Ė&SVIaIᘆ1n`Q P~">_Aʛ~%@*<"&' ¤S7 Mh7v8 *$\ #EQ$,-A 9Ei.k.08%0"q9It4t SP@Q$wNX3~Z%t T-FGz{2ݙ.cuTv+%,ӧ^cRזIW{o޾x>,v>h*f^m!|7/ < fl)}ҔB>5rArY.'3:A1yr` TPߜ2Pd.t&o**U G``hӖ8- P@ Sfb8 DX&ᆁj8ikhZciA,j,SRTTU\D i%|{zNPX頪 *T mlJW\sͣh=ᮽGv_*9w 6Jwa>+xddg.Q]C <Ҽm^电ǒWJi ~(6}@8Fܵf~w7.~{sTCH]ԚB&G 0ӎx85uq450t CTKb4$&`5F&!I Uv6*,CZ}ƏWj `6!J>Jm9u%%aBBn#@ bg'Л_Uvu[^GB6ڠHz3n~)|*ߤlH(xuݜ)lS}6HZߗ[sQWhwwwJUj4i3o˫~ ;矃CPV%ňYeGx!uĤѝ qFa8f8@,;AUv]WώG* dQ{5 '鷱V{,cp2j_~mm{cH]kMc { 2t]jUVyͭ5|0\PB6șVxMX2DȢ;_aό#lOe>F(yP72sg9 R%)~wZY1Oruک}JPzit\R2رK%I X5#Y.H!YDbU,)n4(fᖥv#dB)PZrϻSCsR&TFC 1[3mp<`G@ *ᵁ(S= ݬm3b@tSj^ g|d/9:DX_J_ӑGޯR|(#phcD@p|̺t䡈 >q##/4ٗ[~XUP*p攧x&C&Hc&8X],I\K p3ԈcWc[y)0IPQZx P?s31^NW5BŴ=N4g|}|nCa*#S%"ꖒ(zxp eErg- %>pm\'g|L\thVUT{_yyuOydcG|>RĖ e3KO~LK+PD2cq=,k葳065ʍkU=S5Luu -qT !U Hc.eb`y/y~ٛh;4v潎=b[{[Ղ՝%*jD-*w領aü@vvk~V8dĊ!1ړ k!*wxIQuWQ̽k9ȝvu>|5LN/)Bz Iݬ#W;!xs#'.kL/Vma3mAf@Ty'gU]ԪIxrqB4n3!7g#|zNgE K"עn,n秱t~ZxLǽXR=ŵJ1h ̛OQOxM/9*$Džng9DEgC7p58z-8;kf*\T2";${;{S-շ١GkzĽǶNj`u\yP[IKsc 9a缒e@z\5=Ye Ǫ,\eS{;X۴ n ,QXY@Xhdv1,M{01mi2miobڴ&L$KQ^.XֹP>Esw;{p;*׍Tc}g|LW@.azgy|%ft{6[@syJ_f$~57- v/]Fzk.eXMFpTX{)^y= nzl)ٹ^AৢBZQ%qiUTv.)V7_u y.-fqQۧ6Z8IRݨ/,VQebBzBk<{U%'(6稱ngn^zʼwSI9e_DzER_e0$npMۍ) LvENiSu;y^ܮ6ӑ E%ݘn7Cć([kk2ՉgP9&Bx;u  ÷]53. CW\nTNbU9-E5U]~rXDSK%ḑ$/EC zh1 GG!gY>&/=>/ ~1L=<<;xMEYӨGō]*رw}nŻq[,:Y=O2u[S|O>7V%BۧeU?Uf|N+\#Ǐdac.1ׄپ5tyBY77T;o&/-K,{85"ւ֌=khy![.(wd sw[ꗫ:P[_[F!ܶ+G|=w#[O^[n zi,;uou:7od! f+*:o Mlz2sIj̢ t۠V[Sdž9w/ʺ΄ω*lѼBh! ԑAV[ τfom61[ [Q3HIf[&+:7PG3t,}P{=7ro0VѼrXCif}nomh"诃ی_yeܦ?z6+;Ih1%Z xpdq 3schv:u®9ǜ$/,um:aS!YM8G_gq^:zpB5 GU/umTioTܞʏG)?R|23;8Lz1Ap:uTRIerYFvS4csdmᇺRT1PZIڻ|nz59uOe xrq=gNxgUTvc$OD-ELplÛKW:nY$4eaرɵ26ʴ Ҹt!75a[gT֗oݷ[-D7q43\O;p"aκOj .-m'1DPxw8?OqXӓxw[bnNZƶÇ(t`FQgBj}n7 <*߹UIUCd[-g]`OA7 %)7g & y4Ppyclv毑ǒudkoӢgx)M7'}/ic> 昜wLY^xJN9&0桃|WՇ^9.=yQM :qͬ)prT]u9\i>ލ2 16M+QʃUQM 㧋=E`2HPFT|^63P=7d>))1zW &;;D~@:d'lP_ iFd]U/l' s|Q}Tbph3sξO8byu [N5f3nY2V <ᅮW }qqF{=-*=Rw1R-On 6y[l{ Sg//${P0F:c Gs%#udP2_A؆r67J,h Ve<+Yf+n3+Kn_ +rÒԈ.) Þ8{$Sowܴ:Yv0SfLո&{*q]l=|yW]'+q`Q=Ui*8}X}l [9=U+s2t͛ToaR|AzbI)TnUK$AR YRL,;mȻOU7cKf6zB<} mʒY}u%x+m!KI}'vJsȗ^49k78qh1? e/Ἒy;|[ ?&[# =y먙,7\.EW._ &YgA;y 2xaI;\c;5&[f}:fm=vcj{7,&d&7Mb 8Xo[b5ry+/5 v(O:M8[t͌d7byݞ|@6puHlƨN=}RrdG )+"oLJx7 I*v2b6<]O9=rL/ xI8W3$4Gv*jCGP66 =Laܪ͜*Ӂ_u>a90tK< NpⳐItx掃(4:o*=r.Q'_w/B6P#`7PA03ugr2TybUܷ1nA)*T 9۩RTYrK+F3N+9&=)ŗG)d-M\Ma%0b4 K'Su 1iD!ؕfG0P-͙ӎbgtTp8έ=7g;SO+C =shGuVΏUӖ1s;yO#+lvb^/o{;3ݢ"xV,74{D h-ף٪猛N賷~9mXS3Fr3\9kzv|#|Ǝʘ5˫ǢE8TE=ejV-vUӎ "rpTyh.ґ,g|{{UyM.4f4UoimC鬡݊z+ˡX/2"ṣw,NgU'z(?t`KDC旍Glp4NiWkԎ [34w?+*nۿ\O*'堾jwQuvFM56Ooz9ҍJȹUrY>B5Yi= byvqT햰eVγ6JxIL?=konUJ yXTufq'{&,茤 T. ۗYDPD:U9L,+9WsTuulivSBn祷=*)f3 :xq\/o*q[(S&s_O g[rn8dR)ZƜv7F吒+E3݋]1{BN<(=ow?Yx9Bcr- !z pjمtRIictui켸;p(]ūhu}-S65Vox@.rk/Qx q)JvL#| &a>rԽ:FoT5P:aT9TΔUf=UMpxŜ=g>vyǶXzm>o.ܾѮG,w}.IsStxiY%0󙧶Y^T1{qW;-i8QSO^}Û67QgLWn{WM-k'Ur }xla1%[UE$Ow{(.d|ri-pܔi"ISVۆW#/d̻m uVVЈ][6Ng?OfDZ˂ )L{Onvpr2^:gTFaÚ\4|׼`=o{N-ݓ`޾Cv(mFRf]m%۶kS[dxlq-Hcqj;۽791À]cw0tY0ؑh"|^7пfJ;Wܶ=SUڴ]ǹ<XDXo% n Vjf''"&/3ttP:FubVu\gY)7бxe`r8SayzkKO1Qj_;2^v (TG:9~J;h8>-OPŞ]9D,AjLEǎz N0TVM)Syy_]!ađOuCDkS hj5h3K7wMO؂֢6L;cǥrcDb"լp5 \{X6{_:A6~Yx0]hu xu|޶aGcWun+7꘺43vmCMwtp Ҝ{`r]k WunP떟>z.V =99L^lfK[ۆvԅy^v }$ Xz؃Fx|?nm)3P^bV}Oi@k*u| /Oǖ9m<#9ŘedT&9/[9A5HTz;RNuZF0vt6=Gd$4-:;9V<*齳Z|BqIz*8CؼyfU"[pog7F|mowhΰ,w[sw.jZxwIC,6:uAT[SQwy #qƫ.Bx:) wPػKB3*>po_Y-'€vG1fU^gtwxS͊E=eBEm.#@6ct]2zptJ=XP'hw.W!Øx2ʬ[*Ѻ%y 4bȳOjڙgH2r~q]IuJ..ӎv\W˧ Y*%-JfDEbTzBz!E|h %Uf*\;ݢ5[NUdU9UWsDڀKIY3Ңi u_mZg{uxPVOTPu*6"Znm'HL9j Hڀb46vD:TW7[Q}is/*Ao cE ܩQG1 R|neUzn6 Qt sN=WstͽT1i!-EJv; ȇC5ynt^ fmcoI̖e?Gیr0EHrz/Ր_i (Ѳi0ڹK(l1y^Vċ|d-+ ѺsFp Z# ۙ&IjFۓ#PkZTOtūYALr0#:{޸%$n򔶲Bx\/MJFN-PH❐ΛqKw˪4njeH.q yxN;sf'Š3]m "O)e]0Ô * ])=k{ԑ9լM q d˂5 Vv Е{RH|$QiBWĕZ۹t#[-]nTp"| -ZF7z'{Y-}دk ѥWez%=,:-3MMu9;rCҵ$Գa9-Mp~=Z;W3IX#+1eemu g}}HwT RXǪ>y#x3;mb)JTqYp(a.}Rǧ0ȷ~$dyOBRܙ,PL4Pвl{N8PCr ⴱxŇRX{ϣ:iӇog'^Tѫsi9=Q)J(h7^fU["Sɼ*IdtqY)j-/۳=2o+n yB$vn/Ea w,[XF+^Ź}2z9l^d:z>513ȉ]շ=X YpjB䤑k回{'ZXLկ@Ev1rڧ;|^a]Uz"}yEr(ƟxD-w(w|p1q*ʆG5d.>ƽ775sO68QcR sU^*%-+gLh;4'vY# EōI2zVB&l/i:\ikAT鼗%6J#`wTeQ0J2Px͚ /uصx(ӝ@վܓyw8KJtkIP®2-/SɫtGBNė}l%y8D1ԕT3 C$f^8WWCh^!Q/ khM^[;w)kƹvXPDg]۽C/nu`Muz\wAIwj׃;wɂ.<1jgjͧ5=Btrp'/ N*fIkPMa盘v海)VJla uxdws!o2(7{řo1i=Yʹ6Fc{y{v14.eHﮁ~zy.=»9lk꽑G%FZ^C(hPV) n$Xݛtݸ km%]u{#Xӯ$4vL^},/ ޠ1J-Kҽ~h}ѣ3A'_Y/e>&ƥo C+U޼}ڮ"mBS͚\Lx>tj1ETn6yV Zez&-p|ryiUAeDx3baz5n\@V*siڐ]fЭg`Qf\4|nnm(:Wk0*U(w7,!/˲FM=iӐp|a PR|/qOl&I #طlSR0k-(~,W;Ց8')7:3#uĒ"7Z_J"8Rӿ@"LQȐζ {yUG/Ft8m3Nbg(|17%}n¹٢׈$њ~g|\J@eNj³sz4>x|ݴTu >+5CT8͵.̩z2eev5||>BmS+ӰhR8x p:{lȳSu,TN ^B[G.3E41Hf̂x׸7aKFg>*~d{UקŞ>5d?{߷{#f)G _~~Xo)w6;Zd۝e@tl8R^g>_GOq&^1zÓ)ok7MX/(ִEuFTzs uxp ьZ[L\7^ҥ1fP2q5ν 0a*c8rᥕqc%<"rXV9.և(1Anup݇ZOc PY4ۻī[y:T;wzN[{r (bM; f9jfZkKyj{[w긕;Cۛ4V)$LQ-̎}X9>j+߼̴]\B=cWS:ZhyUn6V9aONp )9d-U={ds]0[4ıo=ٸlY5f}A#:cڽU\ůC7P7uI0귎S@ave]/bWWXp} >\SZE&lJbKiBz3w,TMtv!CCcoOE`9-4+C"z`ZpP;S$ݜw04t(:k%x2 ^s{9k*!Ʊ02N|VI_RUﱺؠv-omN ݘ: Vve0Pnt]iȹpY!dULԥZ/K%I(|BpL"%1pS\` ,T0e.;sxM# 49,l]+;+D?PÄHB eʏ,r^9'8YH,˛LTJ"7hRkLѭ MGYĊ>+0axɩ}}QŗwWlL}]l ּ}LJ0m/$ABpLӃ,b=/7AiˈD1Æ؃(cv)fU{^TTVs-"[z#\'X&] q2-K3QS5 v)YKys( =wԱLx [Z8sמksЖ;|Ap@~)'COz9`/sDiFtVMz1M5u:S&TtͳwRwAlrgs^].mɯ]ܐƗ]\| 5ץlywfE0ZRNr:;ɮv8CbNg72咍vĻ]sՊ3?}(!>*>=hv3ڀw1QJpaZ|̀+3ܠ(}<%9gҴCGӧӺC)K B5Rb+0]>;VM/9@%\Y.o/30BvV+-1 %[;N/,<K0fQ^R#K_=kz%n3Y}qV 9Uj3)lݑsPc1#6{81oF_t~Dy\P Q.OPpZɲ7G3g9~wdTwjg]3ʤI.'. ~z׽YM5 >pӍt;fj>U.yݘvڼ$4w ]թW^;0NY4bk+Uۏ'ZڪmU][A7uQS3e@GB(/V.{"F+|I9o ]Ve4SecO b.eq]xuKI4.YPa2e }xRMrtMO08SH7Q(LwW= ֛5` ufPX\Z쥊u,r{0!x}ly[v\6RQ#,TWo;=𩻑{&.ޛ6Ca:+ V+KK815Zc rڲM)Ғ<ڨ-\:ETar.+[x2b:]ܺ$9Spi]o)opyUmcۜo]t >eZOC;s-:JfwZ[whA-z3nB^-']o7f "S:-۞ BrS7}xTbw>˫3{7[%yP1YU]bDa^MdU-kQNJ8N% ӝ>Z?@:rT J*W:Ӯ t"ի㡪橩XD+c,agw6ufDTD5\Js"s[[ߑᝮ9yW˚AqY;v<<m4#x]zΛJ]wj"!fD3utDgv3 gL]"0f .g5ھ}u$|gSVz|Q{FJB Y 7%,}2oZ }kә9_<noj\<$Ѯ bՉ)>o< fv[˔QHQY@bݦ̪uǓg Gf`}8Fzm3;<:qe!Z;^r sCN4v8qWK6::NڦFdkC-_pH/Շ16-b͌wH@Y}_|ǨAZvjZ'þYiVQs,""=F9&o[Ts<5ԢxWW!4+bz4vSw|8ɔJUAȨh*1Ց|O>X0 A3OgZNz!r7rZbd"*Ӗsד BsIeu#(zV|&n׌N 9z\s۽ȕz2;yv1\ʋbaoӳ(19W|G!''uv^ Ւ\˭gJ9>j}]YL qr8Zq[Xя<ꭋt~Oj]ͽ=*\ 3^.] OtSX 8Ǜ^!q:"8e4<3|+?p^ږw,Q_1ޓ;AM=5CE= dVvLd4>ٚ~dE9ovԴr6SX]Ys$aOYzސGx;PEljُ)rx1xAy&Z.-}Wgp4M,"ÌlO(<9^]>]1ƘHDA3zk 6yֺs[*$_e1+[4N /u1܋ &g*^GяX++to;7=*'S6LL)Ն-g+<Ҟx\ Ёv{yz}圗r^O;Jb@LcCM~goyn&#ͬ' {Z^|Be9ؠ~p05#iK+rZsigB[l**uE7#q-srrͽr7,pkU;uhe%QqTz4\'Sn鬒&Z-'U?UX"F֡3p1HW5L!H#b)77BU] }Q|C7h`m].U4LOK\dV-߼'Fe䀲x;PW쐼4mH3I3Qj:% ˣ"m"d5N"Qeoi[i *psJVj`UQ^u#;ef>jg%w ^,-ޚF)E!h\QxInu̫Y4_ a`%}h1CwPp FBT<' `pL=6=.kNT8ceW>XC]Q8H/ct]2gZ7r_;2W;G h+e JuJJHR -}JVCFki΁FKR b1P^n|Ϸf֌1^O᧜d޽Q3Y 6i{vקB^XىK"Ay).ƈB~lh(W*T<8o CVߙ^&'T!SdpV`r} jt$Ս,;2<=N̑t^ qG@Ǔ&(tϴ/#h{[HEBQ6D0-ꊔ8 (:lH0Mi"`8+ia@]S[R;```b1DH0TLd;qh zl/lyHZ<*0!m;eR,gq~:5w>yr5t^JtHz X-Kyn{ŒLl/Yr'GR#]Y !;Ug՚qyA0#U@Ve6}'}Op5eWO}Z ϟU^QNyl!1 w8\wKAc* - jU;B-_g94VQiUGvi,,@,#g9H=là]ԂW)]kOKAk&/P>I剟/3S'_U>ѕ&8s׬c+c~i ǙBaVl{ ᅟ0ws:2f΍ќ5Pkf 8 {պO]5ehNUy\o D35rv|'%9uh,Kh2-.5ЬysE)= Xf=DžKFm"L|1uqi]=/ 87PASGN/6~aBU'^W&΢$s14%l sirJkZiuw{?yx|hN_nhڕͳ2(*Y7s#QjvHrBu黎eюj ru7vimrVaٲ]6!l:]t|zjko`{}K0~,kXt`& 39Iʹ2휪M7-t4 63W/aP!p_yA;FygV|RF2pHq&^NP'/&ovn2@2"(ɒ)~;'C>@}ҋHs_ =*LjQ/t.ϑ' 8gU#^Dʺ i&bs6{wn(k P kYT騔5[֍cյ N6 b.zf~%X*<㒑 WA_W=a-me|~`#aA|\!#I_4rK齐l WTeP`kG<~*"ЂG}#k;#oc_J\,ƅ 6?fsFE6ߴ*Ff@ti(1M@YAhuALsMCTAВj/u QT 8wH \&-`(kh8/*q>o{dFȝǶ/b嵩7y~򒍻6NHm `OٖXxydwb;I!yyT1s#IX_}K̞عiҫ-ɹwpOnww!>7O3O!-SW?97n]Jg]UI©tM L@0! n8`E(PYK*4,5& bX(6 0CժshN4)Tt2 i`}P"h=֗+VN8RkK_;'X$ x@'i lܹx,L>4(b6)b2ō:ꇎ'CV9UʣvPs h(> >b`>֫i!0̩TJ|W(# kZ(@T0%cCiQ0 CwF5QK,&I \]QTf i ɱ1 wU$Bݺ؆ E6GG3yZ  STJoNY36ҕ/s{pj]ate̽1;ׂgX'ƹAB/ؑzO>ލUʕֻEʒ]fc,O3=\u-u*-dLjYǰ6BIxd!QTTvc~'*~ދ_TʄACkX 6@1v@10Lpb8؛Z SBH.& UXƐCQ2ŀl-)4_K8-'j% [FX?yNH[o~ t6C8}~[fb{Vi0ԽaT}7(:mj3*x#/et<,$^gڧs_Lz)A{WR̪뻫 \)khRoPSڣ@7vcK4"LL].SCLPApp+(@BtҚ "%uNEuTWPַhvnQ)*;HUR%BMla7D9Ojj͝m1h~FOnKsn Kߏ!._)^-j:󞮧xCS|<Zb}ʝAD }U؉ _>s|D?c0-9`V8Ī5!m".#R1E"8!h^4D MuH p`n,rv"0AA"pQ]O6d L(2#ƒ ȷ2's6\%:AYK|\ A(NݫT}GGvfn5=jv``%?+mPN/32!N6U4Uۈ-8O"@AJ0B ' 5Nsf᳍rɈmA$jKp|1  Hv!;@ww77g3^'ۈ"w>C>$2Q~&9L bQ̯Axh 츲f<xw,0 MG=7͠9_ǝ^N֭{:"\ۻfbXN)wq]A*>XF>\:YT. eÔ¹SL/ p,[d_xYe'{i0M_cd V֟,kN1éͻX{{0*5MUUT@KFHܖc:O잋F7pY"a:,x1(ƘıϞ?#0TeF)Jqz@X0ꁚq fbbgNmȸMo0 QǓ׹vL$̢scyA'',@x=xfxEQYNB{NO_6=3PmFR0/ә|/*raQsbs9}TLO*'50lwtԮ=&@:Zdad />Y^F",0s`[͘c1;ݗbNF}TpM v>ÙҡgC <pJsr=2;B6ϽyWCyؕX}<[,M(b@Vqfn7[q/_ˈV!+lc\Yy'KOt[MέjPv|ȑVa^~Ǒɏql /`˾bh}kiٵS{~ vY[3lzvf |磚 zqy'qi1H ̧HiA g꒻o&z!>d{xdQsǗ\d"ݳ|SNVsUv36tv{D;`M':c[TS"U:^c +oOslj8'M!pPYgoxcۤ:ʔ _ '~ b2KS[mOW^yUAAa{=:F64O6cĻQ4ua#<2{ #s xS܆V=L<|^%9st[= &|)NJM[LÁL"oQv*dQڵɝںF1^ΫrV*i󽷷 A*\*S}nդ΄:*ۚB*˓plphy/1݉&F{^׽nn+3Qw)+ #AKQ9()2}ehrQ`otY}/r38eĄIT#j(ƸZh3S;?aÂne_yrKV ׻QLeӆJGh*\f5+Ӣ;&(\k*'U`m6*RlAǽ+!m9Rg+}m:1 m銜qFA EP"4zEfɍQ /eÎE,BToM'ٞ|CA}=Y#I:7N^Qq#7e h昐{#ײ}ETF.'z- sU^5Ԯ#gy-o=Rg}tk(I !]v]: eJT]~ 73|e6쿧نG+ <]JH'>[4N6XԫƵypVY WC =Ъ44E/׫D^&ir ϯ'BNzm@тyzɐdv(#<ӒPbB>|TR|}ಉg%mKs>W0@ave˲bք6fWL{Z|_ &Nc>f?PR'L;_*}-.;♃R&b,Xb&! R4Dt- Ak0(C`beQMPCCr~u8~ߦVR v26f@)uqnQQ(tyVgwj_4ExXx}>tªw1/+g.>{׵u4 7o?uyr~8$4ʧG:hu/%W={У'柯7ss ~62җ:=+="2>1 0,m&`Ha`Xň `1ı l6E\0 PQ.v߸sۙ I@~ C*?[.EIl1 0P\{-%^i=V*1Ckzw*etŃ+SNϩ3+}Y,b\4b>D~6Yb'N+zaKFִsV/P|4y +]A`r;&gqH;UO|\L" !cF)\) H$VT!C ȮVDǚ0 40pHc`XT0(8۠5WE; r@hu=9(mE 99܉)&_e|0yOC8}\͕oӥ;箚Q[Qõ(Q6",l F:+PO3}⡋[Oy[wit3yɣ}>73'4 ;|}/S.8C&!.PŊ.CE&[%:-] %уDd\ 0TL ݽHV^qݺ J)_;#)J=2O&e󆚕n=Bqx&y_߷+9>iZKz3WR+R^O*`]ĩ_ ǧ >'uU3R֬['b37L lv~ߊv9]MȲ 5T;0;q_5|~CfP WDx x L6MbcXϾA!]u)Cҫ댟 َnu3אAp#, y[ARz Ϝs1>+P7<;s>4 `¡ .A DF)YQ`.jF`;PH+5a*jkfH"j#"& @@F bVbTSP̫a33s߅.0Nmܤ∞ڍ:v}1&RoN!EȯdLdSUPDQnĨthu8,ׇ~kDA0+Dm]ʪkkG3rJ'9؛eENaYEg*R[YvBvdN€#bPly2y4:= qI|y_&׷Ze.@IJ`%V%)x|,Jb`.cu`*xYQRnaĝ}"akq`<ƽ)g\*]wy x¥vo/x%@-C(xi`i^򭔆ts/[mSN7c՞fۼHRYL} [ǀjֵhy;+oLs׸6GaX՗궔OO_Kv7)D cd=oU)pT4vr۫-KsbK =a^c wїթjې~ AzNy8A{bzכdUys"cq֣L*º빺͠%\[&&jl󀉬xswy't8G ױZTr"zU9G+͌spS6щ_b:{ܢFܸ(_&o"Hn^9w$ #(X^)QȀs%Pxc=Y;xo֌HWރ-81^ /V৞. ˲1 v?wCLDd>o,ry1 p?t 9ҮiwU׏R$kd@-4y%R*S C'heA^Y*=J(ݶ9vDE' V Ts08# fTBԃwBLlcH 5Xb1$p ?#kts?Is?S};5VS2lh͘iE"IݥAFx꾺FɅjJM:OSܾۛ%E|ɷU]+F\ل(|&Jr8<1bqW58.*`0Fi쇹ydVBJg޹s^ fpulLN=V{zi]Pl]O6ueD:QjYiD a3wz=dFL_ P=Pa&Et$id$ eXH|yqڠ-Ұ5FA#bË*qVdN.LۙkvAMnz>X #+s6:./[ٝ9R&ўCm.Vaj^D{xA/uzjTV1{/iÐ(YopW]9?0ʛ>7f.Ls÷:^H@ָpzhx!ﭕtaILD#>O&RǬLU f0M40Lm<uw˥ +u}F眵 D}jN5)}|,G,tR5ZT/cJSޚX./[,GG!gǐn;nv'}bYک%m7!cY9 Pܾx}.%ns8} (c޳ D VnQ C(y(/1yvH1 ]BsK׸Py`}6&f^me\10JXR'x:`Yi\La!gYP}x@x}ioe cE*%ja Tۯh\spSKk粟Π>pޯ{ cC˭8+*NNoJٱyH,{&H)Ǖ2cP>Q&UMt>.F(-ǑmuC:.VJ̮4jT}u_Qx Ğx'\L0`}h hZmjEql04qB,H6 pH@Paԭ54\M\+\x.b)LHv22=2˳@{L1(c?!#k+z^K-j}鉹WCk.P£R`6W4d1TϨFh<]%`l/3PvSWRgp`lGs E)_.r pSM5]- \qB UD646` `D (0AtA 0 D4T1Ь\Bڡ݈>@)d|>W]IW&?n{}w__o=!x"<,8Cm!YY1]V<eŏvәNeoH {ObC}eEC~󯘾C.G/SEx‡C\ c S]00H:i!a \P \tj]Qb`e!\ "A`US9G|?*TJvL$@l~.,L%OGK n)^P?:sy^#]~yȭ6&$0zbH+Gt_hh){TY:G12ܓqۑ{-r/h=\!ug,CK> (cI=X i=*ti^}4op3Yo73PrW/bM{Mߨg.wAESck* ]L46)4ab`E4"JA"9!j C@ u` H$J1DLa .Z؄]%!bz^@ 2(9)Q ;9v fTVI^s/.J:o;+|>IG B7οgpH/}dŸęDX_rK\Ϣ֚O">p@GnEA*dQf9ϜC#W'Cp @ U4CM U&&. mM6#u8ckH `H`MUjL@ 1qmmRjp_ |0s'`H}Ҿ2 ?e79dwvpO(VmOLSd_Zܜ[%cmBU^^vAWZl8&+51@OKO}=Q #UM` ba*V; b!D`K@ `X֐Tj0mv QsUZ4A\ p@0ERA*jEPK_$}'Ͽ>JJ"cLFԨL@$= yOW3'AUz Ԕ=F!41z7[9-Ө1\NSr(z$ 8&zB02跉4̍8˨&E!bHG݊z=[ێ3TPEaNgiѮ=^vf"hԭ\oh ۠˫ߒ( ZP񉞧GөeAUG+r`=HڛEW.maL?a2֟ɬ0sXiq|e͸ Y=&Ο_s36v_ YneФwuC;9<:XydzdnWh[BNzN[Kw+pQGhӖʎv#0f-2fm4gf;~ }9'|!ͨS;Ъ8;Xu4髬pb0]E _7ǁ+ GxYAH&@_,GƩp5IXʊGtֺk؜fy }z[oPӦ;0$c4!9Lď]W2ՔW ֎^ Iϓx_@ėen,!gtOJd)K_u˅l@`4L#'FpwQD-I')1vrSf6< ,3)O{%خv5qf:?&YۮKJ|\8{ϳ=$Î 9q{B!.٧N\80GQmknˑU`#T:nfrcii~1q=]$UG< }ݹSYHo FyK03 p)N^s+ā}74yi>g*;cfR{\Gnk 7sVέsŇ-"/(2QH2Ϲ # | CkžǼVi[iwEUZT󠋏P)ヨ:ٱyothExtzߙ_>&Ui׃y?"uEElt (jn! blD)"D1 j(:Ҷ@UQL0, M GB@&MU~הsI^?{+p.~9y!J!E̹R3ѽUf霾{jպO<ٴ]>Z֋n Y43ϫc\i*hCJÁRu!Bo> ^;W^+wء,QçNkJe-V{7 j)q:A +بN &8 tyjdd]iJok5Y굏 lIx}Qqw3a-Wq$ۯ|1#w0Axepc^Tqq+5>0Y돖+`"{g|B>44HElzQJfo'b:H[JatWDX jNb, yh+EKo_nnv{uJqz()7G{%- }3{nt/C} r2};%u:Y.f{xy_nӵ5=\ \m Ǐ?b@M2hj2/w%U뱗\x\$}\,{^+ڮtgHkf[)o ཛ "'G6`wYǰ#V p`2!tq :Ov͉Ӫ̓3]jGU+;HbYݡS[:+Vfp;wxew';Ӌ&-&ψ/Jqn oRŸ?FcpMͽ=g^7U *q7yo-2!-<+1S݉ݧV޼exݶ떬3]Sm7엓6D^u7jcO.NYY@fNz琳p8zGVwaIx&ʬ1M q[Q28/Er|Ly]YD=AfmU680ec(淵\$Zc7O'yhx,8ϯT׹ά7%^3;j ~x1 /۟(uEYY$grգϐ =¡@3X=㚄 Zф|*5,&x!]#}'vܢ V nS'|^f I`G<\1h'ϩ:XnLQvSt^U8b~fIL#uhu40Gʥi ٹKa}G,u?xSM9GdU(Hl•9mo>=S.5=5<,ZIe1hdv)hLdmK 4Ӛ'iR#W_g9\dzuu*! M˒\}غ$˪瘚_;w]*C xWm4vXvsrUQ|*PSD}.'D x-CUSw-m6`hXn T [TB @p 1q5#e D2V! ORʣ_g 8 V۠CCw%:eTUG(Ԭv_*k`5X/wO *hP 6A(K"Φ +uy8n(t JҖwǫY ]O*iO({,DvZlX1kIM3 6AQԐ:8`:dRaDu1`@A}HhQߚw:VU5V*GѸe@m!68Rr;/yDF Sv!j/v|hU׽HԘ0t!"KdP RnW}Evr +^u}EP]̌Kfoc#O! 500 154@w,5DRTݠfedLB" p0Q0Xn%$!fbh*?~>~>. # GvYwG%4wxtq A?}w,X=?G5課Ͳh3l4v3WIG5+IK44+G0LG4A9L)B2d6aEWru;TA=*.a%3w3ȃA; |]#_c mc#hT'vi>A>Z|9"ghrSH*`z~E/]+nQTI*"< !hDFF&!\"AEkf5Au + `[Kt j14/iRnETtt`#m*Rge9ݭ5-k荹m]%6CALúegW$z w¹oW `~x#>7;R~p_ygF:e}<}(MAB=ݡN/}+Qw9^WC.+w}!|} e\=T]? 00wUHn]]`ic6Xn60fX:M$BAW]+A44Һ^kŪB(J.KJv] üڗ`uc/7{&&&@r=~ToᄊA( H~aʻp#UO]ht!bm9ۖ#ݓu*֍5j؟' 0r25hLu-H F"jiXF @X&,qU`1s bjF12]b1upMp2( {Q|8P9.QDDQRƚ=<$ Ī:ͺ'"y6т\pdiw^N4i# 41'WJV5J(c4ؘCT$ Sw)1 Jx*LPnr*'0N9#M$ZА(&RH3P/=;&B`p62jrC:U'NaQG-Ȫ©ʳ}U|)q]O"v}S 5ݒ#p`i;9E-<>d,;q:zި֎ab3)ayc=ED$JFgp*Ys=v:A}m+o7òM4Y/yyZ2 ⸱咱Z|6,ø_G%߄!F}&Z}y<lI#Tƺ%Omf@szyW}v](ד Б}ԥ4XUWաA.X;W }gyknhᠼEsk9}ES2f>^i »Bzm'\M^>է]*i)A ,hz]Bt3Veѵ8)]ޞL8rpT!ޣ3:5nU؆cOG:ͣY-fcYV֨C5ev9zi7\fၽZdXXۚ,k8zX}꼰 $x) ]'Twe]R[;B#.szqo{}]#N.؃wޔ9]7f+sܜGJFNO*iLtUG N9dmվo]$rJ6wؽiDO۷rDn 7/>Lɛĺ띰[džTNb0ņ롾A;Q;M֯"G79|C8 !r$q1_aXt~W\IGp z2.SwYpީzwޮ)؄5R˫whWr*s}{l"9oz7YyF Ֆ| NPMʕջ~>՛Z%pKsayq͍O-EsA "-x0o ZQ,Gd:itE^IϪޫ&5xUqi *i|gEF+ L0aYxx}P:=æ;96$)JJֺد] &D hx1M.!߮CH*+!֋^ÅBx=>#ʋy^_.iB 1<}F A֣ Rʺ̆7*"eׅU+={%c> xANjt#ysnF;*SE]箹ͯ*P^yNKSE*dfB.{3юEWBt>!t* ݻ=߰hX_;B$KQDǂ3UDh< *6eن́Jv {tC5QR CMh8l MBHXcb9XE1H NŚcR tI$3Qt4DWPݤO_+T+n鶤Nwl#{Qۼ<ɾy|<(} juKtE/:X^?.IxBҔU6iC긧*EM<>c dYvO  _A^e se>Q=GD.~H&B(v@!`fHURw2GUQ5a"1J3BaG.'pD@{!K(fbd1NASU%6xtκuz$PǯAÄse;'Ҩ:w 澀'o{+(Mw'yĂS}7i7Gx1P{O !.ص% K+-ww:TV!E4 pXTeѱ ``lˣ @l!el  >#5unRQaẐ웛1 "Ιrxws'b4M_}@Æ殣50c@Wu=JAO6Gs%4W8 EL>}oԙ݃XE(_2+&pO0?G?+dOeH\@a +X f4ݓĬLbI@801`;IaF:$#RtUXe!ChF9w.Jڢmxy=f]h%f_seTWN@?riZߎ~e~~04v4vI6ipzR[fQq>JE'қOϓ޻r/] H~&FHZ|#!3fn(>Ft9wuBa `M@ Gi `f `@ YD5B1 EtH ̵ְqMt~x6i:d~)m=llr)IPv4zXo~ j٠rD#+S)=ʹE/11/7sOBh'mSZM"X9hڇ* Tm>߾ ̃ϖ)̱ qj.VLGvLh,mYq` 4"ƜCq%lR#2-mX bcbm:`"wQ|<#( ^z?m{2 ƵHj+4W)w-jwMާa.}:vn,rZ_㼷t$ؚTHHξÝ̇hENw ͕Uu 32 (~UՅaaگU%@!hE[ "h$6@0pu1 D` 01 IE`$V1l24F8ؑ Q"e>Y_}}=32bbJc&stj3*m>{<>#Lbl:+zYVaZc)Y],+__:I&j$nER* hX24t|fH8UCҶ}_ C8)Jtb,A4i.Fjwu5H9h$،0Z"!Q@q6DF*:@R#bab+AHjKh`A:aͶ#I򑵯*ҕ<ʦd8~ vҺ[Jey6Ly `FM;'#T@^Gh^C)̗ۍ]uT ʺ-1ٕ^VS  D`Tt͒%HiP! Q"P`mnZkP䧼 iu[M;H'?o](6rġ@ W 0Ѵ-q6+)%90ڮ֥td$ByE7V<Zs$)Eg+/"íۏ'L=30XFpRT5Zц tvκ1nW͵X0J<}\ބ2Z=FHAtQ ç>phg0]=nK&ܰdŸжFRp8O_ERL+00i׺j r_"ǼUbadvG W]~lpAëM&(y(v{lHC% 3!RZC4H@˃,SÆ}mw|5\r|1ceˬmRsc,G"8g }#6'q]Z9L-PY <3T<8ilܵZTs='sO_l=Sx /jM.#gK|nuUǻ_N!S `̠M(pȾdᠮL!O*l)x 9lKoDd"=a-ȕ/{={LCk`+:jKp"^kފa϶>tizʅN`!c{Gyc>LӶ}x" n1Vt* &CE;-\twWsl>Wk }MT kgo!f9gUίF5iC핛>BF-o3D>/s5)c5+)@g1B "hV EА8# 15P1S@,p (@ C Utchi` 3׵Tjq(rŎWpT 6W}fuyy3j. 2fc\o#l58mT ǁFsd>o pgnl 輦%Vp2qo>kaOD\jmʪ]N*״DoLl{*G Al'wEn6"veDžRh](uGz]mKL/%"Cұ[C>OEi +hWJ1̠9s9tYdeK^I@c^ݻ4nf}N|#ZسheW;3rkSW)REU!KV {2?mn MǸͥh[=?302`B\ք3!-AcL`l~. I@q¶9>LobYjI-c9$jKpȴrJɉ73Td{u Ӽz=l^/}#VW~)n={Ax)Ե{!XGa߁##˹Exk=9GiUa{iG 6xsfwz|=UpA593Y~~6Q<6(B/&GF=oVf%Y,gʆ:"c? 1ar&xyN8pd>3;EtxJΩٖ /Ƽ|iY2TkbcG7nF,.Kf-~S#[PP9`[Zd5uY!(bMqR.( -6gWjm]Qտ=ͶW1}fJz(xkח-v~\"csT?>fe2ZK˥Ze\nͻ dӺ/^\f9˜ItU `d#Yod9Gkl9QPp ݴC,=aƃBsd%le5C'qrWeYDQXzMYWCIYKǑ<ҥ{]Mk2]eN(NݺW`!A:9{e\<:X.&%zLW"OtBf,kLXYy^Ón:a9\.MBϙ7z!c/c{W1NuC|<`xkĈĘBR[ TN漡F,0|y #r:*mdxpZX2e; +|mF/hyZ+uR=qE˭֚WvHwh$wT]0D!/һXi[曶&0>MY;ϙM?C1s2㝢|OuNG`UvU'@\~;{=} [rt`ML "b";F.$tMSq4jP4wCMihh,6 zUBA"#On_aj);@dw0ЕWTܯ;HQxeCm*J82^& t-8U/9v6UI+%grADXV1(JY XtNp a,[~sO4|q dQ * 81xRkathM sbjC :j:bk颙j064h::}{p=_p=a?..P`eE&K,RwÃn0@  FI]x6϶ߊQ>rDm)C.>u\{^}twk+Qf~̪h(/؅DU}\ˬC@$M j3Makzi.@0 EZ,ak@B!u9!0J )@.nNu*'(2r..u.eZ*פhcp |}TrkjMUl]Ѷ$&Eoz¬!!@.h 6p %OzGf'|'>7쾌>(<իYC->4cBCpuwwL˰6!&Ah  W&6bʣBf+m40g ߢ{Bl)(6{?Ue:=0mN+s$>9_Pj[Gs+k, ؟xmߨqsRv.ܾ>x.3tYF5!gJAC~O@KsUYt<橤!kImUSh"R.)X&Ż6"uteTE"@lآE;QVvPL t0?a .2YV 1 fJArj!m!955++=G|$̼Xܱל 'J(<CS2ˡ]'}~W \~1Kid1 3 F`im E0K-Wcccs*hs˻ yuR78=뫯zCg?.l ykTqϬk-\l.Mb4y~_n˦ꬮ's,nLߙX}Q>Q{ WZzNv3($3<pG 3 ! Clq tH!e"0 [61 KSk1)J#7)zz>T=@E!䵙HvHR~ w[w{>uӆzφ*oC2/ 0bD<~WTۣe=b̌cyZ5f>A(ew/ @g?'˴v>y7씈oUp,m0Brb!\7B0BIa\ /mf 3a1!@MyPIA$}ayw wiM=.Μ}SܹgЂ<8C ^ P+js_|84(SsD#6wݷh)3h.3]̯ف+{Rs0?ך $1ybXb HQ0tHUX8R2RLV# "`"Dce#EW^տsjMm<,,RF*!#*QT*" 0kJ6! I骩(&(v+惛[n4G! ,W#?eUfeKHlQڗwIёms(桥o>,O YaGjQ)ќVIPD(p]hNj=c*֝Nϛ=P]>*;pFz/x7B@[}6;-A@U6mwZ[.b՚"k/P2y7Z/r. I44sU{AȹRKWՃLLRyyOC,砚 "SO`I1b{7==c&y'mȢhKk}|C_p+3 Xb&cX0[,)q.3 TcjKF4`XZ!_};|'9G緯2%*ƽڎK:IM%PRvt5вPy÷ 2ܥ\AIeP'c~۾ pwF\32kB{"]*\ G['h4.ǵo1UoJR _QXdx)ճZG }] (7H3+f:tW^0 <\TNk9|QaCah,)y}3E[ICJyuvd~9, i%zNޣ 6Y^|" [[ F omŅ<J8<;lWOe(PnU0kqycM>^Dz3VèS9,trK zn'*wu˄.p# یt\ZK lRc[_7&OoW6<'DO_vUt7{)I;VS9vxW63ZvDϊ<PbI#'{̝2jJ@o&;f@MQ9=7铢|nӢE /z-Wc*/D9d?zjxxlӬFڢiXVi=5t.{ ]FXS{fkWLt!Xt3WkA,K# n{8ȽWZemK6oB툮CRR7m_z}'cٺEK4%/\IVl+%+F!ze6#k~7_ԊdLaC=$H^iitp,YL/\b%q央f)e5Cĩx"'WB:M#Os*pKR9_1J<'ʱ"yܡ_-\n͛rot[ DcsݛT5P~ Kg lG֢hNѝ9 ;}d胓 >VZ;XJ8¾ܺ0ϚvX [ 3]`2xY ~tdGіhZv}U]}`rI$ѥ¾|\hE6h;ES/bgobȌ){ ^b2@4Zc9n1DHI^ʐ*iR@sgʿ|~*]=~>J)CйUnɖ'22I![Q̺/Fߙ}^_#nXv5Q0B !zvbdͯ |PgeҲҏ4rKL3 DCab ̳2tO>k_='WGVүp }vvU9ŭIhJH>8^ѾJm%/)_f 4nn}B{!t6&#@ ]f!0eB9F TL-p}|/|땛~hi;.AOe*y.FSf@x]y^Jy/Ѝpn< ޼yҺUzϏwW6xYin_"&OW"6WM/ŌȋCݳ:gN`<>\o)O2./Ιw=}}ߺ♆+ A /A0| u{tMk]U7[^`f4 >*gdTLRj}&󳛾YIW^>|3O;l`nbS 0Mw}rYtW>*g*z&y/FFuњ˹0*yrVc@|r >aٞ}rJG#%(įY^:W3 -`3c\tq+mc1 2aGihoXx~kj(wO^Q *S*|Acx|5͸P#v[|kcQ|}I(=1g'1X'~]Itfy%WӛȽws+2*6-,L)>!˱z'`=" HC2 `ݎfPMvB6V:`xÏQ]sJ\¨}Cc09jWi`5W8p>iKx+T~3⾳Su6*߳!5_IG*~xoKGP tqzPCd0Tr>^x"(߯$VѸ#Takf`鉵R#5tĠvIv m! (G $4 !Ѳ$@#jYh"I5Ӱ.XLҀ4v0s@z~nA?Qn^;es'&c xi]PQUzʺJO~= ojIuY57ĦanY(Ҟ7NسfkfeE8b}d`op9ZyKȩc-]4 qX$BUc, kh#!kchf8`L+ 0@!(@8(ywݶW!.L_h&AG>76`YobyACF39nq06(N\bj4i TMm,cwe誶jT " 2q"pV0 5C*!B"4r&i4ߝ˞vۉB.AyqC[`p2y,L^woͺxT m=^wg72>&I˺,»tu>^1Q%?v|+X R5WV'S%tۋ+U_Rॎ'2 \3|=Wfyγ-[þi"Hz\ma9 *f ED]/ 7҃Zпih tSy2O1IؽՅ ^Ş6˰Q3S΍#2RQ7rclcS}=xrx`I;PPŽ^7`ާ&NˮjsʪAY.V L@x4a̤Zmfԡhy̫Xpg/;U<&C}!t0=Mh+czᮅMn~Cu5&rBU^+0+ LLhLp=Gu>R2st$4_h`K  #=#ÄdpXtcN3COE?bf 75c|kYQ[yU0'L#mXtV4ZʇjU[e1sL&oj_R@>o3Og,ݛ t7 R9Icch%l f6^Z\rca^px <18 C8}d:-jgz=hG>!(}O(7dȎS=\3̃وKTwKڪ}Gv:oQHQU ^$ R)r,!LtӜ?3j2Nt5+)3Cu\y˕RHѵKA5m4Y;cAxi<؛{&QeyrȚ}=MBhn<@&MΐbxcASFAWO+̮T\> LT"bmbpmWX&$ĘSj>ު1jsmnrmW:DTlf^y]B*"ƮZ~3r÷͗%cV5C ?calL"}YoM#FS&E=5Q]UUd*|yL~|J zMS7&|R/U؎4ۼ 5nEQ8360 ]Ϙ1GǭHq,Wq攇>,`u|3>&x!WFOe/\NRnE*[WRL֑ܴBѽUUˡYĻo7^\rWW7Э? }TpX@6 3ӈ ZbfECaLal57 hoY}/c zG~Wnۛ[uǘDxVhĤ6okk_{Nd[3?XC?E84H;XPYņٙV^\Bh0+ О)/Mos0;* ͦ+0u)X;f,$#(ocr'V05os}$WY8t7ˉ Are8(UEsxND=r.6Hs(e8\GrUF\Lpқt Z7qfchIh[mG M޶/ Q6diջ 1eRW\U)>V.8I,}v+^6[[utY|!% Yba47sEÌUk{sɯ&z1lp3סSG_G LH=Z@e[Gq̇j4At7 lM>˥{y-][8!c*I DT}$vMZ| iA@kg.1nOi/mC(^(pڬ8x%6J=*]3Vl>: ƒd`˰Q%2[U9o'Nwlˀ;^=k|s>iOX +%''c`0=)5B1;ҏ;ҫ>r^R)Re*j'Ba{'D)Vn /{ʺr=>2a So>aC& e,!&Z6bsD -,SY k0w@ b%b`s?S?t7;;@%!Z*J!USLь<7{ kypxM%۠,A>q烃OUx>1H,DrD fZfema"&" IT_~n_YGRG^Ľ[fQ]%gW>ϝ.{zfoeVr|>t'SX%uv2|ԥ*0G @ᇠ^bc^:'D[Ӟ>7ѭr/5eYnˣ] I~spȹdb6])hb7X8X 9UuC )9 h8m9p8c&:.![Tx~?UJR$ Gzd6%gnC=fbU:Bh(k+֚Kmأ^q =wP $wO*AGC.c[оMCF M.+]C$х޲W9=貘x@@Htdn~XV?ع162>?O~5!am v(YbDfi "`Q X,, F Sez!.W>P-|DO|*9wF4ƽZI~Q/qKcZ yLD"J" }~WKt1+ʪU]_ܕv uӲ|h۝Cdے;oY v |&_:M@K*=A V G3iSlX CLJDŊL q€ V s l0-p3,KrY1 ?~<>M]UMQ@S3@tn'Wfhg2x1^PAFeWt[ lmUHUy=T>5IUMG-X &I|AR lu"LɛOHk3u*~;Ģ̰ru];Zf0G`rSc?ٯ5ߒm~e 3+3 X0J1p1!1HBHXB""C& EMPOṡQ|fbMM{O/~BXx {e}&YvQ<%wwE~k=%4i}s aY;lQ$wpXy[ym3?6%)aZfZbfA$  \X A G^:8}YF{^0rliDXӐNЛ~Nx" Gu6/ƐHc Gך,Q!'u f{(KwuurvjRBlwe|CTl0҃*W| cOtYy[nn HT|6+FުT6T6*Du2le0xq'7}:89xo S (6OF0MJ.%MSu88J8RgѬO%a ;Oޟ[n:y"dÅ"gj^R^CmErPttM/S׵Mf)ưy6H`\ LMfءtݬR0,rjn4P3@7{v n쓦o_tl>Q02B&}O!o~PRϒDtCS_IPlyNX.,y]jgj>/ ;-: ۡvR6bƛB~dpeUZ2Efp]] JmιamN/Axtg8/mNm"(>\XN1S<nYL̈́i*F7՞D-(@qBV{?m{b=1Pۻ37~n Yq=k 'b* xRC}[zQJ}x:k7BcQ|q*ЌvvۏJXYj;cp^]Tz]p"dgE.G8 zN9Q^yz[+^-BE׹NFYʫh܍l2Ӿ{͗K/R|_b1I,' r{de)[>#m>$OWz t9`q}yJGLT¥z_Mz Q /{O [:1`UeVȀ *tɈQaޔUd{,[*+ᤊl|;ѓ2bdM1^Vdx-ʺ6}q7hR=̥DY8j(Q 7)-o'Gtáy1];{ˎ9޺rz%fľ P/mS󬺒hurv25_>"u5~-fA,ˑMBĺu4dMzgaN΂1V]unDޡAWt|xCeed(zbbrѭ6Uڒylf{56oIF.mH[/ڢޫ#}gaEł:9C5=L}B{ry[޾}_.Pε&G\<_*3'CMP2Ӫ mv&ڵd>$[B?]5"7ޭPy:_@úk[a}OXn'gF.Iyxwŀ gerMN߮sJZOvWr>#s'V rKJU0YSdwVjljKS3t]Ka 5v+VCcCʀ`}R'(VlWX-YjZGʛ'"iaeQ]q_TǟWF۠ySlk4n@Mi5/0;7MϦ>8t>ko K=D\HK]0_vJ&4 fX9[茎yqLIqNϹϚ_Ej1F`n"ZP< qV$E6 Cy^KɖMa ]? WsͶd^=2ܕ cŽ'"w>]T)\WmDH,ܬښ\5 wEXyLZ'BN{lx=s[Op^Pb~̐BUuUkf_9Tڟ\^z!H!ڐ6rp#Uav9X^sCA3QUўu`w<]@Xv;H7YޏiKe11"u'(ߓcq:3]e3g)Cy;&{EَAڄ7}_`3&3 =vv2B HjۤjnPkj`b +m`ȖDs)\B# k#J#1A;] |r0 GS;xn9o~K ?t,ӆƬSOMjƒ?Ifn ҦQi(bR7A>!l_q6z&Ie{'s'מNZUp@?br'&vr!:fbS)A|g{͈Q 4jF5m*7@^X\T=O E FBKLW1,pp&Z3 `@@~.s_4SUH1=0$vR c"D , T$USjId=PO)*Rk<4Uˡ4a_8oGaU^q J$=Gʇ{;xjˑs.w0C!/dMUϲ*~d 2EA伿Gx9ESB-?GщdPPLSL\C B%@1- DłB҆1"a- WE" uMK8p@BQ.@MT_#.XWC #/>ci]~(m[3v|zx/zCSmH>}/UwʦpieQ&JQ^@HM#H}]%Gݺa`8ÖL79{ߚTPGȝ̓lgmMzcu c UXU@h307HC1`lRa@n$FYCb@r$KwE%D:﷭m@*S؃m="]Բԫnw. ݪmy.Ni>>8Idz OJ!>pSdTG*La q]W3q e>.3gQ^4>/0zyF9/٘P}aJ >r~~b I(osFn!S<ѡORr E3ŚjYJk!t8Xmd&-m 6..,Lal"w^/>?Us[ޕ_P ( نw6ybv 'cpcE\̦=8\SDBk2]ėQ:{݀j%> 29&(zy)@z8QC\jeSʶI[Cg?c.>`/sww*wUy%QTa 0T/`s(|gfl('?Fn&PPl*PAbr]ml4GGb0,,7D”ҷW su*$@&lLr݊MVᩆhut5E"A~;I`H`KH˪ R(v8XYaQ5+ō>6r4.V0@jO^քҧQ11 tMVR,Phda9><8jjG Ά v^$ӒY7a#l=4F‰¢ 2AJDFkw~^^ʑB@'Xd*?p lMt3  w,uЈ Lv0ڬ1 HaaijAcJ@q\3ݣ*7QNW]J;. J&q9Uk^9Oى̢g;)E=]q޾f!@: 5J (WiGtmfC@&%,aP3jVˣ~ QoԪ9ct|x!z`;&S>"*Ev!oʫ?6%m5C1+tureߔH?]k&~ul3* 1X$@QDl%&E 3 f*@f%q+`Zc-01R# !TE1F('rr(B=YJGO=2Ciܬ6!3^!kib|***:$fTa*BU$Q)R*$J_^*WguݵjnۮǪzVR@Rɣ{}y: K xWwS÷zsm|jUH IUT(J$H *P Q$Jsh[MhTrSLǏT%TTTJAE"UT  *QTRU *)(UU)Q DQETRI *R**T$()QRB@T%UUJRT **(RBRT"R TE*EJBTDs^eUH{P"B%R PWlw^9pN'.kぽog n.ۇ׍{w*Fu;"BP kwuo}'_ x5 6Q#yRDH %(+-B^z;u3=cp8뀺ﯓUR!T)*:4(U+H/gy;,]׃rw;{{zuyHUPDt*U$I6QQD(TUUjOzq;Ãw wٛ|PR7UU T`RT"<K]GnxÝbDs먒xg IQT֔(U `^:a{zGn:˷#^T˱P|A7w2I{jhґQ#F"xZQwR;vnSE"(N&u5:$ݮ䞶61,FLW"TKFƐmöUʎ.ܠud6ץ Q+u77snJa`˚Td"4W`ٔl$I1B!̀nD,ъB4p6paƍWoDjmsL%IFs#"&0DGYvupN귐[$XgvwhV4HWGwjY44fJ$.!-"'\+15(bȗnkL i,D]IX*"X4FƏkWKLܢ*}׵;Qa^y&(*%.7t cKܤO"C,h26[̋6ɓ/fft5\˭uw v6P%)rQWI1d\6uXI:^sy>k4QRyDi d5cH[AA]duWf Ac@)% '"SSwFZ(wkm%`y\-ˑչ 7k&2mF\ 6s\ / 4EzFsovyov۔T,{rn*RhJ4s-,DXQtI0"֍E6u1@QX6Z)si*6k"X),%شc4湷5sK=][Ŋq(kˤч($1w6<-i ۡd2"66,8j6RGm|,7ʯ1` eFL#5DݹƯ),aMm똸D @*&F_++ɘI4G]7Q,޺X`vHh4TU־o0%=Q&}mI1JSQd]X&ENĕlRh+LDF,֯5'tstnFܢ{/W5+`ߟFC1F6K,h\o+ocW7nMn4hE`,i"6k4U{\&=nMvE:wrh$,^ۆ2TY4\ʼn$棫F6(ԄQ==PQY6ܲyW$Ŵ8s"ewmM-r`WaȱUlLV30b.s-!]cXRcQ%D{Eݘ5Fp NlQ%dǷ*g^6(Ezɦ]sw]]1K9Bvc޺ӗh6=W]ݑws ](qF73v,*2#. " K3"(Ԉ%8($6J5@LgJ%˺瑨N褢y7'wɎ8I*eNP$9dX;cy\H'g*qEPKn씙pM%wM&)$!LD[ Lr.w#gN#!NN q4ݢ1]-SEEHܦRg%%r* *Xr+)tuv/{%yr)fJ) E7`f ms&Dt6\5 p`Jqݱ"kUȕ'5qŲqZ)Y*qF)iUfIMZb*tEܵI5CR)D,܊w/mLTL^y̜yqЅpWfl)QH.slu5ص]A..n67+JƯ]'#-Fyas2Nqwuiw]AY.Xnn-(j5rTK|}wntF\yk\Rg)GwMi:+BỶsXnd7(fyA#si}}nu6⋍a'Y!fX rEai$D\I*@QRm,Pq$3c;u\KȄaS 3,s27Mzr悹ׅyo7r\+SJ HQCXP6KכzϽ5S9D%D,ۻM̔HI7sss"Au7I5ɌѱOl"qr li A Nb Dj .(sbkyL%ڽ{@IlZ>?r4k w{_&D&R,luDPD-(uQEfqPnӫ!4BJ蔧\{bݺK%vݷ˛F'zmv",*ĕ;w5.˪nj9;tIDSW,͢,Zm#D^GY})0DTh1}\p9ƈÙ_^ Fgݯm|#vvi()47L8KĮך5zLyE FJFۉE1AdfѤ( .*CQ+qrͰt`Sq,K]sBnVQ\w1h=^Z""?7 7 5DF.J QhAX1n_7FE} 9yѝ zs$X^kMX5%7ڤ`1]W")eBN颧mt$hmr 74*%.]rf̕N$\rҥk*\X 2i Q-,%I3l(h҈-.{FNSv&N%bgX7]ݫlb"b࣎nCKgJ *D%c Ru ZBvtFQxe}^L(]؊8XYIf((9s{Ӷ2=ιEE2&hI!6D¬ݳ\%,]JnUӕ ͥAX9ѓTbLklRQFK6(s4\4m3Fݺ0@S\ i4]=,7u"KԚ4w&sRn먢,E՟q!%Ɲu( yޕrܱJE"LU j"`)ܒ;wA3NŃ`Z"B6 6&-5D$.[hM`؁v []n(ѐCw7U"$F$[,Z(Z)*ݩ %TW9`驮U[JHpRk@&(+q PcRח"򷚐Dhad+3Q]4+Av@FPf]wh`%R].Q&F1nDh!(I&:ئF^iˢQwJTFݤ"6")."+lmrFuu\1ƒ4c%嫥%c@ntmX؎jъ (R[ռLF}6-XfZ()ݮQQRRALLE*,A:[5IQڍb1bK.ʍmkWԘMEE ޽ b,RwxjFƊ6NW5$E1b&{J(*JM=HFb,TD66ƈHhLua Q0wh` 6"5 j6hc9EQV6quvh*V4bk"4i=&F0X*l0aTUvɊ5HL$FFhi5`Ml7;D`P!T%D'[clmƳPڈF cQ)0*QQH!AE}䘢-jQw:Q!bŠvs&ţguFƋQmCVFh؍,5ԹFƣER TFIkX,LFŌƙ2FE) 5A79E&_}m&LE3hBA0J kF H `UrE +FJ,ZF4KFlE%!QA5c%`]Ӷ݅JRQ%@Rl1Sm%$du+ʊLk2M۬bŤ&*KE2劙lht"24lEr搬TV0F%ѢTȨ1j,MQ^%E}_jѐhړ&,ch6 db2XD44[*Qj.WW5f(S&Ѩj4D2eWebEENMc&2"6$hų*IRdWM\DIilcLQ `ɢ*#h2ksb)Xzk Fث!b)aX֊4Y(LDLFaJK]]\6 ll64C5]t+Eر5\Jͨ]l%T0\MlEGk%Blh1d+Y*6 QMDEǭ\Lv__[62E`(FY EHZ4Alc\b 5w.ۑFF6Nnj5 EA pvȚ-hQE[QDb+IvcRb5 (j6K dmjpniF4V4EXPkD"ADmE`ɍ[b,%&٨r 릔GSGl,INm+sDh`ؤw_W寓5% PȆRQX$()d[A ll$&`AR[vmKF4lkIJشQ R,1b1lcQMf+4D(cJbTcI"RFbJ LZJ)*KE5#R!]W5cYMi4J(m$F1C5$wF6Fj2Aa*5b*Mu2j5HkMhTmhȑELf1جd(5[\&LQJŃ&эLDW\]"b#61aƦh=U'q Ln&f4l-F.86"ha6(ƢsvF*)mbMEěB261:mlUf) `“b5ѱsli5Y*,QTVsQ&bQmj,m1]#A%VFk%R"h4VH6JFѹ[lD &1lM"TTjѴ4@ QREdM4d%$4]{OnhF1 U5F*$mC5314EkFє$E&6JKb& ڮci1Ɉ(Qd5+aHX4fVJɨē &65I1!,TmJ4U%ɱ-&HƤI$hY1TRhtQFd4V(ʼn*4I(ds$eEJhJI*#EQHIQu˷KLD62Qlh QbHH쫥E@@[mcTRT ]M\IfXFQbXń]7[rƄ(LI1E4lAE+Flm Thj/mQRI^񦩒b1 QƢ6FIEF;*4cTXAb(2dإ6kQIIN܆hTXĖ%F$$Vku%fTcQ4" AXu݈ IlRQ l hɱɲZLd"[QjH Db@!d"etcQHX2)*KXbƃ117[2me5QQjDCR&d%hIQ$,TEQA!iIQR61hjXf ہV b$S+E(Y-IPj1 &1 Eb @X1cBdВPQC AGI7rW3#h$ƙFDQ) mPcdHRb2MDm$ǰ E1ڊ*B4bvPaX@V6Lhj1cT( HZ5 kDƓ$EE$3dL"*]udXE(5AYB631cQQh2Rm,m(mh(FFHk&)2S*J*( ҹm$YV#!фѠ(TZ nّbZ1T&c+.W#REŢH&҉جb eH,h"M (ƠIwu(hY12I؊(,h#Qdؔmrc$ m)bI1h FcdllA&* *D7s]R lF1dC”bؙ2,Da TYhb hcI&#Tb5(F HA,XXY,Q`ݛIlQHlZ5ls "6EbQ,h-A`ɴ3GuƋ*61Q2 [#B64i-3K`h6F1ɪ *6Q"Plbw.ڸʃ-EB X4a+!X،͈\AXE`FQL&4XEE7vܣ1Y5&)4EX6Ѷ-*cZ(fY&F %* HF5hC@$hbZX4#!Fm#Q4c&,hDh4Z QcZE-,hHՍDj$LX* X#d)"ĄFFRj4XBC5ch4Q (2iDbh,I`$(0b*ѓY2m45{[,̓lnZa 6PH`F M jJ2ZI !5j1IRVHTIhR*ƴmbJe 34F0hRX*ԑ(cZLh f"LQ(1mcQƨ" i@aZE6%S(ōmbM fьfdэI ҫDLѶ1$ՊY3Q,[%AFشDU]mX+6XĚMcIbmiDIhcFBŢJKEHj5ELK011` 2փkF4kjRlhuj-ARmF4SI !lLFm:]% [ bM21 bRRI(Hi}݊)1bݯ&V#&M4Q"̊"#]˶d6ƃAAE&lČEFɣhbƣ)QbY6(I#1lTQlQ˫t`"1h5EDTMb"FMj#IFծ$QEFĉX5X)#Xj-\(A(QDed+JmILlDZt])"ѓb#3QifF#Fъj41ĄhRVKIQ ]*AbLVɒ2F0J([H4lmIQ!A Lm 3j-DTjJb:,RF#Eb(,[F!jH2RF4lQ-Ii1AQF cQ(F,ͦd*2U(6Ѣ1lQ.H4@Q޵1lDmhZІ6"lFI!"b&4m%24L($6e&m3hb"H6a"2hELbŴE,h֙lImh3LV L,D[Df-F4h*#F,lYۮD )f4l b˵Slb)#b1Ri6TX d ,f#IlA dA& I h,61 $ѓ`Ԛ("hZdGE& 4{nZL%0DQcZ"ѣ"-ju˵40ʊ4EE%hL2Q  QF f0QnJfŲEFKb 6. 6(X`D"m(j54PPm*u1UXōEfȌX" t"d S+#R ر&$he\Ƃ̃IZKaTTh)63*Ke Aěi-ܣ鱳1أ%131YL&$aŢ҈F-%#d6FToܼ{wBH .2[ݛBc2&f\E+IRfHj4j$JԖ6BV긑0(,Ed#FƓnl D %dItuJ-&6*-u(Ԛ5&(ԑW(1h5Mr-h4"͹mEbFŻ-sl% X;wD1(JBh"74Xh66,mQhh.Ĩ$,d+V2T\ѬQ#%آ+\]M2Xڈђ &) 6-IDu䉱ch&%;nm*RTҺQ&*55F*5ͮU&*,mFdɴh(2 1Q -ITPkjLD&sЮ}WI1QcTTT--Dh1i! Ŋe"jMFS`bƱXd6lL\QLSHLld(ƦjM&ɺ,Bѓ`LIli*%-ō26*Mr鍍Ơ (،QRci"MHwlld$iqə,IhnmRi$IQ2fAUH6-%^Dݽo6TTVDX6(dXbu A4\s%ۍcKF0$tlE]9FƦQ˦fɣQMrD(#. "(Ŋ(1^nbMB"6$\w'i!m/F1wwr;Eҝ΁"b5뮘Ԇz(Ѥ.^hqpN+2WMkYM."h(틂kZ:5XfNydqD{[vxBq!ۚF..jVrH S,RD# ! 劃L4ޚ P7;fA9dZc1I!$;R.(+a͇()IćpDjam8#I(N`R">}0^jA0iIƁ^Vҕ lN q} -EIbuOwzy!5KlIE8n,2.i84]]cx4d CVH$.и0rMӻ.űdYe9+P?DCj1ծ8) R."@Y^pu@nٽ"SaB~#Y`[hs^~{QZ/ն dSPu No., `֤3Tk 4an!J彁9aHCUR[.a];sN! \.7S6-md0ΊgܧufC(Ą4"66GJ+:C{ߥÉ꺳Hs_tj 0\)h>:/ntQSo흺whL6Pֽ0_&Էm[7Cɝ؜zV玩aQ$.b :c"n9o w9'.GUßBL7 ",,F$HfS39L>SusÜtaJ{/2HI˚wS8rJ2 v{D {4TK$x!if|І;(yvOh hŨ5pˣ%ȩLZ+pH&´%}SƤOG8tS:̧6s75h$pvndPDpgl}0f-Xc [k&uaOS3A=ɌeMD6}G@q+PuΓڀAfw|EDxDivռt_9*fe~ ]QTgoʊ0d͉dpñzh_+E?ID"yeЙs߇nygD}G|R*h"4XjfA F@'3 ۦs vq;ιt_.3/*x8z9ϙj*4٪PeD6wMS)Բ!=k"cTr2dS4W.LUW3ē2*HQׇKcNaӣ(os[ejtp!\[[BpkO>6Q3xVtlˢP >>F}nf"\Ӹ#?Çum)сڙՂ.ELvmA^l?-)l#8JD/o3;wfÛ=u]01WϯH{]ʄ@\$mcN0f#e} Ui&s;d[%6F҉ q`+(]r6J9]B-%paxs-՜hz^c;m(Bj>|Tg0p_jBj*#90J.hӁɆ=/Ѥg'Huo ~ҩnZr o{n+Ϲ"ёs&Yj鎲0|Ƣ7h\(:ٓ4N 5;P'ma;b q8^t24 7W]iҶ#5ڍN~d D{S}Zd) S] 2p٨,#9tA594o jCD<&bWfYP@Y$Rmɱ M/z:x4pLcnvBj$6"WEc4!$i-UvF [hӉ&v /a0Qfk͇s8z7!?9]^\/p78]V=X9Xd:aiӰKu}݇2/Võ͕4ښ.2G<: ڟXsxK:Kז"l^%3t3n w3ZF\sWE0dsG.ͥ@}xa`!Ƶwn͚*Z - 3ww%H`;" VTnMkKٮ{mծi~͚ܪuMEKؖ37_77`9ϘXXY.o)c?L3xpI1N8yUVovu;H5n 14My:eRC4‡6s{R{`:]JC쫹-ްvڬ̺blT/ZWܝ Հs.g_؆͹3Nr<2lY546DZ \X"j޵3nLļ\sF0:h3]гͰt &'n4;sg,=s,@ 81\qvβ <#k2AG8亟f9&P;zyهcsi:Mѷ>Av)]vT\@nvV=w{c}0P<,|6Lov)FvM4G 0;9l Ok#2Ź8ێA:s_!*Q)Uٸn9Vۭ1SqUix;{nmg^Ss0O Sa<~ u_0 Zw iUE3Wz.Ċ$纩,vo4Fn*@@ vՅG\HyT H=(L`$ۺZ-R+ X;}!q+;Lǯ.#3NB8+;]lHUل'v ZcgE6ΥN䝵 kp~gy~+r }Ò#V`\Ϛc(tqw_=V~ݟAx7i+]o4"QF.tRiG+GQҸA4Z|(>x$nKA>!EE٭gX~a-& 8͝v㽓tNd/a0.`qB've*QPlKy1*;f?D?]uZ&3ϴnp:6rQ.4* OnqasSv)0 \|P?qD>ä4ezM\,}naQ*M:&o.hݼC~]LC:]4'I6O G!sN]d{x; k@XD5jh`҄Ka5nvfulJSsh7ҘL H0 [9|{XTyбa$ag<4 K>CmÎhBg˘DbzdVrS;d;;>O =39 w8L(Hin}Ae{Jt?-=%׶b7-G)9^A:_"b%߶0ɹ3Pٛc[u)ri$"AFdct6BV>DfW@XcQ :qD}ƃ ys*֙{oÝ]wO LDY.c==9琐dy\@DÆ2[4IX ۇ NX́8" &e}򺟺pjJ~9$7*C#CKbdoWI;df$EC!؏i8;1/HGᑲyuvQ6WRMrD ͔t# ְp o5s9O9@~=%2(~J_||naN i5V憠.B1$_XB]j*ࡦ,dE`6l*"Ow(Anå~6KIٝ4qns?_ ?ej&J\c\G8Emɯ+%B:" X(`Ԗ5}0Y e(ykԤ̍ň(7Q"K2}LIv xpaYGIj,1mdĒTK _a,rkA"F+xb,-! ɝBjI/H .n`k8F!klU gXkӛ2jU9!TX"ZPBZQF@ Qh H(ܝ-Sh EХSL^ i@T7 D V(րU :  Kj-E7x|LinhudlA3j+Fn]#ֱsD>'6 |L./ "]i] IHdCX;)8vSɝvԤU7&q:):S}J@BpEynټq hW6ٺ[ ۢJ{Z pY7-}n)`r}:Ԥ-^$a"  A =S6st^ woDZ̛ s 2J]35HDhQ"leۄ]S Yr)²oe=J|'Z~-yH^O5prM>5$Son6Ƞw{o  Ђ?v5ݓ߰˝h7m+]Z gBz?-oa{k㞳#}'IJNOќC3j {9חux4WDҶx.zncKc>:eWݽ]ԹҮ]LRWVy{U:ky]yBqbos:Z~).=[F;)7i9Ys۹N,;0ӑT1'f97hB5)Tx4ଭ# YC\.WZQ*4^8y(vdPiW{ۘrBV]("2.v+ɚt2gb“*^9bf%ʦ:TЌqd`úYLqubSejyV[)۞tysFp^̵kY^{K7ќUN񸳈5dڕ>G?>zvI:umxiNVq{97IA>jX;xh523NZ:=9Hb^_RU^kN'T yzfMePP湫 f.uW]Q9: Y9&{-n,mӅ.{A~8L>rhg) UI*^ӭb *3NJ(zOß]Fϳѭ@Y_ @: 3´^Z}ޣK YK ZcB9}LX\ע,y AO Hf{N]tMغ䦣dݦ/ryL Ҍ\eɠ*^<(;Iw'J;xOfi{n*!"%A2^]-P>+߈=hz@XW\Q$$Lqaլz޴;8+tL~z'Gz(/;a֏4IOۜ 9nO>NJӧJman@ު8[!H%?3!6+[*T Ӷ4m8/)g'FrM@ҴבΎI#W)bX~&wϴ#̩׃4Dm5fp5Seq_] ^3^xu; Of9I:Z%Y7dLTlI"޾7()Vs>D8 !9kyX(5$6&\A{[C;Ncf+Iu @3:-(%>jG5=kl"!K);Y4LΧ$٭nFKT;NqzIfSt<9=}^g'Tl.n ?bA6H,=K99v{:z!X&$Tl0p}6"_:rn˯jߵ=oyNV/-s\Cm!iO; K;E5qr9|I ɔ {r>yV/x_S;Әѧ1w)Vo𹽧^f}L 7n$*q5 RGPv(^-{}K;ɴW wܬ3QacLf  /7`[vCF+%t4w2ɨ *uNp\n୛EC6.We+nz6 պj]=1#r4WLB#Z~758J;a[gk/{URnOfS!poL0jrÝTݔo43oG־8j`ǭ=gϴ5{m|*}f7wmTQy*&8[BRLQTD5c*1l8P{OnDCB(~;U5YQtq;dfw"!~|"*K|D?聖*;"e% R$v@}EFQ:د;C6wי\TUquμ ,QˤH H„*B:=ϹpWˮvbn㷭 {Fn!: ^˚'Il﷌bÏ$N٫fn/`/bN%;֌5` WUG#5L݃ƓBq/(!/T{ke^biy yؿʹɹ V:kM) e 0[4Bnc;dEx$d!ϥ8? f k'!kv}t'13XLHNU+4dX+bzuD8U}Z'bP0٠ quPHrn>7sx.?Y 3hUkC{7 cM {`0W'!`xvt-/*/EXmSNQXriy }Þwzpy9w]A_bUQ;9J~}qΊ*(? ?A +9?{{Gn"#?\!nfܔ/僧YHƴiD|AĿ0!#LdIwv#~yy~oƢH#9|F "{OH$J4[ן-jEo Ӟ5_^~ǐ0PnNϛj8)g H8q~\U &. K_> YR/keE(hD~_`21EF4?K#ɍ޼,m2bm}*PS+ʑҏo+ DO<ÅYF^Usr:A3ίO ݴ XvXaA-v5y1MJL=VwK6=K名J\_u0|G~D+5|CXtXaL49Œ{$Λk-k9U23T! q]^TW-ZSHz Vhs7eH堰[PKas,tޱe=9ZB5$|1;t6}7ҍd*U t:7#h[#M$S}mu8qHsjr<$$ 9b3R6JKؐu̻Y$3uy_>.ymY9!U.UcZӎk{9[V̽ywihIMӮyx3S=4 n,IaDoGhnb/-OJWP_ )6=%{],5cK%,k1or.mFo+Z1ĝ-ܧxneӋ5svM*ulb#~?p/Ks,fb^3{sTocƇj , =)S_Jq4J^Ka[8O7 HO>P[Edf)g> Ac5bdO$NSkM܌wNqlM]2Odn]RZv(n7|  Ľ3m :Yc/tS?JTʏywsیI>)ǻ,<8U([ەfA5#Ȳ>8]T ڽ 'f\8^ ﲙx8ḡs [Ie0vg5%cmx(Q蕋I aճ]hV;ﮨ{A%e}3mέ7NlDVo伷ʓ~$ {GZwPf`H;)u3%[;^٧}Zx<ڑee,A_H +#SkP =rZ $'ްl)':>/nE~s%} >#Ǭ<[KaDpY2Qq(/LctR©ʰHZp8>,R5 A$$7]Q,ve@EGGIT¬P+_,i7a9v>܇[Ͻϊ,(WuLmC= [*Q>i?oF'p2a:ggy/,Tq;pNdzy '1L^nYE||>&D=ҽ!zj@R ZNnXXMuggWe_q}e~~؞I_GeG!O-ޗu4 iY'ك~Nw, $4KhOЙr}}䯯jC39+Oh_g.ܤ50:=41~{ffY**8D[jo71(es7'f!N\DzѴyDpF.Zノ+Rm)ZPJ% 9JX-G@(nn`%#DpPJ $DtT'}a}s <˸y@xꢈ_ognN$܈(Z8 $_SUAr=eW2}~݌6D LAv+ eG^3ͣaJ6ǫ `N* /ե%}QHsC(K5 BDVD(ҖY#*{K@(RKZAFP:ۆM.ԗ_?{mdGy旺p*}=uxkE5 uc8'IjNzWd;zVߙڐU`Y"ε%84;~f $Hㅉ|Oߝ.ð 3Ad \p{jn4C3 ug+ө1UPNݲd?7^8ZAiq Uԭ[s mKkJ *в[RUwtcb %@H ¸ ~7'pSA1}~MS\t7۹0 :{aXݫ7;%y:4o <=f:vBCh|] A)G\9ʡz|xABg٪$|*O0E>'?gW?Z(>Ngmr1w5!lH(Y%@ X[44ivBH@hQ?wg,Q#F5 R C hY( GK2$.ojzWό~K0ҕ)p00O9<, į$ yza?u;n(w'zu_x\ɪ. o 1)"9#dbsoD8b2;?Dd|}9:.9YvYYul%ᨪx/ɗoixJ}}HJs~̥g9e+oxrb:dCTw_`|$ƯӬ}=`ǀo.C Tf魡@Jn^ĢRL- Khw1n1J20amVq^`{竒g3;[/fj{/,Yv{44HRv.==4rn,ImDu@@}@4e=wā3PTqr*J/X|;?-3\I9y̷M)_'&D\C8!K#ET꽎S@Wn.G)>! VǑA 4*)aaWҐ dje4@[J7]UCCD.]©R {-~;I׍Ú=~%p8Yz# Ԧ}p*Pje?˛f}o DHDww]ϯLtk[L >¹P50D] '<{ %=y.L+s5kL0uСe3(Ԭ B]ONI-+s`1"hRFV!"9^WЌ RDҔhVRKJ-WU}&'m}]늾+v4f։O]#Ӑd?9YR]P#Cupjx! ާ 4t@]*Fm_ɋ;f)AdP4J@{yۗ',ݽY6\b',Vdxa-aš9ckӗ`wpyucd;`{rt6z]sXgayUSN;}''"sJWEIy/Hu b$3ltc J>㍙.Q _UƈY}ᩭx?q%ƞ>sشoaiǸnx3ȇ뿙_ğmmW6̪'{P!/&2cE>W%͊2ӹDw=_+;Wsn.mOLstKBN**Vj]g<^~ʾl Yc0H;VZ-ogPH'YǥeؐMY$G[t\} YYÇq=Xv({t+]!/ UQvfMzj^q8|bxt4uXnLv } ྱf_O*;;| Nrg5̪(ºR;އsk?\y):Ǹxqu/tFoY$d'N=[C{:hf }&](Ʌ:ҿV|Xϼ~KT=Sܮ}weCgがsOC{L&_n-ٍVܷO6g<8꓎u*s֧17{ۋa\yIg5比87Jh"EY˩2p hp/ky‘B2=CF>LŃ\{GlC *{ \3R_,{=SF+x%KGT]D9ryD1;9L`WO hZjJ^1gY?nr 8 n j\6.$}Ι*m{楌, W{: ~LgzXU ߅X[X8J}7]bϏۙu=OHٸnUভiIVUQHҧ*6@9r峎:ĦVqyBz+xy(n7qFkpm*EŘoպ켔E h/9ft6qjb\nxaY`=qT |o|lWFt'eSwX{ Yg9ǣ-WY#K˂o{M?h#7 5cc՛O"]o9b'fx_ }c2MF8 ɺzm m+]hX" s6wa5]S]4j17^!' sv]]ߩ?JPՌæ_f15s1Үlq/݅zIy&sbV$%Ъy8V&nPCUljwRU [fd$8ݚsn8WNXLv4U u]0$A4\nvE;>U'ob2NsY|ZCĆU޸ԭ6矷5v]0'ƪixΪ{Se h{Cvzg܁6H2OIqړXtrwn緘ⶖӶ[4/yYot7o{)m-B߫iZJ98N4)^,黱x+GU]vag=&Z}70UP9g uV+B嶖 ݼNu]TzkVV(;72>|٧7MHp*U7D1VzY,Θl7#zKT컂3eG9n&hwqqٱrj[ps(ɑZuKɦ!s#[/!7vn73uszLQ7:9, Α=I9Xe/%;sZ$x8Ls%(& Oyԏ'Z2Хݬܾ4|3;Mcy˛:UR_ p?CJPI~3-]F:p_{2).?Z|iDm ~'HA0 "f~(~/?~tanUl\Wn5a&W-Mss9G׸JODD[o\mjэ~AzhF,?=vV`3VvܹQbpQq=b18W-ɌMC"jS{}ϷGW2=+,}QqfUTQt{v>Y8h=.fV ۯ5{u j0F@ ;d͋g#^Y iKEGElA76LQm?VhѩKFqLQ@;:V~:>; OWI8x+Ӟ:wph(X* )i*JKs/~0ä#Gkz(U.>$H$$3"ДARQ]/|bDAU -w:緀*H!" $I$l7=}Ⱦ?wG1 &f'PPmJIɒD,ICTȿggQS1$Q{t~籶:-r"yk.b(ZH\Q]s &Dcwi ⸊ݱ V1%lE 0||λGQ\LVlZw,A} d-QE&ݦ< ij?\Zy X?wla-I2xA jqN .'6/lAyE g3^ߣ+/*i;y(l4mђ%I4m拐WpA2"4?uldr~gb4Na#։5 U3vQ콾n_21VUfT/jtb}lk+Y7u6/^:Nt~s|DڱFI -^:M;2h([pc=} hwco%OJ?sleɲ{_fjeݽg Iwbfwmd`Ё"G{lUuΏ^zlvΤG/6)j]VxEV ;]4#4Wti']\9Q;Y˳nCE4l7pIƟE P'ۖ6j^A&5M. V-eUݯ%,o~{;zJRagyNr׼z̋]̠o*A˶ʱÝ3ӽXԾB#\z]tV<)Nvg[=PkDVfN!j{sF[Am샵m<)K|vbk-;XʫzoɼwA=dC~|\A<櫫c.bz;4J/AXzr}9v: J1Z.B 33wT*@'].V:CؔfyDg2[y-Mѽt_B%FbיqomNˮۓutYO=u 624f^o=Ӫ87qϋ-љlŮu?-=x owmwIaU_MJ0*]lS3fmwyVnn:gx[YPMnKz뉅-U㋫9c23%C('jM=թ&˘Lc+)vGwysmG=V@D' >lYw2QN'\bG(YhUp!l¯+Nc2Ԓ.5)or*D$< ;kOrܗʕMO ˦ .6qipߝh0˺cLzJ\8KAKJxc{G325B VY- kk7YUBym#9w-ƭ[Uv*zj/wɬFw2? nN ԭһ|5Wb} ,f ^bΞ[jmjʫZƜGeb{3nSb^픥6RC1o'o%SUR3b5KqZ;O7#tjәf`s2G{iwR ]H37uƏ9Z/q NL>ٙۏggTL2Sr;m=W; gM SqZ]']+Zaᓌ2-}*놣wkg* "$ZM<'A6Լ^ȭ3qVlp"NJX)70,gSYӧW|ۗzjvʷ+;5_>{ZFuUk|zrl4/h}f9j4zOnRÕ;us|t.Z$a&}UO;7}(uN>ۛ|{7(-+xMmƶVg,#H3VaFwHݣ۹.8;yD)v)P͹L'uK8b{={^l}ukdܽYݩw$֘t, S{۞x5fnqd*qm]BN0p\hdF#Sp䔽^L/j87nLM1 s=m8lvgA-nUK8>3Z=ol9b4RV#'^9ʝSO^ O's3=VǼ"ueS#.l*gbo Qق ˲& =sB=2GjNjv= yzOj;V6F JON:6v6U}$÷URyU,I=If.WSn:!tWa,V7U9%F Ǿޞ^ޔx=y5}/E,T!qHssw3R lC-vv;$yOrff^"Tݞ Hak: ,nڦo`s'BXtĨJS\swh-r:jLbnp}nC9c: gf_ YwtlVpn@O{5{f90워vLkDm4ڜ{TNPNBwÆvޮ7g&f4mS>͋I7fU\c@RKzr͇u== 8gQǜo'cN_m_Lynxc&ܬv^tlu>tuߌwƧw{;Srǁڣ]m *dʡUeJj}*c0{G !|VnC=z3dաkhY\^Luꙺw7^ɜ+Eɣjޝk&= k7|1ՎDPy7+M*d%_R\&$i8${[u^O ],G06Oo j\A ǝzA}NODX]T6o6ew<=L\wUks*߾ڰܹHOy!XbUz)JkTS9Դe^uK~ҋܖi뇵K }M97]/S7 ζoVN "!nf:{swIYuS2:6lKMiResIb땂+Ti0v2dzsz}zKtikև[wnGVLjY@Ө/eL i 3qswedn=JtTƱ%%T^LL죑Dy5A]V&gYffneŒdLn廓sVvbN{.^K+`P5Ur3.ۻM3{ ÷4GGrj6h3Nsj|3Mx?y)Wx ]Ur4I15?fİ?p܏_5rm%"\Y76 9xFf\>a: uOfhKv]˓ tSq+uف>XZ8T׋ŗuC:stv{걑 Ӥ.LVhR 4-7.8f/lԕ\Uǚ8%`qZ.6ޜdܒ~,xʴsnV< GM׊d/cN;Xr6nʨ:?h;!Ofzܳ"F]ׯۭ jrpңRVFތ=z/;\ѱJΕۼJYPԫ,gc=po JWѮӂnЁ|YׯǺlZyTrRU*}>[,Ly;f,l{NlhO%1 fERX;o]W s4ߢd0if5;02MXO;Y4*gXo^]7|[==^Vlo(ιdgkӚ-ꤺ֩x[՛<&ڠUHqӤk"r>'CQrfx>̢[ܶǮ< \8'2G>VEy6ʓejU1)hBҞ[E> lnW'L(q}O@`E8 N#{WIaWZ݃Wm+6Uޓ$|+ʞyKS:I=ŕamCy/*F1+/po_xt'QRrm&$E: Ϻ"’U/9J9ߦ37.6}Δ|{ ބLo=xs(EvHwU-Wt{Vq<R0vWvc|SW9f6.qM/.skya3B CHvixU^˰vf7_\4emUbz疸sPG'1>̅ 2ղL73RrV{MvYm˙w-SNJ8*f׈F3c,O|Dx HMLw)5:M_EXvHZY>9(XnX-0NcO#m#rugX{VmΉRmq$nlGW-˼~L|E|]Œw{,W'upm&-wB`AjsZ\9}Q6;cR= AZYseZCemA Tc,e yYƤp]Φ{:R7Ҝ h[WWF! x-A~61192];P݌8VpZyGF\D#FxSб7}R =+{jX*﯌N>nk:{ns߻_g즚t0u\ͳS}W\6#kk2o((@{^\癴{JЪ\fd^h΄&YBpUǮfGAg$;9&`ތsW6 s;lpܬ=%V8nv]9Zx[h1.G%`0avе(R9UxR0nazsm5HD8쒊xi>twyujRٛSu%Yڼ ²[7KIhؘ9#=!Y&'܍/ۿ.% NjݽTgn4M!!^0jr3;S=;Hכ.4azvAwK] y7٣ݾ}81=.(kV+̚)y(+\urhNM;ulJf֢e(_#7}e!ON|2 !aU{R,ΧՑBϱ8A~JfMnx q/%=ýjAa}`PJ2$MeV}TAoWoH%\Er|QTq]8./lxZm66!=f`Ȇ˔3΂{9D_=>k۳x6NJʮDobj+}K͑ [ۙg%Ak]8HjsP{.ՓmebuWvIRfKH>WQ'U@3m;{c{ ui9mVy`v:k·-IKyߝ?%G4|#qۺ0qogfngRv#4[1fMqW^rлRY `CT'm*v_.2qPVy'xrf{dKVxpD;˵ 3A 6_mbOzS+fXQۚobӺOZ5#wVŵ K#m_Mg*lpӯޖ!:yEټf۬РTNkupl qq9<8*hþӵ];-E|,w1I{e^xzjjݹh=vI{>lZ؈;Rr.fŚ;27gمMF-a;AB_(EI INo*٪U8:wH&;y\lXnh(Dy]*Ao'ty/nNl 66fʬ5gu*jcԸ讼%eNg$O9˩BHUYҚ hp]D'TEzjyW\s;A 4-$2$yL]Y۶^WD)zvk_T}ƝmXx؀ ju,;%U!Z%5@x;7&Uʻb٘:IIR5'5֑.pr.젤ɵ*v8S'Yq`rz˞c\nb9څ zY*b{"YmM kduŝi]c᷎{{K= 8{6Eqg[:u" uu!k:ڞRzl98/eV<w9|Ž͟yhNIuy`+<4̬ٛa~OZ{Ǽ9_l ͭc᾽}-GsٛcZX(t5E!pշoR;ɯg77a֚z}{NT}RTle(P:8'»4R3l|5SzKsƷ^?2ʽ}Q<<Ʒ##sk5J9ձɻ&MYm}095yszh/'ցt-i3vHN¹PwMz;V{LڳKm!59ngZ(޺s=_iᠡvDB̢ (eRJhMpj%xg:7Tpcwʣ2îu^M<?m {N}JɪGCUGW^q<ӗLj\XKGf% o;龡]7nkt 4>SstZb<{e;qAv ]b(xb2l/zAռ򏻧FI%"{.NEK뼚(K:Q䪻t|Юpۘ1뮒}OCe6:h Hݓ0GCxc< 'E1Mr/vLz응F_Gδ֟TVl\co5nd{2. a-6)g}o\ ^qxV+d8^ڒحU8TӴ,>)f^Y._Kw_b4-~I܏:hwsOYw7>VUc{tlLs61@w!O0JYapXI_n'vG`յi9[AUnP7o!kxt9)%G:aFU){Xh]AhTGKyY5#CB6c#pqѻԚgo]4{YU}fpo#gP+p7*ιds<^}ya߲nD3.~^D#~Mh .*\9S{2nozxs{ /:N: P?QiiMݙދ>'z焛 e󙡼43zr7sNײɚNp,.X:4Tb ɥS/Xh' =^#DuiklWw3zЈUs{{]$wwrALI=_5NLͤ])Y"r}OuɺƌڲƶGf jIՍ T\rnq#HuڮŚfY9PUlP;Tgp{Γf]Iv-*[([t/8H*sB tF'<^ak֒46b{\G"rʮŽM$/X=c)xI/ oT܏eЯKqZbxFO>~}bUEjo+ ]D I ߶81f)\wG+uC}YQ"Zfo}tP{,= :쭺VuqmV%NiR;i,uum8T!jY8'{5+ 1H)\ޭ–@nNf`7%y:ÔrG8zK6w/Esb͍wۈ]v[XQhTV=IHp|)@-؂[:t'::>'NgRg} ƻܘ 4l\(tcHƻS'TZi1"LDWtrapHow\ZWۮ%cf[:۪>!]wtvS*WQqu:(oNP\Aܫ!9ShO7Ա1sQ.|!Q!UNb0N7% u}S!HmqUw)5qY{b5/v:M &)w1~~L]o\}/*4ruYx{.̘r#j&ػGf >4 êޞ7z'/PZw FG u5G)0zaE@0.suueN}xh@̵c+Ff&pݔn'#4KK#0k=sW^.W"h=L_jZL|n EAʾ`w'=TQ!q}ԥSR;16TgAfnfvxKkp(}9=;Uq͑p(QIڤZGɶko2 Ǣl{nb"{s5u%讥Qw:w];u;R,c9B2X:i.w]TagtD4DA?AcFѶAg. |h[u7ܨ@cO ;6zm'}va}ib(mq@8*l)BOĆ|A5;fGV}إD1,xXO{S$a:N^wMTS-'mrQ +"Wr>ڲsͼϪfagl#O ^`H !#f{&5Mt⭐U>E%d2фM^pkK/oB{a[eΐsMoԬgҠfՄtaәZ9[ZCju3!)O1Tyf*zYo9; u2qynhuXOcb{!'73I N895{p]?6W؆,Ɔܻ #H^3asOۻ؝W,"x[6Mqm )$Ah|KLQ_N^{ `H8aG.Jrw$\P@d^@x# opctyO0> #W@"t޹pz|ɘJ/+A5e?kƛxc"cr]ۣ v'geQ˧U՛[,+WtʋliYKa^K<Ժiޱ3o} ]URW5coՌ<};YLӶs̎݅ЇF(Lc9'jU;# 6A>f 8%:p8!,^n( j=Iw@|ԯcp<v[b"c-@iʵI'e\r7+(vet'YVq 'W{Kq,u>D CrT>ECD ;$"ϫ/aB`Ɩ&P;CVdB 5>}tT8m)tFBC6\ˠ0ލK2eRբO\vuIad %͹BỏpSUʼm~$ҏ̀_H1Ehx K@5P)kwn!w|0gm{ޤU]NDk9fm>'٦'>,s,|P4Z29 䨟}ve?=.(*@7l[A̧sx(t1r#e"rQ{w-̥A_׮Gg& b_(~D2f*Yu&)8X{cIJRJ|V2k{v.5=) AYGܞEC_s12&GFc3eX҇/V:WʫYCbHyU:@%Gd\:%:3w8SFT¦Z 9" G+x y>/ʓ7c$)64F+}l ,l;}g([cDw0,ky !2 . H|KW-5jE{|B¼YT1A闉) BˣYb\&ܹgLR:B# jx]W= 8d'Y+72$}v7}~wعyV j|ȑG, O($jgw[܅Y{h?|9}T71~e5\':$F8ݷ xmp;-d>VGmeɨ졇3d|f5r1ʀ9z|CՉ@C D8NY=ځD9:֧Z(*'nΦ[+utJޭC@9:{ pu Cy%=JT(sz|ߓ ?_RY.E/,pp&?/N>I }?4B%Б=)(uhe ʅ(w]znq1瞩N>=̏Jv"E}ݯt6wo31BI+'5"fR(xԆ(zr{ bd엶 ᧡huЇ$D_(Q*Lr!pan\NQ@; Du 0h i pe`{H'|>m/r9fq}(U*ȭYM2>b c~sp1K҈~ ]*IzGI-P#쳄/z3GG 'H'̀2#glWn׼4U0Mu5QL?(U ~ɤȢ1ེ& e_]Gׇ<d70;əg^4p:(\s?Oȧbmba'7t {&љ4oD̟وKqC/C~ }*׀5Z>qCTru+Iٔ) (:]?]O;e>ܗޟnmwσGOI'DJ~yfi"8 !"9v32{&@wq3^PT.ٿ[^XSV (>$F֨|4N!C{(Tj+J҄ʁa@8E)qЙ*˪hPV+(~m pJ')v/Q ˤ( peQ&)!k,۰Y"oo1לR㲺s ybۏl8ݝɲehy ._~':ʻ>D8E1! "*A @Ju4 / ȍ 5 w$'Pr`JPd_}; gy=gyZչ[?~:?}Z8,B S\ @Z3Y uMW;?]'\r/ֈ,u_zۍ<@v˷8=C|~E0v0\c$'G,`z~ǀBӆP# PL8p`Q(G U…^E2R&Bf *Tjr5uZ}{@5 'Nh XHҏȘn b(c*P A;wa0L, ]y$|6DI"o vXUXEAoߵO`> !6K 2.Qgv*,LT!/55tGoJֹ].1\=㟠+י9ASw>Tp\wsln  `6Pm#`GcALBcZ/;}nTN#{x=$}CWg-G(t#=}R\3/s?Y粎I IzSrBh)ESOx 7Zr~Ev.uU7t[sa)BVcP¹7Ћqڀ3n*<#nff9H0R +)+TỪێ7N,6ynw2װEahaU#gV%FѮ X<&k#7ØL*Aw{չ+)RyHl^ 5sn In!z))Ltx [pCq$񭤱9!Pr"kf0cHwK1mTZs9AI]+A ]r te>͎v_o@mk{;i+R7_Lk}_d;7:cl.4 J^`3O"~ZR 4DHJ| ND3A[E,68}÷nQ_H]v'#pj[Q;7k˛ a]5 K֜f-Wﳴ@hy=<UѢTRpQ8H0Hr"nPj-լ T £cܜn-Qx;RA y2 J/V=`T48x iQj<0x嵮Yh߫0˴:|)51;L;[gѫCz09:Tee:[Rm47;{qnwry☡> Tyx ,!Yg"k#;|ӔL R2#j]Enm=>u3%g:Rsv$-o='nE92#=%D;k50W.X ݻȮX#aa.^Ѝ#٦돭[BBH"|r#8t^(cg0[v!gqzaoA\!'q4>9a"W&$>{<:WTN/IEs[|][dL^{W#O =gQc2nxnʵ34Rkj +_g5agl/E_72)2dt}мX뻚.~.WA{sSD.)po" hwOc;;zza{ʯM (4yՍVn"@9(sNlZ8ouuX%Fgs u{E;VʦC k2&ύŜk/:bJIzKCL5W\v bm]G:NUt0d2Yo{Et/ 5h'sz,rrmT;Vs<ǯ*ljOSlªbg$0^ # [;V]H}rT'ޯpccH"o׆XBڷa):+?-lqMaO0H|ȀL$)}&5"'AqR)! H-=41;R ; F vW&]O0ޜy*;1EC+Hxe#udNQ .YWȍg{v+Lb4equحâ@ل阗t$)_iSr:aVrVnDi!ur*R lع؅"D vqjXF;-y9v}RO;cdž8J޾6憀$xM9O`Ai_8w[Z9q<+&SeW?">AIZ,F˥R0Zkrݻc h@onrHC | "#vbOƠ9}8yݬMUH^D~Ϗ R״-q xg5jٱ :c32 GD 0'CYf|ϽvzZ`B<'yD;%Wg =JIJsJ&yp7Xx ρQCzz{o+?>+;9s/`)2PIMlB|ٍ;JC:h=}8rHTt8x-%TJP(N%堅8y*P”RA JD8H᠔CZ_4R\QKs=PS7=P'DS7^ͯxkB_P((؄G#`}`ИZ|odL[~$`o{(nR1]TP\ϐ;d LP^d=3>R hP$PAG5$"sb/ x Ns W1s*U"h론j+Fb"4Pw BEUpxvypcG܏|]Bb/|9S( gy=ߜ>Dzt^ٻeEd"Uz<%°^Kn"38>Y3ӊgr tb?l45= 9a4s1vv{)/3;T'p_*qkH(SXFVS;0Z BBT*yG$G$18Vy__OhP ~=GQ\,pF4Gor>n +P@'>֣0y[Hs=f[.3(=L?ѥt|;!!}fϙL΅L9IJfIܥs;f~__OJE^ A)@(7-KbAb40Z(kboPUY j6ZA`^ w}h=_^ow3;뛱Pa3S3Qآѯ\߫q%s8?]{HT`y Yz:b ^v_~Ud~49$DQH-<ޜ=/ =9ݙ]dLtgK Ũ7p8$O'{޿[mr\9'2%L# !C7U,,_Pe1/'ٶi*ř[,dN{gBa[AqT^'JDJmBa?a>.- S?H>XNQ)@FP(%;ⶥR )G2@$|0<0Ki9}G={~ iJƈ~~ fwSfmQsRWmv jtCǝT`K->_`Fw9 E!Tw3U@gNxwbD"M h}D*rZ %N;R b񖆨NJ.63RD14FǞ<<>x}?+xwrݑӾfyx>1E"!o~_0 $`?mu-|N{N,k3^~|X~||5ˎ|gB[Żl}ݒlV|$ *Fz4?_+`|qND}(T J(Z1ª4838*BhQZs#{@"uR/*^Vm0Z)0?9s߮fh_E$gL-]E(C>{} $r -wuۅH1Q} q/GQ=]LYW73gɪ-@r%qqpp>L0-{f)x}o=0q AJСVTy98(J* g_8V[jGX0H8՗5^pGx]pӈ$7kVYItS ,[秶mEAX0<K76Df1CR!̙m.}yrO_,g^fh˗'dK+=xQ>޲ "4Mu'Lv;K^azԥG!I׫e8L7<""+Yb۴ofbuEN7.H,kˆ 'Ä@ u\Z8;{Q<zDANA S2KNe!י{^yx u(!@8F@HUKJ,VxA8(:դ ;a \g@ʑ{^N]=;2.F0g^uKtv.ۉR]ԭZзYɉ7+/+`-|xW*S=\q#ׇHi aA] {TC ٧آX3ovPe6]92H"l=)@'XF!3Rw-7>c܎e#|r}.u'"l!qgߩȠ8Ј\TTpB{W#_z8=yvYR)sZ+M] ak`Ft%wɽ! 7+)CU@֥+ ;RSNWtsgA1N+/eάB!J b|U!N#pv:,rŠ7 *L%B:9Ѳ> DůE^mӼF~Go&Yc7 ޔջY1ܯ2s)_wEP&JkYH7v1FU@cOIoAj]Jc/0 Igx=,Dmuqɼ|~s^>ncnj$?N3z|u۲!xt?Bfx[KȘvPUO$JHXB/+Nsq}|(j DF+us2 m]I87W3,~7x󢯢F. eg* & 1L2tK" wŻP%|pVwm);xUH ծUn@CGb !\cv"a~@om#^ .0W6Α=/XxڳtŝrJ{{Xegf;#A=_w8au[aEf5`nsOgq.9Q2D8A{Ƈ(Q%s{_X8Z\zJQ@LD olb}t]{ lոT~8}N GtT%̃dT/M,@QeD Ŵ}~0nǪ=V' 40p$LA aY[t6G4J耠qY/nΈM&.u#`Ũ59%é˚SQG8Hg]xoltC]|=R|4׏5*k>,갎(%핅jHܬc5Ĉx 9 dPmff3Đ,B;*XZS&!wii=Z%=4^^A9fQ˝?\3֓Ēyg4߼jya Uo.N  {f0> 4݀B6`GGҫ#ߺ5?3=|RQD{8j%NQ" AB܄M]C w"(nwQiʁ$y3* `@ǻ0` EZO{J0gHAoanjW =믳>09=' =oEsk2zn}IAϟ .쮡 pvlg0jc>NE&5˭ r~udl @)uH $ӎWCR!"p:*qh@"lV q ۹$ZXD} H$~ aծejPNtq{X $y|@9Шh7X\Vs׼xG_Kr~0iᱶI42]3>|t>g~wqp pqMCQFj+օ幕(d'0( ^"E8V/B(r#n%@ZqJ99bDGa}IS}!~4v" }>xwߟCa kހG"DZIǏܼoksQ&op9m@Y'x6}臊HHA @M{u,sy/wog?V&`S|H `zReu8~,8@׍ pJȐUdu(8D; 1N!Z;G ZXtI Vp s30@p -*#bi/ J%?ADlW7 ~fg Q$2'%<=TVK)·'Fo=#G9aHmP/>ɸrh m&9ܢ轹Hr $~N '&. {8/VR[ȩ1qʁz!!`a8:Ѭ:@ cppxǿ_"|.bCCV`UwRԢ8Q#s+ B4P ED9:1M (iRP$ISp?߽P`a6g`}w<4RqQ}~'}>qGWx?<'m Jkbɵ.xqe)% ֆ/z# D>=ʼnY@FB+O2̕:C?U)B9E98@B9Q98xQPrRXqJxzB0h4xqyJTh<sqFx@ b@9EM@PUϧ3 ~#VEޒe}teZ)K<ȣh>`3>-D2qO&[#/Dc$L{A6pd;syj$,6 !I}%Hg4 p$1~wIya;KYyL$Csi!nEIP$a '5 >ikK$_P ۤ9_ԒtnIW"8u>L?(oGr $ӿl8k_Dq93$RJZ ?D/g;v{fgj:Md97`ZV^1mQfEw{ZdJ枱\̝ ȼ [̅ ᳈yK;dX-]ʽ4BH'>s|dPvLD[Tv;' W|'~!/59P煀AQ".c #ˆל D98D!'Tl<(R q88H#ܢT+T8TC|g{-:{XV<;ǧt1| 1z<ЄNvHnƹg mpkcvw>8pB/^Uw$`fY`\% 4Q{qLTy.ڸ٠ya 7dqs]`[|  Ζm:ނmB ̣Q[̞-Kk'⧗yG} " =V1T^Q{(}(MY(OWbT>$N=u7LJ"&:2F0(G#GyxSW6Nu2=[\o ;d qUg2Ɓmt|V\:x&ۻJ VUacKFK/p깚RBumjڽA^{uB!3*]A ,%܃=ӠC,aAkiۓ{&//Z 2H ַ:E=,y`aݞCN!]ͬWgޖ47yͦt'5--7VrشXsʖVfFWdZn & T9y31v(|hggbVneAԳ&D2]LezPK) Z8 IƆMhEUv&eÒ@t{MXB`slתS}'?Tp= ,_ch8L}xø-uXTFHE&7FQ"}M~5V(kwfO f:-Όsϲ+ܫ7U*6uS4K~Ӯ A?*c\odc(_sGT4R`:BjB8*9כ[:NG zβia_.>$ j_=̓ jvܹ;줏{EK|gh^-x[ =7u>]0ω0tu hit/59YGHC)_fŷg"y-5i[yzB9rx/aIG9C; UF绨+/eS<4b#A qWA|*{3ٵz0ʳ.n[<\5Sӻ6QXfy*Ջsg_owg#Yt $F.@Wg 8|'{AOh!X؉#l%C, ?2z; p+ҁu^.T56kM]ك(.nDpr*r ̭S2.Gv !߮uebS$-d:g* vhzQ(<n^{cJaQmW.[P;ʹ+$!+n!I]x$?]i!x{cH#A(@qF`n..<iΝ\}[^FqhTb3͔OxҵgL1z]T ˜xV ]D>DfGQ<4!mx#j!!O)Iu*Rܠ|>B,^AC[!A5e}V'3yI4R_.^FOj3TPc#*c4:I ue9F ʕP)=$$Qe<*[ Ј5Gfex =eER_C@u݉4N|f|~!/|>pAggz`$] 2V% #4gL8>)e_Z+ry!{I}%$;4Ewq>G =1 Q(RS[%@)+mCF/( JU(Dfc4PE.*A@Y"w߳p72Nx*>xyyY{phO~sI# qA^L%V!Z-`]7@zǟ\cngwᳰҋGJ" u;:4wsH9Eஃ|}g y~ =ECRhwU](;yy T,A90Uo`v*2Aа"ܠܒ@ EI]%ETN?}J{DwpvB *{=~OcfzܺWئh`0׬^"ODDDq;G-S,I˛8g.]mSd7>_?| d] :P?@0Kyx_Qo:3ϯ^oW{+V-pBBeAW`~=ri; v #qr E$ ILC}iu-"t \UFAu{$ 8@Qރ*$ Uq iw}<6t1\MG {OqO.ȟ}zHOTD K!3&ˀMW3L!B#wӷ~\望l9}7o)I'`\O9fJzOs2>02j_|S}QTHjȨ+(ٝ1N8hLquTS0^A-*q  ְ߸;.6f9wq`x{_'>Dz<@J4<@p Y\#gsiIx!$ϻ8˯w靌2%SΦYCz{j2) Eh26DW+N4J(!ֱV1ȂȜADڑZ(l#D8&w"4-]|熓t\^Rl|Ou>}!ڟ\!~#E:&?zz2.>]TVlֿMӭ|1'zz!f?&AM]c?ksJ"ZMC~ rD9|,gNU^gFwixIUA7BيrN85RKaj*Dwh/:!SyO~yOY?~0>??{fW6zCHU״Z@A&r7? z z9S軶u:B#~TǼ陋 _D&z/z{O7jPC@h ꁰ ]+B {8N*0Ò @Ǝu TQthkP"kQU3C|8ID]?Pi:}7'ht=yOrҸz~ͭB8ט8y!RL3O'~HQO 푎g(G-W;黹kqoǿDr⥱(\[SvBԼs4R *vCI[i  u뤂QQ x3PO y4h <;=vˤn82qt빸(a*i70SO/$${h)bl{Ae7S lUc,ZGIb(D$asހU(G"lI5$Φt[=wy!g"C)``{"wb89 ^C_2j=XFgnN{hϰƱ0eX@e^xE*s^Yny޾:={nQ1|7s!ݽ>Wr`CЁY /xRaz>ACzū}SiTKJ&ABn0N|Ž"3xf|"Jj |װ~Ž#a x AN%{֌:%ne8 rjzo T+/Apv2 fYNv#] v-lIdW3W{nTec9Oj52ثw$h}ڋFH`LE|%k XYA_7mFA=l峊ZٝSmd? hkZ9-CRCT^DNZgKۮf+JiEt{S!b9If'UT24GJ őv'Wy8p};xʜ]Q=Jʆףqn%1;&V7VE/:-Wd E,i"`qAnA"vۊ#H[ ϞDz3ց,D};fAC}ӻHv (K}'d^;5F ͘\LՔhwhp@kºQ[s" *8w=t]s{ܠ=hܟ?wO\pGP׈!qmwRuũF^DLqو@zrwpQwCtZc9ww~,q}3"0 `X"G4AAyt"iT.*-v<^1 g*qP"q GE+y1h/(A&'o<ъ=:B7=! m!وe1i^*W#[]̚hvcF>=%2*UsݭvKl0(L|'KtGkaB{﹫_ k+^B8MqU29Z108);$iohUOI} `!{x5*v:WidCy?>g? SmEE Ho5Kymרk56F(㦽w> - d⼪sCZT!.LLf{nK+ K TdA.h#YD2{WQHNz3u[{y: jV`rA *G Y}RҢ|v\*5 dij$`iLF=/yc<4b4˰}2<Y(D, 轾fu1>"EN"Xq'ZS(nygLw%+̾q'FW;\fURߌX7Z]UxP_kPacm$,y]HI J!Z&!gs1<{c10\c|{Żȍ;㽹"؜9RZ4gh{F@uAf/f8iwxhϭJ#DEckTbmMenJXN?]ɐꚊ!u+ Va:Ùl. hFk)YPTϖSv}W"̸ p14`0Yb9fgfr\'h*ΩE(TXQv} bi$Uwe`*2wO AW<=d {ϟ>"$QRXjRy[R)KqP;0V|ZoJUKRfUiW CLy7f欆 Gf=rLduum^л\Ua#KᶱI;B i.OeU=#N"R#)R)DA 56B >*6o϶Ÿ7C"%zNhLâsAp29Wim!kPy`6s~CS7,Π&|YUCHee# Q#`'ھ *[uԳhQ 7}~i&@9T%S|Nx~1IYN195 7$ /LV{fаR/>`zsm_|HSR(UD?VnĚSrcB/NNBa-Ҙ㋔vw캭 _Ἶ^^/y$Q~/f|}@@| :zh6QPdZrQܭ2niֿ&]?eswRw=Χ8<{eV~˃z/S?}Xi1*@JTAtzU"puD 5lH 2C^]pu@Dw~aup_343><Džpmu.Y  黊km>?YI(H㞦)30>A?ߗ ,U0P"4)a(55i8@FkuUa+EBEA=7~p}Dž%_"N#x^ Y^&ĕV~=puzD*ϫю$X{ Վz'nTOxAֺl";S뵪CaRiG$5&X﹪}E:C+&c QR&l5a lWʭ GGؐv w u(hhU$pf/x׆\s]_Uސٗ=3IkgD r+uh |Qvl} 4}jX*e] RL$SE #/=_n.qs>8}n&3Ut`2Rס_t@yMČq{C]qrAUi F+UU-w=Jqyy߳b iOCp3ü1񃫠򔿽zp!O@8zY eVZu'Y|^}uw3+#NEN_-O6b0t.j'!) BBN(S \Aq!-hH<w=Ff(򛭤z ]{@`o!jrC/|׼(x CaU>r"Dx=8!OSg(Z  tڎѲyWpo cgΒ{G-qI?"aGp/O#p}tHP5U49`A85M`gM48H[<VcQ-Ω)hp=Q!0`cH /3$\@D z Sy,.KFJa`}z@dqBW^YD bs;}gj(8~lU= M9&ygPq)a~ `lE"QI C҉xmP;$9j65[ӗޚ~ OvW?37r:Q=O|>> v }3p|&P ?}I}'ȡ; I'6R:wDrltbŹ0@|ec$R>p}V>![T Ax)w9NTh$'1N {=eEP'hD?p(u\ǿ7R@z]pq$Oƒo67mQE~?rߥ$N%5J$ ~}񼿧iW>0ƻc\e o; WUq/% YR90HX7j)0ϖLGL 28iim+U'jG=q̽ +=zGXpVcF>]݃P톦Rȅ/w&=ui̽^@niU301(TCeӭ t/AWB X:3.h*uj¯.f(:^Κ St!@#:4_i[^qE̝=Gq=י8h Yx4w#IbXZ6<'fB`4׷3SֶGW8{s{QɘFXQ&`$idX#z2 oIﴞw5[7rwrk.u)cE[BϹٗ0,D<92w>~>Oqܷb 38?#5㲷HЏ+ԈUT.4V;40߳#H%k*&C,q&fO])--Aݝ_8iJ!)x*jlȨ*Z h[E ah@R6]=|0nmv՝+RXU{(PtS+;w뷓x{we^Lg9&%震HRn BuXHߡTӹU: %ŵJUQ{TRV( ґ è*ڻT1uuqcT[HQ*]H}[w0nM<.*' Ho]X3;iVVA9m|-zb F=;ATV{66 V3ZXthZ &f6<] {=*oQ@|OP9zYޢzsՙw $z&rya {O~6/zKGNŽq":mvx)vd@Xɒ^A-Mjw1,SX&J7hN 5wQu|`9=eN`j `/Jw"l&gsYE{im*G]eGTiobC^s}HG_IV187Hd+zN*cw[tnRQ\,vn#X˝{D.kEasn% Qѻ3}o^rO4sC~="t`xsu~|Ʊ>) cx$"z/#xOHDN0*j #q e c&V60L[ZmXx9tOM/\m>%$xI:Пcd-p҂&.],;M h;zsȂ|B"Gi[,(!Ar!v9%:laq"\ڂUئV%=YaB!6-h՛#O'Oܵ۫7R\㦣|rD#HH`5!T3* A1D!L#>Ж`#}9%IC VO>qߍ{<;e='•/'M/y^OQ|a=RIAŘzOL>8%.z؀?smRl=fJl0t.r>*!=l7a\>NJ턓3igMRt?tBWˆPZrhR!"C(!;458ȌAn @q(ձjou7?}~/gy|qdXĆyyא`x 816 ]'H9k^*yʞIθ?5o۹ps˶Cڤ8佮<nGCg(hP36H @5UQ"䛂PɫO Yqx3)Su!}(>7|hNFr 2gso\  'q$$XeJh]mMK+F& kn\`߳ÿ~z@zt qRHX.>GEcjN0SD pg&{kYM핕w'/||}bA48`1~m8w>.T>wd3F}~?SA], 4Z1.4ԫHR F)%BؑJZQQGi&?'[GLPA g'2Ks,# x$ rQ:Wfχz"禓_Hg,T 4bUm]Jg 9{vӸ|Ï ##d LhZ1ZB҄لB!"nM6n#*od뺓8)ff>f4st^a0=C8zo߃xd<.Xu(Uc!E"P|'$BQ֡EЬ<@յIԑqw!(`d:"&q*/˪ |Y}7_?8xx0㋋ I"ih "XVbM G0Hf֤Ċ 45s} ߳Q:v@ /;#Bn ۦRdlr>PǤ];b!>~ļo'~ަt78=2Ϡ /sy[=u^Fqk~{s p1ʇ JH5`@,@(6Ă) SG@h+@tҺHWWTx*we{ff' +.v}r׽A'bԠi '"qPt!]:޿4pP:9b(T;mG1EMKcsh݉ms}mĨ6rET*"HC-kFA?8ĊzjPn=uԣ1LӰ7!CQ^ae|pʔHhfA`ҭYDdˀu:5 1Yx^+X(:ESZ+]TWB?wsߍj2W1Ndlٱ Ix?A SCvn؍ԽEGp"c}0%X<16F $0d_?v&1fN^y&{vS ؼMB} .ÛFQohX!c6_=n=v%{X̆z&^9}dvȡ&+`J|ċq̢3QzW(D"ՙubH!ێɔ,$<x _n K*U \/|OeSՑ5F5b#[PO?\}f&OXLo,vVӵ$aܢg?XIadcda ]ڼuH.c2JNsp^q+BRsgt7\Kv;yǻʈ++`|7c.q8H ML=Uk2C繷ȪSn2$t1n[k] cfٓ߁M{K,g0`TXz*tcy>-SPm?qo meXʤ^GN(BtH:64((s|<}T|;L@zaLQ 'CA朹giҺi\0L*.~\O=@&A8gs7y‡QsRin*rZ!۬#wSqgOs6)p7x*37gm.H]z^m^-V %.ޙ O"y)8\^obg5 d")Ekٸ$G]9yq3F-2$.<]'ahëP d8ͧJlڄ;7bç=[QݘIh>f̮4q$U: zq! ΙsIF&,?Nk]R6yeNYOCt _Fcxcۣ{hɟh"A<~yľ2lATH⎷v0ډIJ@mUX!|[eyCM0vf{dUUfg7Is$,/gߘ}u٨9{ɰs7U]!_0Xgd_kj%iجg6 #'2Ԣ-OFɜEvM$I$i+mN<`f0"| 9AHd3Vv&\Ѥ(óOȎ\>fTp^$iܳBdI "ҏNz#S Hb[:U763P+!G?xiE@WrCs׌‹)4eΤvy Hjb]5ȉK(Q  u"*W41AЬX-P>x3ﮦ >G8uUVF+=[;ɚTA edJtâ9DLs_sa|񝏅S(vS ęb58*O}A~}n!~e!bFyxEbCMwPKjJ;4MP@e[#MR5+H)V@$!h ?}37}C3~ѴvyƛmӪa޺PzU{ `e5TCb/,kc`z]n F3%"C\oŞ)OsSB_9۳w\ryP>Nut<:B߻>}RCA!]V88 B 28.D7_ vňʨd4߿fgWapݾy +Aev-[n&!A)=#m}VяPHVKsx``p>9Ӿ+}EUv=/sMC_Y[nwgr]# ;/b-4vvrӼާCG}DX(ɐŊҡ3,DJA+?W3Qh0`D?w==y_yϼ/lLGOO34Mcsy,Ni5<]޳2xR2 D1|}}t:|gbAjP&Д ǭQ8,f> 1f0`vX躮m54#HSAKc~( [mOY8ƀHKdg?RqG4- 2clւ<>$cܸ#y%" QqZ=ø`G5a- 'قD kw3۟KS_j ړr . jztDzI'8zH nE[Cp F)D J&VH1 A :EGAQu>)gw !4hcB<>o‡"V^$A ^&X~,9nfgӳ~\\<\t(@wy{Nbn H "sN*lIyr_8-is$UۑӲC~=&.)aSAHR's^ ^NJD:18prJzB07AGC͹_y O{wǗϼp$wxakT>B&{7B-wkC`2X%%PQt W m~qކs--plna#~2˻!td S{q-B)fjj"!װ#F!X$*6$J")jt(Z%@Ejj4,Rf 4Ay=ܜ B4CC@+ č`@֡PB֍F$KFE-+`@ ,U'+ 8"@A';!k0G} xAL HSSRdP&&䞸.ҒI#4{`BjxṴѨ@.G -) r_JhF1Y ̨2`axunړtdX~q06_d8M'#a!n|{Ӟnz0ZI0f湩rO KDMg3]A3d`(LZUD|KHSZG;h7z y~qP JI5?F+|I&di]ϛ{f*{%P{ل`@sfa9Lm! ipf+[`cz7RRCYjMg,IQ ՋA;rSqoϻ!C+yr;-9KjQlw5!n]`u#[:,}+B5'N;ܐ{bFvq[ޯxԑOhӇ`1&>7,xZf8rJ&:'gS>m֊{s3uOޣ&zjݳ+u`݃i#Иlv.iD[~("vաYzhFy_U&FK8}652G1h= i?a}w I;]:v>ƦR?0Q0 ong7</ PÒoR؟[-a<66&%# .0L|ܟD FHJ HF(AP `* KIMPj6ATu Q;쯶>ՙpO zܲ(02 KjLf'83fd g{2E۝t,tsU}yfi4g0KS4Qy vT:fDeچb ze v`>06Nb7:1N @\O+Q!uZQU C&=ٷr>3_馝IH׮.u'fB,í? AX> >2Uvvڅ/l_J~6e5B1E ~)bzވU!YBfPxsac.I0I:Xs3UMžpFٗ]68;S걚΄W.g<_><lc"xRSěH[n&kHjҼÞ|3ZIk;qR)\V)E7q)lAj9"k^(ugg}-'zndC33/=\!"Aa/oM;xNHrAc窧eL#fV>lcQ]s s,Xk+Ƶ X5;+YBnm_.;&WȖiL|̧p%V=iкH8Al^0V)#r -!͠dD#nMx9G,0zh qf=Ƨyx4rl-Dy3z{9sfÀћC̞1OfUǾ*G [6! WH-xC(uPYб].UMMgX#d,3D[vvB:sh'X(u }Z7$ZzfD?v&-`niaI=ś͎򖺗HN-5og&2Y#i\oB ]٠0b`R-"_b7A݃?!)#؇ HH>?. ƒ_?^ۘPBΛD([u{_oMQmyz͹{tOfi^j\y{`Kci3:wR";jwL$OvǮ}4i{Vb*`#r;J3:F=ဵ"άY CҼh642Z2H./z {Yjb3H0ĊђU_ak|Z:B*2`[{9Ċ9Isٟ 1=݄'P$vC|w}WSCIuU *I'7pd._9;'?N{"XMrr[#BDQ3h#[d8?>霎uMHhhFKP*Vԃ RlQ:, 5!H$2ґuf<>7/[5~ׅxx#ywu#Dag#}"8?_ 7RjMh7Ӥ*6u'`n聡 J34yM ;GVckcY')ܕ8FH|S?R@'ֆhY6~ο>Zݡu BQVh{O>hObk_]CT)!ȰR!SCP#-jB$RhF#gfp۞}7=\ ;<xW꣆Rs}c:}"3B P mhXFˡCiSK)N5tNВWAv! ?>"O$UQr& ]'7>D1m=BVX@5$2G20mXİe{m(/oa {ruIPVT,?9|fOAP+US(Q#$ &XoOug>ϨmIIc0i;4yZ NI69Rf_aTg;f%-'J/S?$#!ijI &`jIBK#XB-`ѥ#m4 :v,0}?>~{gz+@`A#P|&OD("x1mv$>ܗ{t kʨar;KOl=9N;{ώ>`OܸYM^rŊ>"Qd DBs:fҾṸχ}5#!-FE(BDKOx9-l+B:T=g_3Ǘ Ӈ$߰/? >$%1?oVz^*=܌rDֽ,N~|,zo ! ᾞkdDTPP77}.`*6 #S"俷el&&Ě5SuujF+;X-}?w1c8@+u!XP{)jr ҡ.*%[#4-+YO?ͣÒ}==߳q7 LWNIF݊`ѷUݝ1 > >Cs۴owrꚇd`14\V1CÓ!D,D@:u)@A~领fm>qy?S")d{a'7@m$32αȒoH~T EķJR@YK)k&- Ji l[Z!mwي0E}Wqر ><~O7)lH 2(-oWq{"Nr9d!Y/75èC:hИWŘC+tP7ۘChZ}4} i37z;y4PE].6ߖ+QAp>R&>@HBZqWz2f&ںMBX:/Xw;hS}qWBFL긶fš$QgScJk1]r"5>GL䱷I>F vRjإ:ԕv/2(uI7ARxY֡oWlWU`Tw %K6HxSWsgC<[dx sûqUfIuQ 7bwCPÁ=]054Kl">O.nz|8,{Wa\f'e)On;LU6eʜ$_s\L]4.DO)*2Ɇ! +4bBFȤu4 N469e]{_g[бC'\üt3kKFKòf7U 6b_8ϋ0o`EQAnCNLiַ=i :ؤ7%77Wyi%sС%\TDTڎH%* qJYLhB0;ݾ"LDbL|Dzr|%B3gBƊᜐnk >+O$K쭐9o }jZIyxH`! UE,'uGa(C;uM "<36xs7R#i)r飀Åx]֮1Ogɗ.н(!9prfAns97?GJf7y?&4JVKr Uu->8HXv#X0ʈTNGm8OMrn>g GzZ\>v< 2 d{dlP@bGz9%Q^Խӻ-uttv eh;^\c 򷔻"=!g< pw6;Sr;[n $M-ˇRmED -BZ[`Qk܎|_v\QđՑȒD:AK Y`l\7m5{.6fg UW3EuD,]s(# #yB{B"?C2A(i {üQ]pf V xŞ@MS!l~B/}Z4]nѲ .Ǿp3ۮGfA0/Y8t<ۂ,Glk4%RJ]"m ^3WԸC k_֊D./Aʣ;٣&z< Q<.h ktOԌx(.ٜCY~ɹ,Hdyl obV&Ij?eTi*jG. r,H%R5Ň0YI sx<]L=%l#iI}Pf[VKK"A@ħh)aPؾ1ω&(&Pj7 4OC^ߠ_@cy7]sUkqiDsy/yuX ;[K.u ud4. dȬVA>UʝԊA҆xM9xDHj 5$^& M#`ݜ5wTQl)7J.>3nygG>fǞ^~]y5%L]^?uOW BM7*4KR@* F}tf?ޤWʼA+Vc]3y`gU!Ό$<usW~ӽ]g(@>_A)F Ndg'c@<4 :,Q5c<U  cerfQ/OWzQf@Lv>iT16IUOaNJ|6'ˤ&Y_C*Xwx\c}^n{〈8OywRj4/u±[]>Wk[]v*@ɉߏ>V [!Jn !@ZB7BTJ[cRXMu-fbD+Xaػ@8@G]Խ!̤@ Ы#Kp>9f`vI7OX풟w3F]35COyqK1a#+E4#F0X}hݏl!W_n f`Ɣ8ߝ8qgn@ʹ^q5>PzTR\$;I$:2N0Sd ʣ7PS;~j0(@Hnp B.4 +RU,H tօ!BB,4ZR!!Q&_~< ~E%6ޤc7Ҿz'>vJ̨";*]~߸bցp W^L!B;vݡ]gCG7m,3p1/99n[V{n[k6y]ColaG9VB `%(CO=y9P.Ṡ~w1S@Lᵤ`eia@Thjhm3 (BJ@1jnH7 tîvܯD*6it>E{&fԟd/=G_?L}}gh/ۘ|zzi˂¤sExe0}gӲq10K.Gy}}dWy9w!_*h2*)FC Ry9fa0vPچ;4s9; (}]:?g߿~< J mH-5օ6.+*ir t뺚JR:ԠP$"XX ?^!Kp!<a}ݫH# HDF]l̕Fpi:_x@D'ȟy#FSs0>k=MC3w4v - >;w CZ@Ql4(@`5c!HEԶ:eLB7t 蚍V#Ȇ=;,pyg,&;vx{ې=HDw8د /HG_xS+ վ2:>M= þg.4GSk<;, yHw022%ה|ju/aJ~1>rʫ-/}y7_湋W9-;ڣhcGӓ&ÐmSŠB/ W$Ga ;Tvg 8s@N6A "*iH Vj]JBj@2T98a)wwo5?~n6+ fP`!`;~ZOߏʵ(Br>ϯOʴ)~/h!p 7^~A`UeY2 OpZaG ,"zlyf,(f}뇎N߅7}9'4ҹBwq~{X(|ÙEm *2>9=0/_9Nl^J[1HdgJ|JpgeUPne@fgf' S'%fI9=`:# _OjXT [Bj@hoZ0Rr&H<@ X'w!5]PX 8x;A0P0Ij>ϟ{j>A_> y{a!c;s #H}[d'w ;uH= b;Ox~oL]eL;b 0:QFq9sl$$_Ha '08P * wIF+snm˻nEͿZ&nܩ\^||<PZpw!DCm֕u(QREU]kUjkK:I Bmِ4v:cgAz ]S/zAe{޸A;3ӝ!wWC"MT**"`TTJ%PTBU*$DDQB+m- kmݳ]- P!T*I!TH!** ( clE"*QB&Q)RRPE)TEURJlkUTTE!%%$BRB%(H%DHIER*JTAZh"QURA!JTBRJIEH*RI m$PI* @5J2!@T*Q*UQJU)FM* @)U(PDIUJR{i]mʫR6&6Z-6[6{|Gsݶrs_$yj9F)쇼QYlMimB%<I{}Gǥ]WfxzH^cD laZmPm yMy #y xq Tpw.ښJ(6fbM%JX໙8, a]=>>s½RHWHU6իA&YZǦ]s8 WNn Wxz#:N3`<]u 灬6LPfS,̢m\zjxy `Pona2['l bv֠}ڗ<J(P(S1R~LD@ODJ)&j%SzU"d#JSa&h?_@@Y{ Ti1Nj*K ~Jص E6t7,ty ]v,iSciW{miH4{-&^-4TnQ,չ:mIK[idZf- ji4]֮onkny4mclQlmj666SmbmLnmTn]Rhzz׶+%cuݨ5v"$]WzzS.놹eR4]ݹ*I̥^YT{4_&cTIlZMI=–M -1S\rv{vݺi7f(Ngw]5.F+\*Dc"b3]Q.eԚL $.d3+oV(ɮݮY]Wv" f:.") ,vө6"W]i4պj[Eޑo[^Y*Slv)4&3^&E,VSFKv顗Wucݺ0WW-]ƫmͭrW[[W[f[ ah_VO'_Qa_Cjڋ%VmЛJߡ[UJoMo 2?Q_dY E~HE~PT@hj})mV'lM CjFطP>/Ÿ4#eCiuM@p2*ESI*~--~FMfTfً}~[U[*ʔ?~ ~ʶE~M32Xh5QTmiKh}_~H?a(AQTjMo5]5EmڪkrFѮ./y{{;Fe˺uً2u/=;r{]묚]:;oqΗcy:n#U$uEk˻9jXmMCM2D'vEPB&(k|GM_;|բvJm47ve2ls=݆:۩psvhwnMwmtuN75u.N^v"qνo^ӉJ|O;ܸÜuIonk8Nz5`p|u*vt; I6 G#lM ۔\Xwo,NޠKoju7w)]7@6 c)ěNݐu箨rBn7W wu8&.'9L^mo.^^[lk+%YׯxW"w\s](N9twne]ˑn:@\v׻zwuqt" Ȏ]*읨slw{vH&]g::򷖏Kzy= O9lN&yo1tŢ˅W[6lu{yQܮͺ{ݧ^ZZ6+ -6nXF@,hhҊLƲ#nݽt-CUy9(׫\޻s"t\HY"wϟ;^Gͯ"ޗ#h(ӥ({mtp!ֻ9F\ysݻE[ޯfb^fcEEu; hhwZ˛Bl'j*#nWňˬDXDSuAԵp{hQ&$X47σ NXѲ͢ Csx"q*")r,#b{^oZdv35r-u;TX(brLd%) 6,TuwkEd(K%sF"+8.aG[tڊ,ZlX]{| IQI*wW,bz0[|~\sގkuǗH;^3g{չF*]%\.!!,TXCdj6h4dȣ%8]F(Pkɩ4lELcC [箯4sXK͓A5JJ5a4fLM]6#o/yƢ3k]Qfk{MKL(AE@IicGs\^ʣcJ躹z]|l,XHѣEc^4g_=+6LlhQTI̓QHiWuu,Vp+|&&DEFE$X1cuX,wMvۆlh%SYѝw. ^z̏kQãv(mwnݲ$T]m{{\W#IHTYAl!\o[S [S#ShtK]-v.ر&5p7wX^={\Ѣ 7nF7.zOYӂ據toI=sklF/uݮO7o32&`Z¦IIsI3 7{۩tݎ|ws9;FE)1dЗ>XtĘmBI)Iw{7ьۅ.o3=x]_^XT͙)DJ ۏi#w1M3rs2aYshtd]򧳶5]sۼkؙ3|/75B]nb딖1w#t{6Vc9LӨ$;sRdUvrd twBɷ|wscW8F]Mːɞ+{dɭްa&;ۜ[w8[ޯ<{zv,u;uvFǴWQndghbI;.pLs]%DӚ|wrqNs޹4b6{(״=8\2c=uxݽ7Jw\:Qʻ#q>w\5w' MIdъ^Iz׻Kt9wM@Ւ- ji1F{Ro9Ȯ{΍˝{r[v+N^k\t*+ĺ΋t;'z[7{t׎8Hn@ ue %Ew>k7,q9ە玺SdMFʐM1"AQGo3w\.ޣ um&u$M m C9;w\svuqܺަv .Lnu˸(nSa]἞v绻8|twnI佽fw+=]ݻ빼{馽9B{ݥ4m6&H(M)7v]˳||v|b|nHܶ"[QBMnW6ѫE\(LEb"nZDk\Z1*4Qso$tu.Q ۢSccho`is˧u.rWỺݛ]tӇ5ӥr7xWw%.st˩O;w71x먠uN똻;:^];22vh6erINA( :l)IEd>rF"u2uh!urB4cW_=rnWKN]oQFŐ׽MV&Z6.Ur* E&c۩"bbh@6 w{Щ~mjSe$F^籨כ5-b$u/z-31w)'lM%&Gb׭0mb,nK||_-Q;rw=y^{JWsyY ]u޹FѷWfv4p;Dwv^^nj:ʺXW#N(RQ][ ]4b/Nx(5:|] ]Mt'[ק{c=vd;{^r"5۞=C׎]wuvأ6MVD)˷)KSe(0]ߍ7nsq1ܾ{˖Ouݙ{u!͗ 4v`f`)"iΌK8^wryzt(qb# B"LI2(*4M L&O_|Uvwr\/g]ה[ȹE^r]zHy\r.Iqty\ܱˑͼ#{&W]wrݢo_r2&/>i.{!&dUf-}+\<#y$I@ !6ԻS McwrI7qW" mXa "tł雫ji5.*)'yIiI\hy!Jz@ZX{V$&l\y29}$phĸI-$%NA}ئ gL0&!R? ifM XP1L 2{{i D(V2XS4i^Wv@FM0I޺edu^whTH 4]?o~lpAI(%Y[-Wk4^C! 1 ł+ub ` I{]Lt(7FznTso2fx\37c4Ӄ_q!#B<mۿ;q ΛDžWWGjʹlUS]*r'eT|JI$ƻ;{7x 駲 y׳³qD+ šhqBUF.OGEmfWU -A~)`v kk*R"':[V0!d9:nP!/2f`)o >7!WNk~à;S~x/|4J!+ۆstӃƌ\s$*xGl}iTMu͇$R=bo^Zʯ)q%{K<4yw(;iG[II!!"":)R!lNX!n|ÛgJ+G>!t49 BkPӱvyHhA){ ^c_fs`Diw' ŲrsصG`@gG̵إ]{ XZ`˶ ~|W!mh@{0VU;;6k;2v@.мR C.S)u=}M\ ^wrpHGQS#ZduD o IcQ<>,{ RAVľ7/v2vttӺcscfSw#9ۖr%c{䣖-L|SXh6.a:B.eAC*qg #XaszCJT]ج3 19-@ާAR+t}'A۾C[ CLEbSsN=_o^9DYάX٭A{{[WS&F5R7I\d$hqO}/==<6.@3ig.9&^bYOmv/V=?Md>c쭹2vUoMQho&GcwFxYvYw؏(.VGsPӸ* jk pq뫻4OPQ6/(&7c&s{Ymϖʒv}ۓ/U_F 2$Ag$͝oe׳dljִĩqbܗXzlWDŽN.=W:u;6{ӳ$սTzAkOl+S`E,fz{R)tcb"3c#T8vf\3Y ֬݋q6h)fȟcb db ޫ( `]N!cEσz3/λ#F.!^kÁڟnfJPB18D"FUtX,O<_t 8ʚFC(J& J/74@:S֯JVk-d7SV|}./kw0ߴ.U'95GX,-B)$Y.tݘC\ǝN\Pa=A&5gKf{#!w: YXieP5&2ȝ7U飖犥 @8OηF lf$IH$J:l!g^;US^'4 .>>  L_~>'k}_Ph>=O !}7{2{=ZSA^[YBͅ$N Ϯf0{@w'>qHT[#WLk2("kx @s+:Gmgz h5CtE-mAH=xZ*3Ē0 tٗZ&}C*-OZ2 G%~ }{K¢sJMއ*Iu&Gs-R:USt]q8)Zn6֌zT'O:Q!)i"ֵ֥v#YO,K.s#R޾Q{^WIKqfq 1+YVǺמ8&n҅kܰ8=>@QuU_ ŅᾋU0R 05y5]ݕ (^#evfCH_m_ unR'QffC78n+_okbHT= *R_9UA3q)Ng3o[X2;G5wxR|38qbCFbar,'\+4nL%ncÝ\]5_˝!0ajT=9iu.;wh䱸 \@)4x4ryȹw^C)vePEm<IVus=Vs؍ykn>̼K6Y.᱒)y;& qml5w.+Uf]K{XWnq`@"PλVd7^,JO:+0}_qIq v}u, l_]kFs1*C&{@>ZA 4_P2yUyFG4+c^e8׽aVHF/ph3uF}E|y{G{gU&TS6u99{utnoUg۰q\G%s,H/Z!"V Ň;ulf v2zʨfׂ]C25uh> &W˭w:>$c W,t ;jruuXi>b=ۋvpCMyD(v^bU1r]ϋ؆rd"0OȰN\"l#=[. &?{秐 mXd@#%amOVl^XCqe,OH aAM6R~1.K X𖒘=2=Mm+x/j(EWư4̡D<5AK$[i^4=BB?"&lodH2s>fYb(-z夬E(_wKI+)orMڸeiD=מUsNt;yYgY.uS-[_:!d >@Us OzybƊ MHGZ0Gk~K hA@B/~s(M(Vxܾ˼A1 HA@QH #D!PPو]r ߭~zBePJAHSBD*&?ߗ{L~{_H(̂Bn^`IjPTĕ)DXЂ=^D;s‰(rYNU Ek\ʅlT湣w,=og#8v.iwtEw0fnMb[+MIfwy|Ӎx=Qwd Հ/qgI>+yyȪCI#04.P^#d<}J=j.5Z须4 uzϸJʗ: ۚl2]ҲiʝZ|:zbjH\mCpt^M7zn5f)xX%)X^]cy-6 V'f!Kv0h]4-8CfV5/4|lRTLDzxͤf\؟f7nx8DΣqAz 6=4#04&aC1.ZgJV9,MGpwwsA!13eG *ĬJ  ʼnD :BI-5Jj¤ cUeoW^rVt: J"aBU |nGF<k5a~= щVB>qP=q|BGbjv-PU\W>v%wsFۓF*Ѻt]=&p.3{>/F} SV.8~v=bz+*y>_7_GwEkPV(a_.u1=(i_5ǯ.͠ +PUn->y{u utzKj=oՁ~,ς˂պ #B {'^9owcy4#zb;HQ]Kvv{SQb̟S^;ۂ$W" >:3f3s^]4Ca5[K}>Hex4AJ|_G՞޷Ҧaˤ}j-pvqNd!9=z̡×^9Vqe`&>or}us>d&cʔ S y8S}}\DT[lkq[Z1k}F|ܦP&nOy܊M<η]g0cZ!gzD(X.!EpϤ_bQj4!}2MWgj:#i0g/o%{ϊ " Jts)(PUhPJMKccblV73%P QkK`1^xp~J}n#>RbH#- ڵe sXmؒZ)nΝ'rZ(y˷vX4%>!}cY |ZoyJ4xҳIf5X|rN/8{wqlRxU`\ ["Hξ\u-\@Q Px{Ϸ޶}S(ɵ_$ 類U/jOI|'f  R{{}<ݧ;bsq4ˋs]֜B_Q7˻;>ٓߝB-]\N$dJDg~>,0CF L锾b |}y''f+\P?A|d~B=M[u8džN<>p!ɅLrvp3ѥ=xB09JB^,#sһuI:U%_4 T}-mͿ_t[Th~ދ!$|̜H 翟4>'uy_,m jgSٶm6^5DtTUZZW?sMtt}pD[#4̋UB9]Ztpusslqu9;;s|s:siW#Ϲ͙jpU+ .\Vqn>ySZ\ 0(%O]X*X$%SUC R"x()RԄeig/8ؖO('6k}J6©22PI&Q$6{TH}?f$ v@[=m\߷qo]mgSrKo_ [}a΄(ڣ޻s+uֿӴa6Y~_88#O˫Yk#RB %BnT +n\ * n@DZP2!! @jD_8QdnhjNxj9Zfi5WJUɬ}*>fp?JC١N'gG~''A}jPY};镂ZB!+f%4@* #Џ|*1;XwP$H} 灻 Fm,jJR(5vMc4,U6җ&a(0!d m- R)MsRґ R*g_ pv5bvgpV$D%.K2/TP|N~ۺ!{8CR. |GH_-]忭' $/ڕVU(@Z:rluM%‹t\uroZ&I M^+t |Wx6A/|hGu}N1UaLgm(&9 bA+5I|}|Nd^eV_]6ѭm!x5W61$`'=JXJ&Ff.kJCFwMХ QQkM T*T V\% 7g^g{xWkZ%X(R0m)+qRT ?{ Y4lA|eX^}G1R$?z+yR,Gy>xG{@ۨ=T 0P2 2ԶJ>T‹/vBb+NO4&b I$t@ _S=K g+ʤ[W>~pΎ!#gĆmyn"󑯽+'}I 0qX~?F9K!Nk}_wN*A;S~B|4D}ن>x>➳ȾJؘ3pvqWK[7Z~LELFx$xHDz>!8ffK ܝ| )SÛe -$UcxCR~b}j+LP}O}_NQwguXտd>ڎ1>d=}}Х,M-˭;sMΫw֮5QM͚ZQ%CL١hH[!@7G]]4h])hQf PZҖA7PH}ퟃo~~3Xe ϑ°c3d UI;Lჺ1 BU#O&!8'9%ֺQqi ە{2p#qp SYT_f78F{e+"j4=7"`8: zz])O>f ΥR "*/tL&1ofVRl =)޷\ت]'k[KnUdA)r2:#5th뼵3P`:_v*>3nu4صN4xel02K53R)36-$OY1?r,`}B+k&@JͻQ2NC+=}3]=5=qcȁhOáyPfxiy>injWR8{q'0se;[bXg^iVb{RH{XYEk6qr 1 FՏErXN8,9܌(.=.01͖c~>*.Wv o#9񏥃m Swbmvfo؜; KKՋ4s{f-.i* wGbڃy%{1-L{3/ F"u.[NvTvS3̞x^#xJ=sr{/]*msYfUZDȦvbSX's4$)zKN!lP[=qĂL\yq;ǐaVo[z\ ;1; >LUK Y \ |s(@zJrfh`3{Xz-̣jITuSu --ٲJ 'dgGEx3k#ox^;O5zd8ߦ Flx<޿Z|YskSxB=J GSr-L).}[wn ũN n h+Oک쬥rav_w; XD7,L<>Q ܙU~^x 2 +d,!4iT> xX|up5k>95GWn+OL bh`(ײK2ym/j5tuPb]C-fr58x2f``댈DNO"r՞RM[.X*чr3Ԭk\)I.-<:&-#9殴,lM\=:h2۝ga ;ϴ1]L9gMro(1gU؊JMifoJSk }hE v7-_Mn>Ĝ1hr{ZBڅ/{bw{yʚ%VewY-'CD7%޽*W۱\ sFP乚*3ac}fsjGF:uF[˿;C`ajˡm, $r?mYFh0pDPԷF>{9ez)%,cw2Ȼ fw5+g+2y% ;#asT)85r 5fVN<^n*6A0_eVi%r+;^|KvokeU{uju6;s̍WRوgMLݞPMd ,Y]m-Mseᵘs5c5iwrf+}X,1z.nڷ`qiB^K4Wۺn@' \dʎٝ&ܶjG4s0{/Ղ~j9KіEhJ2N|@vᇚڍmtCXھλTB>z{c=N7aպrnw}}Ng"1z2(+ٲ^|x: Y=r^wUg^on^`DtG0% H} ۝f`w˰ޞȅ}]L7 䣹w5nվJ6ȝ .4>͸1.0*'ݩwRwMy^n m"1:*f]g6ml"%:L:ٿg3h0AŠבx87븷r}m8yT;|Gi~نl wgs-3y{ؼgqE2I:f[T$T9 3Fjs6 '.[+3wp4P[t6M0q3_TK'^EUnqCJ7O5~tbn衧0Jr&xRO>} NyVb#Ĩ|4khv߇\RV==xmEYX.2*lO;>Ş|>eN^/)H\qc6+hCRS06KӲU0WuʣX<=3ͯc=>qW68l=*kAcwme:ȧua]>Oua׮Zqkxɭڗ:s._W }{ }#H'V,*ШE4*کcVK{SFpB{fq0,]e]]ZkGvΤ,Scg{:}& mp*&m{eݚ {G~ ʐIsʹKaXJbVNjseMIj] VVm'ƭ+:kyࢣ| v\ d䈧.g|=X軑70fGuBM];I>\}ht‡YCttkpb2:U]f!:XFJrSҩV7b۬i(&Vk!0KA{O3"4GR)-TVIl-Gם-F_n̽cXU3f`/VgvxuZSO9^{rp\/xyyz m{9=P#jƽYe&7pò0+fdw4 n.T=@m)is|;ܮ^y[i{Y^T]ZGf : #6 5_|`I pVsTK?m[2Wweܕ.gtpVێZj.uuǓxnx79zg|]lziUX%H3slDv-^-}e[mBG2zkjUb;)I#_f\=Oc)!M>^*K8L+듏u)YY))GWsoJg,̺RjX_>k(V"u'Zu~F=b+WYݪ;sf-#5-6͛?aBH|OVzΘo\-u7fһ 4.\a}} A~u5y|E|L'M)6ǵF9TLUy^olsUGIZ(;W*[sܠH[PNzَ^AQf:'.B/z}w>4f^;r>[̔Cy:[fYydC qg+zBD6C؎@`$4(U(%z m̡{?ȤP)sč$yrWiy2 WDZKB AJ _.^|mrl:ܤ;_>{9=gr{yy>ϾfH]#7%v5@ϹXF)I jyKS4hLC׳XqU+gv 3z"kWw|Fzx)nJyP@rJDPo7mû=YFl(nNtUSX҇e^- E듏ՙX@\Q,e oב:J$-\(Ud/ykbm| Ht:Y ZfHUɷ6˽\7y@d*vr!F/@T+vbD%#F+8ϰw \M*=aM{I"*نś*+M\|DD}C;FQ\t}^ǞڭR-xQe߱4m/ȌjW^X.RNf;144>1:JQUBK1RidF*wFD:+jN kd}ج z;XWIl\s2_y )ӕ#u쾹1fN+ } 7)'w=t\Ȼ#<}k[ث,isQHk xK)r&mSx$P\eߤ==:}jmZ!F21/pJ-sʫ3{wrQe2s'U*nD<`劝f_7*]BlS0j̗}'g ZGFʤ#ND"+h$'H\s~>6-x#3<7efogŴNK='#UQqJ3# syj"֬ΆeӺmգ@]:A>z[x.}2>n#[y_*EUۮ='Xƙ4xqs˂JL!Fe]TK*5GFk%tvhpq/n/U篈6;3e]yW}G N?[}j`:F(s'}র_mnrd9KzTۆ;vHK Pڎқu{^2dfW^SY6x4c:f-}(iuoyf>Mú('ny+Si #sK]=O^_zU*DrﰩcW-!o++RlL*fJܰv۷TW"z{5׭b[Җ"6j" sBߩ8(՚AGYO.w/e|p7M ؽCcK'# Yu;vw1ȶvps;QQWw+Xy,ڭR͏tk3)vd`{-r%MܕJsM{E-&EP&Y0c$գ֦mO<*vZsoGw.f)ycy5KqR璪eov ܫ:+le.ñN\^ޞ=V\SnٚxTqreuJicQoSz^N\nYLqQdl&K 5zxdUɴ \nST3t`RزRZID\tNtaQ(Aݡ{;at\w}SIbۻL'О![^X+zɰDMC HHPHp4{0{o%͙6DZ-g>7ݤzҧZ?`Ӡ7IОpXvp{O,ggz:F]n .4qPU0Q/bUgK,yyuxdK<~WK ;̣G8]*gky 7EPDE SEhjՇ^1IUK;pP6Yn^{+('/pkzonet.ZQׇ*iz/q"VHrr4wo0]via6/qk˯5^Ɉfj ^wӀfgI=3S9z4Z&CzVtq3d4+F%jSV^~gNr¼ɔXTsn.N{\z69|NldrVMݑ*yX//!|6̹^dii ɵtm|G[NQ$#W06_^4kֽ3Dc~yKV=̷)B{qwXj%,w 1^69_ {׉KUzq&9yt^/^z uD%3vDS;unrT;{ngc"Oa6ow|f\>(bwڎwdǬU9BEW:u[ uravP@z3;&2_a{r^ELT2jѪ/WkJۑN-pGZ/T*]i*=4!"F' U ȳNk^!rH1`CfDzg[g+-j Į>$jBG2.ƵRR&gpw:x*zd*v¡;+s-Lƻ3Rsv{#ip^ʷ1$x}neB#!9]+={ap]i!_z.ԙm,3Nv0_,ѸȵگNH,%D)fuaFq U0Y&+;DRe9,"{,fxhzh˸Kֽ.|gRˁeMKjswjR] v壜fswH]aYh]sI \k*Bk9>.J M4p٥(-ds2!È&)W&ԗ)- ׵z{:r_e:3g-Ϝе]'V`+ǧnW)θkKwk*'$(mۙ`]Zy(0)P9>za!,]=:;іq hyw1ȢU~ {Yzx#в_1VlVMlYmڒɻ'lw,)WkEeK KbZ3%fnv2 +qLju]vh>D/^xf'LcFn侱{0[\ZU/\U]gA5)KotлWgvje"-wݿUc'w۾Z|r3O4%Gc՝QnFGxFK|*k6캷)]Z2- ζ<u6=C5-v<;T۔']ϴQG4rj)UVTҘ# lnZ73фˋ#Ch}Ǟ(${fH-:=<\5%+'q#`j`W{UەR^63i^Yy:&L|# wrb`Ւgvh+-uvًXw[܏Q&*JvA{-S]7$*m,y 1ւ•Kҝsu̾b6@"V\؅+gz Z# `-G׋1lX)-f)n\ް񮴞wEG،s0 pɡPyV/'+(ZwYz^O_w }Me~~⽤Y ۍuQ׹56e& XtHu\I}Z]uжzTk[WաZu4u+)HξXl˫G(+uK&fb7zAPd\y7#G7bwM彜te[IUn@S>ߗcR{NDjfPy7ZTѡQ)Mݱif5Uy98=EЂsӵG m1 n{} ̸/ܕLLL 95;ܹ$5sQmNj$@~SOv IC{ >R{sev*0GV*^yW =_CZdڪР"[}-3e0vva&\941NcNc*2*fr;=Ιˀ:]lj $Dм,OW'pL_uhV.qrvT z':*`Y0 kkd9grd]rh Zu* (mpY2>vd6ҷܺpAKu9Vc[6Ujd{^bck{qչLoo XFH+C72 M[~ s9kVP=ӂA0e?g;Ә5$TS瞼>J}lp@)hZ׭ǛrwF9*0W;9Sج≺7MN(vǤгu . Ln ;uYu :OhBmgBݼ|+{%ͪIB2뷺6]UY1IYҍv'gLl5g[eM3d۹W\u$]8pn˱֙tWJŷ͋]ZrwV3Tu`DC`tzLIӊ*^|]:Q ^=@mmu:n9E8 JVXItnqy)Woww}gh~tI׻2mzkJ\u}2ݵJsxmp`RJ%lأbI+ٻss3s};NjRXӻp;){pgK V+/'`I^Qjd*U\L 79]μg૬!lK[] da31!ٮ"QJ*é3;YtnmKv*ǰە .qL@b ^^"=YQCar_u.CnD]󸆾\*;~::E7u^6n#d%GLanw~_a/uffy[( /8'fA8gòm7J>9l񯬭gv5qS;W)bIw1%&2cY6Y{b̏#FfkDy5b]y凅!sP&Ŷ0VAhȴ27C,w;8d4oN| " S`r~y (*tR!ݮ;{&p=ghQ͊MUUfr,m+) dKX͇{^ŽT'4/tle5ҭS/*sPC`\M$O+ U9^y!v)`:C*[;0VǮ~1-lVh\Xaș˩_@ >þZ"&B93uok'"O>a{f cShÙ;}{Әz#{`L.ܜvnQHR;֯$G;.ÙṴ哣 ʎ(m[l^cý qnMO=}Qeė=.}EC lzl65q7X6<#Cqb j箿t}TުN{s]rxgf{<'0.c=zϫumb̺ƕ'TC*sqc04W#\$Uhdv7nr{qJ- O=Eذ|};TpVv\pfbL^fg/f7-|9OLۿkmȣ ⷒt ~~ɣ+]{»]P)b+k:Rv7l/hd`+N⇨i0qFT}[8`/&1|m9Y_;-n䝫b7݊kG J;SrܯOv:,d<Ʊ`Ь2ude<1KF6MMYݪV kY}};a v v\#vXJ+v6TkAb#Z;!*SU\N@%uڨOGzl}( ޽DvA{Jb`܋ޑHˡeUJ] #-6miaP2OQzC6y4 /Sv12*={XYëO{,Nsۍx o;K4Jof=yTj]&wG5I{qJ(8Jq7o ܘnvs׏cObe<ͅẌx^h^lD`8xҺGn+G8sŠV˺ĻiXpRJ*$w+WsC YĪj{wRY#;qy,"G] }}Nd6JuUv$oS#* LC{L}HZY *fu]v12?f MpBD6W]Vj B] WYDrKRR^×ܮ*,qt/h8Vd+ޖsP[ tcJ7h>T)tKǕo =In{?\,5gͅwַr_uA@J[z7,jt֦ 2ջ+n5.ͳܔ!; vJ"p-{)vcq+|_MWvon^iǝnYSmpܥ>ol/F^OfUqyLǾBXb f=N~νds;vOV7!opu} 'XOg^[//{ę'P!I@:U]43eus9oZ5gQNIED/ޝj);VH^W7@utYihh3/#FL3d<[0o5(dǹ3Ou%nLdG{Zt [M6M''ǹNe4e }wz ;sdاb`%i1-Phq,ɢkw%ʶ-Ʒ{^tЍ=^s݋ +$kٻWq}Pe/}& $tuWt;-"GgqÙ&Wyb]Z8@яye)rOkH[ "t|-P ~1"ռHD]\뺼HӒ69bVxzwY] ]]BX'gwoz.r]`rhe3 6)YstTUp֞jBW;%dۙNjESeAоvrb"o,AXvvMӓپfHvn=Ym x]2fs[s kJz!7eKdlkN¸Ӥ. J3T(U6P)cnբk^9yY(do*VW/3Ҏ݇:XM{`_cۛۺOU2fiToVr/oKcGsjc67b6W} *t;?ۉ|].$t/11w1rߵGT4A4q/9< 0LؽI9ԮŒ5hv=:sP նX!ɖzle>Kڵ2M|Jotɟ_Kz] 4r_<`XO~&c'7;8h箊1Wʎۙ^b&z꽊:TnPO̕H9+"; |wrlJ2/V*=W Y}$WΝ[7!ֶ Fv^nsv9-{՝ۑHؽVY^Zubf1Lۮhd_C+i9c<"j|y <5ugti\hl5C. 9eu4y&R6!uv=@}ggA im-tc@⾓|:1LAyRw8sY>݉J}#{."8$!ݯeϏ`rEpr#y +YtnTDTzfz)eճVrH%v(.y]7uJ]YF썂.z-9<37=){*}쨇7=Azb*7/lٻ->t)\[\NˇO0mQEھ\]u7XHG {r=yƯfԤұg@^=ܞS|wdS;;U2 F[]-;u*Igx}g3q ͽy8unjy6hD}O Tf3.7uzaI#oWnNL {ޱ_, %MуzqD()*^LpxƄg5n.R,dG2lܓўTޚ á(T(-gH8q'fĵv4xp=Rvdq>2d8yJ}#M1E=_K20%OaY4=3{$a חZnbI[NW V Crd6nKIgs(8:@Fcg^QB!}Y4q}K;v+[T[+1ۋ]/[m#m+]٫O:36FV\-=hVίu({7%Ԥ]$rMW1njvotGpx۲0^3&ZfyzZrF Löŧ-sԓ@rp ك{y^':<˥O ww'ٞ{1C6trCO7qbGo1rg 젭65W+iM* yEyM'nGǯ!FbcX &7\YOY񭏶c^6UyKtns\\P%R5"5YnUÅn8$1K.W0 TddCo^t[&Y 8FKʅM‡Iv`u0T^N*ptrУRϷR&7%'-,>zK|M>b];zs5Yőg,efMjmf6Ke݂9%qN^DýEJ9}O?LнO6 'e)c9 â^t2ˇ`Vi/9,%Z]ʣn:̝)rK ђi7)Ppi=e]ˤ԰H }v8&9fbmmd` J{ʕ Y#C xyw@n>od*mjm{EK vV+4Ff/16E4-%ۧ/ chޜulMR倶ZDڷV?a_y.HUEׯؔ)t8\ƇZq8r/E74_=8Mۙv3oʱY |MhQ X/tbg= Zl {Qt }Lz;JRV磣c;*m1\j2ο_j E<iO(pg;}o0۝[jYmd F9=銌̗ Wo|ȺW={yӢis-}tp[dm ٭A %Lo3q 5TiH=3ڏ\Enb@&_՛ 꽊Z>6z6PL ߢay MA!%Oz$Rj 藻(22UnRCqfVQl3cbU9 4%kunP8tj ˢYՇ'M΢Qp ;IEܞu RqIYz/F9'Ljcڿ4^ìS];` s:;rΏ3ILqk+򡜯PV)TFi4s`~dn2/|^[rq@ҵ7I][2LxXvAJ8xDt6Z;bM9E-+y%Uu)NkUs%JJWjK fa/=3 Tbkvt]$# UWq~[1XTz l613ww2K9>E|0#!7F,Ru-.TKzu.Thسn]5hw|唭: O\%_(u7Ұ=0E›O\5Trͻ:N]ڞ/;r/ܙ:d=m,%3t{D!z 1IWRoD$$؛vO#QgЗ1Wt(1`} {ÍHjF/,r3,offf+=0`=YoyǶZ7#1Ƀ:1dhxuSױ0BŴeJaPtw̻ĉi$VܾUn1U\jqm^V!J吭O_QE vիpd96-xr,Hn s&z*%ow#$-\.ldQ3": A'Z ?Dj^%˩(ٟn' r oUi(v=O9Q0D9E\%??Q} JaXWa0z'g<*/{97;DKV Z( q[wzy$NBEW>잪Vç4eVsPڨ(,㇛y4 w[*ȇo5mpH2a Kؼ{>Og?zʔLb> o(L/v\:ScL?w6]"C$HH#P۫`l(K缺?y}> v(Mff.Hu)GɄ~<_"}ׄ7pA# ~ط/:/m¸i^,z?,N+3^(SݙيuuGZN--Q֝t3.A,k}R`g: OC zx3^gOq٫:*e 9t |9e[.S}*\MB JV(u;K4f*MWS(7,s' Ne_Yfq.LMh3&i ]+^JX{bvYjZѽ`6'mȧucVdzfY8Eok}BRhz:qޙw3C.JG7+B[;f2[70{MĻ `՜3yƧ/KP[nߺbз .exbFn'({g÷xptVk6قrд.>cTXAx@^.oR8wq,6Zw]8 Myا,Juj.ݶ|v} 6Kw5o=]= 1}m>6v :UO} GZDD]!1}ɓ)ao&ha>B@wUwFog8S>O&gu`L-3u| BM tȋի|>]"qwL9֡9L٢d|uX2tDxM3{x/+sMή[XD]UM71оjf nsFЗ<'w#ە꙳79VU P˄p8Skr4`w\i>mWItIu0L&.Ϫ:vXiX'h3OM>Er#Pt_uK7qc 26Wƍl|Is>zN7oo T;ѰB{;s)JY)/My2iˏ(dnF573}jTUnжY(7E+QcA:Sz[7})^ݫ׌y7^'./y>q=E&enw]rpB~E;{-XB<=<՚祓o9ù1;Ez'zty#m8*"p+Yp[\؉j|騮f~EJ/zXXeeX;b|'-n;؍3o/x'CmtzJ~?U*-v,,>~zJFnGc^2$uIx9JL B H֡עcyKՋ{|1 }$Gq 1dc$ P!4?'^rxFl2 ž\EUsIx!c}ºBk$zd};[%G&3<ҳ@:! o:TĕX"e7s ,'gs K%M;YlO&Ɖg]g+s$>\xdWG!]{}Z \1C kE+0q֘i)9Sd5Y皚 no8Ͻ2ۛmns<7J'⭡+˷eɋMҤ^qҨ]ޘv[_;'URW/8kK< ֣k2q NgҺu&mKXވ^nws׊u{_"Z4}hAb_k:7q_*Թj㙹I5S@Ϩݙނva*zv]-zU }SZrWLIŢM.rGeZ ,G%:i|J%1h}9`ыV#ZǠҌ{f 3^aa9CՂvf,Gb }i\r=TVONAog"m< Hzj0tXq$ y^>|*\>{hM;K2Qױ<.~Yc2bvًs8pD~ tiZ;qbRSiu Ao3U`.e=ֳ)/F}S%R4w{th#oկ [oȍf *5WSkve2PXѾx6zY(q~Y yz1y>P<⮆1ڬ.m SZ!'lײl -ȱv\L̢Ճ7$ dü۪O/m])]֑1lTVtZA zv r`NnXRAw&YM_f ^Z+gw,Jۙzb=ϠQ4C6#9/v"b?/w^Hy @]st%eeBs O㩠$= ?RyeI}/m -g5ς+ 9-cS.+}˱b 97F :ܑ{q iuTdԾgo$O] 8q g;y#v*ޖ;3lˢFZY4 Y6#vs՞ao UL1)̍ %a̹n ~ǒ&Z2 V;֏,a'vBRwHpʽ= =*z_)p=z ׊eʧRq.)Zx[:WXrFԫѐŷN`D1]YdCݱUX´{Fͫ{!g<=-W#]:Oo^Pu%+,/kknd3ee;Aܹq*sZfɵy&pk}W/Ϸ5uDT.εѫ@m;٫¥{7϶Mxe p k+cG2;Xg ?f Q^غ,Y܊ۋd8R!2+pXfP,wdWѯE>bBwl,),neZ5'ڑnZxh{v|>+qo| &}ګ F;T4yz\Pep z_zqzb:IeKPe=G6E[FkJQr+fHM,IM >4?%P}2UmvX+=+O(683+W9cY{.z+ϩ Ex: $x>mrWU[qJd^5R6'UCH" bܞ 0or]c? R^g|Ӓ1_^,6CA~ FL Ad#[g턐1c\Kzw]3e ns BUňbUZ:v^ꤨex8E56dyϯPFќPs(SʜhveEK4f4Oxymn(^о6 glzF\KBѶ4cERpuZC:z1vC;=+hD[L<;0ES_ e  ;8I}0<չ<<"3V,kܵi[2m ;xҿ(T`}ƯTl\x72g:A!0G)m`^u 4{d,C4yzPAE(kdD0'L2إC" .\KQKׅ_4|8r{ O}.k3aByѯ8o4ӵ87mHJ"PhpunB.蘩 ՕEkz1h |PrZv$P{>'1ӃY?Kaq4 &YIBzӯE?[y+S> fYݥ^N/L=Ĺ5C޶6}YF/:^ BLQ>56έhtqOr_F-HRE/ ~qY}GnørYF;%S.];eGڞ_DDh;sF-v)DCzR(sD?y!PKJЁD@}[)4mSar14Xҋ`P̄vBZx󅹞Z,__u>x^Ց-CW|B:wQ9N]`v}Phdx3=zyy} SVft /X#ٱ~`CgAK i㒡Yuwq9@"/jrmK6aŶHØ= 9&0.5OH+Oqy,ccن!@6= wϩ|M`LMO^U1-2M*"R%Pz 4p܏(<"&} z.[>H Q/ GFF() .~W>GUO}{y: _ye/ 17j#?""Zm_Uv(=҂4~Y14hġFkp%oqsR< {2@QS!;5_DG瞾f 8|ַKkFb-A*ʒݷ{y#AhW6D1K{H y2<-Gy>,P?u} KN?A0uoLdN&/f#_}J?||/I/h4ѢeeUԛMxYƠDjb tb&o¯lII}|Tҽykt͈G]_nj# WkH#5g4*rԸq&' >p]Ϗ&f+Wz>6bU:YOX ,n'1Ye!>j269ѬX"*mؾ"CR_{6W(ch`Cq=";HG~ z|}񦮁@8Ds&Iixhnt 'JSNByAGJPB)JW Uy1 xAC=3{K2Y@Ag'Ӗ^cKWWj-YP$+ŚiJ4Ӓ"q*†/a͡[ت m Ơ n_9ϵ~} a>#؟K즱G/PK hVZ}|>73^>cHB}3~3'OykS=a:'!xi*ۦ5P5U<>?={ióGxty9w p_J$֗ZPZْ J}|x@x)~JR TG$ LFD)ʆ]x WG]Bؚ+'HVx Cesڃm2(kM5I1Im5/`W-}(_,V6|s_znyZ4}ums\ooy{<9 CACM&4S^-k֔( =ڱCq*ТN)ʧ ޲&T'+UDZVDPg~>/vey0bV2/Tkm] ]Ux{v3D>t"oz ,Y:ЁdǨ'Uo?Ws1|W*y^-h#ށت[Tujյ^Smm, (%LZ"i8mS}R?@ɀ?}bdFi$]~`ϼ?8c+R¡ĚT&G•5J#~3{7߿;O9(R.LC| @A=p^m ȵmSUλ E:]vVw]m|Gn2/ȝFȑixEUXmWC%ȸrcο>O'Y}.}E!!Yt}1sm\6'౔n͇AW{S9]^v'W]J 8cRPoyDGqZ@=UwמOmtuwgSwT_:Ϳ\9f<֟@*ߐCwǾg #d?j/9FR|P!xx|;%)_ҧ&#bލ] > Ha RdPoY 4A>N=X?fd! @;s2A}AO9( 5)t󳣪x{١⿈]=pG(uhF^1W)ʽ)zxstr\=U/Qs8rTR+mxyri&phCĪZ(>WUvٿROCU@ѯ6 FOdQ jfWo8c)],uȖτRܿ_aԕxP1(ojFR퐪Y@*՟]Mz](ns/$>_<"Uh3^S΋tWy:r:Ov )3띟~Cy/ xetTJ\꯽r.U^zLp8H^S]gE^TBED1G,RqfԐ}̺9ߢڜ3WT%Q ZHn>)yȟqjnRUZRKT Zio^=əM!8)蹰9j}}DWmޛ+r:Ӗ)<{8HXX&|N''#9BںeԦsR07,jv{{n>[i/#iۃS-ʺ_-Y`RAya~4(!8p7А}ݺ:..|Suخ7 B {%tIAR3+ J+PUGB*|оTcu#H2PГ>6YSDS$ @~(>6k;d%/UWtu'i%q]:9r^r yRiIʏw'ƮKp{^U\NО^/p$y痫ٵrcgGIĽ)"ҵAGgBD]P~j,Jzw:1Q5c̛ 8\S)gjG6PަSsd ¥U8s(U3o2P8K9u{H!R9{mmmut&eYvHRT8 =۫ZAz>ܷ.7( ה'=NYPoU$bI)[aoYT x$#Rm( B=3Ʊ%y(I#ռ]$$q&x~@X  (y{ޟ m{[ 8ٵkMjQ O~kJRHY}_4O Yb̈=.)A40=boNM:WH5ZX*U4 eCg."wEg˽=~;] Pbҩx_ 28~dچf ؠ }U$]'3XHSL/ |R߬*6fD:o"ƤF/r_Chqjj ;Ϗܘn" s4n/o9nb]Um&LD$X1_C7|^߹o5^0&|.0H3«+ݬ/ o=ͿsPVOD!D!wET*u*;@屷iÝjȄz[NL$z+79ڼ-x8uM'0I{]J4N4QXy D89OZ:4MY7cT\73E5R=Y0+·յVEg"׷\(H+nb,۷NBH kY⫅hWى3A- %b.fIzʪZ@԰"=QsҪzJ-:g^D*LvӬV/66G] wƙ Ov\κT3zs҂ƺwj 7s' =lL7{ Cp_gě_w :۹{)=/)!pss<[kj)F K<^ n+cFP(# R]Wۻ.}@#P/'or%St0:?pK$\V!hvD`<~[5EL knbogYLq{!0{'ϝvhdpdd|| ҜG:FsMBe;R?t{,J[V {- `bF%=}o^{Rp`۷gjr_^eX5"㋍> 1)L.> ^A =j)HJ%M}c+hT5p:{d6aSHܯZqVC÷֚_eP.V%1W0{{T}X]xwWmɷo`~t6 Z:gľB7^/@p/ψ!o,=w,A]3,[B5Y-qM}6&YDBz'e|`鿆wڼq>Ƒ+,& z_aUp6}10F8$|3b}1 $O0 HwzjԫA$Ia긧yƗ'$}_S<\NCYVSou MJ#{s7'Kx=Kn8T9wMn}e7=wxx owA_ωz/hC 2{̀$y/7Di`' fy `:x6 lIoC}W_n>mܾ5iQo~}-s~ ȅ?3ϏRVj{x}_ \ tJ @GqJAq ev>wz^q/}qӑ/>x7FE}'O?_|Ϸz~y|ӻ/@j30v>.N vÁaβ4Nuhe3/r~q'sfcㄍyʲ^1 X$P%w_>ty]//szOƾ}}r̘f F}2&{߯c,z癜qzU]:Y򩻡C]]Ssǎ6? ئX$i _|* ;!ᮈgr@n%[:"ymQZ7].2ДWv;2-w{PmQ/-cRR筤i+AS}wvG ">62\1j}WWC@4 (a=8 #W-:o"XP*R˓w:uPUw<7#P}nv(ʔNِ?џ_ْ2GəDy= JTȄ|_2h@Lx41|!- ufoF&&_5N?x=9ZH"\~ܸ Χ%]&'c1&$Ϲt}7el?{#~q~d~ 2.L` 8?%R\꼩7+ŭ B: wJ*c9J(׏/^:|}M'a?B?BR~#_&F¥ TԾ"0~C)ЕhQ C¥6rQ,9]cSĽN7 jECNJ\8+yϏ8_aIZ"jiXQVҕ9*GCZp(ww4!Z4SS:j‰=xtuW___UqâxJϪޜ9KG*bt,u?yCV= ?χ5bQ bc\PuR/kGHw.WD7U=sJx7 >rkOd">!kNk񶇵zuB{F.^յHFJ@y8j \wG}BOZz|iLe<ӛ8r7=uqmtJ(&Cxtt^\\& BD8A-5xtp(R҇hA9@?'{az#dozpb8˰㚳*VMwQJGS-zoIXz>mpU%k0G0~KtzDhLFa$1t 3gxۧxERZ:T4uX|@tYyG2NR Wavou[},^@k #oGCYYh7Q_a$DlHd:M$Уxnz27F!cJw)$:cIq8jXxYQ&ٍF&3le$u} Vq)/ <ls匄A^|`.)9z4,l_`+\SOv(Lq9Z"=7iqU 2̍huWb0+|}u+x6H9o|Xrwgv,bL{U3Ws". rt)WogU}S2qFqucl%$- PB ky PW7_W Y=vtaЎr/v.iRV3nf2k jߞ^0ތ7Nra55sѻf?{%yU ՘N\(p^~vjwE% ut(k`NӃ-W5xuͬgIHH33Å /ˈbg0{g3=̭8eVjQ;:N=Bj[0^c=3%ܷ&IXӞl$sNضL-N:e^ň֟jcYzSK\SgixI2\}vC_ٵˏv7׵sSׂ7EsHs48pݸ肸Mɼ/Øgg&g7Ϸ<Ñe j7lt::/"Y鈄C >#P!bl?4*U+42hŵ}VV]՛.!.爞-iFnj;~k/e8ptf;D1 o%&f%6>ls>zzX[ e"ՄatkQܼM iֱ].NB eͬݼSӮԚ V\cT!<"*gF{(`i<昰J :ӹSG&YgmCڴ{W>{/]SVBvSdO3ـ}clZG ƌ7kW7O=r@G$.WLw}6qO$|$YcK\s=;9BhR=>Hf SQlEN}<Ȣw2˾zܙ%euאXTGed%Ė:{k[4sN+:*Sj BA^wi1O:[o{޻+P^U¢9 F0K5e_XHưs,aⷰ] Tdǣ7!')hv28eK{]D`-yYt\OqC`}31Փ'߱6ck9i+3AcC0^S{*W12J>V.-o\ i|p15_[|dQ%Chաnj+1Ls>zbb)PJ5tABԀ [e5c+$j6R`wNaeD-bPJb[w)i=iӗ6.-4^kC^.M5 f`O3=1xG$gyeiFc{ϼ;s-т̹(n)Ub}϶.قI/ʅzH$kNf|KgBqENV,dJr w=p?~Z%P3吏=ߖ6  (gB^AۻFeulYZB;T+ٯLE ''MьBGԙ Ny:cxө}u"yȯE~O?Ѳrs[S]]A(^;az>|yn]qyuM:(ѠwvMMBGch*d89*@AUO慄߿Jw(;qk{,~dM5N}}/ݟXe >[oY_Pߋ\aV&pn?Z VN 5|j(Z\^؃D$D>`}bj?z}x$@`dOߟxNE^mBZ(%p| ~"'=~^Ww9IVGx'^x{,U$>Hoyy' }W |{$^`Z NJa,~rh/ 6J57x/܊c.( sYR}y>_!A$;rdCa{k>`ëھOk/}ݾ֦H?&y}ǎ}>(P8IyxǧGOH`}DDC^' CF08W+BҜR^)/mxW}JU(,hKc;wJkp;k{u( :Jyb,#<2NvפhKkDE&~e:Jn(Loj/3Ck_Yo̰ $Pxx4h ]wkэSB4@8uVU֚&@ԯ‰KK^3}>89V%H$ ,q; jS<>}8n$y<b?2ݧ+Z"wkכZ#~!cOWx}Z'oW|#@M0JH~_klϿmUhĊ}'~"* ׭YPsZUT8{Omi 6坿W] w#n0פU̸(" 6 '6'6E^ Mngddx&2]'7Ə*K\=L.B s} O OGt9\/J>͝S͖8T]Mt eSѫNSx=krBzxz9ƷT\'Wy5مʺx~r`x;QϺ ˷ՕwBbz-AgﳸNJ` -C1WxyN}:/1$}4nS|J߶I @'l>~_ ~s0!'Ϝj="?ddD{C=Dߒ%(@uk]tC=x9*t#;M]*J=='ʮ;jJCT$PU*Y|9]~n +^# 4xEbmמ^%7^sfp[KdUZn(dLVF 4OZbץ֙%xtIWfܥޒ/s:p!f=}|WV WACٳv{%{;X-8Byq8n&Qr\zAئڸ7(<.uTh;Gkґ ]MoWA@'ilUyGo/ɗ]ƪ"T%K8$T&}hć3w@Ն2Y{Lwf)/Xp؀םN 6;ك>xGd>Gn~G<=Єa}_G\\ Q=c\m+zB㣇%\Kk*zg]'yJOGݦ]S\r{ˑW^G]kuN+zTӮq~]G>ofT7B"80 hUDί՚VwyV\!UR(T`pӕf{F˞K| S| %yDB,seN 9c36؆17!U*c#AlI>jf U*?t`c#jE28{5KքkYՕBTT;oya}[GN3HoD.Kh n/nSWŌELfX_F7!i >lѻX7_9=NRhh)im{a6||^%w/8NKjܭmIV_OxW]js oʺaUvx({ j8j& 16 ^0 ;{H}ۈȅTM<(e!]{ݙr@;cXKweu--pg]l)HfTef_)}OjBL㺗γG}|==k yW'/Zt< AOqި23jۼG*cѥI]ti1J@&:{ы}]KYNzӰz1W z8.Ƒؖ[8*3h.i'z#8Yy|INH53ZA/3Ylw_ Pj.N9u-`Xﲳ 'W_6Z;03rgkyn4EJ縹UF'As\ j8S/"<"08t{OrŌv.)ߒY͘)[i(rV$L&CԫݒWh+FiSPv9Iu[o8HpLx^o U/ǦK<#0Ʉ+KoXd/ۈ2c4c믛Kl3$db6q~}ru/+Wz`OLc7`J] .fekE(L K>9R&=Ig*p(4p E$R= x%)s~Xub,.9 sLb(?5 J[L@AZmsؼ&,(;sLFyYL0Z_Ε )mGPiKB)EHB& Y GqbjR&TqemY#IYhe,7x/G": W Pxe{> kS1O٘3+ўηۚRE8_4Y疃A|b|6钬LWm.P_ R0 [l`i:,VBmXA'TfdevikOxٍ{>L\-A瑥|ϕ u :W{Un]ǂelgcN ޟh2I3g8#fH7/gy?=eDd}^ǥSNmu]UUЄĻuTI΂lb}xHi38J$ Ye/#Uh&}'O@?dgCc>v V~yz9.%!e)`61(1k K >$SO'hAХ]Sʇmo]4t;JP]ut񳫋Gk9zwW#wx˜ŕ}z\FXT>{N'߻uNVmUo O;աO:AL8'f;@>/hmjGיx*1)be_oGHKQ"U?jn|[~O?yg㡾r>]{{;:ꇾ>xrTyN__If8=BxօJBpk5*q {wt!w2~=wK&m 36//I!|b^~&aR + S}jw+Vx{yA? {α SBvWG:ԷyA]\HE$d{޾NSȧ{{ˮq8 E EO^\ 箞;q˴*TjkSy&O)9Ns7[\ rwqQt =?;w wwXoֳF& ?}tmnz //p߃oz^AxDN=rOL"{KôÂ}t쒱w^Jb/b˵^>SvLhU#x<_>y8:U%Z !9dQXk*X5*QURguk<,!WRo]ϾowV +ȟ$1Y=yլsVf6,-z"^E|'+65v-,^*'`'`$faX쓷 E}\W}}<|<ɒ]9^/IRȃZ:'*"wU8uCw{JʡoFTEU]zJj/ :FAK%I*G[8wq6I`iBT@@M0>;őh+x N{R 'La~Jln^(DByXv~X(j/bJ￶ꦿ_h[͛~O߽7%0_|"iGmX]:mMXkpWR*ݘ1f% td"'~ }`@͏PçGWfgCR\zFEDKCjT("P6ApwqPSW;{u9pKsS^*j'ٹo~Mrh!T܄DƌğTM {fn_ʆ/`W mnt˂YPzlXFbVwy>v\zzɄ¶pD EqxIf_(s\pgb*s!}mVjbʼStù-H|v%^R|*Q:  (łE]ap\_e0O j-vvGXb1z8?O"tֈ' DylkJ ûuWwc7kgS9~[|4a8WN,Z{S]Lʨ𥞪[ 8keWZѩAWI>UfDh292m6OgۺNP}k}ثsIȘWR$$!5*r=@u0읪3ǝou*_=5GEgy*ޞ]<(5yNxykp}ş/)3G*ְ rt0%a;VW{-(.,2w5LG[(-3F[^>L8)QO&F'u]2jO32uyY`${yuz$cS$"w' 8IҺÈg!3G2XCNgNkJ3 |=ț6w{|;D+r"mqPed,-RF0o A;2th|&|$#LW_7["?$Iw4۰=ub)c=_f6VG>k@ŰWBϽ0d4F/.@,%f62E(m+HXdaÉ| o/m5cXg۽5FϰO(BMND'Z6e3)B;;8Bw6 svXq<{vUss~]DO *x0O{&B2'|H@̋ו%W垺&-1 }CIw%Z>g!N ,&+R)&{:kd֬O=i4_#|C)ڀU4:6h}]i2^vityRwmQڠz>V}nȊ Xn0J{P"C1jC >]J&7O\l2sj7aM[,FF #z%Kkҭ> <(w;*Ү] tYfͪLyPIh/,lCﰝ=!f7ksr #]>[?d\Yl'|F2J;.5X,l!%Xn",JZqO7!;+-"iH)h22Ơ!&4tZiNάu;Oﰲ Łȥ_l[dk^`?D )7Z9b&%[Ywb J x[a"MYS*{ ("dߥO'(p(e|~Ӈm['el27f"E&فY-Hㅶ'v+wHSbOWЕqm!n=W6AfƦ'5oW|-A%!nk әVL'+ .S~UTu}+O9Ԝ'v\X=cO=!%AyU {#Fx9meV+KjޓWkZ A*VwOIdN)Гq 4YN||w |E6]}}"'rH? }?e0?p:Mo"qR0!TrZZoFF^{uٮ^pM5t ɠ@J;<^m:VV*Uk}|o!ɾoy߻3eެEMjPURK|Yykw~P+:|~a=ՌghIk7!.{mc3ʬ<*%T[_WC>ji5VfwO.Ya}K@MK>_?V^MoB"|Ϧ??xFʂoiD@A5ӃM;N̑q8T1燄D3bpѠr=ՙ:u Î;BR"s pJ<<}oza#G"خ\^uuP> #>:K x^ )X0L˕U7[iQP[JBZ7#J惧Fo?HK&멻1h*߉|6֡ʢp¢kƦ u)^)J<#p]CO>c^|]^E<϶B6EA DQsl*L{Lr^)ܟ7 E2A~T}t45~ qG/{xcSٟWc%m\20Nj 4tx%Zr[NM4tx8{44$ D9`x~ \}/ xuAQA>gUJm˦rH2Z_Nx0CA! \L'v9ɉS2.KdG@YTɏEf z⧇ԙVߢ_o֏vKSBuQM>^ } Ǿ*w82> h()ZqdjJ qƏ8-)Kɠjiak1uZw'qJ@@SzGx=b^,75+(EU꼕wq"ՌLHVkY,ƄO>qev)Vi8 'T_>V:FfP f i%PƨlF&$/1%T}nTȃ>S&f~Ȥ/Îv5uW9|GWZjjp4h ̥cr}sww$ jR(+jO)(1bd17=~>$r?H@2/|FI'ǿ!HBW憎A!jrtG{7.l:G+r}8.Sېw_iʺ]ビZ R*#|>>:{cǫUUjꪲQ3Oq `oE6zlBHZ}~Z (çzUl : ιڨͭ=~T2ߣ"^Mh7"hhs][S -Z/ kb"7ྥ$sܻ)ݮ~?/Z8!EJQNNYĀh\Y1p9S//:8^r^C=] q%9UO`Wn}6<1{_1=d͈C#rHLcl^eB޼ز.ㄘva3gԣzU3>~ե|BCrDoݛ;W c{Zy&zq}nu o Jh s5U70XFՖ"|taɨX(l _ z1'lqg*`/R+ƟQUtz|C;_?X%u' xyz99uS8^]\8i\HyzWv71pN/xzzƎKt==oO'].=y띖%zYz;L]*Q /!@BS=Fyټ;BRfzxtyrOׯ} {pwy=^I>luhxj>k= <{^)qb"[}5]7MV/Z D =\EwZ>^Ko<>J<"#jўI(yܸU[z>`v$ݝmkN f"ib= Ndf{CU{&8E鞏Ϟ )>જhfj kJ x 3zDyzs!DA.wUT,$Rxv- xXLYEJI,窴Ymh*=ce%~>3:`],Tأpɣ!%e/!`RuKHSw"Zv|P|xe]xZxPP ؟سqcOġJSN3T0M Ճ:9ju%/,ntg_n+mrh|:w [r[Eo5eh3}}71V.Efjj(%ݎlFzl#^{Y!ON}* qL܂'+vY.]7)[fYxqw5@ePxI;Y3ZOIvc3ٰ\5 ·$}ffxbI/u,Pr~HƭĚf)v 0B fMh](sD >fސ j4Bk[X*͆WdGJfVrĐ K?3,͗qx 򳂡tcu/fp鲋W TG}uATn;'Uk|G"1 G|o׳*Ih8y3mԞk 6-sɞ< -֒AW>Ƀ׌&$4@"ACI2% eA'igI\l:q RQgNIk-씷I$%f;yxd#OgԀG%٫niCZ.&w3ORS=swj&ÝQ<[S՞E8[©L_k+4HOIHkLm_Dﯼ)UT!;KUklWY-lv] 34vvNv5v̵{c! {7nGGCE w?^hܪ_ } P{{z09Nw甾eRK[kuXKw]^ uX&ldSɗpv:3>0}a)  6-_N[9Έ)x^+kRnؼ&RB_}昅CFf"+R"6װw::'FQ)D1[X_!&O_qX|#UT*yQ'rU"o o7>$dK  SD%!$@->Qiatu3wo=~^+E#Lmhb(Tu/k8WAfݫ`i滁;VuOCpnieMBӹv51(+~֦"4X@CbF:B:]viAIjb uM0Pİ0W)RyWӶh34^}F|x2d@RIBz/|} D+8}3c)vM# tu<^~\ I'϶urZLQ)Yj W#$Wa/HHY|(@Z/Ipyx꺊/qP*4RD(ZkӤxm]=뇎+hij% OvI4|^ B 5Nz)-N9ӝMk' B֥A;ौl"5^aWI@:q yT}=ޞqt~.~J;~}և$Y! xB 7TlYY!]i^L_^_Iݸl>Ͽgcd¹icc;72?@7u~gۡ i e- I|)o'.nPm^P238U]21CPמ(\W{t14^Ib`]X u-U߽~mfy~OˁoxwD+]u"_m@\ Ot>ϋ8u 9#/@V5}* @ZJe+Sؼ/MA@ T_%¸I͆;$|O>W-q8 z4S)@Ҽ󦆁; F]qU u8!~,kjUD<{7s']gnӥDd#dL ]uJulj*xhx\4:yf,zTm T/NhwKڕH=^/_o𾻭r\l}TO}SOwI&ծv=Kƚ&qik=vjƻouiuP9 )P)S̞ϳ#}xzK05MxZrLYnѻdVc+NbNG=k,,ݔjfw+{;6ߺ6ڂm{n}zō[p=M>hBo 6}qQK^E}J64Ouඇ:hksmm8*pumׂVubt!IhsiGM)@^l?϶gUax׀kmRN U"2eP^ @|r2x^_?\|GR\MN6sidfr$ ,Ytre H^=)1'&XHW5~?A$CL֐R:tJ;hӊ*5qw=ZUjPx8S@64gp 4[*Ibv5[KO1 }||; t\6@3 H?C*īD+Embh1Ȭ#Dм0',{tKŒ .Ua s˻E"J U)Jswu5ٗqz_ IA.oxP.)Ȅ]voC#ruh]^Tts~3Jۡ{U g@~dI!2'9Ў 9 [ItSP7Fj:,uSP8ZKaښj:ǻzf~2} jHG}GB >Dgm%nz|aU1`j6,Jk5]/Laprj(ݵbn5wy׫]fc0Y[ϜD/<(4S#}L>tz\u`Nd./T5v*ȕō H4 p@CwDT{&M0μ:ft 2353'W0B) zƣ䞥d();Ωmu/e͟,V.,Oۍ wA 3#N;ޔ5/XB>}=k.w[: (EQ[iѾOzDޠI?}Mb0җfNɏqLԝ1JFsc흇:vI2kz|= V{i'Ljv!y |FUիp݄F[Q䓉, i0)mwRHZ9 {7[wl:vS5_wXxLsլcuJQ/H=we7,!VcU&NU !Z{Ua0biTΥ{Mih42W!Nn,d=4T#8U)͍eū¦:d 9rE 8ng9Ճ^Qfvmˍ]^SB2^Wǻ *o q)+C[c%1,E{>KTK)CqWuMhzȮ3ʹԫΘQ՞rp@Bjzig' ϻٚjubO,yY eZQ)c40]m":mqA ?B D>8՘4yϳDS3z6W ̘cRċ^{.ܾ]Ouԭ0ota3̌+//jDzW!U#/ν44Pdp,w7>u0@RvCE a"nɋ9W;Kņwf򪕍n kx&bf243Q}H&>{'َ颸\2sJ*A) `،i8x0GtEh7ءK:4Bz +w5E:WtVjfr= p&XxSoy\X]FR_ Rն¾B@k1]YP3ݰeopw^t[cEp5X5 ξV!kN1'A; UdpsٗPof4I<&e ^'&Iyx0_LW*va!C4ў'롪hBj=iKJ q0& x9x88x]D;bMCW8S!4D8č*pj=f78C>ҹ`d6/) )qO箺d ++Igʾ @6aԭ <m)$tMu4ŧi&Pit Ҕ.wB`<3==E+~]|Pr~cN޷h ay! Ap)'GAÕoD0v_efi[>/E֣SU\n(FLA$<)P`"BC—%>l͔ԯŷjfn~ݾ_၎!ZWUmk,Z̥#4 ^S8w %n‰-uUK^1y{zg鿃ɶEV `0ggh[^pf@Qg" ^9OnJ 798!r̜ {ǵ->Ka3-AX+OzX#bLo( ΐW!+M?Etr._~95?4MJ6*bm)T'Xj:m84]vgg{?Dr) y{~Hڱ_5*xut@69ӘMPRuMQyKx6E"(Xݙnؾ^QE|^>.;*@]6c>55K}[Pcj(U Č,_g@*{ؐ\Y$ |L<;]5| Ku&jq+Ύr]M4ihɼ&\utҦDZ=+t(ɾN򇱊_T:rĿJca8(r/ ˂煛 WsRդcns:[+dxj33ZI󻋱BC>* x [|Y_ ^S~wEi%WղI)񇾞Ziutt,ʵ5`]/sRS]:ܦBMV22ķjWQ.[u-vWhs_jqרH%AC$+Ҩ.b]yN+k%H8*4NC^,B"w"V{6싋kϦ$֙1/K&hW 3 @RK3FKmK>qpP'/4׊9B2ȁ>7C$4CQ)[\q*St4к5=KtG@Δ+b0 v uSA8KZ59Di;Y'1?dblh伷 on~ҵO=deN@&М]߾߀ 'Y7W+bo62% qOǖ]Tfsm? T>"Lyb1 q7"u2ҿRgbX  IaW5k}'{8?ApsCq =F4yZJ]"Ϋ^t3~O\}Cs9׏>s BT*^S[XEfw;)pY[ҁV:w{yw㧆>J>,[xBɗCc0UHYi ^"CgE܈Guf]6+O16i+)._.{ $o}M2^ T>p|l[>>wW>#/ xcAuFɨZ#QEu9@Uy{@zBDڭCST4Ey>>dW:/ʯ9qӕ}>' 3?=xdƚj[Ro~.=M޸.zc0>ѥk8znBIWT >*UO [;۝CAIZOs|vzy7Lp >pvovn{-w8]c$㼬A NU_IOċlcXf<U+Muo^Vڷ!}r]_s'm#,ͪA =Q:ֳ{ˬidZ^~Do_ft-,#8~*myk wk^ &4+@F;;36>jyAoo[*HGDw\ un J }t0BM B@iIg .h6+| a}ߓy = a _@|_WԎ\/*|χ|W'N}#Nq}Eq qkj!]]]S/}#} }80SZOs˞%0 }ubZ3`N703;t%vQ6x.q2[7M$çT"emʳ%oVE,@bzg[H%1mh^o;͖xaטij̺[KMEyq(ˆXQDk>a"azϯ:fR|Aqc 3GÌ4׎%mf\Z 5]odNA|$CgB,#Sv-=ûw0ٸ yvL<^{q="i|C!-www@qHZ*It[e:b-]Gݽg6Du0A! X*YJ_Z?L5y^z~hm &}~v}:L7@ҫHPL봧3<ݦ6_MaY{^eY@H!DMkZo=Fױ7+wFq\4YN!ik0iKӥlMd3+ݾ`֯홬 x0{:PG,=zG#c1dګF/c>W HfI :2M-sOOxU]^7۰cȎV)%J)LE\GNva-[U)N6G4-)dW9[D׾rlY7d*\ԉ&,g5\BzyЋ{)'ajɼ;ؽJod" d~:~ZC2jŅ8v4 6,Kd[ٚe(2Kmᷳ׻x߆v[:QB¢,Ug ~ߣ2L,=2 xpTm{4ӱ嬣QRe"[mdM+9tjmKnsinV43jl̿pkl~r>"<){ XD 1OaAmL /[ͼAS\5u zEP$U6Tu cwY[tdӉFUWwG{̕\ܩg]7ؠmy:jQؔ~3"Qw6 :1M ѤWuP=f61iT>)\Vu\sq/ہ̱l{zVM)H>K!Nz/<^΂&֬P^ҊՉɕ\8I_;t:3ɂ;L_5$kѭ {ZLÞF/衷2f: 0#_d9y@UvnsD_AijhGlc<#7-HdX oE3t`iGrր&2Ec#PVߗC=>%)Ó|qo>=Sv*)x.J* B8NĜSzTqA{U^TB;a?<.L_,Tp7q,c(L!&R1^fyVAU\^hS鋾'bmFj[9d}΅?" w(lT.%8J:CeNv+C˔Y3"N`d~γ%W~sX յ0J 6t" 'I݃2tE}[o BM,I|e6i9ȵc. `5ynvRy^8ƅ2) HI"~nb,*\P-gLe^2WIv{!U(qv\,/2S0sسqgnٟ;w?/6,=`"8X]5і7!*#B S 5b1DEɿO]wBg!Sݬa* ֯ng%cy)2&fS>E'0+SҫH*~(&J^{qk\[5(a0AB>H 8Mň{0 =:%o&2C*ݳ r` H]Ҥt`u_^4ѫ_җi ٻY4+Úvhy* !&p}ڪcH+T(z,a4b|wٻeϷaŒ?{-ӺBJfsݏt Yz?p/%3*hk E6Kx0KHuDιZGlh鹴&4bz~N/# `d_FR@2Ѵ#iN ? UbO$?,`CߒdBz>z4H7D1HCAOhj--WQ* Uڔu4uSAjRԣpZ #m(uDm*ilb{~<Ͻ٫Ѯ7V~%tI)UJ RZ D(R:AF~d6}~xAIPj~+C{0εJ=\j)EȀ X".<- KQʚ/rWyO˜O޻F+֬H-YgCrRGڧvW_z-7b-}<0$d$IO<|4Cm[PҦ@mҕNjx(C B p1CPJ$޴b%_Ѭ4'/!֢QR'ooXW=jI^Չj1ҵ#MQKzIwH/+Ow@] `])M]T,Zp u-˰5hJL ͸?EbI}Z6=s&$5x_սt|OsykǮ|VL-ӠnS+O>iABD/d,06r72zdߧvkinp$w""/I%ΌX/gu_]464 4wtSCDZkWPN6<:Vsj %td_:跜yqXr-6ro؞c{7_ J'F ~[B<$z ulP$AJv=߾/nOQc>VF4¿CⷽUjxeW =r @{(j4:LUaۅ?//rߍHĐS*⣸&URztbٯϵi;koo!狀jho`✽)ZԼq$9vri iQ4&J;JցB}Fv7P C7UXy$4|ҾLKID^YY`3$]Ч}vt(TAdɿߗ+9ZKL]ߍgڞǏsE>vR H6m.*}AA͔*,(-Ld1~21B Թ߽Dݹ}uʿ2H֢sE*Ϣۗ6_HTSt+j䥷CMmlfRt5M^9p0dC 0J%t5 SJiJ%)(Ҭ{ALM<˷SAֺJRO76~r X;ү7^#Og TU(^N=> @ }'oMXuAGrx'Eس+b+8*<Ĕ[kR!V2sPH8TA)?xX(RL||i;2dT2bq\aiBU}i? C)!s6ίוx摭ՒٹBب|`H>sJ54MJP)hSCG@4JpJjhadMSQm1L0!EqHCD;W2/-CsNP&B3J|e1;)MZy֠DeYXi$my LI7m2#F {.4d̓aLK# @ [LJ/jv{R,ԶUR%]{޽doV Z\y3wki՞)byyfY`찍EZ C睏6l~FK:\hv6֐ *:ZNiSɞЇ!] !4iTlze}iZ10V*B0>uV5M_T`,%B|U'x}$7y%%^$ gJauO]=90IUo`{\r+=~m#ʂ6 z=$ߚkA]>< ZYmLuU`ʡ!1ġI/ "5UIH9~[~˟ortF} }Dj}2H!>!asm!ʿZl43H@H?. Tjn`rj'5M5+Kp12Z. 4tMhUutaI'~ܗ|lţNd 6W㫚>%.uR4_:|~lUԴXJA6ELHuiNWYvi=&>U]PysA,iK_7krvxgg@ܡr!9ğ<.ӡ\ pC*UfKgCV*#V=]ժG֡PE̩DnSO-P>+Ւ|Gf <]n*/&Yjؒl+SƧ4-VhYE0 Nf.vL._.k+ϭH_kDW PTy7ڡ6mBhY4V˜Η;hA'Ĕ* rePUk@Y9:eF(_8zo#}h<]I% MZkn@MƱhʗ`kt6,󆯪̪m,ft=泥'ϪwKG,vWHx5f6jи&pLdE2Hy{-jh%HGղ0{wvɯn^ODŽA'o# ,K)EgI%,(]j`j}5*(9YʍT.tw,&{;10SJwc:1gP3{_;m9ZruCqkYs7+\bȔ<_jxoo6OGT -LZbHcnk9iq'9}LOx5"I\B3a0-E޺+ͤL Ur-";3PRz .f &ń@krAh㣳y:zh2\OWWs0r2A Nf`0n\v+;%h4/"!񺅷ۺ}"|C ,bWGcbKnl7$uۆӈфؽ!*@ Ei /$"QdvYpˠW(/ h݀sIٰ$ d,NڸL!!YRXss;wnJSԡL[,#Jys , QjS|tA3;`J}caPMA,kD gkNf3(VqqwQsS2K ˏ k .}0i׏[WS/{:)drF2ܤy/VaibyojD=ch{77Zs` sn֔+D&.>*s%Uj(O5uvN0 Hv(yS^]雙R]i6UuT2sUF1" "zmߑCkĆOpJ0gc/@A6}(lr7Q@ Fb #W\D郹(-[a9f]]*VWqǽMB{1!m1\/S(!>C5Z8 ;2'ue}($|N ِN2e=2-O)EΝ]b~G4Xԝӥg{-5% F)tؤpKvٸmo;!T:QDJ~g&;[f,^Asg;-yB CJ rݸ*.EwUhRJJ*ddPb]+§P!M߾gݼj(WYVM/n8a+p4CZe5f&%߬.r55cZ3"~ۼ1P2J.PqdkS:I"3D[ nZ4G3=9{T^@p" 3`!#@p??Os!>$ xrg">}v}5>evдfXWۙjPRLLTP@%U* &?떫S)$r|ࡽ,VsLH0@.i>1tI},EWcsW*+g;ZaDب}Kl2%q]*'ۺۘC:k-3BH&'pu P(\\RnT6GAд1p*mS@ GkJhl#hQJ]pw'v{]馒_/DP K)fň|&<9$aH> pt|&S.$72;wȹv$vnb}=H }pagI ا݆@}~&tķyV>|Ga_mK4$ّOAFonm_}#[W?Xg&_V0Żs$@5=SDZ֚Rɡ]󓻎7]CRK@Kh] MSWnАjWu+FF ~bxԇMX^eҎu(Q$vsU,<ߙGҼ8 1~`BOX}"H?2}'{;L7hf/FEP@Wp`&0= Z? 0JQA$IkpAZ[~R[G kt`%Z"1 b ϫmۺ˩\K'cdd7G^ߒvܪDMWXjPv5[zi'ǭ|CSa4h@խiBT~7 K`as4e-JueJ*RO?)w~+֮U=~>e"}ό ~+F.DL䖜ʤHK.'caFһ{-k3/ñ @trq -|,^b) !$pR(*}[ [{pwunJ[_jv%,c >VCk2R}. }kZՊ7(nSTm[pT?ɣ ήSu5jnv@t B`"R!TJ$E5JM0,b܇w=Ȯr&}-B(V^dJJ*Vw.ĿJ-=GjD9dsq_dB=>OO|'?.A>$~| ^FPURJVQ|]|^*n NnOzyp󖂫^Skϗw+/` )Uoάk祠eZAU|'w"K_i+뻤{z˛_%m^o3>9o/Ͽ..|jInOXAɑ>t %97W+}hr뼭漵Ջh L?2G*eJT-t MBȚJR54|tS@5hpjjpqj躝uip:^M-GB@R)ZTJiTUܻS_~QmZW/J6\/p"y@>>Ȅ}C`fR{{s Cba$i:` ]|L)3$ + M3 SXp:*3ߍv,L rQы׾|/WV|[uUtLϳ7qȀy3CS~ݘ{m^\_A.{)mU嘶2 80Џ~?8S@5; s*hShh!'sکh ڗBMMMBR\\DQ@(!"%Z 5w j@~_x3eNqj&/*{M>F᷸nR▊Kt6 }`9'p}>ȉ@a}r`1@||FBβ A> ĥzQ\о>(J+>HnnIt dϾU_d%njߍ_W]ﶼ5k^7"N:TII:=lP}w\Lr߭k!L$B'C߬ L{&o\I`dyz4Jf`AJu* tMi " Q)Ff." U ѡJu]TeONG}I:K춝"1Kr Vy<<W}t]@wy.^K7.Ti y$32{a_#lOO"'+#W_&T{Kbǽ,jτ&YQ::Șlwwy^ [,=r} ^͓ %؃b|n` ̘_Tmwٶr/^ՠӜ}k[rbuVdF4[Eժ_[vrݷ͹\*FS߽S @Jh Q>H:}#踹Ө|Sr8J>+NW>t\>Q|N'S2HIp}66 /%QJDF,iBXE-04ъK"SBj4UTe,FfAdL 33D2B @FB1Ib4 $RhlQMDmi, JbՒDP2QTlm00mV#RXѣE`b(AEE&5!F@Jb6-"HR0(ƌ+$5!Y5&hbȉBDL$QP0a&A6hQbFLѣa&hP"hѪ+H% aC ̑BHƣEb2,V1ĒIMhl V`Eh f (Y$e4I%Hc`@l%J64M+hQL"MZ-hֲ&Ŷ6FAf)%FJP&lhcih$Aj,%1dI*edFM c Qh-Z2[cfI[lId-62i4YaJXF$QڊѴEcTd5F&5--QFe*5(hƆfj!KaB(1QT[F2FŒTml5Q&֒)3(l25h +XASVԶ4fZ3@5RAرFͶ[bUkhmUSj6ƭ[HIa4Qhl*5lBY-ll[ElV-lTDilPb`BXŭ3lͶPdƲƈXJBh؈dflm6 [IF5jCjhڲLdQ6QcFlȚDEXՠڣTF-DmFUMD+QhfLTj"QD[%֓Rhhmkh[kj-Kb6TڦԶ6blFMmJPm)6Sjj[ILͥjSDZi"ڋD6A#jlT%T+`M6PV[+imH+iU+h+il&6TZѴZmRl5f6Sa(lm6%-cThE-kUh&XR)*ڥm3-Uڪl& Ѭ6%6aBѦF-5LZkFڋF0QlMm$mUlAV#feT"ZQkSmTUAmUF6Y*QTm(V-Kdi6T*l-ԭM[JlŰ iJ iVM6( IKe&ʶHm! Sj!i!MV#mDZV-j5hXPDd-hhM6HFQ[X-[Ecmi&қ-Kh6(3RI[$l[$llET[bثhUbcƊ5ch"lb)2V2cb(6ѱlQ VjZ+Eb 6Sil"mā66')F*H1Y_| O^Ϸz j)kqE)TDRz&@;ҥ@A%hΠx R( $ }AA%}#@*( @A:`RR_wFۄo603sr=z^ĸ{΀T@N}>@"EQ C6cx[,L _m{T7@$!$}.BzҨP URmj[KnmZkyR'8w%fg.is2b~9rƃHkLjP[J-<f2bUPZ(TPhTӆpe\cm^75Y2۷ Mv294;ȿ31Rc $~sl1 J]57Z3Ud,ORYӈI(Sy.k."60k43$ \qlZZTb,iWTkZ)iUro/71Eh*;j#j(mzVW{9̥OF 14cCZRkA C crܤmƩJQBod|:9GW1r$viq;880pwa!L;#xJ`Y"@ pF㉆-*>8:0ɧD4mu!m IIo܁N8d橼vȰ4:L-7^FT˫M]ڹgv8뮿aٗ68| ǘJULWtJbJuI ’H5Yf}<;i,Le'pp˳F\7ÄvZ]RI x!Y<;;rު. b,Ӻn %dԴ2;vw$=rLKZ`A/:=5n>?yB]\K)*Ƽ#jwnu{^]RE'9%W9;n QoW75֭ ьj*XBLʗRDF숽ݼmIu4uѫƮ+ݷub]t$ŵȶ6pTռVM ȂQ@L kUWjjKCT(AJ E"B -(7R.STZnUTM@F@Qh -A DYdZAjXjmjkkZŭת|j-V-F[m-h[Z*ƵbڻucV5IjƴQjMTX1tskZݵ]U]hs#nM2I%(ĘU%eȠT&3>rFɃ%d~j+* I8]蠰8x(^K=wvRuqѡ#5 'ℇ@=~ͽt{:7GzN_6_;5;6&I}I!^Y2,T|?}'QT6S-mV0;bWOΤoCO~;)X #&t$>\ bElӻ&B;G 4"lԩ< D|MBlw SIZmTҟ.T!qxʼnPS"(#rvx'?BsA$v>( Eh*p큀-vYsV~ kn~oW"xHgurnDv { EGvwb"@;9: I)T?xk׬rr@C}!cUTĘa5~My4>.bc6$&$z· MO%[W"`(-ˋS,Q`VZʊPẻBNqu]bUiKR%BܹR\AYl.$e-[ZZf LUfLqETw8twÁY2`%TkAe Knd ([[YaRmaun-F w+͈89ck Ma2(5V,֔޷Ea 9`S Um)m l*UE-*[b6釟 QEMr"+U+M"mkԛUʶIF t~ƣr#]"ɣrkI;W:m+sssz%kw,{$,κ*^T]S2ҁRʅ DrZ%p*5(fw],+؝Ѯ]WrYX2ձh6*%,$V: T&,QOBRQR)Fwˋ^zmBajC2+ f%QQfK` Te(,e۪)nW.l@Yλ]HKW0"j i`)beʽqj-ljB)24eWKv1ejZaiKF?nN#owLVrJ7I2rKEcºmNomy˜ P.YL(wN^bI/]ڎZ܉ U͹7jI$)뼮HH- L0 mwo=^FޑnZnb&+͹E|07|m򼷄QhFR]5^myF].yEż"sp& W])*W6˜+6tyXkˌқ21ʷ$1k]9wQ@TƑ4(1`r!b1irpbgv: :EML'uױ 㯞Jˍ_&\2PmPL2RMC 6T5`q iKdZ\̘QLq0-e(mFVRZmlbd9uu$=z]u+ 0aTYmlmTj`JV2i.BDDr$NN'%%ELŎZ\R/.rw9.v\-0i(eu =3}^* -~ ǒImy? "rHP@d3jRL}tDk7e^uwfOKX].0p? |\åRq!,:nFlPRYC~Se((AF?Ѳѳ臫49s?~IIE~Z DJXRs'V"CQH$}b-y}.u=llfxz.'( "vPCBlTD( '_B@ssO Ig-ױAJ=&y9>߮xЉz8mH.WzI^31a镫0zt^oҜ 苪X-'dK.EShk%Ƕt[1#zcOsk " n(y9aNY 3}ϻkV__ria~Wv8;.rĻusrݝ/=TIsbMdHѣ@ DDM6յ[Y @L1nn|QF@yk0E{ۋ(2J8&6 & d̓L()emEʮTT;bKrY10QJaJ0 #AVLP p[-¦d1c iP ҂)fR01`CtX%B57Wdˮq[ڼξzQ=rr;vts2A5*5skӽ]k$vQv1IcwA v ]9(1tSݸ^;5h杵 9>/'vݺtlnӖr5I]m!/oF(C!Pl\ifI#9+;Q6,dHB"bEkyfF%ݬTnr3jsJ,S",h{]14^捓&*1W"ZY ,XADQ6X-&hZKAEmFM) l&HZITcc$B5R0EEboRqw;pm$1&RY&2Yɑ1lM**+kF6HX\  )2HI56"ƲmF!$FXQi(]2Z2Q452AkbX&Qu.FŦQchF-IW6"4)*5%,F,ѓDc71[rJf6cIʼn AaMn64bhVwn24R),d[ !&dEr)*ٔlhʹų1͌ͣXص!S҈(6 h fcX$Ab؍TZMJȘQFYIj(һW&-3RI3i 04bJ+I%Y,hc! RFɊ#I>vܱZbĆ4XœIbEv݅IbZ$wtZ6*5H`ݦhlkDbƗ]ʃQɩ M1d,HŊY5FƱhh"fQX*((:͋%hAEkzRhE&KIF.DjLhԕF;utbS"KD(lX 0lI]REi,REFj)-%6jɻƊ+ F"imjD24b,5 Y,(!-f4Z(+ AbjDm51XcXR*BD%I !)A,Flj4QKQ"J(2BFARImF1PƢ64H&XV0i-1(Xc{wzV"Bj0f$APb6"2QP`bZ L3EcTY E#QY4FX dCh6+ZblZ"VJMPIAcXDEb6"Ʊ[b**(4nW6#j PQf6ئDZisp* i(X֌bPcPLTX%36 6 ĘI)1FZFA-bm%!P)b4Fۡb MRTb2WMk mءL"6 $_-u湍4Z4cF&,R&œcm\ԆElXţUt+%54l.堩eKF5MF,a,EbH& d#Ea6D((nhhQ5bPsnQF1Y J1bE!El$֐ dłhD#FQ(I;`j,dU%c&&&%Qdj6"Q)kEƤ&RQX$2LE-db H+U{1*X%b)" YQm *4hfbX(4XdX0JIC-`RQ5$I(L&`(C,E6Ʊ5|nY6hEQmt#H-JRm0lZHbJ+FJLX06H4TF-UK&E˔l`mD‰4lbTcFQdY0">yr{oM HRd LkEF+Dh(CU͒Z51X7rqFMcEQbшj4bfZ 0Z)6 Dh5IEF0mTm!Q*,cQJ4i](!Mi6LXC3(" fX5F$5TFK&*M&;ݽh* FE62#lV-lM`[J1d$PS5,,QHQ L%QŤF$1`&dEZ +6I**4h!QX6Ŕ"|| AfDb4H*,Lфث)b!6f2R6ƤQ0IX$Fei2+rȉ5`-ccƣj5FCCY PHTb,k1 A &&hv-Ɉ!FJ wjl!cF6"ưʓ`Kc7nծlbمjb+WMBX d5McnIh*5&EEbEh)H0ZLV"1 $W1oiAF-cI,jM4Y F(!)nF1a-ѵPke%.s,Q6,lk&V#laePPQ5F64Ai: QQ4*1lb mI[&ɢ͸b#X"**hƋƤ%Q20k53cDX1$(*1X۶DE4c#Thԉ@1e4Tb%)ITEvɨ j1bƲd e"mJ1#FeɲݫF0F#QQQbTX(جmEhՆd-b5bbE ,Qa4jhljPdd)5*EH;czs@EFə1B`CkT%1Ɠ&̨"fLcDT̑IhAcA!djjKF1fY1AlFIdIFFDИ6,IE̩ ţXDFfJm -hƃsjLVb,AdE FM "-tۑddшI4FJ(A5b 5*+&RX QDPhV (fRk&$Ѷ2 BQlj4Q% hm4%nU2Y 6"4SHM,EM2l-rV K5!b$ѩ@b )h0mRlF-k $Z6#DY\HbMfR4I%&ٚllF2Q[t66-d "T$FQbmdIM1L F֍cIE1FL*$4FZ LmAbAHXQcQFƌX"#R&]-tb`ڔŢChkJ(؃Ii(EP##AI,Z Q$h6(JHZ h؈CPXؠ*61ن"Ѩ6M%*)"QcZ(fh1F1ܭrLjB$3X6dbd m@ 1&mDhAhƈ0Ѣ64lTRddƓ$c$X̲F &&ij"ƶ+#(EBd&Unm1QhQ2MHTik cF@b2P$F(1QD#4j@1h`V"dѰV1H[FƑ1K"ђm"Dj-FѨaŃ L5Q&h*(AR6ZLBo-fE%i j#&hF Fhf"›AQ bfbDE+`64chˆjPEI) PjJ" wm̖4FQAd4FhѶLl`j,&5F Ѣ1ѫ%&ɍQcL۩4L4IQS) FM52QѴF)(,E|{H^mhڒ t)6*651n\)KE@hAQ MD%Y5U˄Ph) 41%kQATDjJ0+%̙c(+*(ĖB1QbJQ+FbY&hEJV)53j65$-mL Flj %BSMj@jhѨc%EDREh) %2PldꔒأlEƋRA2dЛF$$ 61iI(D)*2l`TTPH!V(6dMh[+;FɓH"b6Z #%cQZ0L L50h 3i#b6rI%*b4#QQLE )( F6V**#S"5 j75wo&`1XnƣF;66Fv\MEEF4XAZ4F(\*)(؂AM\Z#Ʊ&-EKRںQcQ%dɂ2DX)Tc%Qm3%i(-hEѤYJ#TZ!^uk5,5TDH)i2JMkdh2Q Ph *(ѲVL5 IJc$PFP4i6$cQhc(Si6* [3h-TbTm"EQcl6@#X (5 Dj*K`ZQXţ!)DĄbjD(JZ `Jk%*0j51iLAVJ4FŤQ/kWio3 %EZ-͢S-EbFDm)P\6 j5&bM&ŃFARXMEfjCE[nUFlEEi52V-"j%5BT4[*1[1lhH%1Z Abҕ[6BcQ%hub#TXƍQ5D[&A 4cX,UmE(1L&j1#LK #FA1I$Qh6 &$9mr4M!DFf##A!1EFAV Pbɶi("(PDʤԄR&d4E؍`4k,(֔%i,m(A63QhTPjR!%, F1JMcI,PPTID2(RЈIA 6`2Fzz絵F1Ydɩ#J6k)!hJPEj2mڍ-#*mfE6eLb"&T (6 Eh l #MI-@QPF(`̨AjRFR5JdM*e%FJ4` 0mURXT#)(dD (-VJ5Қ)(Lڢ X`TB,ck2J-%Y*Mm[6QH( !fjѤ#LMPb$(ؤ TF(Ih#"j4c6IRj4"6Qآ(0c& &1j,$(RQ6%RVfY1"Vԅ 4͓&ƣ(Y(ɢ Є\j5DT1FJQ,&`cXF6jM)(M6#WM\h5h 5Hcb&J Rش%Al%3dml6Q,JF"+#AQlLK$EBhlIE!FM@h#nZQLؠ1RQEd(EDBladrKAQI3h(I)B64#b-a4$bh*j(+I Mh 0̣n)bQQ62FBѬF)hbA%$ImK/9Ami5(4$bDXƌ[f$Qj( RTEѡ0&BEI׷] Fd,V$+2-аm)%w.ےF E1lh(5%Q ccEAlc5ƒ-"b" **,hJ@wZ,ʡ6"I4a Fّ!b",T8\$j L%Y Ha#&*L,]*&R[L5 l&k%b IP3E%I"C24lS#$.֮BZ#Qj( APQDHm,3fX$EѢ(حT#IF4ITIbD1EvҲQHY#cbՙDl$RdQƒDQXc"h#iJKm6I2QDQQUF$H-$c1%F6 CFX,RXe4m$l E Ѵ+H6H Z#bɰVMh(5M1$AT"7fP*A]m5)je1hZH3`fbƒĆ3+bИDhC`EFI,d id5[#ŨbM!DXFԆ$Fb!7mp 3EJaLM2XhdHTZL5$j0)0U3#C5%cTCMFQSZR6 ,QEQJT* 0!,Q[DQG.jLZ"`QEb$$ڹ-FTRw:+&2fh3ɄiJWt-r2PYLlEv޾[|F&1FMˮ*+&'kQdɯ5͊DZ5Z 6 ؍Wu c` ::܍ƍ,m K -EIƤ2KJ0E$64lX, cFDQTV4&BƍˆD͌bHmٕZ1b2lRCFhi Qj-c|Y7n*܍F,jRe!Xh֣0l!d%lF5SfY#m%!Fc`JZ",mFh #6-$HűD6)6lcT5bElVC%Pd4X1Qؤc"Ti LbƋFi AQQdbE!V4v\4QCbBٚ$IQFFĺ%QBh*]pŊR5)(%Q&Ѣ*5jEnlY"f1FDj7];W66F0JJ)B&Ő&ȂLAonVh-DI"a*bM2b4(\1&!hQ3fQDwRQY,[ )AQ%Bvr2 ɢi,[24ѫ4lV#IEXbA`4Un[ELd؊Eѱ]ەY#2XЕZ-HւhL#TmДTi46 QAAU] ѨƐD 4lj"1FQQԅ!"dF-b1f(,b(lQbbh*R*ţ14V(Ĕf=#hأ$ & "3fFIEb֌ 5@bm6đ%d Ihv4fۦ6Ę#cbMF (Qnd]6tѨb1E\!nDgW]63Ō\5dŤ5dL[&5sn{y>H NEpwq]5w;.ͻ].%{\K\B1Gιn5[őjE* 0S[(-mkjc=/;"z+Ýf`0*ƎRF )E4t˂*cXwEȢy^bn30f nRt&kZ6ƮZ X)0f W0qLCR5ecDXEm)\mti V P5ts9*!Zڵ-J(?qǟ}~`s@001gHUw ^S3@$To ]h`I;d5T$[B81U0t^$>VoERUk+T+vy =u\m}1C!$ΛS5^@ޱ?GL~{u}Jr:&)S#᧰c~릖]94óaU{) ¯T}2P8UN(v/8h{ϧ!p)|4, No6ދ]ߏ(;^$+s'O_Ɩ];ò\<;Y}2`aKvrl1Le)I8|{ لwQ,mUx@;D=)I2NjbtWV[>܏:e3{:[Ì5j'4BI-bN1Ϯܶ> H8ҿ~SU3.n7u:۾6ٛo/#?ys ~|;A0JzKQPM|WmNKXernPYOmkԘA0d)mXu5ȹetw"ni|nu &Б6ǣqUR=GM,ocpGYucC 16lBIm3+fVlj*Ƣbtۊf 1[$IJ1Lij\7Ya_Dvpo u]l>Ҁsȵ6aYZ}AjKO1 { SC7bnԭHݥ,jф?Tz8 Бzŝqy}CDUr6?AޑA}23EQeυV.?Zk:c 9`g8ôyP.- fVژ~>~sla#Nqz ]#֓w쁶˞ڔL_r2uݜ=UO111.Ž)WjJw(ܘo-,2kt Ls#"&v'ٵL[^UGBO,J#e_لwtf~wkp#ڷ0}lqM#3֢ >e*F3䢇f5'sT5c+0c~ aNlT+Q.YM瑼MӞU/DnM5о.  zW`+mv"Ze8"r+!ivijž-2li+Dl Wp;O-.}.270}ݎ3>l|G?1vf3oZΗMT_c'\*9v_[\ rf=\YE2Va {'W:#á f@UXC5uVWgN1"+8Iy75eA-˪Uf#4tv2ܶiKlKxF]m]7Iit9 WKc7wJ+װiµ.wmƷZTIȧѽ+zQ)v[kG):)P%YF56 Hye~7i\ܜ]^3%tY0^CLlή*? Ps=.pF{6ٳHvf0j,uIp UNqw&_ӳLKOQ _%џ_愺؛;|d=bw&YU OΘ)gQ\Xβ Vy)Jru+Xu q26RJE+>jqW[دdU/?'}ʼnGݓȊՆy4NgG_,kd_)DFzIv)1G6] ?3[ޙj~Ycdp+>0Y;+g:eA-q6 #?zqq&m {kuT%%jKImD!\hǯ9,_≼H P`& No? 73> G@yX:7<{1t2.ZK;$(<#U<Tg1PJmQ"CT[~ݷ?#d#Y8@G@A T#2 >U}e0(?@HI8ew*6/Zomk5߬+3Tc$$d"r*$BxO#1$Y7n;~zgDĊ/vy70, w5߸"v蔟IA6`؂i"ڶ(*0w(;9}H;=bId3KPץ;B`0Vu#v!ٶm!E3]g.M42BLeDֱ:?gYv(R\[%-@pA|XCZ{yd_r+qd ׇ0-wI1 $XI0dZƙlʫ0t?D~éן>l|W᷆~ I:4h롺UwoǕ +ɫkn].PYu.eygi'}cWdo=7wÍkȽ9~9)l;B:Mk54DWg w Yb۵I;Fg~A&W;i1$/t Mĩ\iCwv=1Yt } p]m$V| JSxjq +o;yVX ʕ*TjylZ2TfUlp =g7{?h]loWC m)1<"zh*Yri,I/;erAbɐD=sӈt0e@7KI~GVG)kԵ/ )V_ְ_k9Cuv9^&D #D+MQKAZe3lZkƊ+F5FŨڊQ2lY)B5Fm&-"j!MX6LZe[hjI ER%l1EA5M6 *b6e 6+CEY*Ғ#E&AJjP[Si* b5m44iU2hҋAbэYkP (dS6J͐KlhQE`5I)6F,EAiS-E&Ѣ"j6mJ1Pi( ɱJeK"F%Zm SAdY-%F2fѵMږJa2m4QfM,ѵf6RmImTdTmkf56bkTmԭVmlQm- QUMJ$3EZ*daeIXiP ME+Til,ZU3Hh lKLV326lkfSkYMjQf%mBU,kR"Z(6-MRIQj!5i[hC[FY̢M&kV6-mFmebڊURjتm[Xdk XkBѶIjѵ5mTѪ֍e+SJ֦[T[mkUmRڴ[UCLZU(  ** )ZQj֤`(*2"  j--j*KjfTaUH`DX@KJkm-m&l@, 0H"*_]cK+6-[jmkխi5UʵFATTXPU$DUk6JV EcUEE"ŭm*mmePbؚ͵ljTmlդfMZڤګ*mm*ڡ+mY֦jj#"* *ԩmZV֍6cTfmڕmemҖ% **QZ+V6Y-U-[4fZEkmQiTնتeZ+QUQb[ljljK%le4-L)RV2VTK"h̵ؚLYfmJMJ*kem"&fR؃TSLf&̒ěc*ML)"#fĥ bYVd%ŪahlR4b̳fɵ&&RPU#&Hl,Ƭm3-!A3T"6h!,FRTmZhZP$$,,țIH61S61cɓcE&Z$bB$2 Hv( lOPNps?;gظyU^C1Z7at(T`4TdO ?vy>gF_? ;.ЬGylcwNxSSUT*)uIrI2G?zR}RCTp"!VC C,k[=eg#Y<^L޴#d쨔^#ZRLjS##UG>}&؎ܒXRT(; $$1¾r@AT=<5h Qd ?aeC>@圷[Xw0U('v sUꠠ?/?_?bG"P@`^HߴȲWL9%]٫eqNaXU>vpuU3 PQۘ&:47wSo)A7&vFF(uћa4;5sPFVC1U]Jj˽W4(ƅ\ܟ!# s5 uh*0)u:Af8ÝW޷j=|q defpB3)pS]8sb=3LWQOF!0U莵Oc̰$!i XMC T +̫S-떸RQErɼ*,9n#JZ[IWL!Y42rw5ޝh¨ pY4E$@_nG-Y*jmԺh1=EZ)"$jwd:=k dTƴTW#gwlI JvsJ0#(aUh(K)HI+~GTEHbIIW6a QJ*`"HⶈI/:fAO*HEŵ iyA-A*)NF$^@fV] ߢ6‚XSF\˕P m DyAqmr! HE 0I0@ S"U^O뱻OWP+2PP ,gj EKO׬V% P9vj7wWbڭjUoWK='oۧ(e+ EZ հq]S4=E (z WE瞆PJL AtXЍ ʐUC6ClI`MaHps i{ˆZ6'M I%DEbu]zZ-Vbfk\u>N%MZfw&LEZEyBIV`݇t3 rh9ϹMQܡ=bqp5KZ$$J Ub m @\Ȳ$w^]%;bâmZISidMժwrfVJ`Zan34qeUUus2nU&$αE$knB4#|}dx^Yk A$BώHp[u6 #=B#-N] ]k* B +$xͤ)mM>5s.gYas}iZT5Vkc:>厬0 GMHȼ!,ެ6MXc۫C("$R ըiJg2+7n9Ls7 {)4ެ%E(ѹdr1oJ7)yhܞmD<0,uyӕly֠6a6y SV )B#}fCgT'FE:r5BtEY'DH`ILsmMln]s5*H8aiHpVn$a.Gg1Q t6YD96h0Ͳu A TU lʐG"(չ!lihӖhB"ڪA$.Iw3wWYX%ZR@X%X,EТ-lܢQUӺrǬW:-E$'(8$A ~VF,m(FW6mwZ+_L[jeBp1(4nQҖpA M!6n T@@Ø8+q@1E \ ⩈ ڶ&+88`&( ṭ8eh`ڥc~z}5Mo 2M " 'T07GlE@&=fR ;b댯VϩC7,:$N3D3^ԈJE׏ 9kD>$W}bCTb(xߋ N8W#ҋT;z Sy G~@13 ƞs ƥB[L m;w-t yOW65|ctxeRW{V9Ś'[w0twnvhg2kVu4o.]4UHTvM]giL[B6I61g(1UC}"x8O AIKĞϹ A<QRIC@a (䘐;ߢP vs|:kZA+$MxYcH|B8$r7 $||||N<38 0i$HT(NWim]lR18އ7׎ZfعYoOUW^A Ѷ3v✺gkTvӽbWyGZX1WՖ +.|B9o'lZ)1U*M}۹.:F+ƚ{`GA;RcxL+:جShPxfӭv(zIה{RRq};*o>+ S֥N[dW^T \ t%=XهSܩE?YW #j(Ro/H$u1ا}\1uLx؏4UY ^qސW;zؽT :SJsͥUEn=%E%JPNEV m_! N#ݨeUǵ5WqKD)WYy뎭*e 4f8y=C #;|WaS FYTc}"Rw5k)O2cu>kSk)^@\7KP4I}߽Üw g6 f^P 2ϴcFxDW5N*B/2܌s9g;FJ9]8Ԙ({Dˆ tXM7t4JXMWPXkQnfF)Hy8.DKU”˧bګ@I +Jp EDz(Sxb'yz * l53:X(eϽp*"̟&Q -bʼn 0X.kQn2m`*Je 1S@ Ȉ EɈ>hvFҠ!kOp0^A\e>0~}* eWw˯wLXO\[gJ0e(&'w:U7pd_nBa'0-z험bOdvQ+mg aa!GS!I˾8/myBY)6OPF_IT02*6 }R\=D,Puz{O'%ܻZv*Bv"8bxZ\:R[ UO3dA/9xf!) YتZƺ^-"8/hn㻐5|WզfN,tNʆST##COjQ>aJüՀ,Hj|3 YGsVm3HtU{8Bۙx>Ƒ׌0[dnfl*A"/F唑UrXn"\+"HoS͐k@h-K|d*!Ldrcͯ<-eחқd]:Wto3a\2 3f[{yj&?0C˶g/ IJER%НJk,(@Ei,-  B2(!u8! )H2"W(/[VhYtd2 "MZ&2I`lnL>{vU0 !֥k^(z0*asZLzkXy06Ϳ8 V HK %FpnM,K<\*VcI96ww~o0lKwm*hN9I6GfYw47cRJ3LH-hDU>6ݣAQw6Zf u?)!02!Js4 4NCld\0xGZKX78蘨N)i .61 d[F5m\-(Q@1 j!29ݡ:xֻwL#rV^t?bcacb,V)4HJg~zxE6kXZ97;2456sԾ#ɜSmg]0LVÎ"^݉݋#5lQPrB#CeZV7C}j.aƦʨ,֬o, IzJuFԑyMRԚT4M&0'ۅ|"?89\7:ϲS đ&0Ę_Zeb U*)h,ި3,L@O[,0wH4Ba+ G곴i w> ڄT3~}_H`'ȯ`!ڠ℩ɝM>u7i4tؤ̹iPbSYKaXo)iLCݡE OnJ %Ȅ!觹tV8*},<);!2c 30֍mF-+~#mrҪv80Kk_Y#l_X 2BVEqdx`>\(uih3ȑG C1 30q0pSL,, qL 00qɊ" a. Xec G05E7Þկ f8!\^A*u7T\ <=!xY'"';$3; dˮ_?o{w.jAg\ްq16uT9iez4=.0̶UiQa&+4Ԇr̸E*N2Qaiuu W-iI;LUDaicbU;QD,zL@!1S4C -   !Mh4 -[]i4tZ6 aa`Zf!.89b+E-)mX ځN*(v$fYgTo8Ccw2bIP wl,!N"^b+5<1vhR 6 :Q OzVl;v 2QE$=jbRsy*ɑww\j-[-2IpO5{'6100C330Lp#S#Aw XfrE G2m.Eihaaie!XZZ%k@QTNQ׉#l*Xo99[-VNk`y-O/^*@oy+r=! a>.D([ ,bi T onBi!bk XOy6p2J05Eeҏ Ԕ7(rMp ~w-k 6#nn*- 2y5RnCx X[xb!cbeX^Ib.a"RIA`SAN%XfE-&bR.wD\ !"{2ik! e8Ÿr(x);w |_{$' u'SMoy{>O&əI>OvuSIHWQ'QWq`BaKZ0@lD >@:IUXc0F<y3ٔjD`XN:'G'=nؤDAbj_J7W"H5A_U!XcV%BdCٌa=hcfY$Y+ x;JyFLx:Ұ)$$jdS)֯6ߦђa`lkh]LS2 .6%aM@E4-IE +MQҶPi'Sr(> FJl/f'U-@ q;U˨UGB&ǜ_FNon, xܺ3D3"π h3U+$<{.UrlӤ\IIS3'&3I>6|kdhQqH 6@r(_2|r[W"ϼ{}] $\!-VR8eT JJJh˲ L0A ypʲ_iJ}2Lh; OPy'}%`wt$:8@0Ẽq _fz~yKJOy)r°f-J3:, |ô iu$zbsEI^[Ibs} y^U[IuCɉ#D% 91C \̴dl "R `B Fx@ 2%4ЅДؾ*8j dI ES PTOVQ [z YVstAleR͡W~Cώ|g_*QlKo* ZnG3[M.,ۊՒ Rӌsb.S !™5PwEPP<$α <ӬR5R7ٵd*W=9ZQZ̝wUa!KMݷ[5\ʸiõ'Kv{DΙO];dSveK-#X^bCƢ{96nzNʻ ivfpE|ˬՋV!)J.vX)ܞ-X˗(m3&7l}H``5gAGv\@G3ffM8v2=ݥJ|Mve:nm+'%JƷ0V,yttU[Bo`|rEJ-"L$%;nZ\3-Ƿ]$ܫ: }gQ(G^"7/vӒ LI֘ޞYͣ@ɇj)x{6%K;\NiÖs`5\sm燉 s]m\o!Jũuof*oeΕU&rVzN7|7yp-{,Bf/w:O]"74W ,E:ݬ!fI/kɶBE39:ͪ;!#ì^/Y wLtݧ\tT!ɃՊf E_:V8iq졼1<,Zث.9UvZb&ecTnZ\qw;0`5af7s݈(oL7Pq;I<}fߺWvu̳BNwNp"y61_P9+X \_&Iܪ)J(B٦v׺>,K{ ݽj Sv+VrBV '(;yu`}7.U) oỴR_G Rd8nu}Ǯm4wl0,+r=u/%u*=ːڧUKK μUeeH*jkG75acΦ7wK.jXm'w19 焩)t%%X@úcjsZq1&c?%Mp f^,_=A0{U@l M Syux{B:8lˮsJͶ.'XgYWre4^?KJrJOM缙CCSERwІoXì].F:uӷsCubƧI^¯kwoj]æ8ˌU.fUVo&T- `\CSXhGH/ć#'JٸUf]Cxqw#&[^j,//tUݷv]z5v-e !l,M (;<4wJ 8.x; iRDWuJo`rjDvC/w0# ͼJ82z:hS dҹ0^f3+iW.G`«Mp/SZ"miڂC$RT^k/=l"!v~OAT*)((ۻk~׋U\x彅ھufS5'U7ף\ݾ Dǖ:PnLjF*7S ێ]\f zъwǞ=UwSݬ[\3^u2NфwvScs3m˼g\RنT(C{ylͫᡋ"R^IfmpmTܪSwe*QLuwM1ͫeZM[RmȞ;]J1YZ3rͼG{:t)my㾺ysz#is+j6>6&7u ݄<'O|]^rqnu7qk[N-s[Y5B:'l+kv jb+.PʱcՌO:3H=[[/Y>]x=Y((F [l=6Վ:6 1Y f4*hh"\y.fR'/(J!v4AQ pXc8&Gֆٙnv zRWI;;n^[W39(w^3. ~ ˙;u܊E[S*GÂw2"9Q]7. [w. zC {2`uo2{-<øa獫:4y؋431r:[1ΝJ]:[;bb*qrT 2 ;s[DA2mvwjb*6U4[c80aVV05RQD ZS*[;MPxrʥ,iz _;ԈpkK%Pe_Z8/UB!f'jwhR*T붬VՃ7:GfV*L=C՗F <X־h;ChQÙOCɗtF;g$^B~f-tۈ;N\M$. L]RVn,]RـCfsYNU|ε\V>Uͩ\z ]U8݊n. \ hƱJԆnW*;٪i]-R!5e6yr[c-E/T{T̬j̊*TfԒ 3,\muy{9'.UCrEʳ̹LvԊث\Cxҳ 엛u",cvnW S{*4-ӷp°V]`۱n=NCzOqP|8$IZb4Ȥ!<7:kBَ9tdrh)hI0>7PzpWcv[l|tv,Tzrf;,s:AOP4orRyo8'z3)jڦĭq/\ul^u5eo cDm`%Ky -ޝcEX95f@5+q:xp71omebE yq{o9[r+ fC4O ;EyFEՈ轴EX9iCaUV j484,}W ΍MeotyFmIgVfD8]u܊ũk,dN<Ȳ 󉝊{}59=w3N̑Ei qٌv1 @ viţ^^ 3 ]RWifπ6)0CEctT6@ƊW$z^Ux 'LyllbD_JcGG)/5v3#oWطxŪ+E[ԉN)ICRn[+DiaW+^=תN g]p}~U;0͛~lWWUPOw7;h+bk Wchlwf]WM*]X,ܬ5s742p.^=&وhѯѼIJOg1UkŚ*w^MGƍ^jf#׸so^^W^GQv[ZW6UZ%<Ԭδ;Eg8HwsF(Waʏ0ϮXP;^ɱSW]m{[7S;هjFk嬤uRmwJsE!Vpݢ^Xr^jB0kJhԚpiW;ok f3o,ЫCsLÕn0Y|6.JDk]Bc)nBAZR<֮ݮ ZK:GX̤T R׷o:@\`OT]VH]LBu|a(hwxo.&ۺ ]ܶ@S_fnmt;yU sle R =5 %5,U9/ϕnoS;'\SB+ETEMvINk]d{wwnS(N;pIWoU [eZ6 'nj}3wV=iTai;7jͬoV7`OUҢ;ݜ0W |77z oy 3[ŵxXsٺ]Zaun '} 2Qx=yg°Czqܖ5#6퓕4؝.J j;a T|j`|pE093V QYVf< m4^=Ard7hyy*(؊2NBRKIהGd5~×2]qg^97e|zIiW[3ꨩu 1}){] ˬs8(7B쮴; :i>(ecPu&m{+w L'uW {}ݔnRHͲ)Zl*ŔSt詛jWoUo]Ck.|.{xlI+8u3Ms!F;lO27٪l:5»{svC%T՞%;m cΧ؝NX^<զwճwk®[.R*vZ. { fKCrɃ1b1.Xʳ7ufv֜2wQSvrlJo%]R9Vyb3 m΄;HRxZ y$K Α6F,}6>do #5;g Z6/_@Pe}c4%F.}ﯾ|jUрEf#e3 )3/26܃bԮR+37 }d8%`.PIqp`ɜ 鮫_>NªcVˬu`=mU7޳n>0X}(Ի,b*E",7O.Уˁ T3P{.NTJ--wqgwG{2or2t=8f]Y]:צn]^ל^#&^ ګ2^iQ]w5p4L;QLɘ)v}[}/222U!IN|VGn8s/5C9}S_iG}^1iiw:]o&@\5!WF }|/-Mh]}کkyiXcL-j&uG 뗉fڊmzGۥ/uK;U[Fq o\bY5 yD[QV"*ܧ/svNtYچ>PRݡ2KjwӝɗVd˚٥,kV }]RO*v UՋ DW]fG$uJdKqFR Brvuє;KUPݧbdzܻN19 2& ŚYwhq#ueGWKxs[b޻Y'K&dMY3ɸ.`4Ύ5Vm,Z+xH4OVQxXfҍVOnU'lueT:F(U4Xe9ёge7OI^ɊYUtznf ˹.U*E22]ɻQK7Fl+E]VK^A:qd.^#{Wn:m}} 邎mpі+Lɕj6o*V*t7ظB75cζ4yv.-[(A}g9':ή teWSV-3QHiõvfeͭheּtɸy-ݞ=Ûsp]ZE{l̦ʊ!2]tEu\NVIkF*2֋uÒUa%R pnWKn#@r`~gҭzwVy VBmKNq[PU VdWowC"4Ke:CAwOhx*ifvzzeD HF [yݧגhDݶ;b=unpqvdrG )s7!Y g Cx2w_4ݩHp^2^۷q Gi^㭫[2q\9۲œբZVL/Qnohn }P3;]|u|֥d1w;N效7\쭑,ނLT&_n\fTB+f8 &AYB:\::^,Fǔ0՗HeYt -LfVTWFS[!!̊RuDr η};;RJ+5v0ҪRff#nU (v0\-aKSGyVwfܼmwĉݻQY]ne;*n`]mjx#j;1EֳtZ ٦ xݪ9yT: j[G]cR(Unu:0w2op2Ao3P*K/Ӭ̞&7gzN;Ð/r=V,K ꭢ\BG=m̫r|Ne:Y5SݣjrRȝ-yo|e&ej#8RI608s9|9[tν{yAPmG曬u4^ە‹̽D[]2u XrNW[< W{;ȎXDv 3rޡ ;~њ]ʨ5Qaoق:3*r.=ݖauZ0 nkHl`#y.=m="prbLL;8uzHU1\dݏnhm52zq=kf`ٖ(=^5O^hZM9ScyzI-ͦ7yPo{W2k3n+ۼp]FҐVwNeKswT/bes ҨNUuRAf8eFtFE%ݜݓtܱ Vir5*ZO)Yur}wҶǨMoaSov)] Un㓕ҋ/K_c7 r'ehtjeRokw Ζ݌Yܶ[cˠ,MiwU[b.0Ssv}K}R,P͗'\Ks[+Ιcg]jc)v>mGGXW`DbGeLhlT6Ǔ2{(or@*45K9ֻAVfftUsv#J(,ѭEs3je^;Zn{}J&U:v[퇆C%RS 3Y{lҗܪYᬓW^ı4Hj֍voUՖvVL{+fʹwSbJؼi>@W`{pՎدv7<^JDG]`HWvƍk;t=l^QnUngOW,o[PmCc by{6febmgL'E6^Iq欻~Ish̀'\E;N `bnו׌՛R턨1^[|;mYD!J4[ 7AkU^Ev7& oե. g|3+!k[z;+0L#W .ohL8bJitkrXjꖷIvq2Tќ\붺Q 7ݮqAږ1xoĠCT*MtX.9.uWñ*ƍA;2r^:MrqEU5\@e yBz̺!ԭJ^ ܧ$gDv(m&֬!Kw$jvLʊ=l*dX˖,BC,凨c X-4^jMc@TM1WXCrqB4>mEb=7{ZE%B0[ki qiK$]6:S}f5ibpZ*_&;/k۰Qbӂ񻡺Xe 5-2强i5Ҏ4.t˝qgU mx@j CƮ:'5kVԂRA &" ]yd!Fnem/: oav *ꪡo.[Dʉ{P1BTM9VhyUy].+*nzYvױ۳Xy)xԼc5Mh3kcp6]><1tJ .wd!C¢*aZ_B7hͪ{hf₁ZҦuP}<L3KD-^Kx⠇e=S:\`FHe* F,m,8Q5Aκdl d^ُ%;l"d#0nbr[OtUϻ=z/YW4ӻeTeN y׮ Ѕi+UL#n1wU7ws0IqΡJK0\R`5;KdT2b݅ c᳐JET0;F`Syz(ٮϯcn^٦)E 1٫O1v== Fܚz2rkvHSxVw2i$)KqWwOv\Äu –|n*Zaݼw扚UeV;Bf䩇k)im*:][װMAB뼾8QRVzʁՅ:њVMrsB‰Ֆu9}slNqđO-wi]'=6hzc*WQҫ+2]Uʲ[<)ףMvAs=WR25mV&TgQ <2+,d1󻩐AW :nlshWc&;o.qfZê¨OkK );Ư-at7ѕwμ&I s8o.ὖk$WvGo%NV#wn*ػk5 Ekg2\y-7\Jim}JEg&WQ`Ņ2,=]zV,B NKŏ.L]v,7+|\yfV)U[0(ofs|[˪ʢw1\ a/$,z)G],ڗ3x=p;|n 'R"myi4d> ꕌKMh+3je>SfN][Jŋ5f%|.W kp<14;a7a;j-{ä/ 3Mh\F"Λ󒮰hv=)VˎЭE~;Cu{fi rfMlaɳZA73+7Awxq:9ɋ 5{u * 6}x7:]ΏܞNU7⥛y릌etqVө;8xqrUKһgS[mXOvlq|r<VՔj 17 9[|ME t0SmFw +_x9i^sT/e}ft 7`dUe,+uٹ5 sf2K[fuon;E;9i5닻nF*m*.~hxڻܡ {__.}3;.m:xF$W.lONS: ʻqVOM\鋩+tC HEDhaʑ mh:ػoՐ&[gGX{{Σ#dw{S]ڈdܡeoqm t"_.MzDN69Vu#WR*| XSfPx^mUNi\5E˭aVp]=LJFoz&!\w:!UZj;V.Ga'U}GvFVgKg*)ڂm^mb\r8$!vuqwn%Zl"qnzQw;:Ury{^"ÚC[fӓ&$rj3A{Fiul-pe5]u[MbK_X 8U.ezz묇 }\Cvgv]6;\T)t+I|GWkM3VB%ltk-0ft7 ۤmʭtNisZ5xmudNcή )]W3B;f^m1*=]/}VN^>zv)ԨC/P@ÍrsٕuO;6⪽ܓl Q%Chk,׶K㺪Gr72SF*X<4f)jW^v*ݛw&#Jfn>TYeb*hvҺщnɗu};ucpuUγUrܷn1iemi4_>EJ,mkL{K+ѯf5k:鸛ǫPVgfnV4*KcZk=wՋwz[G!z#:' i=CkrݳRpnQ/YkM;v.ܻ9w*wc\nH [Mڏ![|nWnԋLkzz:%_mde5nn؛ugi:Ǚ0i wtgԣW`/s,_sCc/̸j1͔ HVrvw/5KWK }1p6 UEww5gf@i&PId3E_Fi.3~o43L\߾WP5ᄁNj[.C,W+ΗP Z^Vf]eU/29uƶ SV(Y25X[*j+Hq$Rw,nNήہcPYu23D8E&2NeY9osHOsJ.t7LCoc>RbQ3/v,s: 3ph#rV7bvL^Y7$=̭}#sW{׻F֞95Ӱxwh|8mP2fK.HtF˶7k,o^Ǧ'x[ɬoت Ϋpݪ4mCfvY&ȋ iX18Y -Q^>2b/Q͛W[.O.1EtBn*"W͖TrτI]pNp]GEfҗ!LNё&ЭKN@V؃pS `gŎcc6 m_髈̓z\NjPwvOefUm.nG/ܱ{SYn]- +t ܺ>%e #:idTA'}" Cn;*ٳÖTt$zX6/vmZ ΍tI̓L(VZCnma2ޛV52Tvl[ٚ]Ks;vn^TޞMB$u Mp|oUά'8ݞ:Vv^ͷqZ!trEΊf)C7Jow-,b^Vx͉ 5{}.X2^)ulašt="jcr̍LgJ-u[rn@u UZaL׶'w]߉f[x?>nVv]3o'U뻺j[|d(u(nf^9u2PN蒁U#o6Oyfa+(ïPy9rr6;.:1λdž+lgk& wMRlMocy \]XhGvˣ5ụJܠpV'uYlrⓍ2Li{u:9x*͔0Z}fnfss9̔j S趪>{YjH+Omv^:d*]UV8%N^ NWuUjZT6V]K+jpTAK'W]-ur$j;o3ezͦ/v=DVZ`v̵ x-T_wJQ;NoQ[R`6Oj6 m*avVf v\/dc/v_-NΗ},BN KoW qnѾތ9S_r'hJ2[FPa^agVHT!f)ҫoetT)n.5ZPُYuъSB9^.xmpEe'*w(&3 m}u'yRN@pz,l{w_buݙ$F+qQ+x(֓zh,_'NSYMzLcνOrp6˭+jV'b)aȶs܍.Uv3%vmVhĊSsK1\$F \1HbX1J|ͅSf{Ry5uKV .5<زi$1ӄcVgJ]V՗!o--BejF"F3Eu}Rm'v%U\l-7oX73ШqE[ʘjZGrHVA%)oxY>ݬ 7[҂PmZp9F2oK3HPD1R|/='Pһ"赓nDRCRn5 {O}y2n!1z<0Z u.&-K4U]T=8Mo͓ViۡηvU f[QGUK RF t*C֬՘j$!iBII{/.`6ŝm))WNJ1efxn0bB%+Z7`JD͙;{[.bޱtѺv1 &YXY(\Y6ΖAЧ(^9q[aKuk(wimLvf;>'R !;pdEYzR >EyՆ24fo Xq楻Nu`cS>~0U[Vu7AtxݬvC<]^i<4l7c % l b+:](#C'Y[kxv_YӣZ +#yw \z|Wl}F KLtgVBf{W:tpZфY5d`TIuCVTt^Ql2L[Ewe͸qx#TCa=۰KUBY. K.M,B۾A7w޺VVK.v֚6;8V&f}[KYB7D㦌3nKnEL>|8lݺPHqgN]mg mqZUws9E]+F<vS]KcR1v[,*729A7RfBݬ{pٛxt }4U ߩ%QjivWF,lX8kG =bӪ}X̗U66 :/+-n'h:[[T*+^{T.mu&;2U8N[Rj[A'P`;wy^gcʭtdw3 V+,n Lr^ݭ݇\ j] Vlv,}ĩQ]evw. Ӱs^gzx6zW`rm]c*7mo)rYZᘅQkK5w] >yvNAԮcەW2WoNѕNIQ529,Uׇ"wɅZojuvїqSfG+];JbWR:Us$5v(v@FӵSd⼭|k;]-AL\{o96Xqm}BW0kUhUWU8%&𚪇)AA4ގ#.=ᦋqaKwb)`Q>UfG%,w he ,&ʹ!jujS\17-7 w+jCǣ9;KkwposD5ӹzxcx,&JN^A1vy6%ܦ롛*][[ P U :7Wpj%dfHff[ܱ`\M)xYu{ aUXxN얁0SS9|\;yD5~A[^GDܚpI86sna B \w/h̵X*w Q$D/,3DسVqGY1z$!!SJ[Rf=Z#24V>D;.U]]֜sppq9n=.Dq7ZuH!ab'g/:v`}FZ9{@ܛܺ]jX{Aⷆ/j S-V%.=Ep@|w 6Ok̮ŲQٗ(.g>oX۝KCNf^՛k8t `gβ :Aj!U3t4U1_rףRPo3כ•_0mdll_sIlo*umݜZ#7V$p:rs|yB]&V;K-D:cA`.+ֳz9U֝J ʛ7 y8ep'%JnKo(.J෗`}mljVo% >E1X 1 ( ݛ[sěFG 2YĨ\y.h[W69j$/^kѓ;Zde9tsw0e UX"@[6V~5BokVҞSOsՔIj㊣ڬYw-^v&f-$g'gpoJqKLeTTL#%Um2/Rd@Ҡ6vL۫ħu"^wRWB * xeAбOJ/R8e%T^5*uQj,Ⱦ [ot1{]Vsnt4ż o8in], ()%3F틤|l"^~ow*)i/9/;6QLtWb6gSt9}foڸ '|4uۙb^wqJdy46UѬ9ܛWJo^lbns7j vJcQ왑5F[}nK阶W^\+رV1k0}-/EW.7ɒҽͱ; <}8SG[b<ioJй\'rc2+v^TOIx{}E,>m t:aVy|ʙYP&^`K峋c;zTú0C,c-9pٵc2.ZQdiupkoz,⩶C$נ5N9ufgAl&᷉4-硋J:@cd+Fo(q' ŷY Fx: :]؄:p޼g53nv bGgf.lfgFmRɜUY*rb Bf_AbnloI{f [iνk eY53PE][p;wIF1My`^λw/R炽5&Bv0kWϳGFwTAN3t; Cke{WvD.3uwo]YmsinGyݏ Ce'osR!a p'bk{.Rҏ=isyrUB|)p'3TRr4800nO^\5w)Ά㗽7od烫BF]vR7e{yz704/c)] j+woeeӮ5"+VK,_=x{hA1RRPθO۪.4FT՝2JSq_upCML zR9vjPp!u<V颥1=BF%}BMƺDVOybTy9K녎G^X%N{y $fWtO3;c˪:;WT*ñ;ݬjvNъjpr&A@nǑv`X@\rI2]CyoGADJmEͭkaȼHx%qݰͮr+$qjUGU{WC2Y'kpCgpv^orrjWdG&z]oR65"css뵊[ PVrܼk]ёU4jvrI=v$|;w{{q$rՆvazCxn`U\rf:hf»oZ)AG4dkMd+s7bM%wفM04O!5ݳ̨s:ʡ{o/%^WVAT!U6O,fo 疥wKXz%s_J:᥶5[Z|vA+ʬD̳bw'\"Yv8B(Err9 ;g"mWcNWu#A씵+Nznmj1Y kn}1nS+ow2cWF ^iv쳻5ךA)5 DĐ*HGET b ?#)h)amy>Q|pc`eI‰R)xtgX2m^S*Q3V˜ێ2E-z$ N *…&H$/NLAPӌl]&'nd&|y&wXLZκCf"a E `cGEoA;IKycr넧|,׊`[Q W{vbWsu,SUۣk$4RC8ɻdY\#'G+⩱f-RUuBv yzq43<1_ /6,X1ci ෕Vj"eϳ%o(H/Ew[oifVrmb EkmΚ or-ԏ\<޽P,)B">~…Rf*€KJ9 6m BkX`D((\H jb}LLݭh`n֛[ PU6 nILCfXd=)][BVeRs5JNA FҾ} 4-7;Q+0yDX:f2u%VȈ9)H@F VNA ,\tEk b ~Uv󳆅\oV'{T}eye8Y^>~X ؟[[`Tl0gڗ!O܃C6R-vlKVY<,Δؚzi`"`x'W*,h "(e_զ9^y1xZ^8GB*IrqʜKtdng]NfDi*\g6>CiƧ3Tiܦ{ ykLwO ns(=w؝]^-9+e3a`nA|D0oIB-=/tRo@ݰC8hyAoX詠6`n.Vne 73|M*Nᝂ6h0zc]X#Hux[Roj⢻6ߌ`7ZT GEz܀lo2P~WR9dVMM"}=aĞɤAn80I^n 'X~*]QLqm4v"#Ѕ9&(̞mG&athUcD-@MrӠgZ{u@TL#_j&T=+%ٛy~Ӛ&$"F) f4X(QZQHDDNCL#- H3#H&J*뙊FuyB$Z )gjPuE <ZsJ:C&0M췞mRtƣ1_=ٵ<|9fLCJ34zѶtj> ҍ&'9 @hz3=H`sZ;>y J-BZi i$\dc SZ 0CJ8]d̮MH|-؈dO@G@F1y.{;jU&v޶& 1+נ҇ Q@im‚VBifq+Z2cS,<\E4˻'x >Cn0 ɿP l&N"îa[=dO0!OL#ˊ& mLOfbhfhh\]RҸe ;mM}94& F&])v Al;b.۳;#D;;ZLG A A]1+6: ʩ+jUl&j [禊6f~C'\k` ($bU5D/o2ɢ`Mw^'JLMmy絾&:.Sq* eޮBIIL6ӣYNM:)-̒х0_i(T>2R/L)V>IZI#қFj>m >Q4NcO!+O0M2ZB[HYgД:;Y$ (>hB`5G|8qtKr^Q!>w=s#}^uHAykdHQ$: !U.> 8uy}C Ti+Sgxxzt$m&^LKװ7wG?3'DCJ>? $d|Yh1nϽ:y&:d7y!Hgoxn\dO̼3Zɵ^/2)BT7i|UX`ϓ3!+ =6H"$b$<1ujBx}6o&Y]h SCa4 1"i4 +T[JRX m k6ʖj]ѽ|h9<zuwgw̑EӔu/\yl{!HĚ~-Р|epJ% YfqrN%DR4R`(k6VNA`"R yQb)8}[A}>5P<6jMXBHHѬZKh RB˷v6%L"k al8:Ph֊BKsH*%+P.HsZVo7buk~CU<4'|k:ϊ=4q'UURM,"zo3.BQJ>pm'[11c~r=C֮E4ԱtqQ(o @Y0{j_ !}k|EUVzִHdC yT|:tIHSj] B/6` Z@Hu Py. PP,)(+0NePb6:`fB i5,9u6D+$K'qղۚѭ)xܛDߊ,Cx'pvU+Igx5(kU_?``"CꙔ5cq:g1(#)f!9˰VwZZxD,bH|CurfRfn U(ABLL4LC;|p6%4JPؘkkAh.-,0̵lplc-  mYcabbe tR ;9CJ~҃o9[,: N{~_}ސ]}'IYb)Njv7A4֖+P$l>LͰƨA9Ouk">@ Z+ 'C@xrjHMj @Nmd|ahj iqU31(0`Re-+ Ycn*YyIHfŀPbmccc),ˈ;W^SEE՝gaݷ8T~z!Ix, s̭/o[ݛ.4%MϾfLYYLP=d>RxcWW1(ץICh(wU2ZUTqTaY1`]Ęy H^0/&xd ,;hVB<N_ɘC,po%`c` h`mkLH( Ds@fRK5 iLK 0p1,,BmGRgo椩SSՑBKUkoniv|ܲH{k}6gp:m; ~>2爫euİ E]#̦ ",+#?x%3 :Cy,K`),=$j8 RH6 cB")`Z-[Ul-!Cq ,F[A0W0LPl bB,]kqA0@4*6+jRX)"&#&+n 2"usC3 P"ssqtQНAA)3A!E]~0xj8r]Ւ*Qݏ{ϨRsѐi[Lpaekyk,Q;\z_yqvY$l@I0%뮌l:m!^^lff\NU&U;QD(6lm Ɲr\'W+M1WkU>}Stc=/'1<z {;p> ]6LTP-ABԵmW+M` [SCJ)& :,Lm0ѬJ6`b s0LWހt?ys|~O"X.^w~e<`X:mV*[z&X z0.[SܴyTCeWTC0(H3L3y%Y*vw] + &/8e }f xZnx.!V=[Hq 4_%.$C:ivlڣz>[Ha(:c8(Y|TuqP* {h cN4P]4=%ztPdyΥNfj귒T1 M۽&T\3 1\|7uf1(HC Q)acYb3exRmܳW]-tr.6Qlчn 'ad jt2T3&xu!W`L-Vs![^ר|AL>`UWPV/.C3J}ܹ &1_v\ڪVV[[Zy(աZ)vE^y2oae'NKT̖͡Pf"taUv U dC(K޿u M*=T\t#j3~H+r]V NBfZ=EqIM YDk9Ui"H=tYՂ0Nf=|rZtoT-LdUYU:72Ap]:"ݺ9C:meΏr IOfycb?sRQa9>.k1 "y>0ƿZc^ܒUrgbgW릌qiQd.Ym ύC`w/[G{2t<ڱ]`z7%j-(T i~3& unZ`< t͌hg 9o66wNw (aBJS%rvؼk t&Rmdꭺ[B-j PNаEW(ImMCO|Tlm6C>fb$GZ?A"%[|^kwnuPSfRiHWeדOK~\a+sj7+'p:hެf=rJKP]MtW@`>H%a (QGܛpb6) Ј@mG0H.IءnIpS42$)3dÀ؉v;Sa'^[Eyکl5K^?atp`2|8 "ڽQeզo@I ,1X`'eL ZoUʬy9q;M~)Sn)iqm*aU. ɥ|\W!3To-le xuy)eW6}{N41bNڦ5*ˬIz wU{%wM+=eP-zRjA  x27Z kxԵ( 8 y[#'O=|5EY`|Gߙ%oAahԓh"5[J|4ioD\}:R"6:0Dak3{SF*RJoX kI'_'l%^Z?0MjgT-\OOdK3(/\In߹4±vM +4M$8TwA@W`feB>xjSlaR1~$x ߄V#^$"H$A s`([F e|yTkn * ]K9acuj;V.-ڽ+kO : Vt!\\^6hZCtS}FJu5νTn>JlRW`KH5m4 GIjPJ L8lD*`(塧6YM tf!ۨ#J;)oY $.QCLX{u5nLý*(VQHr ٶQx[G݊' :&yqtp"&/SHZ\k>>t_6:ҎiWTi*.:r]o< =ʺpLc#qTDKSav kԖo8$i<{2 "4lH|4E(L>&+ h> -RהD@B 29]:|gcB;ͧ ?{H5><~YXlt1L8'N:<~MQ^~O==rRg5~k E7 a4:e׀fx, m$"=>= G 'RCNxH;MO>ZlBK^10\Ѹ Bd X6X. v X.% P #hޡvX#m`6. \lmlWcwOeeַ@p04Tު/+!(|r7eqweE W!\=ӿ pmhǤMABP%!hR!n 5)a -"Fn- E,1Binh DVmxsOeCZT4R>5jm܁;ߎ*d:!UIrzs4G9"s2$cʛ7G9|vۼ.4'RddDM:HG$ NΡ\hns=Iѧp M#hhA4f4MnԵ \ D16ZZ& v[EӭjXp 7bXaRiYie (-,Aͻw|NIǿ8BpnNk^l+6u.W[vkUuOV \Zbk0&9m!B4Hnx|dYYB3N!C_z~ h4PP5֝-1 aZC@h D͡ Dm Cd[bK]#ӽehؘ%SkJZD{6X~?UnMʷѓ^iܪ_ twzt޷r}B8T>}2<%THt< HzOo׵^AM20kX DV>`n PX׶~ Ztu /Zp җcBPXbaTFFs10(quRҔ B1 Cb5wEٕf8{.N5@D\ŭp\J)}m5\}ʨq1Q9g̾ިm(y2`/gDHHOzO2+'Hx=}F '}&|5-Җ .ݻq0 CIp0€ )bۖZ!ae-eeb%a1CHDw5k;DC7%0ʗi' <Nq W*.߾~s<νv[v:N욢 LHxP$NP=!S̀-aD@pxVy Ra|كb ,. K2hhmCY6*kZj0 GHe-qGVXщi`.hѭ:]r,޼t<,z} J xnW,+Og>3>Hց[XIvıq@pb&Klӣ0SJ(058Fеtcq PШգmG9v ; ݁6sqE$V >TlSQPaIoHΝpЈ0 Jq"@d[8@Q{ `@Yg Pe$nջX ܐ{KEY"fȐp.'P=ZE"zq{8},{f_v9K0}VUQM[^44&2d`+`"b҃h.,6/m(:̉AۙžfM]O$:k*8m٧|74{{XNPgWK 4"!zdq+z:q DLg $凤 a,K|ܞMqD&%m镦 dQmL 4}"D'yNb3:p]*`L:dZi Q,"3gnkZzQGI[p;8J+;:VNjȫDFna9ENuhK޷w*̬~ Ff-TCRa #fV&j3\p e)Hq.6sK|cBDO VAD>ᚆmlėP^Vu OuiA5|mtA~j? eNb)g"SUJ:D˺ok) znJZYyG!/he̵(DSBS(~ɌL8&^|S$`#8Jޠ)ɩDmM*u,S%ҝ[Xe&e⬌ehS2U1u"*$ԗLjNt6 1NUWdAɐAHTO@GG҃T M!|TL mA(sܨģ_@̜֩ܮ K h6]Nϩ.tY,^DM5VYN,.ʞ@ъi!𸁵6!M ˓{*]7%۵ sy[Y,$SxT1sJ/Y%KYDNب d4mI:FTvMǬp}J!Eil9L/]K|m.JVu]nF=ٽ4E1OVs"mګjU*%$M'W{ۑ WXݽub0u=-$61tDV%Ԡqgqqʪ1%*݂ 6,5 a&1FSGyf^ 3]FWfl~r>XSCi&8sl<n14тGMu&.dd2MS){z&Qy709YîZo\ʄ=WKuy=iE8]eL-KcdKoc,"p:*L(UJ-/Br2 C.H ":m* ުUF^%ɤ(yj꩎CM1f1E 6QfE$.J0Y ̾`8a(Zc7C3wX9\ {5׍PW*܂흮GOwq榙vZzZݛaʹfbkY\Ywl5,!4[ԱÇkAQgx؋HezcTm u{ tPQ2 dO\qZߙ9pUx(z9;._"6m-w( *@q@ R}cՎCh;"x/}8^Ye-juT?4{ WW{0$dz.ι3)=tczJ͚NӾ*!z D}N@0:"xP>DEŵ|7f:-,, Am2а0T-(ql0EDhZZٛit@!iwD0pKK,0(ppK .-BYHÎݵUawX#kD vl6h>88u8CN=Xm (tBKJNZw)QC}%aV!qg=;]²IXb,/Km QB¶R8&* j"DѭCC&UŤ0P5cR"[C ,\֝&h(tJDeɗSvz4ؔW/5_½c77ۻ_qq yXz-QI"Vq>T6q [GG"8%XPwVS(f#A@ڈ浭4&h0CЛA [hp1pQMQ DHapHnoB ]PFb>Q\>7!@, +25#HSyfy 9d{}kAkByIuG؄SD= d+yT>轏&@.h UL /tРB1(K\Ƅ VՁchb] JZ"A":0KYPd("h-KA҂mj9߾;eGG؊a;xk٦*}M'ȕ]6_}_,tX*E(330)X'udiD'"l6|a@Yh(e`ZLE@V`*He$"%' ƄT݉ijb(R"#!)Sp><iyhq O"!ǽT8rxhsÈ ]X:ӝjMNgrF(BCBqC̀PǏ+9#/sfͶq1tLq WSЈ1ՃabhP ,T4XYAJ@ѴqPK-,uhݹBRX[eP43,y&Ow8 վ~5>S֟ `{x~;ꗳ|tO;@g0XZ`nP靘f󗩴*l4ޫ'PӚ q-bB_M}FVbgaR2ӐGǭoG/]1^vSPI{HdUkbPC=̒nu|3g5<`D/M/JHmĻci0CBqʁvG-6,$s-+z$'ͩکw8&]0Lbw7P6lDXAugN!#a=4v1 B<Q[Euvdv:ZƉ Iă\:vv)|RTGcUḳ!gSYHtNͧQu"P@BM *ڎ$ ҜGuupupޫ8W^Ckwl"&8m U:i 1S5gG4c}WN:Ja!=qp6G:`iTZTtޚmzɴ$H٥Cd=)dwiކbIrs; 0c-Qv.05ٕUTE|{A-d1"զ1OdN.h'(ms5JC҄%̫ g\F݆EE[lgUyK|*x#kCVԺXgi6}B:&f]D +mWN|+G H>C$ren s!Mao9}ݦPΥSvTF'~aH>\˹bH>KB4YLmRW!rl`mT`drje HGl oBf6ۭ.SnuYT=\xɱNngfZz2!R%nB$ R=)%E¢.Ux(#J>x.qls^7}fʹK=X`I@V^v4oh^+YI%)j *( ޹ge+'ang @Yי 49l[{6䷹׵" $-_IGUlu\Mj(VQՙq'f6׈eLzljyfRJQ_UM'̮!J1wK:.U.ZhcRڴ̅m% 9i8b=KV:,8iϩ$B5^o.\h@c^ksZ~Wx StC4*,$Iex6WDj8ltSB,&?<Êxo*Z0H\ -!).>N*"T=zH.<՘M{h02L!Z"TӎШywU/nL<3]P7wp9{o8,u{t:k4-0tlZTdEadMP=~O3TqO55Ъ0=֡< 0]xI c٪BP| )Y'0ȘgRyA<zTìB$jh{#`x h(_WpUffX6&ݗj^H Pj jhmЂ]ۭ``NKF/IihYe%)(+/Zf77LeLrM"_F ;};l0{DE/j 19oG5xeHXPNIu}zg |V#I(N$&=S nS2n 0,iCHi#E*ƒ(h,KtD^AP ME޽,l ܼx:vG7ݽ}[̐,^bnΧE`ܽ֌Id{P ZY:O2AbLBHwhO CZ~m1Lt Q€,P@QPXSLX.  .*Uz-,t^T(h͇ikΠ#_vO Nn@y8Kdo#6vc8~s,YLY/z ;8'y{XJm,L@X6 0S5jBVH"p:W;9a % R/ ,BYf \1EKl1- raT.ۥ(*ED\E̻B@P; 9u .{HsӼ믏=Xg`0ztÿYzo VH=t5YF>{3ل=gbܱS{HO,0OLL!imb|C{I\ρ5HPJ`hUFkD("SdBXm) LL@G2`3J35cinMjеhT(L0DUZ}rK7NgmKè(/ǹNy_/΃ާ_$/sj#rRBP{q "z9)_XHԕЋs:'S*(%DG| HM #IZ3Bbau^LC "#e(ZC@3`hE[l1To"KMW1p5viJ %)01A9oI8s_X'B F!JN)Pq1GPG[ 9,M6J2a@G6P-ʙ~Xk]ar҉ q֯g)IJ,>&}yuM {FZws%QD)^g-[E5T%X QSw=Na8D lZkԐje#J(e[Skc~D2OEݖIE2|Q>PUU5 S7!,Z͸ͳC Y%Q( DHjaA )fx*$(oGL ۴c Eئ,vcxrUGVFBt'HmB@@j>$tKbTvځM3 x2U68HЫl]YJ;7 PG.$QㄣUxUA@$s2ĖlÆ[G #ÅQAdYT ⽲Zu~C{a)TZtciy*{"#!uaƵ;%q`7@,mw]Q|d٢OVHe8'Ps( S: ̺aHsN [,<'\V10ɉt`H;p4 ~j\WUܕ2ހA'iCo}ϾpP/_Ru%M_?VC9@Ļu>6WV_&ny P8uI J<yjZ$v/Z ݈X IYaiq&0)pWP12i302)0)S1P:Kv@Ra)+kU:}ޓ/Rru B=%ƻLw4}( &4źt׬2Stkвh٣^TQf GLUw}IR2eR7U{dWn@gP@UͫFs%9{Y]Vpx[ηPi> 4n6kp%w96nw9j31AGCd{M1xa{]+zps`fﮕCؽLO8H- S6x/x X<: &]vKT*!|,ZI&݊c撉H@"4eܽrCDq+*TJ\ӬYAf1eH7wINj;{i Vʱw,T@.^D& |KBj^WXDaq,B'$꾢:uf>vsWWe}d{p欀l#7epv =㔷rT7/eG*YXwwXt{FR{ι-KAUxrsWAEMrjZ>O .o0YBܹoՑ {I8d&[PhSƊ}>UBvdq{+(<;m"xck 䬫KHWt.N^nk(%x'/&r2Cۮc1E1_AAUW*""c7:DPuI1dEX;[ KFpU2փbm\7l8G1[oբENTƥEnt3oЪ.'K0VjQcķqo, ؊49+C<¯V]j9'\ZyW(N:cbv}3 ՄB,ф$QKcTn$w0v;htUSp5=Uxe` tZ@Ғ))dAE:fy4됈e)-{p(l$R#er'.fyf5pbSbQCh ~UrJI*Vkmw)ޱ(16Hk6Xء.ٷ8mmm zxd, TА6 b}H1.6;smqTL+bvs]b1yJ Cn ۻY88٩>7goB-$T|$ #Byޒo#.! >T:‰QF!D+U/s.+u=]lWzD{rRmXm^LueSI6 ,Ta Ak|Zg5a4XJ sȲ ( f ,i:H3JRdha1U4@#PT|0@vw+hٺj.Ub6j$` Q+y=/tnR CH;X7 ,b*xk.f7Vɍ "o''j',B:x )rLtg1)kMN *U|gS2'YS1]+SBtvVvʜʦjVkYqYzVObG8"#ѐA{u +[͇^FU>7"maZt4$+ؐDv@6#-!S^~|tr9z',6eGc/Ҷeעoh}φ qm*4L^A)jI괨!6ږP-BaVhU89[Z( H "to,؈-mU>K: *o\K9]e:Gͧ6͈O[M ܟ&jj|mk[%-=zn$F. lGw$@UF4qUKĂBd$S^ltCϬrd/F"!W.TVyF[xԪ~gHvUH Qp5g-3~giq>.U"};8,N!Rӌ9C㪩t^j/am9*QQEch3"z'9|OC}  O}N]-0 Յ &}11Ģ$r4HGT& ꐒkZAuI "kAKC_no]4f{ 鞰7wi$wp=BwߵVڗ-Ŭ>vs201E">D$><,< WIIcЂNk0\CvYJRP[02Դϐ kFX0 6vjl4aBiiѫBcESږ],[ P2鐻 6s1?=7g/_F,>Ю<8jp&")rtէF>V$OQ<7I#N*@*BzR|ՈiLEޛlYr BUjm4`N%`&L@hևA 0SE-[\ 5im@(8s>6Hua4{өRiRLm{T:MJٿ]ንêb=P3gyfx&Fd Tçol`Ƒh FGZ:K. ֕ -#S[(B2D211@G TB lA=FWJ5!Bp@kfCWT3V5Ѭ^M^`vj !L80ghJ:M%X{SK߻ ,[mIfNZZ|m}}Ғ\Eʻ-A` BHsw~Vn!Q=pԸ8Ă9)T-'S] Fח-ЄEr˳fmwB-68#˅Va0V[ZQ:6TܵS}fQ5lXE1*US̕DR{#29!׎EiG)b<(}_ C"eJ쇉z= %a@+$5$YLuz:D-T,~5`R#@nnKAubpDNf.)vXhahXbZjIjX4b&P4`Z`f#Ya`t?Ս͚(0f ޑ`wS&5y{جؐƈ=4y1dQ./SҸ}޽wQYȃUFD]aeLK먚ܨ Mx*9x4vWPWv6 zUPDS+bm-Q՛`%QtM W P%):H@ ]Z !Rj&#uǩ3 uH^& @!·,(b} nxԭn 8r]E d9Z /`0|&^kA՝u1aPw0UER%"ZKh ΗYk ̕L$4O*̺s)EA$O"!(&SVQ+{n0_ )*v]ӧ  %X7Rf\5 =Usbw R8.Qg5yi-K4pDmжEAl'9m[jMea_Xu>{~>Q$,ӾVQj9 :}Q[;"Faͼ Vz(lVf[53y4u򞼜 hH弡Ie32Yx VgIkޫULU/jӪEq ;f3.حօ1kC)5 DCacdqu6t|^9=`=Ms11|JiZ<"Q[,a^jw-H(:ɻH=Գyl8>8THTWFdObMzdhtK`z;M Y `h^NI1H߶/ :]# a8qX"gYAVг1{HI4,lW_/·ЮZfVf mg/>u': 'ԫ"!TEDcB/F QX-\٥۪$`3=ӷ4\Us$5v;MϾiw[k'.3) 4ҋiq"6/)h}Jmhii܎Pd*#lh1DR\DYk*daҥ<owD-{Z*t|yuҬB]%;컦Rh]ݯVή1WD[̧]=| gP)H3tc/rq¥TKirZq)lbգ R'3Xv>6+X1&!Y-i+$.#x:ڔ+y#6%+U՗n8"έRGw 9H01IiU܁FS &F@|P{UBw;4Yb""ޏ;1]zJZX}tHD Ёjz6i=@5CdSnQP@NC"^F5U}l=E6LܪcL$F"HQDd&ƼS "|HfۺD%5pQwiX6)'s(w؝ɻQ\ul)Q,GRܥZ«LECyO$n(I %8@JH+)f\]iH4L-Vr ZxE&N;Ui5 }VIT-C%ٺqu5^gG¨gv^) Ȥĭ/"` V&n'Y7s#[lim5wuƧG` bjPYi ^VY(Vs_t6MCE؍Z=x^|뽓z^ao!+B0+>$pW [dPSd}= |ÏdKq&x/)I *Ce _YPR,>W<;eY<1+ǁ {46Po \! 1Lj[eBlJՃjEjcwatV(&T'$769'ڛ\ֽgN,^w_M*3ޟ~=GB;17_r5bCizb=U(rh I*dN1=<'JPRP U-&6YZR޴-זn elR-VR,?6e$\O^!_,l;V\k9]עkf9G/bZC{5DC;!R1SR 61h[@R_h %@>uKK%+ql?\jԴ33, B۲B4!+%ko&RtP0鹻 #wGxf lpWoέzuG=igr=Z>g7CreOq l{MdO>$@5CA򆄲2j/&aT, TQ-` zPv __^ٴ@/IsDo|;Ê"E pJEqa4bzz\>[4}JC'f y @77ƨOY+>Jϛ>-jwAWHR%,a5I@St VhB`U^MjC,֞ac@kۼ3pCi|m4^YQpPd:Y=Y'@|\hG}U}π݁Y"ELDeJ( XtjKrYMn7)%$׵+]&*Va3LACN7%UDZȻTP]De Tָuy()=ZɊ?Tgׇmi7lNuªu (GG4MjQ;=V͙]f&VM֬eH3}mfUa7X,"uGdVgIYa8E*p};@>AGXBxkH1tS@Wg1ӈu6Q-t+`z8PڢgC$=Sl$15B #"DmkROp#aktzX/|2cOf#Osqb/.ejܑѐu%(^^;Zl) ADtt@iV++&G{79޸K,u`€C]>Vq;"Q<|T't,n_ /Bafrl )5agJJK5W7cW`|iB V8dEyIgeT<_uiH:I]5t. !M**S Zt"HC*lzFk շp !sZ: lro)0L*kf7iZ9}؍f)lg[:Qv-0@HgJȏ[Ҁi.ʺ&+"IKs%" :Y H3 鰻MN{]U9\1 k+fQK/0Hve0Dr !Xi8eCfEv DxW)oJ'sT{FyPNR{sY  HQ3)p cd?9[\>:gܕcYUDsWFvW~~3i!0Y`q*KĒVodb'nn +8>iaC5|^s$SrFkK`d$ mp:8ZǛCxg0l[(50G9{e.gm#4,|ɴLjke0g8w8lk@0%]^68eȣGć 9Yg&=~1IzZ^5`tѪ`F]'G,ʘ&K!K\a^,"1gȨ\yDougxμ)e)EVji+1k  PHBc`Kc"aܠEutSem,磟`@tS>]P"E\LU%M!Pح[V֠:]fcVB - 'ÌZw63lv6eyP/I<ɞD 'ȭC8k&RbjTsZ\\0gpZktֵMۤNj^9I/.a7ƱXJyбfB02"|jJe`> RG B$°RIC0ֵl"PA KČ!rpajQ9nDXȭǧ&vl; 1)to#:)mB^ Rkb *Ւ\7HH˦RzdmBypqR,y1Pz٦!aiz]54liIݑIP7ZeBV4^Wg}OP'ýqom&nN(>dYz&4iR0I$1=J(OET<ڪ{R1(ƀ Ll))00.( m ;۫,R*f=*wY!}(M|FSs/ vp}l{އ{bggV߬kfIsCxM2xc!Ĩ)5@i Yc SLjzydY3V,J)ʞU} ՍBD 1Ֆ#iFV6%eFҴݯcoRyH{vII}~K{|hn:ssAzx8!FI<:CQINxP='|"V"VBD|T eB D`U6Q`Z8UJR0T% wT%!X@-9a`U PPV WfSӒnC9̼+\WJVKaGxd7FhEKO\T]V`רh6Z4};YS^]wj$ncl2 H][՞1^Yҧ 636~N,gJљ&8mC @Ks F>i(,- r(BXXe H͉:hJ@ ZZi襊R(.)\*~J)Bj}&{~8lD:;}V=M׈O-!^dէK%V][4]2^*K'a`X};!_Y0'>f5?PTl#E!CVn(ByC@@ m j6`fb`e BRIb6``6]hQZ)W8]rK<='BnTP{wx!8r7[Jh$ gl" ~&5aj%8ҴmۖX(XcBҍPQ@4ЋBm EB" )H"%Ze% ERU%sѯ6/z@ H?/ɵY?S3rRUbr& QPm*mސxe6'BT =(e\"O`'A!xxސ1l! UmW]A/s#//57TH|R}ul]O<5݌rӶ= w{btX,Qzvb"\N֋~R\Rz󅋚ܪd p.>ϗz|O}ɘ\}jwX!c'S@b")B<3u!}&u61tѢ &Ou5RFTa qvG+d<>7H0*'A!x<~S9 YF!mK&UR 4F!iNBB!>:+(VVVUňi|]y#OYWq}Iv;)cb C~gI#D8| ૠֶ;Ix\> Hw#F BGW1iuvsqRtIf$3'MuJȯN=23JE|(Vd;%sۮsivW/TW/ljv=؎3SQ6P'<\ ۥƹYO[%I&ad) W鈰j0(F8-G0e0"dd0a"x/.Q"YMwˢǏy*m3i y[{4 V;oAU4uBV*M^]i#>dư45a|OYy8!٤,g$9dSVFlo-k.4ݣIݱȅְϏW1f3f_XRTr )hwF DΣ*RWq.Xs(m'9n0އ(HUH(CJXb_]սR~/^o3eP\M.̬ W.Ys:T"wN εv;%HbvzN7TZv2 nTAqcv&:eQyao330$q:x -kZ@| J2l^d3:8Kw9٢dj^1 1㓪 Jv)lwD:ȸoheS_ɻH/eGr*WU4ùzvn#rS[Tɹcu!GRBU-,#Hi3wlbOq'3n!wE:̴k6whTAB!MjQ1j 7)⣻b\c4x"I2 kbS-tslQ $\K.>VKJkW"-iW\Gq+2\|& ,б}7m~iU8h/Xٌ1E D+%͂5(\i+*M$ hyZrW4U&heUݟ2)g L, ";dpakrE0RY=5wEhO ޔo!S.p[SLKf2M Vژ+D!j9쐙FDH:GGnWA-#[k`v=K-faP)"lзrz%n:hIW=&t"+i~bj Cuz5o&O τi2SM(d י$!Dr1_ny[Eb:ə +DuJTߏgw+l(YyTA/ ⯲-N]jv}igɀCwCތh}lway+>X:ʬVg/SZR`EPh }U1ܩvV|\"};涤]wY,t잛=bX}}hmԪD>>QƆ+{wnhCnPTZ;z綛wM+, #eL @!O"y|ԥVL:VAJ{5m!}U65SAe RБE)4%`aBҎ-bڡZ@R!#yjZؔ64{uTV]R=)ȽjJuCNLFC$^!םQ05 >Gt5NQ\U-p+"&7)o}mӭf T"TC #$30X Ȋ :Yc9kbCĴƕjC.2R R2,`FҨ3-KD r>*Շ*זXkCf?QY>嗾1|}ѝ>]wfmPZǢdܼyq-s0D=n()&%Wd'^ zSl ]DSݒ"AJE\*I|]P@R%)-(!tB]P9Hҁe 0Z=<ݸ;dUZFiNU'pIǂn>m{EEOv>6՜wfB{<35疌+XvԀ=QSK䶨SɥEy".Y'_Ӌ {ʰ;VNzV@ŞZUYZE QBySLW%Dʠ$0@~*2K hmh(n-(B.. аJ˴- ]z*€@xۜ"T{5wj򇼇`?V}>@^ Q1\>X ]ՈboQ汴̋$6M>bQmۤēV2VFEY<ʶ۾)[U0k>ݖ zcˆ1E|-J [aE!@p 4流YP]aMePKJؓ޻X{oF'br`QQ>Nϖ|Vu QBlVNxZνލD@Nuz3Z=o3UӉ&h*:j$ +:SJƴ>ݟ}>gXkeѝd]T/5pr]X\@*>z; V'n Qb:yQ!m)()kRf>`+ʿ);,m "HCց1Li) B0i[w kVZ)@Z˲hZh Re%4@`ϯz擒lFhbn2bQ0>$8;q=^tԆ[﷬B@>+"<j0[0&0r5)<h&=Ez>]oYhT[b+oCf殔mkɋʇ<3i@`dXBnr0 JC%@,-uw fB&Yije܈@&ZbXb':\<{ɨ?Ͽza~5R¶cʎn[ѱF++&hd@ ƆӞgU (R"[$e*, 6BS *C̈J["eO iЩ "`dQdՉ=E ROvl DWֻmr_cnQ"6%<5vR]]6"F JR*6X iִF@ aBA&ZZh4X6)|&T*..M$4Yl8͊*-^4y{em-[W \5 +XN $QEED &UVeRy*#$5`vN4qݭ:)Wb$WxM*>R! .tM ުp|rm{j $b1dYfkQґ 6Hi<;+:P^z&|ϾHmS7AOYGK< s"T$|ַ;FIT=[oi ̛8@wSYty[6Heuots>˫86f%bUy%!;ڢ& @ݣH0B~fCy9igvasG^otJnm=up!˫)$qbԕ^QGz=\7$ 3]{Zl ZD[ oN+6Y]PUܱNɯ؛w+γs_4SU.zg]J0qVce(EDwHqV]C:fpdo|!-FJ:af/ekywh7Zox+Kˉnβ5uz-K!bN$NoU1k26&O01itvT}WDnʕvhJӺRLyJ9[O>tpjNCOٌeYp2XED*a )q: @Dla|qaMT%.vxj26S#bF駲fE 1* J^\ڏ4Ao:eއm>'P((\ݎYj\ʨc`u޳9PFc11%hB(u {a ;a #i囚%čC[ڳV{{ Эa')(g; qw]mИ_u 8+Zhՙ\(آq"jq ؎Ev_=kG.b^wMǸVO? 88}IԖ\ZTM̂Aaн)Up]W_HVTVڨ8B2,a"LJ[R͸OAWCy*N Yַ#J+zXd驓,d"BI`X՛((QBaQ_[9 HD>DWVL'꘽Tv@ܫ7/zYJ7 ~.)t !̧<> Dѳ88+n)ł"fI2"u6M0;85}sz,[u@Z\( KM:(4k0nKĺ"uMrs7 +4u oTĬE"kETat&3n:gԖj߮jߜf(?FGPvTu@PȕLE-WjY*M׆p}[Xʫ kvS\*9TQq1.RU HrHi 螃$N;9E -Ą5۬Sd+emffnn v՛d!KήTQdok 0oZv.C䷺湋h# r^-b!{HJ]S WyR#5jtB{K=gxeK5 ah'd͛&LB6hiaw^wWdS5&Em[tewQ:8ӵ$$m)zu#ϑA!n4CSxGqV*MvԱpޞdBn}֓(Hj" T}K܃%$|;6(+>O1W5n?9[J,ni*hWis EPDEn#wuuԳUu#%!Vr`\k{|0Ӊ< ^i7 MbVL )H%Tr/EM+}*=xixv(h|H yXe2/qŶ7lq4'@ 5Rг NA  z~PP1X1=xȖC,Иs%t>yxձ3(3|ÁYtşDF*RzOxb8ϊ|T@]{rlmmMnte9|9`mYywu5$<bƚIxןW :J31Mz&$B6Nsv>:-\iGGS~R TH'׼ṲfL Mj5ڶ.c ,,Mm%mRJL0lCڗ?|:ϫJ@LtvNq'Hz/Ԩz賶No╇ԘͽiOmڬTz<ܦ"Һz rjy3`Ud;Z &+W֍*<1Ht9رZr#& PWXXxEArn6o,FŷY, WZX[c (̱mRҩZWZm0*E(C sZtQ/xj|m9'()5'7*r:§jIWֆ0zxz,1''}E!=Rxy`!l*ϩҡP^_Oiziϲbz`O~iEF u}+>P\@6kx4˷bUS_m*13PR!0rIMk1jmnm^ԣݮnkgWۇL-dՁ䆆%@M*GM@yHx{ȟO[ld3=g}H1zoJ+}8 6|32CED!Q%I!Q+T$T!:"J! èI-+I@g:Al|[shQۣb}mno{kY>mlKEL- mR0 LF-C3ˑm03BmG10,l  Řmh c^) N2C$/yKj Z:*A10d>I@b<3y'hI<)<(xljy5Sos>.{2dY I7QCL -&P ځHu$냃SO;l¤}U4Q@L=ATI bu _n_ r%m[WlV5WᾶUEyk*螢) 0(,iLC Bp0\Z-ځx0,,FL - lL0\,A KVՐűqmDP bZb5|U 7{˲-BlT%o{}yp#}$0u-ROV2 x1'|O 'i=Xs:z>|[aذByY7IG,E@;@O-_!ՑdВL!ZMHa D_Dj}_-m;|Q**y=M@*J* : ,(y*c iQXBM$dHH'!0v6]UEBBcw"``&b+jh bX6d%.Z- `v(Z"&. V0L1 -::9H~߂nv?O ^} ? ҏrDx6 6{͛o <lZen\#j.TW_n?߿;RO<}?<6kȿl;Q̑v:a^գJWLtQJ+ 'ĭe=;1~xTݳ!C7]o1y%)ȑޏ5O(=.Wv&קϮᾹ#rΙtWTDžȿ{rrHOFڻi/(`2KEC$8~#qE/zbBa!drbVVTzkt&5@5vgHiW&I^W&VZl?WBO傍{ь.<||ҌK/ª]e۔¸?Rt_o&S(υ xp7#<2[;-b$v% tcs.?-'EA*SQ , ()}]E6s9 qiqF_4c -(}|}vjhH! 7 OAΏocCqWîԃ'ĨA(s~ߡ`qVNS@$7GӥȄ7n] "E:e=޿Mz<J(Q U;RrJ \Rfdce)_J,%aH0>pUP>|W;pu :44Hpy`65u =d})΃_GQx :Qݽ߸X󃶑6 jI ST^veؘ ?;#i:xԻ}+I4_fDZӴy>''7n2YN&D>m"HO'`׻=o,v?!QfFǰ{GFQE'ԣ,,_ sՃ!'0.Wb34 J2lcFNHc<>UFAO? b(E#ˡ=*Q‘/mmqA2bHŅi!I hЄ I4h4F+C+dfhMdѢ -21lQfM JhlYf,dER3Id"b)CP#E(4iXK& ŋb-MB &Y$6 14Tc!٥h%`4!DFT AjLE`b$LL(Ƃ1FFѢh#c"jY- QY# 4)hQj%cbK`Е&+lcchHI5QH6Rm &AChcch5LP[`PV4& ɱTb،0Vlh*-bFI$-FƴPQ ELՈQJ,5+EƈXѶaRhI6 "ZJ"Qj[[QjF !!"fmTT1$ƍQPV&chѴb+U%hF&lF!j5kō6جV% IIFE l 0F-a0X(Ģ1Vi$5TAlmɬmf`,Th) ƣZ6jƄ U`I dɌj5dQmLTXKfІCS$2!֍jQi"1e2#2j ",Tj eDȱ jh1&f %)d!j6 Th#`bj6-hѭQmFmحjZƍQQڍRkcZLTFi(ckV5QbkZ-IId"EAT6-ZkF[Zh3miQѵFj6bD3blIlV+5EVjڭbi@cFEmTjZmhHUѢ-dEh*-A(6j65$Qh*&-ETQMEVkmmQjXƫ[EZjֱURmZmT[QljѶ**+EbڊVmbm6Fh+l *H* b[QkhcV-5U6hՊb1UhEE+hY4`-$QXĈ&6 c4KbdKkE*5FFm֣jEFXcU5bյVPE$AdDAYtUڢIj-EjѶbō[Qk56m4Ѭ,Fѭi(ԅFFmmFZFPc *K0l2i,hhZ6 Dɣhj1lU`Tm-Tb֊5hcj*--llVѵ V6hhڴV6hժ "2 "HMP vN'HpGej:7x,GVNb@"t+P;sW1)# )ً<3PX&۶Ƹnθ$llj66DS\J*Bb#hk (>9d; ٙW^i=xP>o3j_ C&5"Hz{>Zf\NJ? GNDCekZ%9Sm]f9@O>H!"$ۘx/)-JIR.L7oݽ^׏V6}g@>`\!$$o'%~O;(PNDV+SI"B~X=w9Sit<&wtdO%ݵr;?skjô fN$FpBBHö=G[* tT񐞜.\V|h;|ҧ۷GtPxwS_Ph7Ze$F&@><[}>A=x &J) SE^`tQD}R/ w\폟g;r a۲6SLOޟ@oDyw tz:" kǂmb˴H_A}7kv lrnlF"kؙT{7>H:h]S>1RDT(vZíIv<!m݆4aZRU%b wYA;W{=FiM=ڰ|ΐMsrqC}]D C _|Zr|~ynj 2(Ї@y߈읡;Ey(@a@5y0=OnQB|5pe|:B4Sd=)*${"/o&}߷^|j+iNCk>qsr!~͊֏q I|`31_5!)jmOSr&"W#8nܤRy7~co(/Ӧ4oН?AEܖk-qr molݙ8;6s;s/o63~EHo ^mO^0Uv|YvͿ7FHDI$~{(Ep?g#ֻ#Gpmv8HLI%Or fibd6~$4u #EJ!U !+?a=f`v؆fBo,_X+ޥpuxhM!/1Ɖ@uŋɸYY(RnD Hw݁=D {|]8HNh٨Gc!!vT*yO!xm[OL5;k"GxЩ<F "]&v~o 7zdk# +4&J8 @;źd2C(!x-JP'RW2FcHDHWPlO=H% 8_F'̆9G0 BA!%~}tCix%\ Hp8իN{Ǟt6 ܄uѽv#*@"F+y AAl@wù4T~Hވ r}*o8;,wQ({ uz/)M;a /d]%߯H¬`uZF0"!FaY<< zv% pD"53tȂH p$C|d~c!ޓI#<8BCR4\PxU6mņZh h9%)B$Is M C~~ ӯB%HDxǖ P ( 648ЍE\?D-cYd}_çT5{Zp$Y-t@¾ɕ{xyIQE[;L 5µR9*@wQ櫅J`{9XLJ@!jP!F1͋I#b'P*;.hcP?w6 z,'å'RQNHvwx"T&NCʓˠȱ.\&&=ĔNyuz}NnWlD$O,ΣCEOG?-W'O䥟4ET >)JpNagd:r k&&qn8P5Er@,P2ޝK( ;|YfHo@Z`lfk)6D_9VCsehkXp֣4@e#> 8IwJ%)t-3"d ^5NdA hɺ$`X+憨$4EC uv!a8Xjȁ QR!@Fbz3^ ?=R:C!Q #/*lN06Ȉ 6-?_8p{rm_C80P">#h4NssQGv&֢zy>*Po!|eXQDsoX ƿ*$~w᫄x|4#X0?L:^uOr`E\zʆغՆ\v#5.Ps] qRHN4݆V aBr|rOM-&#*_ubғ]aY4LmK;⋡>xN֦1M5챇gUY1\!qVAkAЁ!dOVm;5b3D3+qu"/|H;v\4v_nDHƴ++C1e$lt{߾$7}jand2?5@2Lv$uXXIʥِk7 ]r !ŦCB(!` žHi6(!BwpFtŬ^mh( 7PZYf #[9lZ-$io (@@KXtwq*1DMF{a' D8n q4pOZ#r 21D4oD3~Xdh öE)9pu}@6|Fot|uqq"(bsLbx a􌏀5d \+eD@I.oW 4bAzgE' )$rs/GlW& xâ/ !ƣ7HOy`쯐ߋĄ'NGru"=Mgn~!$ L )ގP=ۉ8p=1%4 2 P0v9(;1(7dE]5R8h?b(P ړp8UjgVL|[0:G7D١:{/oO'1 wNw:_EBpABE#~VM!~?l4⟤]EL+ f U*zc2yY4-"iX&4amYuw2=Xv{茠$ZXdOw)^icB 6Vy ]$OMS)a6@Jh/~0 ؛Y*29ov}l5A7QDU#DCzR_5~Nbh$vקnG0p0x~?:_9C]z_u#F:k9Voke8 gn4,Ä$e6l">x<!^O=% ʙI$iJMT4xWN- l ! #}:?٘ a]'?Q_O` G0 AEfIhPhkmߵomCwϚ>Gj?vJdl@g)eؒB@aY҉Vob6wiB08 <䯹_u?1~+HB%? 6ˆ d?Ұl1EWZC +sVnHPr^0=Bήq_S/7҇qBxY.\Ό7̘i ?s@ )YIxwPG0ԗ(#~<;֜A9w$]\D`>ɡ ӂB*R}M#ޫ4 RXc@PZ&ɩE$ɪ aH߽+ٰHlT>A1ȡ1AGQ8;ƅ@/Acj3> ,"RD|jeÔ;G/rrA69Q{a#ҚyAY9;H@acRB B%;7FJ&ű'@x] ֕G&!'[^4(1l%XW-u!Vgi[3ǥ0YRPW Tٙ(ۛEvqʩ 2 M ہZw$nJRڔanLEB_Ϳw|ɴVS-n`J$Xm$={4t.~M,vIt 1/*{h_4yN2&ڻ/p<"0oV_Uj'4I$g!x !*I; !< pBr")~(~WjH$q7at|4F.U6RXdb0 @O+7'-D$$M2@s! N9: DIbQ) (g 2C QS{}zSe=c$ @?zː#V: )@95%4HU]*늒4G[UR1 #ᘱ02vg ޭmZANY#&X AJ,cj9$O|$97ur6$暈#a~:|1Kwt"d #7A.<Ql>s[y9ڜ_S}햩 V0-D? !`@*MaV(5L$:@Urs< {1(#ґv@ n%"ƂĉڅCN)$ABAnI"B!*v MА'T˳hu8Agx`xomTvI>z$0^~Eu? HnXkLBw]bR&XVl( MDԦ'ri])Dri(|Nw|z#iG^s"RlH6mk:D I%#wsʼ3OZ<(ӻ = ۢ7GaLj&a$$$Dbr|}qp !z >]Һuɷwu)e>k=KzYdNd*2=Dd#m;vО H'ڜ;,S쇅'@mZ&`L]]zY 7 HphfLdd⾥w85}9ņOH/YC#!ˎ 7 oH84k-΄HERIԎἳzð=܈'Y :&C!EJR,$j1R}ݎ̜e)۫Ks fM'jJAPSno{oLw$b G!B&p;~mwFW881c$)dipp_0!0w, O0=Txl BCS k`5dA m-F-c捇23VI~5T{k:k~vzX',39F_5B>V J0Nn ?O bD`qB=/I{tCP ƚ&ontw=`GO20H1;1WQ^'@d)W8R x(^mCƌQ+:_p"1nC}!"f-0WRaXr=MlAwajWv߱8WēS||-UU 3K VKDܭ Ү7ٲXUӻY!b7hx/r@fuJR *pNHle;g,/iYH'YoNWT&`KwSO/2G9\Mw?=LB'T5X"ޠ(Ʉ`vsm066P@dKSeQ 3ǡuj֋y~UN5"m4<˼1 ¬"q*j\,aU6hXU4tQSv ϼ~~ HwF7.~k/B"!@4ECJ·#D(%M)?j+{|ݟ]UO×[Nmm],Nw۠7h!Y*Ґ4[Vm4DEEGsPN4f(CV$a:2PNxd[ 퉣'Ga)"r(nF35ZBjJ ]hv-5 4lF**naXT33';*!&†S }'5%/#1zxށNdCٌAZ^@@b:6cAW=ue cYq(eCb/~u m아6'rmv ))PQaU}D9@v2 J7 eC!Dt?8IFHn^#q=*<: [E e1bH@8y8zL;՜''3wDځ0*g!Ki/SdxS~,S$Г7, x{ع۲ "<پ mi쨇hEï(u8MYZXs_)qOUEMRHGchb&NiAw}Ҍ_)^Y؀EZH iL tW.<ШBϐX] ČS=& &'7z yוc@#P;vJ]}!āvK`UvD([]su_!CbsWCfaF6`W"}{Vw͔$9jrU:.|azT=wǿeGQ, &bZ7jIĊQRA'ǰ,59s8Fd$2WzIu3uo=DGUu@iك$gFqc~Nt `8l?OI n , " HF$HD͌-WV RD6G?@hhp|eK7.o>|Y{yM}p 2Hr6:HҘn#Fl&x@,s{|mRܘno^}|ocûe'P)T  R,m2U&kmکY Rn h4m 1[`*+ARP[j #T* Q (t% @TAJmdQBԍj#vKCmT`AI*)FT$H RQJ*#3Z@*϶5=ݥ*7O;ޤc5˹K9tN-;ǎ}ZC-)+ 7zO^֦<]CtF爼s$;^b_{OR}Og0-{|T"ٶb CӴEZ޼xO1Kvs&(%w;bT ۆ# X v['vhon_|wj L{V[04l4:3(¼)%NRPCm[(j͗\06IW0zkmhp1DiUrjsy(Ww`e^mZdSNENέPVZ }]$8HZrFΚHCRi}mϛ T*)"*SC7l:@VЮ`@z-ҝ;@K%篅{t>}qrg[˻oG.y@O  E*+c_dK7k> 1Hvjhү>nN}};q `ޒzM@TUTmepZxjрT4oo0(|Bޱ *TmBAڬpu*ʃ#Q . J4R, Wּ|yoǻt}/q]Qtwo}=vrs z}6_[#2vm(c9iʮeg3;vRY+\I9NEًjs]cwuc![wwWͦ8]cwGsS0;bRI㤕Ep*[.ÜIw\#ܑG ꨗ9r{rKInYJwcnlb7w)wnV㺔1;q4s -”0;u"\XP]ˇ!n9҇qwRt8M:i 3Vج6evÇw Að7Ä8l.\m8v 7`jj0]L[!cŋqr\F3ӽ@\#O=ZQh. \rfޞmi;α7gu`l+zc`œ]֠3`v`жv5 `m6@wNت $#- Y* Z wm.fn3ʔVc8{ 'KzQx҄UM0C@`&L` 4a 0L2&"M L 4@ё`D@ 4LLL`LLi &&i6L&#&L244dSd4L0M14a0) "2b40F&22444Ab42?A CA# ?OP*H44GA=L4ɑ=lƅM=5OjOMLLF)ei<)h)xddmMOA6IhEE(6(Uڈ6F9yj3,YrbR̸4u/IUQ@2('\'93\cˁpC-^F(B!+Y+JbPS@&:9 GFLZ ?Q%n=Qne$&R.32lgK=^V!m;\F.~ͲZA&zqh($*@PQ.BX"0#L:쮗ICuYϨ쉗1f)a('f0+)Jxe^S2ӄ||Rv!!Ye+v寱6*m|*TQ"ފPC ZeGEoZèQ$)Zy BE*0ԪUZ!84$DR0Oy_? sQ>9odK\3k;P:'و"H$"%i!BGPʤBb"bx蒃EU?* >tIGaQL NPPERJ\R x eaeثufcdDkS%.suM\1񻾯+]~XC{l:a\aޜ= {FtqxW p >sŷ Mc( uJ(j' @5 EHb-rsl:X{HyNiȍ@$>EH|+*>J S)@D A@1;rʾ="e0 P\ bATXشJݭkj;-4l85,ƩՖJPsa5`x8+[`aZUD@0]m0E;jҪ Ea0z !66c+= f٫_0TNLYIK.h:SX(2D#FQS?4M 0OUy =Ҕ_Y;wxw(2?ۿik.ƞ:*߱=o>9w4œ6}V{w +kNBI޿GwެU߷}=waEQP9eWxIGGcUOn2h) 4a'),e(I$a+U1xY3PA1eh3NbJ%YVPfl¯_,mUFXY+p>ʈ QJHC\$˄h7mB"N-pF/lF@2Q92VUfx,Ix8s+LV* \3D&s,gc21x%Ie]qyGQL&kϽeMmrZ;P$V%[b.AK(h0Earۇfdd?1Yw;ֶ; sw'W};p3/}`rWpm6_~:ܤΧ~ B>1NMX/`j Ć&3J0sܫ߷>*wA\l@@l==|ſsC"M: $08ÿoC߽^߶nwMv;gާ:p`p~/k"aw9a1wP!@(6,w1Ɣi* (wO"?%؆DCܧʘWKn}]Oc\@Oeup;Ŕ(~1`-ljF's{,T Czj ~?1 RTL6+D0c%2Z(1U'Kr ؁(K)e@IT' I) In씱k& jXȁvRي+g.jʛJWwR[$WB2?{+W1ST0mjXo_^1?Olóx粷0߭o  -=ý {m{_O XY^gq8m1=->Wfw( 8ߕe`2dFH,=K.9@hԹʆP4XZ xPO߷Wkџdy=OA<55ꤼo8DSƘ ڎq, ҨSGۃ>"P/$A.Ĕ} XhKh*'夽'"HHOؓ,?;n:`?zl:D);D/i#}._tHUKbqf-90bc*|?%/SoF(+]pk %Orr)s]6{l賙OrUDGW3 _5R>e[.4`gц ,bg! 1x8ЍHl6C a|ڏ#!. {.rc^aTtAPT(uV,TA C,UM僟MUd߷cli%U -D!Ki*5N!*›c<!C0feVS&Ћ՝ࠒXhhBĪ )/+i;3Z20J,T DDnڊ#XV%7(n πi1M YYrePZ^iA2Ř,kR"** chj( T 49|gy9|> 2ЧP~>iUm,qy$K=яi/ xοzd\~n p81t nHލL`+ςs6OʰNѥYRcP#W@#r PeyETú+K#ќ/g}EOݏ~ rRh=AdLq|ҞHv6Hz&]˟o.v\ЂmL_/*3")&c mF?R:?3 Z=7~a:^b'`L9b <pHUVɪ X]V?Or,<.ר;#V,q#nɰzy]/ tANyDVI}l$63~ljq\xlLa4HTN=2@0D@#aЖ'ۿ^wh.MU3Q(Ai(Wz)*Pj}-()ĕFf LPTSAJZZ&cXQUsBuΙTxDPkJy;#]aCZЀͲ/#mli_zM|9;$*^AU]">k򟓇x q;82`r_X۷u%Ts1q0[XODo%2x ?Ux _ I9׭0Iy9m K^ @n0zMF2f@4|,K8!k e)]y{%{ʀZ~u^A0uʏtn=sħ`D4'5Z̪%6lػY ^@u?E[GxzQ֚niƀ:s[9" dD;F"-sT U{܆)LJt1WuiÚg%|Vb#PzC՝7O?vs_A*wɽ]Z) ""I yxZrY)KYAvE,Qye Rz:/x7'"]h?C5\C{ MC"& \(w5qٖ"1}{|SQߖ*'.=`4 85N9b52I.;21,<[?뚄)X} Ntba|6kAm"v~; ?Hr O7$w֙2LGDO&|}h R}.`Wi4b-fOnj:bgrFCMu^l>еD8sfmEwp[8M n|INYQQsějʅ8Dwj+Hϣzi2ä3"UHd ƙlj}4y}Eng!ƴeOYuaóf@,sHIͰENna`QՍ'D?/w8m }QD陗$˓Ҹ7-`'>\cu4dHZ`*:FcK;͜+U8: ~C1:70n/Y n^CLG4]Jl[2AWT0-7_AF`RpJqe\<j n({x4w#'$`j5]mz,hg*uxtX: ",WR1f Am pB즔CxAq*{ p):-@BῩ ڧ8/b /Eø 8Adۍ>\'ݸ "A,,?++2=s#r*=ωo Q0[ڒ%w-J0 xqޏ%+W?REx]IS|dboDOB? fVtM y?f}i;9F)}S^cH@sw9|acl 3H(g>:0E!8|^Hϩ>~ip-vav2jq)ۃ~QrtYRq>2y1-3 JKC}_ԅl u^WvlqlW4`!6i'}RhJUҙ0wT%.`"CNzX@-(?_ԍkm.h`$ qSR`Up9K]=G4ʹX 4S1 ~ք<~xpuewdvq ծ2wNj7eyDȣlj!gĶb^O] 65ɐ'OY~#VapVkF ㈛c5tpZ/-TH^|,*[]1>۪t?,_|LpѰgO3\Dc\rXxNSpmV[2ʹ͔ xAݍF 2ZJr!5MBA`oʀ$1yvkjK79^JӦJEUr mx5?.bs.xO~s]}b{:OF4R:| >#PRz=9 vJ!6?&i46lD vڲAS Sh@WH2-+ dHfFt 4I $˃6ߵjhpv\Ac`-~Qt`zj7$WE&hEO}pDR VΎg3e_7.szvZnE r2Q:qcRw?/S3rUwlfV/yo7՝]Vh3&~QۜNv/xCV0)U( @0ḷg%Z^;Y -^êm'%o|g_g;D&H?[ 3\ZEU/R:km:?v@$DX` T#~^SK]yG{kvQ\#1%n15&"QfsΓ*`&RBS}*]Nkw|o4ncX`C&rhD6 k~ȑtlziZ5lkmN=R?w w^`C:uA4rD~&y{*ނϖGC}7ձ~-:[CNtb7)(l0߈QVf`e#aM~XZ! &)ҷRC w$sj0?tk71)Qx ,t_C|ưj3t$j!t07\/ܑDr +suBZRl\ z_j߭vӺ < P݌*υĨ5qV1Ie) uQ뮌o|.X:] ʆȏTמ;|,mN s.}_p" t~2Dk>~[zȓcKkW=!H1qn(ɠrj>j4uX k@e7Ơ}^OFA2Ϫ >Ƴ3d!$&yaXRF~wz%x:.޾,3|гO{ fӛO k}m.N wLEK~@ GPC]M{.Y.a|s p`I>@z;afriNXG@JO=VENU2KegY8Z?>C1f>/P_o ZSS\>=[ygIE3"K D_e u')&hJ{ 1Qjj.yDD@eXd1 #p(hxF+>K!t噙0fdd`TOԇhm0\%$T_LЯPLhpHyRfDťir5ZW6fI$I&I$I$I$mQ$H$I$I$I$I!$I$I$I $I$I$I$I!Ng}r?7Au{wЄc FW9atxWw*ј44t۟@u@~e0 J*BzTGTm7?aTA5XT%z0DR*TEI%J%iR؁bBCFS% QUXZicH!!$EHI0B$uT;0Ʉd P"*B$X#d#*H*ȁbF2c!$1` 1V0` !Bbd "I IE2Qa@Q"I!$RRB!Q0#i-AP#3YXeg"jhmH({t`d@bV.JQ„ +:;* P333)֢_&嵿ߏg:DйdRQUgeȡdt!4e;5HH$ 2~*`]j lEWk &~ϓu &ѺԢo(YWT)@vG얤C:;v[[^ղ9!ב;0H 8 Y'Ӑ3s]5!$QKM&j DL{6@!sv,I`]v֡@-۷CLM:42$ȩb($?бR%1*I$xEL 68Wb#6eQمpCW? q|, ͘ffmkU;- (z U c9g+{n;w㧸GgZJ֡ $Pcqؕ@Z$<}#)aI:S) "BU\K I‹%8!C# orX€Fc$"!”$THP#xxxwGM y|EWREE86Ԟ W*uP$݌#$A"@5dB I!I@!SgFá #_`-xjT@a $(q Xl߃ԣj왲ʐ(3f};XTL jZ15b h&0IYP )i Vь0Yи1f , iQS4r73MUTDBAo  @HI$!#  ނ (V1Hx "eAFH ӹ_ Z;:DUA U!@!FdI$  !EX0dDI$$@IX@I@c "DPDTbE(HUf<#lk݉Ƴv.gd tXwj!-,*wIECrwh0i I$I! 6ȣ Ilin1XKQ$[T5jTZ dRYHtD5YR5)*4RP-`@!zKg:BIjBDD @9 HJI(RFrK&9 eɉ{73Z2 Y621Esf-ј,q @0r!M%IHDKE*HLQ W 521GRj1ֶC[WT!\[Rܤ^]ZњUUt(TQZ҉U(H(QD(S](XĥRRn`ue ci TR Ŋ&)Qpa0QdQ jYAF]qvk&S]fR[ܸH02gcG&8d%K,d Pb0n8Y0:8ຘ(SxJ/!f ϥ4b?~s%f@lc{ت+iBBIhThdVT6#K0SrZWh"[4 ILaa8E5qPpXn\jҖY%&5cԔ$kA۠s e8{{i$Ze6FͲ-@L@6`d0tølC>*ff ʌK^qe5"A4$ AD+!T($q @i(PfMX= j3Ϟ*J k^ةPpjhMY"5Yq[fг&֬!͒\Ν7+ XdްPblkO'QΓ%6ic7 K;}VB"2ԁDRAB|0oԎNoQ@6)vpF"1AD$jٽt _!Tkz+QG6/×ǿ_f-/޿O?U\6h}Rg1ɇ>d{Hsl&sc07<-ĉĬ3^:F4_t{eqoQll.,,8AbF _,c JbʌôV7 _:0Ȝ $C29\ D+w\;_k֚@´Jj(3ij0 ISԽVcEPhk2UptܠIB ͊ 3m,h@?3WV' y,{U{\ĄX)C(s2/:u@ȕ-`_]JFnvU :A$dJTMżj ұAd8:,`3 Ka/_F>qs7Rv +We]o?٬ÃB%YZƝ,.h# O̐`Bv8.D15.y47oCĪ՗}[0-{ R* jW cZF~؛1, v=cBkoΛ̻)Ə@Џŵ ́<5<I>VZXѧ;"U!;NzdSv&Nu%?ƢjPPDUn7'ϪjIJ$dJRV8a-!\[|r}^wл6p oR嵀oMӲ ͌zj'^N{l! U͙s5Mפz"'br/|ЂǴD7Jj.|Ϋ>Cⶁ)ʲaC/Ehm)$@A5ymm|Lk./9IEK׮V6Nwe~l wLsoT  &GKZ7r/flf!*V_Tm|@N{*6B:ğ?:^XٷcFe˅Fӽ-)k4C]"!A?KR${۞ӡ/nl]JN > @a?DD4*~0o \>nY䈁`nQ82n*+䅣䊚 `1dcHV-d%7_?[V٧BXK^}+d'f,6ɱt9'BeXԲ֐ /ܸKӴmIZ=dxVbyHm ėQ񬵞b쀊p?9{_r2ad UiuBaE`Z0 /i1Bf>` U<$r{2?'َ-ىł)bB!-.BAKk%ݛ:?Ǿ_7 }ff5KUI؟T+tySUdWQЀwe5ruH~n~qf4ty˹cj"*A8ٸ$u݃-AC0$_@Hݔ2g5Uv3>t* kvQpg/2ּ_aqVx*rydf"cKBL˺ip7y\I&pcXK#< N],qEZbYBB= M &Jl0K4cbxmE0Rn r∹&Zyc.o.lKL Ss>B9qt6zʞmv\-ռ"8H cz&%"Ie=XHmy"ޅ;z8&,ˇl my;u Qy7W8HX :v, f _7yw ~7ՍŷA7^Kra]cMkiT>ݎdJ3c"NNkc$g Tt<5ɪd`~^ mM:AY!(Sgy=񖡕#KOM35ް`GZ9E R&OL) 2j~WL*CsX|^{,B|>oӪW=a &`T]ɽGiFnᩋT}B{^H@}_-FH6=+W#muH|~w JS`~}(F)FJRi瑀? ֯~2r?B[p+\#O!_an-_l1.bp,ϧU+ rR[ozMR j͚F!| ;N3U㊤.ֱTv*A [H?ynq$XИX`:T:E!eZcg s`u즫3lD"/5 |g> Q4H5'"-UEzP0Sx^gRM`W2mzƲnVm.% S nv=8* 1l~hˀJM~=EC`#MM՚~pvmwZl0\KW->o0fwU|zDˊjRC훔ngO0lOMCn1#k->a3ݯ>=tF5h݄WQN[/oWc4OW"ձo4{!>oG9䡲@>q(AÚvGio,3!^j2D#E7OC-tjC|r3@['Ш !I[ 2牆(=?ܜpq_xXvd.tzQV; e+ΫwX1f ؘ?RH)̄m)4*}^~ K-*mu(>M5pvCW3xs|#;8 ] I[$"?Vp)l#~ S$"v_ϼI1ᐃރ5Ͷ7XƄgq:m#lo+].P/`^ e[-)@uigj͐"~ $/*jx} L2Կ&Qeog:GwOÿxQUL¦chI$G/"FfR+ʙW5|g/;M:D^`01o&ꆿKFE4[9(cpctw{$L[8s;8(⨺/rgگ%]iG?0l[ϒ /@d4>r\l{Y V3 353NdaD vf۝U?dP #z?è;H5 n$J|UI7jUXo Ҭ:R#"&o&Z- gQ|T;f˥s Cy56!x澡'O^=9y(1T[]TJ=cQ4W-*o֥7k t.8z jU/|ӶiYp [5n40mp*bʸS]YxhYkU3?gإ84 &]YhҚQnw%@PMxB qWve9"R5[\7|6йg1K6 ˤsZ'/~ WZ|!.4tTXHpDO& l+^ 8}5n'dҍBalPwR_;e#L7IAij P#T, AVW,|5v&*"<>Dé~^lLf fkeJpoU_#Ivg>~%ou~^̊іEYJ?_cPٵgfISݝR7x@;BH@qt8·[|'-ֲ! {?Ι %7rTp\mh((h Ui]hAfD fR@J睁_م]=zaS1tC&[)̍ S*Us:rK 6jOyf .zkm_zLӑ$fA8:+ߨl6zb!du2d:`f SE.,7dY *..X jk C g"AVijأx!idVLI>:$B8reH۩$6]S4 +9\cߌug}Tl-9"^r3W}]ywLJVN*P>~Sgfm>|vo$Q)?O!xKtNW~ *l>J>.1 &fSCq:i/|Iw{+de&K0]Gm<f.^Ȓ4\玊%q0Ml2Ξfρ-а3Q"sƣ2}Ŧ.2mQyѲP[K!٪A$#(bU\֩:@ìgn|`w(&eξKxJv7gyKG52#`Bx2Ut"u3#ǀ~B*if[X4LM0%q8_c$_⟞xI;-,;'~7TAڒ$hC3e_hݱ*e,x:ՓG)^,)ϾQpUQ],2# .x7?rU@t\x 2T"ΙdᒙBbZ&HxlM@3\rxHU+6\# R+:,V_>6s7`KJn=' Hqpg_fmϾbJPUђbDc]n!)S>FD'G&4X6v-:Js/Ԭ~側|kE)֥eWǯi`,Nm1czLVm>/Zc\)GĒm}xr_{[/-Jm!q2NtrnvD @XNl_=%t՗Fn7M~nvL+/qJ Z]y1(/G^G<,߀Fu9f^m*Ci9Ji={!Tv8KQUlx'zJiS0HlEmH]m r9Wu*ɫ iA|! {MdulηR4@ft&/AļqlPn0{:`+#|@"7I|[c%gVǹZΪC^tG [GBU Q* ]_Hֳ-D{KӤh0494Ů3 rGh{E6Hk< [:pR)WI'Zԏ%AvnHa3Rh濿*}P_-33A_g\IR(WBQEhO?؈i %e"A!TL0l'O1wU!+'UMNl݄w{7?{_Mx?vRTJ P.  [)Ѫ:*/0V´?BE=g6 Z?U,,,, f nω~׫!W L#IPc3+1 /-1w]IL!*E`53FS٤3P.P=D 0}/^7gf[͋-Ջƛ2;6UVsR/_-F*ۜn$Ɔg!dk% .*8kz4.Im2οoc7dY[ǵ3f^n`̇A,:|]mWzrUӣI 8QcW~q86sKW˷5N-0BҨ^@>rzNTO{jXލEoE ET0n@S*C~gz۰ID1B~mY$}s.2xH~(%s[1? R7A16eIpwQlGL\M\R6h(ΗOk*INS6M=gLgK|-ӁMn?Z*rAb wE]xDUv5X7H J6m>}jڨ*O.T:xq4n/)?lFE VQCv+]h@kʌ,|i@Aʯ:!h"l>clnUv/ NW:Z4eA|֤䢯4a֗|zYs* y.(6Lf`[MY|&b0Npѹ~ I5~<ĩev-60p_v) iAn뫗>=eYm) G<֢d̫a1‚T,֐X(|]nTt#rhhJ"?t^w?pD3h%^#`S4R V0c:踠[C\yq8ZhX ˣ?̓nl$gЃxL$\p{1dV0~V.fr~x*^.6~o},Ҿ-pwT?X:\Cq'gu+G}қSّG y`Q ?ٯyPWfk&)=>toMBߟ_מLgxǓ验1ZN{[Z}YkHy6'g*0=1rhx+*ZMvP>ϑO :!PN֒5;p^ 7>nm4Lm+CtOlƈ򣫹qب1_B &wMk椺 9#>0| aܑf 8%Gf;]X La[ j;}](Mɒޤ֘,}Ւ"OLU]n_D{(^=]kgEyx,_ȱzq4v1ѺjU~ڸ3!':ѡ}7pc*B u4 EߓZVN {(Y&)c.#Hԩ)"-4!ߕrVZ)u~,r.8ډ,Їs)mS_ԉtH[lPE~J\k:Qt4]i:P&YR_ɶ^3RGցPVy%Q02Ǵ #q8p*|TKz͔0\+ =PeT9U Q];Q'_&=p濡¦$(EI!~uD DQijutͺ`#U?TYu򘳮_&p?y:-m2@3 Z2K!G:oL.gocM }6BC-U MʣPCA m :&\JL--Șaydn%/ez$ ``kIrtHgr2{1)R/W[JA5e=zWڮKc_է߷eh}yJ#?X1 Cd}$ #ZǡhC$ B:T?WB `*潮 ,KMU (櫤@'/S;اyk-APzo*D[۶)նn&"t:;@ _!YF/T5> %ASnc@*'wTE8'N @@s ~-h>*ESyUz k H!A$( P, h %m*EU/oԮO':Bm"OG} ,s%?y"FI# 6…͂$ @$ DM6B-@EHcPh"B_Ϧ$-%4(cS`(d uշ>.Wdm*hEHI(BLO_rvc9z U>&ZL$ tf[\]04_ ꪤI"W~}M1$=9 ̳<***T(P4=+U@ uC-Fѫc^_q 6wq\6B (6.:!"MKKG,l N,.]K3;*;:6Weg{bN&.$s|8g pMHܸB.vglP g Ԯ%](VFH]la* 4wEqa!% BZՁ`*T D &+8iދ0\JH>&|VM#A?w]D@uG/ d6JDTUHSU%:hN#¹lSɴwݻ =qj~\^N'(t--͔GrKȯ!ksg#Z1ֿvx8ʆ{йzߑk8.mV !7#liM-C׊EdI&lou&!NLE){6DTi n/6Hسl3io{h/_Jbhi3f\ WtΔ9`c8Df2m9n:RE(y'tק;>O Hhq ^¬,8<T/9b:tdGQCͷ &φ8Bt&GLIk`` 0<&%#n }M:uQ,ZgJLa9'+vS|_FqvzHmxXWVtO؏# H[r8ŋ](vNkfD-Ƣt! H3n55MaCJ@^1.Vt;Gx5O:P1PRA$bD玺bb5L`UM2Q絉mUX vEeR` d-/~kM#yrhAeSCV-.c=D ;@)@h^=9ڠrLɘCFƩ܁U B,@ 12͔kXNnYɍI8x%{DŽfqb' RgErNbR)SUsi)Vg53,6M94qobwR[g M#ӂT:D`$ DI TI:,{,$1 .ɪ:V@u^!/3BUU֠XUU-J ('Ǔ+NM@/fcy)} DH$T 4pP(zCuTQ*ַKZklFMtJB@[XT⡀(Q|6ÒsU ]EnW jZ#BVPˋs-QjYD(%u0 %ќrTrY B- s)H4=ܚtlFɧhK@! P>u/!JjKpIF9ƵWw?c((/HHveˢ E"alQ`TME0b HN !v@@B6rŕǔ֍U%P&.qq1Q DCalfPvN 4K+YG *EHx[q6ģNM g+"ah:T8D=^{~fx5=4=-& a01`3aTM܂X?>X΋cxY[\cnHcxbJYhIR!BP4…(m@!.˺݊(F "2 1E(SP $"p H TT:|ONDMn7BH ĐNp:)ĸg %,('+5gY9bl<ïƝQ1XFnqg<<& 6u6y/'Iu)v}/v-b$% 7(~M n/0VJD[:j`wJu/A "!Gqj'xϛNz'3nid7=fq_g9dx 0t8m赺mDt`jVz1ROfdؓb*nw^7!ȻvH(驋N4C4̜SsZCrߙjkkXC`RHK؊G+j(rA.TjO+;#t;H֬Aq"x @BDaY  QDb`ݗ/=pj$-Շl7rI7L6VQC/s;~D*ę<2f 索 ぺe0j Q@Z)=F;[>Eȓ!k" X7ꚝ;jNл'i'D)P*((jxS:JqWKEM-UUjK(ЩDJhu9I`4U%h((B(jj) 0wN`d'188 [\f|Xc_@-۳N0.bcipusRjCUCk/ 6ωevGOqsI6ih>G;qFIPAcצ3lEȝ>[:A Su$i 0EqeNpsGpSG`LMHHHUn'8dT?=mGp8CTW& A:(T2E$j O~<تU)8D)!ϫ Rt["U(+"F0z]5j&`21Z2u\^&)!4iԋed,rxRRCE10/[k}9 &3pYt.\ pem.`W UQ6)E7V*m5mNLwqt=u 5l BI/jU k]El]:X"6GNY[ȁz ?/iD iɂ8Ӈ]Lq$Dl [żfffm@*02`E)`  7"p5ɼZ1; *uGr22"8s ew%B@A7dԙ[gщôAM3nS2$;9S:-  9f0flq!)(5Q5GJ0,0T8eV}]iˆ H4Wxbh\d k Jče\EZ6 1pM-l񌲚\u苻&,ZK ͍ZKaFKB`h͐L^w<i, -_Ljp 3ͳs̡lIg d2ek1PavuGp0^IL)mŋ6ɞ™x hZk4Y[LFN4ߎn'eYe[eEgtQ$`Z5m͆ f/KpNU(_QCkL2 #[ҔLVdVVk(TN=g/Vx$)}}K,[+cr{`튨L2R[w=KC_uX*@!bKi42H-m/T3D VH:Un^,&}蝎\ݯ\zgQ5pg8\ 73vwg%7chJuL4(fHF3T3ezԘla:Tv6CJ2I7NJe-aPjh#IIImI[7n(2T,ѥZ4nt0JkfQLaJ η_HgMj2&hX+|gڿB5N:ka59tlrqgvLf$`BN2a{Ḫy#ok[\R<j^Xfí0 RڒVifӶpUoH\:x]ٗ}x2FVRqr]չ)*nw%FR, be i+"H.${V#6BSFGmEpۭ$4 CF,H)Wl-KWg:77 jgʤ0ՊYMYvGcfwY[$c5LJL|MJ]jA$鵹7:juA+ 8#:u!-o.p1َPĥ9j^l Ȗ(6ɐWOIVZ c)E#s8[@e>$xMm }|#' 2i5j-'.Zyi&;nl_E~Wn:{ VcHt"ۢV6XP"j7&W.c4٭(ܳ{Wٓtorp,kъc1IP[wepd&Y(poW.u\erŵ Њ DȤdlpI?K3`ޥczdь`b`"L8; ɤTcvؐg2" !1#IHD#1/=nxpJ 1*2X%5YUj 40%֪L!B8T_4"z :cD,ϙj& b5"¹*X.@ZeQhes鉪Nkl3f0הcə#/4A I lq4f0iW1ذNXKN18uv?~1kZ#o1wig"v2=Xqbkl5n!b&ɽ$_S0^{T/LS:Tn݅D"1YE l/3x|lM0WJWQ$Ja5(0C޵fJylc~֦Jk!3b`:qNډ0ln-0^u%I2d_ehˤ dӫ24m47![87Kn]B dp5X؜b {مO(gwF%pU@@@riڶ‚6ZrF28άK9[gITNLpM\"kaUn ,8722iaP*V"eeTRd`(EmTTUDSV )aWˎޛa1\;t vP!̛yfq@uZ=Yk|)WmRM*-VeBPXV6#``8զi/%{\SY8PgJ襑RWD3M9L!E5ia؝kT^-$Y )ȱ[d _P *e`U"o'a|juwFy)qrqgxgi+ңQkoÊ" =oٶ[&zv-q͈YSy%+̆9AUjtt e(395h+%ӶqĵRڄ/ ;]d!! U %Z[INEmNI{Iɶ 6l*IӨaPeKوC-g 0PO:8b({i [1aI^ŴI\y-U3څIM5.nPc* h+ @dVE1xfg B֠!,# E@,DD$B0HR I#Q REJ%DwCI 2e,") ~۱ q G2=vF`yw;mavp(&F.+`S&&DHl& 4{+\CC~2#X.;/qbS,Ofq9 d{L=yvaR TBqj MƵe5apy?K<$ YMQ?/$4=jU'ubҳDBDb+R\XDE}O+2mW+{((ĉRgmKQZ}\/XǑ9;~bS@LzYf#F^,H4Av+%ZQ6?{UuIaBX{6֜>.*VrDCN_nDF ua?b5?6_ zKw\5rOk9#/ GvS #ݤ2%w?qjO@Q@QࠧA#oGo3-<:Ӆ3]].+i Q~vcj(9 ZC0U$? wHq4Ar9xrQ>;8? 7g/ ft(Ŕږ /[GXW> dQ5t򒜳XVɝ irJ xO S7nDyshR(ۈE/ĵ`'c\58߹D?Se6j!3CQ)2zy<\sDLYr䡼y[6hβʼn#G1]o{5亩PlijeV/9 |hPX͗Q%OEdKdc w#3pA2%xB@:v f vG2*sEa,bTkWVP5fI1*r@P"ކ6$Q\~PyuQ{QuLQ 8䎳ȁk}N n]^D"A [ ţ)z5<)Ԝ ÷3 딧)qG!9q@ࣶ.,Su1"2j DrݯhuO^#TU:4zg+HIhA}ŵ^;L> =)S½pZ?nN dl"PTc.Xm?pu-=x&"\}&d!P/<n@DŸ˼AX,#3S[#<&b,a80Ct3vi2THj6Vhas1EfpY5[|dK+غS^ڭf,]~nF#āVǽ%ILV.ڢ&Q}oq*v 70}!fÞGyN5z4S9ʺXk x(t^;I; U "S3Xj{ZZ}nMz'gzp  y8tBsp.sxC%٘T+!C?jq`πh5tJeu9}^CkEB"(%rI# @)$'k 㮔g^)Q P'&&5YGmL8X]ӋԨA` `P $yt_gmb|b^ PĂphr4ONh̔b.& v<];Me>.Ѫ}*,;an>j=B3>9 { |OPu}u9fޥ#-Kk |Ң46x_93zpH_s;L;=qf9~~grzqbUZL,3Ue=kC>aNkIK0B͍5`.Cۿˋ :c)\@NFj 1n%p#2S ^SR|fBm`:;7Lڗҳq;dZdӻiIZQ"( T#Ȧ!M̶%1#3s!m~FGS6,3.p![er.F5՘ț1b/]n:zamBa6g{)Du;ϐym!HߓOŶl>V>M\N? 3Rgnzө=>x^E~(Ue[rZJ 6 2q O,14,p+@g$ ;*`dQ=E$Ҹ\BvV%:[QR|r ۂ$3b8ܢIFoe 2qiOfG,ZN41Mj+} m >Dx~ \ߗ'P +ƟMC"0!(1%1{Q"hyCE妎ҥ2a(@E X0I$I$I$I$I$I$I$I$I$I$$I$@AvV,1@;|grl۫c377Y $߁"RmE.P& 5ɤ/|w{I;Y4/rqLGQ)TrnoNu @0$_1ai^1,0 g}ײ{%_[`wόM\abk,|>oL*-/1 `a*7|MTD?1VgH}Q 笫m|)<&mia魀!ђEå>Y-&56=rP@!͆Zo8??]=oxGsLju@fM`Bl|C!t-Aw5{Ȣ_՝g:[9F_ x@tagԆ*@u+\?3~v $ps{2 p $ƀ\X0Z+d]m iR~ D۾hܿ3Lh&fO{^p|r"ՃtQT_w7\PmfF0GqcŖasdU!XzM<7f'KM%z 9D뼛M>C'E&2q?[HpG~=X Q &ږ##,"6z@C{0ӵDG$u'&M+^ }S1RRBqo6nQp\ȡ8IbUO@v_O]pR\xtr sI4}S}gﮐ/dFRE]uVry } tA-@n8oFyv`߯""  !ԲZݞ3&;?U\M TRb_&@QAD¡``}vP bndQ HVIc}L8[͟޴г6S` oR2$ொÒvy 1p$a9r?txMpw׎'oqy֟7j" 1NPf464^T@\_YSC1r׸j4^&Q{_kFRt: (9KmZSx u EƩ1$͝x@~\~&4-bnaNU%9 YyżL.f8.S\_p<&}_"cX}ᣛ5&fDž+e^7:,ysQ)rE?_M56wvfΝI)b>Щ'r cY 7.<΂\2$,Ol;lS:8>:*>dU#(H# ﻞB)00+%l_V,ϟ}9Z=BwEb/`mۮc&]MCVp:cXXDbFh@Fْ-zKb@(P $`pA7I7u 1>Q[p,,b8(D!)*UI!P²o'\T40:lFrlV~ N銄Ie~h(g3X̻W#F^D[IZi(R /b1i7 Tf~3/u// R|-lSb2o6ԗJ xG`  K2Ͱ3b wF>3.X^Biޚ7]!~f,~tT[h%VE%8A(<=越Ae]Uh毙j&@ElwunLq.$2>~_O^[3t k@=uh:ּΘZ?u`A 6Sj{㒮5Ȅh ՟뵍Dv<]hYWUR1oeA7}'JX$?c?5c(xÛ/Etwg{ؼ0M)Zt3"9f |IW&wV2!AHt#4>}Bщx X,{e_HZV%'p*;M/~XGE:;poi|$X^v|vr||/*@ A~OE%G= aB;$ (Y}1l&qPvsi?"jTc!M4,Zi JTT@@=сv6ȯ /ꘌoI ׁ(:vo_2V\%qӃEBW *2N.kE(8tdTgc,- qi8قTS4%eʈTSA 1a%d)K匝d _zdob4S|s>~dfWn%&Lٔ`z:'"pO!}i \`b 2xw.~ Jl^LNB)ш~bU3[Z#TMNħ%&#~çg55IGr &Bhldf;@nG[ؙ- H^-åu6kTgגijۦca-^dH+LJȜAl)E T0JV-T (} ŢsK=cZդyYj%g*f.ubUZ  rپtN̿Tf歧P}/JɢT ~;qv RQI?=pBDLxYy>=ae@oHy3i.-Ru&@:/nm`oMNFr᫯_rvkcpn!` TL|P 0 BI!Yyqg5zh W6woTs*?W#($S(E BI0!$v4J DrČ\RK}$ A۔eKM^oe fs# dfbQ|0)\ qo6/KYik,Fu?s.ffZ˰y3 e"MȘBA%(kŬԱL%,"^$3Qʶ(XP.E>&c5J- c /)+XQBp%ԁ[k& J$ CL.F=ƒ& fb`(Fl$U:?[~zz l ENBYP#>J[:FʷnUxDn^݌-U}JԵf1.6o-ìއOF:3R~4;M_Uy+WI`A6MLNU^=Qm7mܤSa2Qi;K|C%1Y5cX'.׽p)DnlI.S|[s4?w}RȱmIk0U IfPrqlw%5x{: 61]nN7BuO{LʯYצ+:  ;xv=3b9>ڿm\s[x?$4 I<q9CifeﱝFh5Ǥ gA{7iZ %DP)i b"P޿PVg ?nifj!b#YWB)u^#"Ă )3`\ !B0aY^^.%T BD.KQ[ ضMy9WusY84f 9 ZQۻ]ًh;>/4u4?@µM3 cu։;x3>T'wà _tcjOo-u>Lw 9!uƳc".ص?E~xh"iH;:W"yWON۔D^y6$p'Շ1NJ-=JJ)OC* Tf`K*8 [T{$֡Eg{ K*PLo2l M)aQ- F -䜋=}IjHsDzE YԢWWdyd"En c0TW]xc^#gbBkI-ź Rs=SKKA`lȆՋRRR !A$fHN Y'/{۱zN95(_6% H&+Hs. žP*7{b>H\Q[G?-Z`ٹG<!|/A"4#]gڊQ!Y6$ʪF`[ yy[;$j HwMADP@,N:Uϓ,sk@\aÕ~2P8RKjSX:Yicw±T<.%,*uAHu%EA, cmzp@i=,n󼝞ꬶגwRBKC2勗]]UǁK|˩ 8Knp2ʜ.miIô'aIs$lFCM/!r\>Aܞ)?;Fnzq1@ZLDE13uCjg_#[3 nx,DnH֐׆e[ـLa.wd;k `vqSa[OeD++-" UP'0!]EnV)i]h͜kj23XFMZ .@8@ W<&r *UY 00*787.x,l*,ѓYza{ YJ E?"M(L=u@'THHBl喳GB 5 1*ZE3Toak9򘁒=v EpITq$b jpL%#R%SAIJkU2*y-zb!%*bG = FBL!DA!K4+[լc=tX@(&ߋ0V@Fil~BF_Qg]TᦥLW[{2M ATWΡ[{ynpt<#p'I]#FˮE/hk<8`Gm}i`qqX $iS"i#O6_럠Tz-^ Up/猭W^o{-0NR R!^5cG'r4:fNT>l-xެ#4!e~vLjkcrRj`_# `O3VD7ݚ1xUf4[[&P(g(94H2ȇ5BkgG1 ("JGcO Qj9I~Urh$6KS y.kB+㭻\ne@;[s:cRSM Sw=[/zy_{+U(ʜ(󫻏ZW,27Tɂ8 :uzz>i86o0U2+QDشADwH="YV7X{Ṳ]A@]E`[&P7c~o` AޖXIY>e+#@G\-M5􌵨$Ӫ7v꣐AQ|&p*&S '⛻w>bWES}q*\-.t`T=|y#Z@cW4*湦<3Jk9f]d[]t|OF6ؒkSg?i{^A ,ߤI tCROjmziIXs6J=tN 8X 8\'dD'@pnW@Ԃgiz6 sr0U2 3h XIh\(hX]a&[n߹:C3Pk헣Y]H(^K }Z׈ۆ ķ}u\h Q}4qx4ԞWU1+&z \C[n\SȀP!TFuNL(!%ӯ7'̝kx}Y-vXEA{nȏB8|׋~Ԇ]§zz; !QJ{1U} ,:&_Xg*lݺZ{MuT ;^&yoQSv.?OAq$jiwѓd…(ALL{v&J_7[Y]&GWB@ $uwA~v$2VEq:Lw՚EFZNTA9$٨} fi>M3mov'`ڼo F ?>7Hs^\gP'N3 1>T=>yNnEoz5Cй~+IT־4&ueL7qf fyS`ϱ8tR ;48 If|)Kc5Bϝh\2ЦohJvrc9C7aH :(OݿLH+!hf1x+HQh۴#*xeuҿ) qLT4~1 H_G <{(~!-j`!aH_ߦiO^I愆\)Ih~.$=zFI#ؘ8uz|]=i#IJJ{u=g `gPҢF¸{6b\HD-u-.E( FAUUcߕ*kSflRh.~ ۥ1 MC1`UpZ PTTdX0,Gb7A-^ֹxBX}p%vvaD(ƍ l`bcșM%{s_iFȼXffs#js2~ i-d qc˝xx{ 0e r/3+!åRpNϐwZ\ؕS!,Dh}dqe,N#u)EFr*8DaSSk@RW<\46Į^]!Kmucb[HX1YxQȺ[H)kI_kUzFжD-HB}]r*΢0v>nw9zE廧d,M#Os z*u3R Fm-[SYoav^Zgsc "g41`գ/38u`wSuV'Yuڕjx U0܆Ұ-47~(F>ٴa,%98cX_ƒeB)-:c jF^Y=`A1(ݓƭz7KBu@{RfVuE Y  X5{ <==.̥O͋$#?3LtJPUNʪ`bF`لf"1*E? АZwk^âZ? 9gY!i&/.6pꥤc,p?:iC#b"/ 8|onWZ9B LGRap;rFFFZ#lƵq"2#3tp$]WŷD >ͯu\뗉<^?E[j|ל!$! U!HB@&N'%E[H,p&Jh;Fƻ,U9'jEBr/F+$%ցeP}ON]gsqU=jo[6U-MtޝBpdž?iߩ3TOyㅢk}fU .N?ލSz0 p-wt˰ZS<. q.OY!/HflSPdaD<a4gݵ뵛Z:/5QF Q/ܫ=WZ0PۿFP$Nn ``+ Ue%PƷ#u1t-EEKW:ɵezy]XcMu&8My_R L`;k}*{Bsbe^Y{{?zG'sEYxqf2`lsG]>NWBFFIr 6gl}K1kVJkAwڑ, G-rw -,D.IjH |Ѵmr0a=AES˲}__qj,1(\r L@h9&$e6?=ik5ENUkZłZdfV &BCy:'kOonE82gM[vꗳ_Gn}myDЩ+6jc o8gNgTqoT(#gASxx? SWbX&\X7]oe[ta@ e'},EFZJ6Ρ;qŮ%ɠ%KY V~Lչk5Mua,Ue C]ױMd+}߻w$~/=ג *ClLI$IA3] CubQ3Q*5D&&{UUζ|DFC}c}}cS>20I-?gm9ϗYf{;tYVkXCzOI~/簟:~.rv;-גazdH]X@!u|9Ƶ}(N_l֛;]ˮo)B%ZBpV&H9YpP$3eAnץg#-/p6\=6r`/28#zy R1r6e$,fBGѳXOxys99S`{fBQmQEw368nvD->NscU1q(sA }cBP[7Nh=6Ɖ?{oX铸, =cҬXs%W ׹E-BOi2C45 1Z/RcsZX"rXqhƱ1 " Ȭ#!vŰˑ$)^<}V% ^vӂR~GP싫@r K1X|pe-qcD) HIօžg|g}iʋt(^`zmE{ t-_5[F[-M xIk>CmD3L㕿m54@@q#X oIn%x%L~&~Mo<ޟK缻;L6 *;습m_ΈâQY$$VZфT_& jp޶^kCfr#_?tO?MqQwWB0+U|2G|~zo_[ށ3{fC}X K,M2LN z=afY 5} Vh'~QŪcl7a=_] GjI&ftΜ{}mCh IV،BՠݤzKLM@ @0(|}\8PJĈپ(麝e*e'IwPɋdղ=M BMu !m"qPTzs0ghh 7U âu#t=~ Us\ [b8M&>C}+WOkch#kP؀mBU|3m!C/;!_'旆v($Id'-%cRea3 _3z?P8r#䜃 &\9QvL-s82H9d5t'&& b3 EnGy/t{7li셉]Axˤ @ G&Ur4-% [A^8fZBظrӢ! ɌP/duiP-3 Y Gh&l .\2\!b=3Bf1E!NsI(MU(}hC@r| й֐/Q0]D馒5"%"BR0O;o;:Z]?ssklT{WJF " ǤXBDT"*H(0TV:DL7[dQD:+Og{PP6 ʹ+f6;6["b x g(YiD/0Jֶ%AzRwY\'q-<+M%IH  `-;H;N߷J֨O!Pq@| ^SzfMLrK]FBI!mPff ^4 ]zhHBaR/%uQiRV LF60w!&$BƢlC@E!Z  K[5b[EUfkHuV_7z7iV ZЃa>nˍ TGwSXDnO2=EzBamI2Gc+8B}Ve"h@>7()DET+hр@`T=PQSuSaAQ ʊDJu5PN $TDJO@uR+ `"M 00"HTEu_*تٜWuEV%j*3p}bIJ#B=K× qE*?$rB7qU'@.if[,50Ś|ooz**ꮌ_/y, 9 g`[ln$Kam*!sҨ}Nl/KʟWQ.Yul-Z3o_&"=VVPKdS$ (ݺsJcKD8=&SzKzUΔ+Ic}|\&ϐ'k 9/+װQ_ w6pe^]b+rWW3FxJ79e-z4U+&>1ߥh=xl|mUkw[PŪbv^р8D27V&'x`\DDI3ɀB_7> dq+p#$ "C#2Gy-ns_c(~nio|H$5o2Lrb[Xj_ %] 0`xR> -T Lu¸$"D |8sbUAHL=TLYXbiF4˘5^}Vw]_Z"dnai.EFI0Ń(`K=֠4""ȈxD+TҌ(z[P*¥+5 .#$;kg KU!4PP) UjH֗U4| Zz v'36$x gC^%khl Ȉ4HN54T! I-bsẁkKUCd*T^Şo7GvK4?F4_۱$dZ9JH*^ d5-ƽ)]'#ky'Q ¶quaRp-ccnDN7FO5T2hAAH,\PaWchZ ƒXV1ajßzt B I6HA 9Kሶ3 7*l bb06VcYAfiMڻ|+f%6p ˗/kÈ1c]y(42?xZ ?58)7mpۏq >P?QME Cϖm-4b9'i'O7s(5/B8 {Qr'edtr> xӝ^&ܣM'NśBH-4C0{DKTn4nB7C^jh( @`ϔB5ur K($қ3DPb(" *aβ9H$@ 21 jU5շW+R_~or/_"lH5p/[c* h"(' N$DI# [xT7yy)./}AjbhbzaMtTzMtq+E7sleɌZkK=uV[؆U%vقRn 3n̷6Jq$e *dhU@l^Zfn?K{ hY qD %B:kPY<{f2'_Õf[ ZٽX$9p *f@ׁXRQ*LãxL#M&܇h8&(fBYyqת1x0(ܪ[ -oǝޝWur`ft9DB5~RvAP7ɓ H5?#,OMBhM".jS7'7OL's7?u u@j!fx̨9pJAo\P7ItF_ u%k--Irc W:S w?t 6L4"6$N2_%X5 'Kz*0|ǏۛL hFb3$d՚&#AC)~>ڣ]Bl_kA{q1ZRJHp"qQ(ȱFc_${NXg+N\0u8F芉^!WqDB5-QxqOm_B+.&j(KopE"ՈR*ugO=$O4"lFlp<\zk3xPLYs3Z.ݩχA]0n.=7=bRIPF/o 1#98XY:0 2VPr3l2b+zLI3-\]|eB dUP!D*DUvUP$+It{[;o*AXݗs6ٰ*s lC ٛI1ذ"WT,O8V.9{t: :(r.Z.nA3:תtevinZk=YqS^ u-d( FqD\-\=r63ALDt%)Y6/D'焪Džsz]M<,ߴ֢V#jЯWZdpWO}]g kp"2AB"XCh7Q« }v@b{*o~m7e;F$(,IFb&lƪrWf]yKD.n7KwRdW{GԚ& p0pC d3ڟL^({N X+O<1|/56J8n- c5%ºA*骑fznOY;x1x3~}C`^\":ube|,[Np<_Ǭ)G zIskF+:V3H7yu7&sl5\l>Epwz/M i-g7=="o;Brk2y7cķ xWO3mDF4mذjfFZGV%$}pͳ06YS,8s;cseIΎ.ܳsşa:3kynVAm+q9pGP2,t^~OCaTx) 'jgvO(i{>L1FQUD,H *6jz,r_L(iĶ]L;.B_+澅!zr_DL*12 _| t$ gE `]-qVTfrFJiȊ P!@֐\a| >:%N-^>z\dxw@'x,#ah$i1+[R`\1Y?A&{n4nOܯdV DIt!s0 wgs@~3vҬ,KII*d*Mh='aOʝFDڢQMUiivzj*Cp5DƿdZX~'qm9ƼyM#1/(ūHH"]5X#( AC\fMڪ5}/4/\.?/ۘal:mizQŁ!Z0<_=x\t~kC >p! 8SѻP00!dFaZF@V{qbJm@ $lԮҨ9} b>CAQ G@14/($f%vX*E(T*֠*@b\ʷDkܤ?x_==_MsO`ٺ慯8;{ffhEBLdLcc Ƨaa A!`WO7*dB~.@r$ܬrI$@ / 9Y2/PWKASwC"p] #Lv|`8_>hEE] ( ^ Ub*T0-F QL1 ( DPL X|Qo}z2m .A4{ m)i}IjpK RH.&E:.SZf¬J5d͚GUbQg xk)G=pi1(?t|Za j8ъl1X=zf˕  ^(pF@ň I-Ofn3f[cG3 04g MP#\V[5{ZL ۸R)-22Tߺ?&2ob*oǩ^(_0:r9^`Ľӑ&KU ˗Y!fZorEɮ^[2e[5\ &<+x[/ <>n1~\O*; yk^*Qyj$EVOºUU0krLaV|ێ i]=@WuUcA8ȵ`kR r7PL0_`&h-); Vjc0PT; ; 2bC$TV rW.+]oMj2=x5N xEI#$!#$HItOnϮ"_)U?~"rDBU7j+-zx>/^j n6x~bXV{VMUTekrz6}4_Yrw]ܪ] RHLF~h襬]"U{PݳNggD_ޯuzrcVнw5vS+I?^Y8$ %ֽ>iH!ܒQ<"X"wΝLVćvWϿKiJAeDSdO$m4fMGqM&.Ӛ>eYX^S $d(l)T~:y"#m൪1K>EP. f.qXha䦔9?o-.^#o^]-oE9uh:MN{[rh&𷾕bI~"̨BlZu] 6\u/3 ꦤ{W~شQ,jyQ4*: ;U^䱰M@ Wo""025TitG6h3ˠNij@vPBPD$r"*"H~2I6I%~N?G96^d /cޢӭ=Y@z]u-*6~Q:l.R4"W:Nt5>7Ǟ9plrS[jU7kx#t,^c~/ӓɋ"Qv󴑥+FuT9˜PV P Ps.T` H,S-jO -p7>t|YoPH"vvobZ<>.dx|:QJkEZLjI02g !$(TYYDŽ50:ɭ$jDO lJ]3P_eJ8uR點חE_HJS³өZ')^DZ[;лU˱DAգ%GȸLF>KaVg0eRߤǓ|bخk@u18Ȇ)DO5owD5VBE(.tQ$J6}kq qt B] CsXKߟ/ۜ]~`vh]Llּo9ws["a@Q @a@b,H3\gU]|,oLbVKJ&L`y4jVg~[+/H&o\Nzo R6Uz*qcwbta !-3_s~AF‚oc]@/79s%Ε=t; d&AM%1'?S9N~3 'gS# %Ŋ~A$0b*xbI$ZbP Fl|:w팅ϣhHʉ|n!+UG?sʯnx5‰o{7nw1'' :z 5:e]7eL\rBZIk?慡Ѕ2+w0%`N{`3"L3 nqLH m39q[g%#UJ}n__'W>'ϫ)`Al  D yF<=MS:P~_M fYJy;Q$DDbiPģWYVuXfeB %5 RT$e*@P0ALY*uܕf"M#Wf1Bz" @QʮzII#(ԩ[z0b޶Yi$I6#KW0F3P2Vv& "*͑\_>VML"S I ܷI$WRČ%X؀uz6hs ֮-> j U W'2-+Yݱ~~ K.=CJE-H'lAPK~i_uZ^tm:,U0 0!L$He\Eʜ<+>bXk|1~zR.;z`zXHCXic:`}Q~Gؽf~eڲ)GK V9E}Ґi\&0rT_V/Na{\z/mWe>,616\Uڲ+9Ae)DyPd"ѹRj\1*rϖ";g*_7[r|3qum;"O6q|_? trFHHؒII- 3kX] xZt޺B0 0 3%nۧ'XEp0.s)%'ؽ$]D"*@36tS@Syv4(RR, %V"@T: F=>Ž,7/u [ tsuS/tz!m,Cu WA:mr^3oKɬSpA0i%@Jm17e5ZDB !sLx{&wq^YE &$jJ)pW oJ"V9($* 7l!6U%afȝ hjF?1FӡՂ6V$Wu>8/|2l- )!UdfgeMX`WSFv mP opC@ Mt+Q ƪ*UIfi H9(N)\e(&in!mVJuU K24%MyDK,j;vYABaA !B) Pʳ` 3*0(USM4KQhχP4g6HH(DVWev쪎A$@"ҙE7rK^eQ=Y|ނ߃va,_4~k,%*c aGP$ B   A`OJ"}\Mx?SOGG~Y4u Z~z=FC3u$n[!&۝/^M(K%U֡58A"ٱ %" -K1pPd:*hpv\LvCiA.dry4tn|۝A|U[$(w#7ۇY>o `XIEn1"un;59j3@yL->+ XxC{Ф,N_! ~kn5IJ kH:?4G%#BCELj]E?$=|)aW&(/="ȅbǔ a`S>P8Σomĕ9Zgf%hl#εhbۏ O+}-bWQwoaV /px (VRSQ OŮƈRv^zT4d[[_y7X3ٗ&E5ov j52cV=z0*MQ+|lK5\dDqe_EsJJx^ش8DZQ6ƀUZ1Pꨙ5 U զ(Vtb1[7WQK~돛( g! 7<;-{]lz({?Vtu1T9=bD=xs_ ׿+yYDH@@ O-k8v 99e&Kܐ`©t p}*  ?]X ݵp zO 8V޿9N t5[T?JqkK@5P+Wu(9`r {a6Q='[z[19 t0CEO 6|sq"92s|m4 MJF Nc2\gŊ B?Cw Nt.ed"`//(ӿgߍ‰~91|O "~x W 9ɹ;%Q-bzR[=&u'8`qB`!DPl4;F6|O_"gxڃ% Dwv'  ".(L2# _27ƙᨧfia w)b@(`+8@G0#0 Nw[{Bn;Pd 8H ZTPCi $xJ\>v)>ϳ%:lX)a?.8`U)k |,1@UTdϬ `0b'o|!&ݴ$.s8(<5RZ[ma߭ Al1&hDSlfU,q A洌 b"G`!O pU?FnR6Y}[3t2f9V'7CQb"A^s8mW3Π3#ϣ!rldv}`\«vvTQ8ac#*Sca. 0It@ZҘ`0${\(A Mp?-x< 7DB :u-QbdY0dI4ZrQPSRB䀭vGQṆ˸g0L $AVŤP`A yu@ZDS7'^ɔ@+Td''r4I{`)$ |Y2Ղ)7P*xNbo Z57q˱6J&r(̽|b: ,"G*p?HrY ֶ6b5&ѲS1rYq‹3Ⱥtmr0n~5264-Pb`߸H4 Izy&3OQqY}5qz'5I]9);CwNjνf gsΪ^xF^ sNv$B~NdDg}VL+8*B]Rpwm(kYQ+@l殱̛ r={r /YIvq›RIX7 IhBMaկ&)p 8Ci,](LXߵ@ 4Ic>Ux9 _% XyJU1+$~!Vhь]~O<Z10֯H4?+bXw=* .|gc\ngDiK[oc vWb/Jƺq=E]Z&1'} XO `*ڪI[~f*!=&wL䬺Uc*3e{ۇKE]c|ޫO緆k/BrBzbDƄPx跹-HK7ռ{տ"t]QYn]`H r]漮K"4}Z.d%Mv( I:2j(WG@@)Xe Ii99Әa#.F>]i_d*'=TN)$ ~GQ0N_{}z~*еV]ԝ+KɁ^R L9y N I>j`̦ ߹,LJӢT1/0hT48"3g]- .Nᫍv9HLvۃ,j"e"$!((Dh6.2Loy뙽qvRb6S呥FdfkuNg?o*:BI$_P@xDP$*-K(ňM 'i\ApfOgs[F|Ԝ*b 9NHMCYb3l SCVmShquq-|Ag4IPaqF.@L).F.ͼ #RHQs#I4 $0Q%eUS)BcN,ma%|S׏HZ8 cm?<^*L݆퉺$fd*)!ɝ9ω!UJI:y? njͽ$Qokvu7Fr&hA6x;9Z{PG]B(l١ZQf`E{nw." H%&!t lEWtƺDHDlvJ ;DT\xʜ.dqe$WP`Ek**S:z+IqǪ)gXFkݬ iq0hQ!2fIk^ž>A=t~}`BA^%BiP`Vm1:D6@^DԨ #mPB|u2p$H2Gs !FQU+%00MO Q\IT|bAGkg!Tߦ^wvUM=(CWY}?b{@RxHTV*"z|F۩ǿOX;਒* (!}P0d`0 t"4 ) PF9Q!Y)2:@(Lh3AvpffcZe1mH_ntLs(ydpL$ր"&&G"R0D`?Բq$K05"l/k$Z jl~,sfg`ti24!XaCZ _1tanRP%@, Y P!AM5GNB_2Rh P}O(LڛX>LqgY(| "*c.I?rkP )D²qs;|6Bp E+%vKndNjQ-[r{*%gֻ^2?vOUR/;k&~ꌓdgwqkJ]b2$YB*➃QMϑ%^L:6àe 8?TzuԸ+E5#.GHcޚC Ʋi]`7 SdYS[n)&u mR &9tw oѓ!i!2㢈eɨՠh? kj ^jlGngGErui{ò$g6C\ɞnYX5Ώ4t($K.;b@s ul[ӑL*Ǩlo bZ6HT"bO \axKSw!2LX0w4-+2ptkk(n:O8dI~ME/S6+eVqN"LM 4ݨuά8mZO1Fݡj(vFT >t24:I$@I)[*RJՃ[wW>ūqg497NCC<7ą`nHn꜔yEEĿ|;˱9;З/paCŌֲE佹LIF,("ȂFF`̈59e+zgOei{ԆHgcU=~aK$ @k c>,>Rv{߄Kѧ6<KUN:?QiG3S308qT@4׶aվ)3bJy_J$I/MS9~m+KΧ06ܫ㲜vT$sj#ˉ0bg'xYQWGc_z` v xFO H#DGU 2+u*O%@)%rVw eK&Z*(z@k訠O!$ ?Ff[-ᑑP/W_֑LTȇ^8#!`!IB0hI 7UF, #01z (zBTB|3s8PNZТF^ S@P2Dk 2֡Ak8&[,d>;I]y뾐up䣚IB* AE)n0dr@7TSU4QRJ T?FJ!Wb*Pw b+=9pRXZòؘN_䖏{1Ī7b[6\Za1/$ x"_i( z"eʬ[IyD ك>Dṩ/wਧ! LL2%&\P#>^6\d(PsjxcCNIr:+3mD[Lu?f!7nLU3~QCҫ]&AꦃMtbPHd ڣFʬ Gb' Jʯ! ;s;5ΕP:X9bW#+TFxiq *#Ux=?ۈ؎5B>U^~Go!=#r$0޺ĝExtì%ltJ"HXRrmZ vYhhjn m~Ӌ"Rl$ !3 ^߄pݵ 9"߼*xL$TY0CԜf DUN>"`c*iN5~W>$t&HM_iR`qȑlsvO?1|H-k#JքCVc$_߮1pMxwPmUpl+tf+T t{֨'UKLܖ)+}15q@`h0XFqm~7b~1hI0ݏW=|y߁z2)KN)HÚ]A!Zn_с&͂#Q0q0!Tx5D&G# 2쌟 ʸ(IZQ9i)ǃ("#U>;g0,n> tjukKdN!*#-8/PC no="]2ni?DG(&u +]S+Pf4wAQU?PA7AeG-ExWPCh5X`39$Sq Η6.qǖ;WA>D{cbXDEChIrX%`[P*[ܮ1.]{!쌓$dq^EZjcG˦ 21FEGGN5ÙSߒ0,joc}J.ڱr\)nxdz!ZVU=FpBphBY8 OSd.QBF]J[Fg J!HS  sĶYp4Il#VjE۽OA>r O?5hPOZgQvgrr9F;JG +HoF[i#֚Jx?]Rݘǘ0~CיyzD~&B ( HbǏu)}w#H7)] 0$o$HH$#n$ ea $r ̈oI!%9=>-{НN=8O:B9Hs @`̤zGblxSɤ).L䤀L91T?`ߔĐ?I=Z`$h$2wgv@}ĹxCIa,hs-\ `[f%`7l=8RC36rgr -EIâF$UռVABI'd@ n"iE0"zL*{"D3t̛иRA2 df3 b5nާ7two*&;@(ArfV◼J F`U#{-[7,r74NPN]tbN7SE+um.ڮRmue`j(\N Jm>ͤܰ0`.{Md` ϟiql%9~®3I%Q!b#$4;?2yO:k,"5]7C!B !n+47K'߉ŸJ ?!~=|OM萮NêEE7DcCS,61oZ\+ƚ9Ƹk. 'ڂpSUګFG<~'r݊9B˹n F(T)2e_|>X!\-yZײ~}Ș˪!G9Á|eyHJ(^R?n~q :=pb3vo#_AuG}=' M /&'" 0,%.*zJQxcik1JK~I8uլ{nt=3w-b Zv- Ȥ`cӾ\t,E. 1)"( Wd ͢TE%C:~9:rtʝ9$ģ+Nˈ6GjC./by0#&m27 rA'`1ƽIiX`ߺBRQs6%=HRN%3Z nךsr8.b5% *(b 8k>ܢXiG`9){V"C>Lʀd;.7x?*wzSJȀcyY.!ey(BEq$J)+:kj.GuD -xlbl7!8aHq )8kE UJ%QBq- wjmχ7\lqiTQ%.-{㥞Êש"|}yxg&53 Ǒ3g΃(xb(4a;A GIF<9J~ƚ~(l:<4UQ-ȄdE*:lR:lB}:(ObI(5C/.FqvBXmtzP1uJf:56 S#x`k"*ZTylp` ՛jETÊj&Hvb"M8MQޝ1SVD§TB cb~|\K0\;u h1@s嚜}էCtn:?Z6fi6q6{?g2L÷UFdb??efִȴF"*05!=ȵ2)E @f+IN7Jxǿ&dž/iWτČP}0YϥWQ]=owޤfgiBb#Xܸ)Λ`M!tV:Ň޻o>CV7!~;ׄD Bf+׹v?K+m5WnY%OW$3IK0EV`JӦzWhX`WPUT.^AJS7l 8AMd$1񈍐q uhZЛŨ34":,,#Sqd{A)XlrY5z bW_ҹt @ ͙3;!UG(#j(fuC>^0m2UQTbM+BȢ O-{VHɜXb'>Vw5F۽Whsȭ5UU .`s)s>K Y6AZ-fkb3x֨9Gnaj|EGP#&b.*vz,LA>NU~߶Hq\>fżr"G2D ۧӧ_`=n_wl5;m],s?wHsو,-J( <^5B C0^H I9R^?^ɤL_"nB&ՎȏwcG#[tyFR5W;%x=x0`T̊RTs%eEtLŌcgsLlcM`#!:fE4RL h׭S@`{؛rh,i:PD/Nfx'Ove<''A3 x?PN/@ SN[1!bt&swSAhgI$ qoH1fXࡃ3g jPĚ(T31P0Oj|[j#d>*2ݚd2cQ uM)#/FgK8E˅g(-AE /n'Qñz,<PыOʼjQU:WS4 b Ӎ $I2$HT!B/$ ]."+#~84a)ؚC3 N1~Qc[HI#;+8xhOey{|RZEYYo:0dck @ QŘ u&ҹ(fBfO'NFeVk@?}+hnNϫXvJHNF>֊sABC"cM:HT;t>/ɁHȋpgiSAЊQn.qhVh,mZ4h3#4x&&`~r]BoͥoZ&P cqMωlԘvPv^aBJNw#-p;-:*b.!4 y_RrjB-e9rqZk*d&\0(K erp4 ccsj f3fSgt$R5l'_~PSqm5jtMLGd^?5W?5^n=M*T8X,NG{`-=tW4ֻ[[Svr6pQtQuLX+iԝ4W-ZV"0IY";8K)ְQ}kfylx bG!RT~… X(a@"Eb(RFZEd@\`{RªP JD ,)%*Т혢 &*TN{|QN3s4`# аYZ,&"rZ] n:E8'D!9Ó.bscrR,\g}7x-Xr Q@[o+j;#*~=};2U7RGt߹_?ΐt`007NguR3qy/Y]DHG~An[8:_5!G0df`<Aqx3=܅lLtיu2  r+϶25dZ\MM5{\I[dɎ4Pi]4`f`KsE=:{ N !fsf b2 W@RC*:1[HQ#BT#}QB.E?tIb*s19#}|"eAO2,F]2:D!= I4 УhE$(|=ExW`i!#B`x#0bPЖJ3*B?bs9-&ʠ%ʹ5 $|V*bnp1dk<{7@՚ OWfri0FRm PV,w d+RوHe;uG:J8QuajXZ=lUHD*[-3?=0HU?bca*w]E3%?_u! fUWaG+`tkå8B . -kfW}V?"İ2])&dS$@I){/oe~6י~2i `Pg?Ct@ \v-|%X{xCFwpg@y=*?Fҧɒ/"0͋F&+ { ;uVXr![=1@ԄemjޟiT!;6NT0^_ZFRjBR979ȷ^Z:ո_{   s@Pc@ *,+rk,j_F%tC Jy1 ,UD/+ۅh& !uC oa0l}*ո [hA!nf>W[<<rLbE *o<[Ʃ:/Q"41po#h|?s!B^/#1Jg;(IR;Ib0rVR%G%Ҭ$Zm>䐑 &K:&?^̿K04Pk D/owC{tʥ#AϢeQ6>zweნAЁa8 e<ߪ?iMM~1?$P>Aٙ4'XED?: ;aG[=R4B3PRj_}t 9eb)?!"LPF/)Ӟ05Ffq=) "}$cpm&4?EV+ӵS#@21GFtD5(vB(hlIX&R*pzd5[bն炮N͒#~k SU4[]qfJlZA3hAȦJo%.:XKʳDx:\gKGG8ңh<FE݈b  rnvo&u3ƷXfC:a}20!p3_<--X@ (}fu Ve b!ݳ= sLNWu>v@/V,yLJi|T hm]}0| V_Ԃ@U \o>JRG##X*&44u`~{;{r [:S]-2#s5 zdjZ~۵5v=^|oM0OM3=ΈddE3u@`3(p#(V$&G#,2YfN',!)*3Щd :8?ؾk\t5F Heݻw$u[y(G:m&߳_rn\%t^J5*S` SX!"owk$kVV qZ\}ixO+  ^# & X&7-'{HyB 2`#lq+ P8U 2_UM5z̑R9abݣׯ÷̏~GwB1x\-Ӊu4![*%V?Hu5iPO6O! _(K&Bc&B}[ة4c鶛01'}n`<4]N[S\ c TMzphKXbhҰqx6ZYy|~k&Ԭ&᱅t{{k1&)4Bͣ5]m{Tv|ëZv28V\PيFͼ5"WQ(r C c*]OGF^A`k̐o[:9QL-^!NoCٞcN = }ۊ fmP6Åa0 XDs"t'S"A#ďƔkԸhKNw&ylhAO0[7חX0ԪkQ"gi/<S ;y48*$bL'n@5iNB(20~HEoب" `)#׉yvvUQ\ߋSy67x uTw;:A?-.r :_ DDt؝¼4dDskA:>* R lʋSsd"JjQu@:.z^n%Si4Y'ȉrx'NDQ-k[NIUW0\^+ma^]N|a_"K.y?]UVӧ^`=^uNT~i j=fǤHڣ~>r rv\ 09_q"#s,#KU(FryP*IO8miFhEc[SspBk$&DZVeҏ9GVyX98aifʐ @nٻz(#}D~!$fRr{wA~ɑ cns$ؐ{tCX9>Ҍ7;b*~lTG3݌)4% 3WqQS4'PhCp2a|yz5ew>4rxR0xgȈ=Hɝ:F^^Wp*01`22bO`+<op?w0n> ~ ۮ hPԪEe0ull f\] T m{-J#pVq>xp.<4軘9Tl7|*. 󃤁I/fD 8AGs:kfhB:*| i}:$YyGGڬLS@$ARnm]T`\wq E˷NW$yI1x^Ah)UVYk >bYր0WY25oA9Y $6i6}f;)͉ 3#:tmr%ы#aWsr8%[g);p#^N치;c.=BѨ@,ep1bP8Q$7æH]?iYDLwInq)j8`#NU8zQ 3Oh^[_VS8TDO$W"TXp\"Xy5_P?i @M o7nDw`?u27?n!h)@2?1}J#h[rpYR 1zR=G{EihtWdN|j)0Zn=~LVpl'57 yA< ?vS+!Ubݒg+ʕ/\;6~huAdGaRJݑ*/w8*DNMODOzh|I"Ԣ`R"k_xM ׽57+9^3A/,f3:1ԃ 6ʺ%u!}+7@"vb, &ͱ!@7il~iH RRH̀c_ݑOO`՜tsQiѮ<~p2> f!8伭ç.k^=;;Q:RgL{ ={:[3WU/M5ڛP Ёc4xV>0tX+, PF B`V|n _q؏sz&]Y, nt 6”:UR#xu:; Ù`)I>uܿʛ>Ybɒqb? G)gG/Q yvMAbº6$g̀  VWmףأIΈԑ`I25[3LI yZT`ۓU) 1XDEs&Ǥ8 Ņ4/Qzu:~ok(v>8>zyהDpd 3_WtArң=L:_~޹?c\T" R#?}}WSKK vP@aem^- B*B'g77^ڕ-}w+a6yNթ"%AL0 sΰ%3*ӏH@ (ÿa`f0x8  `0q00q 1w, *B Z0x80qT {mM9X8G-wY }D&-(XD+㱚<az]S:8;];ӔLu}̭u 4?YRlݶ"7BR/,nV蕮,݃g,Q s +Er*~ev7v9sjvW`!M\&y*ZU XNX]iQXײUF *\5Qݥ)2kvbl+XԷYS`"#I -ןv$@sU :'䣯)z9]aЏ.JZ_pt`I>B7WA,M[7xA{14u8 ~ètw,7y1ؔp3٭|_\2VAuni#Fsy\RO\P9_&D|!A߹#|8>^F,x^m DWʯ濆>nuH)We 򱥕_`:"n <z㊉Rx~װ%׸v4Mbw1ժfA0Hћs.&{fHHR̺<1#ޟFu-'߼?G=&08#, dK˒{?3%,pJ=uN:IWd&"0/҉|2-<۾$@BX:Tqw!su4^x[M>R܌ ckl7oA+M03eڒI + 1hKTP0_@7N`=~&7g),G:T0{+1zZjtUڒW`~=}f"UEM`wo ,HtKzzX0mPEALr|5U,³Pf! ОjԸb2& zof7D:TjGyU/* |_)'=hoxн#/6̨f1y0};JgvH#MT ;#Sa&S`H@BR9soW-ew_32DcZ{A]cLgZˁ%oyT.`%/ / . `Q콋~Fr$Ke>oӮÍ1jiW߄# PbIJIși;3ߺnV֑`QomNJD}2Zk`tޤDt[VRһ"z8H6' z!"j@aJj@ S^EF’>'_l``0ڣ׼om$Mޟ?M[,\`{29FR݋>y)bxocҾ~ fŔ*M/=k#d}i?D0R%[iBs{!"fQh5f Y" 2E|u, :5Io4nWQ~p^ b2;6WE&N%Z&5(r5v#Q[!% prdoUVNXHծzx&j7ܗd4Vq To 솼glM7BI_BCQS|9vvotr]u^]X[{  !Y}v{Z({>18PUMr {(k:HLBmAmZxm]v*mzdZ  wMAH@Gr{RËoo<fx:sf CۖiF{|FةjHiO,*޾."-V0 u@}o^#0,󻂑AVe(4T!؅x29RphQ_9?` &

:HI% 'D%ߩ ` AQW([S3yJqjM3SEP;uNl Ԩ26[ ~PA ѝ3V˸R[iX:ɺtg$I1 ?؎ 0$4\7@笯G: \%GW)%q4ǥ pJDzG1 5+|y^iga3 qXɈZщ6_?xѥA!9ye99#5yle; $i=>N78"#vG)$# J+y|Ӥhr3ih D0d_.!8weKesff 3B!:ȸQ  aRcieiAj3BI||ֽ"Bws긹T/wķ>8rFhBHzgUY2T-ȓAh 羍?ֽrRs|'ف>^?)d@HQ{X 9 *h5HDEΈ eҴz``}깶΄H8Xqay [/c%P]cyjЁX=V~. #]O[/)Ф,т@,-M_*¶e^%yl .}'%VXEƷض- F)K؍J?2 S , nPlT񸇸_{벏]T0~4 ˸w?.[Wx+/s׈\R"v>?_ yRfj 2zIp~,nhHP T3" qMv+S}~6=HkB~]9/3zJ Za.$Ѽ" ş ekcJ?ד~fHQEZ B(hi ,\cDXEL.S5Z.$;a9;9bƣA9Ǝߣ9+N~⼮M!7RP:CEd(yݦS3(j+ƬN]#+?lBə7-}Ͷ킝]9'eHE,p!hcG{޾H1)V[Գ~\!h}j\+/dٿhzNTg"XC0 pQ$bϛa*voFWXX9dɗ=nDQ2зp|3 ڹ38Eߪkۦql{Û>*L5<$suB'Ț+aS @0P 1)YwjXƗ?RUk-4r#"lѻLLcH~Ag?mw=m'n".gf`EptttݑOiE0LEShuxV۽؁M8$B*H( rIMtv Lv>B0] i9kt\@ZNU!,VȺbSJ~ N}.T5#Hz|Sy@Z+UÂmt£ (@E/ H+H|UB]9W))A|^ K`;NlDm 1熚cĸi)Č~%+ȫiLJH1wzy+z"bFM!"'D"\-l16IWJ2@?AgH{d&|zx"-HcS1)xF Ћ}-(qQ"',6˝X"ю!=EupQ15"#Ѹwpok@8Uw9#kmtl^łBaF@$L",D&-w[c7FsmU?Oq r!6+ +,gMx !U>$#hBei ~c7h{oK|,[@ ,P_nNn>,ާomI=בٿc ȳ\gydvER Ө1P? s/n ߪADDCSA n%|8 9{Ur}yzmt!{p0; "@P A׍ SQ:\´]\",C;T$`@`Q$BEZUE*"!y7  " %1BkesK>#{}? aێ/X[d| o#|[.)cp@r SvZ6fL,ZhP. M%޳>;0 * -d`>/QU*ז"Er-K^U7)z4^//-k`H\1Xarmy3ሮ_H"!xNa\ KmݶM.E~^Zf' kp<Կ1"/ZGWX$ q.)`G[;fꞂ%AC "y* -Ln9W(8 _?|)I麛xFI'O_ƌd$`g !I,>FdI$Ĵ$"BFHE$HRa$ ߴ.e(2Vg_#o4! D@9/KGJ_tXlmZNb=^Zqw>_M8dEmy_- EYmfpy?\ڀ@wٿw9dƎ~ #H x Lᦸ @멯ZiçZ~Vۼ,,5cDvH6_y 3`)V; WCK4si|_ɡK`y-PQ5 I])\o>u:R/=g9Gr~vBNUK6ॉeT%عf}??0}lv;+z9c ZI$3gzk, VUZ{wLYS`9L(UL"IUb2&8M ,|h6FFOO_4~XQ+|$ cOru8/t9/Y|VᷧFhI$!7G쉁!G~$4EuN6Dtv.c_v$ZtA`*d0^?*AZ~$"ek|bYz4U FCId./G11&*IYs+4{+6b#"H &A>*9eY遝0/5[Pc/ @x%DfE #uu&"-.voEgu4 Xs%2si*™;O++cH ޔΑSK%_s#In01\:cĢe@ջh‹Dws7=<)o9򽗋9#gM:jjرoXX Rk P`y9pNuG_2q0f_]s}:sC`;y6Czfy3ZЈ1DZnbި«\iD}w8\2mhX>٫/ bi"lUswhd昏.`oeep-9~ɬ BHjJk R{syNh Q=V\*%Db߿P.ug011%T&*Pyʤ %[Y( ́mvb}B):ΦD1RM=+ 4I$! DK=J"t֌ )4dnxY[$G +X:.*B rs6*bfb(@](8zϋrq5ȍ=m0"3kd"xU$p|H?P miυ۽S]nN[>UNg9Gq:R3§].~gKh_=ɖBnO`;x˗u˂~1+ۼᙑ;D}_i" Z}OOo׏%)%Cz'H`/02{xhMO6{YJbbF]=[)ۄ!351*ٲC+S)"KD\D!tHrۯja_~[n ,_2_a Z?i]y["/rv/2+}1\6^ǓIpIKLd@B ¿ݱ]tS)cxêt`+s<YOrmRPȵHyp`=jAf e[>c|2rb`y g{!|jx2 )@ @ C>aAL7G7eW%Ք[_]ޕ~[+*B#_rE L1 A1L}Op!hyIn֍]'TtG;;0@P8!hI!TjrGq@ J%:-4bs(~5{,I`j'`~+"J+xy##TkQ!5feOQӂ8pYPzZ~Kq<;tHI޻y Y529L<"j@*Erba{h焿 ڦԕ}GRN=`Hl T7Gc ~qFFp5i `lmoI3;1iVx8#0pP$uY@`tsy<ϛ{|{~> Hdj/P0q5CQhFAܐÊ}ܽ'.lmmM}x?>:E<<w=r&"zavRR_,FB923x7Zš̌p.,, "֑lu?g߸54U]FU]eTO޳E@0#Ad o?>oWgswPC6rMjQ?k+qZ5v§GPif=enZ"U( = _JP_9TQ>Ԭ7tzgdc>+D4{ >1 n\oʉM֒ ]AH@!D1I8;,u{;VV6l@GJ.EJ ~$oaq. 6Tz} gךK vԴ3&H" JO0ƖS!4fJDʭ?O>G*zi-?K*kcojF$0ZX]73 ԩͨW:o٠ʾb;>W)YN{ŌZz?n%ut~/v9GdPbE9~IqV-׆d*YX]3ZC&j?xqbJ%⼃NjMymP?WQPʧ}×`zZ:RB+x"_0=ͩ)윒 Ԃ| pt ki@4y!)GL=Aw Ht ŸFe A$"o;CP+~mD&YZ-U;IJNaRFx;Hu*Pp|x/@yh PP (. 0DHu'>;ge,Xcej¯s&n#%zVMH:ױBnMzjG)[8,dH;MR_a5qXU˦9|0<! /L" !*:^ .eVXT@RWJմbv-HI)DWyirw!$Q49FsB/  hURW8emal"[J7S`]ҷ ӌͨFNvx6/S0lF*N㡣)CM&%4 $ YNp@ U@|zplmA $5rb9 R1B`UWe$ B o7o/lմꤎUd$0X_1][*X(j#$Z'!ˤD""BsŻ(`[<Ȩ!9gwdV^ 5vJݒ[?dthXFA#PrHZ#)CXҵƀ?M\u` FEA_r$@{^Cnۙ^}Kg{;SfI{ ɎL@f9~.IBhܴYq3녟`&.!041- ,X`O_U|?m}FI$D!BBa ÐNWfEeBߥ4*}=E.ZSCjxXPRy'樐܌D).ic|dtDmob6"\16Gt <2G:}y>ۻe5̅O8n%RQt~k/$L?sYOUX @xs?4eJm!3acuci'R(z`AG eޯ8}#̓0GEyXiya[EbTU*Qy5Qv3/ݬCȕft3ɭ+fy=tXR~| qoE|X (ׅH{C6*Ϥ@3aSgl_(ϧ l5CF1)hhѯVg>'#'͜m4[U_ Z0; yrjJˋrIbw\ dB4}@0B,ޛ"SKx(>iLb b@**UK⥢Hc$aB8 E$R@ Q#r1%aHD.ŔE~?AEzD@B`,E%-%>dR)J 2)"P!&Hr% RQ - (b);A (bX(.YChBE!JJ1HAJYCc qBc"$N(YCc b#1BXH0P);A (bBbAe RQ \+!BD,E"#B)B(˂Wu"%$#@A)B)HB5 aPa5 aPa5 aPa5 !" !@A(!,0a G pTp0 G 0Tp0  04eL)QSnK^$(%RO0zE]uBE-,bYeFRԺŒb芤c[ f *1 -ALC%AEPQEQk6ƽ*,K)!HT@" J KViU$U  D4DP@) "_cE$D^L )H D# #"$iiD,%jJKX)HEMo:6cUJZ~] Zz!PJ B%ŀE @@)- (d(`-6 [Tp 00j0 G 0Q 0Tp˵ 9H,/&Hl00 E5>ۡatq=w*B;t&jb=^hy[s;k W .țqG۔x>+ypf kLgSu4 P@ٌDtiRBpIZbƒsX / ]MvXBߨSTS-"oTeu~ާuNDU1 ;1#bQ~2G:u-r6nNߢZd5~B7Yz+~3jj@ \)E* ʊDX$I$DQ= Ō d0K,z"ł@( ` }M0A(XIaA ZF,,B,Eo$OP}^ɥ` Hv!@Z$H0 P>-0Dp dHE?o~!i[/ֽv[VIFBI1UB9X-?0<ڑJ Ϣ %i If($AM@.+oWL&qWL"e~T.o{IqJ|*?nc2 m~G#3fۣ#;T[P#9Ԃ>u6V 8_nh)zD }Tle;I2ݱ.?e.Q +l~:Ga~m/0 r]r?Cu i&dբa 6qA5p@mrE5IQ%)j@M+q|r+N&qzgǧKx|&u:A, JRȁ8:I?:A4AQvhIuc͢~iXJ~@ &@V]fl]5E^c.vmuamͼ (U 򊑋 3 @hMdZL09=5zݣtc[FD$P;o:iKQ'v""F#ơދFF+wzڴe=S7W.ydh& o<^SCEKKYd֬Ik=ZIP>̘iS"!U+q0 ^"zz1= eF $zΘ-:ܲ?p~jI|d17N#Zۉu,_*Nx{0J;ʽ() 8xmj}Zi[b=J암/=;~.CPy%`#ԯC]!qDpJ`\lT[-S @%&ÐBvj4}f<yRP׈oQ?긟f&|oc쳒RHk(oTelp^Y3mF!^UlME 0cO=@^/S5TR\Nv-m&N̞#O(Ї&Рkf|L}/"21yayS=*rUPD?YR e9nQ02}Kų$[rvɿyBOu/{&cl(}F=\)[a`.J?ImJo/o/xr(2{+Ֆa{~ȷeaA9UfUWy5Jў?]Ñ#[yPk?9#o՟2 w?T}\#= |&h=T}=e-c Ҫ W=QQLVJz_O "~P>XdBdQ E Qx' D?2a%€/z1UUP !B! B6?soCӻ&!])#+ E| g&~\(MG ~*z0a0X=@.03w*<+TKFAԙsT\գY,exJ6]%1[mL&k2$9ekoN55LF_BIF[ (`\g7tЯ  cC*ŤG Orf@7iby}f z, T<32ܖ"C'DC9{tPR9s8ceMn9,>;m# #h=j9/Iо+W(mێRLXϩ2W2|N v91 UT\΄9n.gKAJE2IOY#GNkO]D[z L2rE<&fLPtblѽo鍾S@ kYhnLrP47k@-ܺ#Q("1dxuCrL f<*P4a}۪kS{9I!HùXVe_ VeH@Aww_gmhY9WSU}U@wR @B  wFYW:JR7P|; Ntd; _񦯚tfNH7b#ADRG#H)}S-p\)w@H P&LSH"Y>FHiIq}R{gR{ss1)miUpFk:dFtN-rh  in g.R3ۘ O5~!t"#0`==0%ƌݓB@TFJV'cr\Z4ZmAsh?, ԍFF|Zt62B;;MsPf-FpTr\2z=&%GqNb[t'v Es˿GwK xp.TȰ ,=f3 $T'l2J4Ivْo7NmNq*:Zh=ۊ&tM[ 4!7ßPe2ɪsh~7Ba [w],TRBM2Kε]>:+80`,sSm=1Ywd0@ձGk:PP:EE{TaTԣvLޯ\Þ[YJ\x%b;[,=̈>Az)4Ctq ;>` :=p\/p[| 6JP'm$U{J^4MoO`ZaHG3SϕAx{p-Q$co'|';Ɉ5uTjR` dLeQW0Q›; YsneXq2lDGW|NwY^ 8M2na\TyYU-9b~iSR`5bp:Col|]s 1rb~CFzֻܢRF2)c=Eͩ -k33j؜'`(A@9{oD\u_ )DT\ob$q1+a+H8qOoQ: !ىנOF,@AŹ'S٢Qmc+ɩhzRX,:]hTzԯ~"SWҙYo@B" ${vڟ8doǤ6ԅ(((a@RQK;;q 50XJ v\]U,ܙD)Cl:b6r!a) 8`wL1/R Fr,zu<>5Zf?ˏ3yOEB0$DwG;>_V‰`GYC vn|x154jƝBA`*# y0V!5"Z /)/k2%/(1z>zïj1nyƬ_%!4{q _H+?Z,, ^Ö>D!רO@W ,11\~ݠԆF"hӧ9,VUNѽe[{ff *bvD= 1 ˆ&hKfsJ.BݠI{yX\h*3Dd+~EPlUxWC;7][`3QNJk[,Yx%\hU'bR: HDw`jdfo e9"ىR x/:"~]`V_7^}'6Z%f4b}4d9sb erP8oj[ɒMEz^BBU<"\%g~ȋ"ն(@ Ƞ]P.M2c Vv_nW#aᇋ7]Gi)ة]9(Ldzok8,WG!pDy:s)|u}d]z\qpBT9 ߝ8롩}ݸwbk*hPN;3U")|mPHֲ|ՅròHav(?iWz_e5t\`_&`}ERRH%V.M aqRnO8MgIEYζ᪌Z߾4>^V6r/5UdQDA$KFe zď"i>o*S:׿75¯/nuZTeS| \M@3&?bY~:>/،1yJgbE[z@r`3gv/#&t[sS>5{>3HXa/^$oҿ,k΁-u=Zj|R-cs?J οj'`@0ǎDZ"7GmL$k flH[cc#ໍ uإ7.@)4#*V~5*/.aUǸ`拶9C)ڪ 7W\!bK ?}Gr~G&4Oo7 &qHJa@S4k=2`UH#ƠR%IBlqz_4;[Ri8@3!G~o>GnWf/q4Ve%E7trM_IW*9y. Bu m4vy/VVL˷S@(a;x *~O2Pԯ<ΧHCg1`DO8,BHB':sdjLjQD5I0aq2"ˑ:ߍmE*d|/=*9p5pC{5{OĽ!q\ 1cʑ<~g7@֝XݔHꈐ팲k$hoU||9pZOU5]LC#/ZI:ĴR%rAluVM"  v5olMEY1$x;?H;oa5mT3NTe_k}6A!Ph+>@7ݨ!l˸ ͕5qa*k}?"}l@j^jl)_ +H02\o~ =ٗ:!,TD"0+jj2Lvof @1|qJk6]q}3,/X=1BU6[xwʜ]= OΫ3!ðybZ Qmc5'JG:,%y,bC#įp)'@5 Z-SQk@+2B΅aRhB 6ઓ$/$džf2O#u˂OX==q#'hD!$SA*3Q?;?aM۰#n1-I,*ʤ2It D@R|/\ۍyuȥsjiaI;a` .3u{HB^W8 @ GS 5yLqd=ydeK|R5`"[7ab7+ԼP("%Аqu$CHU^r)\~~ A`K"b <%iDG V@Dd$> Ei$ȠײxDT7zwc6+9XԂ$ǼY1F*NpˮH6jPߖTY0$d@C0["}PVX-;&9."/\vM/вoI򫚻!-U:Hp`j)c HŃ nd2"Q hv.׍rд8Kx}򷀘W[DlkVq-jXsF?7y}1 /Db6e`bbp*gM1Q$Y7v;8 ?B>G遧M֒};Ĉ^L 6>=ҎȮHZx`ɮ(yf0_!uLNt-F´5tsMLuv_t^P[vZ% \|:O Sr ?H%gebjǍ6Vc҃)Lj܌ *3^zՏE -jITBl0_T{}e' U lMSmdxK_}̺?:Č0 &,Cܡ@P(P(j&V^B$qn9F0׳(ۗ( İ/% |n_m~b@ % g}Nc$!Nuo0=NjޑO*!9Q+#2cO-w v}P6Qك=5@8Pȵ8^H#i5N9X>#CQj@d@j<Wy+bXswA6 ^S0*[61 ` 7.͈ꅀ , \72Pi:" i#4 GѠ7H*È&|ݾb u'}t>{/ڸ IO q],:Ŧ_+p4ȑ kOUyZõOk/σ(۳Iq8_%Kl]WAH_#aƉU_W_y~?56<:D83WIA/#q=?_cT=y9䮚۾d$O DBHSr(B Q̝P0/il_ecL/: 2B514Vil "T8OoiI:@   ?$F/Rizt\>LM~?2=4]| J@4bP3u\lTvd xִ>s8N"x!,,jf35MD +pŊ$[H;I!zwEXvg;¾R>G :r'ϬQg"[FZsJdDC2޳m\E`SK͙234/q6}f$ {6JRhclv k݄Tp-qy|jro~)SE 2S_d*ŊLZ0k^CZؒBgƪ^ZjlR 1 D+=Yg'ܓV qi6&5vVMER4 UsB P p-x'ћ=D}E̟roFO_X6I, T$1Q @8QA̼tI0­HMәGhT9XUTPprvx@ Tp5֧JGTxVw~'W/hf=SWhpd,@E,kn@_4*TT5W$c`m] !9N8fD⸸t["][(3[_xߚԨ!zrѷGtKsCvVZis],=_.(_ [WY)}ֆϲbl(C|@ WxJ4d #5_ U5 7z=^l]lSf`˽qc6/ku_JĈW [(&ʁ D2;g} !a/vCq'F`2A!z^!K(;Q'g)3$G0/aPEB%\Qrŏ(Z([8-y?K;g/ sߝHy{sݑ~ &= A30 /8 ˾7JCk0<"0[5`x>Zo:PR 44$4-zXܮ_iX=/1J[]ZB |O]Pd&O8_}Ni32lRdn] DD"HܸQ9wѥ /cZ M{lq[UcDLCng}mZ#o]htј G;'D_])ҋH@4Ofϵ9bm,~;W"14 ;S`(/rImLAAWCH \n3[K*줎Wk;/-"-ɀ?bU% ܠ/~^fy#*~ Rp 0m'' H&rǿu.U0HD$v!@P&6OV0;߳ uV--{MwiH_`;&@mI/4(Cs6Σ\OxXΐr%̭cb%&|̪O`euX@;9u1qr^6Z>۰SLj*gVcDݹP3Mڻbnpߜȳ;mu/q++Y4.  E<7Ŝ5)+ԝY_KnimR@]J3`9zd gU0HMYmpO֡DwE~1B}7נuY(ۊ^ ӑ0%CnNA(8)w?gE##BA2!|`梾PNA{3NZ̮D3 19dEGiLş8 Te o8a BD,-wNĦR&LAK_\.Zpc$uzڒ414eBu jW6yaw򕯰  v?c@v4xz?r3vgam] vܨp D -<x(2j `_BI_Ϻ5õdIb"DHpZҥ$4f5|$  [`~ ^Q.r%0/%( _Y5d=6xZYΎ{Vl~.M"<+/b/cS/gpҗl"qu^kݱ9&{qL]1CUNS>3Zu-j%Sw"R ('tw0ᓋf浊0cq_Ua嫱vL'HQ'+4GY [oz|/m0q(VG|\0/Or I眔ԖS_`Ӊ \Goz@c]Lfv*{1<.Z9w.~VYW⟕L @\.vPN?~7~}CP ϧKDI2#H1sq.5ۻ9JYû }4_ׇZ#{%W:eXXgb|ݞ3{d@NR`ce\']Z*75{>Mi?e{fdڀH\?rEDط~ })餪~G<>t> E>LP躾Giu$AgE~DNry'O;NfewPk HnKk?0(f@  9A!;@T({ [^JrQJ\!C4lbX?PL;\- QCM;-9go\u!m$ztelߴ fH`-l4lMV`D9 Hv<9Anh^DaTr~zLI}!̿]kd ܰ눽#@{OﭯrNxuGl`UtoA[/p')"P P @@3ʐwe V^ν >+h2~[|_?xZ!ֱDEH$ Ab2(1 usnJy|nמ^;EI\NG"po:$ 6" Bx@*}؁ w˦D(-P)y:*+Mjp.HH g諂иdAqg5t|ՁYL͊u~ ]99p`%Sֺ9ha8%EX&\J7:9GcNeT0D$g&Y퉉}c,ֆQx `Wa뉗x9=VX-%aA Jt5=1^4/ S([>Yr 7ag~ 5쩄r,r[+ gdA|W56x¼#׀!}ꝑq5~dv/˂ ef &0RB0J@8ݑ͢1OOZW%":>a ZU+$b7|RTr0}yt8uUL[kYh \@]0c!rKq@p 3 b+T5ܛo=&^ܔ8Dw7-;";kj@ N 1C"jtA22]fT1*w}7z?SikƹX\堄X޵ՄUr[n(2@2 -dCZJ+wJ6Yբ=˲$ 7qQ}A³,;[2CBDD)B|rjN/`ZWGcyujˢE .2(j$:< '@+ҿz FkϠs^C}:GO1:^Wi0]TGHKl,4@XHdKՒ2 /!Uy5\kRv#\>@ d{uW:aT0彀&EqDOF1Ɣ o=Gd}A k[e\>K{#p`\^7᜿cwoPS4 SBKFmY,pFg{N2pCc]Jd2R?%x!x̀ BWnv_5waͫ (Ư6X~egyb@j"R+b"kom}>#RҎt1JQR]$v1?V檬a6 )P E$ʬ`yb %kX̍VӀHy"R/nuz: Zb,ҳE5 !!(às2Μ98d;GxF`~OWi@O JYK۲Qё 2@ K  P3ϑf"f\cc)mP1^`A, +O7ug8ς@$ȋ S倍8i@؁@[pksKl*rcwaK%<(0˘ η_Tjo_|iRD7h xuMNjŤ͋ 3U5vj| gAPsU_v. @Y.^v˅[C\Xb ?-4zbI!?-IZu}gd*W~Y %BQ*I #$$@n`UdPr.[\~Eݬ Ahv[_ n_#L!Ci !!FVlqP$ XK!EdYDdY K( (,˨ВPM!z,!`(9sy)O?xX2/$A[Mt瓮ў彩kIAg.,'MEDWYIM=6Ʊc~~iBW w\0v>4vW2sGOZjC,h{d/f\gd|# }k)-vJ |U} 3 ѺD# & D@kaaj<6;o > "ٝ.ߚ%E w~ky"߮0@x'Aԣbɬ;h^yDfY/"k# !9>"0շjŐwq +(N&[3[78L; !j0@PB`@T7t] BwR})4$_6r92)G5PdK?8kn%&!!.e?,TB ?1E p4 < "5/ 2(HPEjJ(%O@@?.D~wݝݭ)ŞWq;u^}b'" !3_Y_dN5Fd ؉b'@C2@$ v0oScKp]>^AO8kZDh9ccWTzO)Cark$`J) ďYT  @搗   ف}#TW E 1KFK JTRLj$e+/p?[{~*AWϭ4]|x~o;5.A  i%^Ӳ\`]_yYMvycM7z'{N#`Xg}}oݿ2&c[BR:?fN"<=W9c -\ y1p\unpo~RUT*ƭeGe-x& ̹lY'3@,鱧hr[WN,༳L{:^aMq^c`5 `Fty=v<`^D: DU]{0v_HP G=~Sm ԹEO@+#3N!Hƶ. E [4qw=jMԹ׃HFV!GQIDTSU؏vŎW;u.gXl9үܯT8zf(YYà]OSuJ%鲳c#>cb*by wmɑjTǰRJ&sUN|g%NJ gITL Jلa>]@& eF,5U=r@V4F5՘Tk;UxII6~X@Jg5\CK\$鰒BN*#σ;?Oq}E<7ed+GwnXZj/bbfF@ҩ<-}jfLTXc3̑-~I_ٕ' ! Wq<޿Nฎ+VD{:LҦˉ7 GNƉK\9 Tن;+Ӹ"GUUh|[lʗ M`Fٺ)TE-?Gְ[򼝲dQ.iVSEla_ H+e՞ycNk]s;=d@b' 7ff^F;S8~L+"6-d5 &cFrXц{/cq]d͇AmM:l/&5sTOuY/ R-UNXڵ *6XО/M-Ϗ3&aE$ߛ"M[o2/v[MW9b3 "WU)yy-{YLOKNP|?ǹhqd 00 ӑ@UB [B|teaLYsd0 L/m`׵6犬 &tlB<@`@l==Rjti̻f!_v@P<0dI)~_i-fmrRd\3zbIk ]컊f9l̠vy=K#VY)r+(q?tJm59ZDP'Z=r{<20TsttO*=Mo% Rfn<\n<4N}<ꐸ2;|TRv?Xq)C~ݦ*o3^ /@#G%?#lݳǪx0PTKhf1bsr藦^9M&(P4mJ}|M|]$6bMK)F1hO}3Lr9BݙIt;ݞPB%%=m7aĖ)_q D@Ncd}D@?wx/w[0v͸%`v~7vƟ`/㐋lQs*٩&!ԏòNUj[WmDjTcy: *N3Kx' $"<+5@!%g͚BI wjLoGL÷2!KVƄĺ^D̈ a$S zZi[UFo^y'R]b9O}MC@*ybhL `5Cl@S_/S^I2^hoŠ\Mdohn4xƐE?j&uM{lM?L]+qy& Rh,bk2bak؊0X!7S$0bl6uSEncٸc/m 5_M4N%/= &57'H_h(U\Za.:t^Vr-i,iY_(](V#a *v $>1z?VϽt8 ,\L_ p [XR)sȶ|.uMڨHZu(OI}܀"j ,PIf0x`2UK`@΁qX-^`cySg%y꾺5M:ˍ/)Nw^ы߻1ݭVtEJ0f9GKꠜWg`73nNpLH٩i >^LnK%. id!5:gK.EƐVb%!W aU#?pCJ? Fv1Q)Nj  `Xvz(ic1@Oe.#)M&Ϧ^Jy\H y\FJ>P:|dmdQJgڹQIPԝ]9e."4Q4+>C/aoX%X  FR,d _ّ?'6ۙ (uNS.4jD?eNWm1AcIqvZ ៧4r 294'[U0N4@$JH Z7; k@clYqȈ r뛐PXC̷̰5DGK( Srd_41Wd8}-,9N~WyT{q?hs3UNod _&:?fs>¤.6.~zٵobðSz(f@ dD@r\4B_ $ %ˎȕ-\2ha\b-bnCSd%HQ&NݽB5{c ʄJ$ 7 $tLi@g_>#~e(;f_kFJUBWO]fr}^ 1$ɷ |Oɥ(n%zJ:jS5,,dcg˧no[hB,|p큋.R$ډ1+U¨yvʯXFvlIWV29jJYoѵcjkGpgEqe #K/w|~V[i.O\;Iᢀ:(u@S߉;p}}A,K,zɻdp*2(ULF$`Ë[ UgWJGo6񏁁bsW;kc@0Ԉd=5~|['3`*Lsrx4]0e#eUrik8T1 ^#?IY{[t|b i]TI{KŢ%x.~>ɲ̀b,I+ygB* iC8rЂIKnq?.ca2&u-aiRtnKIõZU2AGCiPgST6b _tJ2}}EE% 9\(Ŋ.NNBOȊr讣J|{t:-)OPq޷l a0@$ 0OoIKsV~WG! BgDPg#ts!]c{E}ѧu_l6HrL%.T% >UcOH}ÊG殙PHBI[`Dɥ<\=m_?wPI^rW|2,~[Gq*wB0u 1Iq ќ8]b~Q#i }e8nmuoF=1Pf37xEOV`ԎHS1P 9['!R6~PnME&sS/-t U$mzFa 0 nVw kWb~}@) ֝&$T,CA*('|8g,Jk1afbQ@zk ^,!Y)k!j&jyӝ/+W7B"'7+(Y*_Sg=4p=EZeb"P'T;ad;?fNHv j.{|@1g+o_"K}!.7Z;t?Cv?eqxH(0BM%"a Yk\LO}+IXXyMm7;~7$H_v4eFS\X#pL&KZ=a>ɕH)<@pW7Ew{`z֦8NųCˇ}ۮa1(у(ϩԲ5@&\e rnz_vZmaҶoV:B"ymvV`&HF Zmya"~+H8!'GaPGIuHQT*Qb¡EJ:E / 0-,TkfTyE?V7MDP E?C8)؜8?#[JB[XD>q|fHHIR^752?ZH[v̳l-1S_(nlu!$$ UOd2`]h.B1g)n<+ý6L9T-O;so7YR~˩X H(@G3+s[zr|3elpN̙\~ m,<kY0{zjzk+LmHUsO}x\pwRlM$LFׁmjkb.'HW4u=o ~pqBL0ؖ\vزsIn'IPE=9Z$%I&qos{i3`JU.;,>X\}/ղ=unh[eKMOD_&\ȳ)qj݅aڛOϹ"JZ: kt>du2VR& sMﭶ CMR0ȧ#yK [,MDAL,z$$lP!;ظn/=.c~ $cf>YBc^C:V^ifNbI9r]8ER)ӫ_2H&@2CFp{އȕ6^T:xK48Z-|fYL15tQN4ߡ$-b g=ڭa=LgH J 2DD~G$VYv~tF~⾟'nLlC'JA 3J3!"@%^]Z\ֲak۽}ϟ?}WW6xO a]3B_H\0(p.00>ၝkjѲb}\TB\|_4۽UXW(v@#U hfm+ȗz<0Vkbˋ=ƛԯh/B{\R~[Ȯxg$16&A @e 6iqW=8y(!%$o'˔m#J461{~9v\4VIJ m٬=;ۧN 2`:㰝6g];j 8> _͏&F[e:CXr7 +=L"OV3v @.l|OOpc`7}j+P:deuGAIZtz3@gH\9%7P8luXSlZDB]>N-'y0eΞӏhM.B4J!@pí-(K-ZKHAiOާA$}0TuD*PCCo:RнK9턱~u:29|482/; pNh Lힴ ̠8g$f!3ZW*ŔE'WUѦ\Qo(Gf2rMa >:B:gG;+>*)hBms~q\%jPgO/}J!U<-6玒*Mrvb(vbOC;nmrȗUоb#~,FiX ^] :;o$+c _6jJ_g%x` .hN бb}w&$y/Z,+ ߑIh5d ]of҅(,Pk"QOz WX3[X'ifKĿ,5Nt츲@yyr<͊Ɖ2l>̿õjV:Pqz,PbtXp\X gu;l2DZ:yGP5t&Y'.}ԟ6yKC$[Ix7!.T#ɉ]sGΒt%}I3n\d*1N=W L%?O0}|k%ڵ;vtLQy_wn_+Sb#W~:%azKr}2!IE9V"aTY Ȅ.NdW?9K0ޥ؝JsOy g2}ov} x"r-JFo؊XeX |zœ{5Zr~jn?Y0!"?P30 46-, KRP?I  r vigC/#b;:`WZI,'LXH=/ZBh~Q4I$K;ˈFK3[ɫ9W/-iڎ#:>TK-d t<"yREkRbnA_oldi3k-m:4 21UUE -X5Zife#QPbCqkSDR A\$!$IkOͦ2qRN{r$FI3g"&u$"YD@ɖQ2`2>K.SgK4r ٮM@&9aD!PUB| 65NGrXړ&t>OЉoeEqk-bˆjP Td7AH?/=tԭ@9ڇl`F4ott,얉6 K\RLK0e'kP:5MD:pg׌(dI %I=}C?e%E(u ^a:bfGky5CMuN78'OVl)l'MgӰ\ml ˝.JI+!b)RTpE' 4G_lo7{a9%*cOYtυp9P$ +}Wt}n\<7[:^{2;o] ox၀Ҽ,x've7$!$B0Gi \PlU U(G**NǟUm(lh|q ,)-)ouα H)\2td7MEEQmR^j+,=l9bLI$!uT# $$ G;CX`it1i0,quQg#u3+s{GVN|~}WtЄeMp~A.TCt3q+AHQAJ˦ldN|8{_mqo4#/;>/zYZ X&S[}TY릳pu7gDG-""^!|?[}epR,cLI$I$WNb9G.9;f HxʎNyFB="WwQ)[c[$FE B8c%(6!RI0S'PϑO(iSh Uڨh5b hZU{5# Š6`n}$*"H݈B~y]jisHR3nKev$PB H#h$#V% R:J:GNg/C{lxC a]E33]<," fH% !#b8KZ՘nBB!$a #!E!TH%J"\ qT2D 92dS"@R"ʙT,ƒ0$CTaVXEhb6lP0V%R)B(^e`I &fq5*pQ!PV" BI D R$#UR*b,cff!,cEu4FB2B6B- D!! jh"A`)D4`,mdwH LW!C$HHuňHB$! ${\Qx{~O|[ߵzNz/ PVs^]04xlNiw,,* t3((:| q÷]W&S9 ՕrdS;P72!.SD2&ߵQ.o  < %*i"A,B IFG-t^KE͑$`$M+Xeh4cϧbR)V40Ė^ŅjUhNLP5% ResU.ȫ^Zҡ{ҥ%40`[LEDRR,!P2J 67L@]BFB`QV BI='+ Q"St'7N r)ۭDdkȯYZJ]8bt°)d)H*DzHB cOQS.^:fR?ETe L{yR4O i&<.9_QSqn\$Jq})j$HEZh^$e< tVI)"<t(DW2w(-qT@/ V>1o+xb^x^9B\ >b׷l|NwEup/xU%K8ՇEF;g::ฺkNoۆAn<^ۺTD] ocLK )֞D{L.3랴&Jx^SH[t0^v2o%1󝕦W |x_́2>]Gzq[{}:byׅc̑Yr-)۠, 7}XD ӗ9<9Y2 R,ˤn E}ux|gB]΃ ZRAlߥ{Rím+[e2Q?ϧF>k@ ͊eYն[r0k)դ/3|iWgd UYC+ZAO$a#1g8zM[q'T9_D_$ O~(.0@N3Lʒf6.%2$ߣpŋ,t2<^6hLoq vrG5ڰm*~4,P@́1mց<+ lوH*!7t #ZqjjTٟd/uG Zdh7<&5Ȧ6'4b%Gljl ûn{pCos0L"ĭՋ6UҮ'{\qI$~Q1_Vˣx%xlӤGuoJVTћ=?G_/b,yQ\^zuX" !1,= -n;^.RӅZʣ1@Aˇh83?  >>sU>'l,-A%w((Y=Ck|;(mhuμFj, #V-uvwϋCw^/=<쭢G˵ ǡ-'t{,y%? V|\0i\-ئ9>J˜oeX|{_SRe?O[館q.VMoDjXiIF})0d+0,BÑD@—CNA%Vvv|2D@YoAv>կyqG[D30\g۴+!ܒREKjߣo'R}~…Kz8⏓|!.U)$XK}Ej %HR.KTjIU aHdDH$Lbby(x>f@:*# = dpCG`"|h] x뮋Ϟ*E_uh*z4PobH\/""/M-z -VЄ hի - 04?U1[j^`ƻ'_j@X~*|3 M >'nzʟ?Ug~NLޣ?E*6QHbE1Z鐤,R[EnN4 S.De;Ϻ"v-$W[ Ίji4 HI4Xb>m\BG,mYkkܝoƲg "4"Vj72TLNRD:- p$: a A+B߷Di,aa=.[ <`ל:A!m*'JB,,I!(HxZC]Aםhx#pU؞*9D+ }]҈_zKR}dF2mR# ]"d 9ŏj[~ I :8\M+/50:! jT fqY 1`1o[ [K$NHto,90Cϒ XlRHZ1D5 *+EX(il4̀Xv@U6GUef3+$PhH({> 0u8B~k(R x&_/}&DOӅ̴}kB@^?w!J^|DdA F@A.P.0n6*P/CR$c5k#Dt#fn;OKi7Vg1+`%m(Vf#J,ۢ.]oCHHAHBAb}F&}4T5(,AA (2P$@#"A)M=l([+):hAPWj}.Py;ѿY@0UxP1㢠Lf<$\j Hto}ףw =)(0Dȏ=((J =9Qq*xC(Jn\DYI8"T \| 5vtpb Kq0*"uE倮0!cHA  aQ@1A!HH2$"@URTPH)TJH 1`Ea(2(8@20P _K)-diDWXIi&vE$U&rK[9h$*,XQp`h䴖fIRUUIRTVҡD,zi#DXobBQz@.Lks|PP)UAy)QePL(XQx` b TEῗ ҧ9k OʏR $J*J#HhhTXzG5*iBN>_})Yv"EBa34*bze%PȂ ._Υ%n]}O-jbtpK RyjZVaq!_.VblPR#ԗ` k!"j1LBF  ~F'"f%er⌄ωP׻\c 3e9D`?D2%RNvʂvfTij/k!3TUܷ!GkzO>d6}efrCŇZ++ 6p+QVѹ(^~Ukv~ώ>b+Dp@]d3ǘ%ajXm &4 ֒k^Rk; gN}'Q<B_O4;e0H4'(ͮץJ"iTj]GӍ%j'bDF ZE*}h(JhIT DHBZ/ؕ)9|Y34*p

;9 䔤ڊ/GA)S%m {Ɗ=e:Ș%fZm[|Q ݔ^7; >f;YQd1!eM@k D$s\# Bea@0^KЪэEqCQ/qB l@M"𰑔J78ɽmYoaL Hb_D+KX ~Z/" d,5APHIǥ* 3!fRJH姬 & !`$i!闒{*w&oqV?|X3Kf.FUpLQaSe^0?#뛺t56},{/S@1.=_[໯YT4큉S;lz-(ДH"obY V#Td ~&B%@ڑ|VhN{<(s)0@3n?ux0@ Ҕ6ك! li V XQsvUڄX72xOJeKx`B<"ϘFwD`dFO.`@ ViS;p!6_gz Җ{.T,IE"LOA!D"" V>@Uz%:Rπ+ۀ󴟡34hEk@ş_[HhZsRj|y4+*_[He N#a0dv,pЎ%yG_n!Z$tjHòM:* gr%?f G v3֒HYR#, {;!t b6-vmq!L`[{jWi\N~6&S`|ohpJi? Ӎ9tP#R`J+PdTC }>.7Mo_ Dc0e3v 1 L٠ 2 V{=!<G)>yy~z'Y "~ }v+J} W>Jq&"$ޠgT sVnڲ/3,(9N墬fҖ4ݜ%QaQC0$@*ܷ*dϧ]IOѭ-u|JY>0"K#\y ʣmAE(ʾ Dv6@#l4ϙ]lWi}B1q1ͽaF3YT+m?@]Ō-ajpqnPk%CIjbWPPPRd?AʇܡAAB |i$,"H,'_PD@F05] \ @{Cҿ3,>޷ϭ!( TUQUEUTUQUEWya߭_ϫa^Ri9 ̤mQł{_scSڎ:%jka*ǁC[F$" \P()F ρ" R X) E**Ţ(HQnsfL 5t/lHgQuu |́aV B+(aH;u6瘕Ck_ Ȓ1PF@l(Hڋ1D%TBWpRv!]\ 'WU–28n1}B]+ bB\\pWBv' p8J к[G'Oy4M ڎo3o_~p`5d@,B4T (m ͨk ~OI66y<6jK XEX rbTEx?;;A8Ⱦt>VP!r@أdY#Oeyjμ!:TvT]ʻޗy<]PNЀ,{oBr` T @ !D8{|@Xd \!UIJ!M}HIJU Sp@9{_GeW&I$$!Ea$Fxg]7^)ɒI $TVIIZM)0H>URŐjf\Q,4{j_[/$<X@$ZD"zBZ"* af$(DAA?O܈ *P=ߘΫ_8R|ORyZTDC\=OT\zv@?U+Bw INX`|2G}Z.tM#_+ 3 b-b-pyyyퟙF+$Ît9fc᧤_2KgWz+G3jѷ,?q^'>y$'h_ -QUFx,ҜH4=wRj6>IiǍbpm<A&C50 vSc=rجӺs݃cOM2.,&%NrfQNoh}TWLT_R&OYvoZ|WOF X`ff_oMsץ$pHW d)B`ܐ,BX ]izz?}OtojRVNkq_\_O2"(G`cͪBDdpEJ-JZ@`b5_40.*mE0 (R%R@Z$e P`H2$2 BTނаF@Jpi0.݃"HF*.@F10G Qƨ* iAU*-hLef Š2QQBP)"F1$C66ah y *X)Paej(hB</o.wƺ~\Lu I0x*QH7nAӈ EQ4eF aKdbnvT%UT* )D*UWQbA~ZHA%1;' v#+)}!L=UVi4&׺HA_Д"| fq4Q,loMء Tn}8b ׄ` X,s6EY2 @U1 })B~Y#DDIي@ "4E 1P$&APZoc jl$ń~ӉRT*%JRT*%JRT*%J*JRT*w9|.!CfCbB. $Y`p1I4T*%JRT*%JRT*%JRT*%JRTi`e &y,8U=~5Vvh~?7~*SvqA^t /!NBDE`X$zHb-J$yĽw#\ߕȆ;ۺzT5O|~w4!1PPE PIGBH`>+SG;gBJTZZ23p<_1Or< A?KFHEfjVͤ&T"|BmX&kQ~C˱v! t …9Dn'3Hn<^O@A63i 6Y劎>=@Ud4}1r]Fe\ "Z!Y;YP.paՂ#_S9J H:$d/tղ^5 ѮZkj mZaEjؽa?FYhk{1Q\JeUEM@([u9AaH*i@.Pq#^o*Kg3/7z}LG T%T+U[4.Q?gYH2eG3s.BX :c oԁn|ƊSEL„"*ErJt%@ ʆ*!̦VsB`2kIjѷ#2ԣY5&6&%ѥecT0ɕ&Llŀٜ/a *6V0l7 E BZA (i^ʎKJΦA1‹03kiHZmęʦ&& uP") 9+{l/9PHnal٧/ 9 S`[M.JJvLM|[c ϭcSMZ(Vׄ[f44&3,I *Afb bg -!3S^*YV&8^H%Ym5mL(kuh) %!Ib%6jB Jjc1\%j^Q 4K\dཁ]pIFꍜ;MeGF5 L)b3jY!B @R HJ[\og{V`qH)a *F@уFd%J K9F/5r /`J\fc{z?:ݫ y^jl8FbדzsDc-鞚h @KԐ$^I$ &`l6ʃ\g& MQG(roU0AliY)^"-qV dˋ`$R^MՃ"j)ReI+n8x&RXit9$e۞jzPc)1>}Qv#DPDյ^Ԗ*p*SpeЈ1̸,ޥcabLCp 7m@P+f8T-vc%C Iv8 H -TsP\qf5k.N, @a,rF[Uo.ZRE.c2#g H*JI@f0LZ,]t0ױ*!p//ᩔ 0D/0G +PD'":2L =y|/kDZ&W}A}dfD `S7z"aRaWT-\~@Ix\[DC"bu%F0D*h``o^ sqDexT^e2 ,)z3m(}Gf|_hp?#N$ Z et=u`Fxz`Ҟ4}x-`HVV$!B!UUUUUT _6B{,. v@?o?1=s ^Hgp'Z8(3I#._OW7[K4Xl/ CCրq i6\ c8%H.ªb ĭDRL lKdE:7[DV׮cgF~{q]l-TxV웗 CӃ$vy e RU)$XRB%REkkqԻÊ I-֝6)@{5Ϝ;yz$W"KÕT"V1B0CJ,-&}qMl3yUmtTB)\R) !EP t M!B(5@B -:"iN|S Iǁ-Rg8wKslES1֖(B=iXC>~#B6*m]mR*gMsf˚!"b-awny)P^fB l/y9;X;g4:dWA E5(oY[݆kp܂U3+Ť2C 峖dhjgv3_zxPe;p3FvqB(vI0@3; Z5JEZ%&iP%Y0YMDPe ^HM%t,9 Frr"T(J+ I"! T9h,"Hk'Q\F tDP6F$ v}. `ZrY(HD5~}۪A65Hi6{a7T:;Uȏ'plXyߑ()(%eD|P_U:YSJYk5k jSŔ^ x7"L,Ҿ_K0b/ԺĤ2Vj`0B.0s*1ZUUi3SP(X͖EFr,0(UmLn0aFqU'qXUBjlU考@^HIu]0ŚKE()a iRIgeAJ56EH(mjQEIjrECZA$RlI <%.T#)i2J 6 0L=_@0dXtLQ{E{NեjqfթbQYKP CPJQbfD0W@lB ,҆2K~F3iBj[Qq|#]w;I|"V6F$ʈ_Kk+v"ѩEngزjՔͩ3dZXYq_T٩Mc׳Lj*̕- sj5Ybmzdhdsg)3-Q(1.טT/*QF3T$C.PC%($FD UHS$*dg%pa$$Q..(pV 0Am$U @%s $*- 8XQ* (@4%D@ A0bz6 0 dxԀI$*$J1*5K"J*YKDJCA)JEp@ #B8ĄUN4AIH\X@0 AH PHH   ""DR)+$+r: DT  p!H4GMV# HHD=\|O?g!(ݽ+ @c7{kGNMgru~obgIJԯޔT=TTMPlU&P~-P~P{ A*j5AUvl^>֨VX7Qun9Epo=>RfF!R* Ω(IzZ;P5W2-@C,&Tv]wE\;7EqOrPfEдSñi#q5yٴ0(L& O,t  P#mc^DDQ@-y ̍+U׺Pc$$; O>7L<DDc7v f)}r-%#dR]}XOHV&*[uHZ# m"sS %al*vxۮwZĈb͙izȍG3+gBn-##c4ۻC%"kkyk{SqWљKI)D %;JE Z=PzEj"0pT-WU ;P /m+o em :N]x1~߫8YζQbv&T 3 !`VYqhȒ>k]*|ZPYUC " ^OBV͞7x,u8AQ;ui^.$ŻdzlA@`4 J?-YproHyzָ v7,9{!JR蓁")ajoh)(#|jx]klj+Ҩ*,vVFѨ ճ{O_VQ$N ;^9Pu [pCgwN "%}qZT)S]bؘWRPJQA XI`) =cc,"DyWzCʗ\5*R9tݺ܌GN|Y*b-,E F$( l80Q1R)J A)X((C!\- lYdRԔ J.zpX.* %HT}^ZB?p6H &ɪTK{'틠992z,)B:-71- $nԴI/c|r/>{kxNittUv:S wUyu,lym"pyu|%]r" h*Z"(??:)$TT3EY|g;rTwBICTbNE(U(Wǹz$R7`(L. a.׺No tJ}/.T&/ xnԞWq.ah=_`eo*MSVĘ~{ޏnv gJU>eԋ{2Oc9uzdތc7 Έr"T0 i˞CE2:1wz-L9LCݝQ>|<jK\YRz{Q͚$t[G=ߩkmcOa1^v ]X1ݩ(Scy\3{~HPh uF?%_;i 󣨝<hyϓد?bM'Fs-6a޵mfIK?n'l'69P[]K{Nص%mZ$/~onju`xO\ƓӾ#s\o !+vb-lVտNGa=Qaz<;!GGRLqM)kZ9Mc哏 @X[=b#׊)ɩ8{J'Uӭ zY""Dq,0_n{qQ~ kthb~={bF/~U>q@F @]y呓'}~E>o ]vA\33X"7ȚsPނ}p!`Eŕ8lG RVզ۸<ˑ7$Z 2x) &#P7QeoDVZRm;uӡ9 $}oKiItfGMsq㜏7k__z)+4۪7N@Tu3(K?V|zuFݹbvDB,5 'ABS梨c ) ʟ:C XnsEԪz8G,z'MpI,L'@*̋!YQτr$IUz_D/M^}prsŁp]z@G( e0Coܾ%YFh`ɳ@HRs0lg r{s޶/ fmѻghdj \ XJS%=,Z~RQĭ۬L*9cN W,Z=YwE 凥*\hiK(]Oy;Ͷ^,:QMtDI@s-ȝX( O頼FS".aX&8]p2HY!t څEdĩQ*TJAQ*T|/fL^hv$a!PlyaJ~2(1Ԍ@ Cf Elꚧ~h飩b Mc&}Y*z_FWiy|Ye}ztغ{*joNvH̓(NcDFv6qg]G{E%96, XaA*Nr$%Vh9Ȑ"4^pÅE>+Լs "_^TEo [FH1' |zx1 7fObߋԌ0P-(AwH1t4cZ.߈D)nX{Q)Ɵ?rfPD ryD VdLVJe>k Lb{}Ox~,bb(EU(=(x]6p>Nx1" 6jpD-ݱm 4+xqj7^]ڮYbQokej37!M*|H弶Gp wQ]FglCC$0B}xYL6-΋DVŜ DGf `j9?8ƥx @7^R!N\(pE XqM wė|D#*{m9 #e&~nI<4w|:ڧC*6 "{o8NxO ]o~{1i O=/>v[Q}q3;WfAPBЀJSނ+ f?yB P! " (A ȤUHȪbH(B2!  ,"# *ȁ؟? X?v[R@@g>^cnH$U(OYhc$(|D*D$PL  EbaZ["?X׳8m18؂@ mL^A"/APyFakmQ-q}` ' x.ǭkyY[k}[ĚET< *P !B G[)z1TmUȴ8;/Ө3[U%!leP LFFj N[ò{WM5Ybwu~F}5A;Amr!,9k@A ܔnxl!6^4<]ɘ"ɃʑoNN~Y{OcvH2H=_m$#D`yMkWX @kW&>,U<`y_\|&]siryj$OG# ~UlCQp6K5 u} svD ²$`VzΧ!֝>whokd`@~r{WUI6$ Jn*%%DJ #)(@Q$WiUeQ@# ӾII߱_&I*QEHxB@R )/xa]oHID @G)$x*Le؅׵ pp Q1 "P P Zoaa{0  cj>֍J#s9U 6N\Rb}{ gioȉ/BkCe8$@#"EPÝ8Y‚}PmdP&Dτ’X``H AP HD(@c(ܰ>h . af0G&Db6%/P)P7A04cVj ExhI(*`I Q0k2*Q ~Uc|P h:Ca$dE*tW΍eHn엺A٫(_}p9~HmH֩h2NZ]JFuoB W[ \g[_Rx]fkr"Ư12;; u;ӧx7FMvZ(":Mu,z! U߿IRBBxDЋ#HAZ#DK"  E #EAJ,X(`,DZ"&A6mlI!iPTb$*GF/K,xsWB_.dD̤)R*[DmI*D.@Alqv" Ċu Ց&aMPxê%("Ȇ Bذ{52Ej.N\8⸙Ԃ;N"CDE#$brCre 3?*WD#"QT79\$H&d`ؠV PRV}}CGd$ JYJiuS2/4=~uFv;krQcVuIz%FA/U$! %SU DtA5 fܗkg8]V4a[eƂэc)0(- ca@DXJS![XIs5Ud|рJ3(&dϓuG}Rwȗ35ǿ$*#u&mB:. DLi(K26 .@-|-2\SFG\L‚Yq/YfQB&PMU$¡u. Q"KQd˪4a@rҒꠔ\3WJtQ*TJDQ*TJ'{T0fë;.?>?{Ij Y$$J,RE@FD 1H"T"00$D@" HXD" B0 Ȅ`H$l>>$OA#\ء{R=^Ɖ4Q RD\H o*1-'"H"a! $bI$"28U{9۲,R.&<Ȗ^d%R |wPp6kY>*h֡'rVY*Btg>eZ]$≉cȤ$2L"H}j#.{T'W(Ϩ$d'>_hԟU4+BvRkeX' Yd+Q2!L@zcS9I#[3!/Gz ߻j5Ȍ(^Om'WuiZ7 LuF þӖ sȰ֗ȝ5oİ@TIlv_zx~K?'W~󬥂xPaQ۠qŽ߬~ ɳIٸ:q$TQD,?p*glbL՜p{}4J{+N,0 `x|?tEqϿqb1+rvr{ F@ aߕƩA%bd 9=0LA#J7X"OTtPo0TP\&R>}кO{SlprTOejAZdw2F=6~KeԀnݩݎǭ3.EFFP mnrmd~Mt*qÜ͑ řr& eQ0LΦglD=9%S_1m`}?s $0,%nc}3Ry*SZbo|#ݒ|0"dq$#Gfeܞj@=5 :K9 +5z͝Axu 0" A Wo;'\T[58H Y ZM ;xV{m #2< b Ĥ",rF`9kI|8zk e5Q.Ûb4sR4CD j Lj1%P׭blB? |kbֻ6PALPA!_{&]~.]^NIK8J{caSI&+ӼA\;8QBB7xS/?x#(u ö*fmCҙD8Lt*. /ćtb~蟜!Hא7S_S⸣Lw[m$\yB)X&Nayܧf52WfLy鿮blep0֊*-S]P{.C*3G~W )R&vG0r:+Wt{iܥڋuYo0TYh@(SA$\nLîUvVgɾ h͗)yD!A.v< x;sy;,m^Xn) 9jSFvDSR-P=2@ )ēK8^-t P( XXxM<퉥EJ$l!KWb3ߍ]Eu5&ج\b' [@&Dϡ`)2#U ]$>!(uVv9 \%`;sl qg 6?5?e_ܐf+@f`*նݮlV팡 yA^oߊ';jP KmE#zl "+լv HPW۫ah nEKsκ֠`gj4A *dL UQ~˽h7Y[9nu.u ~@Ȍ$DrL"gWvV<]kaٷ15 Ɔ5E?(ß<Ātw| ZH41\_F|G+Q{LZ6xzw䁬{qpE!ƏmRbC!g$^S 2oCH8f;g1cuV~~yX=#e;ny1mR}nM$kh럖I}^w)GJg N : ~i:}*󨻇"^ ocNE^.N /~G|2SږVV{l7O*S}~[Ayk՚*OU,H*jFV.̮:RP;XC([(xsS LDm8EMQv/vc +  "b *(BE@9>QL{Bt%(#ԙ"_c1nSxU뀖 PrԭoLp9젚C"ZO7 YeSJ1LAԒ$'4'6MgMH*c֮f"Zj8j."*T#w]']ܟjDYCM-b8'>ktn~`H(hžt6mypHicyT!N sロw{^H}wX-:=s$m)@. @`:/:"Y1su>2@Az6XܲZp5"=0qBF{eZ+MxQF AHA9—p棌 !{bc*9m3n+DņѐAUB)&;s(?ͬSI%ւDzTN aZԄ=H*m0iSXW6᳕1w]`8 joD;PuGW(a&^g{LkVׂSޢ渣Զ X'AdDFDW39?MӬiqz5sVΌ7:٬7/AȩSZ \!edb-HR lrI\7wbiX z}VR=~6< M@3`3 iv Mdaү+Ċ.gA0`4H&$fU% Dy!øskF#~rO=h*7юeJ痳3r _G7 3T/5t):vG|9J\k[ ƪ/d 5hXXk1g+w"A&>5 tCjȐE,?Mȧt?[h498+A5G]iX/g@0j vD}&-#H^afS(!Pԇxs;" E]`y^ .Wnt\w}#"@*I()""6<! eMcJ2 "2 Wy [r@ ÷RWM{iPGEe1’LXIh*t>P&?dE1S{U=U+~jg^5,oؙ,F%r@obB-J7궜/n+߰ W-3h"5呬ߚUYِ?7 v{L18얨(~h-yBf=jz1`r yAe]JG!V)iJ!xR"+OOx6&>w^/'bU#1C  Ff 8m\'^dm *KEF# |kZԀ^HʘH*@@˪o)9k>Fxv?{\~P$"'(j)RY`RCE%HdU Rt(7Z)@l"ZYGahT/!z FAm{[.!)6!kabb,(`% #ڀi# 0B׳x,׫HR1"ZLޛ%Y7}`ȈdoKPn>]Kű xֱh A3:8!TȋK$Yt-os1p^!(ϿbЈF FK$V $H'b?߽,c@QGcGY|Ce<{IprAR% @W31m|i-Qf2c"e2 ҄^"@ I@uE#RpB2 X歲ޫgs{,(a;$'m+<4aUfl1M97^vMܦ5?}#WblN1`bXR9 !hlЁe->T ə +䴌`4\&QX t0f%ab,Hc 0p[4\+odZZLShț\RRkQ%RL.xX@[|]䞗P}q] QD<(YL x [,cTa U.zV ƒYF H`B@[bT`DY,RHQJ #h$jԡSwl]]5 H:CBԁs4ޖ[RZBK($$ AB,YBȩ)*D.\XR r"QR),X%Q K1AIT,)AcH=& GFEiN}nbA@4sy)$s3N?4]0ԆDFs*N e,9!WˢH 9`"ȃ @ "1F(RV,B$2*0,! "DbH@B*tT,"E !,"L:z yoppqdz?;PMq:(’k'0P"X+% +HxEK ׉Y 2P(F M; T`Z2.X^Wg{]3hT }3tumY& d$)J# nͻc85iZC &iW-l`ythRJ ``,H."ei7|frw8{,Mǥ=o1&^cu!ClD+u-@J)K% lxUԌ,"U8$YhIPb !#FdA!"($!$J A!@ ($B}`FIR#+P 7HD0i[8 PL"FXEa@ Epw<Ϧ룦Q p)K9?Y,2JegTE9SAlor^￑g<y\U%/])KSVw޾RmL;-Y7_񇛸:ƅvtˋ*얕y{%7#V:> jRʲ'JSkf}e!jy ~AJlh*?G/hB5:\A!lY!2f #L d0r cvw{sO5P4j+><_Kb)b !_xƘ_3G~P\H‹_7'3PYlaV|L+tFRF;^#~]}c:,aJv?MeFV:þ]e4Hsf`F<8wfA#%LOT0'4Zz3%&:0s\z)V3D!=F׋O,3^vd}:~^ogPڏ)'ՖPSq2`Yd ,7:/1 H gЂ}-=щ حZkZy?0 "@ "lsؚ~3MPC"HAo(tuƜTh9>COvÿ eo켍!Y2oiPXL AQS9.@8P@^lOom'sT@kı^ l$lG_ E RI#?ΌDha!=Q/`$#"H$ AȣBBP$ D`F(]?N;(`ĂIE"2(X*=zQr zr.espKTyZF%35eU67a@F NUZz5a "Br˿PqS1}{wYb9Pk\vT{8r$h$d(AS|CKu[Ri/9AW(sok @z`RM "+rZD PF}-)1.dT/,KIhQ !F$b```P]r8UTc$sylzt^扸[j*"- ɢA!9[ r6A"vA򊒢QPs'4w@9N͘X+Eq_qz_s\P"p#[ Y!}Ms4EBT'Tr8.\v5~y@DWBssxl(J HDx)b"<P::'ID4԰CkΒ.X[8PHPCP*npNԲ!j'o:J|~ 339b^HJYALkD.A""{YYhq^wT*gUGɹCIǏIԹ'wWYbo"'CmΤ7|_P,PP5e8ߞˈ*XCl_Â-U J}+nj̊}9hǕ_}*e!;0JuEc}؝ 8/F+{rV邞sW!z5`oŌ/7PԜ\D8W2L$DX[n7dRFLkH*ݧҕY>wN$ub@wƶ4~I` 0ç‹%ajw-J@S|κ'DZ=\{ 4ʌ \D3=Urԫbp "i];fMۧK;}ޗ.:B@+!P+Xk@ꘘL#U&"B#aL $W C2ݟKFB#I_WST9ܶ4!\TG˅^X?:_1AiZ>v⽏b*4[MF"(A@ۧ(ƇbF,B'o)$`eO7!Hd>~&0@ H])X5,{Mơ_wo ĈG- s-=L?Z:`F 50 ~G?ܭݲVdUj@qfƬ =W叻mml?[z^Wܐ xJ?~!HNWA؜PA *$P%RtJ(>px'o&*_KqGyb2P&ETDV ]0 3ՐbAm*z==J/ߌAQVA # ۋ * ' *@8o\96=Ÿx.v UNⱓH-F.0DEB +5s][T!VXy}SJO[FKZ< ~PQ6{OWyCÕ!K&+U _\x̄x>xP,+P cBK6M-t_7Ygޓ:$溜h))h"cBXOT\6W'v5YU22>e]Sm]oKxtݟ(u:$:^ uQI%W<E|V̱T/+\p=0MQ*VMsn֑T1 T`gpI"+pviXƶmf{koXF&I~"2:43W݅BkVtWs ]ٷ$wi Ĥ&)IbYjE2^rMhVm2xeι$۔Wcevb%Q$?'d2"N,HPl "?J~;0u*G'NyB--[}?Ƀ[[ky[ 2," qojۧWeθ$/+M`>;8k{֛W߷^ZwM$\8ث/Чn|O߽1\!׊ta .)\@WiL9 Ը 8w(DKG_nskb;|+k>Z*QG)aj֧qxŽi1Ry'VYjWg? -=ċk8|q)X)QCw6c\ӐCK ^ bgݶUrG>|0/=LHu%^r WlÁ؀eƟuW>EnwjK32xBF垌(>ԻO*sc}|4yȌ̈SPQxOk:wf"TH$H `] xys7kf}Oon]7*>0W ^ #D!JEpI-: WD#hbZZ%,A ńF10 !  (%QdDJyqN#P$` C ) AID,X-DD Bd# ~ޱ}/qnJHhmϲlXxUV_bWg84~7$&4z0HHH*.A]2A [UnQW?xݎԇ1|AEtGo!J!M?o^q6o#cP,9>t-(/'|_Lʃ^7_qh/$bm^]AB{Aw9YvD07@$g3M+"q~8ΛM\|D~oޭ+1SAaigӿ4?W`- @a`g bEF!\닂%]V(l魋2+ Tb5h@*uD"@'ن "@Bh\BD*o:]jzkQ 5}};;mo^ 0"BwQ~l=jfme|v ZkŐ*,D дU#Pʭ+p ?Nl@$I$F6y}M lhI"+*$HR!" )^2RJvȒ8#0]iANoyM)PC[=eB K}1>I&#"6Pyݛ$]I/%tE(ɀ=R h l@S8[ PՋTk:m,<%S6tF @Kd BSgT+M\x@E|X"r` :zf);,=yQ08t< 2,HzPH?f9 C`۰N/ӄdDREBB+Q;=ѠH*R(dSшji] 0 c $D#d "H0D1Rv ͫ냒A;k38B  @Pq,'jF B! !"D`4<<.J v~2y?>L4YA6 P҉d*(U%DCHr#(Z} Q/}&ĈD $XP@#ajbhLѥZT2!s~=&tz֚x@ㆬoGCТhܞo27BI"̴F[jQV*B$*TBo @I&tx?c 3˫yYړRTiّe00j 㹇5F$lAgq4o^1}.]}_k0ɗW7ʃ2@uL]^d\ຣ򛢩2|~Y]{ihRgdo#"/[bZCKV|IgXz֌M]Mw"+8\R4u%Yv \f lbW*gS|c]ĩuʼ{yrjԳ{{Rj Oy Xp΍#:> x e?8K!H1ptޑ%0%[-0&94%v iҋrGV-g]ԧҷE=FM7*gmr\'>!Y:ڰ$;N .* Z.×TyH=BBtHH'Y Ii}ŤcMۿ"QXe7"'Ũr򾁓ׯj$gyorqEA'4 䱀w21o]RD&ApL#.x\ 86@ )[JF9fh s 9I9H&a+F͡s-O?,.1Kl84c|?L2I(U*Vbi27@j5KӁ9jd^kF&k+ Zf)ކD,"1r@ҢD6SVy~a eG<pӪ 6ZehZ(BJ%^!eY 5%A`&TL`p1 Bp3:m=sf~&;[w%xy uCKy300 _?d2M5B HEҔ;3L GN.3V`yTwV~1,c,sMǩrX$J<82rI + 3L. \%Sα EW>s0H.Q^s. ߛhċ5~_k[PfC&ɶ{GuC2xc?5~.6A`$H8vD?׽b xkCZE%Hۦ*RYѡ- $kp jA֪XZȹ"clXRZ$`έE$n&J/lGA@"JqΆbB$P3cH&>s"hyu"&AD(XV}[N lH,Li[T%7H`BC|֙@@ !k"(D͌ $#Y4 SDdI  BD(Q!Cu8!]^{ϗLR&HCay<Ɉ`F[i{9N2t#J9Dk4HsQ)Sl&o q΢JQ#`mvg$-lJRP1KxC7vz[ JxlJIU/~ `NßH_[ CE *v^|힥:x? \AI6J@dVsdB$') O{y%XRH))JȬ$sAa$B@BFD$ DI! A$!$bBQ@$! $RH !B BujBB"HˎDnwVxxE?[Yo)~NC%8ze{4TPBJޤC5r[1M8 cP4ҧ̈Ȇ?(^K"9Iz$. j 8#$CXICi(RB$b,@a47$JEArNiBDBHN 7&mȋǂTQJ "E(TdPdEPZ4J ~c qatx]ҿ:X%٘I)-TFr\db 7 QE͗OfHH}/]DBf!vz(>b5fϏ=W o_J޵AQ$7OA5sNV &B8Qp.2a|25hKȣ"h!2 _|XZMfҳeᮊa@nEfHռAīoI$t`²ckclƐUUbcvZ$0?9`"~q6C/O}SU:݆qԀ HJLHܖj=ɈsaBf2 (Tđ"47!b#%0%G bŦ*t8`б*=,04%fؗE3ҨzP`Y@,RVxQLcLbh^ee PPA!! Rq $jCFxAQy*Z1ҭը0e3mYc!](*47-`S Vs-&x`#u"2cLfZDh49b)!C*[Vŋ+p!"a"D+PfO ^`(.!siˤB H73 4Y,fe FTΪa(2aH%ٗ%-:SZF\anS>]$Kh4UFvcm Š峫 hj2VTVb2c|4V2 ^;2_!!!*[(12ȍ@0 8ŒUY12k@l Q=Q12B%VAqUPH[4ԵѢq`CD`dK%aHBB #+a% AR]"b pQUU2@ [ JAUBɴl}wUzw{ lE"D! 6_e–FȮ@hU)YV )RL)S50eEr$㖢ӊI00~,(TQJO{K|H8nŕRt▜.`Jk~20Kt[3(D  I)2@%Hl {J)`Y"ZhԘ!KRI$`sj01!s*e67Lٙ++TfD   tVX Wx(VX` :`B " c~j.`lg^>?^UײuU|nć(|gTvX,0l"u~' 'Ego>G}$:1wqyDI$0 $MRUרmɛK[ͥ>ﺟg L- h`C?XK\[yh+CQZކUǖWӺE܏chA$""A[H?W0f (F+J }?i^$P`$ (sx]O9A@;Mm 2el,*7B$PB0H0H-Ph6UReJ6!,Q ( &;AbA!$"ă$C RL222"F$lA$% BABJ#*HSHQU4@*h e@)N%I`RUQ)A, , |`2H`Nܥ 1!XD)o qF׏nbvQB+eT.EF `C\[]T k h1+\{zC( (('j)IRTBL҈5]+)hZ/jfEҀ0(Bfr~ru)ZB#!7 N>Y!# tPkapH+""py 077 / zX x RCF RABj*,.`BYU#d"I@J >ԩ\" p^Bj zsN hMLNDADqtwAU(GTP7^BvR0ҥD $d e\8 TF$GNNamb52b^*ܫVqaiwc7-q8!0PBD RDi$UHH.1UBd X.( y* * G d$YovZ&qƈ$"${/"\\'T J(RJ  R],w_Wx1@(z?6M~Ǐ}?#P72E /=AQX d$,@48bd")( yo"8S:= A＀cy_[[[44Um5/w|&MVȾZcvjCm$(b٥0\qq[2Ԅ(I*QX9mhaGm#>E hrtf`qDx{}}%8(5(XZV XEsovW(g"hX  BijyP-4h>0A>B-w5T͚wj"F#8,X DE*QkF0F,/i)/YdV 砳P`V+ۯz pr%%Ba l###C{ !j,X%.YOK0au1ebJ(Ɗ.Wz14ZD;3 RE20@7hn8}bV6N|*ϫUx{#֜ib.vMKlcA՛Tdm6Eeњ/pqhk6_Oq5RadL@T[ʷ14P6 S@BHL93KQ&60(&gk+TZ!ٜu3a{v9a<:#ot?W-6[D.XXL9T{SP5y,c[sϯcˇs[%,Ry1TSO}Rݗ %~v^vWjS_ 5Y\%)};ÈT֒ͽ9Q~!Bg8gYCmCnM ~`kS>m αҨ9NhD+AǛ>-fb[~s'H]|6aeRu7K]B"vn26.S| óĴU15X!vB4.,0xi/9-~ZL r+ ".ϠSOz-㜗6?_Tt RwwJ|Z|AKߊϿpmY.EZ(+ȇ 1ջ`6b}b[ r0E& L.Q>r#ҼiUTS1"8RnAMTI$r@ #!$$IHIoڨ.6ׂZH?;)E"@ȉq B THli}YUѹ@<-ة3X0HW@ `&D"Z@4[>cA$TY gXs['_Y5bUh@b"xMb& 42$ po#]`qs{e$}b8{P=x<4,sECQM J`N[PF+⾳֐ EH"F!eBHDE)WŸrH@:!C#%9n6}+I(B "m \$F)(YJ1T@zI~~dhb)}D_>̲vHHPO\ƍiDPAOw |~gS@G N)8!8>o|O%<. F(LEIHH@#TU!*H,P2D  F"! d@,ABQ!YfJF, 0HRBVdSS^Oppc4~?8[Fiyqt3|rMnu'mi 45Z v$PBKQ ::9U5>ؚL\[kb~vA$5&%U&ಓ7qx@`~ _t7?) {[$~|l HB bWD~.o+=L @E@Fխ .-eDQh*U= MIhF^YmT'ݧ $EQ\)+8 'ݥ$V)?+Zͧ_M@HlA9OXp^ϱf*.vFi<ɠnj+Lba?Y@g]kY9v-f3T|)B0ӗb`0xū*|"7$#uL`35u%⒜NZnd/KPVЕ : ,$y X#x?]Oa{ _cx| T@0@R4#fpf#kYd~tcQ .мM7sqyxlD@o^G)z5_Ω,\I @I$HFH@`@Ff@$4рkzxeE_C)Zܩb6BBUl]E8 'TSŬq@F0Tm])e]$ng֮t QE=ͼ5ܨT$&D OsAZ`\getLg%m2*9 y%+ i 52nE:)>̿S]Hɋw4a O7'K x,/o8:A.%x;!Ač~Fƨ607{LALp!cL!˻@.GFwzB|+`Ea5P:^Ǘ'}?F⥢뽧ABl\9g&MhfDTMO 9\ldBn$Lmb.z*`pZ4^*W0'T_K^l1z}\tDNRa0HBnGQt:Ps $ '2v?<3 gN.ק:NY,|b%ʆY~!#:hڟeE̶ h[i)|@F/[pc ɥ~1Nk_Jmwb2ӛoݢ-]6um#KKo"Vˠt'i|* \@އoC203]a0@n׈(>{?9Z-O'Xρl4D t/J Hj;4q/~k`gs|c^Ǒd ?}g|ޫoiPu$YP"EDdbĈBzNwS@hVhdVK? w@V {5f@t|.(#;5k\=(:T{ 76 lS#fRL#EFڗ@x.U't@UT)wo$[ ^ ' j/غHkEO Нӷ'}Sr`u] leQg1Gj 7{ElME,E j:B /Z d{]L{/o0?0+.^!y Rȿ~HAPկ8BK@"˔v 6CoL2J $/򬎓AY\}Js{2pJ)J 8d#)@3Pg{QJ̡TuRנUhW^K6gf팁&yHgpíFwHF>sX6[ ~pK)QC\_#xVG`"&{0ڕU&oLd@(`w̙ Ze6WS,'{,b:$7G a๲ŧi@X$ 2< $Id#$( Dzx% HP- {UGE=M].?W_F(^,^Kv79̟7LE[;"ҩ 2,REhy)Yx`Gv HM{?y_ 3Bf@乑 HC Ӷ*7e`n"i|,RM3u8yŞcUԇP= *#.Z_Q'xw:ХDB^?l~;jFo9?"`f϶Ut+!c2sFTrQ 97\jM NDAõ-F z.TLY{uΥlKkrLo;e1r'ۯ<ѫXpߣ .(=H{k^ԣ*m/wg{wۄvPHU ?H߫ "KQeQlHcצa#^$4YdC(C S !LBuTQA&zN#0ȺPFL>%>;,j})prNŮ]R DD-@/O&==Q/,- IV!KZK $PPA$$gj:Mo}Ǵb3dNct9hX\urx+ <.c_y?&d['xfK|Bk5X#RRHt|4Ց:hU}>M>tofұ`ww{hru ɹԜ1쉴[mE?O$l`ՑӄL<5ٻ% 邑 Ef_`caW%G%?V q4c]W9Ҍdĭhe)h5k3j^FX<')36C{`FbX~ |`ɦGԉ qcmϿeS6ķ7uP_-[ )/ۊZbn?U69&Cib f7؉Kc% MTB2z;E?EA1$=\xpU&A>BOby4 K:%:\v5Ɨ&wZm,* Jk+FX>jLR ! "(=@ L45O}֯^q7۽Vjʹ$EfXξ (<}wO0^ (Ar'R1yx/ws#6S:H!B*>#9@w{po}yv@B|FtY PM>K0R)u9=ocbg-(ȭvǹFi/nƚ7ZX""\ā},e {V,TmuђXݖ;us樠u>\$Ѣ^gcܥ<-ljJ:۟Y@F ,9Ҝq$CsN}?}F}X>Iɜ=8F%8Tڗ/XyP"&[LPΣl33~g01dabOswhpa,XtEx9hSjvpC)Oپ|m[j)+ $a9QՂd܈ǚ(`*j.pˤ:wq""DBϡq;e"=@hNlZg#<;j3mTMŠ}tUOC(vS"hL>zsI8 )>ǐGrL1]HK*FUoz&87]?<ڬ̤%B)\N'~vK=%L E[ R9wNIvs?0 o;9?MbE>:](W`;*󪂀v1~ x^16,t|W:opEL n@$^yE#Ŭ7}_!,WybY_UR}EՊQ~)~YS.x"ȁ ݪo] N\ecɚ]`C~]߫ihB3iT퇑Jl^ʪ/2gjW#:_KBA'6>\BA*9q?1ɹ"n]Cf)h@~շ}:?^d7fr1H;W۟^OZ1p𘥎:KV"3DW0Cn4'ҺfI'C/ńd̚,ZWLk8,dXsCĄmrdvaHنf 9A~HDA Of"U|*:貺 i`?gC/P֞׹7tbkK"񼧃Ss{lTkFMg;0_ K%H{ 9敔'Fc'K-[h](E)K$anAmțmzL#NK8'=x赝o eWMxWPp8)FqBQ38Yn ;Á ok,ef)|J2iY?]-mhjÀV Yho(BtQҷE&n;R-AC!yZR?=Z/|G7*A:6~WfV:nNV΀hgyÀ$_@-2閿kqGIOb44rhH! ĝR~"Q~rsu v$n_cI@CVȢ#DcQ |W e^>>#" *RAOCLAj~~Ϩ/m~}jK湠z{:yD&C 3|^{,TD_gO}NBu7,ƗE],s?;oFEG=Y3Xg(!ăD{UCW@ "?C,WZ8n+?:7> >1@0f {=*v;!<, FLpW;[Me3[PuT_W&M[P׃*aޖau"/#,b `}α:"x7灴jGҾ( ] ؽo4old_*# UilKf\ҥ%Lk])fNGסxXB=O\8~pӵX6Χn\t)Zi9E|[ŸdF5Jo^;:9,7 @F.knB8 P60f>Tί5gfry/j+*jeWtB+y {6ɜ0[3ssgcG:9ȇ`\eaDckG} o[G'kCOxc}{mōŽjcS8_PziJ 5$^@_CŵnO#"8r44䴠SS%/PXŰ=&(@̐SP˅~FM'.Je Á(&?*/ь_Ly My c8Iu8[(7NxݦieT8:% 'ߙPU&yY718QEADB}B5Aӯ|yDh9j•ESϓ* $3MuT6Z3[e'\5s0 -Y ׸+m!3KM߉$1"$o@o7x{Vz顴$$E נT%P(xNT G`dm%Ό"9"Q;˽lk-Z,'m4x4S!igYkS 9Xԝy_O=[pJz~N]&OW-VF2VzeV!,g`pli[!ou=X CђAihʙIHO-P:°"tYJZn*JiO`W@\o&A xx3c)X-|J>1JjZvFa RMm/ZM';BExAVEuTćwP? K aL3GLPV.HmqMhBwC1`nK`bMͻu_~|ͅ\( fH #2ȧP3Hk!8[$Vm W/ 3dstv "_ӝ!\Wb{aT*3͗GՀ@P+KG}Lc7YS{?xM<gﮈ'ġil_y#Q(;d)0e&j8/1|:ڿy?J7-/BpǭӨ!rPKˆRVdUj)+{ʰ0UH4Z~h<*7 )?Qo:W#݋%]aQ.=߉[jTL F3=ƚPKfő5 ޥJqݛ8(OmB0.sZqos^L2I-_Qil uE慽(g(ҹT4sGޣc#Pq7yI(l~`sFlm]k8|!rh71&P+R{pjXԦq6@pc}cvK[@m2L( w%+J)1w#gH3FI1dL?䏀 z_vh1,⚭0!uAQc@vy^ܢI,ГΊA=lX5vK09:b|ք i&ma݇Hp?юEzv+ 'rih ad|Bf\b `09y/&+U6:yd~j$s1`G+qR/)(BUA>zbWatr㷀u?K'6QI:S%K;p!/Ja<v<4lz^K?Xy$\vsJ 04mwP0 i~:-ʒoeygԊ1T<(bgf䋭*7jO㗎zմ8bG@iAU7p9ze-LK9Թ<`P"8=); ho˾޻>rͱk:^?mCzNHQ}:.k5{;_:ɳ>Cl0p2y}r:հ``SgQ-ד;BUc ^I' ݺ_KXΗfεi\ `)=VpS&.EJ|cha{ligԞ#ٗ<2wLSO)țS`{䄕vxQ!tߛ_R}aZ4ٔo?Χ<obuZd%0$*TDl>\*ROT؁fbm|CDMjeđv Gԃ]rÆX0tk9fN0B,Q{36y|vG3"E/lcK$}&!, ~B{ed'ߎR96edc X\_ɷP|Xĥ %6di¼ Cg|еpzb;yܠ3{yvC1fV*jؿ!y%@PzCX#U`Ҽm м@hy7.aDճ6~M'{AFMD֠K2Xk=DTQc S=KFT_l߅{B#ySŮTr Ez5=^c\! ,-w pyf َL0 ժ\^M_9v3 !{*t B;/3ެzq6ʍMU-۪T"i1V"5!7X#_+<m% f`,v]< &qmL⩓ iOg@2'l"ܦ1ؖk#+ \zyaQJTv0;vm3[og`~(T8 t.F._j}-QG<gru,L`҇=@#uSLqQfX V:c1RQmǬW U4W5lC،BE,@HsQDftxV]JO;(чQ >@1ȣcoJ1JJ]T/Xˌ&ӼVsggj,I|'ul(b%X,~rNW&P~'x KGr+smO%?BAfcٱ @Fo0:3xbV϶C\7=0G@Y1DC;suV~OIu H\My;D\HN[lvFt-mv/6U, ]' 8XrS$XYhi^&RZ>%^ 3(=̅*?rl3Gk.q|5(.*4x/v_WNk7Z;ܶ./dQ_Q>lKtmˠ2c]/ -j[Xb[WPrxtsU!7+޺jL)h5DϾ:h/.)[@W1NRK,8NGPv@j2[dtL ZNwқ In*s )-i4j8IwM W + r{?B]xeSxBniAZS u-A%rw~HkĎʿbHa CAjZit>{g.gxj']׏/lׯir±4ɚU3̗/ 8ǴϘ F/yUTwWA 71#؟%V)G ۟,8V>k{$QoTiH+?n JS $)#PJ^Ȋ8EO8IP+/̽[ rͶ#h&S.?Qʉ0%5T.BQR.@ʯ/𦀣d8.#2A]#,4nm2_,Тqc؆%!>4+!Gŧ< 8-F?bhIX5'쒙FcK͈ՁdhJFĹ&&f-H;p5t6I;LuEy|}u J4?]薎 H w#}w'][ʄPXo#Q" z E'Yv˰G_!oH̘#Jٳa.f-xw# G'O%4seMpXXhs]5&)|-/#f5L%8,N+,QF-&_qDpNY6Y'\NIZ<ѵ' J$džNzOf2V[KRv=UG ] `5Ռ8:!0@[49<H Ҥh`̈@RFݧv|Ŗw܍^ l;oz)UW;ӫ:EwxLQ76KC# / 2301@33Iern23J9ہ(xvRJ>$YߗyaQ![!@Qu:xƿGn*vs99p@LKp = rKg] UG1o{q}^9]n]# UKE!|޼_Nϻ7(y w TmyP,:d,"2.<ŢYc].D /ppKg[QIHĐj. ?ܜk1 qVyymo rIe;i+010fob7k/;XY7~H6|ѭ^X! c)IjסA/Nz(3Y 3Gyn&(1B;3Ķ2ͥ%]#^the.'Ȓл]4 H4H䍯QbSQ9vwJ ep|U6P>W?[$+I4T,G[' 8hZK8'?;4y_O5^= nrQ>kX |8fHDM +.%LE39R"Yxz>Euh9X:y ꬥRhd0EjrD툿UMlP*y/mFEzUCg̝R8ZUݶRjrTdmVXYOc 0 %6<20Jdh(`V5??|ǣ_fxֆѴYZXtWΕW@*41/FRpYAֽͩ_o8 8 p|4CNai(>X?p1 ^Fw@NL!# RZ+]ʳ|%2q"/A7PIGD7€vJ:"1^T.\yȆQ_WCq83ᤴ7g JL%x6 զһ sFHw9TY 葀h4wV'1UzGf:4 bN<݂нtz:{9Q73Boh!FF҉ld)dQa8{ HA@q($ $:W*`i0VnzI*ʌCЋnt{z*nrfacyy4Y":mO 0+zBrMdR-P|<X VMWg;L7> /-A ֌ַCUnrÏ_Qbh2sS><3 rTa&g$,+6BaQbT9pѥa}_zA0`20F 3D`>[`2n|[w6GW}i9R8^ g .1x(:c Di6޶`RJ@L.Ojr Zqvu mPf,7ypfp_1ͮH-I,md)N֢!+f'7_`jE˺_kVŷƢ9Cpt+˗{a?}';Q䯑$(š/-nH1GE9nR 3]3߱5x7v _REE!QMOJ/9 PbH_S>:,)Xj`rXc4)t3aŞϔqHtdOaqޫfhAd[n|յRXR[e̓s1zԙnHfR1<] B5c Mξvlw}l.u+>!_CL-ڵ wP6J۞aTu/mfZ׎g/&#p'5g4b7.\3qMƛ m`4;$a#IbA3+ME.S{'df}Z$Ø%R$>RTV6cQӢՂ^ ,4ặ,k~$^ϼo}yMj@6'Q V/gymzv^ U;۝?(eٲ$, ʧ`<ԜD!0sa mhU:[9FKfslj=+jF,Q {OBbK6P8şW5&xAD]圚٨.L[ZjNL|Q0w@bAY3ѻ9; D<Ҏk1HH04&wTyl$.&(((p>UUM򅬆 /UU޾I<=i9{̌Ļm/]M<ĵ 9]!c06"DEqG9!BÖ́# ~1ڱ# ݁wyN[x& ~DL(ٱb\\_ծ@AJS萍;oKn&cg?uʱC~="ݪǻ1f:quy)>fhS,9- 趜 F[C=ъG>$p(;oz M0q? (d`7 7 pF N]INhdwp'* z~APl(`-+ NL V$%=-,)|g(Q](sf/,nNEaT"@g T6(Dm?m!-p^(z߹ kDn$"*ݍ*}5X1m&~c5 %h9mE!=2k3"D7E+J 5'5 KX9Fr}MCS%:-=T }Y)zFrgqywgfXma __+j Ԑp@p }:#ĪpNlN< L@HKΞ@%R#GA E !B@Xؑ7Ļ@C./){=l-FSya[Ɋz3 ˥,f}ؙˣ֝#\eC;ZA>:yKA/9mQlW10KC+-{yvoRP5[y7EAᢜsxYB2~㙷C:GC듓 'YTD!*HZ/^# z/ҚZ {v^uY֦z{zGZCssĘlWo 8-$}uGb9P84zzK;\̚kߟk+][R/.-DCAѝMr4Oi3 < 39$4>ȆTSQjQffJr|#./j9Qi!YFG%sC }LAщ\spjlV'k^a{߽ "٘m >F4r=v6pf "lj;ֽ[ho>]0>~Ab` %M';1xDHByj%H(-H L8U1a^0. #+= ҍ(k}DYRy(hT:a$t:jk?&^];:8~’i'\"q\1[~R.v^甛A{O‘zFypq8?ᏊT(lWS0bRZtXm'&EC7! @0 .[ZSjkU]?~}b/vhTFj/EbCp]z"krqW(o(I*+ozՄVcE4px ͻfG _Lؐ⭢HQ쭪f1\Nb[L<5v jF4pµGNY 9+I+g'>?ZuO=㫓8RS@X.!lq͹i׊[%0? F~[OcƙˑOSeԻ>z xiq$>ˮ1`>%7ghŦ3>BRz9ߋiBW)$PMGRL>#G1eKG7GB&fvtۮbjXZ$ +VCW/5C|$?Q2j5t"kD%ȓlI\7/p腌`>6(^RݜdP?%8ұܯdo%Ȼ uQ48$"/]( քؖ;9wԌr$5)<\+?ުgam pۚgqhCIM(( hfe:) ^3p2JatU 7Sflr^W`ִ:Fz2:V5G8/,? H\fz2+ilIؔeU,YfEI bx[?AT_E;T:0>rƠX(i2$ j3~ߒWΧ6Y ޙ2^&a8OrH -Ɓi'ڜ|&J gUQhyJaҎYG;wd*Rom̞MFZo@l[$gx@S#E|3鯀<*66팟9Kۘu[=vFi>h: `3HffEV{DtEvAHwnFLWͺz(. ?qUiZ3j3ѮVYZJ[ϒkpyXuk V K/΁?rB br^@Vm#>)'6uiTGP틿. <9S_|Ykȱ}O Q;Ȧ(|$j5Cq/kwŹw .s$YG4DZ7A%Mw7US&uw*6 (gE,M \y#~0w{]}GV܆ 0URzxT mcJfl%j>Z)ڷX@^ݻD%%k "_'el3N.u/o屴2fcίY(` d"'w,(Dڰk)c2% ZJ yc%Zd9ʷD_pŽ!oe0#k 4Ħ{Q1K-1æ%"/þ=VSUH:o<`Qh+GtLE'ߖoA*^:Œ-#5w>Y4)Mw ~5"C $\dwg7K;/QK3_/ý WcmBC _pG"28n!=*D0jv<cӊS 4j{]9y nBݟ'吮0t1Ο a!sԄX]Y 2)5eOi<xνMO?=x52bfth.)ST eM9/XORN,QK/'g@熪hi\$A 4{[Z[ՄVKWS]E³¶p̲}l;7g5- aAMlڗz>KׄW6>zڵBQnvS$^\v4^v.n!]rEH<-O0E;׉̔IkV$TY',Qy<\$}T}aXl|.r+cXD(Y;CuY NõCJg|@OtB:2tkd? p݋W(Vh Ǣ/C,<m~ [ _˧)o%Rtm*B#[g/$]0iQ`W>mHbH@I9&Afnva_Zy,GOny dcңd:K̴;?uyhQ fy nTYKxg('>WJ>?sH2=9\$5/,C  ]I%jTƄMuy_n9bLD"e0R xﴖYHӻt?)x19GfOX{‰qjeP+ت\/\ 0#W ID-]SCZ#vpIȵΏՍ`ѷ3NNG/ ]="} 9Gm@Ne~w?R_n[Eg%. ؂ɉ͚L֋_|?l0Tܲ<|hqVHkҔg33Ψ/Ecӣm4&G,#GZbD*KcU+``~RF'(um\q"F;>ReypT2|sĨ}qf)WrHo-F>ȸb *QiL:AK|!XIpmAt:a tIINj-o=%!T4?N4 8}qn ,ơBT>K#FOMnQ.`ǐJ @aepRHP H[2 D~|M"ezFj$]SCb:Tں$= RTfgFLtwj2 M+ &Σdl>x؏uԅTB\s?]trb]}W$.d<ݺiޖJ,:&t'ag>7"&]=qokeH MvDCs?1e|%vy]C馓j#\jyQ)M6%룊n>UILȳ?L -)TCW5r0'u2usxGbjmz{х[ݙWtqx0gE Ip!d-?w% Is'Ev"/ vu7 [5`l&R;31?G'NnOQڿvGRVWmπR7XD{O{+k>5JYNJ/쓺"VƼ5$,FU$7I2mʚQ\ܯ!/4y;&M(J_]ʆ𫉻w nci,e&1c_&0]IƺeF}.,t gɈ(tZHbB5;p#ip_gw1|ϕ&EH3r 7-r[$2wdsyL"rYZWjvưNFV 񲔣2#~6Tjښp[V]]ĎpP,BbuFԭ/jlYS9DBcY2lnϳ+k|O#`?h% j'ƁCGȼÓ5U}-  I'ǺΕxWJMtЙ1CodgQȾ"kfcDOKFAcsewyK7~ue_7hk!/{$_rLYQ_<çrP:UmП5x "wݹX&?=S=g=4RRHF~[Pj[Myd"d"ϻ ?+X 64 40UZtqS:$2toesj^[jƚ w<FDHRc&!8H^LUk-E!ҋ'xʺJhp&聬]i$<ƫ],Pz/)x\ {T+E dB f`6@m Np=]L >w˔{AM~(4pv;&TiVt@%zj+ɷi%d~<oNYMI<uSz_Ǯ2hV|% 8nmu? xnB)UI __[u>]U\!z 88)D;Oj6J!zKŝ.ϯ>;'uF@?=X}n9dXS)i1B+a)r+ #XpxJy>ƕ;EDL;oi* ,c?h^榒&˞Eӫ.DZR0,tݰo,/?UwiL#\R(H)C&\Q!ohB%B9p v>g:D.P99z@UtCG&Em4X`xFE:cm]sٖS NTR8we5l˭eܘ)۱3d"d=U$eARUM?;#䟁W؇.Cɛw> 'w>Ųt̊af=tU*@g\o$6&{ XuT)+ceB E$Ua]rӤn81;/j'rT\ӫ(u;e-QRernx8|LlsbLJbS,40Xi|kn`CڂML oSrN0c?EJH0I4k<E/LU%Ay) }A(6^co++2|nz w[t~:r$vi,r\w&K^X;/'2ğ3ULSOgj`  c* s}̜E;,jV'#1d0d+Ò5e`c\Rlf~Sl6?WW{|OU2 WiycU{(j*+Ok"ÅUUp:W3ݠx@_VJWY3V^Oy>AnC0v*"=v'*2o̲ՈC8f;N*qdBKtz+v9JyyCkQ$a_Ίn RSn*j}gn"<0-%ҫ'%~ڄ*jjSJNum2iS܈c("å٠ }omhN5Ksf./ XJ J,H[oB4nX}x4x0T7ɵBvpUAps]"%/Fltbn4Җ`.ަ )J I[=`/1x(13x3JWuF75@x ~x^TvJM?z&(.X_vtQ>\|d< *t(e#b͂\TޖٸnX/Rk +ooz3.8ȑ|CDЗDvHJWtno7DsGi OJF"vBXhKH*4bAtA'eLu!FpY Fk^2$Vo]-ZMۦ>i]R_g>[6+~w(I)xq=''e6;q+RF<#p+у# V߭8H]nSt _h:KgEVs٬aoE$2=Gn@U"Y%md +?R]L%7צksѪRأ'4rRq9݂T]ԧ4][KV)Nؑ 2*$&; ꢐkY{fуas`IGLƈ(=YAg +??PGe" ["!IZxt3-3p8F_c+VB k24 3 ?Yr׋b4B#)JEܯ =uJVYШ`],bYBb+R/0:% yX:Nvkɋk2fK\6j$H~D^\p;T_>u]Uoryͪ;EwGآW$U$V=MntM`fh*W16l ՈRyڢ9ep,XK"#9#(H6 J4Λ†,0Xw0N`TSW92yi1<_O.X̤z'{<=KNLXtytBeF)`T>K'𲆯Mz٩|&,?o:kyJx t)(uQ<\KnPN0/ 68*J}V|׻ 12T*zao=k쮳% X6y~yb3}MQ_zy;%E,}mB<YE ]/EoqCWk݈JՎ'{_ ^\~/eODz_AHw8L{_6|oH(?,txM7LG=a9;V3!Ʋ=w8 +wԊatv 7ȴʈc%I)?A )$NpYmkHbod/-P'yy/CQ)em;o[M[dli1im 1bA#6响½%9i^gb &(F̺0 2KyZKuz Qˊw$CŠ-{ş55~nK9>*PݢR+h6%D 6ض.B*sMF rI}N5H2)_tqɿJ{W>z_g haj~ޝDD O`p.͐ oxmrm>Euat >Sc Mheq5D{4+32/?9LcM훍= .V%\ Λ}4A =>G$/wz2\mq-(fe&Z'mnxG(m}tv]7²ƲFnEn{k5akBtqUᔫ%p}>̮XzB׵;2Aǔ 7=$8_?;ęayJyNI=-9Xy 7sPXLm>5w/)+b`5wk%X/qc+c/8SCVIyNP. ^\_nӧmWs%q-zг :oafsnq(t"% ~V1mnF)eTmqMP>uJ#x~< 3 nM`.KĚO7PDCpQm~/ɭy `w1٠aua} i1oSU7Ιx7}/_l!᝺qx17[j +VN oe?s?VZ쩔vNpo g:quG.]{#7Z OG,IoO|Ka56h D㕁L#UQvG9j5_fSqh_y糫lx ZCjm?m: Lqb$Xؐi0t+ c|)s mCK}n };彪q(_ mF; +5?f)-qw#B0EkBM|@D$zMZ(ru:)O%ɻĒN_h5g-RK1j>P[sh;J\Q*-:jz?+VF#f0J#L&vzM9gu|4jP2 /LZu)_^\m7y ctS%9GE(o_߷bnKk%pRc4?ȇpXs _8@el<"XDX^?6lnpK|qD4b#?v4O!bYKbLy2ю3F= z0VY~^N۪r<KHzb"/9#yAµrNo/ːQJTSXlnb|<'S̱s)!4;ޑbf\{u]J/)Z! _>J&#DqH8υ!3 D>}UK@6L>UjB nQ ).u~CAu;{LC1$HиuMoQڜ b7]P&hW[Q@&zn̻[o[6(]`VVIُŒo߲XV1s|,sI4P}&$рdaN@3aBC5)}H7J$r.$T$kap{u,=jB1~m%(~[_˥zl.9>j_ ]x׻ܻsr Jg ֱ|}o,HCg og g'Lz&J'ín,}Y vY. -'&0z;BϭNk!bU{~Q Zt-VNbG֨},v7a0'BCO!s6v0K>FT\(1-H;$- qGx}|sJ@{7]06N줸}=Hiwе]KǓm1u*0 }5%2KxpX0+{LvV%"G2+]Wim퐄)"I\sa88bsca, 6)uOo *pis3P,b=_TI9RmƆ V҅*w;o&_GMb`|_ bظ^jeX㲍ލ)+$\l-{ 0[&$FTq}v2gWT wb](8*{n M ۥ{ce1s黦_A9'-i0Ϗ>' v?(J~ 'fC(TXoKwoLu#T]rshA>~ #A 1(p.{;7,a~!JNU$ώmD4eHXLւŧnÔuZlq@Gr .}HƇ# 2rpveL_%{۳͋AOPGT;pQ{i@%Д9J:$<$bnnƒ_0A`(+ Bƽhϙ8<5G'g.'3Sj@7:<&w/DY|< $U?SArj}̡HixCi6EQUPY H[RIp.lגhrALK}XC}6 Gr=Q'ϻnM+rVz)7JdzFY7I h!n=l0xصz/ 3'bRW]D5k*4+T.\?XT)a2E#>eEXMU >$!`o}|U t?3d5&Z%_*at@禇XJo?fQO~b4=IqԡĽ_cH4sܑ鏂 y.AojGmf+rsZffb52+;4E)dCBr`&R [ebYv߰`n?5) ,-TK ӊ:IP=TKv~'Sw1zݭۊA|_@Q VeJ~ k0 Ft(vpF3OCx_bonG[ [e l)^"9|>R fg)`ѽsQXց0DDEA z4a5c1M׋j=%EcУ-%QavXdR [`.[K}.t!ś_Ms9Ct9FtT21hwDƆfjϨֲظd 9R`N ,!AY*[T+_?2]u]y cKv)mjaǎ=뷼΀Y?w9 .Pp +l&WOoSȦݞvګ ?<ҜJԲ +t%`Ix?ac2<}f0ǚj@IWrBq#$M]t+B'ˌJС +s_ XuII?wB[Y% W"߫`yjޣD0h'P}\;;'RI(f ^RMTjX+ÛM)\%^RiÖҪ[ ]5>~3l?.B ~~[&&h%/5p/_nS]Rq! V~J;j 8m/_`ä pB2Y-@ZLI }IZ5zc󫨔-y Ш¡]uX5`T{#/*ZΘ .w ˾-ßs= `RuTylQ(̺bP>S8L#CVPӁ2#Ttn DulOkz/ٺS+<.MWI5X4V G?\nzg\Cb$h8{,U9g`K>`JDQ:"܎FuEC=D&cI>Gix]W5 Ufkko[9;需c5O5;q~Bg!أ[]zA~}gh+"5v];d7V)51e /3^ emA @A}m-'94,i@$;O|HCK-|ViWtT=lDBt\HDex@{(SI0"%Hp5+rwQ350UVF鬃ZlS|@/K-Idh{@ HF2  H_/W|4&5acj5m2ye c|IH0Qͥ@r&Yx:I.ScD5M*`]!UtԨ,PFХ1 AܯmR tD!q( ߚ2(.(i$P~>DcㆃϾu~LY2> W`w=$w܏}g蜛7x?Absfżѧ.JvnEagsc>o}v#[w 6<{Db7ƧzJrd=%t$\H,~/t%:8_DPBm_pY4Y~GSG'cç ?sUY8 )?*k{~̨9*M般똂 D9m )}P4sHX߿s6x*-ykE2屋UzSFQ 5l7&f):IJyϚ4?dpa]1즔 97$xkƩdX\LT뎚 Kj6TzE9sS]<FѦ?2r=km$ӿVnfUΟqt3;f0ZP;g>3MO`p~6]j پj&{*X3lV >)h"GZ@XAvʈhQf0VGɰכ$ Sc&Dnhj.^_A|.V@gb%]99&鼿 _o,pX-[Ouåᖂ!^w1-Hoݝĥ"hfVO bi6hN(QG,zO?M_~}k[Hr%45.$äc)j^`-&. a@s 8m$.׆Dzq3Ϻh3רJuJPȗ9Kĸb5"Y[W݃&ocPgZ0 =)rJ#T^y`hԫI ~o׻)lW_L,DTN8h7=F3Q? [, v|A2tt;P)#\@X2` N}ֈ~1DŽ$֪*ˆ+ 59I?GX,ŕ6UVںA(؋CgřG'!Xg6Mrߌʍu}vKfv'LBE }GcCTn1EGyU9~y>.4$*ArS|2&rt8wYOп$)I_9؅_ٶpux3[hĉM#ɔ]mxG5 ?=qJ0䢖laC=#䡧1U+29ڬ{׵̓ۈ_eIR7_,'_Nl//y&y.fj{:eO􅝃~x .SA~ivW:-w Ѣzf}ŌP _5Z~zO*%ן[k<4{LSج51M~I=Nr~\a'65ӕt;E6VW1yӠ%J!ʺ(^IcLǤ RCڏ&l;j}r^` ' 4AK;1v}d"I ʣ3 ю+S;?kKsʰ[s37l P[k'/GL5Ɏ5 3ف"Q5wrET]V!qj'-}i}K>V{>jfd6?#bI]1ŭyϝBj(eujY4ϧ~ƚoю#]:s$ǁ6ATLdKǼ>r8\\gN0mPHr`4.N|083Pq /a7=w"D_tߋ&'?d2_-.#Ϫ {>5<-[vNDzGU'<D`,U-{?r|[u1Sxr΍eh"a"֏L]u%;nmQ _ZvE/ZetXQ ̸yJڗ9Ρǎ8Ity e+i >H <м:u~bSh5v}|w ̰I߇Q8x"k̞Qj{O*t=m0bL{RwSeR2(~#TiyqǑ}Y"̏{Vm77In75N`YEx ${tRVy!]E?|R@񰂫dѦ.1*)5xqϨ( $$D0u4>@nC1WhuCO8"ZS!rndJ=0c#'x ʊhѵX-r3c41qUP)jwH1>kKM0KP ' G2ӯ(:a]\?B;w"O5 [:%S79zu@*rW=kHy S8gu3mjTLRbS^CWgd0@&ƳstHH0bj;?j[)b~U=r"}cCAȒ+Qy ywHB1#too+›+P*m$C0ȲY[aY<@}O5g$Z2I:WQ V}4LCh#@exZa6^oe-sG{d!eƛî3L) vq)x6eI4P"fWUub~aʦp W[Lukٕa6S >2ttUVHF+lMK@ʅֳGwc,vW8] Esj-bw'uʰdZ .r=5zdc!^Zus-E PyMP٪:+vh^E?8ZDQf^esA-$O+NZ% x?^"&<-9^=?O~\h =V,~;.O,8R,K NG/'7庤%< Mz ͢-oSz[)j"|5zn{'YXlHXth3N=F`ɐfUqRWoP9d5<:TD/ >P2G͆~2nEI{(lZGr_;MVgRo3G $^6Wj@M,pۯI;r6הEJ@& .oNCY~ Cyo#@}-๊p12*Vcނ72i*Tj0]]­`LZỲ{,~*!֓V5$+5(NOeb ==E ^QOl~ y@@7S"ѫԢ,/BH,Ty(;q]6h?Ȫ[hon# Si)Ij{qG΅bY-M}Α hAFi]iر.zß|u1|Z?{jR;=J4Go4^-㿈Hk~xAc !EHO#L+7깪-=w?}!eV_E#du-fwowHs?}wWOp}Vp,W OyҼj]0 3tm%oKq[{E>3M;ZQTTg"/G;ಽyy)Vv"^9pI-m+hGEenDx=ݵ>ڝ]=ֳ \,'aHr62L*9#y'{}o)5{Rلb\c\RJ?RVkS*L1g-bf0:9wJ!qz>Saw.) K}7! ~-E|d!*_%ohMшUi?8 1,6g:U_ vyI^d~|O ^6-yG}i:{ð6lnwb`bO_)3G8[FmE/L!pmX/ ,ҵMbORLס׊٦ ET8 ΋=TpGoC{$/,ݴCNŠ\FxPhHo[TľNք_T颌x_I5f\NM W%x')b">x߯*+zA,3l "TX#ty5?0#S됲co9Ȕ^LȞ첾/Dž z4gD}^]K7^~?bR_C 9QYtjVG_צsh"#4 |K~GV_lHt9ig2@y<_Nj5yb=Vxپf&umzW}Ж@f>1رega=-∡SLd\*u!tQwê> '2]M41f|ZD̈́ȏ S@0џN=Nh%HIaPLrkgrfOe, kT2+{9_|jd|E?z+0uk~Y\ħq?T>=B*S*HXSܺ\7EW\>OEܺ5TWiD&a@8[߸3%U$@b9Q@ -*rbl +O1" x^}kn!cJe4 jqL2Zޑc,'j71չ<J1"Ka9۸Rq&gl['YQvCb+!U.?B'oԦ[fا5Z܏@tDgpy\0&܄_4i-ʍHE_-,6ޣssTWSycK5nL 瑻T%ugg_P2y1APڏ&AJ~ßpXvl!PE4lS;XٱVp9 _>N6}] o`}J嘶R\Ԕ܌J`}t?}>0ޝ•]g+0,) l6Ϸ_&wӂ"ȔNcևl"3$N,e._wi}& OMFq8q0!cI; ӵꭔ#Oj#5L]Zptdc۽/a/:ض__igL,1SY 9Đ1T1$HV=(Z?[?DMW~[YFa9`jFɐˡz"dn/j%S80P=-$R,{s /ڎ*`WREY:dTʐDIx¤5sCR D8E\^2ohgĺ&?QvtR:j ^s*\Q2s+Jh= ,c b=r|?ߠDw/r"b%pmͧ$n+-7flBUN ˁ|b￰YD_4h7j${NP:+7L]b^r-};j+gCt< V`ǁH)6g=#z!'TOkC| Cz6iv_PwC UPHdx0Y)>KAHHkÈ$,,fC{NI w^=MAcn+/8ZJK5¯+'qߚ̖~]h%O9TNZrT4yK|i)MۑI+L0  'B2{,`z'=K*O&I(Э0>g K'k~?pjMڕqrI ,/Ifhrw%EAPs@Ǻ94ua0%q8E՗~?›I.gZztiVr ]K} :nA;kV=YքZK*yn. 2'W}>]H!GB6oD2(IXB"B eOH]0dShE!J~Ŝ6<gm/~9&SJ5~ʼ w%Eѿ, 0TD+zItgo0lDߋ`f?{ 0tp$'\ˤdznp9To6N"I}/-G8)ythm4{NEN9 gL|a9Έ44:,9*rѬ_DxܣZ >_xl kN.aVnmyP, Т LNhG/BdNHI>^ֻ҆~$C%^f ~L"TkF,܁5.v.Of(*}ViC;p f*&'>&:^f Ft[˯QJ`b&\XV?-Y_eVbyyCR!ڒ¹Cb8ٓr˜a`"2Q1-L ؉ҔSXpޜQ@ }zGy&7^ "3z?c9-咐?(C]{4JW&;ӄgO$/rq,Qi۾_&쫵UDʓfIj-1UʩFԍI!f>*ۘdcP&MQjlf @S SFX57Xp#;C !!ݐ~4nk}w Bñ%<%0Gǧdœثf=W,3KFZ&7|H4x5RsI 1W`Wԯ7 ]n:.5O`#!  q"okӲqƱ&3Y6:f'u}<] zRJ*}bפ>KZm,F^1sH)wr.w{Y9&4B[Lt*.u$AZ$RDtF,!ؿSSó?YTYCkyzv"- -zYoQIe}9L$DFd5,*XJˋ_~B3|sm/SMB \ps} NCL&N( )h61s3@5L}NפH M ~dcyfYvz+|%?G+Lvxٸk@AcDQs qR'X@_ppGdXuΜ&ߥ,YwlJ!j'yG?2Bqh̘fEblZ, o>v<5^_P*?|Ӆ<"u ;Ê%  pHE|k5HMMu8HYn6VN W5/&&s>Hݿ+6_%x?5>s;:D̖͗$ CruF)`t)wa>v&hڈ6UH`NDh弩KG^'<5:?*!Y:;ThrGͳ0M=QeȉK|&9>.F;gۤ5f 'D}u[^8 yn%E#ϛuQm Ǡ1[/Ma7#7IZ*ZPfTS{YZdG9&2d2-Ӧ<6k 2f5<*Ow!eLldaBĕO*7g_Tb0qdGL%̞2xnFUwrL. M,N֏Epb]GÃ[S)V-߶Y"%@-al}>D*y{$>>W%`s}zvU7:aQ9IfMA/|J:V߿) cg1j)C]^<w \N Rx<^x}ʒ&J̳E;Sb̼)x_l6\#cy/&SNId*Rv=rbDx0U_|+kvQD5;("V7Ui? 7W7AؠDl i%{rY$|kڷB^Ȁ$["!$H@ţYMbA=˴(PQ4-z?!&v_fФtZ 09%y;) uMu B369 7LiȒcup_p51He{P|^L Hg9.C暰*4e\P22pGuOfHA0 ^{҉|UZ&e>JUU#g@ah~Q6N+u><ljt݋4:UL/{~BEBBRc+(ZmHR%ٿ)8NA"yKiJYޤU$&s;̓98\]>ҼK`.w.rul-!1:/ڃ0O)`^A*]?ZvO~YH̟=a Gl$$z啻V0ڙczj}U\IC*4>Qzz-&ν!q~.RSB%HB#Ylh`Q}mo>R]>mbO"9?Cф㼁9Qac|XD9pMG Qq{0sJތD(ƲgIȟKW"^Hmw:( 0!DG`dzᙉuI"|7ЙIGUDwT:/!1 C=-Y7M㑼}Y!r$B#)m,16Lt. D*Qnݒi~~SID.k$1|l.t}Gip D;)qOIJ1m6G3 ߰$_ ܴ,3suF՜V{h(~ *sZpwqQxtn[#Dt4VdB2ɚ\jaQyi7vl&9?hthݒUJy"=mLzل,l ^5fmKU7WM}8_I~E2bSY?3xŚ261g^DPv&_2_[T=M;;PZ|؏jAFjcySY4(J-|j=btlpr2De'lQ bCciu׷X"23nVLi[d+oܣH_tm56"b[Az} x,囶TΔ \sIL#iDQO?%}1N>@CS֛gy n=?;Ճ;愺5xoו ff.UC2xo}&}raBDyBXKۓA) 0䣯=B(,##:k$KڸD}խBg$=G75]Gmn" (Fv?7U07M+RN26򃚻/[MGIfChhN@^+P(y3&/W?BSA: Έ>F]~R+t+o$ _{a Sbq{Ȃ`~p_(jld秬N%T3WlF4\f |ДX_:y&(cgni;|1͂LCP|yƝm}>}- T ly%{%@fPW|LmwojrX;2[Feb6eVųx~Qa Y_(l[v#.ʕ*UXO^lW]KeZ׭볠FBmU]'㮑HBfPP`f nrk4r=rV]Y`ɦ Hی=+XL>j>\ڹio~jU9NϣLT-/ayN7e'lIf9% -itsx*P̶^&U]FT|28,XX320̨5%d_I'שFGM?q=RZ Ԥ{} |­z]4IX;la.a< -v [/A4dL\X 0-Uv:NeӛX &⎉ VSyceqH'ѫzU^dþmQ)Z'}Q yo"7ш>=ˣsXKl:){W\8l8?\ʋgO}NB&iԉHpCV(. ()] !v]T6G]u$̖5KU3%7`~}r9`i{Y|GpoW-1Y KDȤ;c\;Kn~Q3ޅ(q/njXs^Uz-礢|$*w ( *^PzhJFU[5}j'5* ?^ # btiNxȭA {"%~&+7(sy<<'+=,k⡮GӃ}S`<1E{C=x)ȿկ"̜> `Ht:w&{ro[slT"r=:su*#"tmH`ǎc$ tҲkm;pjMaaҕӗDQ1w$ys=|Dr3GLTm: b$-~Q-I!hY F2'.]~ oW6 qwuKd…Oew=gIGYja.c*}}G1J@sƤ_D&{$v.l]I&v{#O-SEi2}3oTCP| {Oj9ImiȬ96oS, X-LwU|O/%(śmLo"F1N`9:V ~WX`"ɪeFa7xJw=!I:3H <.tLn/NJσB TQ)p,b$N/%7`׸.͢fu$o!߆CV"!Ȧ_6]D7n Q; "Rtb.65-$Onmt212^e)%P`yFxs(C;d\[Ϥ(XBp߹:/8Se O[Įh66dyJ=?oV6ccgT"ڢw,q>3tW"O<?3ϳc3i&QPog*҈Go1݂Z֞EِzQz獤C8I[!gYɪo (nڤv~Tc=[.-Q5v2Zfx7es߲D5Tѕ5/.bXlz+}8uF4AOpәs~0aw7ulX֕ w2qT|SӇsNoUPwV j%YK9bc'`e,L h.K:"0ŭYNOzVV*3%8'x Qz ^hCy\h|MJ褣DZűtw4ϚteSx.WO^hN? ; ",i65MDóo`ANt1$AQdkҔҁc>4̍N.2PfWۇs0"^RV䰀MT&U6%Te2tn-8ttk(2+VWpzk̇#/rO8р ^ƸqRUNyS~%}6 6Zuf18>)*予N"xA}kKYAxns_,X:y")5tMK + 5t5˅6 Y#!AO!owf(3sdRfef }cZ:~K5j/\^[IzC=LFƑA]J2XP&Dع&H n_J,JǨb Q-لXo@&ݰVt0UFA+~!C m1|DfDMy?Ϋ}Nt'KI܏iKF䶧/CَW",E|H;>@[ v: 4]- -#M'kbIӭ.WџW0 K7ZAIo[ѪO {qv5.QoY , ;CSeg侒ucJwSҞ%:r)H p_qVZb2llѽ N.3 Qsfa+2g\d-xC7*MX@ZkY^lKHsNJΐ\;gNnY#9'f u{,f9mNXdAv6vN<{7``>@@!"tO GF..ءSƲ ZџƅhCxܗkXO UvF9w+?TzYzHt3W{pr8g~t[۠vYpRʭyA-Y5E[$޹XIMᴯ/>Ru #5}|iӥ5-iyRz0¾m0_sSDo*$JBj9i#LX[ԥ+p4DeTl =D`b9?w+Ũïۙ|cqk!F:L4:u؄P|Z~ fej{'E?=@8;k|̍ʹ ~Ͷs1)UPo~0SUJBP3d0U$``'z,MkZm>0#]VJ.<bɯ˾'.S/ slWNsz2H5Z?bN~!ac-Gv[8c\; 8R۹UС&.7_dЯ8S4-SɳZ͙pҬEyzdP$dSP+pkT.8s>ĺ%x(|#QQ?ɑ,Q;kD3݄h2EPUAPulǑ*H}O>d5pNŻK*)#VN? MH{. BK/w;/UrWf-~KZ#jzZ{V)m{5G$0XC1 ̓-% %0*^M]xB>U^_ SeTS=mf$,J]-P1]g{͗ZSJJMgW/v~RB _G9[+KZ-h fK+F"s/.k J8L'TP?KP$řǻZ  `ΥJ8͕`<8@kzT낟=, AK<[בI'۫[tU"@Oh{U2sjU쫷V޲,S=/ H XO= }E>Ud3X5RռY Pd`83:!\†28_ZH=8fݟU{kHAn 1~!B1;oS̢Fc#-GM^P̔8O`Us-m#v#Ƃ89 UL096?kvj~ȍA3ɋv!OY Y!re5Ȕ11!TeB'H.VB"S,'ᣟףN:2 #(>ue3/RA}K>9>պ*q"dx,`jWWb6!Z5 1lH " J[TImF,wU`dۀPP &tc-6"ݓ25<rYs$.Bxs"L (~; (lS˹׷7D AL@棢K끆PMk2kCco6;g]oS BXjejn1W {]'%Ze^D*S6zFQfa@휣ngX ;x+aX"лׅr4y+9nPfn(s7ɢ Qx; US1ax?<"{y[m_;9/-ϰX\(yo@r1EXhoS/~G1y KN4XԉdѤt : Yg`/Oduqd[[AU~4Rt³3Kx_掲r9bwdtLtq\s﮺vwъ mlε<0-t. U=!&HMKy;GMaN=7 UPSa)SJ2~)ṥo*ߛ T?z*lZ|jw B~iS?|mPi`v`= jxAKt>ԕTLW=OK X|ws 6М+w͹j(H{->8roݜb\_vCgDh%ma0kpTA4(ҫ \܂eo'Z:nĵ˗0[`OR,Ck~3N`n':BAY42*d0`LH%{AW\zwI sg`݇~5oN9 期%`xo^Pz&aNFՑH}ރBp_fvYvEgC8_@&H `H9gPAYWKŐL)nz*vvĩ_eшbT%T(uO-3RUa i+C;Tz:Gq`$}`d0Af(8s!@Xp䱬qT1+#_*җ9a*1~C4.!U/&j/%Qv^kr||hW1kkBujkQE kѴC˪8߽{Wq8fU0wte>ڸ[GLWoӗZuyrLL]3לN3.urV'Qo=z"gLpVj+U)&KD$vuM*<鮴^}X, tDZt M+APiH*/|pn\\La>Ԑ&*Er=rL4dZj)~7gڙeNPMc {uRDñ^EoC~7jp`*tݽdS58kxpqr,0QNXΈԁ.sKk؅ZmxxQ29*ݶ\$ ێl/@9od˻X I4@XPN5A۹Ԍ'W*kM+-kZQ!,kܛvtGwI|cMcb;_Bآ@u04F=2=jut^:DH(*]WiߕSꬍn vRLT(9j69&a%̱W>.\>PP$h)K; :^4Gh!D(*FQrн|kM}M@qZ?_nKYʏ^ۉ5O#3@:b40$FH00VUo7hy-S 4)_{?byQ>~VGd3r&lsHO%nw){l0IX7>Qa KA[urTeR^G.wI h}J?K};Hm籼t#" /ٞMt_mCR5P5X6S#G,se?T >"2 RdUi /&&-< '&iX:N[Ru`bB/> ExGUU;kѱg,?.wu?0[{z14cZqCH616&<k&gehh9^T чd*nՓieM?9߹RSuD5^79{yUbs>Axb{Z6uO`g;H'0e uZueۆ$|\@d[ k^h_Aۖە[㦴aHތUt%(on^B䈀`]Llw|NuH7o3Xt au-)AH&8-h:ުpUȮ?}~hU-;!"yqb@^hM=%HC:1 /94>ƵT{w9e˟N}5EInM)Ms2Bꖊ@"xkYMT\zLpV$2%0ꓟXHcun9{,JC ? kjXA$ŗ}M;p`pBo*:~s}ޘ[p%;UʎA,Y?6\clOݚY B \qnEU\Po?mXj;8Crxw{eI.hc18\FRkswfJ٨ߏ]2uisi(u%/c_Z3t!\Eƥ8_$"g"pcSqh~d9AN A#c.!p?U{ V7't\0lEPBNJzm8Z&EknI ֽSdH 0KSM۾!Ɋj\aHVn,O &i a0a /ֈ0B+?kZf[BM_y:4]w LYL/C,mk䠅$n .CRtxQ3+۝ȔGOWּ h:}bi @6K?`+|5VEU X~I3iA)0tߊǁQA"(~<ꗥSu7B_C oa O2r!1̐(y]eYpTs<k6zʮu_- ]+kMKD.5xʟ=;H\s/2@,xrX0tr`;_ UC[m ;Vzgs!@f4j$g/ qVʒxs^glk3VeiR'FdQdF˟҇V͠۽lj[džĮlgZL2J%/diḗcACeCLc_b)*FiPI%34:~&N2= 5ܲa۵Y 5Z+4W-OLL.2,ձ2̎;o'rh^=P&LrXBVB ;@3qPIO؞O~OƧcLȯuك\Yů+^%vxEEA͜u4/P8gO*7FF} C~hV)&⳦͈a#Esb8u/΍Ed^ZhlΞEb;JEtvǠ%hu=~6'};) CQUxB_:`1rfcdoGKzwI#-{!G7ˌP$%\\.ipe%"\jwdʘ(1&Pot#wZǰ%o`>Y؟"xPf0@W\ZoNLz͎>nDž|,%D L !ܷ&q)^<έ0vW҂YGGw?IwЌϨ%zv{;Tu Gr^ 3GgV Z~n,դ /$ 4F 1l?[xB\9mb2>%1]ǒK!B 4++*Z% {3M G5KV6^5y8PЫئ15?ɦ# ^cVĶJ#ї\-E;CL~RJ~٦XPPT>߳"rO^Y $)'MM또v:P40FX'a-oܦʱbEglp/>Pk U$ƪa|a$ڑfLTGmpfwMb2=utuG:Dd*z=P蟸FZfjG$tyĂ^`gw EF#ud9%P瑱w?gkM#BⰗ kSүhhN>\CɎ s0(dpOI"Dd\IaBlEJLxlK◯D_7tdѳS)irƿ;iP[Y3|";3L &Nx &ꠎ3aqlrŞ\# k$l5VFJ"tGچ?zՉ]9<娇+dw>cQwo.S.+{e"&&qN"<zA>0$ 6qтOE}DS@hکzCڒ'?*j-Cu ^Lb|(@O&-yp5&ۭ=O'VHJ*j*K?u,?U.cn6'Gik2}w?zխơΣ\,CIzV蚞W /Vu,J* *Y}-zpP, H$s"&NF+s£Y UFO dbPOVF-GˆP[?/Qv1 &Q>Qc2Q>U-7 9{:)GUFSDd3Z`j>{*}a:c%-DGc=q0uEEnwc'o.4ѴqfUąz<#^{J%ï$ZWEAe. oߧ cS:P@2xN1+ ZE7pH F SV pr/8\g G|->SLuvkQ)Z R ےLaۜEG@?(*z'ܭ|ZF-nȢ"vNj%ET~@ ru;qLN[M%MZ™/K_RZc5k:E[9,wRN^VTmr>N6b`gyppa5y !wPt*|{6T'%J;l$6 =$Xm{ǮBS 5jF;Ud]-_ç(-OH3VE11HVNuE aGj>^$n/~^ԜqAC'aY'̮TkZ?[!z[BC- u?  FbCʦ*$_&1JZՏQBhHrc<˜-|2BQ/[oA'AM\MH Ik`ozxr&l*s^=@$SYj عP'#‡}z>.pxר drYZQT" Aݬbr Y&Hy`FK?w͘2I a?s]t$gXXI0pm3`3MyEh^L"\E ŵ=7":损-*cW6F)wхf!M$Mh9)F1 5֟X8Id"&))%>yRX= 1GZV~T]r6"""z-6?+D2јh>+\rl\^JeD$ʷSye<3ŵq}TF_cX17 / Hd^ܺr]rw&'Q #*9cd^tGS+ Qt|.VqCC9&"73:Uz~ (]#.BM<|G$sF PPXҪI)rzf:[Q Y# o}!A⾊a %\($tk:iA 񥵊IJt5 RҰC4MYNYQ9S.)Uݎ ]!/<Ӻ.PK-_Հ%o1)Jӧtf$Jln'Lہ)L_SCeL1]?;^ gϠ@C{AU;x~њHV7zFDޮbtw/78:}&kn#WsN{|ݺbG+6 !y\*zmz{8?wf1dcG,=o\lZs`gs -e:[&.4# +.8LtQ,2g w}&(;ѻmُ?9!|$)Ma)?lS:]i3`(1psȼ-W*dwRolF瓾=e>͙2MtΝ ?E)58O}쟽BDyh ,隄$'X%9hMD/Kؙ[,Ga-$VIDlwl'q؀{DdH~D-5?&s5^Y߹s\7ڼ(_`=ɥHSBIH_ŧ"3) fTA HYmLx\D@CtHt,qHR CO $jJ>.{2+OY/i<>!M>dy>e#KoMqp|ji +ng}!.);<)µ,˵F}E+Hz_[F緊7.JV*]arП<90#u AsO^pVu~)A֟}RYe--8*IK'" V^Î8Vϸ><5Fs> PcuΌH2&D-[/l9#Gc)8뀕?xN\۔]iw/R.Wyu-EF`ȁ=y)fdԸQJ} gterĔRQ [z:a(q#&-6ϣQis!SV]I]Xq*I0fntt 4g,mzE@xJ|^^6O:6uwZ:~.0QO/Ŝ / Syau*wQ:%#Oۚڧ]Wہ(6FV$^p4Tڿt2*X1SFjj+}bg?%fD`Y6Z.*'2&[$G9(iOafL͏yOSQky]j~UBR;'FFy'̍+ߤ))Wfp%R 2g1HBt|ld2S4PIlM*HWZQ"[5 h_Hb(+5"4;{P:*磿4[0Ǘ*e۹"xV|Nc*ҞOة!f) c;e6SU ph_+ GQ-ۛ^1dP 9R1iK1k,fN{)E 7=;uMk7җ7>Bzvob߉_Ir<\,~)k.<^5<'j/}6gW77 s4/ԇڭ /]v`Mk?k˧ k0 YZp+&w)n"KRtl2ֽ ^-w{~WB)>p ‘* :pZs]{spа \ RO=%:-^C$Y1/Ugd5'Aוʙijzҩ{0ߦu!N$p0K>P_s'm0o۟ }b=&H" p|۷ ^ 32)v s%fFN DI)$]!'4hq_xJWS;*h3Lo ;}wIOAN&4Q^<]]cY{ga,#[9z(m̙GoV%TK6fLP$Y6=! (QH>-Z=ܝ Q7y*MF['JE4_#q$Ba @H`B#cPF8誇5,_s-(, Ѕ:6-Qj"e -.iPp:;i ɿĬ4]gf 9qwNxro~TUxg2;b<ʈ`ǚ[}"Gdҍ"MDॶ-%g O۴|hDb7TSrg4Jcm}nM dzȞ6˙ը[W.fatq EOq#۞V*1.lqnZլg혊0A016M]%&˷gS`%6߱`ksE0@Lh|Ї;b7~wEҥq+YaC@A{V?BhZSBYrqiGw fV\$V9*VڠqṖ^&9Ԡo[{sKS0#\c{@`97#ZG)zF}=!Cʉ$ItoP, {q;f0&:yq˫2>Ox@W npLi!ww"=;+XlAX#DP@Bg7RG#Jՠ*(e@fFT[j {[^g%G]I$-A'&~%,~vYp12lJWJLDG;q/Ujs{W BNAUqxxK(΅ZRH* ̉јPǐ]pԌTxFn}:C"Ozگ+:G#~/#ڃAC9i~-kv }?hGID@ ao]k9~)gၒiw 43kIHV$$TL͔Yݭ#KNnk[}²Qy%wA'D::O~Y\c`lգ#9CxS@_?M۞UW0y8@08^GgZÖ1[ۢt-neTr+р練*ֲ+Ff|Uů%P!3ØUq9Xa80Jp&' Րe"xŭ }}n˞uĂ /,3O&7ɡU!YLGz CO4=XESFp#0iٱ%b:'ǯ _1^ynlZqp{nYlV]3JQn4.N}g aM746U"DĚU A'q]&w6 33b=d ߗB r[gɲvm$ӛhc5+ s626]oݛL[DvXv JƥxpKy̬$FyȐjJX p'1W `+~v[|mC" ´uL!Qe~#_-ޗb\EV 00c s42>#ZrjC'@E0x)TVFףݝ0+}5Uz GvwY*B0)>eTFSN.ʿ~}iڏ~}!kId 4*ROڤnԱ-9ے}AqE 5\)TB#!A@M@0.0pwgzxݹ^:$ʕ1(cN'kXt+T}lq,(GB)$#~˝Ir!(Rʺ! )\03!A%Wȧ'ioT5!E(-aqyi?ESMi-`(&񹐪3\a0>*TWՇ O GO0E_O5<E6GSR#`) 'H<pg ZU,0_F :͑nܸhu^|L}3:1"}(f{C=$.qFrEb6v@~ oq nu71?&Ƴ#xSI:((~~{/j~EW5ROءFW֞KjTݳEoXv6r .OvBR)CFYu@Jo6P6?[[:~` o+᧬)~9uW#(]>,$\ϭZdp9קh!7ze]{*T7F7m(I4)І7g}??]c4牮YЋx('dv(J ˰ƋZ [Hbaߦފx7 g'V>yL%eƉ#(Ѭod߄Dȏ=oBW)ш^ 3GI ۍü1sn"f7Ȧ4 ;sRs,B 9">'E$,x36q/b\_{z?^rL`h%d/s9E16e)jN#Ki!௿FS"} K/lf},XY &n8SX`^a];l)rGmF%RYMKQTr&'VO[1$KKtYy0~R =BOL)B*s'mۈ l  S7u#<rm|Cz_dGMk.VJzqd0HU&^$߅D”;S{AՉ9YsvueQW jrU('|7 9rLskJĥJ5˪2=+B}( aޤ#n2IW-pkhh5tP'cT|Tc_5)?0bhD`^+=r%on!ΏYM`h yX7Gc*Uie ʋA_h͹!II5* px6K2*PJ3[.r1RRJnEqP(&l2!JPUHj AA&MUjҵۅJn}m,4(l`}7o ;n=iť?XۏuOTvޯmyU uA-H1`Lō!thىke֫d\+BcF3LXz+vWo4Emch2&jvAX @c_wBq1O"BwZ/٬-|Tc&͒ D7V.C Y(j|zxL[8RP${3\D݂ۤ0(֮t88'1#an\hjؼt,2F0)öʩ !яr/k5F?xn&3~JFq"X`o)~ȯͪ55|l)#=\QC>s!Sͷnnl212 x{ 42q(3fx18tl *9O8JgZJnKu~XBQhmGXe|?JLՙΑb,jN]i~闬O ydW̌6="p!To2-#i3]ۢ2PZHeL`JURgP`Io-?\*m1@W`/ ` S zJPUAUB(UCAL**1 ̫ٹM@xI,;}#,krwZCtzގ'Ā?cR"eȍ_]Q흘Fw(:RO1$zX`vAy<1-//BsAx6:@ʀ$ R E'~)@F) YR7*P^3[ ."8a[5c1 ݃&"w/m΃\ 6=|j؛Ҏ[yvI ׌[BtM-*|X/~=h$ۥ^q0L MZoU0f}6B1^ǂ+x8\| z+ ?PۮAj)aV%dwYgbآ Rǂ';N 4L:M5Yf⇶" j8Vν4}aH\=E~OvxBLxA'\9"C?F?5BaqyR?92⠡21euqS7B9̙ǿJ7$-ک|]YZdD i& T*q|>nIʪLX8__4eWCz>8͋k l忺Fϵݠ8p~9WXXޮ*uק3mGqȽ0_ 8W?-EKmc1Sa8;wԉcd/8ӫkRX٠χ bՌ &X9 AZeE}zc=}dZʩ)x ϊŽ*˥wEEy '\ct۸$65A&E 3I#!NC+kGnuz\o -}ɘO0S9 "k5"gt)7[dkcgS%$*Q )$rh4Ѥæ@/IGԻXKQ*2*m-rSN(8IF+-X6>jjo۱o^E;l\6L!,8jY|,dEAHp~#U|n tfk]3_X (~WFKvEϱ9@\o{χp`_{su'R|_緀ZBŶBkXow1kg`?D&7M%+#@eo>RON][%oE3{E1z| NDN ,.H 5x*:꿿_40x6ԑ?m$[nP~yE |zPzU>e.I`:4pΔ$WXq 1ӹQD;rѴi≠ϻl#w\zO?3Қad4ѕkƾ ]f ѽ1u#aM{)S3zlG{i{14Iѽj =~s$ Qg/-3`pgҴX3j e,)_ bUA.s3sý2ޣwÓ"<`Iw"JVD( H.1<a]9l_!W {yoʨQU#GVM!Ӥn\E e%*3lCY5Wf.pG=vgȮ##Y /%=?ۯ6V@TVEO=y\KqB.2 8X=rR Sf0}81Uh! ̲~ك&s/w"K7lW?1iCNf4r;5uL?@w)ATb/0BdDBnaawXp!sfa=ߙNz8IE&ݥQ=ܢe  QS?uoĒF#Diᠬ50 Az[j.뺲RW3'螊U?9 $sI g a3+f)E_thD<{ಙӒ?wJܡ-ۛD򥏡Y+zGsd~}h}ZDnoR6 ΟkOÚV4M2fB>i^7ZIuU119(Q׮ñ`q5`PUgD1 "$u2r9Qiӄ-%&H FzWjF67ob,e)NAcް^&cai$lHdn2~KGG3+{K+p<= pDG_E]lN?ðbbkt:2ybbxBp瀹(X+n<@0[ݣ@2e'逮sE %vgxٺg9݃ӗ=:SM kF!5th-SS uD7ߎof^-cƎڮ!ml&.QCV Z`UNd9)f@t^Lţ%U (ġ~Mٮv2YL5" ^IJp tlp(zS#Ό؋eOS?UX(eFtL$^\':pG*nUD1;hE?bW@=m[}/ Rߎ6ݸmpp@d/,.qk7nP1PH}}9M\pn1YxfOSWb7W l` F_d j EˤUñ巫sMONnϱ8,A9;fB+jdF~H5*'uBB䇏_DlIg:ZeFwY`D_%6$7㡩MwM }u $R`Kj|D r 0PBhh 0%H5E U E<˞RN7^lk>].3x}bjσY86]cWqxt}(I$0]ϸb~;_ŨGXբ1z?΋|3|ag " lpUK_B6id;5lT%g >`ˈM6=9Y332÷$ şo=ahB6NƁ*+v57BG(rǩK~!/^*a'JٱvEn 켪mK܅kٰB`E5b4ܕ,`c}p-Q%H{C1n6y*T[3̝h /o Kj,v+0!A>vԲN\Q?.%GĀYC:C? }VVbX .}k;DC" +HЗf9C_$!䬪~IqrRC`ˆEZm~/$d6~vڥcx4uz ۯZ8T0>&a5ݠ;Gu:.k=a3ff{Td Հ%~,OX ͈%Tc_t:/շ7R`*SgZl <$>UȿQn#IxfIgU;~2̌~4lX&JSլ^5A mH&BCW-;{"p$K}~.J4M~CCfoC~]B!ՀENJMa9-&w9Ka>ݨ{Eah.Vrɫ5YF /]gLZQ}hcbq_p'1$TjVD }a2?;Te4?Qo|l1>=Jcsx|-~s gUGIFa޿@rF6\[1ْRs@6O{WŮkD<|UۅŸ_] hӶ l3!| &T d?g0Gv. 36q_^LWT:lS5w5[μ|}*c+B3)HKQFeJ';w_Εv8gvRˍCN"vx$%)\p'B9*U2@oMwWRFdz3j}` kz"PEq}FHR 3LA^e4sU j-AwZl_d̍f9 J0@8-IΕ:e~o_u d `4e3ƥ& `3)hu?lWZHޝܾ:Aqxl"\q )5Z]ia?P2?IW(%7$ߤKoE;lTk;b擑ӟ6G s#cڽŨN 2 $_亭/&Hf+o]hH^,He9UEy4a_mhRIMiIr^j,wV |yRFh]5;$Fkg NKh܍XOL_,ۭ;q7*jш2{CSudUi'hR$-Pǫl8.ѻxSfn6#G|"+Gz_ռON"8\v퓢ãoNd*T*a#->7]]gHsTR"Bjɜ%˜+[daěT_b4!dہXi+T7`g+~Ҿ;#YW߯OU2t^h(/OkBN;Y3 ay7*gc LS#܃d1ǝ@“ʃS}L+:"4qgz_Y蜋M6jN}5v Q,,H.d7!AJ︟zԕiBlhg &}CeTM_EmUV~to]'zbڬ'C9%sڦYהWĞ.O8te`;Xe9|BW*,(Kdp>WFz9H!$e!<~ZxC|L͉l-98q4}9EX %-zA6/3.ki.%UV2ft<V(q g (D ӣip* d;iwHrmYQ*^qх'K ;NlpHfڑ1MOV@2E:ZtT܊廢PEXUVe2 w/Yqvxg/G9swu  `?P27ҽ}ZE7` z8d=/0Vs#I=!N1FfYF3_MI ̙3; c!4p&h`&ϼJ&oceQ0gVW>L[Ց+y?32|SuL¾Js|.aKyv g{$uӃo82i L|W#UX&-U.Q_ qz $~5<֪Lb#%x7<H*NsqqߖL!؉IJ=~b x{ֺ-4 qgͩy6S$+WJpޓ=3ȍ]u<0pnh6<\K U;5f{p2 WM%P"2cy_5bns%# *Y{O\W*N =mϛjY5Z4f !>ptpw~״6zh}!G|·E''~v2BĄn{|{qnAeI%2RlYTjs&  A,Sz[)+pѽ$WlЌgeFm8^swO׫͑WEBXD1*NᔁZ[p]/3,,!y^!VrԌpYΩm&C`CqFg/,xacZ'~y ?ScfGf>u}*+U>ՅOe.W~L= bnnZ~ϛ#(DtTwsZju4ۛ>cmfo$Kr_bNͦn'M]ս!/lr)|QUs Oz;Ld,( w!D:PϑlP\;rUy`fK&x E$O2b^ŃDB/]fc-b=}Y]_3"W3^3XS.PBeD|x PN`B{p(~{d3_Ǩ>Yf~>Y oŃU4}UGwp|(\]xݟi;5r.} sFMh5a7Cq*>7#?*Tz<[.lJ^x(L^Vj~V3Wh Ks.cDηBEi{`SNu8z̿\BQ^t Axu^pBF5U:(팏rNUgierKmS1qMH"#,~  Ғ,8N.VZYN=ӌZjvG82.(.4YXm)Wzy-d*Zbe&}"Khg ڑ `ʤsvfo<_b^hZ"?ܭ{)t.J ȀqZd/L[DCjsB9ԧzh$X\zNs714zrb[?, hx/G՜4 Ŋ0*?k/whԴO/wN.3Q-Jв*ČQ 8-zW|C.ݷU)kU~Z!6?&]>`%*#i 9t6H9,->9 kVc^* ڄGڜWE1|a^vR58w`pxIƍFnBB\Uܲ^nC,KK7fqS?fU[ߜ HHpIjԒ3',0_;,Nn:|/@\N{"?.smJBٛTԀR I8ʲU]ƠyР§ƑRTAm%YJKBH]!wZvO]3^3s+(@3LŲLD>0_G pwhaVyiل̔|zVE ]ASO) хUtQ:l6<) Rǯ5lH"aa m1ç崕$'vau,3?awU:BU4^#,* |6\},nF4JDv}@Jz N:ܦ uq(G L.Y]~k_Kޡͮ0u!R0㮷&zOJ\yJ]?GCT+i[/h"v}>6.nAX1*?YSvr\+)yK}YY$tM<}riɵpt {ҙكDž+KVs9OM4g.W&-'wh=G"lOi$p+h>dʧ$<;]ͽFJC*!;DV6ߡ&Ѯ*'K^ݳ0{3K4) idDD$`G[`&f]ضIC@> 1ZcB2 83aG\8+n&UM^j&vsN?\@lJ_4vg[^2 B,@8v(C7|DBc4r>s& Iž7ĉ 㾧!~7hF{tsV=FcIE4jlxz!\Īl^EѧO1$Z g$BIl5Ρ!`? F42#I4l_ѿ"nbRVr??9*|$Iﮋq*f1n&\HBlёwNȡ` k0#ގ3?xӱt'o*c1"ǒjtJydžDC}p5iXXNXUQzlAt…C/$<g*i_Kҕ\=4 j5 Jx+3'Tή<폋Hz<~-<0'ٚ@x2\Fm"$5n HA#9EmCz AݕTYft`~f"]d9vO03lL 3 1"dEf2Ȱ]ة9Ev< \;8eTXya0€WI%Uch6K%Umsi:Bw ^v]s?3;0?'o(/uL.fSCϜ06N@nA`%EW/Fj>zm!--2O}оXM~HJ>lểb &U0Eau{\en 6+(?F1veX%`k|E(rU^fp$|L!d,X/Ch{GIyDoaaWW9@-@ڕ@-fs3r64K_";nmF1A;|g&+-5*mc8O*ṔUㅓ#U^!t/׫Tc*r7.>a&)1}[x9n>㎫Ns5τko=[+i!lQʾ%Ry! A6C{ SRP$2GciQZk.^759ݢ,`u^pek&(# h*Ⱦ/ּ77b WBcv9^vu.{i_R>1]e|U1m :oWkE}'Q!JհwZOm]#M*fPr`k {E#5qF$L$}}°zi?՛=Չm( y ry OQ,.kVl(Y-Y9-4[da9< /ࡗPr5; /fd!lS`ue[ *?[w + OA\s Î)5k&pM߁B $xT$ {MdB~3ٺDվ1kl>&1\CcG(QWtJIJL@i$kz+DRM_#^\LW6Y?UYSƧMFt2EfB8x3qqA&'e|;~JD;2f`|,ӕq{<&Κ͡w#}T[8r֜ Tv1z&:I)I"53vlE>M&}?#܄MàV|߇OKEYlܓq2H{ke骜cJ^%RD* }20( ]YWw9u- >"Ur8.u%9gˎy`8?p #{Ct<mJ7WS8fvk<2.5jR8Ñ{C3k'*#cy5ZT's9{?6ѳ2̫WTԂR&۠$jny[`!dnE{N)c4hV6:;KZf^ 7>JDN%vGEm PQL\TZ>bGA\WF|lꔻ"8$odRUR52PW{?~ Bu2rrw`FHFAѴ}9|-]\iYo7(Է3΋) e1r]r=ߵ Gʧ\^)z=߁;^whEDvp,PD'8WG> 8uLZ80;/ `h3x26/ :qՋ_Oc庽[c42vb08K{+E{d7VTIF>8HczvSͭ{P eEROZYxm_$)!gtv4lm 6ϖNP \3k?nl"L5Gﺣn[R`r'F5#ʧ]5+fXL({ 6%\3a^[zBGތ,\|coaW(~~F@ŻR cU|y5kK*Z [Jȴ^j>(o]l0/ ^Kq|8)?rJamf& soКb,3%cu;)&RP|a?ӆ[^BmZuPu*}oWC5G ɰC^%*8WU WsR4.G|\edºƳܐ&M&*(vI_\k9vcq5ll EQzb$6̔5W2[ZҢojfG,IԆ0al kRt}   Ֆ L2Zb?5I44ogSL-v7SfeϏ14G}`[S G xidix/M_^eξT5T>z`,*lj@HTr`n!G 3t5BB*Ƒg,DN*ug`63 #{TیRv3!J-gqˎmqoNYhmqahQ =3iy?Ժu2ElݔHfh>!& v~[ڰpprFRwY8Rji#Cq/C4``1NEw%l,6fM+zĴCP+w<:VQ{VV¶>㢄h#&u A@zmp2mtZ3Z82'IL;2qp\樱>vz>BQvgjT,7[by'7~ҧ:~ZsqV/iVMɏtFs"mY2qړqЩ$U˕bbDa),O4@' / rdAUuh쁚 H@IV=֥є²In ) i751!35; +xLZ_ #e67+6uJ B^c~ 'e9)-\uڻǟ]cĢNԅKwzwO4L0D.rm@_GCP"Oףmѱh٠y>`̄ >.P 2W{Ր /9lefaT-2YxIw>@a.ks ]U$ '1#T/ZGq]YʏlShUQ.=BqӗdC7").LJltwm"uJ汞̲?*Z'ؘZTWPY;C8܄j|!e6 E.i mB|3^$r` !(_ !E & Cɥ 9q1#m׋e@.%~};ѧ!._33Ȝrk;e5qVgtCg݂_aj+גve]x9#:O&z6AfzH!q[Ӓ=Oc5ćh;(]G1>s`bÏtݖKYȰoIdVT3l[`(ScJ]X+p*Zh.NXv"9=@.@iČe E\`nZw\󵵱<9]ƲӥvӾwN du#Z #zS:c{Gޞ${c$! U{!uʶ>#?ԸʫQ1$6%Z-Y| Rδ_˂[1[lYKf5߄nw7pWN 酆ӕkT='o5z2C_}*ЈԊouϸ*A+jW{*5{ zњ]+$owϱu^EȠy<7"tP9+=WIUߞKv؝1څ)BqBQOz+]qQfdrxMa1>U rnn˖RCR1M\I09C.ߏP? W,ǧ4vݟP"'5mz抟B{'_* e'ۄH`|g}uYďF_ Җj$Pb0E`j^wz.EA-|6 Zbд{V)cY~w˓(7yK \SC^e6waTpP31j~DlTs-hHEccs,$?>7C@^˓Z!- H &wIDb!VKKoV-`kR8?lYkhJ=[I:Ԟ"d9-*ʧ@?SY^>Xkk琫E44D\Ik:4-?$~9-uTKilncvY4t?/6QL[}gof;)TVgYҏ:)ٻTBM޹@W̹V?V{iZKT;Wgee[BDph(|lD.G'^Vb RͰse/c|orw~ (ҭ9g &%iKVӈ >h3'(ڱRzMN߯^ `ή\_z+V4{5b7G,>nSl?BuʫJԥVS]mhmf&<)ZϦ]{&VZ]l\P$')*0Mw -q;ᤅX1rЄz"[fdG3Z󰱱NzO1&#!ŀiǶS7fZ/0@1Ar g X]橽dbkb`.5X{2?kQ΂d$ s-(4G+Ǹ2 Y3p棳yEfUuX>6ո>%~z_fryVSmMi6r2V 6ΐ:ïcYNW]$~E(]{W] *='-<:l4^t7I{x 9dtMp 3E%uhrA~~@j+C*ԨqE)G'&$u?k򿛃Msۂ/.9&dc# h}/9"]=khVe,g Ara.?dsIUD9O$ {J9=GdQqˉ8ʓ43;{V}IF.U1 ٿ?Kִ+I%@TJDp~\nu2co>"/'w$#xTri(^u{0"/|מ>KQ9Fr[9!H'4k=/0Pš*8l-> 'Gq9Bn8SA} %8ߏi#4\'C(O]\n ` GsH"?C%Vi&Y 1y5@Rws-c,Y)'bɑuȌLm|ixV3n;ݮohÊׁ}ȍuhAUE&^H&xBVǙ5J'Be1Gnhr{zx~`Z#GkeՔzD-u*sTv7\tzԂU] )xA@vM$Q&uXAMíeC$]kdcn_ HzKk$,g{Ktg Fß#zJ(q32]q VdI9BE qCP2kYP1e޶{ybk' T](CĴh ipb+k])$&Y% 2j.>*^p:Ӿv;w^?TsӅ(nY黁)4>gv{<['ޱwOߤC_:;",TWѪ4P0jA694b$j Vnb#-FA\/$=IOOU`R D*(1%qHERA9孉V4Շb]3D<*}ozW=莐+pTo&ln"}e< T6z[wta4[irq1PQwyd*`ff~0Bb5;|WKPy=]x+h۱ PJ(: :#bmlr60F)VIbw]Tvp>a\./6yx9LxTA_Oȷ%3.2<Lk$QMgńsbD=I$2fzFS{c@'D"P21Tܻ}R^Feg-P\hp~Uvj(S As.1m-k~g%'#r1"#F"`CJM-._ 2^rH9lR+p)?r;M_S 9E N8ƌB@gW+gM-؝hx6f}baYineFcn2:Y xmJ^KgFeI,מ&g?-غE"}h"|1^'j 3iEv *dW$nL/":%UBtݾ'G. %f2b0Kgk3L6;ںa/ s&Ѵ_(˅tL}OMT/PDL%A .NQ{l#3nXǒL.3BHd/nD֤ⱊK?nAaaEߛl5;am;A9UaY)@6u7Ni)UQZCJ TBd;seIADo֓pvԟ&5&_`3UD   uF2a'Dw?ĝ_"␿V\3g}=mlVM|)S~ &B]e3S5)Q 5] sOï䜭o*q|})V?IA<47/Y*)eVHI| a*װ7Z}CX} _W + ءS H/= Ɵ^%m5@F嵂pn1m'| BؔMbE,ڗeMdWjB 5oqF) h"/mIY 1I PVHnJj\[\1vxWmjmK?M4kEЍk^zTD5XqM,篴{!]HN/%9&–-V6SINIuwAITKji_VG͇̕nԨ wZqU*&Uxj[3|~,{٨%!/9APU&;*\;0e o8@ P̎mlHйQ+4))t${s$-zJ}SU5QqĢeج@E4'uE2 3 wo=v3@;{e`Vc\}t,d8wzWq|a-"TVTо2?zІ^q%B@r~?gL.xuVk]hwxf뭜8b8Cخg3Jue`6i?Žfzi~}9 曗[vVZ =j_\tq'6ZQEidK-.aʱ ;ೀbA۽i!J5˕baNR"Z  2o$;vbzmÐ -U > f$7ܐ9 kbԄ9L' EIL;~}C EŸV~D?Z,#ԋ(i5Ga`KI9Hr&g*P [ Su\#jslc9I(|՚eXĭ8R Q00/҈m!a%>Orټ%(X=AlpliUaA [{]8^$tӞ&}흼5ZU'}jѩ+~K15ūҬ?vX~E%H9.0&xM"ǵWܧ,C y S{m-.i6A!~qKnY#K_zx?zrHs'ed.!/*s,9L7rs>cd ?ju,'B&^.e:%d<!DEa,>/\&pLu^]fYnʊ~V i l4σ3'=;7 FKvv. T q 'IL^0r*no6$ >qO|1ˣܠ:!iYfXuFKК$#- }9_%4lOg>4tb^Q pPћx+tƼ8;?b,#JZ G*[ 9&w@9i4w%p1>&\EB#⸍SQxsQyIG43}Vgiٓ.+KG@3.+ ETm(0"KD t~޾l@ļDt!ҧOܒu)N&U"s;yQ˂Nd.7\kexx#dCd}L* wǏӓ8,9fY/{h#3u&a-;ǽX#(1ղG]M?+k`WiO{tr)V|yO}ˑM9b윉i{Uվx.?[OĪm G8z(tIɥ#.PkG=c p3P- l##҇YS<]=xD,ݷa38ViO[S`Y/X]F+1O.J]?_keZ1bCjtr䐻#}ڬ­Uv|1T0-v7kPI ֯f탛@顬&HKSE"MBEH+-0THU@ M9lP( ׁnh;@JPCF X8 #ܥ91rnF6D}2"gܛ<-*|_]oМaYE_t$$0?3g)y\bm0h]02cfnPuCBCk'ږ$^ޖiޥ!F>=CX\O1~JGc57\8?g^ܯAcܡ W 8fI6|k_^\m7O;qf [2Uvoڳ$]~sPZϡ7bZ^4ȐܮN\rǠKͿAB8<~kDle9A3aņy\T;{%&lL"N:I=WN4B2.)d p~rP}[ ̿ZY\^?ݯ.cѨ*-?}\b߂)DLUqH'߷Q!݇3G& GƑ ޑp=vB6h@qZOCR ŸMrؾSƵbGAv|x4ALC P6$Ѓ̺Bk=NK֋ϔ>v^YءZ1-Ge޼@w^Co˧k>Vs½![+ʜLgi[/*q#A=U*l=P~zLH@T|$I((}scsmy#lbOi: Qh}`ژ\5d8N߇{>yj$X7:D"鞎-Bw\{zz& k\"$0J $[l"c20BQZV`<b"CMYN/ա*5̂E*|̄FGJ"c-/(T# ۪1B)Wapd,* ~™+[--L8UyEKHjH# T C`js'-<]R]YKzDVkrԼD;MNuk_dZ7XCwӳ:QKn\00@^<=ϛBEm}cժv*'Rֻ >OOT?L5fͬ6K;鹾 a v86K?aK:jGC *rOXϚ>nV4X=z6AJ.px&)qxі#r &,dX969SnBk90UYW/_{j=(U3PI֭%[sMe$䑹F,8ShiPxXU\pcM2 Kz@m4`{zXJeiBAIΌe,C̋}@g23J <sm֘ږ_( (J 9|-OQvjLETxd4 DI3Z QTjR⟌)2$62Ėh=ےB̻4p>yrƐ81+;5Gngϛo$隳5Ҍ&>\q;\cD{ /I1ޘМcčPne$k`_^栗qoX=5ӪEz2/=h>OZMzEGilЦ8ʜKc}pκc:ٯ*iRxY6p'rtC Vf4ܜmQYcC`B>q^&kM0^C$ mXbgxc/bwHrP1Ƌ#MX,C3JفXWtv3Y 4Uu։mW@zm4Ųn#{Y7 <ƌp U1x]A [C!.öƃtr18`A~ז?6sf߾|2a,VxJLJW(b Néw9rEmrpp†QHY4I e(h`6L+X/Y\?rb)qj*AETMp§y[ٲ1^4*U'0P'gjY,4WS kЊqq 8`"*БIkڦ8S#JnPzsMo_:N0dMg΁;`r1uw!1nv9"̳I 3#.sdcd1- Gp9kV U@T PC>}Vii`$ Hi(mqD4( $U6lUlj[`B4JFMT (U 8%>A-T@h ) 5I)Zf  "VEPPP@$b@ (RhP(  (Q@Pf[vM%B`.C`=$Z65=ؽW]34]p]|Cָܹ8r$ Om_}yA=iwZwJ>Dzx=’_f]m-ᡔ ZQ`c5|ެre [f)|OeyrI|׵o%zU&/wTznmE;oG{Bj6܇ŵ۠3Ҕ|Нݵ=g^ si ÃZユ64 ϮϱC[5CgϪ c|/l@JXJklѵzdim'P>} D>T}N -rm6,U)i:F#g1@Y皜%U }ZlkVmm1lѫEMP4jT=n0R5`@Vwn-ۃ\z9HRS6٩N|:E;%R_013)l|&"J*JZ"5 @PPl!B@DʅRU } =JB|{gFTѠ%5Dӎ^eUtHP@ R$!cJ@VJݤi Jw%",*J%O*EB@P{WϋyUTEThf .4l@J#޵PJTʪh%*r%J [*BHbNWTDTM; T\y-]yt·>˔)|}v{DQYuP(PkE)AZҨU("J($IJ5(JQ@* JPJ R6(( B*RA 24h M wzJVB AT*BETUP$H T(H h)J@ TRB"kH(P[5AlE$i ʔ*PklHJBP(PID$($j)AKaP)* (lF$lTU 3fPERBT$ ((Hm h JP($M2El@d$mkeZ&QO<Bd && F#&M4J~4&L414#FM4ѣAdb!04Ѡh F@@h@44 !&F&0QL 4LSdjSe?OIO2eOi=eOO4LQ4ɦ?4iOQ{JzHAd0#F#&5'CLCA4)L6DڞQ<=GISM=4dl(iJD Ɉ0&04d2bbMѦFLCii0!ϾԌ[=k|{{݇;cPQd9E1dcZCcKRXQk?z㜎~©$:99rSj'tTXOOiOI(0I.Ol=ݞN}_y==W |׋Ǔ4=-|u>w{{wgp_~߬Onx|n}<|vgzϗtO1׳~M}>ǹw>+0!$#jNӋ\Y('wv\m7+OdSa?t aEy@@JB ;):'rN̏=*R~Xl3yL?CۣJ}Blye KN7:+:^S0XX!r&1hUџ&-# FIxk?-Ϸ·:=f;I]Lk<tj<.=vmY{f:^_y=jIy }b8ƻbuϟGkk}+p-܆-&W+15c39%SO~#C?X@΄ Q=G8!uD{C:Ӵ~R?)@*U~r49*ȡ` pq=ߵR10$9uH{vj`g CI,'6'Ww2D[xZͮCI|ar3GvRxsʪ*{]LmŦwq5ne6DvJTF1WI_;"k'kyr%;q43ϴD/Qү&kޱ682qz 7v5i¼V}1XΦk{ImΪ֛*ÇYS*}c[[DއcC&O蚵6Î% 0K~xZd^3X.xIԹĕ8G>%Х\% GH.q,WmpˌɡH $6.p$QдXk'O};lQBK'k,W}[ 6 +;K]w[EKv>jM7ΞvoY6Ps$~;vaR RQ<4Д@آ2$H?Ni&i'Q>}7 KrJoh'+6iM}iM~)؜T< <nt&@s2Z ]#L0M0OaуE!-qrlIrI@\H?BP\E/5$= q[.K$ А@C0=dX,X5=tAL$$f+*kÒwjoAv AiEGrT 7}B~y3¹Y90O{_*0c/tQ]<Dy?YK#> z x#WwTl_aoPoh GV(t:K*! ۩S{o5X9-Ae꠫,;;NSEE*ݱ|T]UQNvWjhd>H$ PH@B@~dH%\iǕ:Î8{QJ1lmlmVbت-xx\YjԮ77-(/菁lGkFdU-޾ȚEK¾;MC⇣^R}5*.V'ѡjUf?(ɚh@ u7Ѧl,s5ȼ|^ܡ1]W0H;7⍟GDu:jQtc맴'Ibr՗"'uzp`ؼQv_5}AO{N@-r*jkt~I $$I%UUUUUEUUTETUUUUQEUUQDUUUUUUUEWUEUUTUSQUUUQUUUUUUTEEUUUUUUTDUUUUUQQUUU񪪪C?X%@T6oBXS- MCtCdF?v8HȜl+E콤vilQ9p̦r?dMyꃧ]@[8 T0O0=DcSH%OoyHLã vS6rg`0_$!.ݻ!6KvB+ڞ _SsMpTV߫P_ ~^ kNw} LCj ;:o5(v!WhD!(1maފGw0$l>3ojNSn60~ §x뺸o5s#he0,vxMHoPW>6`S~܍):1WW }qBD] d+6w-Tbv r RgWg}/H@ OL]^ E~<+jXB#2xG%A@s= ߽RÅν|w,+8(kwH.Wo(s2cUC)0G7l u5 16sm*Bϩ%v-ZU4 9)yqpP?a''/W@!px>[s= |L}G:ӎoߍ0p-p/ūs 6ļ}15}F ,@X.`wKZOdBМ$(*X2IY>=ߩq{lz :\}eBԗc*T8gD!""-fp h4qc synK!0I Kĩ{-̮KrEތ\.m˃K4$0<4=d}xfшf nU]|WZ3glݮH0Kӟ?I#P&pkg4 A\ lFA Q36C9aWm ACu]]+=<6m'mTizV .2\3z S-lowSډ܀\DL8 -gƻdnTZ>e8Qg.-N#CW) hDє5 .NN5c [6:qζ:CE4)Pna;f%7_25Ik*W $99њ AN1Z( s^Ec/6{ܣ/[LuRt MH C)2EA"{ų%q2f+ptc̼TuÕexpƨiZ*lPD <8m7I PfP8B%EmOcI !*{vl0%pvbPF'@k}c4~ cm=K5#8PlLnZXp1nɬ8eAa}L#U"@XRD^W5,`8w"ָ7:bѿoWרBmdu[x7-[-:9䇸*Zc-cTÆR}!نd7Or@CSK@# s R`2l():?煴75\8i(oy*4x1zB}¢g>+]IBRimz;bFckCc6c{BRML$<>bWtL6*Q穾8<~@jc9f?1Oo6fWV7u<Ǟ^1ˍ8c jyvX!RҜBkۙ>Q1){ΙDi!ٞ ̞œ[}=:ݑ["Q͗0]P"Wuݻt+In~42?"<*FYoPrz{;%@+8x~C44PT2BrC LRU^1+ri:0$-Vv`X&5t~Gv>a/y<ϕu\" =7>o϶FIl1 >N=MߔXuf231Y*YGV;=jO QѢA+YO"F?L']wŲk]mZSuGݣ~8m+en TJ[Qi({|C鏡,bOe#<^Lq3*e *YΣ-r @Fۣ]4$hҭL@b1H4Kz5y:`yîf\LvMǼ 3X UA|}]LS*I9$Zp^֡@a FWQsONߔgAg'V gV 95GsBCܭp*i&_bO*ɕ858U7]V l;W0M9`RNdy" 6ml,ɸDIh>sYAHBQV% @ل+'T? qS3_? bv(NG xh97k(&5YAݢhVX G(gc4Xco-\ϣ V2a_ j>=|x[PKC9טte8Aȶ:C:Ù-N>!tȖ!W#<UJT5dԘ`hԈNVȤhqkŠͅ,2?<딅 %ZJF CvÕ+oORk'.FV gg' Kz*+xM7C3Q4Ew?,aݽЎm. Sk{Ku9':n}Vj2? M+OP?umO${{n"+yui1FJX>\Ή~?>h Qib.쒕UwkoGhjy.#Q] 爓/sӂ|&4~Y_EPkZ5(u] T`DL'Xy (cYpw#/CКRJ@& W H7;Zb(+k)qI uل)sBKzOT.ډCVޒ=SY t^a=<WN#othy\PGL]s3nql {/zk @'_QMґ4f9r"E@hB<7ϊ܋\̐^iăXiGU3w(Խ d*r\F"@gZ?˚aHav?{9-oZG %#c-3Q%hfTV}7 &=&ԅ-x>wO' bVl،f+3 T8 k9J 3 CzѪRóGӻ3W_r~BtaY*: X&vu$BLU[5EkwQ6s Lvo18PH0 - $7W@ j[oA(ϒǕ{*ۜ)5V>(d8" LdI~JƬ*'0mbLJ'nCiD, r6}t0[$+;զ7 k٭;|me^Y)=Sb?)PnC C, sCUa iVXs%pvS3oܘ 6(vrbo˙+͑שmkZH0 jZߕ2ɜbe r (6qc>V`aPlk$gH> @hr 5 io="(bb/ww]8,EY'^^t f\UM\RK}sdf|7 '4Cl¬n'q .R'~F6grTKo w@gY-ɍH qR00A4Y3u "mJC UMD`mV.=Fu#;>2 >rɞjඑ-4 DI ud/JPh9>HwŏPS$ѻ!.v\|_$I$tGt?Hv5(Q8L^|UUUUUUUUUUUUUUUUUy**(*jjj***j*Ʋaj0:אUM wreV9g껾wv5xУkgfdȑ7",HHE!5CdUf"SFYXBx`L`?:S!d* ̨*e ;%! r:!h& a2Q]@0B xnu *<l<6?9'GdPic}f)4/GK]% Rq(elBTI@RP_.ϴ|rE[6b,Xcn& N,+8  Ag)2  ") C&Ai B(J 2%rD& h*)XFf))[@=PP'ز N_}|/;^GTs Xo.YT*W yXp pҺ̗MY<sXk%n-k@<)e4|zm#3UDkKwfKJ5'f? Oi7# G!OInQ}>k#-iD0$ G,= /]B'Xf#.m|^R(p3&9/^pHoX;!mbt f# Xio! #\8./_cksz4 9a_(!%}<OcAPTxˇXlXJfQ!4,M.Tb|ٓ+ VI?4, r?ǟsx~2MJ|$2VM z}pA83#Hv .CfZJsi:qPM;k_1n;J6 H#](sJ[.Q׷]@sĥծ#7 (.Ȃ$y͋@As5%9X:%D gH9\B629O=.Jfgӗ[[t;g}^[=W (wil%2F1n.Y=woDN & OhcW2G~{;=e'3{2!N $&1zMW^pzlzF{/0r7#3ZHSQ!tO}$!5w%t}R$`񘏄7msؚhf~y>/}ì ,92@>ȳxH,i ':ԋ$.b9ee0m+ÂYhbQ<>>|V CK8>߰'6|~J`il2Pe|gD쟣s +\=,]A@(P<1ف$;*D S?#>ޔwca_}ƹȀ.|51gmwC^7KygLSa3IcjWz)~/;Ztת(Gk}y\+M4 #J A߁x} u|L u6<ژ ɯvo[ןӰe &n8z0zXW{ku[n~ͮb\RLLOf][ g?x'ӪQ~֞,Su#ʓrԦT"sE!,Ԧx1@Ī-2z ZR٤PUרNЄ򚊐H0?7~}xzbUTI$.nerE-vV>idrt/;G<ΫgOo`_kanI!&HB$d21᫼04dz"/;[.i,m2t"sBl */l<žx,H4OT `Speb>[;o{g&-AnP A'iJy:Шqſc g=m:;MvgTH d@uL/xx<_o=zMTX9cuõn8{z\Vtԋdm `BQ<$Id{ gpK+/NMŨw!y߂Yk D=U&j>00.t$ZvVxx2Fdڨ`?2y--}yq<(xL<,z.QbTJR6xީԪդ  L_jv3B-+ZjY[лpJ )bIY>$5 Y1!hZRŇO႖ zvסy곰fuZP2ho,40K 6TGնe WruɉvLfD\=A+M@T hQoPEZ; HךUôd5U7pLD# O؟8lpx"0#ùE'x~jֺXC@Ju9}ĚzL|iLWLqH|f^zS$++t^m ` Gw/$won]F }V א~D׹ ?91U$%B|ڄ\\aJ@OTH8-#Ŷ2ƨJhcRJżoH-'lu=%ݮ 5^!EuubL˛NR}DJ'7G'kB320 ߉ݝ-ؤYbOϲO.l9X"xve,mp)ySΨ5s 3{o|9i.IO*R+~a_\TĒQ(KC6RU > qWlFZJ}hfϜH v,{+,ǛsUHX!yiq*@㥜 bSi.S$i0 V\)G:+dU~tKIdN6 L*~zi ѾI8#4ע1e۱ts)|I(>rhEBOˡy=_D>QX7wϔ=qd[h" ue.g/?` rixB-PLtΆTW94`+Fu[N靄/A!4T~MǕc) >U7pv[2`ғ~P˝09o4zP)u+M#N"hO6GiGo)6]9۷}KRjg$gmS-$$\{g}ˬis!_l9ࣂI LdTna$d`eJ3X "-S]Bh4B7h]q@3y'= Z6ΐf:gc.[fNTּ/@p3a#*͋7 ;l`s1OJ=O((yˎ Wg>]ՙX\r3XqZ 0Љ.w#3 4t6R ' &gR0*7@;XG遯&x1h˘YV:*-OJ' 4: \dX6U>~pZN< O@0b`Wy핝;fmy^ ǒ׉-`Q,ur8]~;Y?Y 7b#|]:WgL ɆęǼ5jLF}?ז]?%L$B!#86bhW%Aᙽ襴Ũ:*qNkҿW@v(ӿ[?`܏aSa-97xi#flXAzRCjφj{+!ش0[qޤE`u6PՔ;nڳJ6àr'J)39{?v+ҏHaHu3J>R"j2Dnyѷc_`k }ݫtӖ - !+c=+^EpW{-vJP0+|SbnwKIhw )A'20'Tp /ޞ1b>sά梄6ɚ)(El ߩqYzm_=}* [.d !u4hڕKͪ9 C V0VV ϒ{f*tnyZj ~=IKm pt=j=k2e"lgGڧXBҺ<L'ed} hQ"(e= u+A!&;ۓ%0NER=$M[ M Sb5#U]091Fnl'aB@B Vۙ6s}6ßcU y-x& q+TP,hZJQ筭1 tZd< k@|A6 aٽ4]BW+ݲ,1K#麺R5d׎N{0%A# X۱H|lilζ}Q5 ozr+-Z8yG(Q奦*gZiA݌oLJqs='T>ea',㬟Rj8:-kVFG͋WфH/oID~͍}[qqb׵-$7ɷ2Յ-֏) Kx[)jxc֔= g֬m&''I. ?T~G>Yckg#Ù{l,krd_, Мg{bISN]?R9ϻI+uGВ퓑9uMJ8-[t{]*~b17%tq%'>=']/{53 cy~;3m{ns|\rCQmU;B;2ӭ:;Hi*ӞNۘEIB*2h'ل , "MӠkAX&1hm1xe~ѯh\ ,Fkȷ}\. fsQY=]58 I,&{w¹Ε )Y\,q +H[r{? 2) B̝FgnXqdkHlf82#dxPWq-iM'4¸$aFŧ\4 ]y4%*܃鷜t/;v }EJgvPG5RprC™ċPr4+>F`r:qYO?24%&ezYX89e5U%C mǦ4end*ij jͪs|j3jFi`"A5)} ǡQL؎5].ˬQe OY)8oS#ow7,Mm78%Ϝ 'Sc(j"1J(h,ݢS3\+:#b)00By<{3iv!i^1w Zz7UQ#`m,'y; TLEИ#S'K',3h#a ѷ&*1/ zP'Z ~I,bCMg.<7`p^HRǭK=#v cӔsVcUq59&,vyWc,2'<͇:m;ޟk"f"\mai_[m,\{JœS^nJidne &`q"_vZBSBJtOH{B$뎾QՂ7lN[ 8ڛ,bIT`9o__AG:R{ö,Tgה1}amOb)ζ$~Z?__"u9}ɶ@ 1}rvo^Z5jLCc52Lcw>&gM_Ϭ{'Kbw툱DԷW^"ٹa?)V˩Է;iLc hq\N{ j!_&|nu0i7{~)NFJS\ϏeA}2?ǡ&\cy?\#!#F҇~$۝4!Ri-tRH0>`{v@Rms\`0Bfl‘L۟ey6|ocW2*GpesQYlvZA>[MKl)s#z!4Rš"S.it93fq F7T}m- MdǟeU [k=AbpEZ7]Ex$O?A_J|U [ms`\fsXlֲ4\PcfЬAAt𾜝FYT|X:9wjQhe+^p@ o 7E9??1^Aikʉy$RrY*D!q(&"!/H@ V”پ}+u]|7r3ĨBBwwY.D5+-n"u>їӱPGeql#du*=Jb2TB>nnhzw:|L+{y`͋g-HC 1^ B* DžuA$_ tby֕@Z( sQdYfF/գNȖ Q/t}-"mE\cS9d8pCXʵM2Z>WIMk&p 2LmxW"Т@`' g~nЀs [&_{.l  |-dJ_.F+X?6^/Q04Ke*Gg(u,s'+ǥ @zB:?APtoTM"nC:&b<{Y{tm9g/)cm;Ok@ڷ6;{Yr9@5_zN!F&e=>3aҎ?< \GX{_1f|l(eF?k=SK0-Sٺ[{ifN<^Yϣ;PEBtšla q,HŮqȶKb~Nac?A QZT"7a 0Pdw~n~ӳmsO}Nw{@–ge ]b .TqrIVo"\F2$o 6Ϙ\9#Ӎ:E]"׮-YlBk R[FtuTF|LV"E@3-,ۤp͞o־5usSݨL$E'C7,7@.h Éb|材&(Uf^yR R*ϣy(ē~ү x:[2e~WT՞ PG/ RdHkp6*k5,ɼߊC!"Bh >r@.CɩV|#/$LIJt;\nw8޶ 5Ah<>/Y _GtC_:iD0&I%϶ >鴾yr\ۜ5ynpJc|m}8D-N?qh8YoEX8S-z| D%Y:?K16kPZ;Ѵ>GZAS>В:M ̟K[$0& E*'=k%=xޅ7:_u p!#*[1??FÙW얜okGm^ AեHUxڜ0za:b^NH>a>*lP] i>Iq2 pq9 u&Rgk,Ҷэ/0V/ϯlmޡxHҜPaF]UgߋNpyQa\RAx9ou~kyZ,j#b7 q.܂ 9tۂd $Z'~  s թq?:{@ӢW&*h9,Lφ!_", pb-_ss;ʾ y-pKNJ ]7lq:3bQ"kQ781g6C~Pe=%C8,q0ex\sE +葴G0F6$@Ry̡pDF>$\0Խvӫ@C|zc5W) AolA(1j[s+8% ќciuoM'w1u]LAi * ,Ew`id5)K3J@_wS/КD Kz\1R,llv1:;tqe0CӠ;>r-QE1AE)q $(G 𱁬VɎEMwŠ>;g҃ԋy[:r2@XvRVoDB0{ObY[ј =BUGa[D7o4\#wwƔb[Z|us4 X gA[ }vÆ+Ռ,8-ʯ+[~.z ?\*p*{o͡3 =jR0lh6cHB2SI)&J.tAVk3/ޓkR,4x 0Uo^s.Ě}?L,#r% |%*8<5[McBZY\ KZR8',w箉 =K[($OxcOF seF!GP՜+rॄK>⬁/ΒRE 8K_`W(K" pyB!P1tHg^^/nsًe+W GrLZ'73K#Z_4 ^QàCKEг4+;`k/E/ kt>&xZ~&_#3&>ΝV}!)Ll?dlHTm 2:bϓ{qb7Znp*,ﻳ[0s9vavxsNKTx߿xhi8T$=YhV`$$zOmnR}"Rg CZNӯ t=V="JTu{]N -GsF %qĊyݥ[Dݶ#WKϵɎ?a_ =G8S+׎Pr.A;ZW mmy,Q+/ DWt>MC3B:qx#dhX0?3[k1oz`pH3YDr>@Hs&.*+BSHS);E7Fl*Z6NU&]Ѥ?])Og_ȥ2v 1Y >yZ( ṰRM_şM2vn\{όr#7ؚ6oYTo[VUFP{n+?kCp Q]4U[Fm ̯e$&`@+ `  d/dAɶ4SˆpRH9 gzmR|0gQp fsv֤ WP )_Rp}oY+':utE˙bGԤ*maVlI ]nlq& ?m %TcZ {~Ez+bc#Q-7u3p )ݹٓm,ctifx[ፓG=o C;H@o?,**P%KHz4 'btszչ98"Ykx^12?2ZX`|1M^2N@G d["/$=|Bt6r9MDZ샂e"6Z:"QgW nс1StehM_.H8WW<т '҂ K}a_+o Fsy!(.XEU/8pj-X\ rttstBZz;{AȎĜ- RN6%]^<^ OnMt 8Mka˃p#Ԍ-\L[ ʐDw+S3[76[ՈI1HF:f^"vTPO2]kf.Ҋ8Ӏ:Y1E[À~ I`4tAqE(\WH%r[oޔRE ͨq G2r-[Z`oaĉ)"w,̂g5-z.& I#<#e%I 6yw >F#jmt1kL#]F]HRq?H_+ͥ,wM9BEh' nc@˪ra_5kxPlzCX|$GM@ \qA<̗ 7Fmh:׫"Ԝ%tgXM{`ݹp4a99ύ%6f߉-k+rǤi&:+ČL[fCD)}.`Q,o*izBW=W6 /)re"`h;t~/eu%ZPM)/uB(w0vЛEvioE5l-`)>PeMH%uX(}HJTm"CoIS8iV6U a+q&_ uBt r!*Rp9 I1}svꆑl9ib8z~GjԈY! u| &f|]ykߘF(|˸9 ^LNkP3tHp~'VU\{bc2Zp;\LXW-FD^>L&Bu0H?4w0t&?} VwA?fQE! ҽGۯLn#'޾nՈ8xwFAV&Ԛ \ خ4Zi LݤT S! |Ka9E̅z#9k;MNyMȾWt[Ô-!hs{-2Дu|$d"^ezg<;xF+hcpxe?q1G6kN, ִ-yAL7H؅;peOlU'F*&i)Ap:B(3, `#(̖ `CNK Α%`?M=ܰ4qRc;6뭍U?ceS1?@ ) ҍJ9hB5i<Ʃ>P:]`;IFPp#m:w]<zQ$y1`?# tǎCb2u$PR@ʤ\ϐ!4ߎB E0AkUo=:x* b&B6"? FP#jryC&eKi\nr'ߟfws ޠ{Zh^;U@n잌Gؓ$yz-ܥZ)fl)TwÒʾhgDk7T!Ъ~(W Jԧ7|35J&KǖFT@1{\=4fJ $!rjlPMsd`~dO9(w#qj>nu Ԛ !ҶR;8oҁzC)78EvA 6h2vW~1/KA5 ?(q$ʱ+4vtGo)YrhsY mN}ӫjO4pbK{iRxVGZydp GˡD嵅q&O䀱^w9 &XVo_ٲjKB(9`]EMYsRC;uJ~p[N0GMVhkZpa]eEH뿥Յ9"1T,D47T =U\M:1")H֨~T5ie 8k8̡֧4Y"%};|֪ R36T%S27 39Y﹚w21i zB(P࿉hf̩ wc pJ9Z8xKSe4s@TgTSѣ#ؤAK"Us/ѷx'/EJᘌX;GYtFk>{\@XFnEp9g 2`h6FC dQNJ~dW$y$ uKAz+\TrB(F5IM PO맵FuiNb33hnvT?N[.-lF.HUYdN֣А5] "ȉ@`K(7[gkV6D5.ty bf.E} _G0pẠbI֥uԴ!⿢CS O;s薰i~S W KCTC=c%)/H;֎A BYRyT,KI&vʹ&&U]|P=k)0$W*.Ω;70X_̍ET16[mXzoi,dN{& ErVJc C`k3NzgvW"ofSѳr^67Л ǵ+ma ȐEk9B5i/w^C9e1Q&ZGێm)(Գ 8>~~w̰Ii 'AkFL}'sHp`iǰ}da[POu9Aomhc'ͪuM" ]J$Hڕ E\X",)L}ߺk.tCͼ?8`3dgX覓i*h<g0 (1*msg|-G ”Zߟ>?g!U {C4FRZʨj-E}AY2)s+nFfղ)!nj5d[B%;ݴOQWpE՟qyB BGwTXq_cR?6,wTWAyQQQp"9V!⢾D{ ;gwU 96zW5OPQLՉs~wR+u-J/Uc<;#vTmA΢>QT(|@DuXJ Wa<@@E`@P TF(IR2Oq@5uR$PHHiV AVJEiTA|?!هCwg`afjl㘃u*4QGaSd@2- Td ?(g*F,N'=cPKa܂p(haPX@E3"Q*f!BZU (Xb"P!DUS7N'8 D$H&Š`& |t }TDST} @z02Ao/&!0-_yYa DRZ.Y+~ Dᒧ; hxk]aoy'3zff[]8'JcƣKڙ B:[wU4nRiscqFA[GR=SMYO҂,0 ~+ðy7g?ζ]}t+p#rV- mp;|^NKX`Y/x"Vb$lPPpSL&ej*qeixkfpA$&3MxRVw@(Cu)dsd$TBkA fiCRu"P;hcN_|v %-NJ(H3=[STW6O1;~ڒ~L#hEts@8BXe’'qՎ %3.\y#Cfmr)+,`d$d bZf&DQ!@Pʄ=( B~P5UIA f&Be'='M gZG5trllxIO5P :)j LgӸ? qı02[' g;?J{v{'%Ԭ| FQZA-Eõk[9 Tou(eu,u]5_'Zm+cOf :S?El#¥&jf;^&"XA? h9=~Ψ| d -G_ew1^:֑J91o@-?Dj B ^="m u`]k\| Rݪc2E݌8@:[_z Xb`w?7;4oVk{Sd3tcn2Vm0"C@a&|I/|e9ed#pvpeaOeZarXXĶ<~H&ʷFP UѐY^bn9WmM \;(QIT䁍;8` _d/x9_Ӳ-[imup@Z/Aih}V[b+iZ{fǓs ~.~3^ŸìY뛳/rݝoϖqU32Zl6dӟ梬p}yq}]s-E\Z]>vzǓ˾f5<̺z~YWd%rs5z{!PÇ}eӞcMVuZE5;#133m#ӯ??.>~˃by8oDLDL[cxx13333qS>vELmh@i"oϻ{DGgw^HDG.1n]٫DyJ6y㇑^Rg ys2HJR0)P5 CQjChՇؓBmm_Av rY* WWJ53l,*g1S3ןȂْL  (2I#,|yo1#~.S x[.ӳs5LVfX^3f4|J[Y ȍ$"@@)$}߫Ⱥ=oW]ߦT-).{g6R%tv9PS|c.-lQ(@{ xၼ5pMQ vZ7|n mbpͣRQ,]v%M/r&>bjF`X7Sq>L[=} ~ʈYxΩ!!B2Lc+]a-s @@7i{WO]@#6lY) tW 6MNPSMw,lN'Ngk/lq[`&uL F)%{-+;]oཹ\g/d~$L/Ppz;azG9<@˄6%f?d>ZQGϐD)B4(CH(LO:5Dy% !JQEzO;CU*Jʪ~'W<#  {|R R@ 1Dzn-kmܴ7PQ!i@)J ݄'8^I7_+pp=DX zZ+b~n?8s_ B!eKł"&D`Ůݲ? a`m\Mz`bIh(c2qgWoD. VP} x_ay(842xeRwx"J` TPnk{']\:k9*vI7yo8T?/]O:ߔ}7Yw.Xѽh^IJ(okXg^/,@$2BGL+dJ.S0' x ud\}_mI?}"~vpS.rUt0b`EMQ{$葧23qlˑ`a;1@1#1]"s[ >[G #U|=4>be1/l]Ȁŏw6݃4-6qP7vB>!9,S[૛i)`js.Y13LN ajAOpFgz-ˎ%ze)Cdy1>b)H i1 8TW++CoF)Ti6Y,6lEc"Hbp^ڐ+)6j,9[QэLL<( Pɬ#pH"20#(#'61:Xw@y3~8>k"`.=s~e[q(7q{2?+05~hBm]v\ZC4n$ d)$ 87r_rύx쯵 `h_/$F\%hr5jeCIa9i @>9S!oMkM ˬm*swm,zF9x6M쩋f8كXsf6{>|k51\ziꕛ;cWUQz^DZ`Qޅ$-юy^gWN2<lU%Ms-/z~-g>s9G Cm+?T^w#g{kU#ؒ4jY6Jj9Cn<|7`@HE |vJ-'XnÀv}'D>}3u4X!gdiZлlp&*P`fnO`66KMc_w7 ]ˑYfƝhf:=hvM8a p4{̃ 6 AoXdUC\0_bMMH| Gqhǥ[1$B@ܑ kr=E|&"Q$hmp$2iߡ˅&JxN| Ïm }clm6.K@m~63p-9/'=~.-ԯX+Y SeHq nF/ rƉ#8*vMh-x"ѢL/s#_aBtpGH _ξn rrfNn{Ç7 m]}}D3,K(3 G[wn:c ;&^ŲS3yZM5*A#3N|pǼI.5`BRt>o#:8C Q8yᮻ(-&C|`BjAm +mZg\j;m EÒ}awNտ4lwair.2"ygg8:¹ESA=S8 \d6Xcz= ɗLjCÖ|22t/&xjviJ~V{<-;1[w|itiwx,v =7vD.c=:@[1_Bnlc<4igr#,5c^5+?}b}m7=)X. 4iÇvFzw3■n|qLdzŘ7-eQUGp\]PKhzץ[AkHvuDe9% }M+Cs[ޅ^WW%Seطu|GEj}:p sQev+YeG8q5F[Jtb¦`rFaݾ]nNWvu {ul:p㏁γkR5\-׌[dӱ˳q#~]ODpCi">pjeA܊*2j,˞m[#T{'ajw=3'yã|]O?<Fmx;xR auΡF0dNTw%Зp~f3d |*xY(j ;S+rRc#32w5#5Ơp95_;ahgVL-A90ea0@xitbJ_$mmeG9 ^9y6s9kZz{; F-$Y}{>5탨BYN/;mɫMaxb :\ XH~{baT+":܃s6H~U.h!IawmӴo'yÿᳶ{p 倴XOOk~5v2"}O37yVLD2I4ۢR| @\fdGB2?W u<;'Ka\_xΥFSIGDw:hz_H%3Km壩~u"&3J+6ce4)e#$`" ^aó<KՊuPf*9u $n&5#5v]KEQx-^Oh! דD M3F/#4I:I}sW#Z9 d"Gɑuծ )In,Bѕ{ڪR/eIn JZo~6ΐ6\I}lն> j83Ѹk,拰νȺmŭ;#o"{5{GmEI\컱V!uc^j7ZeS><@cflҽ$sm%Zbz8;e18C nFrhŎy<9\&a?V }9)`kDJͅĀ١[@Ln=Z\4Ytg!n&y9=]+A] ݮxXjUna#"m 8@jS$yp)jX=]NWwx߶WBBiVb. BW0wy/4^6C>;ll>١Z#Fuᚙ~~FPxpʾ$rM{qh)1uñjVflg/8}Oe!ws~^ͨ;F5~}z)Zfi`Ktl_ AO3iSD]xgCOC7A10KcuV RQ3"L?0;! 4\rLq dU]6iFFxPyF~:.][Ic3pLfa0ahL+H{aȭWu9doyK @{!tn!!C*~~<7l$߬΢Bi҈$l fTZM,Φ9oǧw9N58Tb<5+1"5kAx F@= ;{+cwI5T_d!(@* +Ubp Rπ&aZ!L1%f :xʩ \hK>#ð/?e?| ~Zc|aHoA[ZK]RUE&M?tF8+<:ϲ wdtB]R *2䆞cȘGx^޸Hx$hFݘ-RMͩx r:C9>{7|W{DY4 mj "rqͩ\t:!Lm9kǎ5ϔ/|ʺm]<)=OB*9yUoT3/ iOm&Lc[Sh x-UxC.D⢽dֺb;isgJ/?OG;ޑPu詝,x(rx xl~o*HW #Aa⚝k8Ai$aN><#j/ӏ>\5> CBEd0nC|~\;ᐠ> 3Cmh1t#7B9@/ L B7DdfD}C0/c=wjcZ<"4bmlay[_J:.c Ah` yƅ"MqF睌(uv۔1Bȱ.z/]P: P~`7CT2 BZG)5 PWud Bc 'nxNIG.1vZRK<ܙҧn-kqOsod:JKp{ p%D煻*QIi[&Ɲ IJ0]0yPؤs9A59#ֶM=/IL2w 0-8@1{w0pN&Z5 =ydՅVp =UGHW]Xx5n5΂;I ޶,#[D3Ml"y.KDWc\daeA_ à+@ί gӆ,!PSi}$6ʊ|ZRxh\,p;Fy#H]$ 2@:oq91)̆Bv=s0##O $3 nwKC ;ǾvDd;.u Xzx3ט3K3*seZ%[HZND[\"ex"UNW:;3޾S͚>t"vCnc_ NtϐȢC#}0_N{޴xI1+CzĎ\TGnJi C)ddML.c0BgOEC#bR)BUq63^ˉO7VGc]]=ukXzO~v6熻Dss|-1#T ׂH|sRckz?8_K*:A~nHg}=>0X'aCBvbD/ 1m0 unnyg&GL؁(: Ex1Bf!a]`<ӎxUb}B]aN4 @pǑc}Sׅwq59 _skK01O@ٮDk #ѐ'X2^%I]0(*;5<=nF/Ϝ$n-Xp >AIR;&644Fp ER5tY!tv Y;;;E|9 }!]JM{.ƨfދ6^wgds7| ߰]8fp( l,ګ% & IA:z]uQM-S2Qd4AE0DBaYQ֘naϞӭ5޴"Ld[lځ}bq)0>n{=BL#B8ZԻ|a?Bhߎk!.?x"#{FlƷjiKAyKs7< q L(始v-n,L戜4Ư&wg.$ieጔ Ðt,D15ծ#喣Adټ9 .Nډʘ :ַ1nfN 颶%ݱlqaJdn(zۿg7a0$H :L)Ѐ{kcjpˠl6LoTqcR7j^Z4.aaFN郈Dei4,lJ[t2-HX˄ eD=Di1ߊӶڙq>zL$E8ȟ .H 4|쁣blw8>H cxninja֐[65P7,mc9c;12muEd=t3qW|`~@$&˜geྯ FRN|}y=ЖN)@%;( '<zos Iko)c(0,2Bz{lyh$6 ht3+Ñ66ސiTZ2F6Mz f4O„}^!鎈F|ό1q/s'˙j "fL0LDX)jI)r0-ʶA4|{(9 %RMCWA7Mg/e-O[*n&Tݝ[#Y:i>&~.ޜ`NOQ}aW`PT@dha`DGp1>}aV}Eʃ[eC052}fݑ ը9% KvTćHqcHBp0El|nȮU$Qՙ= 41cv i:2̮ٶƍKF ,Ɉ/AKoŮ3)Yv땂j< Hm6C@1s f R$m3zЂ%F%LHi֧pgz;'-BSd%Zw6*LځeP^ lpC^|Ǔ7Mlhotꙁ  ɐJNT4}˕TF;|:|}[]m`lGan]erʖw%-]3-3D)V yl fXi#$~dK^vLwrVڨMiɶ|8 zd~fHGS19}z]8M YR, c3Y#+~ϑd85Ũb=z>ңl*u-j}#m4$d,B}c<` vBTMy48Y@b`TX9aj4u r\vF.)uqwRXlW{Yk}olw(i)d%d\wU~YvU 5vzl7kZxhW(psl6cI<E~Iπ78kէtPM0D3֝uggl\3x8@ 5җ\fԼ@VW6ܢm%ȘYNk'CQwCXĬ҈'T:9i%RQFZzj֓7 r هMү9}udiK`!!};kR-h# o5g̥C yysq TqQ,ÜjͼEMu%+-'N"63/-eIA w*//JHS9SZCD SR]*POP(lIOHQP,xB66&1`=]޺^%! { oC9\Uvi+e/ܾ,( zQyP}{tNX( ՟κ(tS&jq<B }=C Iͷl9A[ox(y,q>J z>,1'/pf \Jy{o"X`3i.=ރ׳j$ m-c%xkwW*, Bjy\+p kqqQa?UIȟo*_AokϜi/Шr]'㑦(RTN)YuhAqݶtkK[%`\M gu,o+P}hYw+OT3Ofm'"<s'C|N-=|5ߺ6`(`WLqK1s dm*!/i-k"FNJ&R0|ok;L,db|̛BdԁξxC&n'u^o56L,u=_132If$s1OB!Z0O6o~?1cZ ~z%!H^7%65oeobjEX`$FԱu);-+^m|]6{HˠA7>9? &u$דλ92W_ߺ ڤ'U.(eMǡDB#s]ct~&;^Kǩ?$?]yy?)dҐ$c|,3W沯uhcH&JmUH!SoIM^%gk,kZQΉ&4M ٬c|띪%_#in_ŵxjul&y.&Me<]@=xkL/ Y3.kKQE1;@tɳoP#ej6r8Je Q1h+~d#.tt\chYLsWG .#M"})Q`:E牏3Q>[V@ 4sz;s"Vڹ;, VQJm:ͩʄd0< `\2Sa+vfts9YoKyHܧf3#ԧ>Ik65?BU/-Cj[8'lkյ:o({l&P` N6RA0^'-!?Z"@vϴo4QGǩo(R8 m9]O Z@P be C=eCNx%19~3gqŤns_}$Z:~L\nY1ٚ8 h&%L9)w]nxސ [e`IL#ʙhtiMaHXn )X`SIi"fS^/aEo_8>ݤ᝔XG #P!ӛaJ$7I -T{C̉% "_QHW ͞Y* pm<57oƍQ=Z10SD5zD:vE|pk"Oho_FYq9qhCpz^ kp'Tyy{_s28./I?F(78GeBx1_. ?#}0?da$&;Z?h| Mg~LzxcF9ˁ"-:'}xEf4{'}#bz%V PaܡYEͿy_Ūww4ˊZ\H[d9 -=KsёX5 G$zLyB`uqW0`%QK:y%э&VHLHRY y[ՕF\^k!DږkњPF-'^?D?[~ݾ8"+Ex; ytwc~̲\닓AZxJj{ZЀWjkPncc^ޙBo$`3bytn*s,Sq?j"V[z Y(̯Zʽ>{<6 9ە纃sA3sSu3 E lS Dg$x(y&=\!=r Koz Y jH|1:ͻ*t߼A VE ^ ʪz<ҥ#ʥfdǤ戠*; 3Gp!we 8?e멽 ^Y9ehw -Ti^$vCu!wWf}-{X"I>fkǣFN~9]##".N>ܰâ~|+V83`+'T*{6r{0Jh 1!W0s^}g_8G"dU|`ԭPMҽd|O"HoxzjUX>c1epngb%G䷹,^/OHǎE'Du @nQ 7?2H'3VKkr_ΐʹ' T2UNA ?B7u˂5׿I!c;qv˕boן2Yeo}lIwHA6]Sh~m; ÝbP`a,WN@e3@һg~pΪO=WDAx Y)u2EG(D[N]~皝/vk];R~XքrIGĆVN2eHUg*iWRA@/oh(B")Z2δFjU! A%a2Q nÓ-8 kKN21SMP]ms[gpX%kz|;Z[(x\a ]＀It 4`s niFpeEXs]6}2/3WS *|ƺP~

&'?͟b0t?EdwzƇ=w>/?<9" p#,zW G/Y0F\=b4OrpK1o*oCsx!SS S*&}_=Ea:T9C)_]bPЧ8Vn3sUiJm prЩ%,+98f` *ÇA!ADTZVps#t@OfC{iL5WbO% JmQwbi=8 7^v k`1yeoO%竞f1T}#oxSH'{oɡ6jvXC,/M?{Dep[/7uap>.#.LzC9i!==6~Ƭ?v 7=NZ1;y&|܈_m99-Io,שp? #ADcBV*3 gKoPj.]h?OxHl(1pw~'+J816g0߹ƅb4Կ6{%/#1G.llczY>ОY$QXjm]bԸ#UhqgxլAÏn׌9X/j_-Iκލybf+!/0618j,XwZZa]esϏǟ'n=3SgvELtLFz߯^ׯ^/p#_1o٦x/oZ$ϖߍ cVߏGZiQ<\n9VCߓsM45E`/LݜlA tö*8ysM錷>?DL]31333313333VqrV1LLۈX-3533-9-sϷ0^_7oyc>%7E8D_ɗwSqm#UohθoqÏɵ Q<ѦL֗+(ýٝtLbtmuukY,( ߞ"9y޼:hM2sĠLfpֽ)Z{:2ܣAP0GI(,0^Rw_:3ڂ(Iz,?yo69p((m=鲟̓sFfv\լܑrUkX*:Ǟ jww [V-QۮP«ryKp<̓%v%1Ƹvkmw݅m6rW4~ zXOl׿sajy ǰ7_"CcMkZÏw%kJLxƘhԨY|k-~?1s7m9_-1oW;_BAL?|#2KD w,]{I K$mˁ4x$XbJPe=y fLW?vs[[=χW <PFsG(˸O{YK7*#+wb [c /otөkm@|^8}}ٕE]mŚO¹Ҽ`qQ]ImuX\$o~}\{B6/2}I$Ƕ{v7q 0ATH %P\/i$& 1aᑌBYo9rH@K!qTA mݫowͺAfaijݮǖy `զ.sV4CyxsQQeBABCudBe Hhg _b9gҧC*O"XU< [;^ D n.Wղa']<_󋢋iWiH0VDH#3!8cOg`?hpC&p@N~g3\4.1s/1xc7bͦ6&ރ4<=i} O@Ȭz8>QQ+S5eyzoUEϙK U.iyk}~V뉂/[><)!n 4$Ҷe?:jՒ~SMTm*+^\z $ [P݋d|Aw o8ϗwYvoa#vݑ X}'D:.ᒎ vIz3QkRSذ!к6kl78uF"ֿD)c{r`͒8r]pčч!RXB$ۥG/yA#\eT9!"P+v2黢0-LP/aEv~/`l#sK$-4y礣BѯM죧t|wq q^L 8(cpj?<&{?[h& ^`P 12Q@vTP y @."t A0{yG#弸[5oŷtퟸo|Gϔݺg=?^KDh<v{nuF$QH!C$pDbEGN0E P 13 c !ZU4p$USE"P0LdLT ! C Ú  &N PH(9 $GZ &A2*ޠz ONz_s6O~̮(`!(Q*2~w) Z`(Bf&@(%j $P̤^H!~_h0M )xɷVqƳ,urao'4hy涿F>Q`c3|M*n/ig}ׂ|7`{~DŽ#Z/}MYg:oڵ./kOJy_ð@*x>)#|k(wO5u@LQ@ +7>|]/дȒlzTvoZΚF ܆9{ᶞbnT<%Rf*cT0ʀ =\'r `K8'_-?~5%3CץŶ1ͫC"qi@l:;H\axX js'* Т u3vAWNCS͚csLX #!nfؓdH.[>YY/Z3c%ih-|'DH-C4 ~vP|_ul\%-xq7ܳ5^C %2L>}[70`" (:wwͪBR]cVI+v<C9+k䘵al&(`&ϡ}w}w B? L-.~UtU1~,=\x=P~+i!"eh e[v[i꜔7F)m2ʨY^2=6aԜF1@G tfd{NŻ7=߸J{I35Ȗ0@WmKd@Z쪢.sÇb{^⣫z}<8>MkHE3kYTT grM<,O=3p|ۅ*Ko۠vnG\B*KA6ĂNNvܒ͈4\C5z!t '=,0m3lm69I+>Tz^]eiyL)d€6L]$ͿޘS>~>0kHI遮_vg-hu}C[xp \X68bs8}.IGN/JD4df^-N(̹0yȱkf,hz asX(&PԾ73[.^7 nDvŪjsiju+_='E*"0oqז+m1OE0ݣSb ge-tyUMFW̥ĭ߷1lg" 7!1M%$ $8d1Q[#-miyK lR?\rYHȤAgۘNljzRJH.\?n= PA&.K`0)0ķ { .~ﯣgѡ#өp0딴u"vy2 W L7-Ň 縝ÁJpіB_SajHcU\ 6ul?ȏE!x%~L*b9f㜱z$I%آR +{D`Hj`<qx̔4tζ钶ff?}]KrR{vIk" F|mJfvaC Xb<qGl'33>f"#+n8ybbƽ gk]>t`hQd2As!dc9_YӜÔb/t$Y xB?{DTN<#VR z$]0 "8LMl' [/;o/2!?eHw7k'KD.6p] :pіqHbI<.,>d6C9572֋wlϣ(f[% k'^m %z5 Z"L 狰-xBߍZ`颧q a>.T$|/\yi7 iL\6k+LC)$flv(h 15-bذ6j?YH a-'OR7ᦟDN%vB1GdQg X;I%zVʵ銨Giؼ M܄p/Q7p̋8o7maEP7泳NcÙ9o9ȂJ B 4yAX fdd Ltʖy,ؕ\,$Ia*`PvIx$Y' %>VFƨ بOAspsklRin^lJD2^Vp\<|k $(@էx}VyJA V0OdJt}/8H;\`gDe5ood'Ղ./iq~{<{[f6 /yVf|(&llVܻe~s3'$V]—GS&x$2sVh. l- snlەF|1D}j>MZrqK$4p|.!6OH)U[>#Y[-A^rH̼$-3\Nj *|ӷŭxLĭـB#gƵ?Ln9(5=_@n0TAmk'Gh `o::;JK1HjbK"+.:} c]c,}wPZS3 #2)2 {Ղ&aIgBHuNR]f ANIR޾ ?ZϢEҧlE4׏{ ycO-"_ga #ԀkL88 ,?eho[ry3Aw1Q՝y.Ha kL<`Rʤ'vxvY<CTCF# H+c p16vyf̮AưaKrmG `w(D 4p>9_?peaԝ0 }] O%#4;d^"js`ԉ`>!&b?ֺHw"Q.``Uْ #1Ԡ(Rр]FR\8DhGL/ 6o}~[׈{_jۄ"sþnKtƯ z_T GE~ ~ea~$dV0\EB[  )tx%e6܁/^7 %~:)4^֍TJEΞǹNEEIC*w64j#96"|{D::왒\%$=8Ųů<[Zb:0 OT`As' kK}7>+7`nDp>RPn0mE#_S4jaa%*؏˻us rP ).f'dR_'F㬝}/#HcGb Xd:_ dN({ΰEHd/aL47>򧕔0^Dgp.sjyy/ew>p4˹mD۪?.UfV:CϴۧV}r!dk49F|K޷O n64{o}>o/鹽7.E }GO T,hUbi1g~vҝ'3o j;4LgNDrMY7t>>1dbil,ke['3jh g{'{ L<[Uqx17e2ijD\S*Ty5M­WEË0i/6ћZޖ- .NDZkTe[4*VcZw>ƏB7$"ւSP$ND߉UgsB-jMUZfđ'P^m#Rƀѻ1A4}-Zǁ>=/CC՘*ZrTJ9tZ&qDmkIyftvVD:S䵆)o,x,M13-]&JӺ,N$!8O饲gcp; n'f>3ݧԳ▷\:ņ{33-%G(07(KR̅Ub!7 Mͩ/QQyU:֯ tܧ1~ۄRXǏ>_ Ǩls cǟlQf,FmmL pcȱo.IϪxnt[QtQwuui ($dYq[Ve3nJ"KQN֤@.aWn]bh E11!Tg23g$>h7?Nک s\:ï:AdNI% qR^6{ |1}ur4 ~kN46ⶆ?*K&!4\ާ+5 տՓJߛ1K M3S;[H\̋.F:*yMqk4h1C*%UFt#M5V`ʪ^ר;Z6ckUWyTiWDQs{M$Mm:Dhe1m>{h q6{qeT؛3SLZ1T8wj̝V9ݘt,J' ! 3?f7scۧnۺQ(ҁ%eZJK5_֬' oo"BŁ`:o򋍋 Ҡn0a;e[_o\(43'v㜍1 gҐ5 uJڑ))$3::UUU4=`:*u$72_TO<$UXӎ,8=FFx;Ɨ՜(l`;{mt@ڐi>Y5aL Q Bb%#VǦ(5 Ƨ/ޟx ;)@CBUjU *\($}Ćdu;x5\ ŏl^)Cmh{`D%tTLM'' ^W&)uP1m|T"~Uؽ네M j$zeZTRf$Lg "=)b!j9v  }&߼T#hd?hC+ۿc;esӦiVl߰7R0g!1V%Jבk_&c]C#}~l)1oo&I{rUQ2 ׇQ>. ?Wi58@YawɦYP#SV+\/o[蕭sj K@=Dx(>h]_ۡۿ.m}+bHECƂu:^d3i(?q9U[pH2N Ųw7?VMaD ?ɢ C|{Uh{x,qyq_UK]_w7˘ȱHX4Ӆ~MaX{EŨMʮV0 $, qRe;JqKُOl?3g5 " `X !"#*p?ku9xb-cÖ́%ƉC \!8 ؋4*8 `C( ta SF#)^t;=_X "9%u=/AL)Fq~b1- _H`C,V>$_?~k;ѷ3($``ϗ$bpQu'.5V͠EкtEp2y5P0E UUUUUT@y<4,Vs|~>   H~>C @|xP>pqYB1D 7 !x8d"bwU]J" c A>/^.o<\jN˨_iZ yK"6(_I}>Bv {?|:,L+{ljpتeI$I*K@?s{˨\ TSGZ̡*bѳ/"(VvL(M8N}]1Dq/W!8,)gs>N25)>3 f4(]#Ҩz.s\Ljkf~}LQoyAas=rsաm7IdqJºI 8+n}i'O7HA36.&XCY[y27ٟlb5BBDDj{LK†"jjSf_(ε5=@szV<0ϑ;,@e c- .Y56\SCXs,GN\c^QL4{v LZPQ!S`P/՝oJ/"?P(ˤ1TppcW@}?>򶀋`E=kX53Wv7cxzn)ۭ&5)$8ژ?U7"7Tp{K{O\R&e&N͛P.1,Q=.W9M[?쑢u)4Zmj'Cx@Qost}ͤn ҡ18O߽ K~vX!wgWO5>PDE MYLA ;$TB,%#=x~ cm;\bD() 1T CL3wIcWV_CgsFۊXX@d1NU^(X]>G"[SQc_"., l9l߹ xW k?lskiא|wlO`Flh.=.GDӘᒻ6'wù?TQ* Ò{RF٭_(dQ%?{PaWj)&!뎙",ߖz_/Xy*|4&\gKƔVk%9F Ҙ6?+ǭ::G(,V1{U'Ãkq=>݅J[ h,.K,| >S_RRaȏsͱ٫EZ9z Vxgd<)"0fNħCG2`u vGAx`3D+7`m#pI&ڏ(  22ڬ!'L^MT, ~ QRVĬݾ' I) am z@lnv_; _|z6^mXY%wv]mH 6֊/%O2C"+;ȟxCLVG~Y&ÝﯵuBo"v֋gwт5پ#m.okgL/މp=ƃzJ7m.afK^:-eZD/rϼ15$LM!'Gz0yI9l'Tsǭ{ 1هlrhsNbD2u9ͧr(i"@j34v#Mg9TG6mV\_%ǷS5EIZ~ I-2RcYʆҌP ^$Tr&So=|鼗2D\4|vͭͷɧPx^v.9ɽ-ڹx7u::\=6‚o:Jf!yBS/nLjߴt~'숈yާaS:l M%Eeqe"X5]nW!!Ys>pYOToyDLXe-~mc};٬};c*YF3遱#O~-JQMkb"a6K(EL~[TR0)%`IL=G 8I1x 4ty'EFOYG"7]UHU xK8A\8j%9c?sUOMX*}X|\|3z, 8Z,!>vG2 =AlkEWM⫣j_Z8QCi׽n,t;p6`-v 5F Z$̅7ɴdčs_U~B$~l *?65 #P}:6*Be~huFۏl6R]zYbw0]fs}| >SlʄJ YtHf1uC7 W4 *lmSS K7ViSVRz^~COpp{V}s1,e\c]Aq07GޫV[prYl,)g\I@7$*5d;ĕ| `8љGs{? hF^a8پt^g){qmK9_7'Rym >pD.c@/p1a ]\M8,.nKw*."w񗨓*.<jRr(;ހūX\Q)I3Dĥ$f("yo`h|O)"1{ɔoD'oZ1gGKkqszy|}@x1ǘռ;6ɓsCl؉]W͒O2~ ;u%qz:e{ux h =N۳pYl _~l)qnX#\6l G>#.Nm;jC~+-7=>d|w?sO/cF &sr$ IH5D0rP_/NCkl"*I,@Y^rJnں2F1luHNZM[$65} W+/V #Wf߭-ɭj$j9~?>ZiLu7=['d"$&[nœ)(i`,QaYr& =sp]ƨ2+碘>nI6cg~D#/3d;ruiR6nN4 =AqR t`I(e\b}=/Eһ(pXzmGnCwV2hY굋z:A(qfma}T[ڻ 1<zY߳"Ma|@j&71~#Лs&a~ͭr3+ q-7LkN2mru;Z,P򬦍'hK *1#*ff9귻>Egs74k9 2Q yWtf,`Դ nu?LfҺd`i&/I,r#6xǬUO)HQZ2+&l̈GO2I@Qdu,|;񵇖OO1cW{GF-Dw5u`= )83 x qݖYPKS] m3[_wLE~Ayffff7}!X0u×/UUUUUUUUUUUUW:p80?ZP"C λffX'?/pި&A9 th I`lu?[觿1áRo-LB%2n %}]GΕ.{?̹j_>'UGMA FŖ0Α^pL+Tm|N1O9- DKK@vD 5ΖZ_￀@=w\ą;)'~?ť]m g*q @{́_qK}Gԃ^G`0'-eQx/gl^X/rZG+mr3:V2U"HZW۱yʘ y{k ~p`V>c-OKȝʸ$Mj?eXȾٻJ'EV :u4{%񸌥^,-[GX&C6t˃aM#lMl d&*c1aAŴ F F|]ċKv:ޑqt''> 쵳! AVɴf>g20Ro-SYў M:P7Ɣ ,v<„=0@^Zƺ'S&=e['wGohSqԶXjM#$y$a<p@~T&2c<;;zW>ήY,G`~abUD2q.ٌUxHRڦ"~'-j='X5U$_W,qq̀|XմRQU7U? DEt* :rESPI_9tj`F$>i# B\gQ i݄qf/lޥ" )bb<-$*w 7[ݷxTh2Y}BbB˶"'ߋ'-B& n{l6N2qjZ}X8Vc]?u/ЬD@ai|"OiNNh:?պał7gwyY@^.Zǧ0#Q]'{bm#C帙mt+;~diasq>SqltCWs ׅWXrbM̘~t#C\mY̧mmFMɵ d5 B-ܷ\( ܲ3t[zY7inύJ-[1w‘EoAi-_ȑ0KB3u6$e_h䞌%I"'; _d4V^Dԝy;`Tmƚdƞ4&| ̲"`/KCo8Ҙ^O^ JnDx;/n3/%17G՞_ϟ000\XTid>RT}4$0PE q6g%L6h&eꏬ ?lqG;5ZQx$7d]ߍ)x(ykߋEșu8iD QyʁJP&U|B ˑ?14hOxJhA yr13h UTU1q1N!ʚ\|x{1A8 !&iA 17p\6|kߗ-~^O1Um=ܻdN|NQQߦP J M.בd;3jze@3w͹-_QaTX %$ulp} Th,|@⿿E I#$mީ`H5?R@!'gx5&/2nΕ:GAP(ÌK׾V:#IQ'?#LB u%CYRXصy%< z5V/Q.viaPIx] >3ޭt ]F3@j-\ǥ-1ЮMp&t&R8lqM%pMf&pszٺ^_CJ0D WfV) ݝ9r巊zsKL1mlIoϚ8DSƝĩ94\f<) #Tc#Vpy|!$cZ {eb_m@="Xnfhi9.(#y'ӂ;z@+7~1St5+IU2$كb3qYYQYu6_cSj}3Vu` xQ;[sRkBQ`6S06N2|#/O.Q'Glqvv0*<GgylV>X0O5PxGi^t9wCs 0n%ZlG$p }WeYgI{tQ滒2 gl` h`vĆ hss|`C{8Ei}*&LtwHDŽfO<TNЂ{ۡ鑴m9%9hVh6vX9ntf)b,4 }ԌuEҦ<+Ur$.{1'WGwPOqu]Y-M};E(C\4xsxvX%!'K|?/֕d햆ol}ܢr7VnU+]dÁo8{g˱.}#GTo/LɾguѨFnF JM8iٙz6!`|\ZaM4{bCj(r u=m8ڑPBwiͱx &w^r%s #2-+ Qa_rق\zTFz[!wI_If B\w1K[!y@N:%w@sd^mM{ۛ}~*z"osy_/?~btӫڮ.l_ư%N.8])ua!ZT|7i)N Cdu_-¨]}3~[3F$4a&Hהy75S lg,iF7ŧA~? %Xc[;a>&7ՖVOo=Hb8lg`p9C@:ө,swMf 7q֪{(kVFm&G|ztx |}aM)B1xqF=Rˍ&ҧ8x1U:L Zn8$8;@>~_UD!Tw2s=C֖ь9h#"Q8\od]^bäLX8L2qS Art?R+r= @9t=5㿃/'q|тɲ I'u"yC87ձ(PB{ z9A{,?:+&~=}̏+W+6oچ'`m=8ӬYhg>HffD9I%6[s*J!/A3*0~.YH|M\>], W>I.,N|x;za j9ubZE7pj QX>'6=Լ-d 3i)4Gf9gI+ltQG&^9eDŽԕ]R#t^jf lM R5$3 O-CoJ"OW+bL$ț2F w ]%^J?Mofmq˖ *<9^K|N*<}piUDޥ{[\wSs)~tAH~GZr#اSmVƱo>O`:6ЗƧ89,__m!HZt"* n0 - KY·tOL?Yiz=V[$chqC检P$'/"/e\s9#蛢$\pEFW.OCg3z!hC{Lx,d\"Yb-!-!"}-X[6:/{n ؒ SU X\!m r?UE) qΔk>%0ܼ)}/EH0$Ȟ(:>*ɏ=0Iyy L?^xTDBvLeR8.+*`F݇j yHOի,DIP1 +⬻C9J OKφT"-Su@%ܭ*BWKfnN˼ S 3M"rfQF nŢ]sCie6yfx^OVkޞ<σI/i5@inY"R E A*4Xԣ}DPU5E;/ *#ELǼrQd%(ԁ%-}q~!LĖ Y<):+D|? }4'٭Y ƣD]ѹbJkB߰o$/osCU0-:T'[_K CҐ^ @ u'0Y,=fXNc૓85e'fO6꣹5xJ[QϤp& =xޠں8}<+IxiK>UZo3hv 5S&lh?[HȻ w`{l6ae7O&E5W;M  L by%qPsF ek^Jw7%jR:{kEæ;63 4(vf5#+=?>JCx<4/_#I R7=r3)X%,Q ׹!)JJng; ىP-ƑvpD;*51OIKHKE .ݜ?mxt si3zP<+Cϯ{?ztR~|zs}KW$PFȂ//c'Ŀųܹ6+Tѡ&[a]^f qxQH>)'\ݱ'|=(4"%H٬qC가̃ î^"4#"p,8'O03lhBsbbI"<4~}-#z]0o>ƒd7iI[f1O?}SMG vOSC5}[3^o=MOg4&g|-';*!ԁDDBEX (jR GĨ 0rBMvR°D$jrV{"?D,п#N|\908s o F1v*{dYq@$PDEZ&I1hgJ F2V49 Yn=c΋x>?%:ٗ]_͡6hц{& *H,,w#-Kt QR ܘո#KfCAzhͰt`He5f-16G{S_*WԶPZs!fξ8&%H $љu#|%"`Bp]IY$ü3:3w 5t):333333 7מU8xȮ$c4$I$YH7Y BQCjb4iu~wK^ `RA"{fxѝwEi۹7P9|i!n!B{9wDy : C" [֜,ͯWA4G|&F#BdmeW+;XY øL4ۼ1 I߁R95 5"Kډ?u]}dA(+5}*JV#1g<}5yI|RV4˛d"d/8cBI#>Mr]܄sv^ؾUyB3JҹSWg- =L!27b{5~yc>:ۅpqtˌgQ2; #1MTqGYol;AHQóQ3If7#d)tƑl ECb MS_::˸UŊ ³:z{>m:Zq4en>m&w P cKa~Q[3^':5;ПC@vL AvkX'WKEd|ŲS}po3wSKџF\E쟢V?}4޳6|{q~w 3$ܒ6-q#^"/洯yX$rRX5<3ew~6 ) lD}2oؖieIkDaޛ[~n+&Ϣ$M@/ }#(|#[ٛҌ4OȧGGtNwSc':JeӸ=[[bv]oL^M% eP#fu6qiI_j:ı-U6kF #u^ s$'NIL 5CM߁0S;SXvF 10v~N4_I_ӢX-qW̑/I 89k>c"8Dp}+xA=M8g4C#c)]Y\cA!;``FB)iQK{H›BF z;В7<_Ar}/[LTNoVecN*͆22oو IBv2X-p9 t+/#ө1 !k |.{B%N nv'd4t?5)꽑 :#i")@CRk6RU@IZajl qP$BP?2SC Gp$e D>+x_?}K@8aY˽vIM~Ph]-Fq⾭3<:Wr^lu]IKe ゚)Kew6m @m[;!ز/ݱcsI ߮FS֪5zZ|_KQXILdD`A;O^j:(WJ_[lC[!F^VH }%pt)"t[LA$ Ùb4fl>\shg={P(Xv\dP{:f d5 D e3}:{>1qu5Y՟{k \O~\,"rH~!)b‡rw(̙BK䌦d4Uyyr =g1!D{|Bή>'Z*ƌshi0o@л}P[s[rNzNuCd5m]nn>N0A~78tUl-_M(/^YR 0*[ZXx >!0 'HddG/\ʷ׶pɱ 'S{=Sy6i!YWBG[\_VceM-+7V27z 6V'&q ^-lO *-H ?q@>AދZ(2Dq cDdA-Œv F7ܒ'we 'N`*QdN$H乪YbiWEc05}`$eb.{d(Hۉ+rp*@$.I>f+7!iLfPE#CHZ3F WM387 ?ao Ȃ+d-S}ʔ_ pzrM$60Ĝz\m7*D`k'<vWo1v[:Ϋ0pufۑ%O O/,`;dshi勹*bd8DOe1ǸXZl!x 8KC8OiݯYq}օCH|۰ r"vqDw";"s(G\zoxϪ^I;^biκ db`<2Noi) Olxi&5DS(efԢpš %5/[iϒ^WuAQގ&DS(J|JRJ=T 9/.]bV6S^&꫏#: b<;tŜ /OCPd-cQ͕côw*MFX8xAM TZDZZdGԤ$2ߓ'u-"Ypuſ#}`tpYWP9z\=&)5hȹ >_$.F/oIz9EF uG}3`J>ߝppX tƭ`*~^-0Høe5$#t,k5{%L ̶v)D6C].o'uг㚪)?g XIu(WBۧGq ^s/@ rK a$tSO(68GO,!%ģ:,bXMPć|Pݶ"xfb4[8$hֺF'rPHOa6PQ9~\'+5yz܈n0chGOm$ZgsSX$`Ims~י봠6pbɃ_uǗZ <])-4F@008ZU/ NkOOEF}@ߓ3/n_D,Gwɿj%@E|c,z[EƘŗ'$**9A_dd2 K{"'73Q~FOQ+* wt߇BΛ[ucA[ws;|h@lGɩ rc1*'-̮CY%o#fpP cGC;GhsլA z_D@I  MNɛH<9z2}^*&aFSCni+3| "#L\3Kŀϛ@Fs -a[~m ^YԿTTOD HawJ'LRKEzQ2# e>kIi$3 4a8EL k#"QAnh٩U1t_Sf`nv[-(i$`Kڱ3EwGn\H'hlW$0_4/!)%8g>$GF,,˥b^b1Ң[R}XCvbzf?9x W`ۖOK~ʈf@J q2865B% /ANOMLK#Qݷz; Edf3 @5O1tRnTxR3/ovú[0 Μ#6BBTȫdbf7`5됨[$ Y=^z ;i5ݟ%ʺ~.)Jj$+w% dkq$,4 ^GyXhQ(҉F"p(w#({Jghu߱}bNC̅>YK%o;O3\Gs[8JH%0i) * B@X,p CTwbaج :**(ǥUIP5 L#ߢ4&b/!=8{m9bbN,)hVJ0!]ɬwt>l ˼>繤lCÎ('sβƇ#qէs9;B64bib<_H<9 9W" w◪]Nqsi# Nx߬P֡pzAlX|Pcۨ GٸʼӴ,b0aIvmyDO#G -/i Cy}!t\i}Lğpʟ, Qջu>EB%0OV^B0}$CϕYqi#Fcd5ÂJa9a`2_q`( T8e\.Fla(re:>1nc"7<&Aiq`DO.)|x9h{ۭy@Œ?mn@3$umW}$q_吏/ p=q3zs)0 )=YMbH+t]#Ɖ k1Bvf7K K.ut5n Jf>z'n|HUG|ӤoRu~*01,nj [.CCw+?5}{Wc`Q~h=5}Ъ+|~_ikrx;5~__QX#/ kq*J\Y+յiw@uR~~$:4"̱Q@0W$7B 8r%N A;wXπsoN7wfM6%qh\M3]hySsN|׿2]o7> h{q !P49qXcY4ѷ/KD)ACB&Fy@0 8F0Pu Ed;QP`^J.I~_S{+Xy;:=\ Ƀ< 1\N(_/Y\7Mھ};vUM1/wLOOJ10+l",ȄbJ_ȟqH@j1s|| 4:U*IW.$CsLSqx uj;3;ULT*o<һ$2:4:8 + |L;'U ŏ%~r6l:ff@_i2?(} nOΥdbQ|}6 Rk) hHj+$^ԧn -$kִ{{}0ik+ֲ"aǶl }[҄wX'pJIfEt;>g>*IB*Gco)JQ=,t(nMkI $cdd{4-,/"k[xۺ~up$OrB ʫDod$R/\W]Ճy7xF V(=8JZf@$H@<\wHu)XkNbҷ >'_&fY~x' x~Ͻqˁҕ ,P@1[ݰ*;T)ԦEP8ĺ66ˁLPQ d-CR+&6FK4 B{t`]IGoxL$eKh5`TDE8G !`'dw)|;;Du0-e/ԺrsO+h _53'Vd=F d82CLr`@ΰtj˖)`kLx3Ym3 (T(TT,I(T ;Ϣ%,CP~Aӛ*eלhfz%e8]3 eЈ/~E?)`Km2;. 0WSsznOo?* pFl7J $dWBtbmEƶESz$|NG8llSI6d1ҥD7^#/~FRW f e^מH ){ġζ80W)`/`%gt˜us28 ܃/x1Z_]9"#9i}T.xϒa8|2c[x^iu-jgٯ'8meLa׳uT]{2*N15Rs{Hڣ/*5@?X׌DP\~Z-;ooZ}lg+ι{uy_7?cvr[Y !$H/Z DST0R&hfbAb5_ד@tW%83!g1}3r,6ȘC,\궐8<@,Ne}5{\_!xL䒞fg2'u[x a32w_i3 =MZ|^ᄐcA$Z7nB"'3[㍥JSF%_r\g9 :<xDL-V|#_laXvCwn. cf:h;tvɊBu) EQn xm7&IR?L@[`R( gMֽ9:YxhF^h5jtMrM EY x=u 0Xb5 DŽ6h( tyd%W3yXtt gw#BW8 &:_!R0H/cRZ#wSTxKRR  v,˔J0$`ٸN{;'w* ށ @a-ۣAg$ K N}V2Rr|6.E4S;'È\5Rv2/).}B*2*ٜX };4UXm-VekJ d[݉eNfرR\;M򷎞ǀAL_vO' #=I1SV ֺ`"4 ,,yMC5_SGZ4ι2&CbU]XW/l#hIq+P'hd@[;d=a)K5p ȷ}׎]k{*Ps})w/Ȱvq\yN @,d^ ǡ~OТѨbnXvZ<,# '!AoMT~1CE[{;L2GB֬"ZA0Nq?mm-31ٷw2L88N26ΦMmmoX~ }"k`#g͛/:+Ə/s]w.+GyѤٖG4ޖvᙎ ێj,7#ᚖmm|7TY^78iˊˎ&N:I:_inpN6vᙎ ێj,7#ᚖmm|7osăxv{u׾?c_ք36(>N3 U_AT__H%8NCܶ0S>!a3M}>M'!T'xԻ}+;=Wqq-hvM ">?$&`JC@jek,GLmHZ+WgQoKi.KU]5૗S8ϟo4!@[Lf`eAb85DDc-'/ocǎA1(d\pUkq `1 CTl:d+f@"a="&ye/)wiWM:_f {8+],ٳaVe^u!Q|Dztm](boUX9_g=fff+8 eVtγ?NK-K+5fW*Ɛ ΁17)AFQ;P5Ǔh H$RA!"pY>y`q㩕)JRkPAk{ =%Faէ!sTy֐qqqq'H1^̈ClF>>EU5B0#`p;=:008Zs z:_|{iff x΁=;*ݪTt׷k O p7*^8y`|>A pPC=<0샲UwppE! T*&5RϨzA͒pQߩ2G0lcB, P_m,^oh˅P{>Ϙ1B(hEBR$*ibVZX$k?_zӵ:s7 6 b'+atC 2" p--:֙r0 * #= 9*"K0a3ʂxft dùg!(*E!D=~ow|3yό5a/V]hVk gLzaeC=;uoE^,2Š bh&f&*pp6aTUTaaeT홖``N1Q4dc2EI @Eٔ35@f2T8pۏ3 3<=3w̼iM"#M4ZxϨ Y1I D%T~ xZk?_h4Fk7yi$Zf+M#騚YϪN()k1a_YywV9G0Q; Y̠8N3zj,mw׿\ZԁrdRPjBXGV7H:D*; mm~ɅCD XlFCVMLh.t$T^hJUas7r;5se&_A;~'-k>W%4e=m( 9i9qLnWItϜ3o93Omϋ/@  aGRہt\Ypd;84koSD>[ @l ydna2pT?MB s`t 6ǣ|n6 ;}ʳmu`vO#$iS:[}ձ??7?p^>5ЮbE =X!F"#?ߨj'@)`! i(BN_9Xf":yM}=ip?1dFN/UI"w>0 Pے'bW羧s^C)Q DԊ❇ [ `@{Z6y߿OXKsn?jP!*s2 =ȡy䈩|#TbhNL1NaXoGޯ;2^L= Wa:0)PatM.Tӿv16n^}l4.R{7ƯCD\v$ |<6+X9屫 t?%νLOkM3(ʠ ZOiǣB/'O]MfI ]{޺/1`.McU ^F|ܫ RK0esrbf,{)u)h@huJy4KRt~R%D(hOLR+H3=3y)2@(q'P>+ )ZuzW~ :!ğ(#S7,=ix&ˮDޚ!ъ 4\кO*0e C;Nmz)p..~h4Zƛ C#<ǯLGY9@WwJ\4 8--*R# F]uWQ]$տ>?o/ !e.1ՙQ7|0KBNSۚMw'8Jαo]Gݼ>Htpu&' `cv;Dh+W~! B?FCsRVLl`D@]aل Ei-j.XNŗBFI7[P`Ncf%^1*C_ 9Dx\W;!7e24ݛ/oqmHܣF;Q&SkE>g޺وо}=Xr*0_XG֨P|E5.-OuF\|>Z4ZñTqێ`UqPm\G!R14+Q+М&D{X(R޷@DVI'{{J "TI},8 >CޙGvvcs OG#ɦ6eUFPyLN{>j@^ <_uho|Q[qBaU vvp'%uS!ۤ):Q͆!<1kl>#Ts&P+kHc*$ ERTʖ[QR$ڗ*W$Kz:|nDLIRDD!(wBD*$LER931>m331vi %(s0Ds0C3'1 Tp*TW" )H= ( SjPpg{Fp{90F108N's*y)!Z5KdU'?'Z,iVD(pDOZW yKQ4dDE֢ 2j'!* 8iiኧe_ԭi xuᦿ馿馿iMSSti馿鮯%ˮNV!zdU[|Ȳ@_>[T}th8eJQQSTTTꊊ3#}D(h*j#/}#aM:( RBjI!!#Z RI*ZG:|ݿ5p53ȉx\;7GPyCdp w?g7bI8azt 8r.q 3BBkV~ƾi:-1i>bQ8?۫8N#n$ϗOO]Zx)S7-&*V_kjs3ntg䕚Tn˥XˌxK# }[ʞGEh3ʁO~]$2d Uj9~(ש6wΦ *-a"f B 5`xצ rH]J 5 R+K1$ '[e}"Ik5xj+YnqPBDf^bȰs֍&iKeoƬLk um9 2Y G^Ds'vY^yO(L2/p,aBߕs+[1'̓E8ͽw1dxQ\GG), nL|O6 F(U "Vg>8$[x%rA}Iomy9V:vǁe]uCcx0 $C#?a 2AL4p|LO}, Z>.ͭ t \+SK8y1Mhך`ur,#/k"txrS< mdpv%5#M?iUq.]H9 Z""bt{/e$ Ǡ"-"29j'ߢQUԫy]E"3~4 ~{kV 9hvћ~Y^,XR)X4k o;-hNT0YaGk>a^oCpֹi?73X?ֿ/A a,QwG|׎ GOsdÝ!@>ڀUPBP DbFEIPZ^xRB<n a y` 0t2j`*U+&hy?Gy~UUUUUTٲ~{?&f&g}> 2ɢX lKQC0u~} D˳bt"U|߃9]2YZ BRf.  69 V'Oï{NՖ^Cm6/Xg UMfɣ>Z8(b ={pܟ2p(.@Z (i D&J P>=Ͳi8ݯ}ҷk_ǀ9HVFD޿%~cyu^v_Mo1|oLJ8vmlp7yv-PbV с2U`!>YԜ=bCF bb*(HIdn_W$Woy5]zOONVR``7yx|څ&1 iժ+W~9 ܥMW&Ǎgvlb 轗l B8W?ڊ ;>)9eNn=Nj9|SqޥlV1sE6*E!Y-T'{Ǩb!*h4(m)̖{`{F/tUB k0 `{„gFnƈݔcg Ks.S}1$(9 L̔Unx}Rň=D2?TAgh%\oDɘ"yw셆~U/W3B֪_T2&R7kx;йB2z Y{l=@2֟X KpJٓ=n[rx c$GjnPci@:f|oHu*koczLD\͍]ˋ_khQ_0S,FʯWhӰɃ_J"vE벇oA>$lj -:%{fR~s_c;lYª2vZAwz[X\g @uw.cW2j 3edSȋYi3PlSah47 n5[rw7>,1ZxgU },gu"}K׺OuٝZ9P/-@ `9{)s?Jm;yÒtaTw( (9F="2_ac :7 Xc8rn3&BCb~̟{6~KB$Cp/_#Y;/W;GwkNy0+ьo;;LѨݓ)኉ux:.F {Ol{Nfi0> HO*:];(Ur .3<~m'cP۱j)d9&; r≯SGP1h^|8E%f$= i5(l}.%m,g%!Z)n/5g7q=[ȶpiS2 q+{v-#wP6],zǬO񅎏>v8b&./r,^K¹Y4Lґot?63Wv-dha꒫\5e9ڠ0m9>6*zO4)6h KCnxR c %N _fԻ||$'04=5}tCAh[H2GiDY?M٢ANd|Y y"Eק,AY3`wSSa5fW7KZ@T\H}1~D{IչZLB+`ӳ}C;}Z9l |ag#DXÅ\Dnk;)7-؞UY8:s)A4@&iIʀV.=m>@1챛)@l)z?yx;4o-OZPGJr8}jg/˹57x;~2@1ǘ'9E/;^zeҨͺJ_$뛾C@___;baMz+ZYM^pD$$% Q݀]+o_`u?WЗo%I𽳲t@yk2IrTC-<}w^mj3333o[z[L0H&ffezN Ѥg332ݵ |*QG^{d噘{ǡ߷n Fp7ϡq^nӫz[w?x~(y;}J)e>3D5-@҂%ܪR%?_n[ 6iL3غᇧc j!{ WBID%JR+V(ZR%KP_--cDNww{%d_ӎ ] 69sKѽPɇ}=~=%wyPY<cyc)Qhv<|#0ۉP`ۃA7q*1yʭg?wU3 knN䐣\>2{PK -c:x M:=3ݷYxOQ( X-]X+IWӉ @=K\WWIQUUZ.2Ѽ fC7\EJfbZ)bNY-БdD&IK% `v3?f@ ^@8 B *fŸDjv [eSa1畬v<Ō?{GSdT-6=b d1Qչc̷-DV/tmp|B-PQYŐ-;'k֏EKA')jycFGFZ〘Ã\'yblt~.^N-/1샱QΔq l"lZ\Eg'ң1Zr(j}]$t\+JDbVDE4Y6J(M|^f`eGD{0<MW̴|G{'<}-jIYKLY4N%ߝ`)'a^xi时?!kcMw󋥊,?&bCiډz~V'ۏޡݫ73ޠ%ZVsZa/.~t),h ^JGi~qT2 $YPogָM1gcqJ{< 1).$>uĤ."`#^,D|HL)QO_eϽ3dTlO h5٫TūM>Y 𪣺J%v MG;!;Y%#\V_S榲O<{Y܉U7oV 7nyh:`UZ28Lg1y oW[^Vl^]{!zZA.}ѺZRJRx]};BkE6?ԄBvCD+BőX0a<vۥFws]VӦ{<=]̒~.p_se}˶0Np uAz!B@[=Y]pȜ"3 Lj&-v$BCEKBbxxj$*A`'[b}AߏIԁt)m=t`01;rۊ`W1Lʅl-3< "uJU"\<3rYO|+r=0Va]B}ۡ4`v*Cxr{n|`KbrԿ=S޶(|}7xש,t= Aݾ[۳(|(pAZABO*̱wB.OT8?zm8,ǿ#ެ/6F*\J .H)Nsw$a3P) AHeDYa8E(d9 IK%U@dfbDTEHD'#&:8p!s=ץa#xa&YQ{ 3=C;464b>s^O0=D}OXGf1 U KbI!-@p%;/wТu p\0UcG}hxk)w٢ 6f^.۠|0ج"3['>LƃV$2%^P¡ S^ u2'̘1u /hKqHc&yS 8‰.3 r96{ uJ_-7*4HQڅ~73F30ӧյu";E%ze1R3hu%-Awx- ^r)̕-GFA7z]Ym[!6`X.\`] {lO"as;كjA8NB;9"&^Xp,$VRoC,0x/g{e&VFBUNe6↖( Xcq.?~T#"%3Jo8lYuZ!Y'#%\?1$(;(1WbTG.DC; q{e(L `6}O߰d]OxnKbn$4_q8+*[Zڀ~:/ IAApKV#10*@.G{ g;oBHay*a 0[P/$ 0ʄ[]HwՀgXub|?%vHs! -`H{32mFb[!9qB:7%1spZzK={_%H),ni-@A~7_JM͇KOw4~&Vx!A*ܿpQ?U 5cOóOIEʂ&kƹcO(Va7S7gkM@潑 Օ))nak$SF/;]Cj!G8@>^i]uS33AR_bK>çDh:3]RzD:yʸh4wwe> \h_B飠? xt{s2Ja^o~ݏQS0yb8e"W߿ՉT U `*r8CZ$` hoq9Z3&^q>]8gHlsS6ʺeLY.XXGWs,E렽A4@ , br)XΥPRY@ܸmgj}ݚv3giߑu@ڡURT;j"cB \E5n qMC/IhYp(8T+kx wr\oܷܳ0?ɌoڿO{_a(9י?NYs<cG>jDj! hVC ds}_cJdxoD UQJX ]6*CkިPNw;g{R;-p{lYTiCOOB g>^BJO_ '׺~nY?ow_ Ղ=FB/d^iҸgIPd1-"3fLC۠S2~և*Z< dGZ B#bQ ,ýBLd[zW){:&ˌY 8.!:SEڬ-Pi3څȋ RvZ1tLnGI )HdJ`S>JnE*OCkYs|_g]Wǣm?aY@6Z\Scv1LtFL,Hu, pJi%I+ZzsH>~OIڴu+b J>H*)@ogC,X3O$&JE' QW(L.B=`Ԓ'  tar 9zKz6 rC {4l| Zx ?X.G EB^ )X1#01 Imr϶uV7aH 9YVb TD` z<\H-O44=wx EfUaծљE[Ȧؤ CLXCsDuWZ];}R&A?DNqGXs|Dhg0SؖDH[ۗE77ˋb|TF=NQnŻUᥢˍ쭺]UA5+ylLBEa\J:Sˑm<>!cxoyk! i 9~}$5Bfonj0E6L\6W}Of}ОpȲҫ4|t+~aY_3G "XDnJ}lZ\,6$~_%n\ Yt)|W RCęGK__!M. B_loۯt{_O^x &u׾"?n"}vFꅐ\ _oSy&WA<+5vUu;5 `rQEK({dNIh?NN>짆#b DkOd_~УnuT_f((1"SY>܏&r4"^f5^Ekv-u YsalJ\ owu Yآ^rȰ)EjD_'XǗҖ\`(,ڣ@ӣTѧjvKos{/[7-e@F)»K)J ֲ՚iYFq~^בv?cG1&sa_A~+-v}DS" d>VYfl䬎u2 Z~m0C?Ɵ:|A+Ƅ}1W*&FCE^Y XUWԫ ~@/ד5-kxwW3k8~͂aT+#WhV{3(_9!$[@kWXkɕP>Su;KEd=nWDrͯqiWn<5M,]`-fjf` aE a^?̓۞uCU(?.c1YD\xQ6KUZk BZ(=5K[SXue༄S{ ќǮUw Ei9";ʏlV(yK 'p8qY$X53q @修:w6zT $ *>NkٜPؔMyC@F !WBSU*WQ!Ps߆7}O~;l}su^8?3}sNog^1z /k'# NJSUDs'?y v+r4>80us7;< 6L=Loe&מm@LXtι (,3OqIվZJjM T@~9h#AeqKf9ji:хc Fȫ YXQsFқ5l^6gi h)^O:cEܩ?$@笜Z2|Jj]p#cKZf  1_e|4vGh8 G~qMg'O >ҔkqYѵ4@m<^q2:LBo2.qzrS Y 3'|A`T?9Q%==}2b6cggmoAkE d!;);-ג w|mA@ 2zD'?Mx!fj}+V>u^'}Ss엗A*M++Mwts+Jݭ62Ա*_EUBp,4zw29&,>~KqǷT@|9j *l {ǣ0Y#׏^ ) -[oxE[ ,tbC_/f#q}_2Xw.ay$M9ӇUde8nSanKqN!M&y8.CR|Z83\oa_N 3FKx*g}i(wHI$IF!vJ<~AgצKuޚ*/w$%J ( Wlt\ 2y 8s b >< $06Oc+E1s-N5ǀfcXTZTH-fj; dl P jYIѾ}& _AJP&4o5o}׵{Fc绌 a кt, m7 !Qt"V >EájOyL뢃L"޳ѶGZbIE DRػ;k x_xs8@I$^$F:6 ayFd KqH618Ga:|7Ӯ' Y%bIσ}a69x0#7b`>WmxX{h)kF ڢx_w.բԐ$48#s7;ZԴZ';@T#$),:l\}#st{UK>m0oZMv@s+Pn B&As$b@V&М@psq2H~C% ƚe{a LB1)n;[Wwyśn;0Ž62f^T*ޯ?t3xPB SѺ;U[{IqEY`OvVWQKyE6 KzvHrNRt݄J*c;~E6]Η-/lCo>ŧ)z^64(LN8@Co``"{8Utj~"#AM"y:qaK.ښ^8fNS/zs]CLֵiiɶ~K`(P~Н@mb32G277 lPy8Z=hJD9jnd1gKگx_<1!q^6x{71?'6-qWջgzF NMyگ}r!!8镑!$KB׮i5cӕ8-"8NA>9K]16Ϛ/fD؝jbӍ6Z*tii98 ٹ,6ԝ5W?Ot]u`T/L$S!1Á=0Z*%F@H3!AFY ձ a=S_߼iz ȈFUCX䒥>-cs`7]/~.UOP NXNs4){P#HÂ*XQP #Pq٭`)(Ҕjscrɰexnׯ^'?ow<\vh_狄dLJep@} 2a[Mo9~WTvL=tG{y^:I8O}{?rUN(4{3:~Ӫz< ?*"z>",>0@˂8 5*$h݆6߱?cv7ަ/uO)=`@}9VH<@ߑ<"8Ä(d8\}ۿq~H|__|' P23LD$!Z () ج*P}~Bw&T 凞Æٸܖ$ky}o-r&4ǜy3¹`%+XU) I(i<*Ozũ˦*5xߗVSP+yk{ۭu[*<-g=n}gqal\?"͙ZC9mV|Me."#+p.eU&( n (>2A&#G/@uo:K~&LxHoHLnLeқH0ʲoY"oXDp;O/a|ڲ΢ ÂVTze0ɣC4DڮGe\2U^1YAa@zZ%8 GhBeY'pZΥ@ȷG`̨_߲l0SxmL \Nq K&$U"ʕ,J#d|, @g.1/9}D]x&dr@15J紾"FZx81RLX nU ݷפ3;"ޚUc&|f8?^|Twjbw!7N%Yd]<8&r@_RIM(JOHBmw)|⨪[{;_ˌFӊDMuZ$DWѶ$kUO`j8[,7P١^B)W#a|=-*鷂I@BRT=WŵY}&Bc ~n؆GO1:שvN#d]7b]>e+VxJC UoWeY|4]b[(DJp` իSFk*+{d7+ޡnZ8@=-**C[_>M]L;E76OLȐCtp@ҚV\E{PS"' (u!`P"VveoqM"-! \!f$<_Eٺy]ZNUfnh=aw2=iά,3炱2Qٶ?ؓӝ=俢xlT빉e[RxSaι~K yU=Q\zLdwc*Q7FG5233b7}v$5.B{(`got9ՕONL]TJ)rѵV@,RM[D3wfn$k$v0Qג$<+^g%1M̌KFwH;62ʙmq)U% \,ybTE ƨF2CwzxRGkر2LzݠNRH͙HUP*//5iDi@tft]^&$1'oDv 9G3{y>[oG} S%}F I|(8b2鳧~X0Rl= *Y>kx,O1srt}|~w aGo~N ؇V_{YMN1&xtot M_Z'5EY*/VthRjި|DJKbteD*o_.\>gwYK?K x4_ Dqm1=J>.gg?]%_Q ζQ;4Džtu)逓>;0X'ux1@1VO7LZa$ ^eLqۖx69I/]]yp(Z[*Bk犁g 8Am]wĞZk*k/G?@ Dttft$j(,u^a>&c ~;\IVwgOI#ٴRO@1@k}%rN\%x+Aw={!̠ !⻫ 34~I*;䈙?[y\[o8 6n=K!b[taƹ4gI4wB2*RI,A#" {-e[8V/ JgWzJR+T@-ʟ^"v6rړ[VH-Aj{0uqjŢaZ@TD'] CxA;bo^2~3\I-z–d}+NsMRsĂtz?Cv5gLc :Z g0Qb{C dW<`bZ[r!lȀAqΦ  ݶZQHM\J(&62刜 $SYz+us7L4+LFAcZd[*3!:>E,+5˸7;lbꯡ5ĭV;`m^" Gפ"I76FS]ެ&{@Pbt$^JIv-c22lxc'~&r? }ďK;6T< fq-AP)-ui7-, sqgt-o 6/((߻XX $8vkrXHʈin Y⣖H=g lVZ6x|mS *QKKBfCiLffG/!2qhDӡ0y+Lgu{D6rI;7cL8E~W#s>D_3@&my9n* ބh Q^I{ {+vsw0nϏ/&6LFpsisRa|Zed<6$4Qrg'lv@#,YcgOWRfOww9&]:U[I|$pEo-j7P^l_rW9קrQ16GsݶMEzBtMi2l "'ɍ*kE`GZO'T(>F74ybˁ )Yz>FNS+[Fd=bfWKl)NU0j LzEàoSn/jOD{,JӭnǾzWfu=[{FJSZec"Hb%Iy#smhJ'+vHiyXy4dP63oAG#if;8r(d"Ɓ`dDQ'VT|@C~z[IIhe:NZ{P-y:?]GӜ=b>*~u ~Cs.g8k%Vv%]y]>[-x*ϋYR:kScN}_hZ Q1vdUeJ?x)w@ %#MM ,EH:j)e[b{:Ss**ꉛRE>{r0318*o.r@YPVW<<Έ7IHt[ /%\ru@|[Ff.yp~WyU|@R$8;\@VK<(X( *} -={}4'kgxY'.$g@VS(+P5TQzF?d˳퓩λ.u/C@Fh+(l#m­|^:j{ 'Bi]ƋOH$QZ-<}i@6)T?dBJB, =˄xnlR5doуXLoE);MAM̅~gCvH"!ߴW<(>; Ԕ)S8X?x@h6TtHy}zXXCDbRKBkV}'/ˋV#x-DbrG6᪫.Oj!zc#>9rBX̦ 3<.䉬*,64 C:M̊L<+(z a7t& Oh A˚K+=n"P c-A]Ndi g-]K`QHn2'yUŽ9/?%BFn-Cu uHZ`THl5O;K 4p V>HBs؀Mat S 9|傐iL̹dd߆d?tӣv-1 \NZSzWK3Y-?"r'EEÑ;#LO"ZlK(}ak,;*ݯ* 3ːJk?+JT/a*loJ3?!c*I-g5lSsZoO7{2PS>'Gɦ8@B3%0itUr v㵛_2FҊ#bgA}Da30<8SZw\G)\GAEIe2NOR0PgAbNȺhj{I]6KE|S[+*V,H'_nv `|U:~ lƶD*z+5atRs0' kxR7d$z 8ea__mm$cɜwJL)(.q]td|> r:!Z?w4u%?#";vWJ-Z8~T=h6s5bæZsRJWW/W9]5z߆o@Ht$`IuwYkq#ߑJ28` T>SQ W"k zy9tFY)\eokx}g 32݁IFPŷ-0$iYNnN[r^|,f.Z:gGbh^Zsx dB 2Ar$P -7HUă֙i Vh=".ulJPl4*̳%,iiޣ8nxh R{!oV'h_5J,5\(fyP{?2lim?9)+Ȑzػ>+7!M>CV@?|q7ܖy/q1n@:IzWBh1_@bPҟ|߭?1m<.3S}%:^Q'p1y 9[.Wi%)֤v){hŒ2@2^9ڲǹD^y1H@&<`'GOaf~sm+L l( 22ȧ33‰qַ1p 1IȘ0s#02ḑ5VKadsVI7 03j|ճ1:DPFW–5^\s?:.'n>w}?2ڷ? i{w:?a`2JH0DV(PUcSj/:QTPݩ#!kQ.rm/|9DΠzG(&nz۹6kˆ@Ezp}Nt_->Ҥ#cEW;wjc8ƪωUS=[]ƒ>]4+k8620;83֢G$2esF>، HN9ӂi8!-!m"!9@ / oPi,qi^;,r89T`uUؕc06ɎHOF qg޲Zh;}_-FK1NG܄&!/Qe5_W_SD^s1 1T<{dxn$sC?jJmBuq;Ck$⁣&iS 5d'q>$I][17ibsf5l3C-M]:l4P<.p$gcrCO3mQcP?)"~׫jz߂E}Y01l0;- Sx2>H篫HyV7`liD&ٻopl}-Dmw*qץނg>"h"A5F|C$֔PL$QVa7eQD[9@9&U`Ycr($u$/<,Eh:apğGw#WCQf."ļC;Hڳ㜶Q[eql8$0* ,sًwM kIz ՝O:'$?KDm0'abI `{fsf0z܋,`V̅ aZt"P"!*NjH@̸G=?qOFp19tNdgC@J2zS.fe"h*d/B ~p֦zY k@RD!B I2EߔQT˾q ?!f&6! F]ʺvԐeKj,lO*Sdq㯋 ! w' J.iy>`1t.07|eXS10`^1"GBٖ;#m [OSc$3֪xi$#EiPO$Ҽ4FJPj+O3 Я5VNR~u89T`c@G̲AyX,4U4;Zb'Z&t@]u"5! vna/DB#/m ZT4C!PM&T2C$\4C?“2!s:s ;Jɷfe*b:`7:d L`c;j!44| h69b+ aI@z~~L)(*}TPg)\3klEǶ$l'~ބZ}=~sN6nHlz 2C8D?& ͈&bA5CRxmDͻt0/9Sg6 i|xr{tj/8~O5t_>OcXk"#HsԖ *Rlx22 (3')-<ƶ#kTXHŻ>Fy9wv[) 4%kv*;[e]lN2\}]c,rK 1'a2 jF),CϬ,Y14)$DBs@]H%YˤK`TJp&J]4 {k S\|٭^Tj _yV~Y':T 4 lW/a1!zG5HL[qsºF%v}-ąDO L5ǽ1Zi:-0\CY;2g9CW"(b<=Jki)l 8To [r,Pwz`29+_҄Q1A @WH m—=lí\)(^UVdt慧LLEV.™-Ka_N9lHvquCSo (E?d@BO`Oo"=qVնOۇ-ffffy ffffUU9! T?#Mڥ%)J_QKAj.(]VIdA*X4O@ꦪU2ɘLIJgj$VH2TJ?9^#(_ϛ$̓Hڴt"ffJلeUg8ۼE:D7أ9eδ9¢^9`~Lʫ Xg贝ŔnD( FrA\WwxDLI`?Ç:= j, G!w?x\hukǻ{MW7iUnQذnUUUUUUUUTUU}YXffeaUU5|5gU^HsXoR2d%aXQ?'9#DErnxM/|_0o/y_A0Oh{ {|:?0j݈]%}xppKu3,I,8+A88_AWy>338Uw333``mdg˖۠&>DA/.:(ī}jǝTL 5J JG3bXn/cyw=?{s[}D޾vN{ݱ`fƤ,>Oy1U@W?@H6450@\BG4* aU~/3*<Ǔ(qo~274͋86 )(1p(e/[x{s㞠*ףx:>lbᡦ'v1m4Z ;0,P1l> 0hLU )$̙ h> #ρw50;׵UUU&àN> H0p2ɣ,1gob9_~>n,fxϋ&w\U r%cm](2ae(r oW-bܰФ0D7S: (98wO&tA!$vDԲ, R 04$ ݎ 4m0sc8Z+F\0,z`іrѩyU乣EVh,TM3Y} ߶a3,;=uy ,7ѱM"o]o99$3 ZJLAE&O4V gY3i5$ DA4x cNޡGxzOO2Nu;ɢbfO;gӘDLdn' zz09GvorfG3N=J,0ɩ1$zcÆ>< RP<@sÞܪs 0cy1W/c<ºbY1d&%HS,/y 4< y 1qcOC8KbdँH 脵 $48ѝ+'*(u8\sGFDkVR^2c9.1#ӯX.,bֵU:i:Zg13pLE9H[A[nI$B7v8BΔd]>Pӧ$`|`}7"n.x6n1Dw+cS'ޝYX6sç3gգb;~yiW^ir׺#=3Ӊ(XNMۉ81m Q@ݧEB81@CaW$}+,!̘ tbC_|Q/dȿ5!OY/ QO2QE$TY鞚%EǏa/SAÓ_O܆yqYxR0W X\+WsrafmngH bM,Zo_/-63S""/Lqj skmzx1.$I%aF)hBU\rM1j,kVQVҢ%S Gs=~A !!^qQr8g1{^k%O#W7\6c ̳!"$pce}]'-r>vWl$T#WM "Hu+ԎVSDŤ[`⋑$0Qn4*_ ޭwގˡ #B^_^[D#-y1ymbFy4ѓE_M( 7Y:z4^WPeAU?חeg elbsyOGq[2ChM@1xŹO@֘A55]|*.;?}9=1>٘D0zdxafk'UmC=DXǾ -\92?֡\<9PH:L?I~GRY~0䞑Qjc7mϬ|o=Mh0gՐ-iPh}cB/ kZ ?wӓ6VWߘ^Xi٦ #B-,*E$ ?knͪᖛ̈́(8[_qil A" zN^,^9N+{є]Y |}Eth5q̮8FۭR'w[7zx@ _AU#h]\Zpϊ6psBW:wOYEك7)Bܗ|ypsl7ܣr]rl*;,/5''bVDiseAXдZ+i7zX޴s٬6aO/ Us߲vն]\n6j m 9hڎ4#;ĹĢ% b랳مvLeqN'JPPӛK j(Vq 9X{:v ޢf!~< TY>D_2yb|2rToɬ3kQwZnaz꽝"f1=i՟tfnm95de @CC-dpڥ> (Jj3Ѽ48rh`bGnJgu`6/Txe_S6sjhX{ Ȣq]!gp^h \OOstY~Usj Z&9GՏgFX°2z B}m ]5(4IRx=[8ɥ"ĐD'MhECd)).a 8,"M4 NY(+!*NE]VV6@3&Z&ćnj40^>*+8-9~nbhb8SJLxf$_¤H\ zzA$ BJH:8p* 1Ʊ2HB (e_eTHhoAdpu'c#I{ӿyv0n:PJFA# _𙄢-v_sr'c9UL!$i`agLrgmY- lƪTUP㳩Ð,a\F.,&2S00sӝ7ҎQ*J{b!#Ё"0*Чj#8' 9Eb:ī?R@~?Ga.C 4hJYq+S8`ن~2J3 .}QH}L~=$m n(߾eDL@V!4/)'t~YAb b %ZQQ)Ee!HHMn| Y B8T2DdФLQQ+D&Xb2 1C0@D /`!E /݃>ņ (҂.OXMZ*D0V%,ʃ5 Α$JaYB]VK!  kވhQB!"ndo (zDx`A@;_h#xW- /UI!3e~}rF|1Y3wWfo2iȡ:z#6aF8·H1LmԶ* SϨSCI AJl5.cс jVG zfa~)(! 0't'% }; #BR v$[ԭ/ux'Z^jD]J2 9aQuxLMr(*@`@iZBFaA B`?N>0GP~$L,3$mM4"`diFJjRA a,@LG50{a}4`^ w["X J_@Pb~>!p YʦSӢl(B%0-\r b40$)%ݳThPs$>J+H P ʔAID@B0D0ԐH$HĊ@AKDJDD*BD  -*!/G? (( @y;O\Fg@蠺WwwHCW2)KtI:뾺|l]سE(yAP NCL%Ji9VNqBvN±aQtpڐ=t vtx׸L<~}>A@,*zu\86ff@ |Z`6Dbu=vq V39fs:M[pxf8 @9ċ\@́.+|sCNHf'vz;?o8~ $ \@0RC'yhՖA>X !~Q7(JMACBC P]eAnE2-]OpU( @T"ОO D>/NrXV bZT?;8^)JB SM@?~|@JBD]6H(ڈLQb%r#]7$Z)h jz2.B1Ga*"Ȃk{搷Ps`ʇGa"`'.?wz9gy;1aQbHf(vq^L80E |1N㟒Ч]zr5Ѡ, cs+MjVL vӮ8d/a.ճ x)ip i_y 2M2Klo_2xHHK%"W0k8$f}ZUn؍`*7}$ ;9հPm-*/*:Lw1twfP ^4n]DsUùgGxiILzclc/)Pm1ю*OOha*q'EU^)4IErޔek$^@)pWg~xUQB4#͢v-WjTr-hIOjU`eՋML";ŷѹϺv.*bCctXRx,ƽ$B@ԃC6v,dDAgKWwkv~r:#߼ogkzn8Er Ism]Odax̫ºN!PQ =kO.SD㬦Ӳ&'@?0L#i'zwn> _kxdip H@ͰBt|1z2dkiJTRG RUc3oSyC m?2 luRIܿ\` Š|ғNK Uc@ QBO;gtյ"o5UUT3'i fQsG @T ҂q,uۘHDDr2I$ ũE2GʪoE 2LTBE ! 0AUHT@PLRJLHEF(E>[;, |_ "&,HcHfp3g#"2bG,XP \EOp~>}2er>=zȀ̻ _CzDzqDeU RQGC~<n2%t9\.7X͕ȅz'ID_< ' 2D!R ρ@ ]E6?rf@&9Q1?_fj 8D;j"ҌM`6DC'dp 'C+M$(,J[g{[TpC4G|ڑcY ů?R?%c4>^W53թr2@C2况ɼS.k0cә KAkQnv{oNW!jm(㸊-{]׽Ysq妟HH8@C ⻴ -KV/XQaAdXn ,-RWAr'gPOŠtߤ~o%j![7j(-"MIA"4il1= Sxϑ> ;x oM ;1x^}CЃ})OÃWs>SZ cIg,@yk$ʼnCvrUt_-XR7EPs /O1tJ( P!"Q1Pjap%B)h,K@r?PNkx:>R0*nUo`,6? F(((E0Џ!TmtG1^˔#I@1#*ҜS%KAA,0PDAL!XE[콞43@:PuHH`PF]t |螘tf)"H22031\ 0q,!ům#fHA $ȧQ0(XJ*t !)))$IThimwǘ(Xc *‰HQg|F@T`[?bs|%̓AhB Ff,|9ᙁB;r6> ~ )LX*B(KWD{ @8!1ɒhm xnZՀUo+Zʁ(-]25W\ )`3+-Y.-@8aa)#aR`&0`!jJ:"fPJr5b) 〓B|ޘXa:+5$PCU6sۘ Q]Ɔ)) G)^׵|Yu'TdccCcbffr^P ,|3 ]1FeP|^VN]<S@H> YlG] Gqu% !(b'8B&T$UŢH! O[(D"o`(H&Lԫ7ڶ`:e4] hЀl>CZ`Bxp?q:W!BRkHXow<6B(]H~X +U*I.ւi>vvŜIE)2]brs]F" j\ټ}&&Xt[bswwJ#>aDžH~YzG pƊ)&P3<%ruUnp <4tF`)( A\|$(' B \Ȁ5O>箏,4 +$b&&4**ݭ4ES "BTHE Kz|7 J8pMY,E~4{?Ƅ΃"HPqh2WDUoKPB HR+H"| %6)]\EM"VbI ">/zٵ[J-F#`I AU d1 "FrT 3`桖NE7Y;[/FK`;/b&{98X̞;5QO?ax_V_W}~iMzS3st<~ kI!ER8h&vЇΰЈ8~k4T21mHoA7d.gq}{DF!x}xmwJj4sWT88^;X({ik!EZugĶ3ҡ)XJ2*=]4 U/.? 2wG݊|wqEE{x%s?@żO<ش5l߼DįnNdێ pC`Ƚ*.qn|4SJS3&oîs>f^ns=B,`{䘀HfCy"ch ctG6b& (vvT$Q_ymb\讖#|cޞ H%*1_kbYhoj(]끞 @G&dm'6yQ,Ad:7ч&ةWoHiB|64ۂok'00_ ܮ0ކbvDqyL@/675ּ: j4lljǓxYjKRF Kr7ّ0]ϋY6/afpޖ=gT*-0;aIe σy!li@ kC` vMkYkҪ,XQxt{54(a_z)""; ID m(ZEbl|ȧc/KѽeYI=yPm14 &Mqt'4 zacBWpÄ ip,h|_[k>pME4mE ӧ'nΏ 6%!"L&4PgC,8\  k*jMhh`Oz\g0|a2% ;({hrp 92b5X:%I(3D'wzm5 FǺӤLւˍ$h"| RroA Ec;=$)HCMye""(<ļ\| Ó@7qe-MQXs[Hs9wyaZO[#$¦Tr@Xj0 c4Năb3h_Ί% =DAtB,bݜII-ZߥXDKC-Z\=҆"8}'MHF3LL L=1#XHwCj.FUNr$`'t+ :1 ܀|cj_RrCc>HqJm(&7K]zY08 &HH-!!V @Uh9g:s;9!=Ѝ RG @AJasq~N9(_n5zsӯ|#s$<> {CH%m{^8Bޢ*9#"`DXXt3,Ekm[9ǂDI}oQ6,Q*",c3P8oDoXfzvx+9 mb `qfb0j2wXeBYP[V`z:QM&[zbk#mi$ Kr*lhX哾5f"1mR4۱8M*#tZu1=wGrw26iq`:o^p$3ђqail "/:p1giw&1bf]n#adsy"E&M6C. /ԜX]gsryzU0Xm4'8qwC[`6 5KCrN/| ت{)L/$и=v|0pn1.<&6 )dQ17qi3OUK}5'I{'BxMJZCߘ߰8GoeIqœD"JnAx"@` \]Z-1m\hԙ6,mb,VIڪbO! oz:0hHMD>PA`m[!\p }|x qLN0k Q&"VC.8Y֊n6T~dK̘%iyX0I˜MicKFcR0"V"!)YihF.G2AM-1c #PQ=e_`W/ĊN87hard׆ųlAGXcjD+%VPdEb@=myu$dhV_sM]:Fp r{d?A&= qAyqVY4٣!c qٱr}l Fj*!f_^_WCbU^`h9G}iUb4Ŋ5,^Q!BA%R׶Qq(~,b>׭1#ٸx+?VÃ5=w9[;ن#7̱kZ̰%͠*gkW?A.>2z_x]&)JR)JR)JSkڧO=_O`d9*D u{˒WbBIH i|^~_m_.ϼƬ-^H$b'pӨ'<,jy x#1/Wp2TL1BdL4U5$9ˆQՃtg羧 oY]QBa8:~85SHӍ6ڜHτ Z4;BSacN5ef`IzU{MRHN5Mt% 310c,01ͫ7 `gHS633-!BP& a@*PPd<#" %d5"H°# HP }_SxIC% iޠ0[ X I.Y d,l34$DT=tM?}|bG%qW$Aa;?z`PȄ@?qC>= /z~`*|%V~O]l@c376BSa~#@Gq |;!Z@U+"d"}04zBa 00+D`tHa`!w% >0+1 M12I\GuqVBMrWozm(XæTӽ\pD6=y3Š&ve߼8*b3JQ 4A-Gf$d a@P0V! )wK &I,%X{}w:ϗ P!wv4J&`qHzo`mf-+\iq)bsN*ͤ\S~n׼:Si8r%M $]F!A@uy9`ugpHP|7fm N]@nz#Q2kh]%Y 3-̾N=o[m|kT^"m&WIbK֮gYЁqߋq}پc -C--t$BaV9c,WOhB+hk,k\7?q:>QUg|?'LI)@($O%L )j@R*Hce|F QAx@( 1O 4h`6+E~p3.+a[c[k4fFH1d!idLO(~8@D s^ gn ƒ09###$jDZاe`k 3,ipuck%9G k @TV$TC(ch)u`pp1 =TX`)(1^8*xp;_o3?@OPF!&aAngz8uNZZ'x<۽ tE$)rV+:Ј `/3$HLL){j%KĄ[$#.iD{eyC#NZH(Z>(D`p~Pt:044 =O2c4ԏ dxP}D2a,8= P%Ohx H#`Cďn5Wuh)B JIGS$ ÷{@af&VV6J. m*d!J3'\p C> (6HBp% uС{?y Kb 1S67fwˢH(i`"EUD`ClJ*Abʔu / )]u$F̥*E zpHl5l_fZ=q]VOM|\8C]_ as͑[EzgM ce];i jBF Qp"tR{MR?R9A,,qx; a߷iJ9h43C~^[Doʾdf-Դץ#1H,{^ۼ7C .[B^?p cc´s̓A@$'-@igxԡn *H B3{|1Byh%p49 \/) װL/2lǁÉS 1AD0О;ɉr?iͱ=WT^kؐ}`JI˦P- Eו`ΟM BD(M]~c~kqSEXtndyqUX@r`Y\o;x;:};)00ўuv^& á=C0[)V]>续 bMrPN奏.=t=6v!H RJmXC&DBGRC@HvNHqVe$iSN7 LA@:c'LMU;?E j(H+lKdJXc4"RHĹ 9"%R -%I@*n쭟UW7Dz|=;/s#CxDf˩[F@s(A~Ŏܶs\ OF4HHIft {8!PŮ:vT5iArp"}jq*E EB H_axܧQx{@kqؘym,ڻ&/Cz\08|b3II0xsPEjV6m/W7oMRN|CXhZ*ozY#1֏|DA9]Nچ~Nͽܚfõ\,ӅSgdࡽO: 'a" 9K-&sC:(צ5ՐwL;ҌpXcPI"7D٨lf (L\ P晴}ZU%,M:Y;'QOGY4.b'QX?xMC.G ^So\M7OQk{l])Ǿ2B_;`'}fԞ3<}Bş~};_6aR\HTLGorBBXmIOm6@T @*.8H V!E@8ɉZܠQUv4 \[Ţcx̫ +W#,-.u.\4b;Hh]CA?Έ>d(q@0)k,b0s^%Ćm\SMڰDȓwޟlEƚ?lhҁ#BmcRY*nzS0Q [^y)IF7 cA /3j|P׊TΟ9.}\ { JADi )`!YSHGȈ=]LS#I12(q`p`"N+7VnuХZ6 {QqWfF:?30xNǕhelA[+_u3Q*N晥a~c,@@KZqqM00\6| 3 |@8eA$WHۜfQG=ybs v&f<:ٔ" \(h!Di:=*R* D({7{d%[п16؈drTB N(k+Ļ濖Cg7+o]Pdb) #@)RP@H2H4#6c+R)D$$@w][q܎kٱ&e.'_Uoa8VObf*(λT_ ? ~UH8;a Xh~3o +Sn $'o黌z.f0D: #vlzOA Pٗ^ZCܨ ?d )zU`%ԆH8m>{dw%tIU}Ĕ)>!s DQ-)yͺ<>,ȝN c!W`K)sbw/tqd  ju " S~iD2à Q?1yz|~Tzq @A mINypq`|0V6[ֳL|EQtp#EZْa  'hc!jo>|gmȿ_6v?Uh!CLn $լD!RIy㲊(( En_;,iq&Y,FI6VۙKȯr=ON$jm‘Fo^7qH0GIW6]2|Q5=TۃwaM,(kͩ@Y9=Za԰"ރ_xB94t?GUCPiDAPۃy*!['p1ۿ&a")iH9HTR"F}=VO7 O#F_5g3\S=ނ}[ޱߕݿ{n|t, e洛("s.h%Ÿs?mK'$ bH%DhJU0hjH0HеHʒ&eHLĢR!AT*Q1BA &8` UDB%4HbD Q$@ҋT&fNXI9CJD4HS%!)% &FP1+B02(8ICSd%1#@ PRRDŕpA x )e A@ߒDV`T{HIE{&M0'e*= 1ح"O^Ãv/_ŞȊ_$4)W`ƩK)0>B@gLKPI"E@SQ @)PTy_[7A'|B g`i|SEKIC1 `P +LF@ ct)% QUńU][GEG%5 kE@`ܡ@@썫V?;Ex#rSa* ?&˶q]K= ؆uԽ9m3,qb0m5yޭCؚmq b9sZ,NER0['L{ .yv< "|M\@?N6ASϙ~bmӲ5EA4Nh~J\W$EA-;s,݉L'r5̕Vop-V&XH4MjyK Xprd:0-0uPвxrqF )ڼ)*9d9iGDÆ[z|lFbDS]d%>1O?G:3m!fR:olCJ~r1R1Ӥ~*+bNB06ߏi^O0E#`K"x@Iq2.XD  ; 1!? H|# meXRL5i鱁u{2Jû#` ࣺ^+?oyqKk=.uA"\Mƶͭ.>縗694[3WC(x ;}U/# /GlYHľ3e8.ɣ3^]2Wۊ5RF0[ ؎3IŗK/w|{.r9˻"5-4?u0Nϡ#^M bC^;1^y5l6~W6::}ocyc{>e HƢT"S3B5@XUjE$G54 ҔBL$5$A @ 3 C?縧0QA$HDU$(sW9 tX, 4* sT0hTx :R D%<\DQT㋯g+5~ʖ $"@3 ?~Ԗ'Q IaEK#jXܴ'C3#@)(A;Ё<)> ʛ% E8fgOP:ID Q}Ҩ! !VHSf1H%&Tk+8T"G =Zx 1)y+[M4\8 YZj޳J}1LA b fyL^ˠˠa XJAް!)R(h$O)dAoi$&ܐ400pSO9R' é2DI}1قd`O H]KL8?2M`M!L0})hZD~GLT 5Oq 0I@4Hj bI?h/Y]Js@UH3DTЪH匃$!PH R0DT5LTJHHd8JM 9" Jd2`A (BSABEHD#B %J 0DCCAAKKQRLR@`P*UkxA+%'w8H~?" X!&hH&CRY_9tA %(  $IDH@LBLRL0D$S7ȁ :o2UUUUTc*Ж0[:ԚFꕛ8g$] @KG+)633T[hHH"`j"UHR rU41 a@(D L?5Tt/q ͺ#Ǻ T V`xQ AZ.W!am=1E򉤪 wϙ 01Rq~_ݛ۷:yb-%jrBlHGDAUb k-P E&4 0V#vgt"ڽ*Tf8_robJPx qbdW651o# @=|=KxƷm7QPb@?c&J!@  AEQB 4N !+1J$+@E(=sFvؿopwaΧbϣ)h')*]hD>zgJI\9] T+N[s\?:`ݲr8:H) $x[|٬bQU  -G\O3j3t}+^ b|lJr$)+p[hB1dlpÈ?. }&[hUT k.?j.`K_,2D q6+848Gp{jʤ-F:i{֋!x:],,&dڂ m %v? a(R!e۩<\@ina]&}+@4IP% t9Fni~n͗jА7S-g wX䫌UƩ7yn3m9?cc7̵X(*ZE4Uyk*y~^3i2d ,hzGu.^xwT)( Tlf.'6)\AXNŠKunK^p~OE'6 GP{9xF +Ȣww>|~sl׽ǬRPf&Y9N)_u3^L&Q7N;j_M/Q|{=RZ]VCY pFU'MׇZ+#7`CVQ&^'[O9rsף`Q+Et xUܺ14> >δ*w&R#bf:(Ƣs"AEʺCW91~BzrЕޗVnʯpY -iiȳƆU`S)M}ߨ{Pax:tLHWW9G۔U!i.0=pTPvj>Oϸ!in# Qnjf]?NM!V2]FaUX\u.d8ȌF 1F^('FK:oQYi4=~i\ Dʺ[׭H=E<㢪C?3_?94?DR,L1ȦUb9$="hT_7z<}Yq٪tM(9B(F~W`5C;w;M%ԙK/Gk+ a(\Z@00&STj 3. q^Y3LZ4Pׂ+B3$5NlKt[/v,i|37> Ln; u )V3&eGc%3zLbg6V'>YW- IPW̪oebX%iIDd&&IrceߘŴ6_uޑ"CǦ*JlUzee{] Eb\@{Oo;jO#d԰җ;s_naIG-\Lw\K`uZq}-bzCAe)?gO8xI T;$C Q,Ǡ+0sa#&C'cq:͕>;a7GkpLnr b49#H(@3։rljS@{Qh.(J[s5~cKc=7I4RP#R TBL_̀jf Bw( R̨ n̠@تeb"HhP;x) /fղY-/v{g_`|[$>XRH]cX%$^Kּk>{w?YZ>2䷟9wM>3i|q@A/&Te@  >"':=3{c۽z6sgfT T0*6O':+WIC;r[߈<_GK<(!>'Agp'$Nc#iqyq\a>n Ou=0ހi;#u.,EpB |pGg705_T1Gŋ[+o2k@СT !#H-" @h Tl_۷om[~ר~&G]B`{?yt`!PHC!҄)!! H9}_΢x^[B{ .$!yE(Q1j"3) 0? 4n@aIB G "g?%g ffDqɢ`x0-4MX -39+wѥWdb\ TC0H4+I1TCPIr#8bV&LqFHPTdJIА&`p+%&`t $>Gt }D)$_ pa>a.Ja(Kע>@`VF'C΁`$ h"6>'a]uIH4GɡO^E݌pΗM0$a:P)7@VYv=n^fό Q؁z1%) (6R9HDrt?$=( jPn^KFR2_ʈD2;PtR=#\6m|C(0 b>O6bR*"c"t"QAэYTL32gKPyy-THT.H@*NF6 !'reGP$Ig7B Hu7eҔ?mb"A C:!C 3L1@pL3 sHrRkfoM) aEE'H)cSӉe2Hsnz6:<}J9gO pi>Kl̂~}%Fؒj*}6;ϼ!C4=Ɲ/у6we8X/sHjQS݋Y_֭,* ̏VDu T4&#؁VoD!]!oHbYUR5tCԠ[ё-9~)~ikYÉ4OEmbe߃}ndXRR#Z?v7gmOJ . ŷNS( _XN|#VU O6דujz?Ŵ 5}5A+q\O[X[#Ftpۆ^b [7}v j5I?c»oOws<3sֹ~[_OL hWH,!r `̱)mԈ`yoCa2!R0D:z)"`]BJ&H@F- Hpϱ[LgNu_cry+yeZ9GƯQTѼd))KqC4Y0R«FX}߫V{9 tnΐ~ !+&v2o&/dsqOk è5Tp* =iqi#{O[@寏 %,jr&82G,bLe p AR X4 &im _FO j"n7` #Ym*Eo^Šd0w3Y,S?ʟT ̒4RK"D#,H7Bcw=9QC Va_hH ALfBKP@9I@$P U *P[bf>/wPB0>jS鷅@DPQC1Lyy=QNſ'COsFaIA`XQFMhg@)V&iJ(ihxJЇKFuUr ,!s^QL24Q<ϻl?% _!@PL T R2Cc^~ lZ @/PjS9W\J'o}At{&g4%0@rQM׏Sc`LV2ZzCW] IzTR p6݅A*Ȗ 1$b0j|k Qsw4|c~(HdPJ*ԒTvZ_ TƐIpuIh6mF=#1t~OWr?jI,{ C3,%oLCI٨^gNؽeQLz#,RDOӻInP&mDE#g]*J'#wzKBUѦr4x]>ejM}t'ƴnF!Kj9W_tΑ8X9g 28˳L! :=*CQv23H>/ʲLfڥ+8" gqY3%V^ݯ$wrRfĜyULėcrurHWLRR#_*$+yoM[x*`><'cgГjΤ;:]b'>IS ?*Wy Fpr\5+ SLyl@=Lh ORj=V7dLo+cKx1^f39-VL2ǯjvcӿ1&{dvlHE4N}v,JG͛cUֽ "Mbw:<- x;֚-:]pC Em]TT?R:'O"G6 `HĕEGSCCoNQBQ4G:1rȈ3`f56@݌+ ="湎PPw"$HZC(*` 9 xo F%wXcRDHauL{u7s1p(ӥ CtT2 bΰw Què#So1z'%@;~ju.,L5EU8ۉa9Ġ<sUӈ. @€aQS"!,2Fh#lb%#dQS4ujeu!FL~߹gn;>@M ̕7 BA o+?@=|'$ &((: wWv *E#0E8@Lt PCkKPX iTE#{0gaMiPݰЗ; vMN:#\M'BD- LA >JH /E9XlAD4*IfDt߶X4@ 07m0tL1@VT"A?@M @z{_y=c=bf!LUkDn9 n,(mM@:U@W"*%&QA(JD)&P@$ jF`b*(HH%fhbR!RP"!`H`"" "eP*J bJVHBY X"DZ %B*AbB(fZ !BA!"F"X& "D_?`02@40!UI[1Yh7'~?'Y.%RB? >SRbb f*8~OOF&*pY!쾼D D5{c6؊*1"aK`1a@ J"K!HEB HH[(Ƕ8pD5+XaqpP h'U]BN~ED^oI&|O]SETUUVj !?* (}T4ȩ ꣜xycTrQG?~n,"ȎA 5Ј20>Mb9l !#s )A7~+UQO:BaqǰxnfcXbE(U-(gS e a i %K ĤcFv'JL ZRrL\rp&LĖ 1ł* J#'t \ 71 *15+nYkfۀdP4?@1,Ru D%H5p+E$O Dp ZJIU\Ät'zL` vSA$)3aہ`!aCE5EOxi-VT& f$>Pa b*g3Zm)JRUP뮰}&(P.D!6%uF&$-Ì T"i2+DU"S5O(&*xm׿[0?S H9栧ۤ|hUh"4x8SD5Бq/jɻu1#3C+Yn6LԼlk1@bghɚ\ZP4k?r}4Zuυ9nc(iU::/]_"!BKQUA\\GWT`X E-J,Apat/>1=%b@f)ڒ t! t*G3^ h(tiPT[vym<w3p8^_q{V$2$"fhz5$L+6sC!}6 - Q@>CkF  TBcg6OjQWALz7Q@Orq[KԸ! LIrP=w"K \WS 1vP\^v.{U^Oi[ud-Zz*қ'}svSg!G{8X IlF#" `7]te = "*Se^c-+A ?8[$AI eB଀Ȑ ?ZJ S M.Bu#T@i!iki< s T DڑX"I$!a06`0P5[)8W #P~D= LC$HB8MM|=+ձ8Ud -"9Pv0g$9p"dڧePHAB AC!P}^vxj*_崰 !D w M;'ެ9.UbFۀPyUPdtG:PkU+ ȚlK.MP墂b 5+̘Â|z}FDX i*@J XjPT H!"ngq [`*D؄?F!J҂)hJBE7"O>'A0;q@ ()JB"}~H&ALJL#DM OtAG*b 10(a8 HCb QxՒP]!Wt|(%d ݱs} LDi @ԥٕLHUť5(Uj՛vл!^fM4.\"h."+q7$ƀ)(#m%M&)#at2BP)-w;絯_iyK5Ywф`(6峅dHPn8о,+擖 Ra'ЖR0 EQΝnzuщ, ɧq:} 蔈LL:ϸ4^^5SLC7ctӊciҫhC`@G}aÌJ!aLAY(_j芦",AGI'Op}2IFbG8K  9=ّqpX 5F`-i`b AA^@e) i"B0 zŵd..3bU&"E!@H?h@4Ni翱30!,Ŀ))*Jqٷ=fD-"N``4Ѐ(F0(>?C!H;~"lT A/`TA|@Hh;ߢ  KaY8ӼB FKK,D@BDSAQ=%g1LQOKe:P0Dľ#Z%T_{ !d3|s؇s ЖJ_`4Z:ȅ@b-"0k VB .!lT& uv60#Rf&J }tY@pe 6K 7ֹσ,C{ [_ Tj.?6(ၶ[c`&B%M6.AXOpD`XfHmKDJ) pˆ;(+sfk˖p1ScQεN-h6q#4I˕&|?*Y3mã^x`LPߕO5^ oۚq5QvLrv0|6=p/;J(lJ|U*J@ @ [MGKʼnK-َj'Daݒ*tr>f7. P %$hPp"i,hDP)h3 + @w28cIq:KޓZ?)8vaGɛiY(̟;!mM9K.S˴ Yu05^ P{|]R "vrAD " fӯ'wQVr]($"HHB'H~.* r䂉>\>@D@P!_>|JH"3a-Ԋ( XTqQ0QJC%GVMU 3קɊ"NxϿSiS!.H"dB@QHҩJ!@'0(a#J!BRH%%"d&Ed)'tD}Q2!M1>˯k_mtϱ9l;y6''PEhkt+[bHǨ Q:赹;t_Qiw }RrռT{Jm(a~TftȦ~lѫFI{@Ŀ ڵ6;tIsaֶo.j3-;-HH?B_^T.8C^\YMe[tmVh&цJKsP:i^tP>0;ƦsxX`Ϊyfݛp!-}h=V)Up bHyh3]4lUtITt<:~$"-\CVa Bt]5M1nթfQ/mBXĭӑ.QJ(NkZIb3)6&Jps5_Y>C  L}lJfXy"7t5{Q:Hb}I)-NѩˎO շdIY$>BZ w`IKץ,h˲Rܾ| n'Z Wt- jJ_W}^otz*cpibQA14%}0;U s$reU<7lrp~ sgmr#wof;k$_O :y ˶B0H@&"OXxR ƇQ_#6*ʸ:OR1f)R~x7Wc(f*%i裔"6?%E'jw|]l " q"DBA;jwr>w|^z{~lGi< _ĝXL"GYVOvά1KvN㚋W9{+^Kt]ە6I6@l/Nx .7Y50 LX{ތflK>CQ92+'DƿmC lUŠD`΂~ *p|yzM Ogu KP-w+:cO} vu{G=/ 8pj~l fO貗N(v,D% ]-N(Ճ}7J+h_:F7žp[,0n!2=UBHrqOG:P@X׼~}m4'CMT`¶u6 AslbDı H‡.ygv~ɴyR{lȤB$ ~o;>ٱ(_Hl} Tr;JYF[|Yjy.]ҸUPЀ"ݵ^xO 8RDā(145R4U ERP2(ʸ`kLkCo;@0=ڒv~j.ګ&Cyc`c!6W6sm-o^37_ZB6/o<3~ɦ|8tr^NwYP $"$'Yr#r6 |Ŕp[[}+b=dR~)h9M ~^ܟ'B5ܯ?uu}wum:NOl86^n>Z戼X(@ "] ;)=bjD  uݨ;I - +C{.G h"4@PO'@ Uzڐ.,Vt 6$BPFcKJ-d^n~;8QF􈸭2/{B$$S񕂙1Wg` }AGgmnh_2XQA)}j D}DS?xE*'~DS ``:m;R0査S e(7rQ.Kph1e ˲ˢ"b*Ӡ֝p ܎~[ p5ݫ,UUQUaU\}bbB*I %CxfL@ hZ1 ZiZXO98! v6qà |~?[Nged2?X"Z?U' I)I") ؁,*Cl` (A1srʰ RU!k]х rA7X"gAh{ a+A0ƒWCJOD !!VU"dd. Lda!fl@9R7L-Gt A!Psk1h(W(%~TPl ܋4 .Tf'  h0 Ҽ7t>b)ErU?x9$E$wncU@NZKDA3 2@?OMq]7mm*AYh+RAﴴȀu1Q0j^*CP,M h"[@rDzi "THz(b?Z1UڂqK=NoQmzu:/ށ|AEHH 'xDZ8B pT2MOHhu`C j(xA?<"PD A J $(f|D(Rʁ !>GU RPVB@6;7OnK#v:l~?^b bA$ JR% Y a eV A!{H+bH$JH`HIX dWb=|BJaVt $@|!({+],|_ꪫJ4hBP!lE 2r%b(I (đ\fLhiF`,pL`p(( @CCPh˪(9{ @/E mP B ̠~C3`u%% Ĵj"@V @P(B^īӻd>w0뼈[RI~?3 .i !&P6M c`8HgyO:с>zz*IBMytb0lNM gFA NW_$6!@9_ޣi~GDp/|0Tl?Z C| %RHT=hӼ%I?*4F`*@iw & |*e l8DjVpݰAruNj9W @]99U##mOܟ>Bu"Rrџp{ẚwSHP&ޅd/oJ#A6^"$E:u].Mgbe85ߚ ߺ]&gT9(Q_rρL+3_0Ϝ"N oǷ,1c Y{H m_|LO~Z6zКڂVLj-v, y&``CrR99@@z$'0G= 'n;ꆵzT%@@q۝n&eu{n$TMTžvݳ:lVHkMU)6+J\@ 4m p,!l8\ !:J 6 ֿz81L &=! )B e>ŭ|'M0IqGVe>C04,ᐡp $2$[llXE4 ̄ Ǔs05썫7H؍C8E7hL$e2i 㨤[Gӳ>k

HrbRf߈XR5 oyf-fҰ1 %h _X沋#3mTT _ N/8\5͹X/tS&!HPVdi6G5mZmwf|3Uبȣm G2M)@hկF-2 80aq&V-fXs$L(FIUL`PZ ̇4a1FP鈞f* y)c<Ӟ#R%.GWuq'U"u4s鼉ڳUD˂"[ͩb͵v" 2u7XB v6Rt`Zr(>s'˚w ! &Py?bP`)a57wﳁio܉37ƭog25VG5oodq+칖d0$BDZ }n퇩"wsݎΕ){xM{9يFԩf>4 {à=2 ,nڪI/%e Q/ $ڷ.7,AvR술bS} =@C'/d w$>afiN1 f4㙦&1aII   0bB`1_6 #L0GEdvNMhDȕKkV;P! A}! >Oד+Kd.bb`D=>0TRi?I?X@?d{JbC|(vSA3=g%}CI$^ To[d'o9Jvq].eAN~^'@Ή$}i$$gu߆ff*XfA1:՘eL<&L"ァz0^>֦ɻQL/"TJ37Jwe2Q`XbC'j X.*>BFo8U#Rdi@HBkx=rX vph$&aKڜ@ {̗˺y}UM}`$:P};aFKaD(OGnSAE İvF,D(SHp*?k"|u2b ; "#hcg)VFB'C2Uӂ#׻ R9L5u{K(E5ߛKu _JP7F#JȄ1*4T ĥd1f"u[3:!"bY "~ ?I` +0bp JtA :@;$G6 OÝ !Ύt3#:7Mg n`7pq$4 0&0%!I 4!2 KRdcB 1>)"PL=~уIt` *?Y^S2 cSWc|sᾺ\0XZ5Idvs8D-q^]ޝKulѕ~YŧOe=ʕ<A1x[qc9Ԩ"<̲ Pǵ[IPTU+*>I)Pm;H}1A2o!*{KU]$/\up´μ0RSwݱi{ er>Żß#+7Rkl 4JE壂U󓖘y_{b@78$~6kMﭲHs$I0>q5Rћ5<<1qǀ,Ȇͽ B2]Qg2s ̷z #3q\2\1U|/s ߣ>SuW ҽUcЗ?bfz2Iox<[okYݾgϥcTO[GD6u Abwl]tJ|&s4ٷAIiZ@ D *"d11"jh %e & &&BbRDS3 3o|YLdk"CpFtv8zhupW}8zL'~OqQeHb7dKꔣB|^~DG?>"1P iv"v{Uӻ1$qrD~-E$BMZG1rBBC4PPP56!4P619yluCpI,޳UT8EIJҒ D-†ebߥ~@'_߼ [>]>XQ}`p-]WVnGX-8Jn̟G9Ӭ"!$ߓڪv6?~ n}<{<1胨7RLJT ZexDBc8KFFfgPdp|ylcLP??C 6"NWQ p \`~ZBIͷ<ptuB@ 0 M!wZͪAɝ}je= -b K*UU7v G-xmyU监~`!_迻[p兗wk322̥'Uc9h )'GF $$S$\ ! !8d1 acfEU.JI- RP@0͋(P:b%t OɀB:@lb]b@a !?7*B~| $.]Y595@6PEAdX` X (h!nXK4/DH_BLDN!P~oo؇}+ꔉBv#ATWȀ,0*Bj*M͛ww77j*3_s4K*%!H,kǎ"K1 ـX,C;59d3]@A&>`bu=,j9#1LCa$fQHl6v s Nޅ8J!a !tSJeEP$ ) yxg0s몊E5Hբ0[& Y,QHmZ"GvkPEFj8w (: 8 StDa b,=t7IgQBE z2+1"qp8˂"f[Z iI]4ĸ˪AG`:H=3ĭ*DC*RȢidJ<⁈wLRJB7JqM,>s3A||P8pUA19&A#CFkշ`5'W_B/;'tb8e b8{3!jF"x;j]@ʂa(hJ!SJpAG *!‰@_ݒ+=B=H*22l@idf~iE,!a~oܤ`(-2>MRFſ E @9*i 7 7YyKM%HQeRQCROYIDTUTDTIU3Dħᰬts""@((*JZ -**WOC|]*O#FE T C ,! h[N)4| 0Kk4h(H@|cBW17N||s M:3OKa<9AA0O9ZZ(B3.0 䔖gX50̲ 2 "S 3 ChW6'02(2Č L \,A'%3Ě[q 0.`8AqB@"cLJ7Rxغ@z5^g[=d"c&/aRی7 lyθ }۬mq)"cp,'Fg`#kڮ;2m$:eʋ.ov1x. q;{u"H 0 Qm00-ӵh)XHp 3{D8'@((addB@$߲fz`H@F\/+, QLRho.%XHUDJ"U!I&&~e0E FUC~IxvtbI8`LL+,ߕ@ELЁ$43dcJ$"SQ98OI@?eel2hU+8OIh~w# ZK?a 48+0^Ҭ-~wrxDji!B) KWdZ}L!/ՀY5P=x WV;=‚_M(G[#|E]<ԛ[~i$0-D(,>.2s RY+ 3KM)9 -wa1m9|FIitjr_n@X+%*Uf`Omyk}Ƿ / 7mui-jjpԼfct$ ?:,.!C.&YYE =k3Z> Wh&Q}_B%,I\,~/Ⱦ/} eJh\ދ-xk*c5hD e ߠ&F$ 1* ꈂ}$I$_  M(``iBjH("a"£~A*/`ŏPj0APEbC~1CiCUF$9-. E]Y𩤷^R`ppEBy^X*]"- e B1h ԙp@\XwKAh[kv߰=Z;PYkP0H )fm 䈊!~Q?B$@EAj ĩ$HP%󦡩!4PM9-vnݔF4FfE/4B tOCtہl@ @fv?Z\֕9UٹosޒvQh5*=&G,~6^qW`w ==SZF_11QbR{%N:D=@ԅᶳ't_zO )zS8e˒DqVcI#,>/2AfT!Pe4wWH4fߢPp:b{Jz1~6K?BM'_) u735(uA{ɿZ+G)|!% ݨB6\QMd+!/(H:.:Ә'!p> N4}KeLR4`nϪkpParo>~ H#3/"/UE%)e.ZЗ[J˃&BAq<[NB;,y{4KbB(S KW&fS?)__VsWHlM&K9/_M۝=dp)U_^D b7v<HeߞTKd+E 3a^ ʷ06]2|y`䚍zZ xOK@ C, Ɵ=5 $H%}gt^r۔hks>jɭ) 0ۢKstnPQVX7쿒Ucp8@ ^jvRm9C)J}{ OX\Q[}'o[A QOW]uײR͋[0!ɁIJGA`a!o&*$ D""vNswރG]t}F8?i D") Jd()arQp-BGѝmѨ h = h0_<&cA1:=l-E r[쿘YB! 6U]2"`!> ߘ$II & ݽwl|.þڗ7~n q"a1zM1D4VA=/b_w~ӛ0R7CO?jF ˮ BJGi>0^ofc}?,Hzt9dدѶ"'5T v HF|ޢ*2MȞ%'ES~[<"إ|M‹ wٍP%)] 2U s{ r;.ME;LP!(j_}NwfM2&wsy2֡;gVj,! *Bߒ=mBAZ3n*%ttnsJ8oQ SS-o.gJbl!\v'`,̓ppCy'(7Aٗ=d-d %P\y|x;D[x, YYU7l9R9t=tXs'al%Le&U5J4:_&䱏QԻњg T9tɵM{,-J42oJ)/_/t^NÛ|ߜ&OX+Pb CGy}o'qV-צXȹQȀ_3a[]oDL1i$Lԝ0t,эGJIWKgכ\`|MϜrqhDs븸7iz]%]M l&5e =n,Ʀ?_5,䍛xXiݬp:K211\x!. Syx,@ޚ+s?|Ǥnс-Yv1}ѼWOΦջ?w+ӿaTH =9wr_K(qQ:z$P"3-+P7zwO{<94 s{:Gx_SԺSMxoCy( 4b(ʰOG_J!nz/~e o݊lOZzfu6L=g}14(*n\64WWyY Qj9GKrz_SX .7ؖ%ZZSy肝[Vh&XUv FwzBc`d>IBu"Ɯsx]W'LmK,,}sL9 Ʀ>Qm*7b)Cz*6cAE V wFv)H#:Sm_]|6֤N[H;kmw;b4ߟ?Zmv (z6`~N9\ze9Xu#%ў!ߞVԐ {IeadTگ/Q D<\[QkB/-XA[u. ǔJ G~j+|bGyr;HUi\\k[k\YPNp5 /h#X>ɑb@LHudP <Ʉ½~ X9>3+Ծt>!s͗nn?[q޽Mn[ ӂNu+p;?\#u<`$ ~n_ktm5w|w,g˷-~FQMG !JF`}KdQ?ΛMc6hIrf#0S{M8dό`I_#u@׏IN9}.ܐH@Pf)2vS< F!Lۄgd^^[˂.fp \yl/ѸѨ)" )=L|-܇XkO@~yp i٩u5K/ TG7?#D!?J-_,?,l@$UB'؜C#z9/hs8 )e,4 OǏ蚊cQJ3FQFŊ]gd}!ՉϞ1w -H<`s8 @Ow(?PΧPn:xrMtJI|wlXaԙuXPѵh(ڠR$ IT|\}60.J:@1.XPPZV(҂ZYh"wvlY,JQ; r gc t?R轈0)V%E#dOش.qu$`N};0xN[IT6)hE!BȔQ7{ϱp>%(K^nzku8cq63LA@+{ʓ.itQbX[ B#cb~\D/o@U_pVg|Uۣ8z.iID}sda$-mw2>S.X{+DN=\ fv߶C汉Q*E+|G!j ^ztsMH/*.ÁVaQ)hTi ^Mϧ]6btS>S?/qxy8t_u,OR'$  *sZ` h>wi/iRP ēDPp Dr@APOL `b&"R(I$4cY9pIx*V2se/*v?5Z B"Ipj2V ei?{V &-e .)DXʐ]fВlS;`ߐձWbZr )Zh_loEbkWH4j ـl.wNU\_Y;Ӓq#ѵ5?m[Et)sˢyVmۧGȆDs.^\ ~ge֩?v,oOG-X=b 𢜬&].-.h޴ ;.,Vhn^㽅I-_F*C$UEz/N/'FshInUB~,9W>Q: HߘHZ |OB=mFMfndzi=h5(+9$7QE B\ ƛ%V\$V DcCNTE7{U"NlTӷq9„ 8ʮ^)CZn8:crZ5mZ d0ԔB ? H~qD ť)K8aLU2f'-˄Z#n|#iUweܶBy¼'&*DT)XO qu 5'<*)r>l|::w7zeA 7} 79Th`_ S4ro򸓋tD\Uly^Uf3)G]P|*13vյ7 u3zX% oDDBY-Ǐ6Td_߮~Bt$/І0Iu❀[ i C/E^O4*ujZ >ݽ69ې; yg}'[2ۏVsDcPgQA櫶n$?x5%d+$xؑS#GQ±H 94ᷖI_.&Jܰ&8vtۋgo!iKѵu4"9PXU8~*Q&$}Fw@`eR*dPPoxe_tZP(AAbQa)DZP)أvecZ P>p:*۰]OM'0'%Ɣ\vݻ<-RO+= =_<'dzтP[i?=0.ÓicG\8泮Qlچ;}c_wJi:2z6/4*D}mdo*9d|f3h$ FBކ'3w&M*/v_q!ͳVLNV0xZXqjnc*{񱣛d]8:OO- ]{~g-Eew}Kmz&a@s݇ijؿ/v,+__[ҿq[(sAsJAuFj,t3X8>TQQp`x((X^7wBGk |Z;+RX]S^=v5mx>캖?]P@?W,f{3>z]\o 9KI7-A1@.~1,s=갦[f@<Dq%4Yl\L1֮jVX)t%ԹVx}Ven{'Ͷ8QkX2F#D T OsHrIm~34?ӗՔP`h=CjP)=p_di2JCK2S\QGx~8;q:R(Et|DyIdms-JY= `!=: |xQ~ !f :MGtjq/+iT`Gvw&?,Ƽg/uQ$=%O~G'C2 /jF=)Z7hlz.VcqUo@S2 Hq6:XYh3$!95=zQ1˺a^]HR=eUR,9o߾IAw"ϸ'GMf6\LrLdRhsQt[P8Gb:Μ2, {_ ayux X+PjO>Ӭh$Q/(XsHQ̜¿Wuoqx)2ǒYl+'zP $7mC>M$Ej:K0m)}_v؂& p c"3\- li}Ø>Yn ϗ-@1 ǰ9 5+O%5W@Pn)hyiWk9X٬x7hU ^<(B]#zY8$ ۯ>N[^HHCb+bn]\^C"_8H .3D׽T^VUgTB_)wS<~y>@C;C2cn7j~|oY-+Pvl[1‹XMϋ-[Ґ' ??~ϡFx5Y4Mp!\ٍyf*Sh9U\蘨&w(1&N'2ܿBW(׶Z*_Zݼp;jKRߍ6vu3jػl@12kP 9:9 /&?N*ߦ7\g||$˿*dYC{'Y4Vuҝۑ„e:+6r0eLe|*3~GnCP`M IA-I'h0^uF\ڨ솺b$_&)!&CI)3rbرҼTwKJwf"a3v#OXoQ>韲x2⿇̀韂q+q_ۀ7 iK gрV` # 6VAs[ăbJ }Qڏ\y6_C}+shz污@0Z*[f u996MrX?Gd@Ui͵~AZu=D^rU|[[*qF6>ݮɺ Hp< e'0u|xBA~&+& 遌..ua=eBA)?h(k2C.ʇ^m{}ytQ2-'K)쑝P)$ˮFhÇSq}U̮ᄅ_܎8qU?sQg̪pL<>}8"0.1!rO2] G*&x\GG۽ᶤD(z ߕ V:ND2uޡ\ HuAi2%o2-T9*[!ȀzyS:W tͶ6wdM>varfwxKĒ ]L4lχ}gTʫTfA>$v c :QmA@`Cr9)FT%8L[yUGF:D _rdܓ iQ#f}/t$"X-F+I4qM@6IZf%UAY%ijNUXf]ʦw8/GlIL]2y0}L%|3*Rm$ʳ(INgJLjК:4=i}َ\33y%}ws3 BXv%wTG 9ˎhBaH}% yBxHؖsOe4 E:7Ri0t- oO&w$o_=5Gy u?CzRrScW]=kX;HD2 C'v}תu sA k !HִWX)UmapZJjllwpu,^sBՃZҁ\7&)g \U(!.>LYAё hp6L/MfDNdWb"ݠ'e ժҫ48֯)]Åɽ\QGo ;v]W4|ԠV6ZO#4Ϛg&mҲ2קz]+\p4@`1斱j'p9A|5]t?km%3wm"< @!8,2s:&<03"vB 1p@ʫI~]@Qe%3F>3)tKa,xuɑ08 /_P9?W(I̯]TK un}.ObٰKQ.GpqxF,sp&"^r${L+JT,{"=}CEl Ֆΰ\-S芇fKuBDXBuJo|9` [eT+#g}V"0韯C ycskl4p6ϡzHA,8I;DakHJ,fG\o趴"6gI W)?Uho9kzZm[&eJh}ع%r}{K=Cѝk!Z3KguD',n #cg=O&hjY|`AM7g JcְKuM z8ὤZ6LBT2CC۴~<;akr|y~:>Rx߰l/P1p7H-$&5ѶR'd/UÊ{ggGTE0L1[CU [9\5kߕQm ˛6>,rWr|oGNx76L|;xGzDžskOٛmMFȜQL5qzjAM594丝\?}hQAr9tE0<@Bn\+X))B. mUH|Nq/)b}Go^_L|ؘئkC 3p# SD`هkjEd!q.UZ>؜  SD@M]wT+hgSyxGvS>ɅnBw'٘_|Z3?Mk-ZA{_ t{0^px[q|9eS54,mPm\}&;>\9%~T pybcK3n/!/[V-~l5!+#, o15Gp4&L5=\zTѓ.aR2y3׬8?[3Wm(_ 91f!\9?NPߦ1<^d{xVm%PP9Sm0&k%ٮw*_qAD $z.dҷ@U,n#wLK-wim#T2ԯy|/: MV{҈Of_4}h賊@-wM޳,bzeN [幒>rݹEA`:]j#_9,#`hi;|=ߕi@qa[Re$tojeOХóބ['|A7YMVw6@ׯӲFµYހR\M2]qu Sg^X**S0z2qI[^f:uWH kqRV"Y љb4hR(BxnZVqa[\1mImw6T[!b.2Np5Y-UkV?nCmԲ8Emʪ_"Q 6j/oZ=$uӤ`O)>j u=܎7TZRiJykv~Vn fvE1IXO҂xFb&}oWL9dp;1qޟPb-B^Dx*0H>g"._*PhE2!RTTѻ!J}3N֟fT!AP r?CfiTIL]W.lO{-3,xSo:k?;.|ieӂy8%6`z YJ`5R'9hk<~B 0}^i8 mWߨ{z>u$a]ێan ,ɗӎriB/wx:oK⠆8 Wrwh+BgvJGְQiJ΍><0Ȭ뵀$b͞>v&g 8´s"^7&;SkS"u@bzjgdtKP:M7Z:*`aS4 I#UѶ|+n^V VXOT+Q4;΍i1ԕ$97NjSǷ$J'kDCjx6DNXjMK)],Yc5Pw$zQ:a"Յ'd07F$X2&}u&nPU*F!GxnmGBcE% VP@1_ !_5G7rjK/AE(j*^"Rd. ύ~.+Qkw}3-{}n-p Oud$;h7cVJd, {S;V[ ]y4ǫU9<R ` $8)JD˵ZKE}'= v|=,QxIEޜb䕞55 hLOZʻP7}m:Lmԗ?] k6ef^is 2*O)kYzΡ?ޙ^v _]5g9 OOJZhe/ڬ{8Y==_6 *Oz1ٲwFLh-E bKG?Tx)}09{c4c\ac0vN?aX(s~+qq?,(Y 0k ܆S*9}7zёTv c}` 6*s 8|a3x5r~Mg<5ai>Ү1[cŀhϓS)uHfs.sSZFt4 LjX-ڻ0IaŸ5+l ݔruz°]s!i$+~*&k&acnZKl˻y3CL.gUݴ8:݃,ZsZ6 ,М(۰8KoYzȆV-KcaM,O:/sO=Z~Èyg~)o2LDlc殻X-9G8&j8!{+nLQhHM4|-=ŸpDG+ Y;ZW#SKڗaR5Mn-Ym,n^`ǀ|+$Yz8'gZ rB@M2/(z&%5ҽ{%wٿL4I" r+oIgGXXJE~ ڀn= X[QF7+2 &#!$n}|/ J +1K#)QUSD/lze,T`56$@P^@"Q!y(Bǂܑ_LΛ=4iV7r j޵Mq @L%o?CruQ~R,`t_x* rޖ̟'W^9o] 0d:q(nS~J ycf.+H|lnl NjWqO@~ΎLo 29/q2!'8NYe]?! yF`q2)y(/+48QMReg?x٥2:a:ulL&Ώc5T3,Uh yRQU[.b L޸U@H:ᖩ}`u蠁1tW jހ1Lt=x {8 esDxӐ'"Ddw9Q!9pa6~!&;0mX`zc҃˝_d%!6dSX`Kq~MdT,ԛ=yX:p5O7#^MZhq64tjE'0}'R=4NI{Wrzx4;L$HEgr^ BE^X1} <0[D+QHBG >i-mzӃPuFyi( n'&~G5`ݘLvR1c>GO^8CI酰X]@*4 A tHpg)+ o1LK֌+?4 3{cg +X^t"`x >,e$nBSo~7Y4fsPцGQCmsO/oCȈKtNcoY_h1 U8[9'F!l Vj#JLГ@,2/FDƟg0Y'Wm2BtḘ,Zt%2euS5^[{jp%1:Ȉavnc0[V@r[cQ91,nG:T*$qBx'ᑩjFgx ( 7P'%ih6AFtY̴:g:ā^}]d|rbWtPt𶘖0D}~ aR;]Rb#GTSL"~$ԗ"3<; h64Z ƍU,K0׌ڀsumu͉Pyi2*Xw_N ǯa,b<Ӝ` p?VlBHC^v ]40z z3"ޘM!Y_Ȫ 4,lm@K`J9Lg>9ʪGP{kVܚ12pкM^3RmD@=T;-C̉g(ZdGMtJmow e*>j4ɗae6 O+򙐥W!SUT#6r6"%8d0U;#CW`Qm9OX%|rdg#)2$dUWEBڑ_ԸS;0&8&ܹ8yS*GՃ1,ş0 $oHt6.ZPUbOtY264O ʪ[.b*?,e|#5Av=vU]iBQ>g5~Ym5_7uth]$LN#C0Mm?W=:Ldc~q}E! S, gP'ƒ1!ߔ8ıfo(]!ќ%Db&.4 G`s!̨X#X;Y6%c]C<)5M`.\߹o}dŒe|i?~HޚEO>Y_]\"cp}I 0_Nԫp:|?[bܗlD~f\trRA[g`:`2\b=tϕ2{Th#Ƌ1)A4dAti$:K,1w0MVd~_Q!ZINwu""JFoV P܅ AY:g<\Kʮ 7O]ɆE kHY&* e}X?zp߈]қѝv=\Ob~p䀱r].̸\\M)g5k0k@ԷcRd+7,C*Nҧ^rXeC]e5F1|u6HNj2+?u9ߏ}˔sdή>ttZwR ѩH,ُ-D"`2?^o䧭+ Κ7v|쥣֟&9w:n} &?= vGguu|?)KRS$hckAvi-ݹ@I&KppҮ|.,%¹_W$4F "69%7}}r~6] YatH$TYww=O{7rJB5}6ƏR"`yyiF݆Ҥ md\+n5աUlޑXےfC}ic&5emr8!ꦁM]Nu#/sNLVz\k"#S,G&Z2OGE y[ ū[3(K_T,/+iWA>/Fᡍ\4KKDGS`2`(z7PFBRZ$~Gu04Îے &6VJ>C߉ UL\WNGs> ,6LOpW? i:؉4^x=1?iLbZ8HȚ-Ln`h=9$*"jK7{p(an#F%!%)!ꓽMGPN~^ENvNkǦIF'OW6i)9'l[1c\Z9ء@dbͷ-bG}a N7aH`#na,FvW7# NNh)jNsy"&f%Yw(3%WniEӸT ;ūd1XZAæd}ޕ0KsTO}7,2|ӲTWF8"~k9̇@O|y?C\ MQ jrAGVUuor̭WdyP8cTf}QHE.RX ӜA_R.홙c m)3P'Ws3KHsjr\sSl(Q8lUM}>?_/o2}Ei``5t\kl?vhW$үF%tE'I XNGLa >'u;;7H A 7l(|(@BjgX2iM-C_f  ˬb xqX !!h @uDF߆ꕳ;\)G}f~t߭g+Mr7׵#I) 6qsGcl 1SiPKUҧ߿Q~YRd>^g-bniiђWx j) wI%PRIw1U ,3JT2*VwrM%I6YQ̫҈=[l(eU&OV㤁ުNvDr`l?chb#d- M0@J=`)BbQ[>t{{Cl45+ Jzf2@;lw l-!ij5Kh@+xKNnKkg5/r.q*AQ rTdmk2wP3xdo_?ɛKJS/,FW93T85hCU@ԀrC#bhHZ~`{*q+|\{`?Le̎AG`ԥhLnƓ $_TO ֜SsYwVs5 I" |oMGt?> T"agY c KsIQO'Mf6P3fŠқ&i .%Wk$¦ ؜\&%:!nRLjn6@3 *LTGtrVk|f'Acq5.,px:M@ghnY?Z-4@7`A7Jˌb.1VzbX|*ٓnyx]TfU$Ei>%1pxdr6i:* @SֶzRQyR魁):w 'd: SZ2v)*)ȹ𹿐_E Csx 4&]*2V)o8]^(k"*v_JE>r=J/\$ ?Kim{$&nPNYn9V-WYҰv&F|g &{ت:MzyX J(Z^T|_I Wx`j+^7-8^NxӀp å:^3WEXHΉfN^ ĝ}4AW)ݕnwڏs,&${X 06󒐳 0c|sP?BZ?jŚ_!ƦGܚ,x=@]Y;NDž $TP74PɓeqWϞe("6toϷExMek * Y]ǽ՗ $&u#W%mjMDTxIKDݦrZzi}(!4s#%ġ} ȍdA6!a6@IAOOu8nWxf#]җ x/>\={dg&>IIvwL/3oKz[b[wi RWو]bcscKf؀ќCdSŷpq-.A"$<.DigIѵK:2fܥ;s _K KƝMbJM0U&<\05ITЖ>Ph+۠W5鈎wB9dL aX1?>fxvދP{S,'J*/ g8wfބC` u?J;톩ـ-JqŰ[C)qu)Sw15&59/~Ctn' )%(7"Ca=5hĊ!PHX@ [NpT&5Jy;Ⱥc(E eWe${y/XE݆~J='y|.0S(}u`LMNf J9[CIDbPozKuo`88<WtpkDks® ,gsV,SNR^<ķj">O?!'%:+Pw: !`2(ML+5f?YrWi~hP$MHxr:~e^S3>+m:OsfS{CZMrr5.`j((޹Y$ZCs&\Tg/L)LXƒķ?o!.d8}w ix)<+arCe:e7gBfGÙoKrڡ*D\ ^c?zqКOmB@QÕ1@nQ~ayRWȀ^ )#nҩ77?+g>ruD.@emyDybcd{nP6.˧Z1E#eBxv*O+m3W?JG2./Oq CaReM.ˠM"aIKԬAT0\usw3D΋Aǫ%PYl=DU3ʝ[O6S3jQ5n>$ēُf#GRpO< D~K665V uBQb@狪"V:Pn*ljFiR&֥ھỦNaBr2f#+!ok91K8볮|_@٥2(w{.ɨIb&CϤ2[,\~X bld&Iz+}[o90 i)Syo>$JE 0jvrK@G,f#Lҋnq%L4)Tż^$^.W2-MyK5vXq|ǍT0O\dRٽ|ޫ/ӥYn-rE'L 38zhL[?Q)2X,FݲT=5U(ϖXiIfM4卍8d&vRc8S&!YɐܢA'ytȮ#`3Hq-M ¯^aAfM/. {z?OݬSn[tq gFdܶ?a$!v0R-vᩨ,ufjP.4Xx+W"ŻžXԕP z}9"l[I>? &Ȩx3m=GGΊ5[B q!]O=Jկ!=)!FFnG@33ӎ:IGO2$t&spS{>b|[4A?YgQsw# XӼ6چ*xLvmq,Ћn0)ϋY=ZW*(Z <M "62wOy7Q~Z=Y:Np˩xLA0>mG勤Kj侲 (]jzŦtB<~R ф`crP9- \Sf·\⦉صmʡtPz>,)d;F%"!.; +mK#; KnG\z=srzFҝ /?Lxђ?͟ٱ;}B&>Ij+ocI V*+ֵ'6`;pN*fWy]b!Q-gni+FPј|'h^Sn=(~p|R]Z |Ǿk%@~+\)͵(S,Җ6]iLQ*V/79*1BH`V6kR"Yg gRxrn(*Ό^vѐ?J*zxOmv Իz_թL;G=yE+X4F~Og9ˀC 9P~R~wTC:VbWI]*RE;(+.u>5ʾ6O>j? Kף%\sa~τ549haW#jwRsF^I݉|Ę\m9ؐk1a~+ ? mY<õ!v|^h )?QvE%cH|rdTcitd"6%  lz9x_onBlrԸ8Ԁ`Bz,&bvy@\6w QD)7T>>Þq^~sVH{[v|ܺDۯbϸFzI[=8 I('щ-Ɋaj*b@^Xv63˙p1(; pN"ǰP@z+(>0|kXE;X N'>:/4!sJ~.?=q`Gnuv{KqUE(i( y=R0&;>?nLhj2EUrl*ocl})٬dl]Qg0D*un6E ";197vݛTKe9ڼztjxvaZqcl͘GVعw $=EoI] #Jۛ;"ha̫vip"7jW?fH6;xId[BlPq?lC>ф)\:@` IҠmQ8g?A:2fKp];xv[Ph=[w~]n#' gTι MU?=9 '91Duflh|rݏLK|NJGx\99m*H{CR^uR_KK8^3jW'w#yFJ," w$Op?oaF<.co'Hf~W*Lxbk]&oq/f;Q nfsLvގx$?76Q噗ҪaKQėgpbڃD '^rxk( R!/{qh=u {Qsyڇ։6g1a:}oGn^\'hlcSP&#EщȠmAf ajPG#٤=Y;l!YhRP"5źhi@Z;H\Pgc2ʄHfK@`MgC4~_f)0E+GŷL8gOB.S?3LfHib.tVKKJEQ$u@ӤW.\:KNvz=ͦp &7Pc1"qX#VP{L(RCf^w?HgP~7QSG(?0ھL _Άp夾ex#}VH>rGjx5G$8\%T*Y&UoJ>[G_D^^mLo}ժMj? P Y/fP Nk>?LުA:p0:a *mhY=m؂\y'Cw$S6("'s1ԛ[N6%*iq`ߐu</OFTb"*Uw];8>es67"V( vXJ]WBy;xVlO9ZQ*.N`NF{KH4g8 nDXDnK&wCSܗ/#S>օ_C9Hyc@o3ϥFaa5{C ^yK',L[ yaQVwo-ҁA᩷^9o+v/΂ȯ%h m̍~gTKKrx.mrlk70GTd`Xm ߻r,QP8-ڞ'\}Qs_y_+027In|!赛ny};7yy-Ijb*N?O#G;73E8ߒu6슓e^h867ӭ2 0dd2HNG0O/C`Ʊ 1 1y& AAt4uD9R\Tqbe q إ!t []% Ѵ$wH{v1Wu}x,m1H T JBckX!6V(o6`i+&Wd<u-/H:'ZY."2'zՊo-N/a1峉dݣ=[էC`ʶu|h]\fȭ'"ká~\T.߿5Ahr-;c62LG8X&FAoC"8:N/wʐ^ٞ/HCwQgSo p;RS9]7xJ*l&'`h6*A{Nh6\6ŶϠO=He,1tZJ3@km'BsJLeM:fp 8f4xb2$[VBxkAYi_8;7Br^ ~'ʥr%6XzddX~Ƥn 0\;jÜDY#s٤rw]䛙áY#.>dжߪP> TX׾8rl1g5[sU R[K TSυј wyNg f9mhwb6-H@LڨϏQտJ8RE*z_X'1[e1g]OJR;L73َ@ L fCIofKվ~cA[ے2>AƗk6bK2}HEm}4$ "gkKuՒ~G'KOѾfxXlzmօ`Xb={Z#x`~u-q!F0YGɦR}nM Y܁ndYoe-<.R>qo^:~ c2hy#"v)5ݾ(;xe >5(2 fwAhtȸ!@4ǐϫP_gq4ѹM3ϧU0STQ3=9'wxB)-' &Koνf\>SO-RdpPE#Ԇ s(jP:D%DzL E=@kנ(]0e:J2E~Ȍn> ʒ ŏn1'Y^ Y߅G&riO<h9)6YG*?dN~~uMqhMEga ;,NPD&Ҍg9VjLJ>>jn݂qiTziD9K 9򐻚qH(܍tFj#ݒ=uMwuXO0 PUEӃU]F{Y]o^5Űz0_o`c<ͳJKS-W:@A\c=(#RuK<c +嬗k#Zmug9kִ}pRR08J?'1?I=^mnF/HDP'xx?cU^+t0τPv7!bTI~Zbr]{WDz֭܈Q"1cE erSt*" Xif G.䫾F1nSAy))-gW̟I=ǽ)>L&z~ yvl_&/.lEasPթI&Sw@^%D闺@NCQm#P»r%&KqL'k s%v#ܽ;t; ɝ|itU k2$7[' =~ۣ4.Ko^Pmo|} * 6C Onwʱ2uIPrMgn.maTb3획A;$25~uv.R%[\}+b'MW1:RFbg->VE1%Y e<ǃ%c+6z8`Ayְؑwsl]_ Y2>=Ooj!'ZP`X7Mc3@x08?*,vs"R I6TQ+\1SRt:*mQc%t:})sJ_M&$JiKQZ8V 2]U ~͈)Qr\p~Cڵ]e({\u$ dӃzyQj꾎u,jqNSOÎx`L}+/z5ddPlw/E6DDBJ{8ṅ汥~Ak60$_j)߲ifUcĄF9+LLx0ZmG;5E(Ls. =ťsL}]Q~5l5lIaN7^7 łm鿐-Һ%9{҈ @ő𺯮(V@u;!_o݉P^?#޼ R{! CA3ZE1g1q1̀ 0>姴X<~ >D0;d?J.?4UTf\>@!nu>@TiM&PΛH݌@N3 ɪs~p~ZoG':_A#PO`nI V{Ɔsg-8.jJGu-(΋|!8QAq/MFȣA翇4Di`6i#P޶i@iDZuh?ԟ~z $y nZ*nt&jgd cV=eu1~N6UP|XTcFA  !ElD\%u;!ك5MQs|,۶H,w#b- Tӣ,;:ͮ2:J/YKZ "x82A^3>6I#z3`0VOhWtn9 |ޫDNyja O7]ZebVRy@3apcK_⺚ꅠ1~rV[\FEX.$xoBS\#>oܽ|IJi B՘ 1+_|PQBzH1ѓ+It ;|}/ <a#R/haUFRm?cNH #w:\,V9?f8,TE:0M1v=ELS`V\vjD7t8L '΋r:T~vN?:l'\&*Q͑F<m~*^>]akeVdiED$ө]w^ oo,q$x+W0je:){uyccR,_P o)ui{wH?'"-D%cڵǩҫ!M!9YzB~!g冄6d DM>kK UAa?W$F9a9N/s$f bKNBgi҆L3dOrL`EhrׄB;b-6BXꖛԖ!zt̐0V%!a̽JX*l-bܫ$w3">H d(*@7k/A4wmssFf/ӾYUE3pu?/|lV{bRXdQM(E?7/Ƶ Lqzf(*~V  W4ݴ jѿ.9=c*MDU ݜrs Pv;7Z}ا$ۀ-274@[Jje,Mw@iA``t;I.2T) Nz6ѾUv+Je EzVdG)ڬ5QfaK"@E@txfp!7xẙhUF LpDspc[&*bsBw/3,1-hj/JuDZȝ {g٬5*x0fҐ2|Zu\DW`O'Q Q|)=7t1D2D7bYXQȘu^Ƭwld,oC_8{.:&8tKEˡI-'YnRH99OHHIjC)}n boweWw8v/#rX)yE/[da[~@9CMl'Y\xҗUqU)G@/z wZT2cY W튌 r DJ6Ot #SJloAsϭbسj< ls"a*el@TGZ+/Kae':j$URRS;i7wZ5F}mhxmǻ 47w;?2'V"}(#w nN*{4S7&g(wtႺ] $#q3Uee7$bo7oBCDh$d v"I<^S&s.,PSWAҔGMk{\>^5%-e5y"0r.pM#2~.GzlCRSI3\1dG?Ji5mĄ?~!2(A4Ob pYZxKW:Hu.,5.f:`§V9G㍆ӹ}3Ծץ_z $$Xb("!"J"B!"! H%BH0001L)q\؞?s ?筹ׅt/9Ҏ aXQDg`-rmV`t#/R/)Qq}&tspHZRS/ %+. C1 3_a;9!Cx}5W 32mѰTLkԷ74=,ج3YaZR.Yu!+X ڦ_ey7dБu&IX=NQ]1K ;89Iv~kX-e 錰1O&NFbThNwRP 3o̺uuID=X]f3yl;Nh8p=;w_d2󀞵,s(G_] %~6,J JA|#rwG#b4+ -3Pӊ.u.I]˽Sng$oª]uij$.{E<ҩsIMcv}0\1BU ObV_y&S܏%j j%k{6(Tkhɍa(4\p{K:Df6 1 N)V78r5{9F?0Qe7KR\_[c%JZbZYE=+o9^P2qx{'x>mw`[H yxe`D Aߑ_YXkrHbi2 /8n}u5+v7j~n­ }:# Fd!6+t},r 0I2"d?דgx11F_O™`I`ָ!ɏXRnz: Rͨ)ئKEvh6B&jSr\uŞ`xH췱LwLX,5sB)\H).VP L?CnDAR{yl^C{5ڋ ui#b'ln _wAy'9wq}=ג\pRɕG+Qv,,j~{n+IޗWHWI! !ซ—,I SG=TZ7Oo7xDڇ3gNϢXI8/WvEuU/ټG`1>se/&f&ėlid/xt}3:rEhvoU F+<b-~-&Mz-~h7]+LlrԏM÷<ߛ8aº=tcn!v+P]'GT HAQWĝrGԙFp&珸=`Lg8 3 tLfXK(΢BRt(S"z쬕Rsv0s;=({*Ә5aOQdGѢ42ÙepZDp/-ÈƓnHYǪ]O"ue_VgqtfK$fN5UE6ER6P_$qB ȘCXtcT2&*}~"jaw)pXRweNn I92 ܣ!GAӯO(حnL,,pfP s,.s"XS-=9󚫏CiqoYVwrTeY9zQC+VS9Y`] #?H\qנ,Tpӆ9e S|y ~ά~I $K$qI5d{vu+297ȄlWGDrh :b;Izˌ݆qL f ٻ S+I’>%  ^r?"{rRSHB|n=, { ?uV5xY+a  _Wc]QG9;K9${r6PFp  vFmI{=.3 1oĀqv`% &MX xӞ/u%H빴VClvٷ|aq4ZIɣUe M5 XowהʟbBb)h| qګN3έwg۾:VNҳRPQ] Ab#@fn_0K1C~E>ՇDәJ{grR-ŕZF^vođXIA:^wɯG`irQ.?Cam(Fi͍VG4B֊/b :zF]l(L:03Vf*e "{|_}AQa,Qdu`ε7l=2m d6)$:Xæ]ȷuT \#K5pIbֳnGl_V _@4A1Dl%֏ߪSX1*ҩ-H#pa7yu)HX.QT΁OYI ]MElC`co爋cj%J{5e)ixW%鉂 ﱜ"lˬR,֜D/fVXcI=nl+c- 8!.ڥ9,A~jѠd39ʭ?!P9qfNQO@n[a~>ΞN$ [Ib;@O9Xx7;jdm 4V_H(>cT{r`+;%RBΠ ew )J)ȼx[}ۅ qF ]e #Ӭߵa5!sq0ħEos-;FDO~Uaiy0]tqѠY)6y!]pXCppV)98Xd"tD_ftϰ r[xkB|p(7J0ɘez[4nݝ*p#ܒ;+YQNaR-Av$__D(FE3N4en6B 78y++xɰk"NA|G2̈́<:yD}rx_`v3V -q?fTYC$Z̙QzajyL>Hm! A HSRnÂ'_ y 5RlJU _#bu]ϣI-~iJhCKqw(nHӸ/`fl")J)̓pbΞ<䅓({.5!!~#Fރ35u@'$Pdy:OKUD/z(J/ʷ$CTbV0d.mkmzC&? :YGmEo .%R_oDm_H<זN--7lw(~O8qXm"biyb=I1;yd`I󜢞 WC:P4JLbj SMp4efC;Bث B@mD"8_ O;c*4[ڱD+kVhqTǺ;SHRY"f=|{1O֫W>$KT`X .}*Lߢ!~ym7bg-zTy>$߫ >={tyDv W9&xI'qH)Fqg7/,Oi(e&@'9Mq!&X8U&,B绐%/u0,x8Ԙ]7vf;r}m` Oiz0HPxdhr'#"ڣ?5j:ʤU<0E6apK BݚV:{U]P |'Buk>a g;{Eo:9Kղ9r/d$AD]cIbwFEdM87.~,FnBR٢VwGQ[{jv5˾YҴ܋*Fܦ&J*9/0jƻN.:.U:AQ>IcŚq+}!qPLþ{Wf!M6?@+EOZ|*!( &.%c}9y !FG:^2yeTL?<hc^5P}cqDY`N) 8@$!q*v!y,(*nw BHh Ř 6@*bh*e"5,V^]Bt'EbW[  CJ^ƨ;BnGu d+d2΅co' SNR $8bvn׬9;YunpVʭZ <' nğJoء\Ic}@"-qLw4stJn;TApBP?aFX~@#XPۖXL1)|[;**֌6Mi{`*YN&"osJ(~&mߌBђ dw6iļ# p9Ygϧs:Vr..L?r0qx ?u¬{aA&r\ qY:a[1LS0S>~m(2wDusvMARX& )!WbՈ^wr{ӓ_R59q UmLaЌj6cYg'wh19}U A?$6Su6sxcA)mKcB@Va-cnw~<Mq1 0V n9`Q+n5Vv̷ǖ޳i" E9VWo'pǰZF!fhB I :ߑ$Wv)ĽJڗ"Sy70IizNm<ᚓnh=?z𮗑/x[2N?x oF5)xAژaRYb 6.xTK<;^VqJsD Lc2|j~;ۣXbfS֓+qw"(EPso4~eh֩ٯi.n^2[Fv., ؜De}zcn>=FDwҪ8z>o}ɻDӡѲ 7qWZXA]SyL;8nd^DR!-M;Pzk!Q汹&)]*+}يС+DƵܲHfa <' McV⹟\$_v4_ r^XEo4Zg$RRڍs$Zn\m:K:5M$ɐq+nigTf{Sy-^UUCDT0 \U<UjwV y:4F5Y}c[8A;L?䄔oJ &ʹnpIREu{`l GJ ƣ.+DfEwTۯ4ע}"3Ī(/-Q[rʢIϔxoR*&"FJA-Nfv('0@G] u_UY_Z @I֩Bxs1̣7"\6Z6Za[N+M.u(ǔ=M|Ov^ :2Ev ރ}qBĝ1|*)^<^ţirTkVcäB}ĵAy'3u}%8$jFށ8sh,[ P<+osƦ.4!v:Yfu$dؾ?uEͺ#j. g/1T㹈^ZJOJ)\;rX"&:m!aVݫG]ռh[/t{qiBko^ FMi{ *?ZW (0iҸhw cy[M#pxk ,OfaYoXTW 7'Yzja|soUTbaP+(rf•MiTϐjǩEC&Ug*Gi2a1y׋)v&Yȹ7xBF2aI@JhɶTwbqBȮ^lb<R8EGx#ypd!*^[ .uP[a u:֐* L}n/eSg@bnU\Ae:RC/qb#Lj_.5#Ȩ3,TmɆC8٧*ťnӿ|zCS'63VwۗP^65u$egiD^47!+6S2,xqZ(3t|<57F"?_Ayi]Ye݌jh#T\"lшo?9;.*jXЋSz8"S#&J9[K c}]+<^c jof"dzı_RՁ,lo|̗7Ye4gV0GTZF\=Xa3/F.HؤVlW.@Y9X:IsqX{#d(h_y_\굢g^n82)_N5tw \HXhAQ@u5IQϦ̓51؃?V_|w* W52>7Oʡ$"T`"j},02)p%:j[Ot,,T8 Ck=|^\hFHs!hIXDwϓ\Yw<fu% Q>lТť!dHT=>/e$-}zJ ǺL€]yaV䗔yUWvuvыܶP* bm{}Ir :8a )!:3]hθNߺq}>sZh(㮶R;I[Es-G'eTөoy 07}_)V(q[osCUnL¼l0T} '4&o TWIfHА1F_qϜdj-?FfpT9'PbU}+I}qy=] )Q׻ ,^;6$8/,3SIV>wl@a}i5$sAP_=?!T%ڮsHIn7%;o6j{Mɢ'˅k7W?37ţ݃%2YzRT"mp/OYH/e>`2p^6E,B+_(pq¢K5De'7ӇI7k%_RCj`ˁkܥʿ[/reES64ZKkuY>|4~ ,lu|5׊1kpZNq:3Ճ.IƢو0%OIX/X1Ǯs@dU uRs|(hUHm^#" Ξ޲{/n;ho *Ko(]w@dXC1gU:E 97h]j gz7G0{80xϻ@_ `)>@,bF!M5Ǯs0/I1 Gacd$}w3v6L2uwŚOQ.vB~ǜ3MMAŸs\+Uc9om"?fefGۥ?osZì!Wd *LA~^^Ih% [][7N]yA<,Ka% 7K3ل$b: ) ˞H(N*MReM$ZχR 35šӥ6bٗ\) 0N4TA%9L޶uT`$VRgmǨkwB% +fw !#EHl 6lQTu4f.1'M@JS8A &xR;Ԗzzc# u۸iHj"["Y=pbl!qUQA*apPd+"j q;xf0p k]"P4JܯqsX ZmB_S8k%3XF=u]'0ҩpLV>$a5kfi_yFBalWc^r}=Dg=x|yؔn]37^Yс%zP`NIKϕ3AV{ÓSZ@o72K/;eye'Fjƣеo%5Zf,?sg;uB I7tfaK𭯖p}9ylwAt/>ꖶ?-pAmdSOs-]Zi3yE^^Kps2 R.MYMF~Ex3>>9oVyw:bL㌔8))·@U9zNk28e5@?>%ͤJ&{vc|r`ɡ-%_OnGJ7[>%~*R1畚R;+@$0(mIT&XT\< i]8AepG Zs/ǏX'TZzO\FT+3VPY9>lڪS# >}Ly{t&JqmoeIP)- >$F0lb !"w//} >OuiHݰ7\ V|?6E0V ͳ1gU*Kժ1GQrǠc`g@U0Hx ?׬9}PF2MٔjtK̉Ӡ+·BDf4ť>imiLZx`e FŽe[ Ӡ|Ѻ̚aӵOhbAmOV2Mj6FgZxMi$VcS28AD;Ntp ?j_ $&'fg=,cMU "-jr!k*bp;NNྡྷK2O骎 1eK.Dxf=MWW޶B':Ao~`O-3Kzi1-pNxTN`ɡl 'ff 37SA #|u.̔4Ef&XURڲJj#CIҗ^vkw~#uM2 ٮ( 3b!Oxq߻8r1[pt-.n#Q)}XCWxĤ\ EblBFa_)Mx<k%йq]Bk4\K~ﶥ0JUg^_٘l>NbǴ'U g?> \&(CjDwg|4.ǃXyNKr͌mcvcsPU _bϘG+Q"#>5*OG0q*jT4Kgu_~#s8$di3&`/8z^Pkմ_鬤=k8 q&"؁or6f{|w?@!|u#%p6ys_&kT%*4"iJ"dņ~GYrȆrgRI{va\2 &}qW'7FNz.HRgnlx|9Fl #ʉu!~F@dnWdo`TUk<*xvS[]yzC 4y 5ǝJnc(uQ{;Zb ӱ.`N¢G3 L%mxZ=QQN]y~55cr;Ys+uO%ϱl1 m(F澵ȪlKkdt!/a1.(r>:qyb<*42ie2,@ rµ]-A-ް`ٗSm ,f^ 91,⺓L :T]'307^6͙!6/ k N]R &c\ 7A^2mhV 1Ћo oJ+ !lbr| HĔ Mr%{`zۯ >Ӹ̑guW'"?p!w?n"1)0ySIc󀜼S3|jhLEctBX!NkK]bcHhJ mJ\>w&dH0<3w'{AH -G\%ܥDAX$)JiU>{-8;ݰ!&YhBHP7^PA>4F"?}N3Wyu:%䯠vd[6@8))ȡ2ZU/7C Vr/S^&CrS*Kvx"XE Y6N0J*WV 'llJ #g;`H̿M?(M*c@&  z7CA{޸c-sur"F(03[ٗyƪS夳^k إ=:we)Exury9:Ew< L~2(Bsrd}D7q(0xϑFҊdNk+~7),ܸ9v}ֶR45]tʁ_g$Q*R`LvwUO<DZ ;*8݄T7OW6 6T|zs]_ V3B> U8tʼnA@Mc;@p#WQ`,pM\pvV5? {DCHE_-CNhB !دj>|5&.RKk4,}2&B *F¡t$D6!2 3C&>bXV+0FDL&ԑ^Bּi9Vc7e "2ΖQpH+}A#E_2=(e،f4#X{?8c{.A<sxHUՙ9fg lZ< ]vҜ.M(=ҴcxBLܢ_1+en^SdtUD_?%w}k*W!NS;{0,1K'*|( !Te6_y vM Ea~ `t$N9 Bvz ݌WI\e, gtZ!S>A7p2@v pGs3 ~#L6qͅITE|5j|h`&%soQglSl>M6e!a(ك9]vhijb|&zϔnJ7e01WGKYl(n4Ц4O?y۠\sBQ #q`GlpL@qL^KIX.q'Ҽ"dU,PSi'h4g܆-;EkylPhćSJ_aZOMLy^ vN˓i ȲO{:M8ɫ2Ֆ 6t}&"|1`$ThLթTMT!bbO?CTM =NC&A֝êVo9 f}*$#sD'bG4\k;1^^S1zlmΰ .?U2Y%HI@tȒQl 01oVQ.*0}o&|G)͉S,JJN&!K&krr,¦"Xp5dm4ʨsQ\aǂ]joQ|o` ˟w A[?tiP8D[tMl9 |Qņ%)qOߧ2Y-O`m_8 fNAd_EJƈ~%1r0S-N,(8{5esb&K =a#"{ևĐ^E=hk z:w<|Jz?IBliHSpb; EXwIc{=.kl`͡ 8QhR JO7/e/*Ll_Ug0(\UߢP[A"-$ r$2#sa @^;s6E0Rz7jEPZ '<.l p*y{3_C(h>D}r^K L{xD"r#o)ْU1X\Y!V=bm&+F=()Lz Xvņ(`c7ED2ۢ :\;(c{I4 n˰Խj(y/bt7q.Pe"/t~/wpS76s-Mgnl|D6['ɢ mQo!O .jD tg&`{L8>bYl"-.1iqruHLY!Sk L:;1O,giSN9#sNB-o!~sxů3Z,gqF ;&ƹSKu ݳX5bI!7[cC$ vy;crXf˘uԟ[OI Ume%lW2[d*8*npY l;֫&lqgWB/ʸr].-l'$F>/)KLi_*nY*gV%?#RD͞kR;~3It'3YDY] n92/ Jj-!> K6:lTJ"im9M>:N6ŷn!j, k+!D'[ǿHp{ dGeP䷿"nscRUS;akE_?+_JR'_ a ֡@![CVO%&hV"`T.42sg,K=/A8uIXoT9 J+F ~x L9lH zhͿ|zGp-{6V?tNTuì#c8p#_~Q̔%*% &X<|Gg]9Kdڿr9? j?2IIC rrSX<0YY{έ g&:'&ZTTiD#,;Q/nwO<3E6s6ǀ.k%& Lbtrfքlthoks+>,'P8G4RҍA ?Rk#r{39R2w\OH!qT@Eg۞\.6J >y)^=?0Sٜd?-"u%b0U$b{hM;=F>]H"/'"38u#UY *X#XI:)[ҐeWwb7kd> sn i3 n_603^D3Ϣ!rR'HLJWSA2Q^|d:7^Z1G~b/ɵ";%xނWͯ ->HZݱu|||2bGV8S)D8`g7V؇Ѳہ)hJ݂+Z{Ftfg4Gx]P qn,6ݜ=(^X]?,x:Lawar{9e0lJ${HnAs庹 6Q?k*B*iM/=pPuS6R#3۬۫J}f7tVUHi#N=["uFM T+ (%'o 42[G4C>' iOPNB$2S6>s&i@ᵦW@9E K|/Ѹ8NK2(rqo*Arb0<:SMEeI*n/̽!d9_KHcv%Dn%2Czşt47`Eך^g 5uCaY¤G/n!Jo8vt4DJ_tUR5R2yjּ@kvd3Ҏ~iqO]FZ"NLӎ@0bqaĭ5U@/+ kO] =/gHX? _r5y!1 @L?-byzQ8.Z9N?UYc4e2$CgvM|- tbKl6Zv ՎV1NQI J$"^ )zB n5PR6[ jXÉ"ݠq,+ vwkB92KXJacD/p2X lq:DKLOYNO3#yءA/4mf=ŐeiVQEF ,ؙ/2\{~r9S8vP*VIq;qT5! W1 rf(ý1j,L"r RZ0U}2bavxAnGi~wm3Sc9Le5pD&m yn0o25MO,bGy5Fwp[Gʥ ޱan n!M ~ =QlF3GHnZiOрPq;R+:rMh!U^loHh5XS3&qipR\9NHO#8])rTQzqYF l2c' t'v/7hlTI&>Y:tޮs[e{Ġ(ruI laE5o?~15B@"6A~,{p]%iT7vsjaG]T>_?kVNy`_?b|%^-Z6?oyXט֔E#MMgxU]yq 6xMI1KT1'O%>5Y`JzZ+o"`NIz@ϐ{.HH@ VLn2#>-I?V{Wa"rß ^J B$ J?N=;k#C: @>>KsNk[ h9"=?xsW0¸dfW5g!8R%~a47wbqS…NY@YHtрcoOQwy=NHpl:;oi4vZNFgW;KkNKCjN~| NdÕvbo^tk~b5j`D=h"\r01x}VJЋݽ͂0Y01̲IɿyvSf}ܫ\Mabi6m;% >K [˿#tJۂb%\ok﬊(B.SF0i,j bNil6i6#,J`2S@J%Z'R [JzBk b6t&ȡCprsh@afa#49󯌓?.8W/Y(uc8@lX ~ڵn볷TrHhiIIR\]ƳkHV%2;NcM>E $TN'2 UO l=Gd?;L YD1W4'"hdr:tMs@id4T\Is>‰m~++@zM*Iz+n}HQQfySȣ8~5$O9r =UQ'P4V:6`GAM QE%HiO/OI(Qǿ+ů =FC4iZht`<\W3|%QJ@Yl]U!ޭb1b[|c;?0ލH % m0HA]?qI7,%BR\WvĢåG<'!!pֲP@ 0'Rh_uP2[֣e<~] B/b1[+bh'+QR6̜;[PFB`Xc,Zr v 5 !|z"0pÁq>R聵RWI?<~yוp̂#q/d {9]TlEߗW fY$6}z=VKZMQձaXLПld"n:ٲVĮקn#ֆ)GtY+-\z7XAm5\p/~f'޲hSrrc;& ZjSîgO?K>-}otHjPb"t$λA=$^M$ g۬Td󮸘ۿ$Կ=2i>R#{"H>6"tt^j~Ѷ8>f&I O*x"MZ}0yуDÉ3 D[bL*VԗVȯ̡pv &\O[a Ϭ 7f׸bܺ  #6F`/Sgٗ*k|UzW8Mӯjd.&$uA-#wѥ8g k&ޥɊ$Rw i[i#J59k!.,R&9D+KW<<]Sk롡呏;'FfPe)Կ_M_2 ^9/@@pfs <2rte㊕[4uY mWb`Hp\rC6 gC*úx0:G/^ +gTgN1.uG 1SxA10YqSوQsj͒dCZ=]Lp|jHA"TqdAMb@nǠ̽˖S14W]1Hw2.&ԝ%okR3)s!ܠ(mMe.9'2#RCӯXl uOLIWXe;+/_ P+sRhIVFi 8Di=zA*=ණFeQ-+,\f"L:>7w)E=4#xP头 bFh* gWňko5+nG%%훲+F2>XxRwpWe􉯾m*jvc"ekɹRQ\Ig:̘2+{1 8O&81Ŵ"M'Lh<2{ !Dj2vXpz =&)K\fUPce<=OeiFSE )GHqDa0o?$'xZ0.AEUHbkw@eиj!I|us}=潻Y;\L.€ +xu0 I.M2!*q}Q%PAȼaTdT"_ðj9I͌;ГZy0_?ʘ34O1L]P>x寳";lmu稅m]\Pt`9g&e.}^/cryhv+VΘX+Sw\ݍl zס&i]Iqjs#uH%A1kZDҭwKۋjGSQS-@NY+{Y; vź$Y^T`}cGnW6%`h7d aJOlH2g YJL5!a %o%T qan7W=`!;7[Eu I#6xIF~.G&^CE =mU+ Lp.o۲&k~5t02 b:HQ讜W sm]sL̀D8My9 ё'rl,8DDG*`,.Fk-_mwHyou7ӌh|C:)CZ(D$ ICMִe3bKl^̮f^iSz=7-OR&MeŮ&<9}8G(w ۯ"8$PujO״z# `p%O4W}:8o۲&>@þy<7i hr"fX{KVcm%B' Q G{9<+:v]qMN=hsUp"a.O$mxv{doqgt"wxcߤ6 Dž}rj91T3ڜrO%` EI0Z}ӟ{`Ck{!TT`4~rVS0X'0 V~09㫬jq{y:80$ #D8|Z) 9;#,8,;@0bX rG̵a @XD"-z?QxEɥ.3|9Daj']ig %oP7u2/@LZlPǤLa k4Ze˄⊙ugqmrŦxJ_A2~WZ6 G#/,~LeB1G|'j\ j1m]cbC'\Y""KI,ryoz>| U6Cv|?ChZ#,hC'6,;mγͪp]@uH 6YH@k6TcKRWshǝ 7 ^tHa6!*E$Lm=A驜$N.0ӥ )!Wxw̚"C7}vS9+:BCX:a#GuOijwt5_ؾE) @H"p@p{9+>GEʼֹfF(_$ɛ:Xlc .J<BՅ znP;-Y~SǞ}TSAg#h_x SU]{-,$̒60PMYĥ]~_h~Ԯ?/VS~YZ0"+X=LxFS3E8r "UMqA5Hx+J`6Mƒk,I?H%̆5`L:I?ØQ{KꌭӉPg!"|S2HRCqj?=i&IZYtd6rlظ>꿡'HNCED."t&hSN, p7a.#ȓ01y } ؤ֧VL%E@_b;nԣ{ GCTL2޳/ߛJzuEb&QL6]}5]JqA7/ùS'Tuϡy jńS+ex4\{c5ozv#%#!Qګ8lIJ'i)c6 &]yA!+ѯ /v")b ZrZ?kXtb-AS[A%bayW>~Vu!"gpe(zv6% Q \Da/GcV5bbl4ԯqo`oW1UKԓpy 4,` ORʈ@&*#" !-Հ!'1)၆9 )~;7VX}pG++ k[j l.񰀙HN?~kbb$Ļ"Ҝs۩jN1]J'Z!N=/YAn$.7:VMi ru{]ro81 > ULa?-2[Tp+GWJʺ !]Xk]Չߴ#UMG:x1\07#o}4o Z:,{g*ϧ; E_oߠC5MemaG~yt!rZ`ؽSQϊ0{%@5 bÖ\+0/b91T߬xMe!F*ych*j9xʪjOR1(Ttάߙ:gpd2g1RDQ9McX[B:Z>Ͼ@vn=&:Ee-]XF* tC(gP]$.5*Д|!nlSi<h=`Y=-gedENgFߙE?S)> Szy.$Ey`sS /7'<{#HR| p%_s s6p0EFwI5Ũ*A:#6jDŽ,R苤)On, ِZV>ȴ5Ɉ)"$Ⱥn/G,LKx\LE<]l7kVՕm]W=ImU\=ssJ5p f"q1@o_)>pY*<ѴiLpOpXEc;itB~|Z+ 8n*Vws8/¦ׅ+qU8$"vUԄf];A:@r{RT.Bzk\/uw]8)#Wq_A}S X _ʌS@_-y?m=j_۾}8rXCMaF ?F&"3]]>mwGq:dՖ/{ D1lU'˯t't mko(qerPmF% j!kwmI[ۣ $MO/!Z&}+m 1} w &1TT_?jh Eґ{%]Y/ ."I2?Tav 6>%u0XKy T-mUƔ >B3GDŽk'<1f8BiH$b \bTLna̓|5:7I4b9OR-sYPd5β{jԌo7;^ui 2rXj҃Iz*fRm@7Gx0.YG-c׋ g7/]Ip*:+Z{#x@5|9;b_ y0kcvX־GQlzZCȆ tI!~…}W|8/uA ,CvE!ms5v+r߱Ʒ}Je70P(4$LҮ=6o"g~П=O2hk: ^P !yym0F+=EGK`Lpr:F ӚƮArCps2ԕU SP` OݰQ2"ьR{$y0b&|5ag/z\[Mu8lp $/c`"B w")`?rd`'(ت4[Bu?͜ϧY-~^)bN4 z"U(NJѲl̺ZE=aɸG!mN "^s(PHB 2%9K*YO97D[VQ:$љ2#ǃt(cpw!W~AWNx%ns-DeV`*#VeQEDx#iH,uڥcvy >&# (:.}"<8kNN%D"vmPaè鹘ZjsApn&YAhR6\L2q$/7,jeշ (e'prK %T]uASJXG²kN Yv-qL6k.߅ՔgD,Կ^ ءj L: xm]z5a$(y'Nǻ7]G<\FB SԴn[cc<}wNSEwRBY\Jmwb\P~95oz +CC= ~b[ȷd}ӋijKvYe D'$瘒zZ/V`23̦n'ˢqceM~=fbʋ"o֕$}Dn`.ׄAJT\eBB">c@r~P{n{xs(3cy_uieÍyVkXZXj*F'%g c_:? @X'IM3bV! 粬yw]{+?cZ˲}' y{-h erQ"%Pa]tٲ;TYiAw=+<oGI_0Dv򜎄8@WE/$s9'*܄>Ɩکq|,>Ka64iՁbl*/`1ީI?TfVf~Ҫ,J T2PfAhF6Z_&;FmGT{A|9=}o?\% EE;rէ:M4GVxl`9\x1:sBCbd=Pv(NRb|kq|wb2-%Bq)'*. 2 DfJP(B[1†=ڶdF!!i+_ Q>_RuL$#a ۑOMN0Lx$sSI,h ~ٮn[3Oc+V`7WEAV%="G_HCx;r {,_D;u0I9tC4+)my<0P{^Iڵ%L ވq42AI5+ EźRw$uI(zELvO9toY.'{@YWG .2jϱOj!C(I? .'nBXTxiul '\Ș4:N<ȣHnG' H0}{+XPqE6(ѪPͿIT$}fתzP+}lZm3a:)N/PޕEk~EYl ̣T(1, Nw>rZ.j"2>ijCWH"*szlzNȄ@~~)ĸfto\ʓS>*-|"K9(_48 t}Nӓua`gS(꠿)GY S.ZhrcЗ_~vۅ.0t2}Af9&uˋ?vX{d,ow8bڠC],?V';{T72 Sr) nAe꿱ᔆARl;'|RFzC{#6bz )\ ]Jn!\gѭ(y֋R$WۥaO,ǹ)rrmѵYwJF$pE ЄrB|s~8UI "--UjOp 갲#8E sZ&q3XUn/R!`D@^ҮauBJ[y\9gMXn(ZO+WԬPu#j jٶ/)uj{[i7%DO2PpHYQ>aûVS wjpd"OXfO$9W?"^?][7@&|hؙyqYe"aH,)nhY=$2uޯgD7*kEYw+ХtB4x/:=5Stm:Qw `ܦd"ӟIҌBpaf6v/СJFL*_E^]PJRʞwlpH66[ȤmB8 ^1V}׼p6f[;]8ᛇ@a/7 n|vȱU&5#X*QvgH jytos(ty#@=sbl 嵉0l^wA7ۀ / &"7g`3kl c)EIVeIPdqG^ZK#Lp_uNkiqNC󹣚ֽDq'(1o.O+]3$~]  w߅勓݁fad& ~fuڸf䫱up'kbXĻHzO$o>v!q8>/\R6"R×˲̑aI Z:]ؕ- #JV{zeoUX2{Lo%SŧJdGv6=jKוk%:)]뭃=,>>Lؼ@7XpRyeRF ;`'=zc(9r *-+|+qsq-l0LiJI+~ms|XM??vVpdN! !∖Sc|-cbo:2}c.PAwt9Vku:O,Ud"]vVSHʱ6w{J`|SSzCqez0R㫴/zqΦL@@Y?omx Exfzg Ƒu X!"ži?̌'+`;c7 -g`od%3i|POia(, DKn{ ¤Z~5=b}- ĸaʽkMdJ24$@U_$R=HMqɊCY&)Y)Ru@ȱe/p?pJ`  Q"g v%εD nZjS%5 •K+5DB~jnJP2aX,f/7D9Hb Cf(V:G[x#IRnwKAFf$RO=cp0Pw5ܲsz'y 79Z2]lڸ~ .$[7b>074fh^FO^lrW3/i Kco:9E36'(Y z3%~Yr6ך4+.`d$05CNn\;1KPYOKv>Z?wgWQc}*v_QYi|vBseCrӜ/S9.Y|f{Z(Bpad`؂ q)ltXL\:Il([>&ܲ|.M,7d[QX ?@1_Ul1%(iA2z"T|:J&ABӎ.0DTwcŧw m"~ꪝᐙ1dI,wbAy?? `j(9 fkIymGlQ#L/YMZXOށqզ; nw̠ݺysC]Ps-FiE+F#jr*<I+y:S.*DX,Mr!6tX"uoa /%8& sS *;_xJ:1ׅtjiskbTM;̓SX5Ž}߭ߋ ./[_wY>Ä d-A⸡ Į !uITVS*Tx%&\~H @ sF[D6Sӆ,*J{M+Dʈ/ X%!ъ*,늺fg9dß1_0|;![߿l-e/慨㘔Yi^ "#wWݗʼn'А 2{UT)|$ęgFSs?ͤ)Q' ] ,&8z;tUӉ+h-a Hl@f(G;%Ow7 腔*jo.N#|Ⱥ" FA47=Od7}Y~LeHl%Hn~ fPnS`y9+'sxq5O |śg:gX簴SŏxHFj{a)Jz7,P]-Y|2_<}edv(v2 wcT.7,1 a*SF 5z/./v/shH^kH;\CuKjW6ʚ E<~MkG|Th?㣔U'F܃D}`.\KP206'ShUMC{pd/IWlR(R2&; 0zkolxHe:`M@v199Bn.^-ÆD 没PQVB^N_zM9Fe{zC2A^y:hS0@FZ BQq϶$[>jI>Z̑O{A)iCp.Y;AMl%OjnydMeg|ήhe&d&1K\Qܞyʣ dɀ#kl+$h~mlFyPD;* >(_jxM?NfVQ)9^%ӭ^c]MNҼ:oZ8ZgbpD@O50otly*x_ k,Q--Xva'4<D[Y\S}}kvZ'SjGqI, Ty5N~&{n(V@\e/~u'w)|"$. 0bruZ4dcGTOGSU֨N ourif;y~IқjfgzCO X9'Z Oo8.%iV~#e;`ݕ^A ͚'Hۂ.@A/# AOk9|ί#_\8ڟ=x3D0F-*N]ѿeAHAn a0'3`GJLlO5yIc1?EfDI9,LIW6t)@H R AI06QTl Z5"bEW NWO:Fz%CAO"JZS{R!yf)UrhÝp{o ;H ;o Zda.GoW7 LLE}HDMuFʤX?<-o'i㆛dSWL *r t?kgF*Z7Á[zt=*Ki:h8c ~FP5;7)M?1)= 5D:r Xcuf ʷ|~F,>f-y8 jÁB81g sfX iM~yZA" Knzxnu`7lF:ViKy;]}} ^y=Qs -GԾr0owrjFtQJ&1[ŖH=5$3Б)xC <ʵfT:+\!r^fEAUIa`zÂ1fӇ D>rf١Bܶ[Qu-ǧ)OcٻaVBi>X>:E<'FR4]E#U1~"ըjTjLNPJ*k jtCL7v0[L nG*oJuG,KJj#Y: Pz]YH 8Xuw`w%v>"Ͽ%Bl {?B'Ni1^pH:M\= +j/>uXiKIxҝRv$S/~ƨy5߲+)|qX;㡡d:.IcKtyO=*lmK nԖc'yhL^ r*6f#62?feI6ŰƼj_BU.x4$NZrݟǜ?:wzB%Y}Cjot8ƻ:Ӫtk}~$RQ\ðu-ǂJd[.('&{|Y0UMG8 27Xθ o#=ع{=fSuHB.}ne Vd=1ϗVߢ1jG7Bjd1@84w˪Ͷr݃ ċn!9hH7\uvI^A&$!~C|ą 6a:<v٫|8 ,n*V?;8GV,ξZ˧lz<\gƞ{-ϩˋ܃oABb40>L𥭟Pk4.4řYAb>,[ '.y` DIh>CRMj,; | ʟx"Zkyz8]-B*kGl]ŕ[=H8~v+`*䴂&jYM!C3 7{.}\/xT\acJE92 kkH A >5kr\m Qq98r󀁧Gۖ +Y:Vf>K/hf3+0ϣW`AZ tD<5}, z\pL! 4g; ^8Ni53꭬--Iz0NVguNϑ! ^@{łM1֒qaPJE||1W*vtrP`8F) S7v \`'''v?')n(4yXV:PY }ami{5~SZ0DnjmCB̰VOuh:ƛW>y r" +-SӦXps r2(ҹ\"x>Qzkǚn< +Ċ[ڤrR $骱E5QӁ, 1+] FMVu$8VAV,6}Y!L~^睋Gch덍’\o@C a&5W!X_x9j,xwQn H%$̈'3OUsn jW5 m2rkxťkoZW>ߋ4KM]4VD 1._i{ZQ;pj2J׾+ M:9n19{W8 #I%-;[X9-EbsGEF9  z,ֲ%ue{&K Da_ >~><7zv:J̓_LjDǤK0ޞ Zrr=kk{3`/lݮ@q}A;?\4r>N1Oڤ5'+[3BY6ۼM8g,CN-e"sCm|ҥSGL7 ytNtyT葠B>@H0V4;=3#:{Gt1؈; tժ\W2I7yY%Pd8)ң0qZT<>ǾS5eG(k>9~;^݀oYY1Fr4aHW-qdLǽJn_ySNxH–%om"5vx9|86geadjv ;ؓ?|eühvC#;;em^NCsP +R'NF^HrX,='eEܖ\2ʂ`%ɇiOѦOQdAo1~t/d3wYF3lUji`JO8D8s͑B:~Gu klL"#0 :MK!?q :o5^@q+?cs"D+a{J|tK+V JXq10L׽ w'Z!`#~萔-QaZ#i>S/CCpzIjx1$cF<$%?W=^ /03h}!ufHs+yX[rlJ!wd=,Gy PESd!vE9| ;5kmnƩ^vw>VsB ڛ @ {}9"Y2.Z[ <~D}fR)Cu_*z8$>Op:o"<2<&:iyc0q3mȤr LKZ FpB;RkT'"Rqo_=Q.\% ^n0`G>ˆXeD`DeubupE&K%Np5awu%M:'cN`5aP J1b g~es"W%Q$[+XM !"Qt"%) O>&D^|RQj莔rκzd=%^h*YU0"Z+C ^aZh[1mb CKr*EfoY:-mzZ7\uX}'WΝBPE*X`I9]J'=)L/@;YסLFOsx8H&Gtt,`2v1\I2GQ ̫2#S"󥐰X5ρ:0EAFA9 )nM#LU&1V~&kÒQ%Pmf0XA1#: M|ægHZxdJf,50,B@ eGpJ.ʸ(nt_|߯??'^襹O)n}m#Oj]Mm:Ƅmt=J`<*,eB4!e^4n9")qUvgBFoWKhcJ*RIR,]7mw 547dſ5S|.{*.rpD+AJ[1Tz8-?CJмNcHp(DU6s22wLM-f#Bաr{`r.b%؆s ^ `߇dꍤzmxfKbC@A(BSM 薮ۊcZCyE:~wY%8U_SE$ 8{W-2<&zޕ^ OGF3.|` |'|{B([۸^dmp>yn˴Brn Hb:^srl[LA@+ 9?2늈-sh9%Eq+&٢BxxdZ4X _Ӣoo`U $o4qh.u MB`ќSQdEeJX/l;נvp>uα8PGed@o37EIxhw˙ܺWoPqt ~W4G`|tX݇hI oڔqTaP]|Z&G5aE8Sߙ'dHe]⼅Z|Rc&!]O<67%zO?5mriӟ؁W!ʶ=V$r]6 Xi2/e$o&-e| hGM^<> 4vo󂵑jIo6):lUH|ͫ{Pm>Mgsvd@y5,*kqZay~4mU1?,婔{A[E~Pv^%K2GW(EHaZV덱LZ X =BN=- 4rvr[s?!G=2:;Fm_;% ȉJw1ca~x'lj\[!#gbgh=}k\x4K&aᒭX-Ijfd^,gTՋ~ۙcC,t+S)`fHrԸ+~3"98+-f//I.-v-|_=t}]ZwB!"ňd[vn|:dl<!H= K|YU!K:hq 7?g~o.7xy>H|jٟB)2rA|u{`Di..}ũ2哹h=F<Љ 83ک4,G¨:~gF^.x|+@]bsDʄO /8t,Π7jodǂD Gc# |vBq4?4".ne04e3TE"n%^֥3s֪FvNxX+e?K 2jfJL5q~dΪ߫;َX{^hMf#HJ_&V-D[V ALSUgä)fg.ɠL@tZ R^; FRع8[oi V08J!\:hӶqLtDL,+r`kj%S|.1=h$+4JW+SԓX ;,AIUiKj'\a-u ;7F "4mR1J̳q\W$`O]AexD„≱+45YB l mEcD|kRGmE]^!ߙr|$J5kj;ыS}]6 xv>I%.JO!nfǷ}|,ǹԹӱ`{=opFC0+0ZqW '%&+_lzDR*Qq|w"lFika Z03{}^Wnhٚ7*O!eC KNah)bRb4P{"#|j wLǥ4d#%K*Zڼ hd:  7n8]/:QȺw?a+fZιƯJtzuw:b\o2\'%](3[Tf;c0@&qj@0Gfš9'1SRq>)CǔR`flFH"*> x["$a 1FrD`<,!%' &}_K ۉc06 ڿqc@TA.|}D,>XH50 Dz'?Dв,J WD?SCvʸ8y8A(.aX,ι_lhDĈP̖ĢUj@Q6wJ56#D`xϤp noU\s^(I{Ů Ygk=yr+JBq+6V7rTP:qmȈ GKkWz[D>o,Ζ$#o zu1Zd -${#8OK2Ȑ\%.FN8''4OHs9'/HL5P(Ev0Uq #3'#$StD.䳷E,V:Aot~ cÝL] x׵Ahw]pgl){3m(b!@Q}xS$0f*Bm&`8 zᚚ=TzYzy [B Gpyy'47:\ _՜zS+K'jes;"@>hN%-ZTuE:\Զ 7@=}RFI}wBM PTv.Sj/|O˰¸Em/jH]CБ+:<VH#u ӂُNJ9`SWwaJё64v* 1C]c^2ֹo/1`a>Ig?5E#PaT^Sg{ĬC7"{*o ?fؑvq-ꕊ_:OR4_ǷpXp6u߂q|$Kf^{*hjẍ́avEO6sz7 ,ݣ:ۗ`(/Ce +ьCDv K0ofy7Y& f8J[@ ^QJr={/߰挗6~3o #3/u:yȅI1!e3cϦԦ3F؜U-fЇpe̻r)o K%,*%(kJozc_Yz:)Tw!B=׀Kt{izEụ݋#,;I=.o~:=LCav7oD>yB ,2\΁"C#.0@}$Z{N5scDhqAAQS޹hQ ;99vE`T K%-bRmw~v1<8(|wHQA fS%ոax@14Uȯi7u5L҈F|tm瞗:aVf:P ^eU1YQ(eL:0yo״Uțut5̝(X}6ݾuj`ufXYm,1y`8LP[fR8Td7o=!ay(RT +K|9D4{֜wiE>p'6 { š'17y`[tȁ "F2@&v*5Ŕia?{C5*F)>)Mݬ2LT$(O0]1v+FdW/\+uۧuj%m.O-_F9v؄,XG^|r ,-D{4ɔsS}%Nn7i2˵Xwp?Hdi+I xh1%&=% "q;`x93g0ȹKJZWjN_?K=<0{%?~nX%秗ln\ DRѕc*cU*0cq]|@ +<8n HP[ۯ8Lo[U Jvi(Sd 8ο]N+<,pRd| 2B?d ڭ$c|CaTʦdC׎*2ҖX F Ѕ}.C,U9ܚ"}ґrbP!ꈱj*'xF7؎~3kGWbq 4AdŠdhxd* qXP?Ne4 (Yں\#S[+Whk(s kax/?FlfAM*vxN_"9 ?@ٶSj<w\*N ¦rxAxc*Lq-Y Q1g 䎕Q"c;4jGTBH,T;7`9s)t<2}0dDJsL |Aa z'S4λR iFkmQYxg"c`jrDtfU"qm[ UZ˄шb2̸\ 1c_0)~QǗd;nvʖ)\|%F;Kgmq@}å˜.g_;hsYAY^QRozVRtS0n6#SW ;JvA;* TOsevp/r1?ܩ`(a #IhNϽ}'b| v l $\nnH;4Hl/zZhڅ֮$I} o^ĎE~ۇpp֋xƂ/8e= ͬD 8,Hj )7qj&~ԇ);8 f ^ .x-ɖD@+STG RC #u~2^p:[;c3A\|K?T2 òz|yga@c3+ҭOp9u ͱXp zT/[:ۍZ ބN<΀' цqpOJ3@N3?Z9$4$ugXKͷVk%d0I$__ߋo6_u}aabƼ g&v7/{,.ܤ^[^Is*я .@LHYF֨! v9JqҢKͺ "B'$9` ٶceEXR:I-6nh&S(c{}Pbؗ`)F% .q\߬LU 8B^VŹTZFH6y9PBf#"}!"WHy2]?'~9y3 P(BovSԅѪQEdDQ,LŊ\L,rE#J=34ylaTrȐqكF0%_6=B+-<;v7=Z_sɹ`ԑY+MSs|#!ȀPk4)v3LuEM4dbB oOQtSdzp )E;P5Oa^b(hVv&WxADrOwlO;l@Td3JQKWK1hUN#]?W48?Vh/fLhD6+m^crwcwz N`Tl!,e58[qۊAEyAd:KW ^zl!# Wx}KH6|s%AM$m e#%>ԇe 23 zArv6Rc %zIijZiFeS*uݹ'z8#+KԒw\iHDF>(`l5׸.&h9j"͎*b>uG 4D>9_Iqm0(GW$+xuvX6һYpۍ@zr8*$ æ"j/cNw4]_WxűoQXs\j\hbpkkW*it^C2px{ЙDDwPUlRK5 Qh`޽EjdZl @DO| UY)C% S[]י3'W`CV}z>_p%w(*.H@'B짘z ٿ:iюMW?|mS)b ّZ@TLT){x.+f`ԋ:tg5 gl/+kt2 Ɍ=1sylTo!K$2W:| #栰M'3Ys4*$6G:1QeT2#I|5JgʱX&,N1qSkTZty긇(۰QPsOo8lDuqI}"AQHi%YHB0 $VY=G:-b4): [|U2P~(854E@td-y8Qt;etJ/ G!4f=cd_Չ F,VvtkRCs a<&JޡZnZ#3C0߫42G(%Wo^7F9HUYO;bRyʿ.0?sUJY! |:il&0.zt15e|#QU˜ +ãFA'lvA,Z C:F.ri'&h{e'AB<_LZ~4V&EMSiJ`5o1zT JuHV2ϻT5/3ـD@w%b/5tIš'(KJFvL'%#u= rJq¾#{D  '!޶0e}3EK>XG`kl7M4< 'wG\)7{4s<惘Ԭ*06dUK]h- Ϯs1#(󬤧Jh, =pBPؔ0VAkޥL+%v1Ҩ OQ9`l.)4&tx$5UGuղ1 z'ww-)IXsdZdUt|-=10y-pŗIMɐ T1>j1ӣh5mBQ^5Vo8 92%)aTAWsϨ))Y10,e-Ce7i$={pV~„~~^@Sn&ODKsBpY~>U쵨쫖<(@'t|(/jc_ |`볍M+U5=rX-^R A/<"*Qa\v7b0Q,3T\&J+`.[5uj yLMNm)Qf6^l|nc@72^lJOC*ڱRo9_/G`.V\4dL*Z\wF<,1ٺX.bnE6d+~:v,)ưC77w7b_ /bg# e5r'f(g!߉Wq7pbțs|nRŽorgBȑB+;Tٯ ~^4D\Ujp+TLDrPUm.zZ@%3(B;>4j4#ۮ3I{A TU3 &z{0͢znhVz1 cv+L%"Plf(]M-hC\-I C{ cXUNw?Ho$۽u3Ɏly,sy ,alEcSX-4@J}r6`l~((¢|ed1z`F(jthdȀ+| >zdNJgi3ד-#nW`Γ܃qĽVrc~xOyqNC@Z.OlAGl!w%qYXsB.vW=zb)ge)DJ3`c/?Y6{cR?j{mş텂l])9'\,);H0 )(1QM %Rh\k􅮂,,k=.$Qȼ1v2\3 !͜rP&z<,:B<|RXm(;l~L% 8 9$GF$f|dWEdBã]`n.vbm+v4 bh W2I7x. BYf\UA+.-. <-=[I1ysސ7ZR܂t::nt.qJ+= 72^D'g!@us{񼆀XRHs+DX^=&@Jb(*S鄉1OF%їP}?''K5]Cz6h*^Nsՙ.:里"U];QyGc^`M~[4?Cm0Biր9$+Bc`-bkIcY!uwi[wEOF7e@Lю,CZ.̆)6M o` Ι3}Dֺd iiloxɲSZ@~̜ Wͭ?8>[0|>=K}UY$ oi u\ٟ*םLs [K$UḸKoY}OVvip fI4͚pXvtyʾeKVd\l}W XQ@.DdjPM*Qn%h92T>%'JZfp+ TĒ{Tj+=?>GVa}:c!8 CAZT|H@bjG1cq ObR## Ĩe؋cLa"p_Ye"FXOJ䅁#eqٴ.D C@L~ɛOo$H\_?-eU iN1D=@i}x HPEQL ,BCd)?0lPf++bl*MHTsZ(3x:b o f39`phIts@YD$7>X:׏0s%h sB eЕsÙ<ˬOaBr3>p+L_!{FO"L9=ʡ;}jdf{~jԘdWʝۭx &=`:Qo}lFTk2YV*V\aXfD%>UL71CH/6H$9-D]F>=с~IBʁ3MZT{.^ĝRZvrR}aH {O!EԹQCz|Wny?O J^wCƃY)L 땜TQmEy_R+}"1e`k`)o*JFx]iՂI$Wk"Ϋ}?\g wqTSm?JaK!?>cmļiꝧ%zLP2a;V8,"r/{ C)dE]v` jy@m謫DKԪzXF5kbR,RQ,o Ro^M!| D1!Zȅ< o 2)|C @e [#&Q + IK= :|hi(en~&e[?\NRn@´D.6,q6w=@\/6c~|gK TyZ]!c*v ?NѸ܇h!Kfx"1 5E9E`; j :KJvՠ V+Y8 i_'";]?%)^H'=vSq*-a5S2x+T &`VEo8EGܾ5. b9tQm)GsS~䏸/ޛ LVvy? l4j u?}949I! QNZo/~[ծDJ5A'gH~(bCfv~Cx[uoDG"n"}w,Iݨ=`rC֌?%^'XJ`ʪeiiݛ%a ۞GRWhcY!JJg-Va{e:W+]*o٫vhD}67ws+5׀K3d Bx u&ކFMACy}b#KɵoANKT9ͤ&sh`^[UꉹۗXyd.10$6vЮ9l d ?y'8H8ew _8VE3G¯)^t}Oj1=FE' J.H Jv[D! ѵ$y/ƋϵPduΰ k;U[:;g/xYH#oĭ hz4_@ xde[-apQ-\7e`_!y ` *mƳg &Q ƾh !"w#&dTx<`##~:;#7nI&l>p-˯vD;B|X9 =ůmn60~^ :Bɰ#M-U}sz(jURPpdq"/2>'A'|9>'p>zHI:NᒤifAU Mx>o[?mK=)Ūvx;Ce*{l yBnx9tYq$*3gᏇͲ ھ| ,s}~ /?[4NsQ [~t:WL锤ixV`ﱳ/j.AN؍ (aVvHԮM%d ~$>L)3s/zgx,T! Lj?pDh ^J r멥"xԃOdM/:e\´2 iGNaJ !Du'eP'yqқ63ҷWҦf:VeEx6{c `?PUeJԫXs٣SO5O9g̀Tޣ3`]L&׊miY\?wwG>vmrw20ù֬L=MؐC|nJheg֨2z$v=L$# e$z#'70Fs!zAѬ$R`)},l Kֆ@s?z{Z=0/go\W,;Y'o'M<$k?Gg vmDfĻ4t!d*,>|7id`s1k!е (*_d@j9|9,Ck!dZA"Os;' 0rƻ i-kY6<5hbG KBK8$`ےJ;;(]U,ptA~,8B1y&n-9 ~8pYzL})xJ-bԀCN2ǹcTocA/'!-g {# 06Ev3wiYT4iZ vMxU6F.001)Hp\Hh@` =["1xwTeMh};( Kz; 2p|T!_"|94(Y& _irCRDBWW|}pm eq@1>L/9wFնמWGy->LI hZfa~iF?ɮ$|#ibGKewI"= FiPaɑu{3'?a\  $UUK0@Fʷ<1#xZּP`RtX2iN̔L)f]4ܡB5]?WSv1Ϛ;'jg!Hp`X~@'ēlol?ORG&m{̪~xo`ĖPL7hIA8ֲ2DAxlX p ]ln[aJέКfRniV&;tG L)AS4ay#JV\VazPn1ETm. 9tN ,vEݳFgˊ(pIA{7Kw̗b& ZLjdL"^\mbg? կ={6NbSӸOi2'ՍQx T(nQ ;-2 I"nDٮms5\*^Ёc=9 9iqJTv!W삱$R Two逹NDd!psK)LCTmnW!ֿeQ0b})շRSy,b)PlLE}8vrt[T2H5C'蠼CUd'bh;Y+D*]YIl %|xbx+@=h- U3bFπV)=ᅀ_6"Γ![7^u{ERYg$dK(icWB~ޤ7 Gȑ9wQ' vtzQL,g-%ols=*iˣԾDj[:,ܠ2I1)ƥfaEwoS@9%,ַS]PP@ g&n^-qqf<.e}' O@֮djƨ4hFXef ؏qaΞ c-ح8 @L ^q{Pn!Îk+?0ˎ-ޢْ/7EvQ=+"r: ?`㼰ِ"Jl'NFCb6$3nHʻhQSGll?j :ĉd('.4Eq0 {^E(:#W&'K5R7.8 /!xm-&)ιD× $gjΚ;gޖD{!3` Jt_%Rz>ތHULq!`1||y!"bU~<g%B>@EU"UL ?zbi3JSjO `&'@%a`ʏygRk,.& F&e n ҹlEg^\s~F 8SFԨ RF%'?w0;"!8)z^\imu4S(Q%x _ ,}SӅiFP}$K/_} Ɣ/xA|%NnVZCK[+Y8۲*Ās:{#.Ӕ\)Hs r}%V-= a p ,d<j3PǓP:-t`P$1Un]4=PՍZCV˺QW(bx|c(9_V-fٕ&+ރH84Q<#Rp:v샅}t2{fU)% 'f),$ލz3rkX02{Ww ν;X%=;wh)7ӏoDk#xSzFsĊoɚ т}FTl[ <q^n[N\ZO\*"M9Ѹ P/Q<ڔAl}MBBպa5 t\x#-u jV8 @Vjs2AOю'W.Eǃ .x/mOcnߨC@V`UoxTiv~ 7_LrCu{r sވ3{z7^1M0&4x RCNShB9bEXQHOf}1+1N-ٍG?Š /M5@z4t5_6PBr4*rmL~l,,YiKrelWUtD%V,8&;条u.nyƗ,PtZhS{&wʓ)%P)@gv4Z3aM.Fᤅ R ,/pGvlƅ (ZÐUV?iC}ͽx>.N3/z{yM]ɗ:`5A`Vf NT/R4J^l>թp{wp~4?FBB7ƛ0ӫ{TnOkўn,TNhvUX?Jx./11]yl,f'ej2߰r\3== $1[(H%B#{LEZ}'ڔ~^*[= ?B:$|cl_wqڨ P-VԿe4Z$2ª l-V!H7EK\?_=l#Qx~w^ìe2E]&G/m)l0bsM =uU9G>Y Vn[Li$Җ Wy.e#Fw>!׃jMY/{XXoqt_|9=#KNC!:)zu*&5Y[{ZwWϘ]C7uX}]4ޙ#nw/0攇: cyö[<\VMVL 6ǻԡA_mTcTeBqB'1ڿ I@]lo"[V\:c^Aa'VUad3`SE|̈́ҫUH*y8 -ESú[ӃPk014f74*Ј?sH#@ڻ `$ʦŤ ql!͖uIr+qNSvL4^~~j_nRVMp\6[*<,%=?}@_"]ނ<νU41e=ɽ`# VWZZ 80 b;6 çT?J;vqx{\"[%+ԋm3e5|HBB" eyҁ;zj}e(Tl]_*;7 -unާǹ׮^3}oU U]1U=}7˻ѻo} h] `}}d{] {hM[]+vNiDwfl;^NXmY}^w8(_*CԘG}S:iWwש>'WqGcJD _]w m {jzn|{Wv{ؾCt篾}m{aiosU׶[{5끋N^Zo_o%>E=Uf>}ͭMl6C[8NͶ:R tmak'r)KyBw>xɺ&W3ݧUxm"dkjPxǀ& =;룩_F4:U7{ެv.7Tyڊ>Ӥ{f_f=qFJ)J{$ͭntޭwm}{jMkZ7kavĪ o^%R\nƵ>}lz_t @6-lIJuFR#E' 4}^YCC }_\Wιٯl}u;1n3ڇmƘnflS{fF{۽zw^U}a-7H|)T`S8H&Az52 G4jz$M MMm4ѦSiDѦAHԉ"bd=M&Sކ&)QꞧzSO𚞦i=M4 ='$IIHz2Q!dhB@ M4 M4Ʃj42mOSښxhQ" @hLJ?TƑ##M6@hh4d?Ȅ\Z.K 8xhkUQ܊`aU"v"~"ʰGeB% .//;uH:Ұ˙BB$]XPVxv꫼yiV䗖Z}ItchT?%UD"T%RXTJUiCp CHP60qM RB@B, "ЫA(Yb?F;qG0d8M4?tJTedbYbII1D[ Hf(52Qwj[e_ZsmcUTkss;u\?O4guQH$h H[뻻dhnnhɱIb+J(A`0[Qv <滵ښK}'cjˑVؤK]Ibɥ]2[LرPTͶݷ<1˕Jmcm%y\ko1B0q SSA-j->k>~?7gem,羙K@oT9klsheUUeHHyt./wHHzp9@ $@ =wwHsp~n`Iw@w@$>.@A׻|(.t˨6)L.l lv~1^wI:[TA>TcD JLL`4&O?s6?&gVq^Ѯ/tNW)^%N- BՆE&2Þ)e@3+5yv͎d|dW.o#_}~.N%=HJ{1LL M?[c+F4UVjW*bc[2-,ogډMmmV{e71lK2 "¬JJCKH)BIsWݭn RThцQ)dzf0H Klɩ)K_257Uړ"znR) daI2fͺ|iדIbfIfM2WeL{z&Ϋ8]\VD " C"RmoWi&R)@RpTNc N3c8 ! `Ro]k )6-̠dZR*М26%EIQ5\ L$ѼY eڍW՚.Lrk刪7LZ>)^n)KCPGRCRHm d ys:.AO9ri[Wૼ녮|M)nbʼn*VaPSNf& @7#FSD5zsieθz+:""3)il»WBYW#jn;r˻4#UlZtZU*&JИJ߳n3tAc}/YY6&QB1{4*Gd4Ƶj 4TzEQ % [5@-:S`&taSmf(5uX̏r˙G-Tܴp!McRi(*Ef ?%% ABDr.8㷞w{ߎ.sJ__U^DDDj5Fևj@q+M-"jJZ7߮Ϯ\.ؤXbrX !JFH5ɶFJ0(qR+X鯍nnX~ˌח5VYl; Vmn􊩶6}3i D# e7+ 'KF*3K`,1K-}*㊮Z.01BSbT&f#5meQnDce!tX1Q&QWS_dԒ)Z-4%dI55S5Jj6m+reU^\:<'FI!cW\~.5XuPf]nbjHڳfr㍝VY wm\"T4ݍP4sT4јLe+jJ4J`lAqHFU"q50BpMR:z+bH vJNQIUęJʗn"23QDK4 [lus.6:e+]-Ο&{no+Y]+Khisd[CrRS$PŽz5*YCa%pP‹ (YuDe#BeT3RP*cA P"blh"4(}ץeYɆ͕J6"--3Q:l-9YmFYI<2M]Qv66#mӭNi;R1"g ;ٶXbW+dEH7TSQc |4%HVj Cspy#h?î;nJ'9 utϗ˸FI,#6@ XM{4kbBiq-j B! E_z]*mx7{z[ֺKrO59N⢸MVѡmMѲRlv'ɷJ Lx,XZܶ8j\2-3"fvÞ"ʀcCb9 zRtl]jiZi QMN`VZ2 KÆ5p<捯|/R7iLXZFWv(elcW+2)nx0.P6D6- F(\iC }aIoQKHn8FB vB'f0@B :B,im%Վ7fmUڸoC]zjƫ `jVQ4tp77yRsudyiU-Gz e/B(RsS`:k8f9E~8WtÊɣ뎷e5<=dT~㌿3n*<;k 5ڴhlsݖ ^\/㯅W!uTUnONh|>"9t2g"fP7PR C#D$Aٸn!wqH^MMjn>.#P 5#!}":Zp=Npm</keb:[t4+rҫW}x)cN#Н1]mӆ1>-#mTg vW/$tW6z.U+y^m9WcݚiU tmMM6yvpӅic۲C6274f&&E77f;V.O5N9tc>-Ǚ8{Zilǵx;bhL3*X&y] 0 ˗bOb殍UzލpufRrSF+ ӻgmǛ* Rm=zճxȮί5L{]X4yD^Y5KJ>qI;:,B'%I d;[tDU{&>н0`4?oK6(I?mc(|`=ޟ>xzWu!yb& BEͲ)]Wr.Vv kI*]Pd8UR~c5{4ӗ6JTS^QZ}R1 3*bfzBӮ;ZΉK\R[Y:^%(Vhu\樮ђ^>|-4FEr}GT>̐H- P B!BG!! m!Z^p%pݗ>SĮlA@/( B(ڍ"Z,hXūomWKZ\$2D$Ul#0\DF3iۇQT1_ iL>`PSA6n'.!JemLIIu]]v:Lğ=7$(!"(WxrV)X+Ubh]fQ+|m钾7^m='6+sZ j,mhcqB)}x"d*J"! C+LGo!R#&a E.3ߘXɉ3$De h!fX!BQeH! TLCpDDEW$PzPxXUj7brfv!a#x LQ!BC',1 $RBX1HRSX,L$ U_DЉ.gc']uCSP'GNV-sMA$ $s+__w3$稲;p3 Ni A_Y3+Wæ($FC@v;1l[S#Tk'E@RV$I#UH,0t " F eEQ@ozIs 4;pV)S-(bNhIjAGP!JȀ l!D.chX+   2XD,@$!YlexHHf  >Zg-"#SާqU ` 4ƗtG~Gȡ$ s:i;O;KvᶠƄYBHYyN?;5Iu"*Zcdjϳ"/IF5BPߡ|6?Ҿ@TbwsͲ7Rt@Ī YK2 LcOL(dĥ-l&aYdRi[U{1&@1&N069uӒE!̬gX TgU5P1R#|bh2f22‘!3FÒS8A$jS>GE|Z12oK1dl fS/*4}Vt*ZmcHdžDiYE.Ybfn~f8:;D\$'IUP{]tP,5*) "Rh XتѣI"5te2FU$IdqqS\eY ŏ4'<;]}VE(-yqfŚ<K=\Ц}肢 Z3 28W_bHna +ob%p}q)lĪ"}}6/:nTyrm`~iP\%2hڊ~yWM}o`JedžƖSlD8Q 4+{ן-?|z{}!># ׄ7ۙwO-~*[eu<5d\CM%:ʴ9üCpOL>m]:lЧ|kFVnպ}LӠ{\Jrj{]oOSpz]5Z75oLwtgIS Ij9i){۽U:f]fx,Ƹn6<z'̍͹`m[y~~~n52Nt^6+_wSD}9,K6sna_a˵70K&$0BB6EBXGX0rs0p46_)VjmFGX}V=_ީnNo뻮"2=:L'q[lm]\eM A7NY%784u;4|)' h@PمTjLj ̇)+2wv!ڷNn;0M%FB}E .}ƫ[Ғ)T*bbACB@VD!$h_T/oNE lJ`>:$pE#(" `jiфpFݑ&II(bT֬LkFC &

&XRm jNgH JwN& G" ,ˉ];iIՓvU7Ty6v )Xb$dG:QF1c;uy3 nIhHDd!!X";??gQ:ܙku#{$G5@$j AJDMl-`P}pdL. ) H,ȴ(fP B[]h5v8ۻ15hBRM;.\W,E`kVܺQe\&҉AbF9i TF-,Ud50J(( iy PW~\?J)8ח96TS`Jb9&JVճjCɳ5"4{ >[}q~8mbK4&IM]-*H0eRdl\mJ0 K-*Yꔫ&UkD(B쪼 Zh#jj$c$$@vsIZYC!بYJ0Ezn tYLX ;<)G =j-~ /t( 'NO`gSGa|@#>d`iXu02]|4jhև=7wWuv;~xϣGQHS且kga՝%1(HJ 7 `Z𞡧H=o#+PafA{sOOBt} A.dXPt^S{/M{du٣evTQ$+۬?|EڀWZ~bW!RruE96.% ;#nF3A[] C& 'C,UG^voIOLKC>*IeqA=qл!6 HrW읷2 xP\{˦g>3UUP5T-txq|uH_E[֛;}y}u^<:*p O}L~gLQy+m쉯50.^EVr&ñ5<]Rյ ;lPa(*ᤋ0fRӈ'iq$v;z-7sKY{=ouOւ/VW[YAe"2<%\mLgXL`hkL2p+yJJ kx? :HDJ(2 P탶)DOhkeЩ{}P1?ɎD\ Ǵ9x,"{4 6G 9 ;~.~7R@O}1$4*JJ /t&*P #Ji).ީbK#<S0Om^1Io[Jp@iX-0KIs<)#s*'+Щ]ǒc"0Nr, \>s=! J'> Є,I׳v:o<Y2_JϗpRCcY<# =Eԣ h0HV3p#̞Ԃ(M,Z\,jHU&'tי\82.qȤJ왖1[yR3c@}GJ ŢGfcRQkAG]WoiM, #D~;ϼ8Ή0b@bʊuI:HO#quT#HYրȉs]'۲T̈FY%tid!VEˊX\RÞG$]e-~y$`S#S $i5y'n_ iݱY IkHֺQ/\OSJwASʰGW`.Ti%D! wͱ5`\s% i_6`* [RrNRIq*DTAc}vBC:Zkp-k.k_H !a ⨯#H$U0;B}0%ɀB6E3T518T{{WLgQ3$n1L9>Mw$!װBشHtR3)5`H$NSS_g|WZȻќ-і#K1v,459k!*+fN~ pwL!e.Aӣ`)ڸbڠCd9qadc-B҉xzPsSikR9 N(S :$#_H8~^#Z+H E ݬ+KF% C>u෗g;ZQ@dJm͂h*HM>.׍DI8`Ed@FUHς ƖeiJ!\!Ch$HяL')0G̠_76^IJ^pʮ؍޽UT7I$JE&8yF2~[uڔ an" Cؐx"Xr^ᤄwKhVLsq(؉"(*9E,~@w5RMB픆ܢ"68N=){~L3$.3 $V4LH]Ba&CX8UJDٲh[%*j Aɵ V-*hEB!@U _ߞ`~3Ǒ uU k>3nǸrJR%76QZ$v&藧-" sO+K| ؍܈.TR㣗WfV^꯯mx7*!\JTDY.‡EldNRqCձ .+ln!h'!/M[G--Y`C>i:?kz~Jz@+ mӫ''TDDGc@~!^Lbb RSV<# 2,BZyy0 6v:ҙ2DDaZk֑+Hkkr2 Ńsm8n^B}Fz%b*I_9N\ݫDP4 %A\0h%!$Hq(*`nA %M9FcV xAh d+^o;߇B oWq0q4%bfZF"B&WWFTTWC;ӨaxP5kCb i J4eV)|q;OI^X۩Yp Ԁ% I#t pдLJ$ni%g¹6oG[0(y+ni=F6qȉA˶ec]=y{펡3,:ufju}o"ɘs*W?þW[5t=> lB8P.Ñ)"$l=$ΓDvXi_1Hb4U=G#ʜM] "EPOuwU*ЌGL3DhUӧd"@PZLʚN6a  /B( ,am|47M[!HM/9آރry*uviKie@M+$/vʐ{H tf0^ pnGF߉ܺuDs"L+^R,IKhHO`ðHq>&_WG*̵K*"=(-z264UƗq&T*#!#"bF\q˜$::EV *`!m L] eMC#; =hJ1 ^J@t+Z|x,w pI"a`4 -Bk4c]uT9 *jSe}~nu?}Ey%!pYY$v$/2^y4W JPif*(O&7`i/5fP_> 6G@@pkD(b S'ure`˜w6@E.00CI`BϤ9+i}'RP$}#wBHc"Itb΁-ddI p2IHM$F $*AAO[Cxf&I cѯٹGG#3փ-u!4sm 2s'&3+mfYqfƖ C<#tVRp8mClpWnRUZ-#պ(>bUOJ@i\DuFfZH6mj?j1quif0EQXri$%=~/f_)Y'P'} nvJУf Me0b)ll8?Ψ?{Ũ'I0RK%+Wb6ԛW67,%nDDDHcn׭<~'dn7rZD>Yy!.'ŢT>K\ c p1*1Db#b633 FC3\D50\'qD"$ %c@S uڐ"4rZf(CUbM`w#Z?q3͈OY'̾Rplq)H!w+d7gpR!<6wت+Fqc\)R%6tC OP /̀5REqWaQN_"5xe;+/*p 44Z~!f]3Msp6za=n5aC@?SkE)NEP#'X? _V0K XI3d:7UU܁ɖK|"XmXi<0,vE fqJ(GLX8hd V'b a²&jJqP$C'9 8Ȩ7 !>p$4>DX3"Imcp`#%?"eՊՄœP~YJsXT hF%UJZsBI6EFX)&2mK Dc2EIp( L|#emscMEa]xG*Γum~w#]W{Y>ѹW׌S9:~J5]Og(ֽnOKE9qa4ڹp[+HjQZc;-n}:/p8*vXMeGi=r}v) v??ӿޛG?^܉N8MȭYO8'Ho䙨r0ȕȉ6x`yttohP.0fbfdLffffL(Lff$ 332aݪ:1tcv'I;1W]t]uАA9q3<5Sm:HI&$d]tRwvLjb3DEP^ԅdGɽ1lډ0D5+l#ͫa=IdU@g;GLQ0PBFZ@ڍKLUo~ۯP,!EнäpHB JhV` >KA(R% a;n;Ւb%"&'٩w+ w |qf1aIas _2g;ʪ= 2Y]-Ya>ԃ,1$0Y Y%*|R2eP aت픥IIH[3@P"ʓKaKh:}#d~rY9.ٝځ mgܢerhXmdY80d̮|팎W 5Ň`͇C:6$Ň- SR\OnS)^64mbkҴ1iX["ڠجfȥ<%г_AwY0S=!BLT3hJ@ 2B7e5,l␺:L$I9d`%QH.0!GMPcM:#y@M'n/Nz|P=s!9Oґzyu:c0ibi^fA pTgI397O]˾mpj`\;Z bb;'V8? 0WbJD;G -pQCeI6|J~8J6=bć2=KduڂStiP,$(H E,?'/}YIYZ:)1V06lј:T߫N~^^vL nwz=gJHb*OH$δtdۥcmtp7LiPcKMseG:R@|;08v:4Q:B]![˻ly7;։Fϖ=~ٹ5UR_9֞S3&˴xCDxD&йSvf.0ǦsfhH A_@EM*+E BlM-]4Tܫ+1H}j)dD8VhԧIr s!uDd~fz&1 [HOBFή)ˡRSppp~^Z ?x )úM&ȁDdӝ~K˦ uzG3λyǜK [#wnsLŪղZ6L0оcCam%:*l 6[zؾ:Ged0EV MiB+13#C{*FyGwgd'7!VTRa$^՚,]|d=OpH5/12iX@dg=mRķ SBZ*<9!|u|w<%!F&4)? h h4 lŹmƝt΁,dF X|N%H@=3¾w](y XTαSרfzuqWaG\NVRo{52|䊶g"_O4GVS^Ρ%Ά*{%(ҥ\8~o:E|gx؀Mx<%mWU;,(zbpKuuI"lvksCvIKf$4 4 IBE"65-j-{pρ63ITi#di`n&=fCM+3%Bӭzm{LLOAԉiϙ'NIcE5/N V05,D{<[W'vyeгi>lvE)+C$$@t>G_ 3vKR0~`O\,5༺He{czE[(4Fs\&Eeչs|dzHd"b je9{߮+H{01 $h%ܯC 7Nbs "'~$Beeӻ~̍3ä-_  6kZaJ įUd!$xz՜8γs,%MIV,.G&.oUܙ@JKCS%ZKoIs^lۛÖl4xcYJC;agC/")%;g (<%6#uv$0X[a0.a Ux b>ꣀms7FrA4a4iYyG]8dv<%}웹J,EѲr$lA궉ʕG)x ,etuuNǤТ!$2ĚcizևmgR"] F&*C,2ʔ0"(`YvlqS5US8ŗLlF&7N pW-RX+a`F9~aKS\Ũ淺exvj^̔i J3.2Uߴi}#o=Y:G$b MHb]MNʳ<% )d)^N#}zb חYBC ,ܐK(,z W~sr ?`#V)EUi 0Rb_i*ʴJr/^I)$J8mUÆӆ1cjT URV`bF IUJUV;_<&Yq&0)†*QڣҧU&c"( •9p4e:9i )UªbJҫSjڜ66c +JJUwSl*uM)b*b0|b<C'Lb%qJ͘)37 Z.d&,-j݈ Ѐʩ!( d$OUǸٖ"cȍDh6FdDxDG҈ݽ@pA L`biF Aa!rD!WI@q?tHQw!P֝1pQPL .d"`f fE&HiH55LyM(!Q$s͂4 4CB&p3*ʇ(orBo1pàOT'|ҤRfbi]ǝ*z& & z/Ү7DV)M&塊"d^[*F׬кj_+y!!(p ܱv1ecـ!DPB2,iڋe5-YcFFT$FFHU%%i4&HlѴsQc (,*(#'t+FGx_@ :!T !J qD<=ΐO ¯MoPPRUp=vuLo#uo,jJü{9['d)RHՎ ikmBQ/!Mq^'rS:T:ǖf|[flO#IkQvFr.aT ʤA@ЉeMl0I*Ha[(mn3) L0`[ Q=QM+Dd{>ozI T:MD= J@ЈmYDl}{>Ƶ&?1~/*Y1)1`Ҍf.qEE[ɄHcWmltE OQYk><}߮5/0(:v$tϣ 43lEhUqɘaY[ᚉ n=;5HlNdv'{%'U~>nfm,>.UU^(,>i=7ftr~WcQX6QcM**dwՆNźmcrrDmјӍmxR; bXmpҴ}lec{0nЄNl@k-jp@2g`dhAX0)י.Zꫯks"@r#+,P҃UK(mA|w~uKDv;P)+8P8G=SǞ[&C,]1'bm-0m`l0wi3uP)I τܺu`6#%KިBc4u&R y9=.]@Tj .,&;]#Gw+DQ,3AD@^`#NQEW/{NJf;g)QPk9D{dFND{A4ҀQi0v^5&&#qY(J!e#lH(aՐ$Kp­T)߈!PD5%2BoJ-ȂNOHPBl>'#3 =G`;c`'}tݢpgyzf6aFhm{v5 #D`pwx;PB P0ܪ#&HwKMiJ:Oc#ʼn"}A@CUZX7iOcddh(k@-vH\htg#i ΃TŹcw`B[[h]U/SAGaBG`щiMKOaY焐\P>NI4 e @$q%Rkige:֊׿&4(N+Y sd,$םem*\'/$$x$xz~8 44w-9q^!cQ%6}ϵ -Ĥ(ײdy Lhc^['V"_%@[  JUE?̦~T@K3X'b de̅ K.ߍy{ Yeh(g] |\pORt~#hHH!ӷ9΋/?ͻ Al Bc ۬IH,|v>V% % )ay~ǿʿ*6[J[ǼZ}o|>[/w[KDn7})=Lc GI{Ab>8_ PA}K8[E](2,]+ܖc6J!?T;>"$HNibE@F#sOW<^)FF2㸵O_= .]xE.Yra ;o!oFϩ !":BEΛ5Ͷ(Ffb&<Ux%̵[QmsV'8AC`؀M@$WUfzLUt`|x\ /DU"qAN(Hh@ .|L0˛oR_G&i7 gdZ&$ bAb␠T( 4YW(GV/k3Pen!&1gmg`CI1賬;FˠԐoƄX-A|>/D杩:_,CtajRJ"H_ <5 rT0v{3@qSW!AmBDN8I#0Ug6GqG''fE7My!"l/g$lBF{@x:NsN5SDr'Sr><]А6m /4!#3[yiBLI%AFeJT1%pRC!ZQB$ZURq9Z04qU}R4(H4&:`VU#h' h qi*eF@B$gpiYFqF"α"넨g.Ȥ>(w3}\60$+Bbbr{&hu@lmZ"^-sMqAek}!FI~uӣ<2TM;zeG~(ڐ87>÷"0Fd ]`uvD)R'_CGGzT-jG4JO.F,H*mRvxĆ\$UBgZ$ܤ]l;#i ( mhQ=L#Y)>]at# }owWi HВ 24\QatҾώ7=t-Ԑd4cЎ XfN4&@Īqw>d< H[cPTGH( m&h˱$oSjFUZr$de)p(H8%ab[Q1 )ϻ.%@8iy@3퇾 DP!nRu2`(v?TG/\H3hžr.|`)riZJhs4K &ըD@MH V)(.1C~!HH=SsPYِmL̳ Ėl'}CGv0ґJ~V#4ۦް+@յdb,iVbjdx+mnר]zε1#>)rn;&E3]pM%Lr(mYEԕ,%1@Лt#=LQ%;gjL,f+>zk8|f Ũ۾ez}}S\M ?Ont%jBx/t'25WzE!'0aApud5![ K '>B(U{ a$)aVz&99^5wonx<>eVf3R/{/9Ƶߢ굴i'nur2+v?5W[|zJRNvͥu%)˔z]Y9Z7rÏ"8û^ӏ'H9X.S=hD"yzڴ_kt,yܢwʛ0f9%;ެք}_MTNx^RI$UI$K׫{ܒ;{w$%)XKG= $HHY =g= U%T$JRYVHNܺm6ÔʲM9'?!1GTd2 * \F֚Me]XU Qa I,pKS#(_5p *2@ #2B?\Vn_~Q!ĩT@!-vԓ)4)-EJiVXѥ5Z51)d6&) `31][P!98a2p &!i)VttT3: y J{2HK?5$7QPHCPÿcR?BiS t"hP`%_Cㄠ{O-s <`,N' %TSy_SbL$qHp)pXxXZdygg$Gc;05MɄƃfĸS(9 1!$Izc˅u$@ByDvO]$eʡEj nIB6H_!y5<%H8߫0\ GM3ЀGE@,c 6DD@*J K-(-F"$IE_ƿJo?2,?$牀AًE UE"7UzAvV ݊F.X0`SƓsPsW]Օ*Wn[VKFR4B-njЧWn[W%.lRbX N4-7`fDf2ċQKeTQ9ցԸ^Ã5[AT}InZqceee1su6˩ߛFi$\Fvrd-cQtnÇRPtL‚(0  1YX2iZ uع˜˜@q qM. Ƃ}]["-v&423QyiRBRRDSC@AD~O%! @H!pll`%(c?ZO$U"QU\I5K#tY%mUR=['R$>568Bt@M3 Q>_N1CQ'ThR Y0hh>=_oԉΌ2$UJDLd?II@WJȈ_π%_N@IWʭt%;xKji189qҍ&B` ח:';Ubc{lJ6G= ``Wb("^UaTX Uv jগ)t5 xq@==邖$Hu_gk +S\I-O'@/c  4߯ѯ$r02$#f$~|HYp*/$/GƚÔZ4TzGke?k2*426Q23VnFGf 짍fVQ;jVhi9*b)Nl;D/A0( m|ޚwwII'E*y<_wG#BW|oSyʪ 6 f(6"JNSG[mvS{r>ּc#5qfha03ބ<զrѰūi$ȶ(¯pM 1 Ti6 艄Ԯ_VH I37gՍ>*S9bHVbi{:۹/(љwwu>w4u|^,~q܇~jmm橹<^yELm-;iޯ[~^FtM hnwC׎Jnn!&vݝǎ|{kw2Q&mm{8o~퇇t?sۤ8{GX4)DHbCBbp^p!Zy˓}])KX WlAyyD{CȞm|g4{$2' 7OyK#;$.6,JcFOj-_7xVaO_·0!"jSe&STVA U@fX(eT"@G@FcP)fa8IC.3fF5U3m@$fԖ,heCJ8Xb2B4XJ N9V]BW!T- JՕ1M1L-[֦2L-978͵%a2uPU[t-HR/Hh7#IP15 4격joU\uUC0kK H%gavAkퟗ'ZY:ļfɈ\$/2]I T/iOgx!|kymŨ+aBfqlZ"$ PFŋo$ I ,xDThShzd0"M$ FGZ\q%! 䤞,"7eh !"oSUUtг- o\ݔ5G Te#rUvsgstsYdljGTA1Ah_+*&题癡k縩g`x~]V kP+պ$KٜnGsVF% VZQcsPNa &YaVb5ժ?H~AQ~T6B6Q;ϴgd3K2E1K+k׿pύE=7>V$ɒծ~pkXuDDDDatQnNh!~CU qp .Hw c hFyjd, $&SuI?3faT>Z >I'%zrYCr&f⥲-U!K);V*OcٱŒ/+d&DQ(bV&$Y b(V&rd 6QcnήΦCMU[D"RBZdX\V\PD2&Ee P G.k@N r}Kz. Æ&.Y"a"1iMD%BV^Q4]&QtkFtdaa]Q+DDbb%l wj֍ Ѓ;\wrڻ.d8J8J8ilΩF 90q(I 4QJRd`!($HXLilEL/ f(LPFXDF).!&S0F)23Z2LqQ$(Lbb&1E"#b&4x0S'9F!J :z{zyw/"""""Qy|_:DDD'km/'/.]]]wn{^DDD^Oq2U0l1ե ޴(&+)Pkm1/D1`-Fa|5+: ‘=70RW$VXhGvQPy jF3#z6mqV9 jhBSR"4GF!]-Me1ਦ8vA˪}%IrS H+MҔfi, c.YS2P#ԡʔj[> RP=B3O"<'5oKIs5Z-3Dl*|(A(]dzZ|G1rޙlAĿM؁0ˡ6xFkc4D_=atF^A C-2 -nٵl6֣L1awG.ݤURST\P@DܩHyf8e[G;طA1mOPB;0E܅`%(1;J_P$R){;+ ?Qb?ޒTmLSRJR)i61M*cBhG?'i(:߲$Sw(^lB>~~D`n7neH"u넉vz1UY|JU)N&Ui&ء\M3 _TK^ņ+)s2T"׫9o'Szn$iHHlZ H%6v\B$S(msfm^ۀt[kUr/lJ %!@N/_O.Eh# .`$)1E( чH-|?hФUEV+Q\1SAE VJ @IA{_~?gV?YڲiY鮸Zt7,:[`Azm$DImTIX$R1D ~]@(">?>ΏS4>֛l$zޑ)JQ1J*Rb¥) %6a"DD0ܭlc aZ4bV¸VS 6U*b+n1S픧 TjQT~UO\I,N]T~XGܘҥLQ:TIOE1XRbR JTTm1I%M,Īт?c!NVERRt\uX &B#jʢL"U#k&5QT”؁Ш"zQ?].\&@BkR$iAϝV"JX),qڨ2E{i6ShʕR]I))]%#Fq!<{{XZjձb""""#DDDDDDDEVDDDDA""""""""$""""""""e"""""""""""""""""""J""""""""""""DDDDDDQDDDDDDDDDDDDDDDQ"""""""""""""""""""""""""""""""""""""-Uh(a+u{#[nHw熒 $)JzQ$VB),Gjapd|g|e@(X4pq*;ITРTB߽D1'5>!P۳wI$^uсuMs\nI$x;1c!$6`fp@‹Bd6'Ds޼LEDU} hP%';fkv}[ID$Ɔ4"Jz%rk~NU:A(2(V5IM}FC1Wi 1µ[NyfE)n (X@F"FMcSq\ ޴<$y7mE , K~\ʯ,ʯa"!m! LRB`2@)e*V49Cl!'B*(~ȦVV[F鲖hGReڸ85A0$ߤ0ev PFԁ@_gf#3FjLׯN4Ƀ z zL5ac[J-ȳFWMu ۮͰlX&`qh $p^pbKa ڦ )8H6ٲQ+Kbhxocʵ9']4Apx]6S8B,0OGer* XVR2ʴ,i\|e ^҇HSD4=QIlY%ՠl F7,T|22E321EBRhOܞVt6#2]ѠAZ&#xBQ!X'a͝,pliHI>cS}f=a jIvJB (hh!-9'ટ"~k66P%^Ί("=۾)ֿ7ޞgDϐY}lYB\}Qrb&`DG꒡@?uYe/L™dDi akC.6sCj]OJ+U^/_֊vcˀ"V xK6 ,ukfXETPm9v˾nWE֭RtdxM5`ܽ˦ZN̼k(F#prQ?$zɖ}ƿ ٠ABFyp]QM| vf޷[$[ȓkP1 avYk;^Ym,eJC3LH;y\J[m١0p=rnݵo[ B?#)q"KZ##u̱K`X|hǮQoN- 1mjʨbzٛw"t /!| Uq!}kA 杧"('Ϯ`Q$BɓdהI!`qtGm:1{d([֨ٔDi :Q¢O2-A-ChLyF_} ğ />"5Ht|v"s>oZZ x7J.}wD9){/1U1MohmOmbE5ڰjXb>y*nFr(QHWO_h@ml $"* cd]((( .r9yU֮[g+֦\}f=X%촊a־t`3A 0- hGK-prҡ#džXqVTC#(TbK}oW(A"bH`Io4.#0vo& j< 3PtvJ;x&Oaتڂ""`xbH`m'.) cTЖ xCL +bCYCZ]*8.,A#l?,=x0=77TS)ȋ"".EKKF4h6ϰI)$IKȟ\It7u̷ffPҿdl,` 7-H~"f"f"fEY7}(kZu`8BPQpUU@$3&I?,B~Zx˥E ;(JbGUϯRef-6+{?K?4[q'$q>i<#B=LB߿7:?1y7-Ԋϙ'gN&=@E(`C C3=?YrUV\ZfnT8L[BEΐ3?D'3c@중*}nbU$控Cw0rũ&]iVTF:?8ڏV3"I6WF,E\3 Eʹ@ /o\ "rtN}}--W&RD&KBL>t1J(aaaa  9$\8;{\x hz{?<ˉSUEk~C_7*,($aeXl q5[S*@BI) WG?+b|a1+xS[> 1i,ݣSFUvPV͓"V0M,*e6i%t8hIB8z7hKc.&z j&]vBg!AE=hV9 겔[L@} I_}o_ݟ@3Ny;~|-@=WK?MV?'% $O8.0V?}"g3^BoxXYURX0N%whᷟg^G_jyKp(m^^6o@55aNH(8]eU~\kG35RTwU-(bl6X1wyKk޶y.) eS(7(&B@u3y胏΀H%/Yh'iTcvpalR0 ˻.5Gg޸O_1%s+p$aR?D\RU/\' Ah 8߼xeGՆkKߪ#uTQ L)kgNcXy2#tTG厜7ozxsY(0{=x=G :QEk c _;\Ĝ#$D0e;jUm'8",W^{Qf(nn? Ccc[f:$Ծ:@)2RoK0\DS `U6HF"=f޼2^Ŷ=ġf:K%9We`vGEZDn̘vd3X)SX9ս/գ.s )Bǒ JR #:<8&E92 'io4ӈP۪Ő1 s b!]hD? @c ȖʚMDUPX$+0,"  #8!D D2 "HJ ҃J"_~68*d|+ II I|>sXj,u҄7pC: 0%-9sڧs@OAL<&&X8BFX˸XJ7;B$3W0ka+Ik}**fa,]G^Y $=2&Ll@24rtaVu$loY`W.yKSAqS5&ǕP ZvUKY 1LXkǷMDUV7̪lʮ6.߇U&^(Y(i%ǨJKA-4/} ñm 1 1rIHHCZ#OSn4d.S3,4HY8k~;RN!#IȈ(hm"5~vHHHЎ>_{JY)'Pcn9\ 烯8ꃑikY!8[C]O{XHjY ;z)PhDHCS SțZ_: ~|t(dV$7b&,/X{;KoC"h+Xn|H_kmlW$%U._1j_wzI]t3Z304FIMhJv%M>#3EDuv]'j,JR>_CT ʪ|`<ШO~(ǽ7GoFhXnI=T{i֥cowjq/8L&VT &O3$*D0(ٜ,Ę!%J@7ыhvRp F^|:rd H+vs4Pv y|`VQQ67=|E[bj"QB~$# ؉jSEF;T^3P>YsKFQ2>rw~끱0dGOk2#ryc=V\Goe&I4j㣫+ [=/Es:E0Ȍrc'=Π̧NfӐmUS$nr&ޞzSnh ^:<ڍ /h <* Zۡ(CôLd_#=^q3*ʥ=MWA"gFY ! ! =L9忈ܱU'M#  +LU41C@5LɘuB#]ZwtUV3(eT&(u<^{XkfHŒ\Ȱpii9pd.hww:xƻzfE vS-QEuvJ9р3Ta3-Ţͷ?'08ab=^z:7";3)$Tuv\>D1_AN.!Zp!66MJW*&6/tGUSAbC3%{),Lu@Ac{;m,K Ķw ,a%[jC LWCgsN@XElH=̜\ 8r{ 0BU64m.Ԑl:ӉEW}a7:1:$Xc*e2x݌[TeCFL6a'QSGsĜS6\dJ i d{"QorGG vʚvS`MfƑ^bh`7GE(r&Fz~99c|C^2X 4 QaFYf|ӐP73*&*ב}uv6xlTK  K랈-e**tr8"mO5zXVTlV]YCBteWf*4]5/ ~4ܜuI:m,,aS(iCA@ԙ8#VgiX\VFH\ Ȭ(B.IK E(H0M@K0PL Gc`t;J~R<S# E}>y/".A@Z&H;"Q}8S;Ѕ);,(%1D]vBG _67=?8:jQ2FW |S-HPXȲD'OꈟEvA~Ar1QLXcV%&2H[6R۳d2Y'ݷ'umUSSi, &pGꦘ5AIt!$c"(|YsyOwW=0}5G'HRS4>><'r?h$PoE1$G^ʎ5,JаRœh+JK+&d*3Q+Md+Z6HE 2#B@NWV:T` GJ2$hK%,EV61C6b֋o|%HQߍ.64B]+xAi_ƴZ~XUNAsehS n"[E6І؅y=x/g}Po8IeGh#WGGXRą(-HX`uu_jfBYkD+&a@,H$0RD$5cLJڒAZY"U46i5KJIEJږ+b%XQQR2UQY$ԑSDTHwvwX;AKWP׸ٱr"ppW'uUw$# q'Τ$CD&a1Xl??#UQ#r;\A+I(\cRѥeLɖɌư”*]M5[5vii "$aE6S_ox)Um1Mܺ{BKP4hD.S4hKZkIɃb'~!Q{'"xi"*駢 g?yGt'a#HNF-CΑO>d̖{">CĐO M*H (C""ʁ=&Б$KH'|Yf+0մȪV*i)!m0\HmFgqFɦ<F5$Ta$iIMEJY5}Y+)#5(U%fQ# *--)fH5#%z:}C05ЄhM CQ$F :i|e:~3}N7ogkKFTUY'H[ES Ci Q*(1a!IDY`Ybj Hd"FY?wUJ"C>ADDҒcHNKF?{!#t^DI!02C$0 &RY,JA!#4^J[ih1Χ5>1No?A^$nFMՎĊDO_~fffffg{~0AȏiCI < #A$0 ?pOօp/$$@B.e=F(id ZbQL$IN|H_& rz0AG $F#=>P/Ң_k!-o3ݶ{ }!1DC=I:ΉS!'=)$D8pTSf/Î9#oBe~rHJt$) NJl@;f)NM*L++bIic{ݝ#AwUAe.nSmÆd+}]!i\|4a#j!bUVRa1vI:$Z68Q$d"xD|F,H:ۿ!g&Bd!ByC*Ra7L9-C{؋(H8`2(~϶ eDHB> ~~!9nM~j!=ax:QJRL1bĨlhsiXs‡C (>$!yje9w&=B|$,ut&Q>gQ$vGh;?((((h(lA@sDBy(! 4^Ðd@)+&:0ίOBO*$|~ēܩT=엁ac9E6 }awwz8ၮ[>PL@8 f J4J&ICR$Ck } o~ {!>ZUK=cL r| Fر>h4$AV- 3  TX*%Hv HFZjڂ%%Xdhӯ\B48R=-1-cU0[DJIQ %JXmKH㉙BK$b2! #:CrC'j8RHn* t-Ji(+xtzrl@A O*?Ηܿ46+}_\?62p,P27ӆ/{`P*TjZʮMn,پW2V,. wVwB_/ (QsBf*i5䔐HY ]"w>EQUEUUR>S۔a:FO>!{(Ez xaD$: )+*&t])vG 2pJ2;'$3ϞzyJZ/7>&ς| KZWzSz9T:&]`TSӃN4 tAGbT`DZNa$& = j&*$$Y]j )pKJ0tAb< %T &!vXQQ! S&".["7SU0Q3ذV$jBm HRP ?^Ycd%I9i$vQVFGi F6Rd,nᐈRU7%QȈvBErUY*@cAI(3*)*@@T+PsR$$ " !0(4*0@0 :pNVܤV"恨I44&K7=i$dɴ74J$UZAlΛd|~/`C4C*G֤4A#$i a'jhZZYQʪѹ4r͕-i'ʲLKs6N!RptsufP1X:{RdO Nj,Biv5-$o#22 DlWӤir^LA~X`G>dD"@ NN*$0R\WS>J&W|'}o"胷揚xǿZ" mJLOql~/6I`PP L9rNd΢~0U1`~5H\?~KA V;bhQքKߗ0y;<ʖ*#1m(_T40vf$$N};9 :a@R]^IZ6r)fJ qȧ/7~_c?LB$z `}`/iNVg"E**j[LZH.i@nA!xi .cDD,'`%,h +%1$М1ĽŌ#rWyyte+>?);\h%j 씔(e!h<_?=>4d}GcJ ^ۉ[;Z" rpV#M6IGxWmD|U 2WrLVoóIi gQ4rEiՌwy9pvSI[UuO"x᷃ NN]уˣѝ ܺM1' y9mrWgvܺ1A̩]W~+SWnj'q׏&IU* Ы+Ӫegd$y@4Qz!3wncKlFrP1:uhqJWF.FHnJ89PQCop & ‹9)޴b"I Ue-h: O+V4M}UEzߨuIYy++zlu rS{(mtn$=RH1UZSTw-Qs@U CjRdS;k;(:loJpvbF)w6RrʻGNJſ/\Hr(CZ ~ x,Vcl`SNn˽ś4DgM'2]7H8%FM-ePW&6-R%uTz}N`i0mwjqJ54ww94m0閖Su밡w BèJM[b6FI#1VҪ5&I%!%fQҡb r)l-wIb@" )zZPm5 FM-0V[ &3NRUA0qMJ_땺~9Ƃ2wCwL1Ӈ>#+U 4EQV;rNLM2$Ã0;N54,hƖZتԖFRř;Gy(Tt9hnjHxA6sāh6t96QiHv (u֭rҎnQlK"`pt$tCW[b9(Ma{\ViwmnSf6N|$puh^m'35o4'I &܌Ft , 9ڞkVL(a;QWr@S 'p%5(MJ K+ADuag 6b"#> 㰲GyRH2E5& jU;i T$н yi2[)Ub幊B2:@5F5"@ QHa@NJDĹ:Q4%$A$Kh^CЦ$ +3>$(!BGJNy#N,Dd JĵQ,G2mtʥ71N*2l.Z^Ƨ[$FMUV(1f#RBAqWu}}SE{< DN9y #\VYH %U0jO4DI ѩ!&gAH~đOkq"<" 4H>'/z[w EUP✑< v@=!ps>^uJVrD4%Zx$S~`_JB}?Pa O܉"mv%.(Cz-f#Sldmc,q$*%FId?/%ґ Ã)$vtTYJZ_@*.Ա,0!)BI "[ E 8~f#ROp%f٨ {2R?ۤ\;D/5%"VaIrC]BT 0 $0, DT4PzWteQbd吥""`baB ̦d0g"j<MR6TFRH}x,5ꫪMM,&5V*i)hiXUYK+TUhE&Z!qkPHr, 1W"p254@ny";{#WV|kQ̵ JQ|ߟ_%#,, e[Ti2AUWA Ϫ%J( Av]] fF7_7 @Ѓ;A,悃P[%oNNȁlzjiN/DJ`FI7DY)i2s":Bft!qp4 4ka?VUl` IMhE)ĕ$@8 BTxG ohHDH7X:m\H}U{yѤ#vUم@q| QH!*QJ;zM?[9JInϽr5L/8`BE 19Z7]lA0n}SHEt7%emnEv^OBh])I pD !E!$tGY*3c0$@UBUP@T5*$b}hx>0f IZ6ԘI(L,a't{jM{dl*{mmۤw6i6$jpc@61F$G6t XYp&Zf[oն[Z4$  a!-@j XZ "#Z!Ё Jl$%lʂm5B -2 Bj`-2Аc&&iLjI)1) $fa 2HaT%1L ") F#Y!&2e ,mjLRjjZc$ĵiM$2bFb34m4Hٛm3Hm+kHDʹҵ$bY!!fZJjLi lc6HaeFCB"*H}ȰSr"yi'I"$I!D"Q;O||)ֽͷO;h%#zga*> BiR/xzP|a(Kݾl7$9:0 \r?cl6`moLcDW0crpu'E)8̬?TYf'~?>n1c"OR@I@ \.hfJBD ` 5F)*%Y$똡(QěfDF`J톂Yd !>Ϡ<au 2 $(Ib@&YJk%E%Zҳ^ A iRN!S2DPBU`QNe@@QAu9V~U<[&'uvʷ\]&ruSFh*Mw.+2d+i45 k7d0hbT"=#SPGlDwØT4]+#۷vyrA/<<U`Q[# (ҢUGe+y jŠ(<`dƚh:H_ &q]T#OB@V6R;3196 wN͑FewAL֝ްIFHuRpIR1#$<p5Sk8 6Ou931E->.ZeJabTNf9U REʨpX(ZM-!,lNi!:+YCpox97E`*0,^g-41}Ӣ|O4v`=pFvH{?gaZ_v]/1=i#jn%aJuHHMz>N}c$_U] > IRF+QE"„emƝS80!Á>"9?tyfq{0tjTb!MZh^ }D[/鎲)NޔW5e =Why1dLi($fj-""b 'Nc9EVi[l-eMfH-Mk-HmPHolkY9#10p%LPESX\ )w@\ ֳEd )a%XwN 0#>aҽBh1e0YaUTirR|~9m#=\}VM:uXĩIi5 -!Ӫi,_sS{ʹBC/ʠGLk\o hp\SL!\px㮲;t$)ªXL[LQ1ЊJq%n 6&)=Gg"GO7g4E>*:gZ,2p1 ? (nLኴNx̝ܛa= 'srl,ʪ"'G+=AGX17)jڎ$F'ͼ*&肆1à gb,q:bg/9dsZe rL0 ""4 ଌ;ճҤ>ݏzHN`d:'?* ('t+N{F'bi 1/8xs/g54ɢ{^S@A)K) leIːPthEOM*B? )0`1>aV0L'jM`=叒l jR-hmLV[UZ)EUU[TUUUhUTUKaV[O["6;$J7t!7崂ĘVQ8(0ֆa~9^^ S(ʝ֫4qV.|-1H|P@]%Np"\z0pJNQbHi$;D줔+[h6m{PX"zNW pΏs]D-?x֪ESuT&I$I$Z o72⪗#3#y-z}aER^r,P t@p&?!F~ݼI?]ghqN'xʲ?O8otHP*XAA[/{'}?t?~s?W!=HOP $g44*(ҀR" B(+J @P !04R!M7~,@2gSM CČŕ֙ l)TPEԽ Y$6 $ ARQ{ LzȋJUl-]DGrC$ى$f8K!'TgfS RJb#,' IfğdH1'1XUK &6E=Cޠ Od%*XbIbZ|Lomt7=4|F/,AB/ @?4#JlJ :~\fw9*]}y d,CM`.&}V A^ؒ?4ixWdtGt~pE-ņ 8#GQW?dRE43AErD@!eD\>U7Azl]&=pGح4&'TNS7$9 CMx55'%'5 P2FhS%J@u-}]k%HQcFr`C$̢dChRv24s!0a,v]HZĩ%l1h#v97iW%l@ @]qrdp5 @*^XQ5$ܣ!cpD9ڀa`!L!Qȗj嘲hu#eTw16aie(D@:SE{#y3ª̶pVQNgVm ]Qͣ^Apt"y!Hg٩ Ť;ĘmZw0T=UyN O9|oD$J{ =g9Y]m-*& Dv"z4p֓NP,;rT3[dELd6oO@dꦀ:Z2MN5:NTh(R Hķ\>I&j]f&A% jqIKswnkJ*}?TLL\tXm).h?u x><*ZAhu5a&@]i, oM8յL2PT8 \4t0br6Bs0.9R;;N$aBeJ:n-f\1S 3&H89"y>i<Hx69J$#c"*8~> !ȉdDQPadD%,%#Ru#jLb,LBiBуPbI N&CL0QNb)`8 Db$uGg8aXGAM'x?_ )ȁJ`bI)U$ i{_E SUk4"ff&JP9*Х y &QCȞ!'%Li:f&D?ez%\5I+e2ZN02rɺQmo,[j0O+,̾*%O1v>FAvIwR "Īq`2>Mʑ)HbDť F $ƺcDуAaf*B!5^h%$hDXL1@9 (M) ?E#Hd)aIƙ!?, ܇l( $L\UDwG'%LBCe Q TT 0MrEiQjSFZ]VqJ"A!rDCdH"i .O>lH|)otHۇ#aH>2C}<+ؐ1E;W$[lbK$:kN1hŋf)=9(#T.* C[F:JK${| p,y4dO_C0``kUSY&CxcC[J3:|ڔJe*B+i->k R.0FQ$U"A`&T"Ua D`"u9zɱRzg,[JH=t200OZźƟWndKICE*YXYB4`Lm00L 3%qh:@4$Q R3!D,C썛XV4m7AOfwT>n Y-=,kZE mO2$dhK2(xub*&!33phIqpGGH#P<<h-ӊ@\7TfTeB__BM0FϷ}Cw§LGa)sr|G(= {S{'p-zM1 HdMp g\vYjFQm,_O ,iqCpX9IPh(A$PJpqGjJ;% `X! p8S u s1NLqٷ0URDٺ"9Gx:Zq_[N6T)2LL=1C#"%c,+vo }+YJM0 *A+bsazԪ%!^}bB"H_ ,y&΄A?SQ*?$32LgTGGPPB SJ*T(= o&簪J`@!DaUO14eL ]g|G`+)(D ̓ +DVA4zsDP7:Gs r|FpIU$L3 2~7$3 Y!KJ+Cҥ"#D;țJ‚pq&b=j@HY@ XPY6CeG*B"QA%R$x"Gói{k5S 6 "(]!UKR 0Nrel{n(nFc!$CzC9hO&o#JS1ZsHTeDN?4TV̶,қݺCe ̩63 C(`ȿDjDql` %$80Yr3-tAEmy"Tv 2U+hRN%r騩IE=DkN\D}L- HL2=Bb]|p7xK\LfOpȡo"S|PG]$kt<+p&Sn|0P!a"Ue"A$a zGF>JU$>kb)4 %BGg!i)HfI bz [жHDĹ5Teo/=JM**rW'pG(B,CGڤBTh- *˨:.(!Hn@(pHeQMKpˣ[sUY22X,Ӟ?Rzfp )J@1 ɑs4X>FY<rߗSGI?<$ۛ\qU}<57púRg~_333333=PvT _΃chY/'TJ> SH ޢ*hTZQB$0RZL\9v#ae(CdHz IxxU!|$)P2zɳuo6™2*&)`Q s[}Sj <wm)NcN᰻*YUn.F洤L[ }_smVAK(nFfs: zMy W|][)1΂]X Ֆ}~'0 yxf9 VO}>CAGϨ=! L(T~6_@e0k.,9c!3SGP2{%`0hFYW$gE6C(bd|;KA,,nO_>/pOȜŇ A,-һ:sf({zc8xw 'S""*SO~XO-Z[huDR,1/? 8!L 4+',*kxNEkA,)JF#h a+4N i, o.k0t A!X)@ dlɜQg#J%E`;K"\ 2ZH[2Q1UeklW{ wpL2DTY, _ERRZۗ\1}}|Z#RK#DQRcoI4^#c14W&L0 #h7Qv7Sp&TqW$X[;]ۍѠŶ3x[K G VRRP(R124XjmFbd0 œBhQ;6J|O xxag1!px!4=S;8p5a# (BLbV''$܍ 8nmK,bajF 8:!ʯo5XJ2 75$`&ŒISb:08PJI#X qAdpq74umhMôJ {ӄr!/C%dvV,41!fDV"?S8D`(%'5<7eSf4@cüA)P ?aAOA;'FHAu38S39d{'m&&M$,ePZg}ױ*J N Ljf[{o[kθ 1V$$$[.0 faUTU\H>pXOI#C|OhT!P&OgW#}›d?ǽ'l޺Gw!M/hA"KAAL@?!_o 0¹>N%nNM5":'- 6_l,J\nDJU?1A @ iϥò gGjeeYeFB?v}8;_nIeh~DD?tXG>YbDdi&2)E4PPQݶ8tGojLXBIh]uo6Uy {ЄKVH :arhEJco '#8f$h(¦i[z(_sm_xWC 'YC H*#T8FD문DCQ`¦ 0R2jCN5d"ІbD^J}_[*,(APBQc(Kt~D(SzY DGP1TO-?ԈBν$||0'{(R(,ā B,*P7 IH5 0t~}El%Yae$@J#@*1:ɱ5lW jmXI42]`̦w+e\,!F gϯaa7x<^lLb|œʰo\@G^iŃ&4 d[CTÐRJqUٿ'$c$t,J|qaD,Զw{lwKH{1$H t4!]er溸Q!Dy c$GF 2J%H%r`iPq xAy lJ 3V5mҩ"(H/jhp``R!c]2&! !*4 ɖN كlni%!#)"ߊut(q\EGuWXJ ܢ_$-&z^b2vETJ3UP -Um {`oD]Ya:{; 4Gi1D!n cQLB TS ҵMul'Eߗz!@( QuNĪT>OF7"z&&I蜡p>29|m>`NAlڡIdXi#|Nç's~á2]a!8@=z0qY N#vc&ѭKH4LNL'o!(ro1l| i..Tjv1hesƑ11] ~gЧ  l%"Pʉ|~D&I1Ftѭt/F *ȴI(Du &aXRSAک]aIcv$| !ɸhڷh)z%Q2"*kC_/4=MLzjGof6Y&@h#ӎ4Cj NK4y_a`6q'$=gycw1| 0p{ĩ E{sra G2v0>pǩxGiJ`!HA$_ JI$utii6C̫#`>Sel'Sۣ_sL][u"|$q1WOW[]s"6e,SavqtD^L-pN[ƽAX0B|:˞ c/W Ub3&I⹆JGEp"M'Il q(П)1Ko0by b mP$_JH5ՎS#MGˤ-Lh""U iCy'n= ;R|OWJ}?hBzee2YSlqd=eah cNNdoۻ\k]mΪLW USѣEp9+rupvmaU# T4K2YQw69i57u*sEe4l6QmIYI)Mv*&j-^JD+A:4'f⤌Pr3 i4&˧W*\]]2Z(o){@d,8! 3V ,BE+ ,8FPܓ$ҜeL4ڲN,]! :{ fn5U2V҂U`H!a%QbR0 h0\5H[[.b ;fItNm:H9Ċ`WH+ЅIR!WLIV z1^)<I@ҾH> RIkjS;[xy^sAP0@i`ʘ'-* B)617N wsB6vL2"9OWN5"Mk044ֱVJXPj&hJ0$jBH$6G9z8t`U΅Qfųi3Kb/zI'{;*&]-44ؘ5r:J4l@,ڪVeCDX3va 08Ȟ&uU־f쪽CM00Hd@D l*GqUP !cf2| ]8 ) f^;[k6脍 25I H4 ,+ >ؔaHv@1r00\.ZiMnj J M a2@PB (X Q$I2epID4ŸF6bb(bhCtN*WA"Ny;#0 0ekzlY)JPj$xIH;C9##K#q@ d$RGsD$w>VRJ*VO:$Ju b'#SxѵCzP{;!"C)A6Xv\ H5L%U{jFq*JԲUR^HLLUIhc[]k 4la0faVadVRQd!,TZVS*-nYTʥ2OJF`[I^B32qxDH9z~@OꈨjB{)> ̥Sy8GYR2[UId!XR$hԲp!!|,"4K{ٯc,pT0>9H K$lA_M̬#pA)M ߛЏ)SV6D8,,+,Z+3&/;C>:u\\) <<"btx"ӧZȒ MyWmTdƺΚ.2ʚ,>rN yB=FZ/$π]y ZU<6ڳ/JcqȲ2ö ߠ|(W7lG1R`~!_|Y;dRU2H1%&! @A$iDN&0B$d/2D'^>ouȿ$CR/"l$4C>aw`JJJ1}B!T=~'#? [<!H~(Д&.G#R zF)) OS@P"?:Q4,aL(኱&0) K-d 6֎b5ZjI"Ѭ6J$!$ Q!)&I"cX`$FQJXQP#*>SNZ)SFT* ?O`A 8E_e@((-*H B*3  6 ) Tzj}\UnO{qwZpi6i|\˭&`e< fɵugT=T7(BXNw5 0+0:KEH c 'hv01N F-`ꡡ)(_JdEUO $HjDaHA2$I'"=bx@K6 e`Ocs:  UK&ִi3Ro*]ĊmlbM#C$U|>t?N"U4cY4JX0dI(M$D-."neOܦDŽp&ɥ?[3\O؛e>oUk3 R"LjOHw>DP%JBԐNr+Ԫ*3إEM}!l O@ҟ'W<GpKp%- BT'z! Ү8d$ S3'}JrTH JE>Ek@T0q B6<`$FSEUbMvmH `2JJDJDA&,G2agq2*+IgId2&S1qa,KD؆*tw.' "#dS60scFc:s#E8j**IضC9jr zBE#\=*GQ,Yeʺ̔o#'0":!<_I'ܥnӍ4>XyO쨊DK'CU }{}¬{#,Og,u|Ћo?=dH@Sc<;;lDZ }t2|iģ 蝎#m] E$5(0) JMbb[㜶{:A 31u$!+ TEtPhbVEH1 n t23&+?CI$xyԕ5JXխ(j2UIR$?2H:sz%!a!`RBTYGK!EU?w@pB&B AeL$Q&AQJB OTO@Ax%7 KR rXD-D~iY`#u:T uA 'YP?#P}h3|sHKZ5 O9|ןZ["XZPē͇2̌{83." &"'6 &'>#vniDaZ9ˍuמ3,Ҵr]99I6sΎ$dH'I#=Z(.Yad0(ߩXrs$XY@n=SHs'-<#ݴǡ/BYsnBjF ;1AY&SY{vH`pX raLrT='A>.w4W(wnsFێj|wNY9ܑ:>8+AkҭPuu|`9cGoq)&駭{=oZ@oNlʟtSut| 34[Z;]w]6zH7V݆MrO[|Qs̩6y"$}e {kVf3'؟B-z[l:.2KN_vuvtp nTrܮ#e۞yuo'v{:wc*^U zϕ f1ٵ革&M7xl^δfk*nKskg mhۢwN#] 06WꪩwAJTVl wm;{MrU miVޟvA]{Ԭ{pͻ=swlwe.xbzcS1@ֻ{_{[b@m_wu[wU˸]r>;;{|zۻו;m\>V_m7vSݞSd+Of}b7UJREZB[ysiy=b}tuw*O]v2J[jףcgֻw{ӇmvHztq=+_M(B֯^{2ƝPm]=;%#ov6Z޺=h!-Hi,5IG^ހdfn$}{t3Os$Iq@W4}>ڷR7{6/3HO>Жk_lQϛD{q:^y=m)he)_l(t;q>rIͱ}*;i>7/{沇gzbC!^m/2/sV\V-aGk2[j#-$I}GZŖ/lE[4u ZWڷ}j U 6P=}@=¾@Ѡ}';X<]OS3ﻯ< ֟x_ AOCE`m^jՀotwXڽswUW޺G wۚTmc-KZ* %[$̗]m<"w>ڗl?a$ lYtX k ȇj! L~٫+OaթqX]\abG2 o9[L3'8@: +]i &]"c@gX[.6YqٌCfTݓ.```xTP UCM0ER |x a: JGPR f5EL5H(8Ҁ MF5Ū\F!PG^x5ќAA؞8t0š;%E\*86j @bEk7/ãH(+O' ,9WlY%$&fFl<jͨlSl1`?`{Mf&#? Mj Q]3-H+Ry|YGnzpJkVKڂPJQ ャ ;%#3Y(yf-Q \_~룊!3u/#V_]5[SAghsGcч.TJ@?|bf~G1"kbg"L]==wU^o1,g*[χ7OS:Ou-Qm^'%⮷s{YegsQdy`B+CKͯv_H}E*\[xl=fGA]j*H4?ybrkê=]3ureU-EݙT{3rk(g\Ƅןsb% zA" ZX# 0L4&(+n9}2Xci*)4L> Rgo϶MHq*&[HR;xl B&ۡ8p;ى@ /(=>AwmkG[7w&9y׊M/?Ծb|ha@euQk{ מ9)wE4ϡy`Q4_A( ?V+raQ0;qo?Ͽq1W.;g$UNK٘fE>-]0eH̻xђƀA}|&t9}oO-{Ok-ER'KF2AiMY1QQQjR!]}gFv0"Y Dagwa=A^80t3 Ij2}|2uw:K}f Jo)V5sL555[;'C̆(F>HS[ےYD?:5ujE3Mj"+a b26b5$ $fRlu-٭r2K&Ҙyz&Wۖ'CaP؍d0;6047y8GaޏJ;5IfL|gzPi5>gs!Uj- 4`tVRZu#T<_oyyW.qd\л]w]^J$Pr b Jfi_efJYЩF`DeDQ*2F̪2ȜdY^up\숑 ;H$2_i,h weOT V3>$@8gXţ>=yFgW0(^ME_R&<*'[iiVRZc%̢$7"ƛ`KkL 59&c9t63 &kf4UXRbKs%j"^fF}lr#CLmkӕ.ݒi%(OfOJ M a4p2;&חdkM4HZWstq4H QYT0\YfcJ[&6-E2 iV@ 1)G@:n!(;HCAȕR0_gT|Z՘"ԮK hUߦ.&l>}뽘18nT>:ښtUscʈz$ȰjwڨCw QRQw9~m6NmǍ][ !|K*t3U[ N{W8 Σ8S.+-jWEֺ.oeD1nPmMbS"" TO<8ǕtT) ٧YGxw\0IԊYbg_f z=%尜``FҢ=/<_r&-8G+9zio#lN1-b*Ѭx880FTzkFjK]lZ0z ir鉀"c|lj0:xu+^cGigO=û 5tfb* F=(,5\|]nr'RUQ{mW~']xT"}\nm)#ll\s9,ϯs/FP Y#HMV"p6kN.z`,16,0]o_cCo/¤vyy ?YΗʌPN3op2}; M3"=((f݇TVh{mhֺI&7YW*D2;N/Z*Ie(- @qR%Hp`=U8\l1FW~vWDOS#|`Y}/01᳌, iȲB\Ψkqf2x%Pj1AN\|ஆdC .^/ E&3v n?9pc-}|9Q4~<stu 5BC]*{;WUW3uA0%NN'1˸yscd"m÷]jQ aݓOZ#<\rz{shvr45JZi*û,@79uFDI,Sdih\P PcǏ_xN~'Oqg%{p80,͛4x3H`{"ԄO+.f%Xkq:^ۮz'o?xS/LL KAm->L[Uidj{\]UR|}ƈ\Yp /#4|fGj^)}>*BB :x#Uv|F^+Xa&Y21@JِT,͖Sc>3 s:4NxY(AI[9'MƉ7va sWzT{"wOP2oiTW gi 5&B=RhZAQ K$hJפRT15' b1Lع,`G(οYTJAdQ3(?ϟ$O:eWPAh0?ҀivWշQn}ٸ?|r]AXwa{Uu*Џ@| L2a dC8%#s_2`,`y|^l]59S8S˭ymp;^ĐGt9\]U<6r X5jn4D~] UE1qʰ6y>]1a, pA.q4-dt vgMuݠK+ P n֘ 7t_d!};ޯQ/A]?=N^s9dL4+J0zp_W9mf+AaZyxPYW<]Vc3JN3,O?XrG9|G|:%bwY&]?Mbq%p?A1q7gVfY.)2!aDoMN-׷NWk~m/ӯKz8pΫ87y|z917N|7?4lj>9z{㗞_wggu_o<:ߣֻıt<&"<br0J151mf2 Vڏ//7ɾ*;(;Ha27uu`Ӡaa_9 ), Zߨl$do#pj7. T &d]6 '9џΊ;x8(ˆ%,nF}kh|_;s{3e>q8$fO>P]5=geuKMPv` M ӱ Ҁ7vw׺X5+T|62[sL +Ko^o ֐6Yv@b[foCT)녔SA̓JN,HCh_hGB*,isw/wǷV{.G9.oE8 %~2P{ >. }k^v[ 2Ph|0pV$0? G~XC v>}ߛ;俰sܮ -:fAb~ܲ,Ξ>J@22%kr> 뫆mmuuG9E }%'yaȦD;_ 4rR?7}5w@j}'igHb;eďD޵p 0"Л+{ۿ.g|V%2PUlĒbi@mkqZਤeZg\QQ]0~wήϳ!B!wIQA55 fWr^B?7@!")ߝ (H:ГA[2v& C& E\L%!,|0%S# ]$W85U4"$~?;5~UC\Vf7b9H 3~P+J}#<*jeYPgY9跬nTBbZnF|=v2NԌH!׍6=5ר87\ϒ^cPGtMJs{9/ŵx CYܢ)?PTnQDzf Kn%!ka YRr`Ueg=֪0j?xd!mr&%g8$Ba.x0]~jv2[td@Y+(yV !FHOB؅D #*CJ(e@%iÍ`Z^ス=eXO Ig@ebj+j[w@'ϖ"pMAI$91U}R;Je 6)@f6#;ޜb"9!-D|.j;ncw36'v0 LYa HQX nIw/,-1DԪs\pL!98:պp XHqhԞdKPK/zY/2CCJL4#!'0_ !Oׇt! `augw{`9}Ѹ+ .$<'LF4/lU2(zX,RjJz 4TQh@`\%`S*kC4@R @BhEFg˫S5"5 $ T9.j)`dlS,i&jKb6!)5VB0J3e5eS4˅A$y%m C`wH˛- ɘICNlH>LS71V)K"JT=E?.bHz`x׃CCJRPI+ԢiLN!P2$`jDH%TX,IȄ-D|.L&G뺣J l$Q#J@J4PmFؠI) mȫsZ053Iw8lPA!lql^:*ie-ilhljr49QΖP}Pl9oD\%O07]`AUD33J *L+D!$S*Zޥ2ڙZKkLtT^`JKmh/akwqi{N^،qXo˼s!6v:,6e6ibx76Ovϖ&^Uvu1pa}jf{g]O,಺& ;T) H}y>ސ$xߞ2!QO\)#_Cz_ b< ZDB0dBED8F YmmZK2 0cA>#~lְ#M2"6&/Қ?%,W*<Ri߉x>?_ޒM `18jUg}K۾ӥ|wxClr6lVD+f=>6.KdEG*)!Ctui B4Ka)l#uѱaYBd|}Nz 91S7vXH؆oL;7>`Lm &~3!8BiǑ[ ]$m`RN8j?#ʦjЛcNS% ZYmvFDԸ6ө\Hu!`WIBg'l%$Yf7MFn[b3$|+5f(dg5/=蝉վ<5w\֍JbmLiڰ I!qEbK)d%O8B=eY]2kUF$`sh & I,+ 3mdU۲3juiU,RwvtE%@2XB!zkB @8Q9ht>bmR l^/ Caz/Kv{ݖ!ԆCm=cjQNQy6ק~' 輈$ lX%g4BF!#ITϖLjuDECLϋVkE3Dф:8i$M=IO}xV./84l>L65<=; ^C81n4fg$a#J *PsS a[3w>^T4i"ʖi3CDL%fW ) Yj9^|.:C7Q~AZQDjA}G)f֎0 ď<ONjrgu&𘶋ɯ:¼L,Hj i!=QL%w pC[LX?|qqQ@u{j8@#" }d ANi&<#\0?|ugwLٰ'팟IQI!1d tbhB; #W7XQ( v99ρ[IZղy5H o1s+S`FrVd)qӃ*>_*E ZκD{l )簀O4{ͼdO|;O/LN=Iaj"?I EOM'bAzdOH Dp|uNxшU&Dq` IXj Z$ "bV}&Hs}HAV BAPZ/1FJg!\AO㐡g!@`!HYCzzQʐB aZ*5 JW"4U&6FRGo-ںVTI+\u)eK@1ZK VjFA$ SyJG.(C&(%z@q4l10G"kt/Yw=묱Yܧz/$ܘT)w2LYWR&˲lnyퟱ9q (;N"eE ` >&)n5ho=JC_җc5+IH}W 6dXXr 2~n8O9?D䥋nrnңbי_OW6UdxtBȬ6-vW:2|g-eg0bZ% X06͛MɢPofv9c*YDŽ–>lZc`dY1‚I% l.;ΘKWֆ7ygtɖ"u=GļoeٝGu O2h6hDnB +}E؄+⪄qsdL' g% @@t18A{&8V0LJ/'I8Ӕ5,*5ﶹr\Wl*JJ粰 VL@MZO~F'sNT4f`.z`ms} -'A3~(g̏eb$G*+F,d5i%,\T[p@ NQLiل t4 |G@Aòt2ZvU\LZea@Ae,s2 ,Hчz?SíW&B.Ny[K!XO!ʹȽ6"c͍Im߽q>9xom[ڽkky&غ˥MQFIݏrI=uY1fʚ.1'Ͷ&'9q|P{Lم-E_OZfh2.aq/#Ha~p&:\hoGj/~AG2fY"$a|Ag~ ,#Ƈ ;9B.͘UNgy8˒'R= 9BP炐$MY&0/mzZ$9uixBB;ˍ0&B #6Z+pr>L)+Á ."`E)nbH~$Qv7!I1-Y*Nt sX28ڋ.@} ^aKg7qŮ^ag Z%Ǐ0Av|gH|389/WkUnpq?^4#.[q*4>k~PCp_AˉUq,I^&+JwIŠHW0ܝj}? ~ch]ԉFHL9CG,iu {8|sA 8$")&3E&_J-h*+cM;x Rp@8z~)<4Cv]|W*g@(MhJK!JlU2z5!Juʘ2qCaXp#hCVC ݽH {z;}!zrρjui]}lxܼwtO'J_<*  `֒+q9Qd i*:j3ڌn+^}9Vy9B*HF@D~&~n9X,`>c'lDJJ)NV!gbA`}4z3 |ģ9lllKJ́%CDE9:FP6d `"7m9>G>Ubk8m3'8BIP 8fj'gLq,ĩs ‰ ,.$و2rrUv(Jv^yapaӧL=.^ѝC2#*ˎyGE+ZB!:\ZDzJJ-UfeS@#4Vk auXPzE'MDNއn1i3USfsu 0{ߨH,0eA^r0L6y64Ɗj:v*x"~gl)k5A ,GY"4.ڄc򶻆@%*#}`411D ) Yé9"gQJ 3%j:%έ#*2Mh!«ࡦ4\̩B%Gw8%jޱBX8DVV{k~mr|vI lI5Csb3Jl媫j4ckɑ鏳 RTgu5Of1s{o˫˛F0RpϿ&?5QTUQTUQTUQTUQTUQTUQTUQTUQTUQTUQTUQTUQTUQTUQTUQTUQTUQTUQTUQTUQTUQTUQTUQTUQTUQTUQTUQTUQTUQTUQTUQTUQTUQTUQTUQTWw cT2PIoYWSNkZvA؜V!5ŗ;PO <HtwdD,GA0JYi0'((#:Ũ.D*"eT)&Za Hp2GrX'Er5adjk Xvl*jgS߬*lʔ5 *01(DiI6/:zo~k?: U$X KRϫ=@DdR͉¦cL0`.ds&3HS{5fZ0^*NaY 1!X0u(fl{ TMCar,D8t=eGtE󜛮4m"KEPj11 tQ?II.>Fô7.u^p>Dti,t8^A0=U*K D44TO.1*̙#:\)8P1_p*$# ܧl3a(׎)BB#]bdu:uApnk YfHɤ!mPGi*pkВ 炦zش}x @5 V'gAAI}`Ov/W#lJl+Àla32'}ST8XĉϦ4ƍ*MiȬy#c4NFvhEְ1-6*/jq rET Aw顄pi#XlwtRiy;_OS lkGR:缝=U C#UmdiG*& K ~% &HlMCdD=,Q/_<_yUNϛD^sǬ%*]~GK (4JQ+.)vc5 |+C5Ȑdc`CK1ĦYj:vzG  w'EImcpK_1i[,'F> ~xh쭯ֻfDnbeS>}mmr$ KA #'<&Yk41eC-Ž\"ه/}d LyNk[@vnG2_d΢62b̆bYs@Yi:D؆ )t+5XBUHET骿!l +yM-}Qu$4M}:nw:Eb02Fu(XAPF;4PA0ׁӍYLVtD 0IUù7:,N׺:LGA,6`]ĥX(e #B?ew4@e d)DAT03DHnK  D'y5("IH9q3yM8d-hYj8]xgFfcJEbr,e)<aXDHo3 !gAֶƩT+zYTʠCAG g:"Y@O7՜#}CS2TwQס61Atxa[IF"r(")+B hAL}LdhڣH_G]b3k184B&B$:HL  2#Et!ݶ䀺&N1@y߃-S$Gáɗϻ&KAX[=rcP##rXAR\*fLlYʵ 2(RHM"V -mp"@ GE^)0KGPFi; +x*G|8g忖UIRY_"2J8. RSj KGDύPcF"Et5Bbp13,>rE<.boe dB {) X `_cOqIa2dh,gid0DUQE $P"| #D'y| ӧ8jfDA NWV.Ѳs{_அ'&yD4k@pTqn+|/1 "qNiţEwzB0q, `0 }]ah+rЙis8XZWZLzAD/!#KN D&# 4]F yn*O4vhJlN+ \# "+Q [YtrYL!T ͑XRˡZ!&aޣNp\fI`ʐ- ^K(pѻjQ74RV(:(u2a`V$]hAC(r5mA(l' g jH8`#Frp GfuGD s" rn 8ELl%dfs2,(, W<冧L=/$뉑oIyIӨ} :%=UL~| Hc`2$/3L#ae!()=qvn,C@Щ$r:+T E@0׹Bu-TyP pIO˦X~4 %QOo"cz(74Ad@R"< So=s,)<՗Ep_#GrC"BA2Ȧy|%@.|SD=k9{0Jt5tYsRq[N^UjI9| ]J; vh4~+Ǟ!(ŧcB$014B s\SFoCkF1fEb j$((]צ2}{EP6,b,ɥ^a}939qZO89y*)pg& qe5W;'µ) !.]WyqBt&;5hldʔXո mZ-"Z>I!R{bUAe9 ,dZ Hi밷Q V4\UW/zN; Am}u>C\gVQ<_hLB܊:/5H,DPc$ fz'\4D+C&?;\E3 AԐ VJX ubO^q .=fgZKG"؉Ea.!zЊ($1yίX8/騩|XzBтP0RY yа?/(-bm0X2iwAd,NxQ]Aࢠ5&|tar#AK.!&ꧡv.8U:P-jEuRe5͵x fzqU:7X!ZBE X.A]Ϧ;haZ`[H WĽ=pEb& TXf΂GӒ7H;%l_s;EJe^MxŅ"XeMa8$YttDc2.';Ea9HxN&*?ATY6Le-]I:iqM·Ha AL"8!KSu<~ ئbXJUEJDgt)`bN$$fٳ͏ 1K\!@VCUHvVI< cz 1Z4A8Ha {'ϐ*4(,Di¹c{eQ 0W! ބ**4sD{{+9 P$+YuE9  HmDp<#-[jQ{%xL4 jjh: QrX0pI$1 I uC-ƪh&A2i x2"B̎HUi{UX)g($qeQ^D9z&3t̒ ,P8eQ"DnG&)X8FKmy G2~S^b(\TbfcS810j# əzs֕(y"{``Jt^ #{"4hUZ2BIXRLT[v|U6p[bl,fo5pFz1g/i/%R72cQ7!CC7o/b75w2^4Gbd9#wwy?]͂a>Aep3pyj*2;`O<%@`MH_@`E(l]͇!9#GIzu"u7Y{FD<{N,:8k(+GR6$% &@I- ~CB bbbFtmBL(Ox>YH'4m%Y%8Ɇ#ͩm'|b9YwqFeV$KKN@!UuJf1!+3AG(7LE8bCVL1mUYHI ٖWY* -APZǚ3d@y>i+U"LS#J XhtyLj`<4$y.:<6\J1|LPôpl.tnzHbIY+= -mj3 ; Vggh' v\9w'v=]iH9G,/Tvi'h3+"t52+BDJe9"!\5<0x`X}hO4+x#Jd0ȆNmD/QJH#gwſ@rl܇.Ta<"hMz_aQj-m$DQ L|wzb6'q㵘@P~TvG+mwmyh@.|*֕qE}c dgڞ휋vdמLȰHc0*#* 0)Nە5 ;mҩՠ* Ɇ# 8IN;&yf*Hz(f.>)"+,̪6aLs] gzXj iup(9xJ8x!vc  H; ;aqvFH+IXU6"S" L/lfhmb.1@W,Z2 HuKN2P&3 JĪh 2nDHEx3XGD8=m8ͭt)(0/L8P~狷< EU?^aGuu>ݮbYZk{ϴrx/c1x 2£QJ/ R_1tFAr<^n'Qe2/-^vF r8=H}**) F#lh>&IH5WV+5E'9R3.3@9 &+VEp*Hͥ*0 GK-#"-f] 35UWt]? 59Ou ;Ɓo1BbL^Ƶb YIS*H#>XENO8\14.DXib%ꛇ s )!p3i4' m.*Qj6'mzVtdaAՊ28cАS& @؜ %}~.|9(`ٞe2ԋs=JPɎ.8 67vNn+WYRSa#EJIJ0574'̡B 28x@NFErfݘeÊS Tl^V`>Qs!gJ)Rwkm(իTaƇ`?HQ5;%mOj`_dj6҆CP%gσoiIGNգ#U쇻3',ͪғh R #&LHNX\:̉'^:sObT|PY5!fiڐf!NȈ$8#>+G!`t#G 1G8GLW5P! THgp$ ȄTX2DEsfk!.>hJE"ue\IPYT,еO0xIH*bP5hgcP?<0hP& )c *@!D%5 9p#B)ZǪP+XjR`e:\' gkTA  їYPdP!YRz+Ofx*ױz10"w$vH~j~\jP*XэԲ)!az $SC Rn։/ +2q B~!Ayh^m6LR\*A1oc, xݗ=^4lTAO]' -.U1ov={t,"WD`h {{vSrJַyQ+#Zʫ@Daeѓf.׋*.7Ws}Eԋ u YIaaAC`Ȫ'<Y ,pL+o4V@+$ NqS9g&ͼ"E89i= .Hz7nEat|cJtI0F ^Ea(@ڼs6`BQ"eTѱWE(%ɭȼZ~3X8JB-n 9 50e$yW`jR X>΄̈¡O% Ƅ[ iP%X̹<߾|뷟sMXSJ2,`# "IEfܪ,_n Ҩ%Tr"L5bjY Vx22/" iJ&RGVVdp(}顿E- CSθ+M!tqg4咴BwMRުk?b,=%'gLK|KճER.E6^L6~y$2r=}s}A Hb2xY"F%jU12;_d&'ݙ4 ,<79 Yȓ_k ň*$M{1|0;xȂ߹Q?<"| OZDf 1l T"Ibu\UŎ/,{} ߰(0-0]U9)MJ(Fla1$1@ 5"f E'1^Цpjt%N3m/^df3ã 5pcpp{g݉ܯIZdZ7 ,c$ ưj>!\U80{;I;we Ld,W,PllѴCM؎ mm[Qy$CKק|C7#5لТqBY[_00O^##IbZMem )$B8i :FQgƧgă J /P"Cd08$?x'Gsʙ1(Vˊ688Ldᰕ,U{qQug,jNqfǣď WP"#EVd"zs_Sϛf8-@I Hu_Td-Xf6bDB styG)&c"LpWMdl_i&!">c "u 0fqپ[p×s@+L pyHHNna[MeaQj/7cQFxc\slz[ossB*qN|GNVPj Y6knFFV̷-RZYLFsk5ъLEv& >$KRTmDF2jMZ5mMGW (;J҄JXLm6JkUHjh R;;ve~юVK't>50,E+.GPj@a= Zi/G\?,3g[/=^h&]k|Q5 y*ߓr Yt::|˲9!]{Np[ضupK[?OVCxT!cl^ yiӦ$Fa 04Etci^|+Ba#[ tve0nHf+a*Lk3[aT#DX$}}GxQ[滋/e!/"@:"1Eas𚴨-m`ّ{ O_:j?MlaMkI ! z1=_t}y^qt?;|3H^P,Q+xDd,3{㫨*w~=]xe: qZ?^> \lYuΈ{P%4>IJX"%ާ}?7QKL' xsЗHn:w[%fRY(ͦ*𩲋$m[U[546MMi][EidhiSBIPPr&?yjKaDz l6 Uԍ%m-m5jp[Y9Ü8ݷ2u-~jgj쒚Rf3.pi'+'_;Dљy~PL>ȱهW0YF&F #%Ob<5}\Y?pQ³j|1{z*1Gz( |ia}R_w8lGӦ!N`ǫyx5^<9.ț|]ۖN.MTT}-7~h,@t ,G ֳ:y↩&HB4q:T(ɍv mjEU$E*tpH\6tc܍tY^ULBNY EXTBe 똋(f|_9oU=̐|#\c˴v3:tkM:̞zCӆ]`? >Ke58<]qTRrB8M6ś{ ;ĸA*omssIӡ;9FXpGJmz:O~  /2¨) x hUJ)Aq&߰dGv3>!M>i6?q Q.-h$dR>wd&#<]ࢸ f4!mTJn fe 4Y8%k-yݤJ;`tm N %@L6k9 E")r9#QqZ@ 4lo`V4ce3* A]olui\ 3biβUI,: ׀ǂpȺmޓ"wjf7 9M4эOd#c'z;/]^2CaC,R%gOxo~,ݓ#H{$DoLa9MV8˵D#iM`lF?4Cb% co# vH{z#"̶d婁~d9Q;&ȿZ_KPЉJ ߞBXR1{K+o؉:Nb%ƂS-ܱQ 6*GUNCO>-> 'ā4ԕȌ[g]dCVpTEKʌ2!3{ᐯ] AwfJ`a ۻ,d:Vy\ǚ5Or>a^|p~i^56=2cK#NdgW?Wa6LcUy*I'dcvsi~5D`Xt 蹜iR! {"/Ŵ~G v `?XRUJb0 m@Α3a " |hkZLA&`}V Cb 'ɊeX[^t=Y ɿ"d.h~Ka,̚?935*8C耪_!Dx d?ˮx8_̐qerg:Z} LY5B~€HbpFC0uM@F11 ~lJJ,6A nSn\G/%I P`^ucSBqK!, tLR۳FVًN4vWzod uvTc>%!pnh+F L HAQ̍(qFD $m}L<>bGݧq5y[ Z3&NUB"JJu3Ϸwb%"fA=8P n_޻0}&(,v&U}LnΙ&aRso\ !C@tX;d%sˉe) 󕏱5'atYL}ODk/e|\>? |?cտNA|"96+߽(Ҷi*hE9v{vR%4U%pI`/J~͂qDL2Y( MaB'LeSC %ƒd%Jwɭr 5d[K7%7 4N: JdN Km.`0}t dM Kr=" `PJPew!O:h늓o)R^aJS]B@BQEURT~TKccwhrrB#K *.7劇*jUHQTؖϗ jeIи 7/U3O=bQEÇ1*ݼ.'^'`)" D3f+P:é-l顂Nwh^Kxrr$HU-߷5doY$L-k}֜d?;'NrɊ5feDx=k6yUD1}2(`Z3:>N zcWy.EΒWoHgjUlZ`K ua+c; fKK+0$@r  qp@Atb__pb^mKg5:A(c@|EQVF:&@,P5U8 0,vWͧf;%;YPX`Y&f9%0HCw:^X#d*PȐ! ,_N*&q-V&&G' 07+(4&DGBWЦך!-;uMA۾a:QGWgmpXX]l4zI 3Y$30)7vfpg|pϔEmCO&tQյ27h p1tnWiz0n 2Y$i|d˚/U5cmq<(:jtL{67^ӭY-~|  f߬ӬA4r꫘vmS8 wB|J0sE~`(H-Su3Bf,$P5,D[0Oc7oqaٛxV*؆ NvL4; #qoa2>[Uj k`;3ew=X½⸏)Ì }*z@``(P3!Hlcr=a&@zm;jQp9fff(%=-1(p::iD+zSpÏB2dXfH(ƞٶ f+ֹh,29`tťt^Qƨ3zw:O+I ȓΦHk'y%@_Q\6~l&p<s4a_]ƳMRjUsSI3ʽ Rdr{HQ~D͌ZSadQ)ٙ낝̠pj~_YBVvx92ɬD:ob`TsFJ] ʅw!Cr6X2 CD"S}g  mݎZ8*&R<5_3"8`@󡶈o^P@tٸ)7$ C Ad,$H? #LNd *HG{E[TPEAÿ?|`"1Ta ;i p@3*t֑8Jт@AzAI~KVJwr.+Ld_W778]Ggzl*Y$Չ>4>9@}8yԟ)VϮC*h Fؒw%3.>SYÄz9 CaM.ITi"WE8ig~B٩- hm!M, bL`>>^K[iS6,4)S*YdJ!xBkFԩˬ A*䧡 &)s麢cPPC@Ku+k TuP:CnQ34rk8-]N,Iڙ%f`&P˻6o|5$5K&D4M/ޘdq 9 O2ҏ*K#1=1 C@0w5mqjWǒ@ K)Y3[*og¢3!c#jЛVW5 k3( 6Jip>_<Z9,90ACdu`: a`T^1΅j5ؓiplgX&LƶV556;ne63nJPx^&|Z tBo,PvĢZcx-gu blC M!ᬳS9`YST%fF_Dp0"J=h2˅MpƓPJ ߏF2nB=>CZq>t=b3PCL#A,deJ*"{}B´[M3mYy ńǝշxy\BFK$c}F(~N`$ݔld*]@M՝2B>X{bE=g`Ylҏg | ;"HMX XH ӁqVT"GBkJR6(E!0eIiaͶ)MDREewqĪH.. @""ž}?n#֡T0ʵLy`qOYGҟ޶,suy/R.+ɩT)*#+/xvT + K.VB8R#苉s IDH?o@ BcsI޹p0B85;.oL٦Uwu::ɺз#WB9@rh!,yH c>H(Z"!PoUzG \hUbщ`o&m-$"Mvf:= ha (ҋ+f.Y"F8D4~fM~>ߋo lT!Y[vh4!cnHFr5KR"g. _¸|$"X%O B *>kfFh-"vl6F;Sc R>I* g)L'R0t(o)9I5 "ɯdO٣_3aDYE'Mud5x$hT=9VB ~p{/` (*H$L$$K>&dx9o$⳷ =$߇7S$G.0dCf$xFak6b7̳ x’c@rqX@4j.Yil(r7JJcjɪ `@ )u '\4ʼfЍ,K˸?EY؂Gޡ(#C t0`ƉN)6@nTyިqBz](PS8'v=PHA8DɎD9Pfk䐐;GYYm1U?x B?/l -ٴӲxݷ2Y(g[ef4mwJnr'<*#rSM5J&;w4W;y0e`t_>Tޖ㱊}?^Oqc(њ:~SG[]L[seMm~?|UB  Td*όa2Pk~/GD|pɭsa?& 6I[ c tzHP7Pz Q4}Rx339Y mw:Ao^}UQKUUUUvls?-ZEB~yu9 bt:1jc#eUz)!K-uIfŗ[ &-3㢺 h,\)H1+I94FqȞ3a3DYVI܃  0ADAt*=*جAg8ٌO8I : laǨ z3f)XEY*DJoB%"7B-]O>Ohs][rlyiDZu~!n.B}TC;KRjhhAԘTP(ٷ1<:QR8t!gUX#LI'~RD1fLt4A: 9:M=W{o/v@FqgU Ys8TFSpA($2Zg$0(V4jgam~Cf{lmU޳>|;>Y3/ϟ 6|jC'qP2Is"dlB6*T\Ls^g0g2&hyX~]?>ѻgDl(u0$sArڣ< =}b/Ѓ]wIta1{b ѯe&~>~%=  ܔB, 6Fa{_75˄/#>uIδ3s ڱ?;$cD0 I%GGQ.L8!|67G|-U;*ѣEϟEgf4hEEz4YTgYʦ͔S ,(<~3~Q әG(g)PW3asLX% VD}Ϳ$ b:{`HTB#K&KbIa&TV)Qm'Q7g3BE3f5Ujf|nv|gl||g;UFzz<~cnVfאtmx CSXK&{Aæa弖JJ3pCF_HL/jɧdSHuy?!qRC j !t>O$E`~!? h`P1?z|u _K/B̐!Wb,GH|@I&F5S\xU{Kk%UxcAӺgơЖRZzq67 9hYjX`~por\c%1lLR3+B4Y!ݺ~uO_Cjceʡg"Jh(uj٘ Qw!/u&i#rI9#fw5::BTF)a& Q SRדN_i@4,YK C7ѱWmlc #,ÁeC|OGޏFsqʋ) po[0cq0j)OcP8i $j!9.ICY۬8b (d5Ymlw pSjV7wf1U y5d9,jՄ`%\;ø3E% i{ztLEiL+q#$7BFsz{9!%6 {ނ  )\^ʺ5|Q-Gr4zYz='_ u71I?5'בo3)S1~(*DB /|}hqN ewԐ 3@TE;)Z~+=UU]h}|;a;/P(D-ywy> !H|( QZ50V@Ї@Ml44o 6J=$VgC 1œj!euO}?dD_wyٟѨ22нmL/ TLdP Bc"K*A};WkWZGhWaU!br!UI\}XgH^vO?yNQhNE!"ۨoH!IJÃ&+F1Tɗ WF]vqV &f&qJ\P&)8+KD$pO̢YHIbp3YF)aKd0CS1ZR=!o!}=7i)J`!6Ok]nG_ŭeι7+l,"\X!4WFS)P L  1fhƇy9v@*&FMʐކ'wSzlTyS[PdհЮ]N[ y c'=iB)2mۏbl(bduvaspqlRI2SKqtL,[M]TdF r{;. ׮Hkd d@ "9|C\kj xEQ/u~ܻbՌWtNucF(_2ϹH&I$)6{^sgG M2BL+2$Hol`lGHOwĎO &j?~DL܃NqB\"RGvMAb"ȇ!~PR[TE- fGhqe*02 4ăA*lܵ8̆2&,JUB&x/APPN|)2ĨDI*An4ns! 6B`Y`;4~$ߡvLXtء;d(̋A^~E8ʉ*~ny`AyJޤy<뒌*y3 YYG'|GK|aLaY"5ʯ_Q({2XJ1lq@_)Y_,T2fH"m)=]\O\)T CBL5%D,)  v)i|s340ʅ+kW†/"~~paƑBxAMuT;K0`m !1T0#CY(-c,ν[-KώE$ khJߌ:DjꐃnsGC tE1  6ؾ~W 6 6JvLtF İSd! ²w}Zs{Gn=jǃ]ONpⰜY0C2/;qrn:K|>#S8L'OZoo\. $oS0 qNE>Fк\$`8>1u>Pf p^ 94(D43㤝h<}cz|R2va;Da}%,H*ApZE?ڋzNAc@l"Xfԗ:38ߔ~RyIQ!1~z2)}45 'Y):ӧYK4z%s},:lcA٬%jZ5S%l}LJcq%K^EEUWiq5ϧ6A DxkrU828Ӯy`/`n-d)uB3x_DL|$Kȉ27pNMJN0*%p(hmvwvޚ?.gߕ y㎩ m׏pD(()Ldqa9 e6= Gwz?=,"[`7W4_.51xTVTG(@kzg;Q;؏JueVV`NX) @I@aF5ӊ:YGiF)xD>$dArL/`(O/Xlơ'@~lZm7w5!@G^:"(\2 TCM&e*^*W=fSߺi> xmj4_e -4˜岲T3Eej0,UBh4 f>OЀ=$&$%QTAXFPPdPVUB%@D Ca 0ǔ m,"X BZ #$*m*!AI_[MY'v b#:olm$|W߳?r]r}{@KMa-)E6"_1_%,X$i7I,PDɆ? !x:ğ&u[t]#JKT'$rOԃ;ӼѤmKmP}I&V%G`swWs/wG s6h5fpfu?{zଞbԱy M BkZе̨@_m+QҸZH(Y C#!p %!X(`3:c$߸OI[d<ڌ*y|I7`H'p$vK^RV [r-1ScTO4n'{Pٽ8@ w2ʍYxph> ?7$la?Z-}9ޱY[.Zm.n}H_:8?| -NQY[jDI$bq4Y"^́Jphϼ=uyP -w|(Ļ>5θ-ЄHDI٭7[; ۴pUv 46 ok0g%bjTJ>A9m< s2CٻvO_2b&cmM@ !3! 9;KM C捻œ3>c^xȃ|0[y=}޽mTSa m`rk?OmYX00 -:3vYLd4W) PzBz%p8) s2D !ê;D٥ZSS!v!N\ .cΜ[2Mv.'{+ L$i.|ɇq\O~K?}}rٞnJa#UF39 %hpL!jA/ȌoW0(' <1D1@M%߁#1e,w g,\7m"'SA ΰ,J]~GD2ڑ cD&!der^'&JI4c>^tR 9Ȓ<><4@ HzΜ&'&2`^SX2BFo?>]c䏣n÷QE/gy,VXy6Q“ctJbF+E6@TO d ƾ)c AqsۺQUg$I}d ME"PF6,ϬY鎕Ʀ׎q*{7,pՁV!HbĜTLDPus?,Om>Ml^aJY'4DNBI !/Qd$d\A#gf8#L4iPo)Bܢ9e;1iS{ ^@±'~Bl+߰sV mz$%D$Ky {%BD"*IyE%ua_ӛ]RH GaL!*Bb AXp"X^d(z5A>h5ߋO.d>"$J4sӸE'YN4-ϑwjv1Wg*@n(zqP*H]X8lw0q=|6l J N>0 {üv?ǃE3X~Mֈ6*tDN2\MaW|47 iSF#A 0kYh 3D2QH;xH !0 <{{N (g(%B< 8n[%7x$QT~td 54$)hfP~j{GN{X:ʹ&:@Wܐ5 ,b,D&~X,y;P.QB6\,YSĩO̎]%"r) Twd`?@{eNu)M}! P(tثCd%6WB]fɸs<_'Iosq@6/hRqaї1UoDC2$KgtJIJ=t" J&JHR 1?=W?Ky#Hh⻫3D}P * Yx66π W]P3PA߇kE_ox|x>L}˒1>Q~ҜP%  %ogPY{0QV8i:}9!T>dd/COvSE Rl2vCJs)?%I0Ag|lԾM?2 ~ih]-0P:e1dYUr֩x +ɸ<ɀnv^I,:S%R}`ff0"_Ŷ?kpt%Ù݀nA5a|52%dN݇2*p50~Scxoo~܎,hẒW`zQmlDCq͙8Tn.(#mƴs( 4*y<8^>D^hT38/6. B rî:Al'#v6S3T. sD0xClcPȍ8!Viz<篙[%>HL !Qd E%7s(wc"u;>@֊ X/ԳAx)$z)!8spOtUUUUaϊot A'?Ϥ,!,Nne^2iPXl|oNTxpz|ZYV# ƐI8 iebj cr\M }h rNZG$7{-]Dh+Qwj7dȇdȇ{nX= ʒ)ǟCɳmO/r6qZPMG/DŽAKA K0B RqSb++PO<`ȱ@Q bg@Lȷ$4#)HVyJ Ћcy++Xa^I9`%@VA `s~\vo2$q\fp$Ph( x" qS<8%PR'"ݢ.ܔQfI0"0iIsnWiuۛwquݻŻcbY%$lTybCyq|>6){cNb)" dJ7abKPdL |k 利01I?`_d/ OFP ]r{ Gd0ݝz#C E=dPq|"|AC{U"hLBDHBXñLԌc)+ye_iʿ!L[kLU8.HW-9TEB]iLX3Y))%M'pN,Uq64!>g$l=O͐KC$cQ41 *"?#d G60]@C Sb"Vl}E6A_9Hd9 ?|qrLnCǓ3&M$ kW,G<ӣvRf0)0%W̨10ȶ= z>{h2a$ G8ND)l圔 rC~S,0@JECG}3%€ef(8U!:􈞤*K"j!;Qx=x,A8 w|tM&I5$ha*Aa`y"{2?!*y<[NCn.cf-gצhLo2LHB%qE_Q\A?O V!4U=ǗP1NH~zѠI&`6~y˵znj;1 ["RѶJ0 _GN97ZO!@y-+/"UX#KbBT[ ( Y[*nBNie[=-cWwk3wnnd18:iNJVT'Չv NDaDvIu/+]k.fPFe)KJ݀rr(K,ZM!efFcD) JR,<u dܷI"ymLz٢fSrJ2Ր64C@ Z adzp,P;̂慲ڎF6:RnFctQүpdZ(İc1:3!`ٙ$&f60"+`tbp;n-dtEQi 'V]dS!$2˴Vefd-&%ug0*<Ɣ%fRf D$γnqcBVږ!{Mmzx<g( bCԡZ!J RdJ ʊie2қ|ubDH&#L%є8 9n.dJ_>&۩IJaCRJIj˶E%[- R$t0j֓PИy R`BĕTdh;pWv6ȁs P VL3M#TӧKƈfew & "dI 쉩0GLjWRE\2@dbdb8y4 *5.*)Ģ"S6 bi2,eH&I /A9iG" &i|h]Ml (bMt -qI#`F%CC !CDJ[I%Y2(IE5&+*Tcjk5JWuWL0BYvİ,h5*! Z &b2O7 &sw]Z"na;F-AQőKHL 1& KrYhR 2a5l!FեeJ%mcY(ÂlNHr-;nmޗo-ʤwcKe-2$iDJRФ(PE%҆] ˆq9[&KB͉4fl Bҵشr\l Zll3,c B[ `6l[ bпJR2w-Sv:ΡJE)ڕM26hV.I5η]Ջ)K].*ibQ%ҔD0AbJ,$S @lp6ǃ IRA)%Li 4diT푥F+I.WL,^]ԝ.KtDJ"2e(x4l͋QwDL-13DלgddZIu- " PC֠ur%J*#Ӱ'r2f Btܲy:e0P;Z#0 mbE=#~rbL-:$QeI%$eDiH)m!.)a`8UaaaO4p&dWQpd<cM1FC9dDYNDߴ&HLW[~"$,$ 4 rlH!Ȗem~xQEE A]@`!O2%12DPB@ !KL[zhF5,TxBd^ ͱ`)` ?=U2b\Tc6uoL-kuHAj՚L3h[?7_۷=7b-hss'SQ`hU*䱕(YMfd@Ā|2Ȃ`2zX<wǰ_=>W3KU}T Y8]<(gD8)+|P1"G{Jc$DJuKb_.2nxĐe;aiL>~sة sCXlʴ^$Ж( H~&!Pp>HNhacR8,d;XJ ؠt?tty T4e <#̟,MACu e8dF'Gbv}?M\I>0<)tսt#JJdgު4(od#URdoΞɒ0a??JP<5]">?L1d7I6=;'|HLA}hC=(?86W{""؟3?8D xNxNl'窬|˶ Jlli^^'ZC?돛Xv0JB8GT[ ~^?gN v}Sff@tjIU<4_v!E!].dt"Aɸۀ^Q(6##UJ^zɴ#գ]<:5갪T?z0H#JT ~$m7ZQ[/BJF>n8Rۇi,f:H{# %iiYyQt?v2,Sd8G$>>aC'DOc#"pbJ$atvPLd1Idw8>?nĠJRN$lq=P܏/L'!@C̞U"b=&uf[DfRd;}͂ NH]בy =<rdQSt>/7?(z/P82{W_cCē៉V+t-p8 cowk;YIR*[۬Z,O'B0IC'^=;U8/Ng/Q 8IGΨ]#qc(X̊:+Rd~Hˈ̻|x|ӡ'2""d:!FH"&BNc"x4$eyGuR|-<ۢ} OУQ:՘U![G<9*' i9B]p!DDc|s?1rgeI ĆH*$@H?jø0S=1dp|M=!̲!G_ٽFI hde~3*].D+X@.(Ad8PяiIHл/+ipU 0d"/ΨG8AА@LSLT!>'n7"4nip'|maf"tß$6؟!lU @`,Fa -Hݹ<#XYȱ8Ȳ<Ӈ ԲQ~Ohl_D1bsVu'U@@d iHOl^<_W~h# oz_>?NQۑ 4Fk1,{l~'w2|j$Cv3_)!ً >F0!If' ԡ̞> ؑLH>6hGsʍ#!By!'^,\1<#A<&~ pj G&ߎ%b[TqdC;ϐTc]$Rtޙ0yƁ$H Fk''t5(x1][M /3hw_ Bԣ$T?yisXWB l ~ $PRz MRTm$z ׵N\:sQ{0H?UʐK)ggh!P˱6٨ڏO JbrmdBd s޾' !Reu+5!>?OH#+#0 bJ=v%}"hʕalU_E*5ܙ>dGi6'~F[#\dba}ffYrңim-Xj(Eߓ݇ԘZĦZn줰z#H; 㐼S>HM$ 1;2;>PI;ABo&E; 1L7Ez:~>bS %[tDSt\ِKbfEB?XøEa=dOwcnvmB*~`~=X^܃EAUԕ%&Ko8:$)=0>.A?;S 0?;kfn+DAK{!2 )D`š0tta X ]*~yWLJy hSD 2zNwxa۹|H k)o#1xti BP;jIH>Q@i]p0e0-I[HǴw͒Ⱥ">f-a*J_Mluy ~ױ"A>%:8TEO)#ͳaeƛ׎yyIdwz>dHn^pNq !) Ru! q2$<C 0p%>S$4mԬ9$웣RhOJ}n(L6$2#Kx0/\BG̚~_׵$7ܰ3u{!P/xH0A¡AR'"#O0R:C  dl]>U(DhO鍏ׂud $ʹp<>KQ|hzFީU0\bж05bUR喡͞JJ„I͔cg xZ25'q# D|N/<V]Y@ 4"YId, d&4#rKh, i?18Ypℯ#jJz"j! 5*,IP5j*3lJ87-g.rk8uŹuŹuŹu$N2 Y Y f@fNIY f@d f@ׄN nZ Y89mkk ^'7-y"qrׄN2Qܵ@d f@d f@d fd= drSv=bHHҟ4r4]![phK jDaP~*d!H DA!"hOmАBJ5KŃ!o"|`=HK1f0ӣwU)Gꈻv.tt XUgއyB0/ywB!9F=`_GsłK`'4B7?s!}ABhy8<46oߓdReR;~OTWL1Lqn~?"{^MO5J<.yakd q)~LfgzTYi~&D8 |(#QXDJD|I@/2^AFbxO؛o{PDwƐqI௸~|$D>cr6y&ͷYW.FN9okߎ?7<αFG9%FpO|; ĩy *!u`qF#%yO3CQo$8d4}-q2ԇx9#_wO9_[#K>>;?$SYJc$dOXO"! HO*2* r T~pL?ڢِ"YSEq2Io$"'qD*!b!knP>KJy-RW~S%+|5d[G2LL$>rK>{; 0x;!%T@5釩Mt!\R V&J7Оq6ֶ5[DFI۵`tߩW-%UU@` K|^F୶&y)X}fM1JR%(P=*J?cÛBy/s>\cS}Ƶߩ?G!,=}RN ~Zxg c>Mȅ- :20H4wlHX¡X53yO!~wjV E@{Zإ<uA/>ff=j6mZ:яhG*^i7z^Gʖ+C3.\<^b{)/ 0Uכ/o^`o9\T#~^Ф0*>)bLLə>A`_K Z 8B H/K?|܀MU},8O.yϐ!?vA>֗z<x-PDw}I4ʏ#\M?8::23_ÙidQɞkRH&P2.:Pa_T;\Ew-#ާkNhar~#/fcK<„Z"14C>;h:WB~Utye6zToQȅ``xCo~==lY02 x5$ G` i3^qPٴ xMb@nNp@źm`l|/|~r 0d޾N>~4">o?CVּ/יNffe? |W *Ց4rP:юBUw Z|<~C3ahxz9IEeH$'\spն/mpxs^440t;[yRdB/q!w&9h"3{6OZx54EW{l|I[mB8=sKr 5!["[ťҍI5 \Mm$h8ҨiaZ.@tA9V XBQZEp ٶr n*yqWq%1 04N(Ki:#$J& awg\$lC-QO0#:>ary(VɁϹ1|x3ndR+wg>8X_ڻ46T%Ph S)Q(JGbmZq rCRs~ֆJ[eKHΔTIc?R>I)uֻq۽vEvXɎs!$ԕvve2sv]R!2")teo ^r%)G`& sdqɆre5 ]Y-m*TS1Ol0[nk k#mj5gSxt۫Da.uaJ;4##%D HbmT9 !jkur8Ero|$wIݻ|c1Aۓo1ؽkjH^*R"<ҕO=xuU\ eXƝ jDبiz FÑ9ǻrC! lG {&Fѳ ɤ@}7^46 &f&fga,ҒlPնAZVjUŞuz/MK"|Gį\8'))4; ݬ6qwHr4){WZ$8pR :*JxYY 3l,&e Fq_ F K3Sm4$"9+rMˇ艈h4!eħ>K硅`*Q@ -=8(y'A?*unD} B92Ȃ h5RI'?8mF' vL &M9 2Q)JCb :D i)-BҰ%)pyDK9iU""qvzzFn Bde  V!PIq v _ ~Q#@@!A{9)8Ш$:T8mKvaY)4DDAC>xN׸g.֋ȑcv .i Pm%u+PP5bN0eAӌMxED&hu!_490 "Kڟ"$Z]( FR!L"_#4,IRl %JQаM9(D BC&HF'W6q>zޑX ʨq V?}2!8ؐԪ0$& ašNt0T*y|)b̄>^I+,(viS@A<}8w7`Ώ84d 'pY>AVEQbCKhhguB(mpƢax%i&F%U&EHCCǜ8SrRǹ ƿ;:b2DxTL?{V饚b4IQ0;M|^R% i%  .(7`"AJ tdNi2 *Db@TIY"ŰX0+"PcHP ےܸT8ˆ(P%‰H PR]#Ip JIZTfkjʜ#C`fG;x0iPԁ ʤ'=Hh4<<|^YT}T&D.1wp>sw;= dULU)4V]T HP!LP!TĘ&F!T₞t= ѳ+NK*-J aāDU>GTCfd2=ı}Z$Q)F44$b}z2Э,I!D0h W26atB H!) Ta{ lîj/T*f=qHqO)$X"4BHaԨĕ;I>ǎkxԞ.$, dy$)S!:uSI7D}~c4xH!bgC&iF"RX=ڑULLܙ1Iz%*I KՅ 뱃 BŒl,(% ;Q&ؕV3Af* fdӲ$ ^WmLC$&y1]6޲73DlӇK;"NYJm$|"Ӳ$( R*B(%!~bSs#̞U'[#$pC•Ȥ _תΡ" X1bYc2HQ4 c %!GȀKA.b,?Zgf$[%VyH> $9qVÒGoiZX}l€f2LE%6H<&ȕ󲸧[uy]YD`S&qYn$[T!:Y&0mȔBѐ`iD&Jɫ%^f6CɟIp+ۣpmmfSRVnj~6iIKaL6[|]Eƒ_1% E u(;3ǣR`xF3}AI3=[_8Rh00dZD6 {5WC:܁I BK?z2\2OR6Fo3qCڟ2@)I24, BL B߄hTٔ!Bf$ l"@/$%}+KBDDs!\4r̥r5:1L|",,SuwFƍyPX 4Ò!J3 `mQ1,IY&mdusi]mjIMb%eW$D-b%XX21f2II9 d>`AMHgIC+0"p(D_j+/t!%B! )'(I:jL0C,xy1BzcٍrDx'e& mט"X!PX!$h0 94QIXviۡDt11Mx)ÈuyO"۹p!#i4$2I#7#Q5Q1d2%! k/x#]kWڟwiP牁a5s " e̜p|ƒ}H'PD Q)kljm~SPH>3* \|E*F>. G+dW%(BɉaS*|߿ ~(>'0PqiZk#X#1_*쒤;0.B# oS/ >^U$':77|obV Yӹ4|&juwxJ> ־E*ҡ|֓g>#C+}_ qU73Wwwwwwwwwwwwv;Wuwwwwww| =( `L *H=$qRI=J<>$:Y!$|wa xi=V|9U,90+ 9!.]a$fZU֛,ԼQUL&A=D- 1*Ҕ'z.3,jQA0i0! $ Xl9`8`'\;i,T^Szw䵇QZT2R_Ziu~S; ='p8lX,Y=҇GLq#Ɖ|+">1 'y$*`zD͠x @]f(ưjު #g.]dQ 3}JJ0GP98]!I6TxFXJj_kDw?`8/< &#, U0Q{sJt p܂]N.FD*AZct@m̮D>?n@! ) kK@XCBH%1J\S_&" IGudC=8" (XpML_pv|p{!ez@zoq$aV&SKC/b|S$} Vág%$!hlli IhKb0ɉcduֆf@Y@. JYil!QYvӑX's Ѻ\Đ Ǝ8fjFk5TW3 $989}E˜S.PNr;a2fnvA:$  :$,4 H8O<#FҲEPOq}`IJ@_wNOj'&I3G I=R<{D=O;{M%^jllT]\͝*M+ euq(\`RaMLkl) !HU#(2E!RUaBJYRBQ%KT%̘1M\R$^1+0-x,8# J*LYI $C$vlݾJaރDqW015;Xhb>y}DG@CN@p&٨Tѧ6`YKldrCW37opp@d __9j$ LB\&J)2fc& V̒d#h^i@#e} c] ‰Z20͇ed֝nJ6=bfb,H #*L_:ܤʋTʇ OW~"!R@:F/a|{eGO=5gYDhc{pIIM!@Xm!)W,NM|4cX9I Nxp44d#FWQ DV ^ A.Gy!R'Bxڪ tP֩g}IE$2DFC1y!%( v),s0^mىxFi͔*,Wjdʱ=Cdm{T%)Jj)0gO  M&[WrmQdCݐ(!]U]ԍQ:bMmRΓ[l1xqL3ppz}F#-k7FTImLzm5HYSĵ2N%2@Zm bymDDUQN$!)Zš^% (%΃Ϊ:(0%G Bh'gUSL``cS3+AB$,Qɦ>̉$cؒG >?TOrI:#)G r@`"!NS$ $ 1eL%B@d$6eb-כ2Kպٜ 1 Cr'&`K#i{"9ǃ+ĝ1R*wf2d57FI@e}ҟ bJA X)\[jQ=gћ䄌5d2˜%Ӓ!0Eo4=rpdyP7)BAl]$J :CIRD҇Q DJ]0*e挑 Jk)4g犍ӕtjl'G 5]Dc,Ȇ ix3 փ hYn#cfd-(EEbƖ  v KZrSP8B`dIxhL0XsD[ɭkR4)SD”Bq,-/-ԻkDIRF!MLNba;3QZLmٕ*enF,A֞DJ6#!oCB;aT`Q JBTslH#!7PaYdXt Q9̘_5il{]i "i\Zд|4K@m!w06š r18n M2u*ʺ24a& 5߃"ZU3[$M8bZR*X7$$Ueps@ LfkpR`F!"[N4J 2D2<2U4ųf(PA.E8LHH1Q%hm vvX6ă @!F9p+bO"V!!z4p4#.<FvSx2~oAFY c.ךE&IiJuH& mTlj} ,mDe4V\!WYbQhH))JPA[C$$/{%~C6ǰ**#)J%,/q=@,|18~+D'\uC}'UfY9!}3O49 !I$ }ř&K&#OR Ug["D (Iu*J +Ho5"= {$~#dARtv;.6Mjy#+&yZ{1>X9" ( 'dJ (st㤙qf95l$Q4ht!Tk$0jI3`74iО*[WNKUhg :;'C jR İW; Pn71?uș׆桳MPfRa4Jg B*( g<l DjeA(E?)b#A(5x}<41RLUԍ%BAE;t#i? :EgDQ8pG8ޱz CFG.]r6\pk]YN5.J+’fScgl΅4wIk=e#b^*P.(GZuא7-dN<O&mb6Z5Tf9~\T뇖AFƟfD'-^f [dWb9o- xkEc6u(-F-dЮ9UTPY[2V$p%P& {gSNݹ=110&pPD[@uŤBr $PfQ4 H&ՏC8X.O㱘;hIX0{.| ѠEsũ9w1"&Rĸ`rmsdNY$l^[Z6 0#UU]R7DEsG Lּgx؃2S~}($a g ž Q#CfѸV3)"̚iPrI9mAx8஄GWO\+;/"DU1clG ~Y8'Unep-b4o\#fZڄ9A*%Y< T ( "߁b:"Xej)VbR(0b'uüiJA"]ǔy0 FF9`ϥ6D WE„"GSb6d = 6 ax73 &?I-=Pmȼv$u1t߇G|76#ؠ$H:\LI Sk'= z*\]Tں娈FAGu bU(.Lҧ%Xjwug>I-1aq{#/' N>eO):1ڌr,]br p*JF$<;(:''tKFPt{؄AF]Yғgp ,H5z)sF, bg=#saQY (9:92uFu߸@y <#3˼{*E>;}y!wtS,i̽* R*P*( OA Bg⼃PMěYɃ ʕ5لc8[25g4&ˁ]hTAl4RA܀]Mԯ_+z+iL |X}Vs,Oc 1nu7aȊ8jyEc(oD?$'D+: tKJ%@n#BBb62t+`1IrY#-$ydflْ#4"kAx95e.6C[ y4Qd.Jkd3J@#rKm ^ g]?=ox!.9 ,1]W<2BBb1%Dҡ\HżŎTsTâEI*>(ѯvSJ EU!ʼn*?Cf}אQ*ġ]l/ _r*"[2B:6%}['=̏gM/ άoZ X4J{jC)y,kٓ"F٥GQ ؗA3%wrc+mz[Ά^5 ŒL^ldD!0AHȢU.e6za(}J&K5mSlRy d( Li-6b! D ꬢdPp5Lf#;+Lpz?!LWXpއ%xSԝ|ܨ bK|oJAtIPOFBL8K.@h0r`/fg|dW"+1y20[&831$ GX,&tV*lL<1%/KGBX[·+APqOX}qBZ1@EɹK9e3dL01A)p$$7+(fƬՈi @FrLHZk =0ig&KG}1,O(<s 8XVb5ٞh 6_d]nR#f ADjj٪ a3XMa$ P]XU$c6HdZPGE8;Bߛh~=\^))(f*|p2{q ΢6cc=l uZ:yP; @{ e;.F0S)" O0 xbH " Uw P*/ddxM6I dтV䬑YReSEŐN0}t8TJⴛ\7f WR (Qb$:J=Y^5 l1F\]i\%:=އ1'v&2Ay$sq 0,"/!Ҍ@L#bzs4d ?hTP'og(^bwbIVC\p,Aja>-?!}&x[cCBCRj 2Q%h  5bJYR8hCFK 4UA9>& zsִXZ%`rCDlNQaÕO& KZ%TčdpEV&P¶yΡ 8{#c,ѥƌ? dX+&ncA]QX Jѡ1@}";Oҍj\O$lt4R䂢HH LB V[^YIeNqɼ `1#[fN烡kAw`"Bg' ]8.qE ]2p! Ē] [*ʎNKFL +t9k,#G5Y7rjH#1*Y|2c&BrZ(F fթ4Y->,&`1DiBW1m,Ō}Q)0iPrp*붳V I"d cH($j ZAR0؊m(XEfMن* z<H#.Ptt&66Iq\, ɴHK%*$#JRht1{Fm $6Me!"c VOf,")LK5V5 &iޛu:# "$y91*i$H6Ia;5 $G [RWcEX&hI&5&ⱺ{=D{ݶf>^)Cppl.l~bAae0iYD!6,m889>!H*!% R1P#s^nN2 P*$V-LV@`(6ܾ $&K3d:Մ+|UL)WczhAk`rvBs,$M-a`8#71!Fɛ4U]ej*|YZP@(jy2)XDwfh\vJt~A>;Y2BCW {9[/9DzL"ᙅB6#GKKc;qe "x/%5 w] Okr#}v cUBeqfHٽF<\LX .,юddJh( "~ ,UidpgԛTx䠠w2U2ҤHM#,a ,@(հ$|z:! $14&HH\uA ^ 0XIQ% HYIhA$EY IB(TB(ddJ `V V%VH@@TZUZD, ! Y`&CFNoMsÒ'yu,>.5VJAQbMj*Ѣvoڟ { qq#B#KhdibkU/$pRHb†A `'$5h*R'Jad-ҒbҊ@5b)HmheC1I#iIXf3Vb)&dikPS,TD $(Wq3ILmc"#$Fқ)K!Je& Zme%ȆBj٪eu$*Uնh$$6J(BfH)d$m- RI&bF[kjT&@AD43:qysEB&*&78lo)qYZ$=c8&G 6ā|Lem7P[$Cs7/T|'zLO͐ #p0 id AjK:*HT2JU$ZZ.f21֎䆢VFD(~n{'ú"$=r(?`0L(}p`Ȭ\j-ܿ&6qSXXI" L ljy",:7Ve*6p%MoqulduNDLK' NQ QDB% mub׈ ,@*eHZFʾ'Rw\bQG#y=;v b !PM6زy؎;.,xc Yu!Ǭ8]{@Ә@GtAШrC )}7,( DlDa bb4yr&CqwDnÊMeCKtBxR$U(Qd+sne#@*m)  a$iT?$5E,I˦&VD~a35݉Oe[i1, hkER;QyNPRH?NO3#FcC^r.GI=g'5$m?Jv0ǠoPRy& Qm$ 4OlI6y"n|"=Ǘcn[[WBht$f0OF lBkVm*TRRf Ŝ֛-TfaH|zOYeDY+ 5hjPUOtuOm$U7zv$ X<ȄT;?Nwa%~ t;t,T«fi`0.3$ 0P-lOU7sUa4~j Aʛ$0}*$pXFC.!J;S~1cȒE)%1a0JYF>Jt!RC &$0q U`zyh)ONI ~W" ^%)J6;^>)Dwڕ=9Jb=F=]MnT8ʑy~V$ZHbɾՄU2gKI3O{GΉf d.C0m874<R2s;13cL$ |p% i"H=jjaBd+CD[wb^ dF 8JC,mX($=1lqujD pfѴ&SQfHbSv챤5 N U5.Bj`"@MJ`@.rLGmBjՄZ791HAŋ(eD % P"T%@FbU c1E4A*Dxټ˂4xs$NRe2`+?4 :rZca:)Â<*g(D&$MpW\drߵۑY w[_>'=~YQм'*! f:%y*z`hCQ#O9m&F#F?E_]B (aQy/96y>UǼ(odnJݟ=-?Sb=MokJ!vd$ 9i"bF"EӃSu}xSGI*cDU-UZUYCK7>$`~uLVSܕ2 sȈTIf'8R{|s$=$ 8Dw/{7}?_?՟w????_~~?'{/٣~_ɁЃCsT7 *!H퍟kX$qTLˮ**qH1DUGڜ8jR\)<83k6sc 1MdHiH0P-o\zi[v9 Ա)h)6l=rg0$弴E`Z1VaETޖKp冬FHfA0v^%9@i!Pewa T$xs=܏b9ɋ@̣]M{STLV`1# La./qX.8#%ERF!J DB[@;jU=Tz+ݬ{zMĘ b$Ziy)U&ses;,Dǰhe6Z%4g};PۅP !ps*o Q-dZjY>>CEngy/-e6n7&0!@."`,͸nK*,APpiE&L:O"+I% E-*'"~rRw=vgw#ֲ9&yf9 "ĄeG}^!\ls&T| p^ ,ҜKG+ EވQVǕLqFONk=<0U1!o*%&3"Ř$)-9΃9}]ۇaӒMRT ,2}R| d ΰ9NI "T(3ӊ>ލ7(Hf0>Lay~mɉ=vUHa 4\URwIuG'C6|i (w'OJ )#W!IjZPBdJ)xMbVR3)[irrA!UBHb !1W GM1 LbHV"I)^^hdK$SQJHs ځ8A PI^1PdGdxŒ:?q)?'1QHȜbIb%|-$dGߜB9{=< `}#Ņ5}L`$53R!=rI))$!KݐOCtQ*t&.Xcvl(n/4OP(Lly aoNad=)4 ^Z'Cңl¯IG~g|V>y>cg0Z fXb@DNW=[BGQ,lAEIiܝM!S9 ?U}OggD&L`l옛lmDlllLKE _3.UdiÁ[.Qrs  Z+JQ$ Fw)b J:p1$'ßxIx|'i <y>w*SDS8=a)Sd6(xaF2I3EŢs lC@vٔ #ȣR/Da<)\YAѡ=5RNO;fZмDTD. h$F@a!F`ӲxjF) ѼƊeqG X2khhMH I,UV !?5m^3a]+;U)EK4WPS΂4"%Bc%" :I8Iml<pCѷ2Ȟ1'`ī " ЉwبsˠpuӰ٠zu |C3`<~fm~#w4 mDIfQ3 &?H۔$&]9934=g>8 'G ӫ \/pGNJj1g3cyJ$G:pӪ1JĆG=gB-RPف&,,΃¾SCGIjUZ~bKmMSZlƕIPQZR͔6ZƙI#Ch[t5-HXMg7WWU̬MkRmc55"00CY\)00 )XF͢ZZRkI[r2}1dRa(88/NO ҝj'HU#!En!qN*/oDNv?YD:{g!D &P(W&F %$"R@bijf4,000LKdfIU"Y"R I{*272R]+H#G#fSO쩁d5d.Hp!2 FtGkC{^i=|;hn vF dvdynir]tG8QiTvs}!.aC'3 N!$yv8r39"hE <19xLp"ysq_(+."d,$_-KJRɋLsLwZt U-Z(M8Dq_DiAQi;OQYSiJuI#nh'F#!dpI=RCԠ1\W4e,fdo BJP@0fؔp!M"UaH 0N =pB JTJGbGaduR]b$@ 4Ў7g\Ayl_Q>P\C:Urt$'Ayi7sx; H` %)bv0z#cAX% Cj+?#O;]I"?!Ú7K2*A 5`|=2'EJKF+-.q jCM\% Q>D '_Wu: Edd^pTŕku~IhڍviRDM$J%$"#rpx!U*IRvy'Jk5b/OĒA u.]wH0|>^b(jEkU/NfCzO?oaY(%HYU'Ow&,4A,$&3!dfd5U\y;=Q8+RP#- @,̤}PI ː͓nT$ɉe 01 ͖FlM)Y*YQRqfs"r&qI6]1&Q5qf0!LȔܔO!OxJj2xI8s2'Zp:\ Ip 5.ŁbU 0D)RTZ QTHup-6v521P!T"-,AN΃)3~O aU F$ujn,i 4l2`l۝6)x4hiE&+**c\QBcRD1JV4ik!,CtkQ+lryvKU*.e- &J?8ˋKl)(g3'[FIQkIԖ:2lTC!d008B&RMƥkDQF%TDRfZUI,a5-Ƒ0TК ?_y\9p? B):SOy6>:B`Ab%pռfL}o+ՄhtnzK84PBHUhPJvx-?( JPw6<ݐ4xt}E&^u>K qW!F*%Y ?ˤ|(Z0 `  u( LB_BYIWIe*~7vHFG;3m&.gҒ8vl5ێFK@hwb LE8& B'ѤԖJ(JUT:M3epv^`ȓ.&TddV֥2KflTICR8B`Foh^B: %! e@-e`eC 6 H(sB! b4 R1&)vp* ނ{$1D0@@B> E@ 3Ն!9=d䦫0$I4kZ>?NT^yW`BG_J/ S= rP Jd; z`UCᅶi)O*&P% g%C3 V qdn=gGt 0ٓjz^qp>|yMb'ɒ8b*8K-ԒHIt(IY`" H kZ&uLuS>6pd7E tBɑ{kiԅӎ+.(?ni$0l)Xa!;/}V 125b8f8Nnl;Ch3dzmvSx5 )SktCB* D@RI ͦNfPۀvc"$+BP#s9Nzꏔ !zcF8s3w hL HWYI"d*gMF,/d=ލ&:sN (qfp0:c䤰%p6Ch C8t7"YInll^Hr'x uAERD.xm$GUu}sIp1H7pqa ) _ H`~-E`?SRfa,YsLHjDOK v*-!Fͤ4}&z~A;<IHD&D*fmjeK5H %^c_'9w G0ə" (@‹HM,vt7mIj- ),IQ arT &&P!PejT}"1 .k˺̘$v1ca_d^ϪK7E 7шyj0:cepX̯ൕqcC S `GךKI$E3g8/O 9iw'$eRO dl6LHI0%qW8lYROB4uGDLNs5&1b&KE\4 ) dИ,F(D؀ɠe]v>SeIabb}GʆΪ>g'!:+'J,Q>^~7W?t"UaF5ťj6 4ZP4M@cD5n%p. ~bZr>h,gb Dl51z;=c;(`1$;ց'+($'QDSg_g441@|3ؐg>"_tI@ }ֵۮ.UnD!0蛲NeMR3/ uxv3/)"sQ?S=dd& M Ki>8mᆞ5\\v"1`HH?R IHE۪ñ0M1! (j FBI"F|GcR3# Ddhb pdII:&D@hYjzx]^{jL2Fo>لU᤮f q:'zDوrЮ4nvpDɈakAlnPƒƴb#B$axNiU$) 0 Zu;AX„ē=2)58=áI,`! q2Z1FHC/8P`<+r@(d!б$R,Hɣ5 )Vbƒ~eb8I@@.H A%,9bD#Ållܛ)BthKc;98|8%Fz a܆31%yCœ mҕdEd#ݥVl'uO& b3dKB>RP0)rWC,npcnrJpd@1l U&mlK89aB lكo~7I`r#Z6SNdf ZZdC]r64L4}D6K8109΍V4~veW86d&,2i5t"'h40ሔ.6a h]jt#3&-3H+v,ݓڷ` ZEOkJ̇cM,'ԑcwa{Ra+9(m!2 ma6ff 8EO`Bd T?,/.tpA\ 3!& ̬XEቆđsWG[Rl{~^tlkǴqhCY(t,q߾h4MT5vN3? dBq:)A,RbJzf4Bs0h4Ax0Sv S5U&Օ4̬xaJ)w;)g 9Zh(7e Yhz&=kthia !*4.d2Al;&GDSF#u*iv! 0@pЮB@+Q4\K I8J*|srTy5!H#)!UE؁!!Si<0@ӔC L&%=c2O8I<ԓuBY,7" <|̬ y*UV'Q 0NL HSЄ,JDB̥A_6*0Bnb%$0  (Ć*JQI*bNt1,RҔ1Y$5¬5SwT6;憽1!H$C>uQˣ/S_azGPEԲ@0 *`v/)] #TQHU)%BdX)6hM45%YJi(H%YlF5lJ5-Y0I""D!"D#ZiʥTESiRS-j*YXFVMk&ɵ i-jmͦd-E"mIjZm4RTil O lRr`GL0KKX*±'hv5lͣ{!Y "ȅLC*6`ʍ ZJ[Ju.5F !B)  2J5@0 <γmǀ}w<|9Eբ#'sI-CqeUŖtC1Pc!'fIG OOٙͅ]jw=C,{~#s%(hu1&hHZ܅}M|O& b2xCvWdsN蓔<>y'AӁ'TyP5O 3 IOm X$Ij(& |1(U dlȌԆhMɻE.*$Ppe-B6!1|I-˦ZTbӵ-$iĩuֱD$JDǗJhJ5Xmh0V`t` CfoM1\WHtt0,$`X[)Y"!TfcX)$D.hbQd%1 ҉D3xKfB6Rd۷7iLd4NT6c|Ql`Uh7Jo6)IpP!`XP( cKC`#%MFhcHfbI3'SCKJQ 4`D3+pV5Ѽ[oZUu{hU9*RI&d!=R0$ͫfRRnH6=d_#ɵ1)nAӋG% C[#ol`[=CyT%M8 YCKsY@6 i"wO$ꍖ \17Y8SNyiJBrP 9%5j"2NdcNlHBh5!_fvXZ.$M#@49ؔ A>GDfޒH88)xB͊!i@F4`'̐'|p%!qQlO JF'KAl|qk!x`FP ɘI%@١(bG J\~S!K^3(^\ۉ&DD+SG~C!aycϡ$ҟ0Y$1H% oЃ!L1`.ҧh 7p92j=أ0W Zh! Q~;QdO"A=[ $"UQ;B Nh fQx t=@#%+^kʕ),D 0?D$AP R^"(`u#\ؐyU_9C*0;;sbQT} nm›JQT,R6kKf%m02(P̃/"u&FŒZISdv#@D~24WJaiSs7pbzT0T" "PkZxuD}$jQ( G:H{Y$gDz%J+D0 BCIEBj$0Z~Dq.,5.h1*lm0hh'RFX JMb*Be [$NŐWoъESdWGD<ĕR#I *a"JǵF#O;vT=PŤ"a;vG(;'*D|S'^c i^f&L*chfD|JGF߻cs< `(d@b=zP(+fĴ(qhf1BSw8lVfWR&tu+SL[7ffɖ뉛r %EѠ 4GkGAhCJ},d 钐HD!BM.s^]oo+^&R8[ᳰ5)S$)SoM PJ MT(RIM7¦M1D5T8MIcy*ŕTZ I9Ԓfn1pbB، iz`ˡ`J, r+G0"QP"\@e鹀-jo.DT8 [ְˈIJ"j>:yyym&bV'bnP'mV5kDm' hX6!B8 1N4q^u"]d ̑#D;lISQ:&ҴKЄr~K2*m0J=򉿥$VT ĔQ12bvjqP#UH@fM*"6ƳKJ~@טz H"bz},)?6W{Ӕ>geGrcʶdBDؓ vz;1j9 NbރޱBP),"AF$!sE IL GÝbl$HBbXI'#vuËxbl\Ŕ`!lh] e4INI 2H"b{O) tD$]*=r qп?g?J?Q(҅$C8)U+s[m,8!]Gm6έܓ3%Y!*!j^ѐB~Cc Ham~O~g1uwwwwwwwx1bfU9Uy"=I)8&r{TO|}ɋ"UUVjC>%~(HYS%dg ?iJt޶2P`0wA7TDcR Bm:цԚ 1ֈ{o0H=# pD6Yy@^GT&(b$<4gmcGt ,Պ=Fy=te@%廀I_D@6O."~kO֢bT5%P 4z=l*N _xt{`8 !H&3/4cdӡ6CPr fZ\*`0 L1XR8آ( ȄEC6ͱe$TF%=eR7vzI,DJG|O)GQDoؤ$Y%Gc7!1UD~ {l+$V([\mF87mz%ӫ3ݶv}q i0,0) 5' Y-~G E (u Fm S@ BL ZeI 3s,* (%p`JK Ke,eF=ġL\$'IЄXH8bRoJ+$wOSw8E CN9KU)E&Kd'w"j"?7 vKNVjX2Q]IEq> )29NãHD:D DT`LR') "Et_J>DuE~gNO3c&ۈtY A6H}# 9@C %I5>JD(ԲM DX]'FK"NA$߇@G C["/_4$M6dr6Ca A!-",B0'IX#$"'L(a % IFVJ A=>4 |ǜFHOO'=H(ETaH$ GF|=Z` TfX%$gB7+!W;G#QMQcԿD66Cp>jP"`% E-@ (C]S@j)^Ƅr! r!BHwaCt0†3dB! Q $ F bX8"0)J H,,3 hZH JGAa+9*аç"b:I_}?X (iFT,qQ  $;3RjҚlR溥{^Zx ҃hd9D(K @PS%VDpaaB9 9Z.JU^-/"WIhx iNcWUxJ4<0‚# ͼ¹'$XQhB4%(JZ0+(D&/y7b:{"Z,Ǯ?$αNj2hP4ʄRb  Lxg$A{^Bi4 FȈk]usM:913pR+B t_rL\ +C?f 2Z#C8$ \{TXQ&K"  Q0ozO]v< c8ı]) P!o\leGvKBdhe,t"E}ߡgn}m Q]`r"@C'ՈFPs"K Ars[[4k׎|+Tp"Ȱjq'"xg5 o~mv]X #-I8. ^@p@"&KaꤣEhV(|sb - 8S=դIaTJYJJB!g$ dnyZerYjJ^I$!4c[ z, ;gFc2rZKu+`q^g У9<QB%; p=iR#0e (H"[olˀiB(ߏQW3=kJH46$@HeAp#+X7j N'IiGeB7Aʴ1i@,cA;@.lHd=s pе! IR_DEY"cٞbCY)$!Ka&DKIF睙o FM`g8Ԋ`a^hAD.4+c T Qo(v0K H{L}Je`N @K*%:$`Ή2@ܕiLLn}҆OrςEb2k>]ȟ'@ dRsNuhF1wC1JLxӔ l)u`F P);[NYA(m42cpw[ϢH8hb<-l(fmhT F>) [ ~]I0d-΄l!T*7geqz]#2 56(A @ EMI@o ฏJZܬZlH5,A~2ށT0MsD: mDkǵo۵HrYq m>isV8B)U= =|ϹNKEI'IQN%l@He1$+(V@IV%q2If/B %R_qC,Ih5.qڳTP` ,V)Q*efP4 =26C&upH{νQ#I)3a'hh*ڋ$.$o8D'C}E `cR'Xs>9$ Z UYqRRAJ$%1{Ks]OD #oNK[2K6뇔hu2!T,9YXȌ3"fV;5%/x̫b@t7%L#(⦲vJDD m`qt(B>’XШJC+<%z^J?>"GJu !4XLDm*K܇T4PEV$|s, a0K#>_X%u1mKM,j-xlT lO@dK DX~)'//M[[үy[@nRM1$:ϓ'r9Y_/͊ ?Dߕ 4%1fcg!(tНX?nj`=;RȄ(A pI!RI(`Q25ML.f剼M}رՒHXOJ!P6~*;宦2Li]DzHn%aWnlEd54R%F kJhɆd8Iq`Òm uXbnCF{1Ox5RĢ`!P܌|pFGLСӶVTߧxE(ڷ+^?~V= Rh^3 kD @d!@lH{TpFLO_,~ ǹd{s>` #!ٹM,YdT(捹l# G*zU6t7F`JX'#5Vu$$n;SZLvଊ/4{O^ͽ!zd@! !HR%S[,)+RR*a[IS҃хBxbm6͉C@ %YϨ R;.xȇD'ۊ0(rZvכfo%TS*n!ky -o7&~윢gd3Ɏ8umJ8.UfhLZFRqXhލA}7<%O֎^jj1ίfon+EAJ>!i@`mW@1X5Sy H1XFz7 e6xf uu !'~q{B\Q@K n*qB͗ Q&lZ@OFH)J8Pb,h9kHWU⾋ FXA',PɒU)ehYgsZƘ@;2Qιu=!89rɖֽC YHm&1S H9APa`@K JQ1Y7y{ؼPo-db@OH@ppN#췞|9](p.wF]pdlH%#DTơ3T$' C@qg's4ua !j{%0Ydw<Dc$bZPY}.XͣCM |#h Cow]Lم(IdhIUOp=|,lBC" 5`ؐt*ڰ&.#l*n!Q6yM3 3%h\*u ##P.!l&1-DFbࡁ,LYd!4Jv; !h06ҥ%P.e]kt!M2cgR n9`8&%"&˒(l"Q"L АB\Q dt RU&*DR)d P"hXp%CF@ׯu=6gL5d2HAvV-ϰg2y */9Rϰ *0-2EJ@27T\AFa,,,4֙L*^" lnB"X42-d&DTxAA J=B!_L$咑T`$! aG%Dʔ)ŠJ`zSrP^R Dݩ02*3y%L]UGF!'Yw4ZA%GqwŖ4rOW.RVlub"ک%bv;̌p{{j2WtyFBlHqqIX|~pvTTCFlC4ߌ*HXjww;ܫKVm-#VmUwuw wH!ەw;HPm]$`K ɀ]wuuwn:pu]8w[껻]ݮ wupwwww9wp;;pw;;pnwwwpv:;v]wpqwnU@`wx>1WLYD%s@bEP{^UZ񸝣Uz('N18' $K֓HS2/$ki-F aJPF@Jf`R[C)Y!?R- HiQ H}T' "Bfd *}D8\)Q@TD/٘$Fb!L;+!G t VU2u32Hݼz$,@l|NT?L@8z=1REKJJWubH0pd8_I~`';ˏf>φMţ yA$_"Ȼ+psp\&>'TFM #1A 5"8,H';d52,a&RNn6,[h] h9h hI120LrͲ}7t(!Kκ;tR-ׄJp`+B4D&2Ĝa!iiDؐ$)$ k 8J$ RRHhrR+Ԛ-c%51Qfi6cG!\\YUeȲF5NNCDI2B&0d>Q"|\uYXYQZ4Xꭧqׄ$<@BC+S WFhrH"*[ A$NBꒊ @xs}3/$y 9BA}ik&DO!U$7xOpae$Z~*yB9#g(cϓ]읱xY aA6LXhCGum{*)@0Cdy^ !| 7"[!&$GUr: @ (R+)0p特 cd-d'OP*ӡxM! iA6VXHC! ȅv^wukBPRQN.($5IL[:2pS{,ѧGRan2tsRDBY S  ?82"" C0"h1IE"zdbH Dl`J@5PJYp (TZiHxm D"UPPP16*Uh4R0I,JΝ96}W,7p&42"'ҢUaʪR>FJ4<^$7NC|<>Hu/Ve$odhTzCBmg?12$yC+oR;vcxC>~l!| 8j.X{0FAK8DIm$RB= fdSoj J L 0FhѸia8MLR3HW;x#B"ĂLP?i@qڐ^Y$SM.F,B L,JԺO~ TXCAHJQSBT;`6CO%s)bCR{ 5d킦|x8 D nFmXlJV53YVW[\$"@0xTvSɟU jK;I8Oƒ =FPa$[*x"0LAC '*C hTd(R,*K¢Yk%J*kPD%!bN!j2.Jd=Q=`s*%i DUIpS@4hblG%w%Y#>xGMy$G)REUC('l|uWm~VyDO1,32Olt=>*'I2}`]&(CJBʢ1B$BRFxPRYCDШg Hl}#Hw7vl fX,\$\ X0xtE 2 ̀?h)@fG=&Bf/%FC{d FߟvJR2ߋZJfY"~"T5)Jrt wXd (D "|^s EIğgRYMwIPֽ){<;'_@&n# Ce`3(d8A*J#tHa&GA%J4Y' xF y'*FVU==SƠw4#h4;%.D>tWXb'$f)YVjRFF1ņ|"EɁF$eZN2 'DRi%&N`0c`J ⤮ҕk&͊X(ɋ=ɳ[254 ֡KAK CFbaI%E,lʻXp6280o&0Mr 4tNIo;\"ݜY4`@I##L$Y'8dskoGUMy,pԃ)SQ:.m:,OabI$I&lNJzI7Y'qRӼ^rv 2tt"T;+ULfIe Ok~1`F$~9Dp ct߽ (`Xڲ&Jƥ ]FVkHv) ){0d z)`URS^kS~2 ;b?k> I؏z_6$E> Ig|U=1N^T $B,0)$ EJ)GϘ#BK"~]ܨŏƥt(y8Q|?Vr> p+sdWJ *,$0XEXTH;Oە&RGwvwE)*&%: $1p^]114F慢:Vz'C*ŶJIJ`21< y*?SFQ0s24Y1UrEan,)$3 %!IЕ(pߑ݄Cw"`MT9*ZIJM e؍:A*8%A'")$5,s/(v6yXqD6::eSs؄8KNd1)6>Jhh % Pod̝8hE4L܂%hPi @Q%HlHd!#VH⟮Y͏z,ܤm[~ԟrS}34`ArS(e2 "!"R*0@UXHÎ OGZyϰzofxs)5rɘt$^fO--Tqbw;wrKdjPvE]]PQ%`DnWAT/.xLQDDfbi ll){#nڹJa*fR%vjh+]ڤiV(.IU9vwY6bIn $oMJ9D3̨ɷ< >~{ft;"(.8)b¥OmOl1MʫG8qj*BE![\an2 Q4TdpfIn[Y,b-WGe3т  IZC C LNKKN$BJzD%^E(AjqT8 Ms2#,]JåH,070%u( +fP9p5(\ɑwKd D% 1@Ѕ# 2~: oUx'̔ 'xMeDiuc$()(Q"+H%%D  8 :8Cv8Ny\M:N!ꀯ!zH6I3G9ca~ э*RzGW N3MBMI:\=!VCGO g q +t=y'b\OtrYR;8ЎM,I}$ 0oGbP5X= 2Q#5}U|I a FX( iVX@ ! BIȈlHRF! ?],da"#:C^t| g)4~>Թ8F0&BXMi(3&hTOhZ`W!lWoc?2*fY*$2|pR!?:HDaz;{ Ԃ(*D^YjV`cCmw",ɪo!kzmԅ%H-( BL R4 "4S"&- ).C HHT dGãN]T`A%j[@F42@~t7jBHc b`o< rrB~GP񤳜c vxW V:a3 c䁌]7 Ka7t60Qa( IwF(+$k ^??P flz^ڵvwTc>;ַuGoAJ^۶h^z֘ykYy,R\ӯ,:$H>W=}2e A@(h>-T EJr7[hBC5BziN{=w=>GOv 7α@Ѝnޖ  烸[Qϖo{fp Q}R [^a4ܴ[Qvw\{Ź4}y y^4!v")Ӯuwkkj\NUkۦw\+ӑցv osšJ7Mlv;gnl:.4==Ƃ9ݺ(mlͺ7nv9sW9ݺh$ڷ٨ݛ5 g- ݺ %tjجPTݦæh t6x.k;_@$SoM1@U w =tym{FSPj`z_0XێO糣o|4*6P{׻mU嶨ӍFaG8b ϕI>=BB)ESwZ}IҨ1vjweoOW\{wٯkm^kӕ>@lzΪ_zU]wxXո){ި}y};g\vJ-Z}womoNjcvc_{_\N!OfvԺSUJ]F:@q4hLֺNuk:iJ NݻB]i,霵u|==Ͻ:T^ڒy>mx{׹Lju}O6n@.+^^|Cuyn[j}]oe4%ѶPk`}jh((j " x,meCu+z큫aQ VTͶ&+Y6i4ح](4唍7a &=ö"owZogv z)&ݦJ6;wjwuZ:;`'νE|m:tl m{0os*l;2z_yP׶t͸|}]xdݚ < M+@F);wt( B;4\yw{/lI|[@ӀPT'`6ff`^v=z GIjVH2ؠҔ@4P 7Zw.YFDa5 S!3 NlJWvւHAJt:Ű+:Rv99-=<{H)"Cf{X)iӧN]SFNMڜ*>@ySNƊdcScA4"[@@jsie ;`h#&vC9}44H)]5_*)@}Bt+ j쉐$0P}l5ܤ`%6ImkljUR`-yRvj9Tzy= .T2ꪺdiվURSBP;n:Di5J|[{\ Zƀ+3 (vրZ5W{m=z{ (;1@Т:-hX((45.Ƕlԟ}i{7|}\>WG] wwOo "hM4F@ JeOjO5Sڧ%4A"5142e= S̤~6Mh4HH d'U2i~b$j9;GhI-.s֛rKǻi*cxf guX[?:y Tz O34_!ҾcCY1fnσrC`a `=obW2a)faKb0a!R' O#@O|vgaݾ<(Etީo_7v|9&h&!s'6Ov.DA[/bxsUgߑ2 X2=nH㾮<'|c!`  !^pw_"{4S12BÄ`kK쌊7'a\C Ikx>#-DoM'\[}??{*y=i:B ć}ӂnfgę┃B0xǧj/$Ox^؄>GCׇ̎dbD4& Uk0&bt1j5N;}f#N00˴|={5kF'i4ݿJz5%n7.a4Wl_X%0˳xA*uv/ Yz>|L3uVsr~=!xJؘA6wĚ0d'llqH,ia߱|qݷ',gYFŰpl @hRDyCٌ3nn~ͅs0;n9Bk^p1Q5'9Ӯ/laN1!$_ܨLW9h33C>ŒX<? C0~s!D<>|׋؁62h0`?sP-DȞ<u~˯et<͑RB.*JK_8?d| tί"$g__ (柹 LivWzJ]H|;1&]Ndd*9z7CfŒ];r2֘3_JSp*^Wnl CY ik𝷟6!}z¾K<:CiE=[־T>؄ SĿGy͇!hJd4\N\@}{\dY'_g{~N8D6&78rVs.uKn%BCHTt<\vR0rv;ҩ6i~!`S+9|93$1e~OW"*ww97t19n7{rsrqb zFyrTj7a@bsݥ$[5F{x9?C@xQ3$uDۮxS9$r0@shnƐj /s3xqyRẕzt2'Du$ O<6 7>˱]m`xC)&qNS &IqE~`!/G3 lTT#eG !D${ w2=NW|$ ?V@xecga5˦ṿm= ľ/uT5UST+fb*pw:U=H|Rnh\`':ٞ)Q<հx6.P JL ~]dkZ-9{MEuΎ{zdsؠltqOKRӶc;ȢnC_F%Ƞo,_= Z=?5^Qj(0;hD1c)߶mf@VTC'mƎ3K(p/3lk~LlÃ]K3B j]6ַ=9~{`ïF}P}_dO?J ^,YӈPqdG% >J/%?JA A> ijH T[𰴯1`ǚ-bNGf^emM840FBB,-I(C'O4/'CuI=F޿iPOC!sO3Adj2_=A0ntrpP: .>e;Om"W٘{}" MSٹSc]Uz\;ӻ`YڣkywǙovzq2 ڄ;i)%35Wٯbc=~g[NOfau3߻>7af`Vb|a9&GnUwFqt9CfR8c4Ʈn9mCL(&7 .5ޥnyc p<5SC=8uwl`x¬#[b,r("ȎY#u]> j 1$ .OcP66߯L`$^`@mLf4,GM5ߍm)(8Q6x+Iʋ%#MF?_"v9~V:>=u-?M8u^Agb=Fx(&GQ%>4 ڬ2r'aqG  t|v"fSCf^v=Je?.kJizc] [Ois ,Ҋi'=Cض?TE_T>|%)=!yfo>wrdptQ?? ip#=w/ќ}UQXæ^sW<evʄ2"9\~jQ*{<DbydLӱ͠f؜\l5R\N -w(tw]+q]g- /20t@pDt;/+ a'Җ1soeL)=i]`N9:Jjӽkf|O=܊8cuIbQaٹ'3l߄$ ȝ,o"_a$?n2Q9^=oO6ܷSO]*O7woՓa| BXӆLMRmuYm$ɹ~^w1(D*GAǾ(4r~{yGɾ?ZP}E{0u˝F8*T$9ҏiu삻A:*:Di{NnK 9Q?Otq?d= {ѵz#f{ Wf,0J&I͔{irH\::i nlqx߾q{/_: sJ8v4/NPiE li^Rnq޳ _ep!QO 5ABHx( Wi[5m!ZFiS#|mrƸ,4hc2vLhKϟ x^kb&[ZعG,A,qzrx0]zơZڙq/QϺ Xޱ>熔Mw'g=~鈖9 &sCBuFۅQ?$Q`023p ?dB!( EڞxP~؆TTt^3p-c_^B\ zpvs]\nlGAarFA*e;30xut+$"=߭&z%@YU~4: 3P 65ĤIQIgyrd]̩=R U.LJ“Q^(F  b%<}Б~4:߳"b {¸. t2؂Lt{Pu0j&hX,`^**ؓlTAB.`yIjbLYk/fHa$K.GÇnlh)#_=߮L6?Yų<Ϯ̜FS`No Q/?F2I2jG#c<q 1 O T8TwJ g4??f<~WR،6vb*̾*,lDBJ   x i=mL[@- gSbNƈN+>wB/n5ӁaqK6GF1ֺ C"W􄃩PI'Z5ֲh54بxS2i ٜnoVOfoHvR5 +_V\{q"Er'rXO?|L2|pP) 4VXʂmAj4+H'd.bl84k{~1}APEwr?ovWSᲷf'O _26.7hIdOIw[fv̳mkٚg݂PU9C``GH" ῁v(7NT)b=>@@su箯5l8}ޛoLw ,QIT*xi!6M-"BVTܔvi"%10sht0A  Pm@U 78 gco@`>ʚdk?J;r'Ё̢7؛SnԯwgutJFHZ]c_ 7$W !nNk b"m4@PqHagN(&^`pa"a8<'oET4)O؍~'8;" :tJLLwo$'': +,HҿXMȵ(wJB'N0`!Y\+>Pa8RJb N&:`D1E 2GTDK 5Y(:EL HYbH {׋G~'ȯz럭/>CEt#<yߴym\xy{c ${mYˑ,]|ZҜ8JVK^Հh' v΄D9ig77dz{;EOCŚS4V>рsmX],08O楝OdnO`Qj0YI8~p!F[v6 5{M72#8R4?ʭWF]s|[+^96.yaiV})^aG`^JiLn9v͜ +,l=n1s{Mߜ0.>X?k}B7:v10'6]7..H ],ogvݦv:]Qky5 'g p푡iK eΈ''77'737wI݆g؞߬w;񮯺GdsRmv'Ls4FV;/| GX2٦%MᭋļWCcɥ~ M6*"W+DֹM3??o,4:4J4@pt;>3}ɋ7TmU0EA\@~aӤZv"pJєΘѹ)u).;ZI;=l -?Va |sES*i" vBҁ6"L*dfAnz\}XvōO_qƱlD]bK8g\#H>moG7J:=,hw ztȳmN$pa]8@@aTߕ!)# $u*_e7! =PhApOѪ!Z!( *[AUH}(l,E ?Q!WD @0RaRBΐ$HP"Uu(ڊ? .W|"xH "EK0HB0Aٕ%K*Ki@ZYמ"%@DIHWՁ" #0}_gP?aŀa 30kbQр Zή&i&*Is"|re5v=h qDv#<|}RI^ V-}pM/*xD1) RjNz N\xQؔOLjPݟ1 YPW0|pyP$LH5)M+@T5Ή"i|h: >nj~Py H "-)UddeiSJfi6hLMc2MdejYHG0L:LC Cbr9]Vg9&l.D$ 1 )~{7~ K]d!_E5ke+1BQh**pLLTuM~&Gz (&,ųY)ME#t~Ip" K% Sm`亚ٲKYRbXV {}]a]fbN8:C C A"'.O|gqOqn/x !̇{^ JlѤ aӨs\@wQ,цũ`af1*0wDDB kBmr⁡o`}!MyB$cӔTNϮYX/D|?)Bym7 0 000`UWCmȱn:R}N<MTETi#+m'7!#Hc69~y; 6R\/ @4p$S2%~=60`R>t!˟dD`>_Qpz=ֱ$@W@AVofL"NY?A#9<z  {CE^+֤H !,c@R^یaQQ/"e"1u"|sDLš0 0=14^&"vSy x='$#Ih`,J4Ÿ1= S Ѐ`GN* y]\ `: ^B@_?1-[ @|%i"|ȞGңz=Rbj=T;T<ु] @0qE$ Gw1C7^08 1bĀN>qӫr>}N{p$J!0+E<ry#Lqа,g+ԝ;fx hmO@N<t"èZKȏP  Pʛ|C6%HR幨ѱ/Y-)6In$I0Lt`ЄyL8{a8!H!I":9׬ 02  ~m :6*B"G5Q䝟~``b@ 9 0Į0XI W6j5RҤ BHYN.2jGP2HL[1C \z]M|e7 @i1b @`PZB=N2@.]!oFvE4 |@A(v|PRcMR "zB/AOC p(x Xhv0_I4:Bw1tAV=pʺ$B BuIMB(I A*(GRG4䑼{B>D. N!R i0H "byDdoG ,ɬ!}V?( Iˌq _8dpz\{J }jgѹQ0ӗ}۔ٽTtT$nOhtҭ t{iBYX_N)Nق@]~T&IJt\`u?'grf(lqJc{\%"ᬠP4\u-9OGXǡ$x/J^4 B } Ccp uĸ sP}Gz vx~Ęu"-{o9dW@9lGJxHi(w/m|pv[?w>A舏Vðm[^|v,^'밶a@**9w9,3u͎}_$?5UymxšO="fdezt Pl1> U%W~@!g[ IHHH~yѠOw<au^E E|ppM8㙙8``DUH8.{f:g^`cs\E8ϩY!rh .aV'hӖslN@ig$Kmpܛe}t{=?vq}8vkt#aQE$3G 0"(H Aq$ T60 A.ruȂ ToiE_)DJRC4t͸ wS:yH-灼K CX'Ap^r9cL@2܈з*1{`4l6~^$: ^vԄ1J8l$2I~Ē,}^kVd>s=0Xc; E Y" d߃;}}ܒO"!w@aGCmoL3P`_t&C顙Da4oACY[J!7hѡ4SFѢ (QNh 3F 0)q#HeUllI2Hv42Zrpf 5&ܣRjUX$R8n0$'X `Vk2M7R183hli@i.L0Eǽ28s[W|C8L4#D1A(Tȴ;t b]4*LT.WU03,-],#nֻ\vvW[VW[%VG2YLumtR bе9513=ɿAEׁTĵIć?2fy2z`qЉ"3:t7AbH[#th>s?&#傺EyՠhSJC B)tMt$~b+@20_7K>6tP 8Mh,> $|u.\ޤtunV;2]x xy2h (9dP!mmPBxt*10[-~d }^xyz`/U5yX3H>< 25,`;pmpf͛$=.A> PL(RД" X4fRl]( Ӛ P@,hHEm%$"ضt)/< ddCU+`!ǟ@gL'BMW/I$A y |CBZ)  5vBLZa)@.:wwcE3aΫ5 r6k6TMp D#pH8=J}ChGEDv;0[; } &B7! 8fZmO(BZp ̚<0t98Q*tAj fP ȡb[DthX ׀ a >xgm

IcXH:: Nl\:d)j &!&!$ݴpcBft#22dze#KϮ~BSޟAUgyG:^3X6g!+ӣrӏ/< &ih$!-gR\=MB$B)Ĕfwlumlt)& H񹁞A"!尗wyDdUֈ 5H]C.ۨ|y|΋Jͳ~֍ܮ<vɔ`~׬c##`-h6h",X⚞A\c#l4/~M8HxmJL$胣Cڇb(Gdf͞F'Y(v(MF0-KQLF%t;94Rt`;DZ#RоqB@kKk)I2$t a~i "@{2Q"dC, LJY : pD $- yͮHŋ5&<1`%TC5.w$\]6[(U8\$2I@b} .B!PJоd0a.pLxA@^#قCfI$$h`9#6绷#3aIvv ltf|;ibPW(<NS.rSZA'ni=Wu>a /uG8zT1Y M EIL &a7߉ƨZѾ8.Y꾑s(DBb(01ͽ<꫱TMXmᣡtO+ݱLb6Qbs;bΝ4:/?\E;ktË́ @8}XE"%IC(fEfcmQ3|?b',HED/iN.bMƉk",zdbzt(c?4+k/-V!lwQXMӪgWRJ%6 h50RQ-VUkfGbʂO6At!JDuPxmۿq 4QDڗ_t-y5>Z `.nWrJgL p1;Õm}Va-*-n:tI QH|5ӏ=fϩ[Ky;Ρd?ܒMf'i=g!3Z^N& R8t#Jӥ4rQgnmKGQ1$ΜdĊ؅s*zn"`cqa(*|wp&tH t]{p#hƐu(^kE%tdv~׷EX >}Ƈ&kS?s)L'iEBZ(Z9>IG4?$2MIvm\gȱB DQ~߂^ދV,S$' DֿjLvYq!EkƮPTIxc̅4ALI$dI$I%2:L}%8 _?ͯT袄lK7osubN-Gёm"j7XlmO`y3d,Ўx qDõ%?{uj9E Gs `\@}7a J(DB$wBK1i;%TBuXt } cm$D=asw߀5澼,D M]&%^= 8_ſ#=C} %hH?.&'>a`Xc>',3W`pI^eƁY:V kN?˄7#PF7<zUҺȶt+P" yH{n{BOLl!naL2d͓I$Xqb!bNr0p0! b 0=`|a؋ꢠH,t"}P`k5; b: H6C>t@XjfA)'4#n?f IO͑=篯O 0T( 'vfC2+0*2~cs[Zn>#B` z-dd\M0kģbR.v,q7BZC6 zຓ42e:Tw҃̾]T&9g]Ep}!5Cs4C9(^ h qRT׹/#u lq 8izMĂ2 >~+i)&cVE⠤{$%!i X0?p&"5Y~w5` MH_8c)f9raSM<>AtOmFMoNA&c)c෮T>EDyk>~.9]TE%9ǻX @(B 'W1CF(zV#! r~U czPQ g#H[vcʍOS !J Tz"WUhDHB"xKl`߉ly/? H}GoW+U8LD}ߐ%^x `fƞ$ zWj㨾Nh5>"<7+$\c:ati 4V':>4a#y( sH"Z޾\0~$&tӹ&[Fc6/A r"N\^`:&E4bH(섈gg 8dJ  R! bPkV0(!>cyI„#y!}i]k//;FAȢAJU݀B1 k^6HchM AYJ8 hBkL7RvjjRW۵߹""Řֆeh%&J!"5-6mҹLT̚  $Ã3]@+O=&S)2]Ƕ.c=[uw4TwQ2rʙ:p. ltǕ%,fyzŘ4m+շ3RӣgPEC|\}'{)VQ?B|A H_73Ro;0 H|N"Dl#VV$_ݒH.xҧ]+E_3l@KOv&ca@M/H+4QDvc(tc )!q .(+@C# #01& 0Ze "?r"N9 b03h2vGw|wf!%q !82&_w%Kt^#@ i0'N1A"NsH:^pVv?ŬOG݄^RoKBiށ4S،܉ې0 Nd"ld6.~+ +$, 䍜֨="Ca%C#D(BP%f,o^-fgqr` Ntvhwthd7@8#PύVO#*&.tuh3QYN$@E) /" psD CfHe,V",yeWp$4 0~*S^p r{͒e4d 9{'\ֶRqooQCk]5VZwu9Fp"M2[u59G:lј ͖)R%iJ0*l\zz琜J"Sc[Fj]h׍ 8j'^Pj$L4L5`XlAͪ Zڴϓ*8^wf. t̩ܬxL>xL<8^WRm1@PPе3;YREa3m[bD$.x:n7Ig}x/G\|8(f1ݐOU{Q đR۸n5 Zq4dxn@`M$R3a' ^)0WPJ ulJg< 3ٞ=n2-K`]b7Pҋy HBS2o2VU*DJcZ\vRif8NpNqziZv=`GvY.EBX QBT҃c#fӌF !}p}.%?'F z`8 Wq < d5sVw43pB[B0Q?YDl#\:a[we%*.f 6Ffe )C0bfbH5R)ߪ!VL7ȏn 䘴g=ia(@T[ )_3w/SDԞnX-/r݄ #)Jۚ=5lhaH'bwP7uC  AʹICcm7<ĝ bx[2{7765AB 6xᾫZr_Z{ 0#Nw,<7" tqͥօ< ļ9>fIPǺe@'{Q6H'vr]3b,2l4SPjG+f4zl^$@mfvPc9kN,Uyzw^p ߷[&_?Ƈin6ێY5ҀdB/꾭;!4^L7u|>]?>i<8 mۭ><8)j~{;W4ݛ$7igN)2*I  u}?ܾ^я  qyjnG_7Z.\#C_?9`SA$E9?;\p< yrIA!o9ԶСOY6 fd3L0M ϳ*P}a{E>%9d̸dʸ+"=ZA9ṉc*ͬc|T@訞mkg"])b+La,݊?7saʎR6q!ǃlA=uw<֋ 'x(TȈp'4yт8'-/$pj4m __}Y`4Kd42[V 9xwԍ%t\"pEEd<[\""=/81(d>IFcjѕ+L3ZdȪ^hwb A( Ew%7c/77ik!! T`͎G䱹i£z0#Yɶr9~dv{?gFڶj9 b !sSF FM>cY'y8H0qoajՊNjW 5f2b"i#pېs>ze&h1NJ1q‰j. bNCU1iC=\! @rcfCL`lcYikX=H&BۻL@O;6Ih&}AԶ nB4q[ؽ aA27%70f!OGWp#g47'nnZ ;K F$UBt/yJfd@jqpZL@E"t-oGpz<#{rc _#_;e F2lfo]#?Av#'Xp`Dt'eR79`aRx7J"{_<\άM@7'(1}*v^pW^ iLB8N{~E̙|6@dHC9@ܷv KӤӰ ZD%^L &4l^1b816 fkx#9HU!}{z"g\:懿^XS*T):GROncÇ<7<):RQ+sO.ݙ@D}y|! PzV.8 3a-_Z e yO*οW$eijh8{ѢHz .6/ec3࢔p>P]4ycPFLvkhS!$$quhdnDFir?b1#¥{=\l /yH==7Pd@S9 "ݺfC`fhycB"s2H)0 1D+cg}&NrT)I6cD`b=u11 '-N^M)A&Îsɧm8uA99WOדCc|!$^q@屛Ʃ9t>ٳ O{XEEBʧ4Dhq%uWx7SgMMw{cӆ։ެ6]7H26 YH8}M7tL9[v؏rڭGiB03Eؾ_^p^%kZҲbJPFt\Yic/q 󒎦'zOTޟ'ᾶ# R8\lfYAzjj+y=`~;6U'1شƑv*kPbƬwߺ=;'bE13,n//qI ݮZ+m{%Sc 2<z }L2N5axwqH=1U. 'v99.+jL&CyI*.uQ4sXyq{0e$ P qː_OF}l縘3t'];䏐cӂkJj(![:S^%8sPe]1 <|,Dxҍb=Tc0&RvuKigz DzDxUZ%Y+FN~P~Arh)? oM0&#>!f;v,Y\'=@~6U3G^ğ⸾ E_wfWہ,X]95DYn$sD  eS[;wMrP@m@9ɾhkLdf03/ k LĭœNo‹բd nsn LE6T\ a^WR&i36( lN/GC3T"H;ϻ>9X炚H I(, 8ٚ"zP\A|f OvFoNgȒakns.7K"rNߚ)$ Tz P!n7QD^?)U;lhp\pȧDڳ!B05"G%0#+!9߰M̤4/PKKP맞̇2VO:nX }D+6Q `"nt0 O7_~Zxd zMQGbGDOs# B^Eo ΈԟU&Q?pe6qnOCUa%p}d_>Hhd3GV~=i6~zܧXfN2r)pbeN&j # t$$D9IcE]eKTo1 )勸Abǔƴ=M`4qXr~g>S97mBDJ&k@Do|׽ kfKM.:(:85W럯+7Sq$N'^޳O'xPr-D&@lۤ z(hBͷz曐=(ో m;9rnst|=YX08fPi=v}\mbx6g ߮h X؄m|VWW,1Ѡ)Kf% E$zbL[<5,sʟ/MTtrdrcYl=v̩3hk9覞k*| -@*STh^ >_9'0-!/o1֢̦[!Ge15,$S.1ZWty"rAgɵGV R@= Nir#1A Cc@!m9(ye9GӄNԐM \sS62F9R:$hK`gHWwHY(ޛvn aW B*;\\o:sWxv ti'rR(m{; V*LT+<gmN"$ej;'8t#|Yzܚe+ ~7t4=n~ڥ&ZE`.fA% 6`D!uR=aiQr9UqDq MB#vĉQ"]|+ETPU /LL!غܹbyjov}јxj&I!yz2GvPxo9?iV%xH$g \~Zz41LTW}4C (ifWvNj l 3|,! Bྵ~0&qW:1$1С+ߒTYA)q1iBt IdC;g\cQ5 X8*D`LO#G Q(t$=W[KI@'a͛LX MM5.Q9Hrh A#]01'%>XM&(af Gw3E`C 6Jyu+N clƲǁg^&vN3=hN۞T%98! A}[1cFbttEp'EbBTɘ`ɽ4Il#_ ߁/,W;㎟[ĻqQ8 Tn `ivl'r[nWQ{zcHhܹ݊dkQtK>1gG6SdBnscEoՖGXsNk/KnW4 sw'䣶4,iv"Pl_M~X7QԎigro`sRY^7iFgrOھ돡Ǽ|g i_~Ε=sUd|%HN#׉AQFpƃe2!F5]LZtN8Ф&JǴq~1vߴntCXxJ33x]戒m|2g/y78Kqf,NYp S{+ݰg.P_i Vt#B3\m_>|WmM26>.ZQ 1vSs6]\DGs$u~Ɔe[\67 aQ۳:6'],]-Ag0%1|}F2i샟+)4-"|f,&63c;2E [~bzB^Ώ;>l_!ao['rmJ#n''G@(EĶEOT |*|%]tY7tKe2A"dA(qH2QFQ)70ķEĕ!`bFV^x_9*U wE@{&D?jМt!ݮ AwFNjHIX@YĠ.<^s:A5B?@.py!q[`V2='In :a3nq2QLb<uq$]9EXGZk<SKRtYmuNQt-!^L܅ Fgڍ$ǣMB.RM|h9*)*1M6c ʉ+<4QDz8$7~Wy Sgt71 YA)~!?%>UF*?1g;dKNi!6vgGHA4 C6*:4`rʭn!j@;x Vް3Ql!Q`Qi1حڭwYM0H[4gv_1z^,+!Hą8+dh\`t5#ҨO壹gIi( okTѱh9A}hXrL<i# z!Eg%5wcF!3gèѡz?GǞ úH}Z?e.d$֢r ^ŠDR&IbFҮ/mod 3ͮVdg&3 ݱ`a!5WX?Ij*!0` J{Zё5`Er_Oa|l Cф7fp +;YVёۜpnCftUM{}sda~D("nB18|zcsE5QrȆO05=H+h;x%1XGAzA$ѽw^t峿WC CFi~mKrkw|I?z#h ͰH1OF:3t,m yEyn;I'=c)9G$5/sĽ4kr, c͠2{j˖AGl4hu1`xjc*8^ =_;Ypؿ ԰$3 W&Ж}-ndt3Ll!sw~?}@q$_?|LD$LB2.>9' 0 Υ:G:2ShM 8ZNq&>t98@~b[M?=3sɶLZmf6c#`id.F{:sB_>C\mZ?\mh4lwb=n!Ǽr]dEك[y::Si9M{.ˏ6tt{pTi.)vt8'f$ϓofI;s8#FrGRQ{) $!Y͖+XI#ɚ&̄oC=Kaڨ HV2_%;ݤPL<!V|7Hv=qԕDڨH !FyXlNqK D?d*H/v5BFzյ-w"( 炃X=}Y&DPegHdBZDPdoG fߍ֊wxQ">/5.tl<x!ց*&G M3q(?Tee4!tͪo}"Oy4]#C0~0GR!e*M+^z@lWEOś6ΓV1 ;78azFxEJ)S&hT+%90|na2Mig~)pRJ O|^A"C L6w޲Ssݤ fTuKo=PЇJ0ۤXJz 4{@huHl<.hc+҃?($)̓:)#YхvߣޯwbC;̘3j7{˽~71Hy9=Mv3f=}1. P D'v>LI(3"c6I<Ϥ>3YdIn'0򲭞|dQh9 ffYC)oyy캔𻳠a(/'8kԤ5)>36HMieˠCsݗ<\ ;0#}eI%$ҩWs`^0jObt{r^~%ݪ@FVWKSWkR1ic!ُc01DX2"'C b0 G<nnŢs?n~ŀcZ!NR@ՅL@_8+l\L_*Qn| 3`K d^a֛!=$ȡh&7ƹ8,oA-J[{Km&;TK}(:IH]ܓIu~ىmEnCY_#Nhsfx"yd6Ovrv-%_(L*c|'4HL":!uGT^ƽT*wĨ#>1^ܩs-c<[0QbA~ޥRD# $W̱q4zKz +₴s>>I,~CPO>' }eIgsA2*/foX7j$NW TQ}V\r!AN\Wi6mJ#Ď hT0%<;,ϮY϶+Ѹ Et a}0m=)ܐQS<|m:f;7N@_HLLv)2%QYZo|d?p6<_Jvs)堀$i%Y}p0eN V(Ӄ` @--`z|]؃w1O| KЄ>o:dH'L '$\2F$)XQ:_Ct]4-LT&98Q"nmd\ϒg6_hdHzkFA0㷲`N—'.DD0@u0[ԠCr PHKS nX"WP$a6uId0\ @Dl**uMmd\d4{nl(l&И]W*ͯTRj\ucj%"vȡEEyc  U=9lg۸۷SnvǴe RsLcN݈L 3I}&$E z)CvGamy){D"SYqzOqģz " A>1S&Z9mcR~wFYnwqEKk ihc|Ҳ9M$j`MQP+48Z\SR7fƆnώ^ .I%ӝ0Eyܸt1Ҷ+SnU(iũœj@9r}̲YD}~2 $hϘډc[7PjbΨ"|AcҬ(6}P03bHs>ٿtaHC!}F臻^aGCTX5 | 2^M&\ITXör 5Usg}+ꡳAb3 &X3y]D`7OWd_lf|'fqb Q,js&H#))qF^LR!n8F f{W*%u,5H$BaD#5+$:b7jg.7;<(YvVDq+yCpHqH%Foк7+U^z[EZ"0|7E%9PGh|?#FjF]zsBMş"Gv\eN9P2v{\9o!lgiP%3(aK44_IJɆMYjTh_\{k_9K6sjQXqxlncV v?HMC!!'gxyM.jc?(~, >"Ds7~ɕ Y=0̗ : ꉨ%)Jޭ ,)07/]MDGհr"OIO^iNc卽aP.\q-8Vu_ z)?ʿ꿫g4vT0UUR<Ye5ܰ Tu,&̽]h+.b+ rnsQ˾Xuȋ>M,h~#O]2|$d53 ҠƸ\l ȱ=?Ã=Ԏ$x=l4ϙIi{J~RAVT SdޡA f.V[`Fa"βzsk<+š/׵h&i/DU _ɳ'׏)Zk%<VDExZ'/exdN9C_ɡVm(gt񅺲R6,(M' :EBj#Cubᱲ!~DY΋M9*:^apB˰Z {c]\QΙ72aV^\.#ƾ ivFGN畋\7DJnxkPuuؑAJ6v}jj֬8BeC&PhR jÿXB(|}! ;gs l h777KlݘScKػbL_|b0ّsa@f0 }f2X@zļ3ČfSԎ&Y3f=O8w̅flGjĠK:>#Q=5|I&{z󑤌G}R.W bS.GfsG>;%˔)4E$#:"v3${ﴖcy"S Ν?"8z>`^OGGWO6pok狍P !*u@:ʗvZ[OaOYާFĊGAk%r\RBSkۇ+& ,K=Z~31<쓹bC fH'7ıT"O {3J/y7u`49ԙ0[o'k8v744[~ ApOEw:]oa˷|BH;9SM[ Xh୺euhڡH0r{Zm.lٵf$~. Npz5 3n&avo1|4>.Lܪ՟_y?_,(x|@0(T_ wGkh68m9QMȇO$1`m連,n8)82Cr:s"DJ5سqWm_Y*Cs?*Y"4"ΛS2MA'^gㅡx.3r(mp]/U"vj-%:WM-U|'Ġ:Uد[MB6.)cB;7H  5\6VxLcs d#jL&UyzhepԳ<9BtGěChYq1BKB uFj SbX"AJ-~; 9zcjQȼ'vn(&& 1&k ˘=CpݳtnL`'6 k"W13;ŋ:xne1(|EʤvR=W(5#ELp֐zpn};YAReM C:fB#~46 ;P u *=fKRc ?qM-VZR ODvyVX5/-h,1E씌(k VGVDxIq? 51  Gq8 wv)Hw13W)4o}.?1RxH0pp|TY|>;4؉ Fr 't0I߁ FJEn q.d =Hsd[.4ו5z?vt| vQťF0-#Ydav&ċ>5kúRpZ',rθ\h„1#H8zY}Avj-ʿ%7GmtC"`ȦQB^1υ%d\fHkk}s9%gAw,16W'ɶ6ېcQuS0\HYȔ.8"a:8%!56)IrMJL7|#)~5Vbb])J $/Ä_T2 Pbs[) !~cfW-11a>T))R4G6g # Ҽ 25!trtAe1gT NLYWRr"l8ԇ MHR+9!jެ*=%k@ Y~ bt%F)A\c33b-̉^&P~kۚC)1ŒFog,4c0󚩓 OADx;Hv#wZBXԛS@AF|߉a9eߴn߹MXcZ#,*f@#Đ:I6Б˘zH(>Ha:6pJvm$]ff!7-nv2hIyz2]@E9& A{d9BG;.E+ qHQсasxP΍]}r K/H/B|˿`4hj{0 x<1 #Ո&h64Df1h?umbfݿw9*о$@[G m}GG7F뀋q.:߀tk p<lF⢜ :`]Gg _48;2L||3#^8$mc[zzx'`?]볦AhݿDEDqMx u+ba/UV9%tnb'a֌H/zb^;@^oP!IwY0A{v: sʁ[(5(d6h8ǡ)!f>(۝K.ָex Bgi AmQS&Ug%ތAv Ǚ-|P@dYo\͉ 'JXH 5F.8kae ,q t\"EIp?7q&_jk]辰Kf&vt1Ϣ潰.?݌:$:)ѕ`'*8fDX`2e:w%{CzuWRs:de17x3|FHBkgbicc)llz3.mWm ɐijlH5,A"FE0X}StqH!zۦ۷{!\h]hDЃ$wG _O1^=%4|(T46Q1E?p2 ވ3/A>Tr/guyl8Qȱ 캺?6ABc~pA~'0`hlIK:wtH o~(aH%%` A [bɀ%1̽08~YD̘=Wyvx p %폼{\RDP[z>0y1<_|@sԻxw-gX31g|2$ n[ϥJ8 ?T:5Fby/]P#=:$pn e|G:VDPxϴS8fkk) oȞ(Ճ|r`x2ihK#HA{VaAɦ7Qhd+=dM Ҥf[_urX_"=.w!B:A@=Nd'QֵDQhw/'[]b&Oɬ"ұq v~|>VKLu~^|cߗ%b!6[ߘf^̽\AؙB''voi,χP` c7HEu =  K&4r즃~$<׏ƈz$1K2roy3>8pEa\M֎#m z)TO{Z7:OEanGq58C^n[+}#oLPM=s6N@]$HS/ƛOaiӰ y8(< iٻ1{MdZmIqK|u';{w. :meM 34Ώy\!rwEpG 3i,)atLǃ9ѾOlncWccqfGѲ5 Gf3:w_~N9fкцηs`Ԧf/,Z)΋`)= tN7}N1ba<֤\T.k˚$t`5c_ fW偋Zv I&;&uJ:"K&5 O*M+gQTj|p§Թ+}I4mg:5M/SbGzVLǁn1=zze'"牝QfTprQNsoYOZje ƥ @E9uqȏ8|4M6R}hvG9By;碤c0V,9ܣ[6tG'ω:mx>PHwxXۜ: !n0㮬cTS/^G$MC=4H47]eհA᥉U1,޺!Z&n¢ӑNryoOټ8ֻlY1ܔDLu+<1pYdcb>qAs$;#sRͼwW:v#㞉-,1[jfdo<o[ZnĘ6㾍:} F?BjpOD0D _fE@%ZMWMFi4-篳9'69>7 #j)~ q\wd޴\Y ^gi A+ $\|GBmh"  FkV[Ec%PhtXr C9ga[oFxcSl<>lsKolg0aJ43CfoF$=]&7>ͳhQC^.-);5wwAM Sl2 A(+.KI >"@ǩC'$Hu#^1OoK!U>nuyy!!,.^U@xFx)!Qj[}3ȉLZqs/@,G?`:Nk #B66A5?3*NMjE'܆(w#rds\=cR40dowGeW}33M# ^H #*nKS8CBB=O7HBIs"`g?F .-=bS|6޸8 È/O_J&Y2c{aexb<&#Q!Z^,N>gh ' 鸑u{6ZmVڈɩcLqeL'*,(blR6H2 y=9|6{gB%w,JCm{<<8߇u9xz 6\ޤ! g4.{J^lA*◌R: ڃpG<ᦏgr۞OߠX5ݞbTr^v-5GeOSH`q\Dyr\pJ*|SSrqYIbLFuQ!8W4zBzyY=zuT0v0a4`0MIҔ /ͤ'ZqpWX.V" z`D8+>1=;zRTh$ RG5vF:rBnz Ѷ 9.&kܻօ@hiQ`W ERA=n7#judAB4- >ۿD) BPt-}5u^ҪK#;aGvO;7[2"id[;BͺbSMrPD0 @J`bj-p" 7`_8z.!rMyq @/6c}F8ȸó*rFYQZ/* @xfwҵg}}'woJ3 [p X1Gͅ#m~Q'Pћ i}?LIeabQ+`HZ(09Zw4|w"JpU)7Z7Px!OĮ|Ķ<2xCM %i=PLjt}5Q)".FHQ;$՟FmuΆ0 r?E柧~aڝ$StwҎ"GMC_Fw=Z6hxC:!$3yn͖ZPzGv^E} ! ,c Wr8~ʧv8U\s3k6 [ TJMvۥU/-2gµ^&B)(yqe{RcD+ݔ TVCxe%Gd~KG:(dP+:r=.xñ"_*9X12dlB^)C2R0t+sb@w{;Aԛ4ulGhet(k$xāu^6zCS_ 4/HPw">+JGT7T>t/f zViOTNC3HO*]]dWF`7y.Ƞ0Ff)JAIy`V@e[0CFE ̧Fъ \D?~[^\d"ѿ2vHqƂd\;HRχC"9lSϹ7~  GCdĽ"Ɗ&&}IqD.ӗ3<@^6ly4cZD  >2?x u#2ddǁMD=gѐ  ZJ>4``7 8FCIA,CnlJBh9&QrJ䞠=H|sXTIC> k/0GbDS{n6GiF{kG?̳7Dž L/^ŒAޯg?.?{ (b}J+߮-|xMh`~EbjIoĽe$kJ&Z^=6DXGȉ%rã(ӿS_#}հDܢv}(y E^#RC H$W5{:ׂ\n ;Q_dap^Ѻǎ:{,L-B6&I/7@2_dwse.:6LSs|X0^˧C; !A",:ȏ<mbSl`@@٨s۰~z@9"E% D@ TݬImt݁wl,xǪGck((s:9H9)Kh4ִ 2 ̀ Lp"!_`Z4b[;ALR@( q0^?dd:y/8c?;lN8o@mO{ ??CgSіŵWe>^#a/kOsrs';q |G3mm!f޹>" iOԹqI/O~?kHXǞ(-IՏLa9d=%2 qBjRMM>kshx,qC sE>'-CuWh9}\C\kzօ?rNUw D?[$[TH>:~=^%ڗ=!,AP}0_uc1>fp4 ) 6B[? .ٚ ,B(vHWwqybȜ$X- F"S7ɂ 1=,<á[`J,sX*44Gƣ0i\&*H8fF`< @IHXIJW۹OG"0癩 =!cX$(}M UHh1K qA5F_CP@^?%A6Luj>ݟ| P?-GCP9KAYdbU5DA z <*"W9;N -tIsolklA]ӵcu @wlk2u@P5ERΞ%@4@'JuU[)|-U;DW.mVaY QXgrԉ}a(=E` ^;(Y8<*PGpc;KHtܒ30yW6L`30U9'О-d>U'TRS13xYL[|B TAB6аgW$@$o!Aڂ7C$HȺpE1[Co;}7^cAt)_|Kƒ9[ſ>MVc'WZ.cm:cRc8 /[YE]f0كDp뗕5o"wbh3[ֵ 5*juɷZY03T~kȄ3&fnߧ9PØ˯\\,?9e F"5+W@ɨ߾ߦA mI,wWضUU@Ta;*@h)*lv7ߓcBC8fO_fOJMRH~Ӯ]xa!9, <=o /fᴍp@#ligHŤ<ψE-@-쪂ބEӬI9b ZV$A 0f%;ik;.d f0|k1^yIuҋQGf8ja!FNU)jb!+ŗ '|yj Xc3xNSSK uzmu7Zޕ^$,\fL"1kRIS#&r{"u WRA޻x^aG}qwy<5=)JB<+4כw{SD-Cї{*rK\Pzp8?hm:z0.Hw1z\E2R%k[r(Q"wOU5ʵ4Sǿ;,\CK$n.m-95԰.^WUMJ`qHuHVIqx^) pC"+Tݖ#̮RB< nP C-FLFAn뚻i+S#vF:#m2%GXt558,0f (4;hFܶ6Ǹ!Ag@JXop~=oa~(y#wgK?.J7(2|̉g}xwǏ@Cp#>umb1aDÊ`GK .. J<j@`Y,8L?Y.VL;fO~=# #ώ:GA0` JIKnl^Tb!HDh(1 qՁ9d#:xcHlH[:ǽaCyBa%a7*wu!\^cBp:NcnN ޜ1qts K#a҈(,r02(03s#0w|T.%Drě}:"04>y|E9}}9%|灒'חZl>Ec^6_m=- q&.|HcqZ _hhlPEtdfqhFnG3y ,Z҂T[d*?۸rf^kߣ P~q1Dz˸Ea鿿$ߓw6rs/d'C3ǿ^DiaN8xs2sCqNzõv.{: _쁱gUx6]z7צB]'gg;hh Id$dX(!3ShѶ.N&̰Muy<\捒MI,*ewnn2 D u1u)Fab5yuyu9Z=dKīE!_#ZI pe [J/ M胵B߂,sΒ8;Pp0U{o `*h1SͰhviBbp[lDAd@H ??@d!" dኅ !b f$h"~#n MI}!5oA,xݓ xy4yM^xQ TyŕA+G㐱ylV}%3M x8AO53J+3%h Fd#ջ ه? Osr; \ GdsA{$~>ˬb$s ݵ.Fg}93GsB%EiY8NG_s[qOΤB^}BCIRymUߧ?o}cF끏俚?GF׈yރC zQW+~~is-Ww3nLõ+G55p&ڋˍ'6Z0d^E5nENmjfY ukXl!e9jq9dӪCs U1DL[ܶU>"Ph2m*p{z">]i'.~K)IGY.,!f' CwZ f%;>,~hᅬ(e7Z_=?˞U,2us[ {U S[Cֵy2nypzypYw~sull}ܴmc֧M"tyJ< gXBnT$("2./O04.GcQZCR ϶Vs&$4Wl}p oN|x0h} )+t.` ր=**(yy$}U%QfU|Gc]}ىPX>s-TyD {.):r&6:p"&pUi7  E"ՁX#!4lVUM'=o <=Mﳿ>UUיYǹ<M5 دTI·ګE۹̖B7C:W2԰qx%Oa`_c;Ax3?~x?$&f\8ul,(tDHh =HýS)oG (~*!ЀBD - BiX/ܢ5U $j:Y!$5(rB@)I.ݍ6&(#3,iFD//䫖&B`>Sg;㓺u$ )LO:Gt8)14#M@-GDF0&0QۋP6vnF@Q.mOmU<œx0VȎ1x!0Sy xd7H%,kc5] 4$>d*1"MKbM~X'}@Ɔ3Am̭-c!QBw>X=2bB،I|N8Q;wnDr7uSѻu]X# :ț:Tylt<s`/rrؗ`VB:!|_G듞1N%*׍ҁȌCHSFX`Fᆬ24m2"AԽ hO%-@u :vd\i@5I'-`d#etZ0VBtͰȿu ۥUYX͈. k!3fh$? DqH*3[5ѻ*)tCL~+w3 ֔$E: wX8X@$B:§ };CA80,˺!{񡦇6hjFSbR_Y (b~ʉa *!T|Ddz& *s~A"foY^gӝ8D 2Zev@r`!a&( Ē*  :zCƑs#CgCС潈w$!9DM?f"A0@xiHc#Gog$K}=xc (&0`l`::`(F*}.VQoz#)(^G"|&Z[oH/bR]W[{R6TW}"duQ?x?<^9**"] R)MaMiFͨ&lfAmjffi)! % 'ߣL%r 3+ ohϩ AXnDMZ (`+EY0*hv3b~2/=b֦~s=]ta]HPOCwУ|ŋ$۸cpvV` .kw^Q::O2p@+ tGA&EH9ErGl^ g^DJ:LLcn,@!5U2GHO㲒*9!ymG"Tax'fKghsG7cNLqnK{ 6= ɧS,7LƸ1_q2\c{ op3x,_p|)xuWzutl__ZO&+*hOahnwwd!r4*EI,Df/sFd}(Xat*Ӵ 72߄~lZ8m|&4·vUML.\б}wƛ!icte*&v3?/A_OP=j:R1FA~-i>^ovqXJX=; w0wzKDP6sЗ)THe{8@c1 vóꂿ jabct`F<8@Nz"% V1˪^7mH%,ۢB'T̮+6mx"F`@b`MBn qgl9sLS];7L n+ϗ /~ӭX`ϣ&|&<% f7b|jnjLhx6-nC$;d3+JMGK0aUVQP 0F(u,#FoBV" ʅ_=>` KI^T=Qi^tؖreM(͈R}k(7fhwh]vg\݃'Lf8"@N= >XR+5;n+X~R4=Y,1]57D@qֽ?<H pcˀokw \S1?U++u@oTCdFoA&)]NgBuLl;úf6>&,mփdǪ]Q6upșU^9烏eٻnm^<:=V$RPIwowa;7)ߓ_(( )%~ڬֱE~4YtfRZͩ?ݑh&jܿ&]|^U@ƌf'tu*\r"yIĆߌTS_nEmw s7'!6x5+FF܈z*cǿ|0F,H 0dHDlޠ 0<&)G&L9G9Q,2Zm .C|ov~˨8E+  4vbߎZVhOcͅ-=Eշ_ piY#n[^t>76q6yԡj i̙5A9k*2̎@9]W^5>ϰkQlewh#{ Z<0 D}ZR_XoeѭވD_Sn 'm41M>$;7?_8=q %?)'yxB;Hf]msjc6,<r11{juEQ'z\]d<^7]jp`Zlumc3 xHL'8Hm# 7>qtt0(0sN  И&>9.̧h"we)S8Tj6CS95@˂428[OxqMNU719 m47B0H@0ӃfѠehr^fD hg n j?!cd+T FFәjZ½16L8;b`{'pۇ `UPn^N$slԂ k )c!Dv MA. 8`C g4 Cadw>b( ڍZ ;[0r\`P#;pe S%6Qo $ɋTf0%&8riD`ttqAѰC((@\6BSD0@* /&ƚhAw E 0_sQ bQaCІ bC!67S &#>dl 8t#5)R' ?@iSJtÛp.$K$A76G`pXU$5%[ p]LY541 abcV - Й"8Y5"X6h%MC3!.0ҍQ*h0 bMdn{a#F4 @\D(2KĐoZA@Xfr56cm&fhQ!f. )KƉWfب: ÌA!"tJLaNȂm*5%zD!d; 2f.AVZJ ^ B%iwR 2E軛X'JqEp; ag 3E4vNp 0q2)Ycř܀Yl `dn0C"2f;˱P gMA4v-44`l4f]`H0 آi%@F(,f@ikC !ƛd ˺4c 0X0pBŎ Jja88h .5:.DF @ὖ4&6iZba$X2B\!Rq @xQ-f r @vou0;ڶg, :1i1u,!I3Mk&F-JK ip MP3:8V6 A4Set5M4%MX 8El(LU)Z-2 grF0eǝ֬Aa,HH9  a @8b E $(a0b  U֖ 8"c lKUt`5e7SI` 61 2( iV=>'!Q0`'6hiyƐQewڃPbR [m1,)Z*`.`D:8 S)VӸkC i@4u&IHPLϊ*u7vcyK)?QE]= /p[OcU-߁~-,cS_p-] `;0Q=/d}|i|@KR1Nhmc'1R!Y>yQ=>=֣%X8`|Aǧ@5?Gq`o֯d33$J<z|%t `6^G+;mtWnҶIVnab#HҀLB۽יHQ@2%~Q9, $E}!jz Pm!r]c "'[9T+PؑQFx Eq4 ͗3Q*Q"0vp\$5 3Xk Z2p<8`9W8KqL[`ƍ!*ȆPm 5xtcFGC>A4L8r`❢Hd .4 {K f>ʖaۭhV<{Dqd҄bkѶjx۠hE` "h`edDiݥ2[k!{) UgttDHk1h57hLyzʹS]^.'M1pBg@Tvbh՘Y eq"dއUKڤG41%Ʀ}Zt֩3N[) 5#ZFXePmѹaؖ[nkoNՓPyr9!b'a0 FDJk XIgprrS[ re0I2}[fII11 c85陲mr VH(!f1'b &4d'fvMfم$1*So T1b 1RXÎY!")SV arZ&H@. i;6AZn TNT:*E8[Ae=hfk_Y-%5"Fi}EJ7ۑdXCItʠfazFRMyY$}jZ(W}UeT\ۓ92Bȍ4Sxi-kg#h.Sh*E3nq-Dh[ۍGE"I>84b)b/PE3IJ @e mK]w@!!HǴs&MqYhѦ(IssF;t5l,tOLvL铑ZA$MdQFN˜vaJ[K+%8nolJ_P4<4P]N,?e/b $g~?&z;q<8@`N ;j utOʺHewԌuz+飈Q %234/K ŸWa.9И0!%eSXs\UT7,%.#R2W00#,B mGl uE۟#Aa}P.}X< CAyݕK[*HĢ>;k"?Je[LR#!a$"e9fC|LƱ]67 -Nf5BdX:i01C  `10rBD=dvG9n2?^"J?C\"H9SbZ1Flf6a`P'b&yo1v#-cI1JH)D9YѭKtAӷ -,R*2/yEP\4ɍEB6~P珎d1oAFc\L Cqެv]٨G2>&<@*OtL"L^wNyhpz3^,IX! 15A)s1N 47=Y0k6H2Iɴ&;deLe6UJ R@ĉYH-N0Hc!< YYRR.B*$ b9#RF1]Ѐ bBH v06)iQ8Cw`zb0:tЃ`!db<opAEPi{ɎaO? @1kyRh4\pmM5 "7&ШoF@Ifu&N0Mx6F UC .v`$J[W `FnR@ m 2%k0@ƔNYߩ4H l9zyH$BD@0KBBL"^bC` 2p7"΁IqwD iJԈi.-g3%IJdR-*+&֍2+<2l r{X0F ѝ{?nh&c4pjadhϚj,U:ꆧJA..F s-A5Bmϋ@6R*CB9T> hCkm ܰ{u6jt,c9lqߧ^;D "-N@X9`` H܌qNu1HfQ `HXP%#i8Cq: \f/hp K*423"C  GA-z'Zj7])lp9xHpfj4+[*sSip{ىA6)l ":oߛ29rsr@>C^PDy4DlBH2A05Lt μNJ؅ ql0 ߂5;Gt pC ۂhA@lP.]@2h0۾&SL(<[ $m=DL5sO-Cc7?]x|߇XXb??_'?ŸlOŸ*{}U>AuN3*s3_ 2d;sUyP˨~pKCacx̚J π|7ߋy2J{.,Gh72ś  b㦛 .LMԣ׏l#N ob&l.>1I>k3s7eU!qsL1A~$E L%h f&m)hB$8,*rp6KGah4Cj?v"˷@kx@BAӂ:4$wev <޽ ?qC@s %!(^IGA J@$ <0N`)BkI-Kf4J0)HLG? #CHXu`]ЉE<[,[m C uȝ`\DP 5)bs6 0?)C 0gF1?@n*&ّ@@j V"F! $XHFDRXI v* kVήCZtQ#x^F7.8Ys"Y=D!6 CB&@fU"`a 63Ys3A, "`0< o1{$n dTd/ ;)X=$D0q ,WxFAqz&)XT+f@ (3[GFACb;8چ ;,!qi|Fo|a8J␸k6"= # y,;0JPʄ BIT&OSdYqblJY.s1<_H)j)hB$Ó!ݓgxQh9,+4mٛI(C$^BY} 7 熚Q!!YV"=)Sъtإ9 j̛$iiݫ9w0l|Rl@"wb|W{,W?@AȂ@TmYjc'}/b@;U +b~SeFFo䣍qD '@Z&27 ^DJ @ 6}!ܓp|`~j_4$M/| l&b2'{9ETn 4E0kUa ,tr B~j X&2TF` t"چ PDmuyQ!'I@t@FR3tr\3 pQ,2D*Djօ0ϲL{ovAX&x]~_fF)К4GӇZ^쏟<'SCl;b@0 A0=n B @*`%s=%~FEf`~ zӯ aBl;D@,P=Nf= m6o] R :&B q2ύ2'I$ 8 @9NX7#<($yؖl$O\l8RDyGGsC~n,-mQIh-$!TDȭ4-.MUm/ּ:0p̜2$hX%T.6}!'9 `gTKc`   SIC;3CE@ EԈ8B"nb! J荡Q0\ Ԩ;p2*R%dAMR.#Ň!-.n $ %]%j8rL̑$.#Mf gq4|zK  gs& @ǐC 5X ٙ C8Nxsbt{ dᳩFLܶ7G l-daΖ{HqP%7(*'|LwOWEýà/dR}g6_5mXp4Awrq7;UGóJ:D+QSˮh$ށ/n)ع}tt? %qg6S$JQta4eATp˽*zJ.6a.ݣc "$k7 1#fZȀ-2584@ 0;"&  (`guB* 0Z̕h! "dp31ȋ H98'~"3BXK??g7)Eel&ʈY &OmҮ-b%2:T$F .\ t{6lT]?'rJR`5NFEv(P$4P K @|xOD(KqreT̃ԡ/r9듑ppB킦àAr݁&d7tEq;1N0;+M^{9UNZ]L!) sZ$=i@yrd)|AC*<1KC 8fM:#|[6X_6 tc2<dHrz9(vylU`1hZ(ͤ4D&% D(GwmMT6|fG'4Zܨ\jA&ټNkfmˇOzŘ$6$3_jJwLJ )8.b: `4) 57v5ӿ wfiI(*2 \Xh.;)HI LKmK Bp!@7tHB\23d*͡ē3De`ԓ!B(rB֛PC4ImAm6ad9 £kdU$D4 、%Orc <p `vgӜ#{{,QIw՚pgTU2 a4-;-w.4}=ǔm0$IA \$ wc)9EڐVFg&C(_N 4br8M3*N]=8BsKgP;C1AvAKe ucދj)6N÷2Vx9)BC̭)vKpZH@ȳJ- >M>C! *HL] dpkd`DYR$?Jhěz?Nffߦl47A0ޠ65ѳm#i ϡ3w#B.9oE` Tj ePvbזla&&l-mHK!=y#u~7kodkG xn 1r(f"ਜ"P;M,y M6k a]3(ftL*P)1)XE.Ρ՝LQ & BlzA 6 ).Q%@H`HPha8H=$fbeSw\Yi6ɵs-Q0C‹p68<}-B|NxXD@긲=܉Ӻi ;%s:yv9 \0ד,i+xe:h:$:l5= E{ޙ,`nD bX ݲ|{ v2: ֊Nd0jJj)A@P Gp82l!hiCp39`F39,Q"7TOtđ3Uq5#35O4,3F. J9Ԏ.qprOY>~_3rs? $!SB &h@?.69~-!G͐IfID0,,'{oD"XPJL@B@s [C X@İ%)@TX9 A3İV ( r"@p_#41At& NxIDBވdHAK!=v4&677ty %q\`lNqͧ8opJ(!ny4r6t NS PpH@ M+BUT;jpӤͤ3 wQO/],FNOA,dyP`n<eq;N>oͷ'b3FCWcbdatiA:l)5u<]."Uܼ0Fs{&k۷'Yݥ 4DܽLy8 jm9 !\g?'itTBMli*Ez>ǪsǨ @t$I4D"'q;I/эXfX5Jw(TJHi J w/4/ۖDū-P5Mv]b{A֊&]ˠNnV;Cv'*p:L;d{YE+X?9St2JV>%l;P&BνB y@bdxUDzd@`vKI>ߵ3G >yCdg,#RVf2?C'-]l:`_˨:C~% h,,' E *e֊A $u;@~~̓}k g_6:>Pai" "CAو.bt*jU&.' ~P(  `B #) B"x^\a)0lv {Q׹ !~4~l+ ;a̮R94`o_& y8mȌD5PE+|b5Eh-|\~V~tjw0 @~yRch<]f?@;8~ _f_>`jfy ;-u)v'vL:& Zei4إ-4"?h>%罇t")J s>v ,Gibɡ~L0XPd"lz[5`OA_0s~4J}!7_n,UUI/Ĥfl6R8h{@@"k3ȺP d $hPd j XJ r1TG`ؔ.q*ҡF8Z$[$Q'/'R_q|%HC44(I/KPY(a~c׻8'(,.shӣn !1[q?g dXI("˱Oa >aV@'qml #Sb+gɐ I$ .zCv EIlҔ)@w$$L=`8/6ͰJ"w*g̡qsB㯻(^jzK(5 Qo `Y?d$J G)v=~T?k~( A6uc0OtY!k7ff` a~Xx ȴC(BuA(H X?F~X|Jٟ2gғ"eLJ{_pFa"1elg9N@/ ~ tm&z./֘N? (5!Xeⷆӟ[A\) E"XKM>eI)p#3">v8MOG>O ip P;7C~?LC($U_bVSTSr^PFA' {l 57S9n=dMwA`P\1[gi u %nʓ1+Ƞ!Y}#6gc͆&g#@XT~5o(U+2mXa ?~lBMjx>->8>a3uof#Yx>h*æR>M j2[݁xPZ~=_R%{]^pL{p 3}?N/JF'EKl_O BiϜv(rQ>Ib<ӎ*ή>w9r7ygֈsȌиiu) ܱ)RXijR4!rU&DoI$])1Q2i 1|h"``y"8"~ Ҏx4rgdd˱}>*a$7 @9JmIuojAt&,tud*6@A { H{%SB`ED&'=\.,PD=5#A!}Us2,$#ڂG1Q:̳XE.FQ8SpG~ A q? cN_~8@6?<<'ၥOӆ?0A<'&ߞ C@P#Y0L箩|Bm P/FM@ՁNf w8v Fş&@ 򗰏 IoTB!${D@aOhLP J?t"ch(dz )yĨrɦ@#$_;~W&x|Ǎe~;XIaހ@uPUM1^AgaOcQ=_z$h A>c@*2WupjLy"1dl~"&áM_ ~e>h{tyB VZ*hm-[zjKt?ăj@e9ʄGE(OCI gyOJ쀼 JpJ0((*0ĵ"ј4(bb"rrxL!21 LGL$ DS`Nq ԁMلf-9)vD{s5'B>^T8r H1DOn@{ok2:|`4+SI90^Wأ&#$ VHyHOZ+ڔEQ `}i-Sk9|dZ um!(7$1@z~? @zcyc9¾&!CHzY!T1:9av%T:4kR]JKeJm" CVdB !0U*M+CRUUF]^$^OR)|8 Z&X%g<H |'=/]rߝM<G@UIO}揠7PP;I֮A2E  춺NT@'(Cr6!O @"")/Gl*1;pс$;9BO T@>%=~dH>cBp 97^A1a9”0,.Y:@ŹL/u ͫoDn/&u@H~xcbCCJ n厧RAJ3B>Q>ϸ͈\*_g'یQ}()P6~?J屈H U/E\+[[)$&V¬ _01did \(@~4ӀK~F H4=94ZwȐ9HGe|&: 86bHP>21U1` 7?@\Š_n/|m ^Y0PO*zG+_?5>d2>)7".d'RP]ZD^dtC$y'yr+rd=>}ϗ% !`\2)_(10B(-SSrc_Í# a n3ŽM4O ~w bM#`k_xKX-ǏL{Kr"rfX l'C |X˟VE>vB!ԪdmMRX*j,SIT%~TpHe=lm\![\tbGX9JDA,8~QC007> CG{zޱ(=ZeCtx m4׀`G什*`D@./ >9TEWʑ`@A~i9Hq"QDBP!uvGv|zD\鳻T7@oBwz4Q,.h{yJ, ,XP,2Ȱ\o1sXzlL\%?S 4u>@d`>'&#_@c+A!!M@p"(灹LО(限L] C"0w[6 bF l^*](0dQ^ fx.z>yAm_EzRcP? 28 h_0B L3 CtQ?<9)~n }f)xD^T&('!z=6F?62MTJapqE,1Ya}-`\`?P'_l(lƠ33{l X#:fT^>tB6^hg+Jf1ڃ;R8;0]9bI3"=A{ුH`,oC"r͗<`OݧZ#?-vm,@$ z:ƀ=Ek!$88 \tԊ|s`#7 ;00Wr\* fDp@AHHv2:ߛ ^y*c%mX`ep9li@Ud": &Xi{!6۶v_bP|b,HG*LDK`麅yAO0F__J/ί^ FIbf/?TnyvieOW/y舿I2}z̥nފ1BI((D09CEؽ?MlAΧR__ }; kIpP)ATw`]6aoIH C||W6T6`be/ [" ! 5HO!3l *x2$-din4 |&]C53#® ksNfeV~ "Q1-DZ)%qpҚյp偍 %i@Y)CjDqL1UU+} qm-!uy 1bp$dCVrCGĂ}6THāPXi|%[fJ& thcbvϒjw3rk@0d8z5_>ֈcSx5TqPbHgTTWٚ@9CHQ̕e6  BmA^E avv;R(_c `v ha_ :Yꓺ3-6|BjeB {l/yCHQ½`js8p;HJ**`R h|O7ix#Qۙwaʺ x+["|wy鸭.NMƧ3chI4W<;pN} 9O3tVM{?2!sj1{tB A\ XG7% .ajo7340dp'f S:Р Ef199!er;t40c}Oyӳ̣' Ȟ1'C(^2 a113aY1^#/`9⪡:Y7 `ƃ5"/Qxh]' >ӹwFN@Jb'PpKy({fh{0"r鄨E40iʏ֪(T42^qev|Hd j4qdC1  %Jr( =ژLuAhm<rvCjh)Q|mU}괵sc@=1!ɩ;[4S|{^_ &QYA^/kW.V0CK)A v*wMW}˭v{e?Q$K C9c2| ՛f:+.&4:ȠrB0q4ю&!fgS/9 %Dͼ`RFʁ h;A"rbZuJQ5w=xWrRBv[\f(f hݣAj?V' C`N@^s 8L4dOzS vN`&4Be.b8C ̘ɰZ֡ڡ&P{ELyoFI>IOCPF)Tx(za< @x)OJbC08g|j@(o'zJ7S! {pbJERP/^=ݧ|3%OoZn+!.;!AQF{CbCfdBd$i鄋k4ҰU(l0H2;P MChA !3l0W1ƌ+ J f?L~"C!8iוvCL,TI]iT;$bC)H >fZ"QOnx$G6ͥ+kbDA:p4Qfqp$pj$h+0مƆw >F Ac6 $iڻdq+$e[ -5ΐB*DA `@!FHD ࿪Z}2%K) JVкS2x==EE ͟ UF݌*!mM":ƞp*`8*R&i_K9I-"!!lVM\푮&GUR&\}a9!Pކ0 $ul6h^“hiL:pkI'\L5D3< V-0# Ir;/a y?<r%22VGg (صKY0;v8m|dkctBQpbIL2QaCLjX>G@,'f9D@TKX2[EOquXc4 -s9K?ZTT Dt2A|\/,?,Z  00 p!rmRdw,MYM ɈvTMe㥴S̵hԎQGEKD'hCYADV`dEU%HHiChM1)Bc0S H0)mD2@ 8Hd @#u`/h h֔ht) 0@[daBӷ t )L#M}*a h\crCmciR#`47'WK#ZD9ʧ9# ʐdd󯃕~Uq^qJU[`a !7{"%*NDJx,ș }|,Ї  21Hbc1=҂L$14J7f )! $ @'&@AF "\i(>S@䡺$J? k3pq/TDTЄ d)&JdT - Ot}IJ%&}2EJ VD#3pD⠦rJ?6FT>EA̒6'،"K_BvzeǽLEMu,ly 6&3 <3 ax! g CȈ@-7yE IIu@A0/?Ѿ!qu[o<@ A}m:Ct.΂$Z)Kh$w-HL5yv J/7!($H)1A0EJe[%Lڢ6e@?BD|!Mv6pSrO};Х>@(Ț&ML%X] 4!H0n5)֏>*s..FQY#44B0BhJ<:a2&QVd,`] KÄH"þ5Y4T,!)ҩ3KHDw7N ; ҦKc d(P=_|}e08z"eP|_#Pjn>Go=|B `OUO=d)0yֹ[J鬚PCL$U؍f425+р4B4BDB6gQI0aK$3@ q Hf}&3bcȥu5K1\LB, r)Lf)cRF8 0 XA(k诇P0a(Ş۵k+ӕ.u*y&S[Tmj#!rpe(0qlP|ŗh,H0&B$f1p g%pb th?٪R%Rf%*T/5) kdn&x2SsWIR DJD1^z: X Jq*ؾ3!LvുK]6><f4D@@puA)a0N1 02P<x@ hd T򰆻if5D& ;6 *C!JL"D0 7H(bDMb&ԥF 0*aꉒĆ=ȿ D@Y0hV @6M+S)5QUibTFHPfT"< )i}Ҙpٺ)$3dv/OoZ Hc">Ž dބɳpދ76 HM*mha'~݀uBx2ͣC:"x$S$a׶TpFR)Hlj\A9l!" '_3ER W(&T ~6#RgsbL fc~+ЍIٶ+cr5ߦ{੮B&E+QVƗw]!4Z9 -$2#t~1g-*jb)$$0i8xc3Qa62'824Uuj?S&jZ4ê# 9v}c2.-4 ebء#[^(X 1%[tznk M.#AR2s{hң:z7Yc"L"K[iK)Rgf-a4%Qm* ‚%& zbpjF61 gV9h$s86',2e@y (Y{ 5ka'9 ?`LK{0 ?64*! _N_$;YUL!=h"9x1T(T@pn .vB -nĝ>IXb(:<Q|p( TP~ -S]TR'^Oԓ&М2 ဠbjbal(\j"Ch -(RDQ1de!%pJ%%z.`m2,}A$ц1#2hpŚ#({*$H\:`$T?4~E_A6rEdeLa(rh~i~`RH'IBSy0e %MF0d@n*>-JD<dq!#9{`L{`+J>ff(c@[Ea:ĜCxD HiTZ1Lp0BErCdb_J!H ҄$!I2H #@14?4%!@BH%ekFS[ԚmԮB  \p S  AwPBx">6Dy}9@` A8`Q~H/)@W-/`A!qbAByd6%BH]\K tJȖ`(2 CwиB~!A PdC^ !A PL0I!dZJ$]dB?|䃴Da7)v$GPH/HrRb1| Gh* δ+D Y%yH bFZDyA3/BCح@} ) 4(17& ^`92.2I+Y0$rGqLB@&9dhxlƘr2Mt <֑  ;Cd$ l ^k.Y b{ P͎&?BǴ0=1@\JRFQp׆ԜOd|vhCH=ђ+ 8'iAYli%/8X1L8e}Ze0uj.L(+JEj!FCA2gʽlh3u:k)u˚?}i:͇NJ"u ; -&UQ D XWXCZ!V b#F F !hFkp4&*!(1#-&TʓBr7S~!JRHRFHHxhO k߈~E@qA=4O<6Odb (a#1@kz3h? CeyIўT\8e:0r_y 셡5'&hpҰ'yy@*9i{j@ m QZu@[KDXXՙ 7Q\.йT02F:a Freκr-퍷IyyHI1jvVH PSX`4"t묮nTFM($(B cAcw@{n!sP~f ` ?ozTyH_]˷0,_!b-v&Hi)9RPԦ*lUz#=j ҨgXHbEw*R) ]Tε% H|z COkn'JyC(-qw'Rن}0"f#]b>yjOoǔVHEPԃ!dZz? Qa61E]mC|`;p$. mf v.(C&؃ԃ9+A00` F)=@ a,$(vV́oRq w [MkKou2]2ʝBm %ssnyS*x_APR=x\>€ҟmcb;s,@N-(>eSL2| b6(,np(Ch rw$v@`%ha#v %A%;JR5DH>~!~? gWXNWzV|g=:V ]"|0Զ2$BuH@P#"&\| yO૛m_iԷŮӁT:0 SMb)Yi(uD*jbSJFJ̔`b H&BMBi9PacY6R֝7KUANKV֍VJsWΣd뮱=n44WW*+ٳZKfW.Jف#bW22$ UlQ((T  K0 0 !$`"(lgF&)S1} (@:a{%x02W17?)ncѰ)xCJ,%9@nN1m&6öI4LsRve7UֳZZ n $1b5 @FFh4Qt{ pM$78HKbA0X;%h赆oV`>ڥ[B l33 x$ܓi),Ͷ?l$fBD$  iN (`$C . %3V.ȫ $ڕQ mҚZv X(+XRhT#79i|IfQLhr$LciU8ökϣfq vJjVY& y DU6f+L-y+T4jԆ`:R n*؝DQrUQV%J^P' q0[t{Mӹr -IoZPB) a$EcQf2)D %L%W[Ƴ%cCzA0C#a1yM 2ћbɁ f#CI((4bKQC0I]wWݮfc0ʙX@7@oQ ؕ#( 1ofj6IS@F8wAhX&o8T"q,cI0& HV%&Y#fu5]flf6lfu\ӮԷ߼!)4R]QH&!Dh-[t훩Mbi:qCq;{t\[+j*feT0%hӔpto<.h$0UZ{K6ӗ*Ku}>U|w !FQzqhМIE-.0N֭٪5⫩jT0,CȴlajQxU( #aL4e׺76˧H%מ-BhQ,m7FEk603A\hSQZAjDY]fW&bIe{;(ȍHaJѢ4aವf4 DKNח-ݲHebjlW܁//$EW{ux7.L|tuSuڜM!7ӧ0)3LaX။2 =pt&ְPMԂD@k$%:Ԛ-X4Eoki "B.Φ61M:t:$ "gFaobAZVPō VkEQUXչ&%G)Lhie އ3^J=zE VA02D7%AEnsz/%SR0F1d2I49reݜtk%4HkDE`4 bAZV "lôFKr h8.Hf#wI#w,aMMh05J`2:" ӱFőc6!S8IG (1$Km{^Leu5T'ul,cY*M=aa/ T()^j"W3JNf X5/f`}UzJ5nh/d+HXH#/5/&J\ E>R!CQ'Q=:sO`)%3iJamd!bQFd)LU5.ji RiREh"U`zu :#$)*zwi@3 HZ0ZZ#$11p G$,bRQ(ҬPPBJ@IB$4ʦCV!J@[$5G#ȀHiόT 1>G>(!!^2LM نp RsZ[b67X80ALLhƐe ]ʑ 6 hD@m{!qTѦcCmp ɷGwßx#IG<D P&5.$>[{2\"唦l(F3 vV\~1xw!;Ri yY1i 8o49.I8X6}©FT+29p)rcE༭j+%Mh9AhLwNf):={v%c2zN<'?4Pq>YS1Rm'N'E 0^p'0MZMCh3IyԻI㜎:K,/&=q_U<023`j&6 iuD=4ê:L:x6BIJDF8C \"A@ , EPU.GDr(o&CIɑrT6 sy PX za FqD!;̔0M*a`\pp<;5JzP"C4 7c'N z$L"R!ˆdLDs6 jeGc!)14Q9u)S.x+S_& њ6:hxH2dmW!MԹXASfrBYD!C0`o@#(<($67( #݆c}K‚d@{@GO$4 ڊjZ qA##9R OHCl.c&e܎8~~'UД4 drmϻgk(e}šT+VdC)ԮxQs`uEA gf(Ȉ˲\IeȻXyl^pe%jc?|q嵳|@ggH\>NB]{).(ȴlNbO]޹$s9Kq:}K|Dtp7Bخ$Ȩ܍yy!׶Ay)6u; {@ N=P$PN[jŐ@6"#9<cM/6 YXgҒtq),B8Rv˙JmJ|@9"Ɗ0XRXZHX5b5.|Scr;FS a W@A`4t(ijoNH "IF.`xÈ9<6񜸴;)7A%#:q͘R0t(g7.b@Fc@%Eoخ9@ 95)dNͤSz-Xf4hI?OЍ ԇ1cH#; kR<;OHt\Pv"Cxr G۵" t"#qSP^QC& 5sH͌S.9һ" =& % 7L.59aet/SUX\  ;pQRrtНH犍06yNA0A2 +R3P"B$#A,^d\)5lxgOl(NQ,uFTX 拥{oMn63zF[ȬO(Bl4.L="y,`Oxo:o7HQ5ICZHߗ?bI-s>_dnMxa#] 1rôg}IιR84LmsUtC7pi1:o}=3jp5ҭ bUw^Ǘa+S's9\Lֺ:3,JoF+ccq ! In8Jw"&兗jsQ濑0s䂗~`0d5 hhR2(Eн Q3&#Ǘr/j<$cPtl ;87RmV?kfx '-w/~eC 'x['{$"S<*+7B y w/iD2"sn 32r ]9DyQa2A ѣ&)R %xi&5b $5`HfswC)BL&*;,p'5 sԗDf0z[~X `LR9h; li=-תsy6C^hvwY5!%HbzIޏu3F{ʎTnwD6!Q 7bpTkPC*mÞ[3*l›FEǙܪ- 1 Z 'ޔ&8]el8NENy&xHꇔ. c3X Ȓ@sO 4&TR8Q0(\dx+tڹ oB֫ĭ/t#m7O2cKrD֎faѱ*|Rs:"5 ؍60&{g;Q&_d8u!GFػ*4Ƹ!n;4rB J C >3jcc#g6DQ}f;׽; /(lG;Ȇ{&9ֵyumXl3/iz/:2p^P)yaxiІ;gJA6 ƙ)ۓχ38f&˃=`}1F\̐40F{Gt =ZSgn;- 0 嘆b# ZpmpW'V0הF4\X&C' k;Ld-r!yp P;P`aܮ%t1HQSL X eJCg͒!$ :lѣck @.G~V/\;oʥw^cG2ȓGp:ˢ|"N:w03b}s*3Qi2f!f N]K6(q#,}uG9V xmD:k}|S0/܀O}\kM:!JvHmji׳ qeG$r+q._fق7z x,7NHj4hmbEQl5Y3ЃLmS$[Y鲋v?[U ؄U^0\;iZDL`ǘ㰷6{73M;:kdNxxp1 ׺#@P&\;|!8$Ž{cDKumd2َܰ 6]39CU8ܰo y QG#sa`b#(G[TCÖH6T!N-c!dف4UMX|rԦAT@zC.6-QC .'{Ϊ؃ņ&;e)We4co5&{`h0tKS.1 c?s5Zj AC@ȧXTh'&'<7u wߏZك`yjQ ɪII 70yM- w}wtl&YV/}C1{UgaA#Z_7]!ЉJg@1O=-wtքV{aiP 粺<7 Jj0 5\"f cƒZJy"BHP4r .t݂&+=xxxD I CG -0=[BTM4J4K `+#"mLY,^SSD(vJƽ%lT=7>Uɛ%scD[:DrfFvf7u}cѱj|t3Hc%Ձ#H_r$HLO٣MXS4)FwpHE qWlG ti1ˈKڂY٘0EyDi M]!s:kIIX)7|8x|Q^0ycȁ0b<ܷyעDp WK{y |%N\ # o[/[SQS[齷̯)x= {?7@ĹdIŵGfNZ)R9|djJBF^bfEq8 Qkcy7QEU\ I`E&ǝL+|8#H2v7 I7W1ʌ". Lum{<;oȎV 81J5mFK r^^ y#끚e㝰d {7.tjjJtZĴ#TjY{?W_5; ^ (n܀-tvOJ '^NǙ<ōA_τM9fMR2g>y?7b 0݁xg|0he*.:d.1gnH4F D?D1c4cۛ ,%< AMY[h&;hBIۻb_"[Pv2luxRLޒE:sBS=*wSw:; Ӏzκ)݅MJ0]f%$`;6L:N4D;P@F,KJah̉%00H XCP7G ȎɈL ;Q,C ;6`N ?'Gq6 hbbUA$UvLĽBQ}iR `SdO4>sϿpDH R?(y& >0V~2@aCc=^j0IQX==Mdlq _z] 끥TM6,%h2a%Q;"f1#CHSƣ2SQDEC4 4] ArT2@*p01#Lt葊\&CEXk 0`6,I"cxgtEmȟ^gum+3 Ksa[-<#{]؞[zCVO1%*|^& 0}c jDT<ѝË%G1[q LbI΍Q&5#]tF`7чb(\utxG`i 6&bkHÎ G'-^}dy6V5\ RLĸKC9PTrR" Զ7f:bx7*65 56`q/`NK]3Gqaȵݧ {o]nwSBH)B.Ơ%^B+ߨ Oe I:6N&-ɹCm K0Ÿ'K0bɦ3d0Rv=zw40;eid(!0ۃ8 c3e0ɲhj/w/F{ӷFQƩ^:\eH ;F޺5hŁYGCJ7J%g%p.bS%tR߭g:!ZN pWV"AɨڹW L2L (A߆ ~1A4/mgtni!HGt($L\g4EFm 7wAhՕdIb7OQKcr晊'nظ`:=n2Iܗ`j:sʹPyk|ᢺC|<NK̅2g3 V/lٯ͹!L$Cnw'8}' h8l qwLH׍{z@o|d(O:^z&/$:[;N,:2ChQa%bbV犎 sŶzyLa"y;Ԧ,m|1S8=]̉{xtolN#Xdd3G"> L NwF+8Snjh @Fb"rDWIѤdQ#XH-GB nkK^qP硶b<8fZ ZW W P:'4eƶH{#`ZAQtK9dM\ ,0foCPI389iCTTy<:kw[-e5&jzSHGlUiO ^\ Üyzh%]4CjϜ,WPJSh0PBoAˍ ¼f|"5ˏK(\q*ZpufNC%b8@÷\CSB|h$n0ĥ3D0 $Gk[Ͳ+!fA4DRB!${'RE%!&6"i=0yGH ,!-(4H$b$1@=HE?.$! 4ҡ~/gv@} IhP@iCP `> "!Ԅ^7rr 2+HGgM`NS NȀ160= /ꇺNSv%)4TC{h_C-4ÿȃ"*m!JliIY@?#' U+-%m6ޮ)S1*MHh x/{'YEPYf#;SLo0#J ,2 --$CU(@FICH68A&(P:3MḾr"iV3^]vN[4kvR&Z i 7v@H͸l2"$a+㝯zUTmGRiKjՙh:(PibAH6phFc|]=H]m$AE vYfZĵƈѿl#@mTua{9-&&:fiU(g:%%v)UU@VeL`F r@I?EQL0{w(0|i@$=]@>Pp&׭P/t | @6'@/V@o$M  d~ˆ! <`%Ā h;$h0ϒ]k;wAP <!hiQ6\9MNk^mqr9BFn7y} a.& C4uM( raw9"q5^Dv،$0@u3F\4rN75*tфUQ S5CsPrc1oQ{a>^giBh1_fb@]c X q~spQ=''5:obs߶]dF޹Ӥr4tVr bzd6c/ZTىLSuݱ؊mަwkݴnh+AJ0NŁ-V0Ea\/(gΆ3B1js2c$hߍ5;ʳg 6P;VȹD_fhۘ6vf434-9c '#le2x!T` 4QLvD@Vs)9-@iYtd*CQӵUr- 4RILr.&vn]1l[/|bw( 3xdo 0Թ!1J#uN|0c!teLqB.Dž]&q'N;),DkLY|ﰌшq#شnb xyqA,8]S؍Фq=akߝ3zdW$uqK+TDdPDA%;Ӻ8h8Ќo0μ U'3Y;[ ;&a˪ WA\Ǯ4Yz4d3[آtIJ+&#퓧,Ș&^Vhi]ltx:b780W&v.(uɭ8P(S3QNSg-tu(Ǘ}uY FC:eƜ`|3d9mR6kg>*n+c6)f9Yu7cJsʸ,PK^nt$ס{qo 9ȠMyC.hЛvGO'e&4 hsce>eOl7߆zF\hܮwgz}B(Xre[ht^poˈ&Tr-j `"XƇj*>޽q5ŽHw0f,ӛ{pr~v5>h8#Ǚ/l.R4ziQc"Pԑ.֙ߥ;2i߸0 {0f=ƴ.iOvF0;J0@Y;*)YUׁmc>R5:YT%H%vV+,oKXoHIt]>W:CFn)&T5aGI* e5ee8^JQ,zHlK\돥µ;/40Y3~( \,ijė!WD#)? k # hU75M8c#77R@'lVdX#_-mɴh􌸄sw!5*AjHM'Omh#1R!Kf I6=[kc10"Mh $j !S4؉yWP!H0F'19mJS֐cy ne8EbB cJ5(EI04AD4ؤc$M W\` u4S&krTĕEbmkѵ#Scj2IE3*fCMudNk B TcxCTV`i$ s <] ɨ1aZCZO(C g? (?P[! 'n;.#B_O{DEN4:"PD:EOOv|fT=_8OIȄU1q&)C33HLمS,bB RT @r@! Ĩy` TC _~uEPlaE TQ B4 @-9dH. P~i;hD::?TEWB13Pai'4mj E%B#PyH !ٲM*@#)FoCR 4R%6Lf*IxKቾ䂐Zuh߫QM>e:u= GRz^=0;aChFa9& I<4%P)y߲zD پAV%:$pZRpjSY^dP@{!CH ,9/L)z L (o*~Cʨ|1))O9 >%P9! , @a%"^ݸv7U^H705dWXpu]# $*stPZ|Ձ4A x:*mSB`~[ %@1@!B95Jԑbj\}1 R##GRJFʡ@R  Rtt@QP%8h   P7TM1d+"^<ٞn9܀܍D3rM _~T}g&dTLp|`)Ib >c6AB )MP1! RU5m[eMԹQl4le5%SRdե ,bR %hdc%F5j( YRMPa4,-,Di-) 25]$MY*ܮE+r,UʬԵ (,diMFilj63Icmsҵ%fd4U-Y]5RLiJœ3efj24$Х&hّ(Ree$ؤ-[C:rQtVXЛheQib,҉-Rjj&&13ɭ\Q2d6*MlV-X5SE%bFlXLɶ[&hM]MT[S6SdY66U15 i6lU%]YTclZjӦ-#EDjYMER+!ld"h6)lRmt-͟bnr H4mEZ5)3UCQ!Z\CHb{uPBbp>WP \ܬʝ7hح4Q1s]tR斤شkƮW0&B8Y4@9+ rs뮢6p#g ;%n`T,yVגZTaC l%jbuU1FHĚhMlFR7ڗ|]@HJD-A#z43րhsSe$V)a_pIYww_fMBiiRK$5QE4VIhJ00%m4bk 3JlV)aX&Ȍ͓LER4M)?B #^MvJnFa HrMz) @ @5}$" 04O~ݙ|sWګ2(}aե (9HP>V$Z l!c':Gml ôM =">V=&B @ĸ+_\Ubۃ,WȻtr:!?LUX`F9*D%9$8@KfCJN@1 _+S.:]aV )Dq.<M**LL-3fjMk% FaJTdTmlY5UQkDmjch֔Q^v NEV$`((B&H1 !җK;? }oFe9j\ L!bix ӸyL*d4T@A!46T2U ^"{ ?=:*<H@#bY~dДum \=(JLx{eITRMlDo T4!B P S1П3ƋmN8= wG8 iEL";u똀P7c@)N*.oM;2;:Ǒ]E>])VT;;WJ o%8 @p%ՀbMx'f0'()SDd #rClFodaf@`L6ĝ y }P @q ] >h1j}YZvzW0G@c@T{A(!T#Xlf,$A"6SH&rOpxCwٿ  AF-yP8tTbfh4v@x;" 쎼:"l`LIQ4fzW|d ҥ4򸨝ɱ &ҟg fuuk\9QV"C#R:!\5(D)8#E-*^1[f,,Vlf_:-B@)̩LK 4 K*RNFaFc9+2QRJFSc4;<5RP %q)Q(Q*BW0V%1ڱ̐zfi^\ǘ EC VEIwIΌti{1׏;IYAH<~ZTzH(5S/-1{ujHf!E a@ߊ(qBN7Se`P}*?$(bb70\ K9p&tCَr] ! aR.ꟲ(aRfםM\FqU2@Ҕ0`*?4#Fy임(d sZ"|Rx.8qz $L&2SH+̀bC.o6j.d` nCOf'Y.()"ڡ G"7ր _HW }|I#0Zji)|'&|s"DsLm\!'a' )W>Hcߋr,>`nlhw%9򙃑BJ BtXfL~~(?G}U屰0OG#mT}F'$OW0N#<!r0C&pƂ Vz#!='WbzHUw-iU\MVU#mqN4DBhHZZJҢle6TlM6$1JƤm%3VV41S$ZEhXmS63R5fTjRl6Yk%jI"B%ʛ*SkDԚZUuk%]2SMɪ* 6Ҥe^^^yW Qk&lkAYJѴmidkd,fkCAH3*1`JS-k56&mQ2dVű oVRZKtrLJTdRAUE>,P^l `!O~$,S~'Ӻir@ՁR C=(AEv'@؉fa(6~*yCc` zENH I]-fC*=L 0qRHAM&[bP$d @1-AAy*o[)+I5 ؃42C)  DӶɐ:rRB XUjŐҸ2h!u15*@L;„ĉ,LQSZeHZ!$]*]h CL!OmHCXhTO⿼:_}WQb ; p/Y)hL=e=N$ o/EG'tAIOL( G݇X!Zd ,k.S5tL?08z | e-P[J&ߖR/BhH0l"`.زRĢoZ3\0gf%6g` A$wPᏛ}" bGL)$%Y" 0K"tAPU E`x Pb"A" 0aQR1eKb <ǀ$= M)fbWF%<;@~xgܷ+ 9Yw  G9*o D)w&B2@>``%Ƈx^RVC 4A)D+6tƐWu4(f%ȕ(w60֓72HUhbJQ" fIRYMšFi),iL*&cJIFf>kƠm^Z+C*ԜJLnXhluRAو?AV%Wco!! ~EB$BRiMÜxЩpԴ;c^iGWfwӮFXp]Î8`R1;n/#2hh- ^MzKO&uݶmު'kveͣŴ2s^yVB!*C[m @c o8nceDAl`76P;` N) > Tr5UrKBȻH1Iv0QM#))%* a 50&Z0.JT!Cxy7bH 7@j3]TICҀ. rk iBvd3*R1a 5Fʯ< jljG(ܐcf,c9Q4XL77\US DQ$8PZ eBSP\5@[9 a 8ˀ"1 RWP(@$"JV2bLb ƙj#d+ H8ԥꙬ39ˌ!) D103W>{́| *u$@dT@~9R~haCy–~<`E!SRWDm.(yXgawB;'}t#LCH'a tj2TV(Py*S*DK4 (D<}sW2T\='Ġl/{ |q7$My<()@}# Ssbb]PhMbK*:0W- 5m5m(Fa eEȭn:g>driqA/x@v[ vji30C>o7!'{ "$A=ȃ'vQ0€ZҒRc&؈-"12XƣP( ftNIQ4! VLI0d]DERmk]ܮ]2F`f;S 6` K\Il5MDl)  `dJ@*e*0L\[bd\S w$g I ƒiЯ)i)6Q-WU-wD\%ddڄhi8Zld%M\䥞puܜFk!4YX}P m^QU')\#䱒r?S` PYb# V>P&~,]#Y@R'd0qG\ H( h z&)[v|hjom@8֞(eRTJiL J&E IQ22Ji-tZ@ d!1iut2u^Zm)o~"vR2(YD{>\"js]*SQ5Λt`o~UW 5El ZE>a C!"E3(^LU=O`G{1&L 1m f?b! nQLŁ +D4 &ټ!HzJĩ2e1 ­=$p-Š ,T0E[2QΘ Z)`+ `b`b!`$4M:]0\ M#òiȣ.4HNƁK) M*2RykJ&3/,ܷrDLu0 u|I(W!L# FB7 $e /|AJ{i@<'Om 9 .x+U0)Я|hsJ=gcrjA`b|P)u$9 놨w.\}4J;~; aܪ(6!x)!hIu(BСIٰ(00Cb]!e6+)KB{-D!N ̀2Be ƿ,QF0% *ºI+F`$$HFi j*[54^^{֊Q @ MaEo5yԺ-#G]Ylj5ԁ>zN!B:{T0Arx9@儢$rH"X0Br'Xcc!ce(21Ar0cn0c>8FY5H ڰmhCQ3ba&ưcвm&2lYQS0 Xi#F "I28Vn5 s#7T(BB!q%e$`aeR@PNs@#lG$Iaj!F(h6L'd`8( -0aFTD:#Mp6F$Xe1hIX#NEjMr-:Z(4Bje[_;k I\I _O\_Z ^v2WmPb\]IՂ+*J lhP[LLQ3O($iEL0A@zM cGHiY9NlFHe$RcBQ(RB&5l0Є 7XhJsav6-*OX(`A["4ƚc$1SLd  q#l7Dޘ WDhR3$-"67 F(%L oeDM6Y FcGq1b}87Kh ee#oC(I hcH=fZ 0p P` 1 ( AQp:PR`B4db,i6O489DFV"DFc`f.Rĉ88`0*R #U&P+T`6n'b FF*4;QH6P8-5D`mip' ƍ2F11XmF-4ql#%1IJ°9J b`aJ!aFA`2"E U,N**@ ETq4`B8Kf Wf 4St,63&I2`6j+pX=r5<,h6407 e8f&$BgIJلm\,Šh8 U.K[e iV H`J'M1(AmS0X6A &Y`ʆ޲UH RPzVek&;iDX 4" e0F#J/m9z^QB0I4|T"8ȱ { F .ʢ]OfoepdhX4i QԀ6N!59: *YF41X+! ݍ-aRӊDVZ3 aReVڶԲW[8zhDZ5Ȑ0p2Xf㚒@hM۹:y]nv޼]ii&efN)-&#hȭEI06hуTĮ Hdt1*[PnPm)F}0lq%l:AJ GP2_Mqruf10$Q9ŢGj  pDM^LjAB^b7<[m7n0Řp~8Ɖ僐yX"m:N$1 B!&V 2&T9 VV*fMY*pM,a4))ڄ&,8'āu a*b4$Xa@[9 D6; v_jZ Nn ޛJUQuUT![ufa&ɑgw`d: 9$(Cb?i#7dAQI1M,oQ63lp$l"4=qdm~r<(G]&. ةΡ"㐠N(aZ CX۴弳,1V#80Hu.2aц%Ib4HLi9kH`(8ZU܊1b"ߑ>$5D@[*dtͬSRHD ҂:$@Z 2 F!ҵn bMm;҃2AրH&OU=zp0 4ʁʚpV„ʹ2vmޮ)-zVŷ5W5TsVDkJ#{-:21)0tЎ,T;h`B*PDC@ܭ :6D!"Amh - edc4ꔉ))lԴ+~{i*mQItiSQe)|vPA^v)um~o+CIDD$uA0S$k'`k'. 44 O>n 4@y}9]x&w!9\4'jDLEbM@| q}1 48T{Tzwb.CJ)D=#Bp @%Jf)Y%c12!ȂThb I2A1@))V UhE@a!)D UIZ+&R+ITȥRr\tС#B" "P[oQ9f}l0Hg؅i!U0 tiև i!ɗ5xR`ӘC3bQ ID/VhhELCO 3u۫ie,W6:DX*7$:HIjS4ei6Hvg2rHf["qJW$;벷YU<kObBjQADq˨؆F $V[`S:9Ц8gJiF$Z+crW1:P7MPL#!Ǻ۸ 7 _fآId@4<ئH,NG%T6R4b$K!J4O@fNʫA= Q`'eD$Ns= EHgzLd;4@||&M HHJd!c$ÉBsZD7eP;J⮌ ̄u*Bo)rR&HDIwd1wdN xxTC pP ¡DYj@"&"$dlX45k[yl܍&Fb DUA"Ej@بVfbFIi#P)? C7! !x4I/zk(~9*@I>0$@B ʉsDC Cg.b@PJ)- hX ӭR@%،1aJyf(@JC!*jƆԆ$D@TiǫH帻#lALEI(h_TAD9r@OTsLFHJ Or)P@) ⃨60&)B&" P5 `C|cE=,)u1 aygPb1Sy )| oZ:"tHulu`929`bf@|wLd. W%i5Il&QIL.H@94D!QRFL ʀzAT2GvA Wwlܢ]d8؎Մ`eLjm4تfEYZmd֤ڤC/'rrCAiĐf u{c܎;X,!(ЉhSQ2m|1-(]<0QJ ([ `iRRhJUj#@|*HBJ)$-u9H; 8p"|6Ty7%. ?XgtV7E>qIH85̑c^a|L/نtQ+ASQ=}x}c`NX> ZnG Z^A7 ?Oߓy">n[du'N4"334(Tl<v V!dMO;]E׹sZ,#4#ldg (QA5i"4BdM D] 7zd_) ’ 4.GCH؛btٶkZudeaĮ[Z+1 xvڞD;')/$B9ᙀE?P9]ͱq*tjn[lr*u;]$K&2۴iw]]:v&.߬}EۮR۲椢k2 ̳<D1 ޜJ(`A$Hϑ%"97^ʁPC`׎H6g#"'c tJd=g$aq -2C @hŬgZS$L"E27Ͷ,B+;J9O_ŬiD>|xX%B|VBPFbkʖJSQXhi jv[W9bd & ',0s~eHIvăAM:UF2$ҠcQD6S4i5BlC3m2UMAImӟW{6s|vK,HӜ}ulfu JޞC~y)b! #RF@ģmme%%hEi1%hBc0rz@Mx|q *`C98E0iJ47WKJ%^8wՀ ;5Vb>_Fq m @]H `NA=X 4 !2ћVDDtC(u+TJ@nCI4v5R AD{[xw݆Ya3,ƭsp] :J8J0%&u}ACB>*).| a'DpIsd臻Z?$@`"fSNh+]ˈ1 z@_0zEP'WMk OH~mȱvJ'SԢ dý6|Q@(vCG(i%c1]7#GT/j @QeڡIy " o\?~~h}⥩"P}D_O9&tJu ҥ hXb"E(&D!0i\E(~FPFC(%C1#TPPR u7]?iPXhj"*;+O 7\"i}%<*h|2 DhUWJ n#goP:;PDN?Hv&6}]ʑ!a$ GQT:it$tjgp0)$!CV1 e+Bz= >tO#0V`dLJC$VC 1o$>I@e7hQ0@d#oz6Dl'f;[.9{? /S $=2dA:|1,#DS(&)%lKj-%tc>&@"&@15%!AE- K1E,q2l#[3/}QIQ#4FGA7>DYa(44aF@h )"6Q\T5( @Lѯ*1 jܘk>sh=F(#oeBǫmWCɣS$;ȔF{JE2x0P|‡_N*@DBHTB󐉨S?2+I@ ădtA "ds;T$E$ P&1Jw,%4U/ܪz8 A2p@Bh- цa>;% `6E"p>(x<(&(zlΐhM1q"F3L8! !(BX'@+؝"˥ ^O.*ISJ>/d40`_3 P%.fQ Q%tÙ.wNt&i4i._yvr$,MkcJIJz&[nHotɐE4%0DQ!a;s A/Z@P0Li Xb*ұ3VR JN1Ȫ˵01-ZSmԮi)KDlm}ҩm=Idkk^5WHԶѥshL|R]ebiiS!snbH2iEګ4ҵ(ٍ2SUڛ̺jvZKYEv(fMcŋf FӃ4h 3W %%34۩;t(&V-g5uaHή(+6&0 =]6*k l5)2,^ykNkyJipѶjP"RipȓkBҞkԳAhʍe4QkN+Q ͐К4JV(ɭe&TR6⍹̂e -&ֈvnRWu+5ƮduNu^JFm:jK˦zվ>ƚeԣ2"npt &KFR4_u6MԠ߮H;eSV ɄQAH Ҡ!b"`iF4FK,! mF]v֟P6FaP}'mg?A0ꑡ w`4Lژ8iS m ZmuHL8(%7O Đ#x@rb.@*Sƈw1yV awD AD4Ǒ@7b&`p!-,AL2ib-Q)r QL QT2W~ܤZ3 j l`;%/@e' P"A0Un2l&m T *E9"d`*Ya\10g!9$!"Fց7J"T* Ϡ&]ei0 ǸcJ<+) x.{7SFlQ ,DBYH 3$(D)oW"Q(` maV6M=];zۜFFNJ+XpvpV &s0 @4CQA{;!>A>6 hA7d&[M[F*-Id$ 8#|zv49r!X,%@edQMe hƆJ刅ɢ!!F,je $0ݘS18hbL`܇FkB͌A{<H(P9` u.6‚C+uSO0ZM, ! @2D_Qi'EwW2xq?k]>j[v@ ;DRY:0w9/Y>}O `*e~ٓj"_3]Eۧ^?*ZfE1SWRaD-QN ;zRxNp< Zɂ`0 u6W d *|Q:u<&Wt>r(" G;A B1% IHO4"^D"LQ4TF 4H\i9jCl@al`JJ1 J. r \>E~7!G6<ݣAKT]5l!DAq!AQ}P#cZ+ ņC!\S GQ2&10_h2t<5%H($0wj`#=ȏ $z ݈҅;(5W~MuA*h)D^PAHIWJua@*eE X@*E* A(LTհ@ԣH1>l*ve1X(%O1Tj QT:,1 `(&:*XH* V4m S`oKq$`H8B )5"T; A=)S RKhɩ2kY,U6ኚ3IҒFO sS>M j%!p@ & ;ABS^ D$F FR$ (TM"=1Z-u[D,E˴KolLRD\%"Jgyכ[ub[]evh &!DGa^ <\XIJ1 JەʙHnnmmLl5Y33E,`i5e-g0ِyks܃dVRڟ>O DCKA@L55Jj /v:P=À9 vB.=C'~9=ʽA"c%W+VJy.hfE˾ERխԩ+4ƪ*^vsJ1v$4Se"j&U-00iIhRZ +WME2fF4ꆵ] $e3Z,b(ExSj7nHTM)D%0uz t58f`kCW?q@KSUW]JgnK-F2!q?!/L'k\94zt*Fy|׎{Q ϘIN• NH6S(t1Mko;;uB8s"(CL^&^<WTl5ϣ$M!׶{d\$ !0[âWMY-^HU ,3zـ%GNpÅHD+VF1la)i;٥4: RRcOdZӯ2 M0y[bBѣDŔU lq :Ni- " * 3]},:d&a(53jP2{~;7F(Ue9g(֩cb| cM+s8g:X Fnל{Ccڝ6$MĦL܌e=Xh@R@!rr _U7-t -vtPrAmwobE-a $t>"ÖcYFǔ< ^BqE0}P`oZaBCh^`4IBDYu[g@ߦ4x؎4ޚ3r_;w6?-i⟆\z͌pϘvHP9K< 1;yz:8cna&v&JKx, : e`uI&j;F>  9G# nh-8yT| G >oװ^?Ij;&2^8ס94ĻUE^4|a5 |t^hgL[jQB'-hF80D%#wܨlFi˓nwBwU4Gb hoi^Ub0Zq{]sB\#w= Ý:VS48Hj}۫NiUН@ / _7,wq# ;jjXQNK,H *EHz7Y59"ߖ);!&\_"&Inr.WQ!t2hym7T  jb>s\q{3xpj8J@kcmZdB||['>CL0o+=lίL?aBcуݝxnTW(CuFNGQyK6jF KsAOmA b4&bC1d9-W_Y zcMdtg кG3l̮8^HyS7:K|W6cFOÎB딜ܑI. Hi֛Ѯ{hfrn"\ICj TԺ_֢IϬH=m m?.;jghI]c1.]!!';x#3퓺juo)|w:UonIDtѲty+:ڛCgEcU\ f K ¹bƙ\MFQ? H]hcN3z)힒h!7lMѼ+]`ؠr܏Fu(mNzC:mu[8m5S,^B;O&jbPhO{3m‘NVL/}0."OMHmT,} f)NzE] ?X!jxy{=Hu=xb&1|\ &^ٍiF2XZ0L9{U84"gy!  / ?DupFc[Љn!jxyZOSO>wR8;NkRưSCP T ! ^EbȔ#ˆ#Uxa t0SQCK HJ^S4|O)(HCQMhPha נY5-1@y@Qе"!VUe GGFẸ@EPR&1VR ]-b<:.<ޢ'EXPd 5`AX]QA;ZXeĆgpzyb[6 LADFkcIx@1a2AA1&b &48bD )ތV#A,1'xԚYMD$! \Rds tbO) `+6<F7=^Iõ f1#ypE ͦooi b-HF"#+a@\CPj5")h 21 Mu׭.7;A+!vH/.HG(kO%4.L*#C'CCJH %y&>Dz U0<$bP) )D|D T#4D کMG!=;2ݼ$ʧKT"0i=އaMr'Qd)FI $AAG5BCG/Q4_j0FhӠ4[KPxۚ-r|^utf6C5lݕm_ 㺺DDi&W /E-C ~&~} w )(V$MQ1јz6ubgk{!a*1+2B\I0!;pT4FG d ԈtyO]Q0W$5?$4 WJ}י|STt\NmR!xQOX@ʚ7B5 B-'T("*H" o] _]ɨQüp?x*&v 7 $HcaT^ )iZ OdY ٱ1$b "利pHTFƍ<TX23,SR,p$+$ ,$C@@A"p 5"wNr*Suݱm͟_{]P6X̳4,!A(cuzILB(} 9qXf轮Kk,/NMscv6 Ԇ_2LDh"^C@f7ȉ~6+*D?d4;)<oz| >y<E@x7dy@}4uɶ)m&@+=Ѽ@{B#%q y rnRDNS1GXH#:49@D5<|m*Ĉ #0k4'H L0IQt=:92lO@JC5G'tS)д|آb*ȀSbuA4J(  b'!ڦ؅I& h&)@ᰓ`68:sVu,@w׍ܓe,P|c HD{@$ S\ȉ}OtH@}i70 P0Gx0;v)"iRf̲loպ(HFC҂Sn)2Hx(6P`H"@MI gJeG@=)BBWj& @HPZSr4$IL:Ǿ|.H&BY+J=Ъ( .(8Ϫ}b'ũtAjgkq9Bg8\5ۮ/NٱX>j/ 8s*.P,|6 y/ z4 3Dޥ~Zٸ2xKLX^٨68.Iяx׆}W'󧡘ij+|5܆c47 CSY㥽m ۙMXr&E0E"2ܪAi!{цHb4Glni`ZlnJ*'=669wKkC|6G%[teC.ٸ&hKGFUh{{s7H,<4U"&%8 e˜ cŷuo5em#c@1kfuǣ8Fo 3$^<&"2orlkܢ`۱ޫ0igs؉ pyݬfDgޥdH!09r0҅+* $:Ҍ6UƇR&'Br:娉k͜q2-1רq D{óvvC$$Ú .6H٘9ÂbF՚0#Xitwr2:.r ƑHcW 0-0d%O&,컱,V 87%fpMȌTe6hWT2Ldeo $QP'BIz]#gkE,5sS@S\ԾgC2Ü%kLpA3Ї hB9#[%ч-/=h";;cSEf52j9gl ڇdѱɕR16 eUXi#L5;EؾȰDQJ1<31tdޅˊgBX-)c\'7gZ;Ma]iPK!N4:] zɦ q\o% iX0˅1"oZ!@Ne64Nfp p4Y[1nE袴s8CӇVPVzA&՜XМf]TYe&yr3q9fܴ1#7 BhrÇQ!2t8w$ KV9F$ejKŤGr MjmX;0_DFn"Ci$pc O^y*H%0Atd/P& u;$ i tKm$z 0aO!ԥ@<0 n!!@l*D/(:y+^9C w(CX0ҳ4 !s{fc(l- Q!7FUEvzjP{&p)uY$S)!"B(ẺMeP"QIz)H`H>x`0%p {\a\gv!RP+@2%o(DjCg0Tc9 #IBQπJZlD76=}a"\MfYj~YH46&dkH0dL p[hm@DNgV Uր 0+1idmF IQCڲogy191*Cն&l(`z`x<v1ZEhu TGwXf֖PCjS+42.Sne- YP)p $`"h@pGXA^10]3lDEfcM6443+k[;,0RS1DDLiN`N= _&!l9|B0Q JD G4=:lcd=aRUh8^$sHM%uS>F,!"ƑX5F$B匓 d#bv sZNLp3|D}dC}b)4~?a"  ȿgqDsXĠH%"ȅ+ h1 yẠ'=O-Q}|=DOQAGLbQ ̉) %Z!2\с00tH8,Y  2 f1}lư5 HK%"( )` -S*9y!PMB1R欕*WRl)>hrJB"R(ҢߟC#9()JR! V`MJh T7$8 P{էi Dt!GWtBЀP.JR"e HQ0&QZ85TYMljXe^PP%B#r\`Zb8Ԕf IBHB 9A @R )@zG:Pإ )27̣u!5dEfXi"b`EhV&ʊ܍p=!{IC6М6؈ T?0'LQ<t|ZA&~.$!x) @I1Sh_y(!gwH SJT1*_!O|&xr[mD,Tm7^2(Z"ktt <f=^NiqWgTS:Shq d;mh7C3Z!1.V0#V4ֵK:Zt D<,DŽt2dz 6Sssj&VJ"[dw^u D̤C6ӦTTurKQ]ڎqhX@%Q|(f*ܐ"i3hijSDJZT& .Ѕ&lDkF+ CXBƲB(cB#( $ɂʐ&@BjbCe!(23Q46bc7DM; :1DnH1&4{yi,B$ p\Ɔ @ C+"$Xb6 1%Xc1%12I4t(rVU⁒ЃxѩT(oi dFn"Pvm) %J640I48L5"0s!X5F %j :huȤ):gȔ1S5f p"Iޠh2686-eq0 F6mIKqFdT!Tb02LZHSQn{.U( ib`$K BDP I$^PtE6C7Hņ€VU[ęCf 3Z 79DVF//lѫA1J%tEJh|Ddj%j(% QAF 2(S2XL!"Z0 D+}X i%p]@ GTa)J@ HB chTԈdB#䩟j  t4ഁIJ-:D[0859"dd %.@ GVƕIMax i  ]84a%SЗ&TҔL3miQ;B%92ALLfLٞ#w?Ahd}+Qe80 "3EdBbGaS_4SBw-"{>/@R4!!žA C~@خ-d?⇡/@Ѱ!wQC&xHtq܋#`ú*!m*;>I@& "B;m$Lk45(m)J J%HH a@Gi&+鈌rm?HBA#6@p@e"NHSkDɆ!!2˶f {%)e+(.x]ݣJ(q^;Rn=E;A[4'܈Tɤ˒`A6m\rHnfUV?_>=+o^h]_))r^q)%xˢf H7"$"t fY(51XOdť"*A߆>A@PY5V4*eI na{pwj)x  UCy7O*!TЫB12(JB"$Ih ) &D&Z*a?j9G; H%0RdJl@UG #ggNhG%Eo:NgC%6{cr>(rꇑpKiuFS?tD\H)8{> +FCVjEfTZekMVN!"e AJxfбA)W8+}:r fu  FbnF|4`E9 &1oRh) (3hmغ[]K*͵^6BXN *U R<up zT6] BI:}ʘ$DP/ 4+ 0# )X;m߸a.ʒb 0Bdj'b-ߗ^IfY1˳RW%\#P`QD|7ӰHh3%pXD +90C3W%7NMqП"f8E$BY'6jB-h(d) cʏ&FV<><c}TJ_Cp0$@m쮷ƵDh“ Jh"C# CA@h\1,̰M\˃ ̴T]ͮS3.:yL ;,:0(MhbR ;#í`3(5X``HIAO(2 fQ>w,1A"S$@{N|P#QY'~` {1@?+p܇O4X! h )f1 HKR J4 b稏b@Q@ZR>aR|1S@([=M!)$jOe-'|?^cN49P#h)܌12E4JdEx)=p}?KaqX1*{%W!GG rOwNSy:& 3ZuPQXJ"'B%ZG9"zbD(ʆ".2WҼЈ@+!-@sBD d4?j R P4) h)@jRD0u!rR+'؈iT%m_!R5ɢU  CA(=R;J  /L(Jii}n~6'Xll{Wc7%?Q͈p}߿Ӎ}P`NFoAOb yB*EL0~5>N@$??TL^.`/>0m(!_7Ǘ`  ! jHjF=hʐun4/@iІ tSL'눍%&$~I"SLO\%$:` ?JE?=D =OU!TUS$Fv)"E5(()>"T>~HaI:bDoGJ?S];ѝy4cV (h;,H4~rct@J9+8 I+-־5IU҆A/kFa⌛kVCqPjPd䁐d<,mF &75˕llsܮW#\ghϽbѭeyp;&0"r=`y gBCY+H,e(0,.!iXcxj6 R,)I.rI.I+iyyu^ee3$)fi!0F*2yJJI$K$MRIRKzΘm=O&B]=EOx::E PQP}lPѨ04AThȔ%!0Qdܗ4afw]HdQ^o2iRH-ZZYSD!$+*q A) fJ8Jc9\`AiX(J>\?? p< !06]FaTc )hr $`ciU`SUmy .Q@ uWO:Z`FT2ANo! aZrv蠏*`g ;WmH療d7kDʄlCP 3,']*v}أt78RhD&0CGe lXǂnY(S1.t woM=OVQ{˺c"fJH.zx, b(JƓDOmJmriPi#QN(DHG#s XVa ݊,Ҕ\)4AKɤ&An .g_ |& %W$a!!qBP~ 8"ȈDeF9enj@ېJ yY zrÅ!TE~%-p>0%`2LC7^"= (!H5˃a]T/F:nɃq)T/4d^Ϧ641{Ϸ[mzPzs ;_s]۞0g1 ih;9@5OGUYv}|+Cw׻=<=z2&v݃:ʛmC::J͍TK̀SnϯPJ"!}(ƀCzbR*(_ARME@HUZ[&RQȐTJbz!Bfj6eD A)RU+@ 5JHT(RA*B4e4 w  5<]w=MY2ZkA;iٶêYqօtR `_f̙˶j޼ W_x.z6)A@B@ܥ><ޣOѠ4( 5݌E}ϸdnP@f]{ڝl0zlx{<:mj&h)㳺usT+ދ-0u 6ED\1}x[9[6;fs6u-j}lU6[+kvjex=֡z{Tnep;vuYvK2w4tP{n y'.rsnv^L) LtJ7 0n{N:mvaα޻=l}d:){׻]}}w۳ܽ޹\w|ۭ:gvgkkrĖ_lpmYN:cywim^ʷ{J{r͏k嫮oqZU}E/{{pw)ϵx^@T}o`7w=;g9hGٝsc=mۺ>wn*T^z7e] ͍}s/}ګw6Fо}u_88}Ýǯ;)@{T]UƖ${'GNj4sO2u=+/{wM^y {\lm&l`֢۫ݎtwޯwL[q}P)inVՈV6OnsZ^+Р}h[`ʧHgһVd Vun7av6Q:ڵ]m[c8sw{Phtgy݈aImC֨ :t)TN8w}Ͻ78jl{7 MQ4tte=E"2f@h˾Rܱn{xzh0}hP |s-T,jsZvdfm[,>͇< 3zo{Nٽ ӫ)MA4h&&DlF)O*{)!D4 eOi~J~Ѩjh)e=z OI)$SH2THhLdЍ 4ɐ4h $Bi%=1)'?T4L#j4= D@ Jh a2&L4Ѥ4 Oi~T h DA4)@L L&TSTڣe76~i6ڀ=3f`aBa=g0խMu(m *?> O5VXM @D@H?u_~ٶ+| 79HԀw]LYnx,z>uC G|d@(4"R)EE iEX PCJ R9 # JiE5"RU\$wpB!D6L3MQRP"HdXdQ@^0B`Q, (Aܚ8Pr'4,H_ mqGJi J&hr ]\bf{*̔s(a '0}q 3Q1EUP8<qׇ+3q;ȵ6*h ݘgsϣw3xwN )1ZFj3p[d/R/\$yM!xM郡fr+SokϹէR[zTJ:TQUvn IU|{:~THLՠ2j" ,"ᄇ5)I>;wl'qtT={waQ|~3n54',ti8;uT`iڨt @I4őw gV)\#EATQG(~^d_cSySy7I0uA rODce|3p@O CPǔ@Q3&];RO>k/)'y%$%#莻ؗ/ã"pXYK,giaą!'"X(.[Ë,LlTgam͎y"">%i%r_r;G5E^#03ˮw}zkC, ] O8>)*5eKIĂ#!,ay݆~? KWV[Nw$P?kG涡7o#}_圛ʪd択_\w0 Ȼ~mtnQwht:[$Wn;h/٬j"8 \BdG789Jm'eu؋zk|,'Mx‘: /hw'ݳ7:׽}Lݟ%dQٞ"?NS1l?G8)MsRO~ .sBUؾ)}GW\6 X*T88Ù{v pPFV$\>K30֏;`i &)S`W>}i>yZQ^N_s&dߐ9o O>ζaMW'Cw`ۍ\vi"^[%q#7cUUԔQW 'Gv:]4֑35ݲB-'I]]ιݻWv#we̝ w- lMߧ祉8~𣏕S;!O$ԯ!=T~7 'ruBQ ኇ3M:\IĆNNѭ` ?e~\^θL) &?#wC5 QPPT Ҕ (hhh$*f!&")?9 (|e-XfJb_U! Ѣz"濙 Lt)BDQKP$;q$Jg8H#44Y ,@RΎ#BpJT2OҌxj0`&4S1E!SCT4D_]pi6 +}06c|yBaf%)f *$! tꊘi%GII@(I$]%& 5FLFcf'_ɧ;m#c656I7;8`tP+İG8jwpSI'g[bեU@Ajv_k M[c)9-1G͟Ír tUW̄lQԆvKf_)}gccJdm“#]1!i;qiN!NY]TN1[B'l։ JhI`CUyopzA){ pT]6G6HAG!Ŋ6 %RKFZ*tMS֘ju7;5d@N >#OAIΩQ@n# "74ug63C b0׽YjNK@UDocѻ2!9v6q4$V@bYi.WagrvbM"ypF{T?uJNb#|Ej$AÞ#s6byYPBE rZ~$b.Cˈ )ュ{>AGc5Fq3yi+͒0FnB,VC3PьE2Kß]\'x薽T}T.N/뫱Jo àioUw{eEeo򐗕܋o* ʩrLD!f >ڻ t|4f07_p2}y&&?ȧyLnkc2rwbu_}ڹ{"CrZ3Q}XCl'MdJP@M,S39޸bĽÇW_\UsMvP%t^oŌ-)s'ڦ+,q ~iF(LN?SJ[lLj}$߲l*Cgbwڻbl爚CD9k]A(6$B>4xoDA/J)`ۦU!(Ζz,5$DΩ=ic Eq~#nwO:ٷهSS,,z}_ߙ 9¼QȎp~Xh;Gs)Uz%9!d;c˩ۺOv?Bf?8˥Wڍc`y}߇s/Rո7ϵ4k}e1ЙNΎFB*DT$wZFv&[1ni1Y_ΔχB~Fb~ T:Yd$*"QJ `bAk|ELRt%VĮ-fפ!雰Q gjisz-˒݌r%$lkϤ$ZH<(X)LlUKqVU]WZZeiM{?OM.CRcb 0m/{_ަ N♺OaQ]ۉ6_b"gPsᇐS>9t;:gdq'f׃U{zјFdFn cJg>[Mci w p2$@iSBe E ;qw9torLϹ3>Z3Ѹ!BJ?16hDGBu}r#؏:АWB¤vz~U yǪ>0$*L懦4|UgCդѫߊ%؞UM-GĜJE@۾R {1_#n,"YP9|?p CiqѼ瞇 .rOi$s=6bH i!U]a=߫~dDcNn&#Lw;: )QJ.ғ&ھbժ2ߤL/aќeZf1*&;8sr,Ë!me՞Gw֔<\T>k;k'>/ ٟݥj_{^2m|u#62yHWG_Mv*iyZ:ײ6`ѝѨק9ݲ/hWH@n LrZ2{"H88JjQs zSuO tO)??qqGr&;"sDQ$щN'3NN0u'/-o4;1FNxB#؝gJ;*l2%eq;" 6!_ `]|ѻ \Tf٤㪺O6ަQv{`3cUP# 8}G1 C;.x5o|O^]1:bЭO2!H|YQ/1Y"6;@N^|m xn@wv8e7o^/OPC˕(ƣoDNGaZɊҐpT|i5t,tg$YD$ 8ئ!l5ETT`&RvY::ow'H.LL<#sE$5d|܏jJQJ{疘Raf뱹X9ZxIDŤ#l LSa/?78KNԏ/]FΤ\i_#Z::z5!oƛyvlBayCpoMMfgLl]0vnkCt8٬sf2G<262͢C$RïJo` ABqԹLY4:g*yL0YlM9zxwIպɵM̠O6 m)Jp$YĠ'|ˮt.fy'LTrgk8pv kMug;#Iώ-'7a Txϻ01T˯N>Mv[k>!7fa%y6P'X(U@t84omT s,~]Fځr)%@wӄ*ptj%D()P=0 *L1cJ4 N-+m@O:ې(I Idi|\׻iv/|$5hԚo̙_v"9ӑ f#?G}[J8"NXmuxI1AGER4~? M h&N1ѓK)P*M1Ӭف Q'`S63Rf 8ѿhQ6Q N!7r?6'Ld9jsO'_~mʛ !MDm͛a.|wZ'*ItCut:fH#7zcIs.jiFRibYa|[vs;m>v]t'Rbecߘ\ͤ˺[wxd5}PVYR Pw7 i[\ R+!^nքC4k*R@$*D YPCSAp8VSBHI:O']dY@iP %DG ÿc PsaF/bU=ggջ0&D"2[ƍhH ˦~>fƸdzoFvzO%˅x|x]yF)Ҙ+M{8i'y\ / J-8e"֐{\q:A߬rl.#Rp[A;P>)* K +!I (xX r >/2bS?a0.hU7]-*$Ъ@1+@R b:U(~" )Rh(PsS{fO֊% D 05**HF@!JIa (@hB%B7!H%>_<@*|P( "BJ~@'ʮ4&9A1I`wXy5@GYF4RJ E(t4Q 2D/@G 9pPR JR*44D]C2H)̚-f_+㖪[]6t 9)0#J C5슴:R54J D If߀xdM`(P@1]H.s(A B,3Oǃ"#nу@pԈj@?4xRe 2 2`xFҒcDF,;gq~x\p±SқGh`);8&Ip&.QH30]ʭ$@,1Hh(h *}'J Ia {q4wEyd!M,\EDyÆWvA\ $RHwIvDGE.` ø!vy:xd3:/H! 0$dy E_G/I7unN"193FE[^@l}(ݿ8:cLYwL66@ן|I a1B43(3&$xC~yr.y a4JT1 1(D OGA J!Ȏp_$-AԞQC (@P.t@yGt_{ rD{w+Ƈ>n8Azf< h4 Pb@T"R "-dt#J|^nQӤΩ 'OlTWrdyc(6c֏ !Yoc(8ſYDpZpG}hn/1of O> ډ l #_^&/InUĸA4ImQ$ ^ /Sb<:Gwxv~e KkWPqe?}H*P*'{i]۠vFwbd ojsA,B$x "cv4b 4mT0#@l@3ߚl IܩkH8B|C(vɻF}X]f+}39q"wXvH0YJ֪20tO<x8ٔw7L=|pHkb/>.6cHPfcZ1hÜcA1ܳOgKOЪ?cw| Caɣ LAṽ($?i_uUiPb}ʨZ`Z3FWJtr% ;32C d Zgn~y428}#<{MSvT7Xd! tO}/硛5y8t~Ra&4=JR4/{$%D O̴XzffRjDka^,oҜ}-Ұs"' qv?/ȟΤ]Mq7#mXa߹m4: koBÄH&A]/A9́U+`5i Va3"H 8"zv>ƒL7#A<'6 H TrΐIOpi۠0VX0'Ԅɡb0w'&vNM+ohvwf:Y$$XORz4y;b[}ޣuYC G.D|"@ma"THЏA10 H@4]޿Dc9dmQP>pp_<^v_X{ Znf5VKCxzN.4C6 mu&O1HDR ٰb )J QDqL~6?Ӝ;P SHQ'0RIUC$PD$MDkj&8K J0Qڝy>Pa|Hz9Û;3d͍@ah!`8g7VzVNrfI3_LH2d&m+ry&hH\0yC>S<7eM]\sPڇX;zd-_HM!Y&=IE)S9M!Rf$m>v G!~0ꊝX)z`+p7G>Ϟi aCJXR5Tҕ90¿> $a h{dd\ _ȌGNxc.m6~:f!21m$t݃/yZs-kP߷a]>d׬R>x3W8ač^ozrw=ܧ+)9 ">Yd)\)<"Y1dɨyp:IuGώ8+&T yFa42Mm^ߌUh- [pwXb3Sfhzq+H;/ߙ~YW戃`pw .X#RfR^3+KLб Yے]t s%G23O^G\ˆ,C%]aG!Kce\2OꤰGmsw#@Y6!I*jJ\|rtuK9\NB L]Hҭy4*# sʐJnu&fOf5K8L Hu^֎nA?otXxZߡ1ጓZD0H&4'ZU*pDԝmCaM$BpLG3G,H㼾t7sXvԠș| kH|G-u\gz֪U͉[ʴn;.DO"ؑ]uʊghN|/כYA8)6CU1[u):0Q- M_+W>V*$쀆ކi&IIU=Q]KqA6 ?^+АD$2!gU@ĄA)N0i95qȅ@=clPP)Mk‡GdPN>hu#4*޼W_U|}urK$c h,h\Sk"/LG1v^oW`+ͲÿeGv ~ |!߿ >f< nCPwxY795i~ftjA&nɼisNw럫`e*(~Ҫt4 x]q6/)P=L6~#/oZI`ud$HQ_r:FEbA_6DxM?+|>^ȃ) 6т s[}ʾl3h62]" H8e `4aHYr]!Op9nۿ0@x_/,i*&D6/١!pIO|ی \\ՙ2sc*I3}IzG6}y>Nj7e o;*s3[A;}{gC ]~۹/b@n=LC@~Wa}\NcWHo'Lry Wѻ=%2betP aS3m؄u$7olk9nK.XIBJb;{O_N:daӍ#o#p}X I R$f^V˙&<=ry syYE|88Ɂ%GdyۇlO.'=q W`z6i"HDlm݈{5;`4ML |m7Grm׀6Lt=F! t&8n# Q&٪+B}_W/zWSſLL3 .$=P J-#2a.} Obnԛmݓfs?.Ɓ} 7JS06u 8Rn(P`#x2hL vnPƽӼBDbt[:]`A~l>8CxPMfF*fRCUsXmIccK+ӕgQۅgFn:NGŘJdUmqf"/I_cr2QL99M`uun 3EEtϠM5Yp|$=W J EV`Ņ3]5a+z&.۟?FbE|Fœ;#R4p\;ʙ"{, vqMVOc9nMJw7 =Am1Qx2}2`&ay)1Mf2v4jț IgNb4iFvy%,zw^~i#.am6YD@hM51S}Nk͊tj;]2_#M" ɡ6Sq 6h.8 "{$wv9t8q6)uH()gY7@z;*g9F\4sGyb XŮz.L.ѻw#tc>jK}#nT:I!QbtP=E?"ߺ$O"6vq :crc?q}\4 <<?ȤI$#~t=xx{߭]0`#z#gbpIWK I;hDlit$?\{bX@܂Eۡ~܋tÖ3Pd#htEJjUa`0mZ Y6bf^{~L`aa{{g^)&vHYR%jUXi l40$#ERBI%&k/ֻAGq&&y!&ɹ>ˁqtѹ{nISMTIta8}徎#'?CO~.|U9}Spč:fPYc ebßD*_GA45 ŲMeRܽR|qRSpcf ϿǩUa2bv3}.d0~s5c +ذy-c!N♘q 2Ϻs¨sM|a-lvAk3jHvWn.o3~x+: B0N$ ZDHqGPz& 8kW`=q@b#fɐqB_?]b/W0p>>u㝞z6X0< |Q|dmōX:q1E4s]g~;~g}1sDӇX~ Kw7}so]~b O [eÑpc x!$fĐ3. $pp_@DyB0Ԛ#ϥjUUyÚAG0p<ә6AÏ3PB"k>Pذ2WH έUeڕWiUwwuW[UUUUU[}ۯTo,YU5S+Nh**2>WTU~Ӿ[v2<. S 'Ҹm_&MMFEi+zvCQ jAyW6U;%IcCkO Nʐ`JF? ]6w!@a @&Ūm H>o@.JzI˻H('뿭EW<)NV0*Pt4&Z2^<9֕_MDG\hyV̋wbJ-g93 L=EE%#މbNԞ%36>x<b+TbX̧[[>b]" 1C mǠqqFЛ2 0{>㰴xQ'@2Y+L7,*t9 P@\ D3#Ta>3clKP}TT&(0l<4Ūfp\PPGH>o匉`T <]=} VǠ{<d&;c.}s,™pD3L (@ Wt'Gkk)|֌AI?2#FI[py^geU#x_FΣZҜn9J t]90/$P~10͂z883hXKĂ׻]-2x[@@$O<䊅m&}oM%>EɃFL6J`>7?ނ;׮&j}h0OǾCBsN6&qr Bm|5Q1٘1V)c(P-A8N()B's|w#N>4Rk ,ǫݹK8a!lg%Xm(9wog;H 36ntцEs f,b92D5ö G9G1uz#pb3{&f ڇ;Ai 9ǣf~R~:]ę$4L Z1u{Am:A8w HcGh%s nCnw=~yA%a}gowÌ܈죋Β/C\uQLNE\譒UtIʊo5hzoǭ\+Hf!ՔN7U" /7礁9c3T՚885ZNo+$0y kύ/OG5r/aL|4RP]&hW/Y3>῔y+ 3O6^ 쎡g)³޸N0o+3*OouKgn!w\%JM4 O>bwLN㳏_ 4٪l#B #skF17NRlGyQFkZ<*<>1Ὥ:k" *m:ʏ\T==5Ź سEqK=֩dViI1dOHY+QmSaq%12QHW VDȱ{ TPrWMSg^;A}};! n8zڼ3{9M7BF__ F_YTk>﨩*I&=2Xd(v$S fEIE%هDcB:JKFBNձfWI)~o)Iw&d~=rz "ٓ,?j xHzsCQvGC?i!N7fI=M f-\ ^z yW,NApѿq1W,z=oUV|96i"*JO-s%LPX(d}YL1nNg^͹[3]L &E,{eem!3|wTVՓ$DSoV1l,n篓ܦ| 'Hpix?^q;4=,ǰ]o>GơED[dMAz >le*>2:R6Y!;O6n[_ עj%#|_۾!i< Ͷ[R|C䐒HAtd!#Ph W24XM1 e<-wo\yZXEa,JPGYP]2D"'3pbM-&w '띈8P';(0yǑrPeǃ=bQ,bbo>FǫjqqOIrΘ_ӝ菤 $ߌpSc{5@&AHDHr`A8l I` ϜHF,"Cv&[[n8V:6|s0J4pKMhWj" 5]0rxlsPti;$άU#y Xm(Ljbʿ+!W~&'|OKiQeR-&>|Nn) n1w5"զYrd!]ta8m2ssFVŭFY왘8Ui߼ꊢt lS񭅒ڭdD[~^-#@8 3)M𑑜7BBo4asBФe3rcįIxz̈4ZfFUކQX"h/%2Z0B&UzܣP(xvh@nw fU 6*e6B-(^#/FQOuA,QԌpeJwrXe[35KRtKK-ѕw"٩s?g8$9.=5MUʣLi ojjyTZA3>KDTL||ጽ8 [%Ic#Rbv|hOTٔФڇʿ+nW\}.]lsLyVD<ųar:L_HF1"<@#ٓg&cn(߃r.:/:3#>X ,` y7ؿƂzzlLEvنh7Q8p7JeDQV+ji$I܆[`a2ǬqFZ<^~"ǵATggypa;Qaƺ_t#Z(Lk,kHNgRf^C ?A ~Z\Y@]DSᢿs }7ħ|2׹J\AbCeO?|]{_ @ב;_%2=c>ɉEo~(\3\|YtyHQ3WG6#،WrtoLoWS9m g2y?wc*AC&GܗM ]9GC>$YϬ666{"j4١4q4>O_]/V)^$CuCTwS7^>+Wxe+bQSK`9p/-)+d?DF>+HBդP()DmfAt}}M6":ʗ,mٹ!PeQL3:(<h`"v0vF^'#s/ɩ^3}^1{a:%7Yq)!X8%+H*YRe<(?k8D!bHsWp#ITKמHuxмB|PG)`d2a&yN&g1go7wN鱖c{ i [Pi}ov^~l܃*'WfWx 8rI=aG'78ЁL dYfV+@E4()i7AArjVM+5\ >>DYO0.qkUWBոsmDc%фTx̴L%arZGJ*WV- T~4QEnJg?|i`#ly+&QdY=12O,k O[#)G_SAp|y۰ʣ;@F8 Eiaē5A#JspDo)A&͐ͶӺB "N,WNNدf0ɀAz5y'6"ji*4p,#rfO8vQdoR[}e 'uS)o:ޭJRj^v4a iL6;G=/=Bk+.sPSTqS7//[6vu6W|#˪\;%5C|g)'$ 伩C*dZW Jؒ ;D7ɻR2/:uUyu en0+ 4&!ϴ, *)Nf%Og䞣1ua(LX /G&R)udy=A ImV֑F!N'IhIT]1+1Goӯuxt|wǾ!q9L>1WϧYF.Lx`6cф@R9P.]auN?Q&CEyEM?.C򡭗3c7wgcYEʤC~$PvyC M{$?10g^}{=oJmF,\>g7~v{2nkIhT8{Bye6l!!#o;ԑ KtkaD3pC 'w͹drl]Nj- E繬더̤ed)u?zx#R=\s[gUy*s6*hmƑ p٨ش 7R仡Q*dLm`|zeؤ%;dRcg/|}Uo8殂qCnט;ɨ5<ˑy³obC8!uL6&Q %RZ G%7Z0F8:0i ,gITkKu s_޹@qYCi1 \g23{H5}c|-A8k+ib^vZ{74:9b:ymgo5,(Lՠ~6I#;Βnfuѩp6wC8΀kG5#rN3 Qmo}P)Ugﶱ8rj2,YkeWz*< ˮǁ@ISN@a1g cK3MpfjEeCblA83Mr$3^6uŮoɌٛ 99:^j7$K% b]E`7J[ F8WtVUVq}fOlvMky$#^`R;*ATUPhRGSa{BkA)AHh,ZiwH%IEs\wAT Ul4Hr p$6vzc#Gzn3xDM(l H']jS!|'$PY1#C0xXfTdCd= T$:Yk60hLKlZK_ka30# dqyBo-+"i;u]ɞI`ʁ1.5?Eb$!yc9jb:%N%lg'ʺ6PutZ9CeDGӜQęCs4h3a=}%Ѥ~T`S, uJҬ-;K ߾ S~U[u 9X7xmn) q8:4|6Za Vljrz}<|[%y T:Ц@ZQ* 1#Ϟ3e֍>*5c>L`vb7`)0)e3 :g9k$QByFK m, \с!%a* 䆏vEƸveOSRٲgʋl_ˣ,V , 6 KF!P k4{|JXLiBxmC`\Q7Ih2Fsc-XCQAYu=8m[^׹y+缾7=% MIT}Y-Td@lek!ņ*bOB딸3qCTM÷k"]ɰ㙷;U 9(pQ0lU{EgTi{@iB0oNYFD9BxZD8 hw\ҿs-}.K8\^.1"-+iBϦ0>$>XR="N]]XijMy2(Ѧpk_ZR[cpѿƍ-క2]Rfbrs$W&- BO}}ϚÆaM"ľ>v` `C: Gʹ,#w Y$6뽎 Ƙqc 69Sm͘9Somŷ2oEZ3 .zf؈/KA32ݣߛ^*ըlᙍtK~PY=}.=4MHOЭՆ~ZlсM(bC rB~AgOo0@Apfkr- ?U'-+!Ժz+Gtk݆_&#݇B[e)BFJ"3a{wKW|̫tftE[V}nɆ>whL=;.HKwȼ8qcsC߲IȜh9A>>s&z Bǯ9'g떛M 16I $KHRxv# ;yDO }p y lP3GՏ"RƧ$X%pK`@:|~5J69fPy<`-eRa٢U4l,1_y匯il2\;^vO {;Z &J\~Sn㊍D؇dl/ !3c6s3!"xlL4?\WUmnw"#CfqX5)*%GP}UuU0dPtfuUetZ'}N4rxwoh/wDWh …GKkQ*fbPr-AFSU($oQ]ZMx!mn 'ۢ4qypˢRO׼C"4f^WFS68kqqt{l%VʄU΍ܨ1FVDd?%UI 9Ѹ99Ĝ,9N3߸ͯw.LTwGoÁq *V1'rq($&ЕVU|&P;sT#4;2cA!⺜7hgP p|ý>5dQ,Xxpp/RjH`{nefM-S|_?k߉0ձ8C&y@hv&#Ylh($<䡝/u&,9 ̘%,g&эƼ.Eӑ??%zſ{-vѝ)jag!ZlL%q,qН@&.7K'U۵}|UvnayBSnvvLJ:t$ [?T" ӥK7_EXbݜ9C~lH$㋈TaL:6 F}}ԶTS9ZvCt?@NO8s g_ egng)7=!la [&px&*4k3i|SWdޓ?gF @b'?dCKK)pPg Eӳob\JEtQ"ٲ8n!+*BOo}sWtD#ܘ2Е%)4?n<5AKsK6WswzLPI[R8jA gM+nnL֡"JflB@Pq KͲ>-!3<M$XDv0 #(CϏT Ks9Y#hh4Y wgMl;?d}Uso+ڻז 0|HGҩ4[?w{kVp˯ASl0HP<`{J Sz9kcACVྉTql6fbP1c_=^3%Z#UU]"h׾ Af槚Q[M!Y6FnPf) Z72 x[(4PlxY;*͓)'9#?EܝÁlbuXM)VZ^q[\.SW_taSBS)I8|,!"JIT@ >Q|t* GNY߰j]b] Okbぃ4}p00ְʊ'LSWA1OO-6;dv cSY(cj syhg T܈fHva~zV'.+"syDya>LԷu{k3X-j;JkF5/8#4ӫ o7 ۳ALj>?&Lt&LO'~!NrM·M%vCRE74:%)8pqxjPAtlH hTY\R1GsL)qlޓIJC 7%8B2.aicbDpR!ǹ o벗7:7чJЊ]hdha Fq:_7f f#ՆL!oƎh۟4ILnLeʱ 0vBJ3B!0S6Npޭ/7vz6Pk>3Ţ-W>ct?Yׅ@e4CUlc B9Wej~m^'F'x*"PZ_V:}@fr󙷝1B?+9+tږ:IO2+ }I!_]"y~j? ݐ^ByλvranB!eRţ&XIއk*#G;Mٞ f4߫ކƵ KƦfOP׏ >KTks ׶a^=0` I7,z=qǏatZI:7[\l a8dKTš^*l=-w-+oe&\mm:w\E\7{UϱףVi>2piwh>_G4e9P0FiL]&-B:qXz f;ctw I%io~UuǕsk.v>C:( -Vungh%gP!dJz;2wwFj[9C2Bf;%W dql;,`sqߞhe[vzztSV&AV=oݳ=l@v4 ]_W~SFјͨτA9pXu)WVե ZOqiwQ\XR5ewG}^s42r^V=ßݽ\kYQ$ 4lԃ?-푛g.st~-1rT '6n7ܟvO윘npw䇱qIs%UljjPx'Wo6ta{jtYb\胭rS`vx`ou+8 cK;iVf$[ Pvg47sEcY4V@Kzo2?h۟L!f?_gQ$@>oøო~4j̆,P]:ܱ'F Elez}Bv/ mN gY[%QK~ &d0E0N2A6G%Z>q-bT~1'[3sr\Oڟ^s\xLyJ cG ѽ(tuչ(n4וj&)Qz@Af+ sJíDZ$P,%ƤhZOgŶI1vW{E!wb1A3ϥ (J;CcKîXg$! rDԓSwod}2z? õ`sd,![pxCw tKÍ o2'_h@jޔ0doĥuL眆pD5?;c=W,i2jj>2 lݐm2:=^Onc i~9k82znB{:Sf;0hTYAqICQ{bO*]jIS~,q2]\oV`Jd_?k)F1`}eZJyߪfS ͽ3gixuY&/Z{7h JpPx~+nWLUW.؝8Tp;z"FMA&R7n)9-4gec(k@6U_'#T6Tus\%%Z5jm(7?1֦/3Mn.. ijVc 7;,J_ :^ qt!:l' }Caq_c5vR5帘Of*oCf;05vA1 X{-Yx\ש=62RCvr/VZ͔I *"ITF;8L+!yGL>\qH\kxqP]Jy)%HrNc̈0Q7?lK6'zͲVeJo^,IρNDX.ӌ/ZJUCw&abHbyNRi 08 [tf B@ WǎJ}Q :/zTC$o]=WZ$kDߩsSP;Xs'T0$橥g {XDftz[jv:Pn5S([;ƨ"St<. 9ڛㅪ8b 0`Uof؝=+B{1WiԨ2AY 34r9ޚSqSd?t4qmDq[ffw3sO&7`@O]sV;vA8VoJӥWLZL6)3rgIW 5V8o)\H䬚Y~lX6wLS T,rƁop|y?ouY+I` =PkpM$]J%&w# DrV@˶LԔ{0 YOsV%*%1̈0Qց%Om"~BµMur p{ة~":'x,:t;RF蛲ƺWrSq=(bԆ=OA0 #f8͙>}#RG 6#Ie"c۠3҄9yx_:> &VqL47b9-w$t2g[Ҷ׏W߱c<[;a +N$Yg&oz\'̗m;f~_gcВ4YK/b` `l O]N"0=]k,k&JeN$$ڤFY/t_v%ԳF٩:"҄>tai#ޏ/5tzPݼAX_;u5r m1@qٍfj1y4_ HlPs]22^|A.Ƭ"x>Otc~:!aw^fNT*Ⳍ؜ScZ`MjAlۯ5ZvatFPl(WW?$LH_?$cq#rği gI<ťwhtRAQLfUNn)'do)HRgq*D'p\&ǢVO,$$Ja[V_uҤjV?شN{כrXqrBuK1“+ZIu( 7zt|پ`:j{\ՎJzvaV&cUͥLf'2$BWUSǓ#*cOI|fO-`VFY> WJi_U Q Nj !$L!Pm>7\w2A/nY$g+I[ ")i@*yA;<~S* 0݇e=c)R;pӓ*U`֖Mwz%=Bw/oWo}6D- ;os!^޹(G,(zR 9F&߀VȓXycskCgH|\uvM5MiVjѴv/S"d^+e[RVWfU볽ؔ Jʛ pN_~,QHLDͶ5j^.)"4Hr͍ia'ʚƶ"7wctUl%D -">uu42ǏLq_T"lF*DOچdȪl0Ķ ᢸ\(]h2AU[Of򁏸qf烪xWr^q֗9HW<B(\"7N :&:M,UZfOj᦯6Ua%*#I;Y c%2 轳>8zzN֏zʭM7]nKk*ЊPƪ҂r((Yl +xvZׅn+;B/0εKMeS%'[NJ^)y>iKDEJ4/5P" U.ݲzi!! 2 Dg+gKNu/>Yt)^r X-kJO8&Ȍ)yI$u+F>FUV9ߦ5+YzPprRM+kѤa4j0Y%rbUi`)qgYG_2h]=`1rJOm8pd;eʝE𼧜bIz 748ZV|<[C(qG~z*꿟- ގ iIyeN9%M];u=zE5NW::fh8;S:hz͇F_Lxa)@l:!+pF˶b] Nnk1ByEYf&!w_gK98'[F5ՄwQږCֆs->5HZ/[{ ՚(U(vs IpЭl,0 a+L}zcCB ھxC38>#K{FZ{ Z D;~1 axg3"\xY< j=4hs oR88VAa ]|$iG9X}>}'K~)͌^oP3!k2 |m_t;[Ǯ /޷Ӕ51I $ 3bSv6DMjLO*g7^ܩ-OAhd"ܪ{璒u 読MuzˇWWj }pVvbr2NL +&vWy+Z|wFWH\vi;czxsR8Pdp|ѵ4(ll*P}^WoDKu$>Nö}3ʆUÓ]Q6_G* J5\qޛ̏ z"y bFq-_7MDRRb}'#O5$Q ]RPٌl/ħA A!)G Rv,m@6-:d37)ven \wjHZeRza5V W_^TUIykoX3SS) ^w _'TROB9.»nw㸬R]2P@}՗ѝLv7lǞlpm21tvcr15g#<9ʅD"0vk? x\1A1DU D %#sJn*hyQI>Q.Ǐl=JmEO?MޛNQܿ3D,%q+GհDٗW:vryծ:k_ɢP1>k&q)ˍM? a1vD*|)k•Z8J]s3)>:c)^rbS68L~HO?}oz}W~Nmo+#. P~nc/Y[rjӷS<|̿MWPoAdgFmʒn]ϗt9G%?QJO A1⛯1PnwJMfy#]տ,Ѯ;ê<'c#M,`vFDx7u}+gcwt?~;$mq^$+M7mhZeWܩ g88c= Skֈxov>3o c p&לzZw|;-Q΂d4=.̐c)hMOo/庴ڷv>b҄]t 8Iu$:on/Dn|0h^d]C_>``sF ⫨g/WR”YeY=*3u9'm7Fە7E W]XƖ!n`p%] (1q, 1Z4+ئtS,^-7cD3agkF÷J:} e Hy4bt!#|,\a&? OǔER;2;qZh=}`{v}L?=}|׏#?׻i#s#?zS1>)oMy%OzFm `%3 5IUE K0A4$Eύk gR|= P&Gץn[a{o\Gj Ѷ#:{iG>(<$ M3@w7 6Y,`5-j,޴?d4?H!Kus*ܮؽ!ܝ/È]&SùC0$ g~5JYhUYf]VEw_zoQ-M3_VlYn},5z Mw[1[uwD(DB1 4Hl>3 3g5l/LNѰKCfN H/ĴDD=).7t͝p&-HoDρwřr=SA9=|y0vXȁ(&Ź CK0{c:pc?q;x} { C{ں 'boZ;-xz~mOVOynϒw"ɩqG{H_Qȉzx+9QJىU5s"pk8쮨Ä$E$@d;9 ˦1A7&w!%KHG9X#BLVayX" E*UP;i.:j^AvL󷪮 +R7 xjKGZ "*œȉ"̠w*8إ'=B-щ[jwnЈ&PG rǸ{` Axi7j 1\ۡ@n= z3. 0D=:c?_VGd7ȮλljK>M J?|pa_,y<92@$r v 4}^Lh+py?e9yK^z5ʈYiY3Il &D&گ &ǰwk5Aj[vRt;[ωF& igߗ;~d&89u i4aАlgeefCh#b3Iu4ss@,Ae!#_` %s`l%uo yw40G}ݴC$OkĨx6ym,t2Z-lg>5 b?|o+L c}^nOsw[9CY;C~{ɧeE#|yqu43l۬}otz)&|0r^}3.*dQ?O.,a`"l`+#؁%p#zTg6þN8PajtWIw,} ޹0~O8W_D>2I $1?oAAyvN|Hmx Fk+d<>.rL͖ " ֐&NrywSbMBo۸ڏ{NL_ ݻ x}yUg Ē\"Ä́[I "UR+?,',,#E"a9N:|MLb@*z8~~bSNgy ׋ >AyeS-;[߽:XI`rjEf~Kp{@;\Â'Fa3䙢 ; DFcb#!J_*/嬖F @dBຑO%6q.CHH?CXE!!1e}c(rxBB៕x߮?ЛX9O(3;}((*kc}|XyW[88$F>7b¯I:= *PR_ݟRSoH]X&]S~~Mz^M ; DzL$ФHnvO|Z E@R$RTHĔ)gH t7gw(PB HAAݶw]KF''|Y;*2/meKB7bH=D}ф Ť,<;7fc,# hf4h147psT8&gπ;`4H$&dm8iܣ곔zL"Q l/-cϣ+j }<aRdfA mjFfty9ž#3R:<,%nx= rDϩ2>^f3]eӴ9&ԸEЂ[UT(VT}2I<;()GwGgPf[o4"-ٳH19FJ2J%M aXDe-rmFDM+0HA)@9 5G27J4SKM%U÷#gݏ7Axt= Dte쏫 Iw *w]./@]4;xf9Zi֍)h=| vӣ] ہSrw {ims.9cd܇ }K[b[A#0Ve&!1|ڕvosm\vFzy{Q^K=o:vʷ5]%_|G'PI9uV^02'G &$cV`MTѪnVNkdޭH"e虢+BCz)Y )Z*}w?Jp9Y9!,C3s&V̎`à-8"@l9/m~M=Yuˮ>RW;aV{Dw?GHW6iZD/Na#y9gᔕSuF\jPc! =_4:t3qefru>NzF'<FS',夤o)ӷwSެd9lteLJ{dJS d`gEҫnPhjo< y9AI7]qc,2F|/'(wjȣ|&ePsS4:KrrB_)˓9gx˛A̺)tH'8`CLрG}iU1Lgdwyp 5lLI.! 6K31G1 1jp >K\J"s<ﻱo79Ui#6[;r*Z*D<3g9|׏ՏciKl&B߶ 6໵l& 0a VXюhqM\bziQ˜&g=Pupr\m!wAo8`gnx- vRy:HFE>ݽ! ~%BiOp6>r(|3\<ZWi8O}oir }tuPEçiJ 5+zɖ{Л`, M\^xfT`8W\?Ǿe]zaOc75q&4Ϗ{zg7fVݖ夨us\mV"Cѯ9͋V3݆u^;8c&f_9b2BT|:q零˖/ѧN5]ةDrŻ8n%.:k ttTjTZZ,)|KoEOyۣ#+wbiGV~$.(J{k7k(_:ۺb)ze}ZP<niZ]WNe*>dYCݩh>XҴwwϞ폙[C1cpІ%n8:is`dH&`]uTi,sh_;}S8cAK4sThzzA&\`uuVއ|0aS`홸ǘW0:U th \"A ,aNMHi@(= L)HҠR)/JͰ8)tl )aM t4(q: `;ߜ>0`BĪ:$@ DP`UzTzi%/Gݯ;H‡Pu/qЋ@ !|{{Dq⃲Zc4Njgp >|mc`t'љjӧheĸ Swd:PyɆ+b!QP\.0?|7lۛ1!Ƒ3 dj]cE0C%banq Fdʺ]]0P;*^RF:PiBPcUk{wrM=G`̈́`,0|Dt H! K ~8A {4EYEX_?1za{!r?l$9:\ڎ =C"S =x@' EO&I?4_}+9mY]=;kS.7nD33vȧuza=P>yhPfUb9A)(h"!J&)o DH᥈hJ@")B JPDJ BR% A@SH0JPЃJfd.OY:!Gzɸe @@$  )(`)T@P$B @_F8@]{(sB= VBHT0tQUSV_N3!x$(zD{=#&)V}.f>> T+}, |N sR<A~EN؊]ޤsΡኘD7Y*s%T,Cta"Ht Sj1%$6&}6Em\`9}SujL1N@- .@hB dOF7y|0Ȑ14R zN"ۉIPKϦ(FDFvmCBΌF{+$$ԧLgL%z DЧ~CfIQjC&S֋ ߌȡ_LU=7n!zP ޝLY t7ߗ^.3t_O4o6@/# w; !&!-㉚d%Aqa^6,LGac}n&Q/<%Egp͈i;?t*.4yg/dkZ/[ zsҘ)twH5ԼE8aZ<;q?7)6;7Nx7߿|۟2W"&9azznK"ұI|]=ؕhJݖ"\ccxLpl65R6 R_P#.!fPꡚ.mx`V^,M1=)tt1 yg󧒽=NVT1?ސx_7DmcUHыgjErPl/=i;8捍/::{Xd&`R.2eNu۹pgIN ; F! D(C%  ґ0b$!cN6~РڢJZ ~r9p4̑$qB "$Jb)%IN`}? o3b?+4c.Ly%Ow˯ D`kٕ_uOLδfoH+Ze.`fӒY?CS:re#\/G1[O?/-p!CW6v}sޑp8A$C!!'Sg}6yLzvm=O4L'sa“r*2$5}0(m7wLiͰx[hd琗}a*"ԘL'=ˑjgW1G rRLk8ew6=Hj ` n?IQ*$A#.ܥ'88}XL8,;:R&.DT A+J8Dt.HÓOG>MpPF] $BҔ   `9%%.I<8yў# ϯ<.jr5Tzg`/inoY`E0>3z1PH&5P31BťvnVFU;oJ}]#ca18@ hvSҽ 4w,yؘ&C2+1b[bF͊_B;" d!Lq6ѤQմ '] ;jCnϣ#PgNCopa֞1Q(%r ۨgAmGci}.AMtޓ}L;䳣Y^(Wp Mm^\HZc1 Ie)ϔ)A%wR<Dž'Uk]s4`1+{ X߇ Ksu&n&~8i9[7:I:/rS])."!HM]vG)Ae<$pppeŁZ={I#=#&Vz 'zQ=;~,=e8PsQnuE+T|, h.,tѥJuΖIu >(8N+ZR?[ڕř?~p|-wN8I9'P^1 5.#ةiO)rn'O팢rWII:<>4y)p=߶8cKōI2B n𹹒IhXQjJd,{9KyiqԈJX( j!j7Ek/fsr1:ZPUJnאּ<0::Ɠ$u\GZU)}kZ ;xq>FS嬪.7Zv!Xy-<4č̹Tl󿓟:ҷZ%=^c01@\f)J-ŚI>5Ž/%* 'I\LwLF &^.,)t U&RΆ^~3ptP><\yhJOs{/"3|ynf!n3%1*UxTe}m迳uѥ%BcڕӦ\nl%oE7fJ4?V%"޽y{W> ?͌2XF?Ne&pZZ~a>:t= ]ŽW|=@4؟ZwU:Q ~L;t9e+mĎ 8:kٷqs5McM;{yG_^ҝ#v*rQiK'R|'f&02hqp2 uBDVN<̼7okǻq{gxyB1/{v3 cp:S:dϙ~w C6Q_OQJҚ'B?#̛""[QQĪz(Nь)V,ZdHL!@qʵcqSmѪfejN8yVegnm]a9Ts00I&+xKi*p&Hhe:c3uվu7ڛ!C73yɦ 2ݤ|KE+:ZRz*c_T?ߴєͫR+dCe}i|q*ZT-)⑹}>VX#E=[Z]N\?/xŗ +ju 6lI1#u-OswROJ;QpE|pySSd4=#tgXln^8rҠl6Вyoxo֦1ʢф?7}&m'7Djn&kk= ZJ/rh<1[S0?'w|Z9'OExWz*+&],˗R6k&LHfV%D k\xԩx^S:Wi{g*3!ҜNuCPI\ڗ]fLt'>/)|?C6Sbk=(x|!y=ؽ (jA:@S@tqf<&;*bfzgܯ^Q?TՎWFGOs$< npf4!; O>! i?ҙ XuGLۆJo%C?gDu'_xe٩G{C_)@~*04_"B^סO%o'$LC퉊>x =KО|ոM 7#%vЗey6LF. T7z%\M"oӪ!U[+ۛ\?U$s;f.3l 9q( ;qg8JȀxO:y Hpu$Hhi:76nAM1f6ͣllb":YqӔ&0x4T™gvvc\=Gic)n,ʴҦz}HxEgC:cq8&@lQl^L7Al5 =UqH- 5K`,w`@$64h5*WKݓK-ū= eT0r/@19jJBP`]B-I  ~\0_ӎ(Avm$n_7626Tʛj48ɭYqp_<<07Y݆aY!&H4 $Ғ !!4:ʕ$1Z)vIKǟ*s DݸY>r=y&H H(2X3 ճADZrex6lܱm!-Z2i6ccM-<ѝ+LF et!>;J}ȞT0 ̆HQ}|[>>H,\SEA7:M2{ @/Kr-A羀tpTn47 1^<"N$ dC7ھ,KQMw|=E l-Dn P+j"h݈e*-3  k=%߃;[$_B&ȭ~o I)+DŽO'6kۻkmVQxXMBtE)'gJ'Vƍ@k,9'TYYV,Iڢk*;&ooa~;ûh? /7#^dUUUHB<A9AL(h Tq[ВmAqҀq_"mL= niaj ?wfytȜNnÝ9~YaO7stz+&f3%u?Rk9,%˗ :ncun(Q2 0kVpi&eMAF41Qp&f:cR8`oBC0$Ln>Mca//3aG?:K(s4iwD/톒'`-5X7z͟ Ϲm"njec#΂cA} a=Y}_ _9/H] ޠJfSpn5u~{+DD R 09~KB=# QJI~+4 *4Ԅ tu6MYYH|]IXhri"*4F$ݏ9Ae??{qϫ_-tOg)s XtWna\_;~FӇ_'ž S(q !B75RDukí$_x9/זabc oܟh&] m¦ &tB`[j? 3fv}_ƿwmvZGfX #h0xn+DQ$1 }`f?yf՘ #\ޏ>o1k)^J̴h<(| 3YW0;4NBlYQ0?O)frf~ZcݱHLvr1&`ɭQO^OA<7߸k&3GQ QofXd7.yXf25fyC36ڤMJAF f %ۊ?BP0\bɰ0'GXF4*tlpMDC:X , քy^aR苈 cٵRS2N;DaL7aBŬ lCY1@tSrklB1LH$ DЩ2) \'~6pf*u6LdCFF567ndAl|ni_28cѳͪkŘvc{~TbMgʬ*+)6,[Is}L+G?l "n;7щO#ݑyëT ''.2fJNr` F`l`3з'JAFvݣ>{= D 3$ Й >ȷ%Հ_}~>'a"He 1(Du_/~K0Oc[TƊYΦQIݚI]Afᣯ^\O%:KCX0Ri%1DT}[N?}e!^dp4 + g?۟J' уhh rtÒH#{0ѐ>2 5'% UZ6#{ԗC?;ђ@=>vr+)mv1xU0$@X@#$RD`TZRAFa D* I%@Xd1! OD 6\Lq%fWL"D3 :9powQ1ME D B)9]BGb]/y*+&X򷠿9_;U̴CS@=tUWC,$K0VQ {Fx14ڻ{&1h0ϑfcnR;A`TـƘ$&Ba DHlav_=?){%RqmYv -Y40) \:{~+*&H ޫ1n{;dwBܸMgI!~u4@ =I U;!fi_=X5R3!n޺QɃd3kaG&5 :(LCWt85)P}4'͛ hH!/E0#>Z7x7NF`{6 0dU2Xm6 pa>p=l݈E>P3 yG/{E`EүC0(e+ CR"!cuGE8  #0O8#Z{q9i9bh3;HZ8)G܍Lƭ5f{eS<5JDGba ؆f)Cs{ ~p/s~@_˦a~?GqCAɏo2Sv0? nv 눚)CX<.cN~ 8ð&d ;Xk?5Œ!2$w@ҿHH~n\z҉\s?NK"y<>"n&56d~"Ɣm?a0=@{a fa_|y^#OFfsl@{w :͇f,% G9r$&irT{Ci^`X%1ܐz~I"St!A?@(7N{`k^$d@qA%d F(O@ UMKJ5$ SxW9aam %("H/'գf} kB=N@xUOy%XSBm@``!SA|W& J D(t0IF+Ӡ3М'(v{ȃbzY{mGZ('J:O QCǷZ@4"}I.G Cn[.@[P@dd7"D<]c4Ae~ E:9È1%%3:W4wLx981()AC).Pd|̄s$9z K3*6} 6'rŸ lQzqMy>$Z>(i8IWPI^c =Ɓ0hta9p~7ǸA9$pIx+q~=I'{J9DG1$(/^OmSB.TA4,En ҭ 聟~G~5UUEoڲ. f F("((ZJ"*hiTYa!&*H( )$J(")" P*"ij((( D JJZV" i;R6 B@Pİk RRQHL\ ?)uƒ+=&{S Єt+%vwObX;tDaȘ%/;wh]1,񙀜$W (-'Eˍ >+8<(.!m#nvW3﷗!S*u> 6(r`(" HSaԪJ~LKN6nx~oN?8w(hG9b\.JBm 4T. H_/m29 ׉=^z;Ƶi֍R.0CAd6 Abth&: @4mW|u7䜡D}8{1.|I7}|QyKaHHםv79I ;L1r`1 P4fc1sAF,%\ltO6 ~qșa;vt9v؈<T@IRA) vJò9vgxCBFn|Ha|* R BXs}gj(ǫAm}?/Νw`^:|2V7ӼdHP zu^$`|ţ1: hD; H Vl/S ;}te=ȈDS_TGxPC~U@yzȳ9]5`s8H0B̅Yݝ'C˔^H/^'I~8<Sso^x{mC~Cpuqјfvvs03mvĄ,0Q&f]7yHkn)&BLF 1VQc!N=c}v޽'/dR˾;HAoFp44!z4뮵~hs>n պ Mȗq/t_ޏN9FF˖鑑׬AI,yUUTȠOѲGv;mG1Uki]I%:M.k`b8fpC<]v8N"I,;x8ӄ <V * j>UL. ֞'sS3&rbV:w$ B0q 5sZ"ȧ)>~7q( 36^v)n]"-*BJЈ0 Y!2KMRr,5[qmhJt1Gq mm셚C) "tqTh"5lQU. D޵R!@) ( r{ ڃ3&(rO ^U]HvMȀLȊ}ce%nm_U"؈ж=B4h(=~dT4&.Uo6F68y*璍oA56+V Uw#U=BOςoa+Ta9NUQv*T \J z` bY7BQ$buQGK9Ots,{hw*r^qD=>X<k|peU\rTm/m0Tuach59bS8ljbF"" gDm(@R\AKF 2'o}2!,zЁXH\:9UJ3USe^'I;kQPw㍯cgEU-];:}(L!F`\Aƽ}M5ƋmX[ da~|;uSAvA?͈ 97]̿m퀰)mJ( /J|i^nD뛻UUitwz}LrFXcha6q`\`Oȝ&P_`L p]\ts)ǘc@ ؚI&?BKZR. .߃\:N4J6mpWlwHATP?ZenѶP;oES<=6߼fi Rq)3#Jh!drWN%6ȷڋ%)L*0(r1Ur }U#:z7h"vnfT OZ*~l.-hLN"(jN;=)34RE{.tf?,x3f 6lvc(.!'XjYK1 IV\,f Uf1ܨGUU:, q 4THUCE'$KJswCqA07p!딆}rRş=41+ME@t9=k]LRH'KT'{/)'h擅#rBDS>ٻ&vÇ/@Fx@|ÿ6;]dGТG dՊBlw䜧&&#B`;HNaxRRIT'Jqx߿q )F Qtxb{s/eAD:v |ޫ<eFkSa̾I($BH䯅(Yav<8?QGc?ӳlfb,2e83nqa1q3CZӄv8hxx?n}}QSKHK:gI}sG!GѠ*wq"}D5y~/~y GnDHz}0r dpCmT)- A 0H>b s&J96}~~bHqH.(À`7 iP`6!Za@*2(}g (R0o8z.8.2iaxHbbd7Ƴ333336aA 7( py~ԩ;y'RbtgG.b)p:4WV="ذ풝|;0"d ˽$Tf C~j$tKHʜT}`@Nbnt2-2M<; A$v~񐁂#! L`.Gg7c2BbGAcz$)BQv<'=x|˰Tև]U4M)T0^9)(?:SQ;8  ?hiCwl$>#rwã}`!Jq2p} ,22, J}wc{dJŲ<@RE8ŗ1Aϯc(*zdZCY#1Ħs3mꑺmX*g8D0]<_y;0G{z#ň 'CHII t iPP2x O D*t{Ee)Ⱦb% ps+x4wO2(TbOl  ;p Gā\鸃a^ )!.iОNz@`!k '- %!p<=Ò@CyBȣbGvVpwO( Q𛃺=Y 0 RHD~V`a4]eH&`P<"bC};+@LHð q3| cJ)bwJ;4gPP,V1ioZe3_恟iiZ2"t/!:7es7[31ۢP ~8@%򃂇yV;&jB `݁uzl?]_SO[O~OH_uɚcz> ]lTn_`/շΕI >Nh{?Za'Ҝ C]!2u|>nbIs4ʿ3 p02 }*%8>Ȧlo70ڟv4_6unUp0333K]CȉXin8E l#o>R@6Da'JСH  )(s/zCV{ȉh{WFnm2dqPTC(Q a6o*Xa MgkM?TEQ! s鳇J &vi0v8_!}6g".–NyxGIiBܢ(cJ, t=\~_eDu 'E$AHu{!1TVCVf$sI{oET ,24Є.8U;B!Ӽ$E( @$"I\iOg/+?=}tS1w$xbD0o<:иyj<}gjR]Sۻ KQSaćWUsGy>A<t]FʆQRD)`*䋊\kRI#kFmhKdOD].vϢՙW] "m'9ω=z/OiDuӯE; 02HQ듀+)CP0cD 5a-{<<4=BtIl0EGՖZ7I&V(~G3@)^knnpiJb((םkCΰŨ_6h]pWSKuEsOg[3^:T!#l;kPCY#/ _j ZP0&grulLW*J vhA9DZWݑArf(9K]b QQpr(ЩZ TǬ=fw7 %/R`.7,e~r6CW}”q0jw΍=zyXI钃]ͪVllCg~ UF ۇ!ԝŔ9Ͽܤ/1G& zJ.!T \2ϔɻHa1ɑ6%}~< hB?J}ߖ6W(h_ 󢘊0rR^T [0T'gn0% abBVm. D" oB, r9#=$ !vyG'88I BH/.>~?DQ:@X^ $gp$HAO.^ u>:!< 2?Y%q@:JݸlŬ %#=BaTU !9@ , w$"@3LN(K:gQ7I&t4$,d0L7cmUj8it `cH m$ , 4Qي׷"Lq7!Ljͽ>Ęv!^Cb5Fy&!hj7(0EM=<$H4]oF1-p@uDCˉ<WӹGwg1"/y7e>d=E-3Zi2 |4r@40eÂw'| >-C #`!y0rz HJ{~D=؋쎩y7':@ č$(T= ǰCh9IT8}P(( ya142nS WӾ h$ ==Ƒp #ʜ½}G5ŖhS4pW=ǰ??賲w'RեdR%y8BulMW4?k;Nw&Vvu cX+"1a2h 7?~H?Qgfd?zyG k#>a *Ya@yNx+suɑyӽ?7?vk[U5Fv8R$F7kVJv_i#O>_?߯ #z98y8uf?vW72j->=Wpͤ?2? bο&80A>{܊=??odfމvA3w`{U8uA^|: =R$_L'yzx4A〬~QcO R{xT`8TN?< C]OGXr'A'Gc)!>yc1aN4/X}{ —N<rwţgļNu9h|p2=T-!qХ3227`l0l;;-snr;SY`'Z@H >sJajIv/$" مvWS˘nې|U1Qr3c†*ӿ?"=b]ok hmIԊJBJHI,R PHʌJRD ȑLJ*/:R"i! R(c:Z/.\\ PYlUcFݮr;B0pTj%o#GӒY ͧ!k<V:Ք܏JyNtwFS' ):޼뇏8߼E%zhvi8=uy:Ye}>NNc 6A.=Kk|^mݛ߼2Yg ['{eFZk;o߮a}ڒ|䥶Үsnn~ilIEwÆwϣ);pUn2uCL 0b\f :C8(dod$Ljq{XIZ y#}LW'`=< <9ˣW{䐆xH<3pfA 07G$;q٦)r@VlʕO) пEOf9icQw/JbH7y6X,KnάPc2z mp3c >\KZũy'l=B L(WW3&V 2~TAA!ff(8˰%%=x \-Щ+%2_/a4?[Z2w B[p- @rX aaء<;7޻9~AYH9S`9L&ʣѴ1eF Xf,7e-.LPg_=]Ox H<tXׇe>xx> @:z<+۾6ChF d܎l!85sQJ>o.r{\zp#YJ|K~[}oym#KK>{Uޫ=۷mݎ}vzQC-#\:of[L :J8[wWG|̙ϤGt=ǿYP V[n}ym}&Kh*&{!ɰ~'[[#AuN#l"WV=݈5|a `cr-?RB _>@mYf*`7l__GYUs2 m]^\NgɁfL;bA PD&$8W{})AOOD>{sf_9풂&WB cRDLj;O?q;Dx0, MDz8DJ6~cY&;AvG@#&p&Hk/0*fTosP\MuHGX*3430~OJS2Na< 5 ;ܠIm-K9IlC-8 q(#HmqQ6TI pT XD T$@~,rH2 *kuQp晩8N0d{0 sm7 !>9_2ad)Ί<ɱލC@qL.6_g̮s49p(}#R.԰ *-& jbn8ڤ)5s%-;x0žo=Fm}Έޯ ȪhLKѰ0w~X{z[l v{183Cevz\o[>E <{FffD.v1}< аbQ4VŲfC43"""l;0g/LX@2fmG ̨hYL#f*h<>Oϣ݄,x^85ֱ֕s1uѩִz;_J|G&`}N4E,զ c`>~x h|C#sv21 A,G~ 'ԩٰ "&p<} 0ɀ-z!ĭ1:! w5jpcOGKH29 pz8#\ ʊ-cCv=7rlp7V^v!}kMX\B@Fɠ1C{P8|::E_*xz+&Վa+SyIs7 xEUT+NCHDp! u;i<~5׽O t/`(be^G8MA$rgF4> xRācp@yIEH)lv-e!iTJn ʱZQ.Ud1{48T-Y*E wYS]Vr QCZJ$ZmE8IU\PHZGaFٳiECI`l6N#n%o2xGD3ӤQ[2T((!ୢ4Z<qx'$'h0kؓM;dvC1K scd 4D=0y9b8LѺw D'UTPUDDPsf9?0i˩ ㆒)]^Vlx@?O0LH=hp^nrkR{0ܜwsqjc4spxz{pCv!1 =ō. !$QM-ďʝ ϐNAփ !) zpB$L\C|NIBvu8Gnsv ! _kJR0zL;$0f&k3n2Ϫm@McHIhe" &c>LRjl45HfIㆲ7V@S>|Mخx _ pq8j]r2n)K0h6:z ȱ@-94_8愙(p4!T(ja`RÐ pNC7pfr@d,s`0k rDM*BZVbK.s[4G> é34sba nap̡ 06 #p0(WU|Zg8jnJJBsctȺD3w79t80Q=!?)@o}^XH /ܓ$!OO@蓅ND!0L05D T "E2y)0i:P ` $IR}qp]G2BJd}e0.yMpcB  UH xU(?P>P?ڠ{ C! [UPFI~0,~V!4EtS)CX J\ GN̛7RC{Hi(E7qpP trs; pjJ@ UD D ؈Lׄ\>Tt {/W slV"'GTAxbNo&aWQIABţA[ى mWm] -&Z E/ႁ#jGD h&PBR"FJ!p 3_w/]X`{C @DQ! nPWǵf;QL! j~x/j"p )1R >(N7M.Ļ};' ݯxsRts8A \bq !Bh`s!GΏ >5«pd94!*0fvsk ˣЍ$)tM*d`CAw`nvdхƱ`e4ZD13tyit33CgG%?D!É<B{Bl @<Oy>D)A21Ng%liq *<&C&"`ZjX( h?yϽqBF|zќyAH$S#t$Z.jj:(@mFy:3'jJ.>^V vKbki0@|.ZaTX{lNA3 8eaFYY%=_\|A9>JGgo"1(I`Sk&PQ(l@N mmnfA5&tsF0!}o#G5b -\ ;~տ33d^dh;f(lAIM5(DȓHMNa""`(h!b!kx F kB` O:!~ ~+ Jf lVq-д%bbQhÝa4ioʦ2t8䵪NuMpp,hBm1bKu[̌shA y|_O6\>Хp9-K٧23BlxifRE} YM6f H\|)h8% iR*BįzsmZ54)0yUhPE~__d)d6OGÑDkH' tZG I-XGYe/|~bh_B'_ӸPިd"бHHMBhbhcW^``c4${7Q[|.`Ne2|3|>8>l#xݎ>/HtގZnun4x%^{txӀv?(|y )@PT%D u@2f%!FF?ƒE  DABA_< tRK/m/NX!YN͘Oz۶ mNqim4D$Mt"+thM#-"@`JT)ǾA>Xq`!CbP. UU_ ,bb#F!׾t LL4J R#4@C`ut]slC7 >9V˗6j>`%(:¾ZP@J5B{ 1G+'m4 \='䆐9E  @>B412߈cC̾-yUZy7⡆lj|CD£@`=~HOx#H-ԕu\T>|nmr5Qд2"))ޓy@svb#bl>c=8u= 36  (d%$&]bFh >0!C$ ͉7t8,1 2 2tU.hc%ڱfsQbQbZ BE } RÙoup|S!?ʄ2R?{XPp/Bi `˱HX8}Y6mzԫ^wlBg$J̧0A$Vz h@E- (#xPL  l%RuJeOP'Z z!C>puHAd:CȞsݻ "Fb$|'%9z~_O %s̉eTE~/NZ~iDx&@0z man.XV1*c$qQJN)ja֑sBÔ9#QU3gQADc}]tUÔ 16 3 B:Ç) W'B.8#ulNÎotNT \tq8Bݳ ^q%G@㑕* l :H2 lObOEG0ЇOd$BAv(5CJ"!~[`qx /cվ\q(. S T'(l9=ƹC5K KZIWj c%Y0*ZyR\QKpk4r@-CхEh.zv.7&aBM0]{ޣI<|rt槝DщvcK4Zo%6ֳ-UFj7yW&>"S%2!L뛠U#aP L0@z*v14@oS)PW];1a N]}r۞*my4]YÇ;zDy,_'cSsp#jmBQUvfcT&!["E0(iZMf]3`%6 l9%{?0h$xOgϚvfu%uUQiV0xbzt lq 'N%Ɛ4Qd8a]:- cv<ysv AA@t=D NɐrUfbU Wr k8;6n2 gi`2,ݡ?cqT=#|)MvR->%Z41y{9@߁׿-TJ_|=vkTh0\o,>n;"Mij0.gy9a\PR3?py$ai(( %1tyq'8pfd#@WnoHz` '}} 4ƐA_$RQaM#sؖT֚E/I/b S+"GٷFbayHjM߀z>y#Wީʱx4*b"n?РryvB4K@R&GA8P9WԙaxhXO({o7H #j (C_.JO@8K@/뗎|P`7%PN!MСԇ<@EJ5dMzT'z.ICdz˫5U?uMKa014qCi;&6bIC3_.l<ʾ+YԮ,y[muyr(*5ݵ a4^lq:4'?z߸L}7?oG6MKq<;;1̍)5°IV IGHffV~_bfy4GD"I+)Xa3G b\ ?v_"_y!% S<2C`8tsPG}ӡ)CW J>@BFbĒ$ԺU(?"W/J ?N>`Uݧ|)nn"ѷ101ptX95 .sg{Y MHyK>j$/Y;ϭq|ï]R6TUNw:,kka4D4+q,;z_Gאe< GDa3af YIe&4N!S&<[b.y!@S`xWѴT11ˆ#ЁsXq @"uXBdMʜB"S#2P"6Q@%LH!~t* i]OS#˽ ˺|@̢hIA,&`TWǖ6Vϔ5Mא}pTl~C\z;q"9J[I̟(`@<}C6Sْ7#SI2BąP{ as @%&mGI5pF1!LL5ۉ0diM)JΌ.B K\F"M!y I r0S(|@!'2)|;oGs^luiqGN[ O ;L݈l!Td=Ȟ|VK?/3XMG6 f@ASc _+6Gk\af?6޼:Ay0/E1 8qY R 1Ŗ9ITD4&)gc$;|<tLTAAFwM4WҺ@9 gV<]Ꮰ|'~`wJqØQc^|:R9=?׼ \tEŽu.~srW#s[5yws@uWw^U#*13YfUYLI09I<=O $)C su:NN~exݖ )0P`d6S˼Mu@č?90U0UHuAs:0΂B !`ÂHу{_>'w-c ʏG~ecw!C`A(w:"9Ppo`pt&iUc.p p|^y=.h, ӻ'C)KgO;g1' S ІH$zQ==Rz T>GjA6R\ Q$؇UDIATEESxmSEEHTD0/<EC@Sy"H@hu8\oU0f )JE]iO'ʜks¼@5]'xZ%<|!x]BMbI2i$*\31m<}.0ĉ0J :T`A1.W>^®i<N~D {߷n>?Oa)<=Ay O,8x@o w(?@ICK (I&ks4-O5XQbtZ*$U\<8HA<S;"XkFL7OHhDhfMⓋT͐<M"!:-8 rx &$Bi$B=^^ۘƍp6h`J \ ]%ۄ8tcWo|)*HSr &ƴ x\W!c,EXs zQ˖Op7Q8mn9c:;}9 ߉fpxJQH!&6Lvn%0)&dgyDrPgagB $Ni9bE͘P,e#ɝu)hCH6 P%"T%6إ۲PkPa]Cb@na%+AOH]c"p3d21 !M1T0A\ q9H%%=G4\Gvi\@O eN(h Ay m5F+ē1>#Tȴ-fl*m *0̡twjڋ6b<:4cc/qxapISyŶ/f5C:ĵ1  >A᳉b6z:#j/λ{Tů"ىR$h ILj7cIirYl ")q0AJSƶ1HiWZ`-D5B&YJā{&i1돏ú#`L.@$q^*@; Jp"d~ \@1SK( !1\i3A֦W=@livK#Nt4ˈ7@xаv+@J 0ǟ;5T? a'.)Ôj&bHSZB86F_JԎ}waھH lG"32s̼7$Mm~ ,5B;H%D*COE2"%b; BDϫn:Xlr h(w'BAAlUBQHFaaqdSiaMhF$)ǧ)H" D/EW#;%|Kz9L!CStPZ  Ct/K w&*d!IP:+F'>a~%~[e 7¢IL4Ob ۊ_%`PJE0 |CEҨcTǐȴ FGЙ&Zl@ м J d%D|M(l?*ye( @'C\ ƨT% V@vq+.@&,$Bf/=Q$} D4Lzp&G]@jI6ee\$"B1P9zC 97/A_sS/e/_cRT1Ѹ'a}>3L,EDQ0k엢;6TP@~w?Uܻ &Cه}/qOx(бC7lb?Q\L#E e*sBڰ3$8cIӰaʒ 20HP2(R{{p$n>M'p9ri)(Bw+E'9BxQ |wQ_Vi]&!ߘ۷9.NF!&bu a%3.GoJ 9ܳ D9å#3|̀_1?~'t>({A'Bwph#-s\{}ľB!X\A{^2oXeGXz$bƗ^Jߊ|xދ:9]zًϟ&_ RK9~/ 9O5jw[(]qb|ގֺ#2q}dU_j= H ,T*4)2L3Y"z=>|ML]ZLzmϷZ}`qrXicv6'tDiD4B0zHٰh[-`ȝ]3l4 p@S٥,ލhV,1E5."CľA=]S2utAt-$EC`\a%LKxE}dH,ZR@Pa¯=5WkrMMZ7{ibE7rjLQIwvTʯjSI =^sH,cfb n٩\<:BA2nܛy 462.B/,J!_T?IJKxIO2SjsE1ZJ3m jfbU' U mZՙ`4-5'e ta;mL`t4M %4Nى#YVU䕌4X>N*a:Jl{ -YivB P{m[f⻆$ʣzf N<^ W-x2(lϷ< 9=Ҧ7 gӡ`k(hӆF$gڪrkkJ/&>xݨ圦3dO;ec#H: CR2ӟ'^H7ۮs⑴*,e !K( E"{ҁP jc\K#F5Cf3fc̝G5|kv!{;ݞ+4?װߪ, OtP[1)r7lX3 J9yaQ=QE Yߓ\aC k/"*y@j]nNL<3lkG҈R=w-aKZDZE  YYg |e8(ܤ/=V:98,B"Ea顦PQâ2gLAYsYFC7\]#ڽu0.ݖ7a**SV+y遉ƎNgFLvX(@K[s4f6&+ @0|'/ ׭a} `62?}Gsl׼>1,g J)z2߭n77ih;[:im!иa|aDkag'_>6#7Hٕ ^}i i /; {|nބR+4[e uךF5\ԍ7.^$95u$] l.%)XȐ58;1zЋl{J5Q^w*z`N@՚ycYPZ=cEm5 Z=lĜ3؞u;S:c)GEɯ Lj&[N0gGDASBT$6i)8 Lv4(FBcG3@maU@l݇\`wzGv@8`DrT{A똅7=-UMțPBiFpl8#CAX4P~^ǭZ[7nI&x4$͘7⍫*(bbp` vUuKJ mc\B,HV{(\](g{{ZM`FG'am3S|3ޑ4minCKG:tHp% hM}cm/7#:FJ l&x?5gd!AZʚ kstJwe U5|P( RK]dq36zj:hVȋJP/ hH^\8AXP0zg,{QV(*,ƨc8"r̼8;WG@iz>.R2eXEתcW]Hآ;a׋Xq5Izamxz)ؚ`CQUÛzQT֘vdxYܶ4xP=ٜNh6[n ;##t,,q!&x4M :M,-pbۻ3.3lm0JM0G`#{8F/Ǔ~̭ĬEAaxYGOP9v3ԴXր*S\&)"DhY6i"ćT4 &tvLX>TΘ-9&\-Ҧ$ٳ@P1f8s"i"gyP=O5J͇lK\=B'T9}Awd&r'"#Ϳw=ѯƕg5"xAm L:جۂ,$2`hI68bptn]'´ҋ;gM6ű֨/9o8g|u+b[֮k^ҶjV{17dvuh C$YAх$oJ/v>zwhezq\&h_SEC=2 YveQn\.1˹U 6&*DET^ؑAP\Kɯ6k f|kW|b_b-o4; YZ : Kt(HH1K %7j%/mGq#<.6QN秊_%aF`  SAI7zZo8!g;w=tϪG9UɈoԀza34-Pgmk PdIz=Oz םY&Wԇsm g6k@ĹJ?$SIA4r,F SAߪs8}/4# X&ZXC=B#(ZaƳUWhk=בsU+ǒ}Jφ{oia2Ag#}qB-]Sf71-POl>vgǝ#^ly}, fh>rZ7syOR|4Gƌ/lW zmHBGSFrG#/m' 4;֯i FjjѾ3]1nTA7tpWEl:HbGCHy1[bArl5C HxUʄ8pm]3@yP)?Z\%n#:&r:#jXRdUa˳r`3Arܭ4 B]DF o;4KaM)r,d@wd,iCiC)rW-5lE w|ӼLBH`(½^u[(Ty,{A;3d`θ+YsQD\/R3.uI!q^=eprb BG8 hkU}l8EJ< @1s@<ٚ`[ K+6=f'|lZd!,7t4Y5MRUywRF-V5WR6kU#(Sq^|Ž>Q Îb\ Y s}a a"Q6 Hm5Ҭ5W@ʳ,ib!cB]^rIћ&- cWޏ^I};V-`Ȅu`iA3CpBޢp Gx#mkE+apxַϯ>n5(<+ؼ>) \b*M,I`򤕳-u< Aa4A_L7m{|l_X0JtȝZCk"X8wR̞R]`LzѠЙNe܋W[yC5j#~9iI-) DH2QTƓpޫ{lyŏ++$NSC,I.d1 =9yI@{@~rDz`'414v5yr\"犹$Y΍M$Ą  }h7ɷ42s!dg-pOH5#:!iR1 aTc.Q`hY<'ifķK/!F3w`*;Ć 'PذFq!TB8p'@NtSM'wv[Q1PQ%%!藐LT&$1i`v[.1H2(3+rD,IUm=M3P]NU9;tM"Ќ#286dc~94zJl( =t\TLNzS͑)W{؀;9FՁ:cd"GƱR\@}0t&; j ƤL•_@ &W4(B 聥Wd7Rq?sgr(Ph'Vl >%`8 )$$ bdCWr"JOxzIN+ Ou,B@Q+DJ}x$@Q)V~xx OZ/{'9@8*@; 9$:"FbP DII,dD0\5j& q9(f ~~ơ/^fVWP"4- '=qA đf;\~Bpa44f6FWQ8^#4b{w"֮YD9O?1ɞM'Ybj,r"lN2UEŹ\5-"e8" =G;މ(|_.qq?8b$qg͡x ;DxK 9 k TˡAwi&G(fntKei-i0%\2ҒݝrC*ƥ ]sz/ZlhTOyuup+ôŸ 86+)B:w^{ÃesZ\Tx}]u:vkcf]Kw5:N FVXV"hM6Ciyi6MJcy!2wU#^Y`y ofw[ahsxyޕ:n2@n[rm.~8Mݛ3mIƠFܠɼc$64%HP ?d~*k}Z{L󽮂2d(INVeʓ%xnWJ)M?F %Waj̫O1ERT4wLAeR(q%E46x޼El6Mt$h1%Dt˪G VFh0Ҵv$I+9uW Z+i/0ZєJjvN@1h@6>c"O )'caf7xkfg.5kJ b4{,/4S"\Ig"BUE &5 8$˽ֹbX*\Q^EpYoyF{H*S f=aϔyχ#'∵U8Awy\Vځ8ʔNʘXL޽zq_tфlmT %d%iTE bo0eTB9$h'(@?%%EJ4AT'쎄"^u? ϛr }vi$A0$PI ,(%J1$SAJBDPDRP !I}HOfR () 2:z=$I"EF}"pc&D)% I͵b1bёgWt#5:CC:ds%7~X2c[q4nMG!&(:: .Fbe<_N8p0@e8#il`˷pIW%TȒ*Bi$"hPG IH&A~F֟_ <J?Fj龰=s D1¸.]quMO9-:"q;>4S MI ͑Pt七2Q LЛ] j6}0LN8]p(3Q,PԹ2!C* &#wا;W ^ gw3)T!oϑ  z~?9?awӺaELRuh{pO5 {>}.P{".5ƐZC(D=aB!:Q/6 ?>zAHi'Ds ց(y`GM=!Dq͆P,.AOʚ9 OsvW:0\asG<Ekw+OBl`l"B&KJ$0>.cTl>kyJ(A(0ު_n$$cՁ)s8J hKi?|#M (Cڗ A#/ !=pJj&/-"C(pj])'G$()9N"!# &RϐG{?a=xB;!A"" 6 #@db!Ə|74Y1&'..)\}PqCϷX|񛊆Ԑ9cCptR9 9;G(CC,nb.Jk kƗ;O@¼Qb6BSf:EA׹gY !TL4L\_|KMvts<?9T~rd.DΰO( 1$hRxGO@}0"jPSXx섘P׬! `<M_cIH!{2m;B[!քRҦ*i7dD('kz *q-m \~UaY(7pF/B "h(@8pZH*bD  _xj*AGvdhL {krD~tU_ |=:;YUqQ [j/-y~8]x&\f4[-n ] Ax:ix䲷œ\uuA[FJ5%+a5Mhnyޏ hE񫧽[^߇V,l+~F@(E~gcѹQfLr{OIZsãOfjgr/Os{q4NVa59K^z֘{Ff_ӂ".LLmJ֩ˍF;9 / pktWE[te%aX~jYܚkzӢh`h^F=ud1tW9f sd9a}>!g3K/k 0H0Vap|y(벒}ī3:CsCkrIpGOu̻*<Q b'vUC)B рPɪg2#[m  M. Ivv 8F!(A)~Pb)T5A0$J!wcЀ=FCD̝|4 LmL!Q`B a:2#8}&6K|g=>*$B| l}r ʫ=8^|v y5!ӹ vm8>,yRrqR:n/BnPqԝCQQLFhzG 3Hğ4_.$9#/& Y"% *h`X `B")e deTcb'I*E P QF p=}蠶qs˓O+4EHUt_H6C#%+3G#'=c8xr #0ATj*BR 9P=9;(2x#!DswTduނBIQ 1ltذy֢f~>m Վi3syI=x_ekX%U1pqGTvd)?$O@szP>'=28bGdYtF1F:c̹qO! *!W18@r4!Mr2F<#<I N$K.I@,JKR>yW4? L㸄C*R{ 8D&*Ŝ!1'T~]@,v5#RJ.kq)@01u%@[&-94Aݹ@(@2p Rt:'2C$ǸcVCڄ)4֦!G[8& d CH& >D^О/~.HM!C  L֜B}m-!vSAPVSB  mZSJRSɂK # I16P[3(@a D"'& b,L4ĸ$8a( i û{X0%D %PANx" M1!?EC>a"T{# m/Idns3dvOFɐKұ3D>g~@p00bI )\d @ 4E Xe %C Bb X'z6(zGn߻q~uwP{60q|(c6Hdᮖ |&݃Hoz@oHhY@amSfD"N{G %:GbW bpE~R}x<75(KwU`)f΀bF" M{$݋#:.6h!~oq!v )W! y56ϊp?\e*/^B9 >IݽۓD!}=LnAwJ鮶?gLRQE0:I8hCR[+`mwfTC tABj#ސ6t؜h?O9עאޑ:gφ5@lED<8(X&/L,[O*!!G {xDŽ,"ūf"* *ɐD!)RESCrwz|9Am*<(;ɼ3`ydfL;eN}o(bB;kpPb@@yh4H$E݋j"4=k7=(&1dəKˈ{=T\K4%2LP:Dt⸝t8$5W`ĥ12`)'K fۆ.dZ bAY b` Wa3ڀnTCOQ :;s4 ˪+;-x7vߓzsl,_٧r46@p`r Hxh|$!O/!>:IБ`l?@u5)cDK) RSaeJi}HGѨ"*JhUt};C ?G~c~ߗ? _H14h֋G>D8;́~gi6bs2+e7C=` "jDd ']&UT i*.9ZI^a=D_"/گO@*Ĩac V0b!)iDVqFq[b+R j$F(Dd$)$iSN*"*A1H$%Te&((Ġ8,S)hW@֊bP5$1P @&Z A)Bj*h4FP@ąBaSH3tKR2MA&H]JID& hM VX(PSA E)HHf KtR$H3 JRq ""+H bG@Dh4T+AHPS&h)F") F2E H1Q2TD D8ka)-M((He@aĢ ?< B%*@E&r#EDPJA+R@S@%"4"R5SE ST-T5P0>އ ݁9‘.?*oD1$1qqAӝ؄@mRGmGP*P L=HbѢ"-&D rqѻ `TyG?@3MDU%JBH_!^a$!ޣT@PQM+* *)NQUA%-QAJP.I. O;qߨSኊI Ssx-٥v_@;E$'No:6'I`@2M )hZ($")J&"h&fFRBIe!""hZhhb Fi)(h !ܷkf r]e*c)3IqjNY<xpqS{Z:.zg;"TlD>ݞ5`A:9) aήj@2( *>X64v"O4)=_Ep;}v`v܎X OK^uOyx:i+;7D=8}&@䁈߽4;e3@rCKKHB4ĴSA2DESG9'|E<'&>hGRKzvle@{a:@L# P!TD H-PHC(Vߠ<%b 3=Z4w1eE%.Ƞ%ebޣN; ) FTjks4#?AqڜЊ(rSz'ɋۼ}S#rY&β 2#2HN&v*aPa2𛠉 BD@C8$3,4<Ċ+$ǚ|`>bEמL5:lvka t:wn\NL#'&yIWMBRtArbRQJ'Ue1#D'*&\`t$; :bO=;uæpJ(TG\b =D(n $ I r8 (tBOg_v^I֑BnipV܂vU,f5ap(ć Ă)RR꺇 sK*p4]W1PuT1zyR.hMz4 pv3mb8 %M&"(: OW1`:W?|,R4%̞FD Z FcgEvK)psH53@iJ&CC8q{;8 )$b t$·mVE 8_`9c iA%;4$~ -#ڶTEim)bai"}#JЪ +OJAф*+2/ :0JO'=* ~My$;{CN& ${EtD,ȱDPQHADKA$ M 3  BJ, 0D5CABBƺ8ˠ:h]*b(t Qv:Aq= Yt/Н ?,fO 0@(>GbdT iB!|χ m)&$]J‡}J-&`|:t#J'r@ސxpoh_QIȣAH8_E7Hī[? TiX h<>)sɈ]H&pN b_4 n{1:a !}WU:2N5a:?+*ur+v\fISfrho)ѡBv8kY1 8,CD qhSq+$ N6JT{$7/N"CpQ zq)vҷf_eEhоk~?q,םAǭGCez^ )$u OX4AXRI1?0qM5h1w (~;?R}(Bv>iݧ[(rSs.dN|+ X}0g%G ~hWJ9z@6 k*/8tǝ+ _:N55׬J^R %z'Λ $͖xQA1ĘIfKl[[=3lͮr*[C|X(NϪ {/;Z/]:٦Ma% ۳e>ԪS;V Ii{a3ġ*9R,ԬLt,+<%xV33v+V0= eez9ފpL<ލ.sG~9$c_H0jHSBti"S|Ni( ^ !PP6r ~VJzZKһ-3[:c0լ`̆[}/l kD'գFbO8xIa~.it-ᨉZo\^۞Aizx醄U 13G]e2lKl8H)]@o`BAfaM"l][ѸӘxְ:D%*B |E>0`x=ϲ/}ļP}cW:BJDȣ;<' @;=SɄdKH7FONOf?!~5yXH?\etA%$RN܂'L79(`?C5"x0h*ayg6,B?a}/7~/T^(M~}o'q?<%h_NM|Ÿ$d`' Sۏ0%&F AGl`_Xt2pǁHfaAlu(GD4b||#:%*Rq<$io`~H~.QtPB!j% !JR J)KU!0D!D*E0D1M,JҔU L 1 TH$QDJP#R$L$LQ1D1 GBSH?&TIB+@]EQ$@#D (IBPRU-)f("I%&@hB) Z&"V%jc!1)s (S:|uc4ؔrq q4Gl')vur|. X$i4:"Cq(P8"N+z*<}8kI`8G`0 ?fN!$Wp D@4*e `S;pT 9X%TtL"JCKC u;qѵ c5r = Sd w@L/D=G-Tp]c}4z =pOmE0OT kaw*1.u0 nA:7>:ߊ䂴2 A$'.D5އfA~T2PLf_) ppn<=n|2/WIӘ9,{|qg'4x" }!>Hb$dd=eb0'&8uQ!  *'58{8y"dnږ6Å , DN U3fi <%%@LkbıHjEj"H"ZJ!@QD97,ju8eΖP*ק;.r6`-o])@ ־Wi4@AX)|Ux9/g^EOfHByy"+[2 G nPF89[JiL0Cu%8BZqĠe&ԙІH"J(*""j") Wl(T¬dKPQUDT63:_?6;q`{ӌRD4"xgsmI=%-ټ4Aû;ol'蟬vJh%4 Dƒq-TI&/H 9R[L䐤X;"*pE/K b9)yf2J7Bn=F@q/|=z7{ׁ# K4 7T4|h42kq&]A=??{qmrDqCJ_L'Qi #9%4!@ |-6"7A%7ї@T{*N&* *2BIX RC45`2B$" O$?l "F;*SY" Y ryBJX$=@{& 6+Gc, DRNʽ(-t<<%,Bf_I$IHR0GR10ABhi5;r{@[{ЇpwCh] X)z-dR>~ 9$<R"H} v#q1T}xZi`i舠  79'gpOrGLl3A@9ld4$ nBDTo>ep&<y[b ~vd2-Lw~a 'Eg9SgwNt=21i;UC "|A"Q/Qpw?  @8h=qqK9>?iYfZd_+z!3L5GOUKqcRu FCuc_\sLg7xԶtP&1\ +#jهFNQXdcey!ݐv;ca$ì7rkz<ڗ$^ H:Lk>̎''e[$2A-|!0 $Hh)4=#ii-6SF}!w6Td.VMlb I* 0IN JR3bF1h$: e25*NI8yL4Nw#%+ͳD4W,jPc j*b1c3LNAEVMR`șBDDxBPf_CR]Np2tdPPݲ$3TDbIꏘx-A?>OGdG1٢`y+T!>p{7Gdyl% uH2̂w(|e#tp?0`@1f 5;H&N4OZц!lFNmEB& BPI bF >nU8G?ΩZEb1 ąJCi˳؞f:$aQM}Ё @PhiPpHHݓ%0 ~4&偞1,֏MXRӋրJ& zp/:wq0GxmRTVedlluTpvBӱ*D(Khi)Y%g޾ ag!'p ;e"Ki=(>Py2 4b@h;y#FGr!;?\tG;异G#I;q)/+$aHzfȠeaA#3&o& q$;G8 [ I>@yQ6R "'q {ǨPA֓L, &S.4 D`>>(kGm5t1fx, @<4ӈv̐H$_.9ɱPZ+N0>@?4A5ziM1!78I(<~8?gqBu~N_txdq!pF΍x8؍.%8N`Edմ&bԎLuzypG }y0*FIJX4>%\>~6Xaa~nϣ㨢q)XK1QX"D~_B =p;˙$ 8`/CD=xh+v*$K* ĹSir⇢b:*wj:]MrwSKGve'sZ#,96(ңB'zA%oZ,Лq&XރoH 6 6 ' ؏%h~| @^lCCL)h8oqE9:X 13rA@F CӠWh֝UviҼLHH1QH8c/2R j u\92ث-%h%Bq[y$];ow-6&Yh: :SySt20$ ڱ|pcɕz. 58ǦM-F(qtU&d6pJXCeL2zq7V8ˬ&· TU{:>!N! b1GFyN',aJ"J$\u>$O](sgex/#p]ys{a&19&E]<BVĦGv%%JPt8MxnMHgsjYN6HAl a Q՜WHʀT4E5NӤ uUcF;jv82.ՕI i(mH湴Bx9Rp߲Nuuā4+2eB1=q L[oO3xI#`+C9p/%ta\,9'HNPDyOݩ(7`SP,"dSHKCG" u~H>]!|AnPGUBmh*4eDp_3z"b/?lC'Nh̭)fCH9B\^O`)̜* @ootϘ!=|tFA3|0= %<A,T6OeO0(A|s'A{3<\C!B$ ?B^N퐇J<2B~g;vs0%0^4TP!)( %sA( h!]y{nC!K/ϐD+)3l6ʎ5y98 aO p2ӄ2RP1Sv4'OJQ@4 <$yy $%t%LItD<,_C|+:ȯl`nc6HbFW (U3PТΫ΃V! C3wt[<v EW(!D~-m` Fb6"d);aL*$"S$B$9~?׈E@eI6-!* hk hSN#M'qWUe1`H/Km F&YӐ)Bk#ЇφTaǒ" wyMI(n$HBcGK|jIdWd>m'~NU5Y8]k ~9yuk2)_2wωS8"m0lXzs5F wp66*BRCK=x&y@bģQǙE)- A-t&+IzX$ p"D{3%sӯ?|g\01  n :ջ<30p(KpiΡ{:݇0>QUx !Nd!r)ЎE cZ!b,Jp}'[jN  JfXJP9i\$,HSP:k'A!Ju eJv. J IhN(ҚK3IX#$HbRRF( WAG`MSU[pt (0 DU42J.|(@q Jʘ@jc1 PH= C/ AG*2d]1!jP 0xrD(VBP Af!)0gN1f%9Lxq @:JP7Y^7ӛ NDɩ @o\ w0WvP܇؅Ԓ>_hsK>H0 ÈF нO?hB/mp wJߔQ;ď^Ѳ^8󢇳4dЕE*RP]rCCP,grdMrXQSrRvO Q;eOAG01ԋDH8| т\SA%pDM <)L(h ϖ ]8R`" mtm@܉<^uBj:nkrXF`M'5(DJ4i6Gsytƞ`i!B )R H.Z2u(ՆD7@zJj <2O3oL&5҈xMG70 vSR I dhGHalM)2+SI?]2!A!:~`8KZ`] qsK ֧Jm X R`8:@}Jt1~|W jw@'b,4b<2a "(V((?G " dހM8 @$?9+e>OZkzf 4)DB d،(ؐ ,CqA-҆qvBP3ĔXIBeBKaV6Ma %S\z%DjrAr!O>yZZ2@?P@oPh9B ¥ #!)W h 2Q?dxBb X |yXSɼ'9?: /ٱp?܈G a(B I"hr;:A< >1 j@U&!`dU xZ r8*"U BYhXe`|f6JL$% 0%ikd7 ĚM(Kya?LbU!D91􌉕@@Rlf;XMB!LH!$ZV_q$_eݪ7;ѣdC)⠱u53S%b)ĺJ-3?px*P"Q~á{剁#CZ_T N쮥Ӎ4'.T1qqinDD%[gx\"(#((W8c٪Krq 5!:g?2K嘃 xKd@^reؗd9'ihJD.`iCJ>7'Jhq>Z[$5, (D1Dm6ufp$HĂ%%(Eb(@"7Bj>iH%@(D{S?ZV Ek̕Ob0`/ 3 !!z@_1x 0.| V8xT=84)Vm'S7rgg`4a"`"lz}DJPTSñF"OIj )H" eNqa 3, >/Ӆ4Dӥk!vE<"fz1$<:or?)d nㄓ j +yO%e@W1W"XA Pa*I<{^C^TćpG7KCCE !2>G?_@+΀@;<=|'#}-+@R/*GpU9affgƚ$(LH rJE xZ.Y!P`V@|zcHfLPi)MD|sa:p!^ Pb*!7u;l4{T?`@Ҵ=2}rįAjbb(i8HE&r#q=PM (d> ~@lNC'ta|?nA9QKfX6FL1ąXuA!!>I,E6#ìQ,M>8HD!_MrDNW?Uw|۵ζ8;!%"=S a`h^Ѭ$(lcF,Hkn>^;GDlx鹲m Ae0?tQI ' ǦbA(cP!"mdHfF&;U'QVpXC\lB ,0 pH*AU K]i+T4&DiT䩈/hMAhi#w ,hUp-mǟ9C63p1WݍLù' iNAIDR() EN .,1M{*R{M!Y 3o1}ob$_q!8P+Ȋu:2n]b `P-F YADA!i xD: 7Y~v0C[yØvLwIJ䀍xPB O^z)=ُ?/|ESLLЁʢ"!aT{WIL|;pTN*HB"œB2{{So>Ӫ`s~<6?*0f @ "8R$GSQz|7)D6-e:%';OMs {_If TX; +jxO82lNoS>} Ad_ i1ܹەW]𱏅Bb&A01mO &~|" eCh12@3 }V -l@Ch$_ХN0.$.-xψO)А4j) "C#$I4B)D pq_C`9E!A>)St(?(W<%y^e$x4!WvJw#CA|ATDE3M P@Y 8! )2N?^RiBIX0zR&IRhO'֦i0 9q=5CP242b8"R|4 Z0 IQ-$AӮCu\hUd(ッzf` ""چ1$( hb=󞥪BT$)f)")lA1E.C =Y}E4JZ@$/IF F/؆*Zg.$Mֱ3r&9t4A ua9b"!!!Ї90Ķ ܟ'91lL DQ30(d5DEU~#-$I XjH4|c/Hf]C- 4/QHL%D!q@D϶ EAh/{4q'X X_Ñx0@Kc” GyO -*{H1d&Q3UH$J+@bH_$C@-(|i&Ybgoq|t`q!l/w0a 2e(8h<3&Hph(B6ʖ׹y Y˱0A: (  $"ʄ@  2$A"K N %-]ฃ{#К"-~8  cA^K R7 b5ĐBOdbb+0cEcXPJNԞwwyyxp^$o D4^&81)'u+c.bb]iKD(܎CxTg,p/M~8h>_؀*SQ=">rDE4AK LLH@JBh94 KT@ĐH!( %)c{eHF!Jv]w yǕL<+ 6P (4/ֆy6le P=}xt&I&& =ab $Q>7s':7(@(7)#zO8^󹸎L$n<$J(:pL-L^s%m}$YO:881FѦ?9&%. =;`+Y fa҉T0QASWiݙώC+]u/Sci({!A`ZBm1nh%wENBqF|2vӑSRDpBBဝ9z4:j 5^hLll+9c%}qqPki" md4CWW @R(^L vaY:[!j/vpb%6{pfkGZ| ޯπ ֈ᚜54eq3u0ΎI> ݸ}<ݙa\[aYYИsыq+˻Ues Vם58]>+1n?vztX^+,f; O+9]"!!S{Fd3|]M? Աo/}:cbsĀjBn! <`^FNElJW٘ g&k^.zE:i"v6Jϭ%)݉A[tbs|mXqƉ kA5{uF,3d2O e.o?@fS j9Tks$3P\|..pLlcCM uyE F?u(tyoagDQn99IZzMzf6%0Rs6ms+ @@J,LQ6s̼Y00DbYX˜Mzڪ_ 'toi礘I$7M1$f0&2&q06 E["cܡUdQ:ȓنu1ˊ -67*ajcHW($MB)Xފ`LҠ@;]AܺY% nErWȸI"M"H; ,Mqc~+];羾=>\*T]p0܈ #p=cu"6`z\(c ED#Դ/lwu蘬'oIPtfVⴠЃO8rS3GߠW ^kp%`4M84Ac>ߧC/#nl tsٴVy $7f}aЀT/: |R>ؾ ^1H!M'~^_#@Naw!ƕDr x.+;:eO>_$}h=0@k Z)[N<-.Nq#ԯȟG7 xC!j( +tPңȨJzG06`3.](s=54ƍ0B&,(r8~; f)fI|~ԁЇPЏ! Jؘk )J.˜>P%;.3gH{q.39jnh'=İωrv1^x6T QwtB2Vܖ6c6 hIaq3CIBD+REϏ¡D.`%{{4)눐JL0^0|O 0' @| 8F; HKܣ-&"n*9oI7pcv98@>4aw>)r("bQ`N8TPA4QP4P#D !`e0@h hPIiA f$ \S/E\*PP 7ᙉX3a%>>R0uG\%D ]^oQbOٝ G=NW0?&Tcu1Y6 DJ 9@Ӿt< r:h~0Ç@RDS˝:Xq<`KxmPy>J9Ύ3.'D@jG%X:O ׅWVF'78IC~8Kl?`{T ݃:~{Hd #^̡m'C. ,'! D?x?E6lB[M{ fNzK_sb| MQ$ $yzD~5N 6|PG<=r uhNnm#ٍA}͡?PIC;hJI4C,`d' iuI0<.+YwXNv~oO#GOAG=~Ǿ gTS*B@6w.MFo&6l ޠ- Xyeo\}E唍6RDʵ[zU4=kzl\o_ | +A{W][Z+/!6_L1QEEEUQE5UHH\@Qɱ&XҞغGPxNGG 45LG(` &{t+#awwn|>ALEr*JpZ zNmqa78?>yANn1#u1fA߿^D3[`]{UKm%ʜ~xcEPҙP''x X 'Oɀ!`O2 b%ItSrud +4/4bWN BL1Ƙ$.v?_8?rE2A5P6q-wsR>V"><4'A$yv'1.邒'A1I  ز :"soTz(w<<@wl8>-~zV_I;Oh7A=0H2T>VJqBI/t1DO_bJ QH\=Į'vRGBb(^=|v H?#‰1Rba b<|Hp(!C Avą .D!ySDhrR$B?$""*)* BS"!ẻĀq:Q) B7q̡(:'$;$$$^dC:~ ģ҃]]"PJ SRRL 6G E7 VD5rWsj\6$t1P wrm(6Lk':duxPq:W'D-DMDoZWC{ɘ@qE,}=Z0~"qJ J#UEl#QaV&C'^CQ G_ A.uԦzy;$cK_8i,sL!)_yWA>B[)Q+ a'ޏ-!y I 9;gG9{%Kw&u#ǂp$5#>½5 :Ddú6xQa():np5L>3N]&m΂8Ӿ kkV]TDBF$N.9lEدq}w<ؒ"MM@@5A{' F 23] QBoӃJw'1lbK.ɩfq@FMb#0YrbEI \ 'mT启e(bd|﬙%ݼTtl443C2|9-Ҧ; orWLHvvj)i퉖QMԂ)) CA4pN>x(+CǍ,djnNj lD:{Irݓy:&$R4o{h!t8#`u:߯I@2sh[ bRdQ*4ߝ"xgtS.y1 J`fd:4DE_58wc?؞sM3j6.6$ 4*Òj*GY*C2pR#ĀQw"(6 GL$NR(o9!@9dR!vG@'mtQ %QP(L@D%7Ñ R:Ʈ`5+̦G.na&yHbV~`prS|{9~ǰG7(x?Dt'xF2DE~8a϶>')'hhe/vd@I,EBH`ъ|1xPJd'W}pS_ KEf?(9"$$4@$L02H04! " a #$%Z DL!1UD14Ą@Y΀Ҧ5e PR IR `af&b)hBXR@ I 0W/@wQ_TdT?e;\m%G0$TA DZ)UBSAQMb6iHXSPj!6ń&0W؊pE"@D# *d!Gd&% U~08 4?P ((P@8sydEhMӧ֡R?aEA`4Cũu)3/t޿{gQS iFJUÁi9+,dG̲5v62T+Te"*BX$ugvj\e(So)TF̪1J)Eu(I!FE,`M0/; 61kg)c@>ߤ"K隢eqMYYx07zÞ'  $ DH ART(( H`ETThW8;b3"ț> <[%~[: iѮEMPU w5 *8"w '}ȋ ҦFDŊQQA7ZTLP;/h>0v%`Ir$IE`S0IJ~0y홡"AGR'!Mc&a |q{!@CRڰ@n9H|y6#DFӳ|6Az@5 $XbY8aXӘnQH?v@^ixGC;<{/V'C.sYOL Y2`ˢ8Oy 0?13*COP QC@>S $X iiE>4U|${HVD%8f9>8uG@dӧB`O^ubKEw6qކ$ۜ Om$Gi4a0Hiz 2HΎ.kx.<;sh(z#&pv~2ȊrAP)ziwK lGy)s {OPE) ژRC;S\` ~Ѷu1Нg6"XI"(ZB&*b&hbD} 0DQF&,b$C;&GQ˷LQ1"*hv 0F< PPRϐ$Ɉ@a#_O;!L? F ~[wny_7 xDHBPVh"DN~ gj?X ;`? }؝L|@oܲE%L Xyq? )?{iZWR̼<+;wz{@t6.KCGSxcH_&H'gӲ^o>SM(UQ E pwܞcy_|k툕HD|i>@B;XW~XNu؈mĄ`Þ0`o !U̜,9qG,$bR.\!ʒ> :e;{ 䝮! s?$@ MG!Jܦ  iM/y RF)\Ҷ:#u83σD$QbhMCC@&a#o-nQ(9#hK$+y:<͎[SBxBG!2QiR(WIU!oo u(_8̠}.4T&M}vȠGzR˸q>(`⿹vɤ@R4m=K6sL<4'B HB\P"6BkXUBxo8JF/ m;z<_ `^owV`ޙY'#BPutO$<cDF0|%$Pb6Y%!Qi$U @ 0H@쏨o5Oq IG^= J"ǻ28<$6Tdx8#I]`1Aǁxx䊎ؚBB87X5 NH[ɺM؈[Zܼ6 y*dF)3IpH HD0'd0c!|ؒ';u8ƘkrzlF$63_SM:x@? ~i("~bAuDWN=\C"Y6 Ɇ90A7m{N8Mo'Ȯww"vi[$*=Cd "x"qNB?{!<'# m0 U_R JM`1"H@C?)$ p󃉄~>G 0\} 2mٹSsunlȋ.  !tgğnNт3%9H @FhĂ-t BXy$q*C8и(aH%$}ʲzlSEΘ3 %č D<_ `+&` f1 ! ܊d/(>0[08|i(!% GQbD{Oh 2p |]&9)$x` !4PRd ['G$4㴜')9KvS6Unk_u:sZ[췝vs{>AU;UU_ d`=L>}_>`78 ua5c^@®(rD`Ʉ8R&Y"f x-2.x+0TBAlՑ:8EA ]-.D)8N$ꢚTA6x߰D Mv@CH!&4 JY+K!*bG[N' ,ݫa֎_UH„B<*)H*, a (üʂ)20KG=[3_<[.TP8D (#m$phg)~Cjr$ӳm&iܛfBfBXH4BP.Τ%q @  B} i$  '$SXxJG<*0k~(&˕^| $at ) ގ?<wxQxpr)l9= WxД/_@LcSJCǂ&0b8k} j\qUqtm$ - !x>}S7@s&N|8bL/0@@L>y޾Ǡwޯ_S$}vGS@PJwNgl) ө|꩔̍yuuE\C:7ž}YlXA@ :t[ޞ5U굶}_ATk=vVp9PD޷=ӭ^uݕrM@1XTGsێ;Mme5B HZʂ{۝rrD=iP [Pkb%e%T%WT@HL!R* U¨>:j_ar4@TR!R DT"`@{P%&z}Kޯ*(smzko|=e9pZ9Í]Ͳѐ{S 9ײ=5:bKގ5VrMfPUU$>@uͷwHg !l hSdN^5+]ז5YG }n{`>'[Lwr+ևj|)TcY{^jUJge+{qҷ:gN=bv9﻾iz=ᷧ_{݃u}W_Mv^D.k{u;{iz7F++kjfN2Wxs2[[f+wu;xݗϮvIjvv'lk}ύK;ۻcf-ý9wTXާwGEPVJTDUY {Dӭ:>\l{u[5E7HpTiʋZ2HItiQ=h@45.ݴ*R[( 5L=/=S]fĨv5<<=z6s}MCgJ|_{{*_Xhػ۹뽽{{λs΁[63Ld7[bǮ\g/5mNik-0܃]|]Touҽ 5ۯVm ŽޣdwynھhTvvmp݁rl:nϪ!}{9ݗM 2nӷwj}ݫ3;ww5ގ;i-7GPYLU{ifO׌NnaFҺM سOv3Re滒<{VL<{ 1]G:PݹԞvO{^/lǺAkUYp8ӓݽȍշ[e!P=e>l]ڥogv}G{Koj; 4& hShih D 45:!8ؕFmj2s*_^HPU]]dqM^JҒz[9`X`m>yRz`M'Ji ?=E;@9%<+Vg"fep\C55w_3sT惒&Dsqd=@4i H;&DP`GWW3_a}yd0#$GCWC@D] <*@wdAytd1W .v(HaFwez1!Rhc t= h0Nd:ޱo=yn u_.y.MHP3 `Zj"`(f<2h(1L 4D=iKlkݟ(3@Al12)!Q,VmZ)[dq4a9a=YbydggOυclM$H {u! QE$ V~e!3?S)/GEcAO5Oi=4| ">XC7XA@~73Q`OYf$|I/~eߵXM_yZbP0l[3Fj~#]g3&g^S[4YSS{={ `&$Xb=TY4Nq%yM- )jRHP @!QK$LăEQH!b,{`/?a)Q. A77ȟ.Lml?i Clp±tp?<:)OD'&\CuQ)2*ahJh" ¤)6 >OW QQ%/(_`vӭQ}02y tDzUlT>Y*0i %gI~,=[mE$E EE45F:BsdWhNJBh" f۰TQ RD4LI2T9j)JH*H1Ȟ/D-&`u}6R qLL|8/O)x-5/d@"Olϕs7'W<33A{W эwjFSd1ố4{m&ؖ-=]h=z  2ӏ$pyAV<+4PJ1LWDym(i!" 09w{5]6i6F$C1F"M*X" b-U(@6d(}n.Za^vzZMUco7CRiVVFǪLćkFF~ ?D?\[moVޥo-˞Fأ[Cb6?+utgֱHάxtqXZb+z~(3ckohlIOݨ4smwqx55aMH{!1!? ] 5o~܋d(MԃfĆ>~p-xM%PQϲEX$=`}O  H%L%$Pێ)̉DPudNMsD!@p06ГC ꎆgS淭U^;K$ۈYi2dT4fvFh CR VXHL>WNiB^6 b% #H>r|B:E@7e> (F Xt6CLv9D0_"訖< U-*QcWӶ(21"zyޓAV8]HSfq f4XQQ(Ct^C-p3HkYXNp=b0;-l*kE,A 9噄ڰ'g12I `S-5 zIĒ% :$Q`vMk<yף #Ha!|A-pd"\tn˱]tQ*{8a-`IH>pw.wI*3l[`QhNEz7)mNa5A+JtyA`/q_䃹k$.|]]ƆXs>47cvW=N4rB@ڛk0ir}r~ߏ.yIJk:M% \PVxsQM8p!XQ7057%}K73:Wqcz{}(Q"kBx'sbp?`s,4ao]> Oo2MG#jnls~ K\׼v9ZIA]`'bJhB)y;6n7\mCH+1i$${ |sxnum6BU&992h& R R4D/Y<̝8'wRk#.&8ԒA20IYbL(5:W\Շ<},KOSUj%mYoG5 #FBY޵AO6eO Ur633C1̅ep7S:\cg32uexj [tTQщ2xBk*6+/F$tuHaie J1ʼnC#I' wl2%~׃,8a -^kJdOg(#|I!Dmo˃f{~]lZOe;P\ƃ%ZPLA_/Ii&Jĩc%JPDg]P/N^LEUd5'$F4 MMOa*zޝfIbF@I?L6K(1Qu^}rP;O9j1FTQ̶Ai: v$iy$7t6C>)P +" Rd#`WD92[|Qcd2sG ZzޕhFcjA!|oO'ϞHVR 1VU&Ut4E}Fz.^P jU?$yvС7$f7=Ɉ4zTYL# %:tKՅ+Eĩpr9kiޗէO%ڳp #%Fr=NDEA=Y<~>C~PY;'QX{^`t"T?|sOewGu^ru~0/w6w|)pgN>> Y7JFI'Op<<#wz|n9tb9]+)h%J~Sq?KnsJަ>oƤd?~anv}!"U9nYKACi=5?  "pkj:~N{ܓëqhR)ݷp0hēxa'2JZی嗇w9pLaM*^i)ѩN6HDbVo$Yć#Ywr/*6Mo|8|z_ h:ugf$Yp3_IIb PxY-b )pa;{~bS~rL)*{>{Οne{pkڼZTV_|7PϛVAřýeҺz<Οcߋ}|o}1QW$F:ôq[g:M*y_]>|!fZ4svֵ)Q:q5|@ޡ(_ 8'y~n@޻|TE[~tC[7fi쾙e #[c𕋆j zl֕C4Q='Gݚ?wΧ_{qGyM$``1 c kOh5>\O_N_JVBM}aq({hвi4KsetڿSF#n{1f{Rt+wjv_ߊkjSXeܴSAOh@PB(((jZ(PT )@NAώ>~]a|, 96gV HJD/ A}9G菺O3u?RO~t4ƾQmhݲcL`ЧYI3Is[ݚ7 ܁fScH1N޼T]84܅TTL2py&6} J@."xmmni.gw̛OrcOK ?O L].~/["`"0DdpDCdyf ) +aCC@.~8/(±@ir0, (B,K$QS T%A;B>!ДH U8pEDD St4!t sчv٥!`4QfZb)ZZ+4h5UN͡@)JEbi Yi@Xs †IAd;AvȐ` tg#܄PTdNҝd˒IV|d(HHz GFhC0*U>@QU XPd?Dp`X A1BJ# 9a %!GG?wySc GE {jr\K? kTHNX;~}:sOTHks{RߣJUDBߍ, :f]-6 #>_<)U?~J(ӯNMcXmǽIpioΞTsCQ#&*n4=?y&xoCgcLyßZͪdzҜHlS ]zbϜE۴SHiq1*On$!zzf9S;3ݯƚC",nNg6BhP%;PHG `CPK\A4YJю4L|/@L,!B4ҭ%4))HSU!@RBA$H$ xg ntDVv pszSz(IҢ]*o0#@ TQ,DشP}8  R$iJ ZD0 N{y=HWke{>P"?oڼPj}~ Ҕu$%QˀIM4G-8gw0PB+6U Xen荬zϯYa#4T'S#D ߭2X\~.2qngZGĖ8hM[J8Db." P@!k=ܙgtP(@ HJ&ve%DzP(*B BP }LJjGhrE;HHߞ=APYb_ 5$ÓknShH3g)&+(J M5 Ŋ3^j7S J-`Y~}a4ǯO>[y:HJ(SGU^@NH)46#PCkC閌>\ "ubH8~P2Bw.>̟Kn>!"F Kη8P1!.S H:ĩNne4)02à_Tǁ,ou^ethbZX @(txtT_o؎[ٳj9&`30*c!NAk -1C l BɠAƱ67߭DѤ'{ ߑx ! GS~\D1h+-iޤ+%Vg6 ߥ+ jr&Ď *'q*@vaYvA JlVт\ ϯY Ɛji- ˷μTQZ7#07>1ƈ}&Kz٬Ntn[i(>cH `35PDgK@rL6Oޢl|#w+TYb7|˜O7\:kn>B =ŒC@=i<t%~96B!8a/X0&D>ޕ$P(&0>i-M 0sЖ'OgTqbj hcG6_I޼gK+ W~̡-m$`ݙf*,-k mc%beVn-iǿIWtrUT}dŒⰹ^gD {)aza#*/BS   O(H ^t~8a=sX.TonJ~uq9[φb:~V#H\p/ za`̟ 4~A!NSޟ-':/??%uhHa>>5|ٛ/AԠTiz׍]ba `O/}ąSO(9[ynnn4a1zt2d4o躮^h8,txD}pah/mXHlzZ?d򤣴# M8|}OѴI*@`qh^CE-'-ј!{$%(D4//2URZy>v]-hnA_@SBi6/m((3 &,)gP)bφk8PæNAOt}R'NkP^O}(%<۹`HTy y w{ [ FDLt!V! c[l4S!,/C!"BF$i<Ј\vU7TGВFbG̑$bH4e`t6!G]g_mz?kͫ"(gChl5Wq3N77d"im$*M6"a۵Yx8פQeHh9rȇߣ%cѵ-.֪UҢ}>O<8 ZxKۀjh֗"1HN$ 0[Uos/OS#2w%h@.K~tR4pہCd(9vYz%+M?*Vј({aM&JPƁ(h pG >:߳8[oh5jm(/p[}Ѷ+Ihgq]CwZN2~W-\tuU<Ք<{6m@D7Egp[KHۣRKQa4t.\&CR;^?GmΥ&tؚYzg( hYJ] 8p{[' V ӡT. i%2tjWN{vjkk xr?g*&k8R'84N#uB+-a-KyQp2 vG%.9!|#+ciïGx4wfoިmP-|B} 1*`34-rtX{NS_[8|oRש ?Bɣw0hI_(HWeZ׾dzc6;U-X k0yFmu Db pд&H=  ,A`  pG B@0V!dA:%%pS^^bh0"v %Q~ʎPtQ}aLH.FQձ;9FNY@A0|#?@$U-\ 7hJ9W<A/1bAc " PD0bcF8ϻ/3T<ĐDđ|`o|Ɲ$H @0s$PiDRP1"E?L?f adOm?%w_C_]|,:uGb0.$4Bi&"6 JH% H '@l(DxIB* 82T@X@F́wuLD ?LIҺJJ6!:Q ov>S#Uk.Cfy=V,N6a45?=pv IqL! 50>1䗆doSow{O_xv&vffH)ʺ@{O4BDQE%DLiAzy-.): P(_>GV[K=ʁ_Yf)hxK* b7$'M 蝾S pt&Ü:_=ĩ+oy j՝kǻf7Z7\N!ٮ Ԣ@0O.``T_XWЯ?/l{AR0I?O>s-g9*R(  f.xT;j?9U-68󔌎u5`P:i[yLBMuW 4*WvvqDjW=h's4\W^R7::H{?GU }ow%9VMI]tI-'cmبoAևn] C-ѽWq(Z.xƐVPi>AHϼT ݂Gtu42b YKDŽ9(Ϣ>#~{ֱ4wJ77jΫ6DEL)*KVitqL\3c3{{8[TJ}Ĥm\v3>8UkQxLXQmɓWJx֊0/PEP'lyfWnXSJkpn؆kQx8=km/#!tDhgf|_'a^+\wx!O?I$">}sdN,E[t{<>¯t=\ n`ROr9jAR̢afpsw4P6CU"D ;rА25.ڵu^ÔMY@XQ}q{X5$74 7VXz b6 ~ՠ@!|a \Sg/y!\RA.NңzlQnjesBЦhVlwzm`\[<菐Q?!$=u2`1a1@SMvۅ:\yn--%[dX1O\/Qy>2h3dhhQwtv䅪P%o)4ЄxLUU!'_ zҦIWqdz1uQ<'ʧ.d߸;U524cBY*yeY0P*v.Ko}ޖr[>su|8ܽ&3cY3ZYLT,5/'XzJe5F,Ϻz4*)a ZjyÒ>@W ;lpOD*oߜ%`m)#3#,V4lP a> ^I&@l"J)M #Ϊ7ElGN}}+TUcz# .|mi<-eSS-._  \p d$ђ:hk ASU^xp>~{@!٩@l]4fXrPM! :ԁ4H& nqꤛ4H>$/;7ݓk?9aF?!i06 Vﲻ]+$ py@C)@hא t d-`|_( EUUeHt퇶 íE.! z2R1ȰlyO^zO*].|tds+6mps%v靵xÎFrc^6<EjtTUUUW C'Лx^>^ <.xeEWIʪ2 b7õ'mkLJLZT@LeU4RDx2j6E_A)T~6 v J{ӓfeOIDl/#4ŎGw}KL,/O B HCY| mAGjmb7!a@`QE`qbh":YL} ۦzïDHJID UITP! aGWxXNЛ;F4AB⁡HO:4SW 6Od zWǮ4xk^f}.w< hQ?o#C#r7qJ5Fj҃ % $#dr'dnv!$Xݸ'A1З&< @ SUE֠( JMny} 餐mt6^tꃣ]H2̦*bhvacFb]2j݁K(^i3ԩz0.W 1)v?6w{b""')]Y1rdCelODO샹YBm~?>UUPUUPߏd=| (Z<&)<B>-̗"}J^[.$a3p⍹"mtJIm" 4X\SS^ζvcBAoN23=Wb|u{>^KUtYmٕg 6]22 ֽh֍QpM_T 1|8CEniM^6?VuR1@dCI!`%=xS4 ε|^5η&i>ixd<]\9pBɴqeL7 MwuXlI9m{| $iT;d!7̒o*TmIiD-JXNwUM/X n9I3 j* "ۃծn0hE?Yvt=a:.QRqo羋jw+᱑$7=Xd6'y)>&I^7y]; f],dQf*|gaMpShVVڋ5L ӀmhŒ)9s n\(ytcү"mc9+%h9_M=me%5E#L[Kގ0ËCH`TևMs;dqUSqju.Ҙ&&FXM3$aATȻ2iaXEjyΎ.#sonν]\zt5Ime|7KضsF;|~6nL~H[*Ho1lbM:gC6// S·C. NK{-@(ҘK|M2ЅHd9s͔{,$P}X6I$) *?bo֖J>ruمO TକkAѡa\457,' Ƣgjul2~޹µԐAp`)4m64~_\ rdA#q1S w>h`HFf*Ptjw!q,,!*6? ZvR/e p~Bg/>w.pU_gcџ9XӠv'l=bIWj#5PƚYXҧ,fيNʄP+/ yq^R3u6fe[?T$x8YCׂ ɮ+eYHwB5+$vlSڎIX$.^H5/A24B#5}|Q)^П>F_]sj_K)CIRb46ӾA>dr <xt:`Pcf(|pc Fi)r/4)={TlK]ϩCHJÝy.Z;▆BCS(+uؾp6h/.zN>d>9mϟMovsNOsگ\:A; rz:£?WnFg:vl6'@4>|G I[x(qO8Tech}e1.c)JP@;/Lش QF$24*SSʖ4/nm `u둭FČ6X-ȧ2jpIDOKU,~2z>{JH[}:r{1ICa~n74w'/TA՝m hF(-~c׾8t>RO:JL BO~$IWsH36Xq2c@:X^9؆Q9(G&y\i@s\)2L lt'Uv#JȬgs7W";1('oE퍾yE8qGrp,62n N0rGr υ/ϵ8´2w5/o)ڗ ;҈Efb߇fSlZj߶a]HKj}GJHđjjocC߃!{8FkTHz/x@3H۱B~$-|hTWU•9Os5w,U |=+Cb#l D<mx9oeLZFd&y4Ȑic4(Ƒq7)rMxcmp`͔ Cy!BDlԇ֝XZYq(lcI>VA#o#Rd9UY`n5]2c0WWls#5o99CnK9k6g *R :І`˒VI?oBO(.^`d̷y~I[Ԕpm?mA Yh反$=WӟTܣn4ۖZ) ciNSi8/R I&ؓ!cl:%r6טfRj J2ܺ&jViqs?+I-4b 'q9!ԃ<2 k95e˟˾W횐ƿbзq{s1ŞAao~EBO}0J{Q/qm5KTxX:RKY3-mV#G+~P&Fɱ}}Ou,K]1BįT0HAeϝ$2b45ʐіhMk]ެ׃i^ܽl]˅zA5x]KҮFeim;N oăw'z[JJOkd8ܽyy .S; hF?\PU#9eu|XtimՄޗ ,gf.rFy7d ,:.k#$/R7/HyʽٮR]0鶀M%!ҦB&i2w+tM(-ŢG_92/&5d b0`iũZ[1KcTJLޥ #J7Ka"Nq+vsVc<_ s2O=:H^g.1g''MJJzd,}t:2.u>:eNEےhARJ-\Gk& LoڝK83TYѣnmYp} 9s_'nbBKvn`RI3BZoBJ Y{T k1/nŇQ} t|Yy#zX5{x|XM燽:P4i7lQ)8f"4BTo5lN4K4in-֧:/U $]ruR`yUN*^NnUҖ%4O'x#<x*O(XL0RDozXӔ+ Z 5sLyy -W PH4ILCfbW M ,/$U "+lfq|9YHB>-Z)<{MG,kqlvϵRP)BnQW:PXėxL;W?0:'zA܉+#`Η#qhSZ~[p>:TѹDMC>*Mg1>`ŕr q\:$P`~gN+h`w>'mI#Go ]HCXXKhWBT050pc2^| 82 ;ߐk|c\f쇍Gtn֌{6 2h籗SYRj/;r{N J|};kγ8.xeօ\9 iv3MbK 07&m1/ioG/cH:m/~vohdĠqbcbNڕ)%6rHZV_%L"$laZ&$c)O/_' @`4ZRZ(3cmsG;~{>w7 p4 {:<)Hz݁v]FXP]w7IAWROP,єSqֶc0ѭ1aPFAB428=SܫNzBjs&OiM}7\rQMg {iD,܉gXvй]Pj ?#v+b7h%l23Z9\~xdͩ;b1Fs':3\ kFr"%Θ`)JC!Z0}@3]X&7_VYv4*6~,,dU, 9R{ ts]r~{?$ѰϟN"3#ӈ7T[KP2`+Nsٝ˳J`.ezepB?vyDz 9x%$EG#s+ *7v%^X? hB N7JNe'hPi@ǃOKvSgȿ-eϮ{\nḍ#NQZm|m;i˘K5i)CMg(jвpBmӞCx(ʺx5(nmh [p:Xm.߂daS/46ׂ]'̶(LE避c(cg=,̅V -3ad⨹X(Zx pyc:)4J[I:^7J^,gRykSU]׮Q{&}{J̣jCυZqOhf,i_W;s6YNY×eģo aLz֒18n7qf*L+43-m&áj?9['Ux5" F׶"s)FP1vA ՗(ct@B[N;{q"* p,Raj<vu%\eVغrΙTbBXbdc=*T^쭿A/4׋brsyAhDvkzuC2qN2e7„ )2Iҳv[TYØgg,\~c=coHJ*Q0jp":F! 5=$%8:~$  D03)v#fV`Y! :'&kt"rM*)V5MۃB2 >SyQ yn(A HbbiKF]a]Sգ¸!wP~Yy ֝^pV[2/o5⑚3?5vV ^O7r8ߘwb8t^)As&ZP98D(hficwEȧ\,Ъ!g e(}O~}ܮudAcc}G4-{E(SdU(}ž{ / X~EYR`u}\軱AF#R-TQ>8ۚkR9PWK)1VPfgΛZu G;[u6SKR@rX0-xѹݶuF)e卧/ҳ2(7aw1&#WE2"JOh+g/~a * l{-p~存<"ٟԶU毬b;g}?{s *QIb+)ܥ;xV>yE#\;xYtF Vd=fZhT{|i~#>|:(x 4qO&1B;5k@~kAC6 "[drE4FE4,,A wBe`wCzp)㝱b9aTr4/&ā4r*/Q͠<<|w*#y]+F[*#v!AN LӉpY<ݍ̄^ m㡚\_R!5m{)Ό*6Dx^I1O2֮L>얌LrŤT:y316@apɤ:}}wp8 p߅wGzJl:ek.HMF] p&@ZDԪL+ ]aECG>P@6]ƨڥ VMt{Lơ碁(IԹ\NZuלݝXA,@,*5]eSKG :Hf;^̑!)|WoTSS]l( Ӛ7s*PX$I]菺"~ Zb+G;pXaLI?eh@Ѥ&/CƼs\kh,Zmd IϠsȿ'"(#Lϳlr7sWi% \㦽G#cҧWc,3\*]^<&A?mӞ2er3<9xX>mw5ob&0%Mf$󽮴vѰ}ug̡mTJ{Am> ax_dJ27\Agˑ~п; ۙ oq/7DL[>ϳn%G^#e&AF ǔӢ|:?2 k\9gO_UX 1Kj,q:~hrxYm9mA~TmE&cG b7[Jd8a2d7ʧAӦW>b8l c眽>>]"g$3yO.^eY zC(7;VGJfABԡeXv/ϖWWFV̈{Λ/pɚO{!KaoF^]~` Ɩ8Wf)^L̛(i6rQ2hoIn# Wl_nNϝ %k1 $%2&l2C#Uۜ<2 ˙sܱ;T0s^r⼜꼏UTf2TĊ~b&g6duӄsF>pZa^s\0^z< /GK,{rPݣsE){XxR q+^#gIMQTݷSXߊOmw93 5)z҅:k)Dfg}널7fF(7k\2?9KY~%ѝa|a7g0.9>P.AXjq4glG3|t,d362+LU\qc-Sh16rck(v{YUx(JWSiЋ#M-|bY9f5ۥdt`pn-m9<[nxe-H5kg+qN!3/Jz#iP zf7Ҕ;i{ԋ0\N-vi Px7DxuWY`;>x,. >SpGk׃/.gCtYbih",xD( "vgB!IUЋb GMdHZ:yƮMkP5bl{WCk&ښL1h?e]tfy^)+737F}8Px=e|3L߿ LxˌT67+E ^~WUb>*kOkŧeFtǨJp:Q2R# lC;Eo۵k|Pz^oSb u(SrKK%varr lECVnl2;߇΅[aH16h2@&0\kR-;#!0kQwb$a. 2+Y/T>ttS]ŒLJwK3ZhCKI Ǻmey,3<-yNk~TG4/M;$h"c7+Ɣ o{j&Oѫ٨v+77Z&wF]7%x]3-#tQ]ge [Sh]^I<}s8zي0}|/_3yvClUTdEG4b& )Թda_ICBabHDaJ 5ŀ#TY7M"l'D^<3<_3^? odH.T_r3xr߉JꎻbC"8:\Anlm=j;i.d_=rWy=/XVߗSϞވWڽ))N1EC;={?ʭJ?\V}CCG}nG\R/ǯݟac:YefRgĭ7G~ }x:u*P9:<Ԣ*^=E) y2B*)V )llAJ1@ďBd`FOK))J J}lT SHRMPRSGrd|X ;IyVB15B U30x[7S )"(lJ(JF XQ(Z $g*X$4*78}u9*Ud?\,MrKЎ]}TIbaX'N?0اsHGÃ",~'zz{ /I|̽iƵnMCy0scO+9fRnt=\&赙*0ɥ|orbۤj")RVrꁖMI~QZvQO6-ފ8 s;k2[N34al\MWJᲿw]}Wt9T%1x h!pK cD ~8POp"=`4'DGzQNE v?8 >ËAcGx/$ OqF ?ٮu!{u dHQ $)db&-S! O18hܼF%*J" Y!~i 4z|;]~@~'G+7JxKWK3aU.Y?iA.,`ͼ4P1u/ WRdϫ/IWGcIL!|L21:ON!"ۃ߳zi"~r\DS:a |qD۽wiwb?_cډco 'cLZA4@STb}JOyvGui{UF=O(Zg$>Pc)P6B&FƟטY&B#ӧ[Xot߳rh%_sִ(ȤLoڷ9. LMS?ܵ,Z3O'QDd UxOQGhoNp,}u˓V\*WFTz^sR,XYLka7ZSnui+qmSx4f۽l;3E5fd|q..3WZ5WU:bfүS 1etA%{^)s7veG+F<MiwuY$o0O n'w)ӿTTvfj`0ife)#@ )03u3R&4!x]z(0<m4~>*ٱ(#M~?%|f=/4D/BWtaֶb $d&TˁR>h9xG<1~!paw ^1"XsvP'NBߏH|u,1J}gڭJYa*ˑ0m`a ס62=< )rIJ~LN9|DB` /?(Awjn忿)!}Wh9v֔pPx5o)C!C饁n Ib_qt,i{4[>h5A _OQ+a/6?5TmZLG~`f)kE8␻/F9u%h] 8K/~/O}wA{;f)Af\4T[ (֊2O*>inm?,Eb" $THzDXUT>UU%PF`oLDkƳR{8trh*ilRR|xK#mm7ޕ/t̝ ?QwH'}i>gqI+IEl֭R׶2! JOezjq, !̜IDq'>=gj%"-_قuL?ð‘X}Oo?mh$=/Wu(kJLEC<lW ~?a@ WzjFUZlK -dG]!  rA_戼;S6,ADs2'DE$i)jp2T1i݂T5-[II'8R\ɱ:a$t`?s!o"yI([b}f&4hg, ~rrWŕ222~EgRU`7@G#ŅS-cn1>*k7UB}ܔ"H5T$-}D=s\CPm&^T1gu*z𮒬iWʗ)FfOO*^7Q|?~$uF nrz 'ŭ=觸&RI?e%SeM#I$bo4 Bad!THA#I!f >m)>?""=G4aQ!DCw}h9 `9Xq'xҚ\:l,cmL?yGHM i;$Ag1½ţ#4#׈&śT-уL0K5P4U[xcȯF^i=0kj37߿H;e|UD H H`&$GB觻fo<5뒪qi N^ۘG"W /U\҅DRje/a_LlܔܜRu;˧F**C:G?GR}oz \ɔ$cm?)k{8xwX,:ҦJ-lMbє4ߏbe: W|ήZN/Q0V^}~ohG(=fz ٯrw;0̢Jc٫;|9 L(P'@5rIk!](024K Bu~n6< B<=I=aL;cƗZ{/uXCF{cl+D;rN? hrqҷ4ȺtU}7^06IiO .Hqvz?s+yh{"/8hi MySiP:w|QNv^=}Lk|Ŭ @๷}i#wPV^yO&= ![dM4}D7xH;'iz?3z|}k=?_]6dHD՞){&CLq|\|#P {ؼ-ݽn6n Ɣzw4g >nЦSwImׂ#͇PjO5ХLt73pn,*ʬ{_El.AZ`]M5mPG& Nx'd^$2am72j X3_@X-gn*΋sP!%>Kep<ކ8 V?pHp ׏?BuaOoͿ\aؗz&(~o2pu ׃j∍`cn7p[+Mqca8+7˃Mh5. Z .pvx|LJM _9Zglݣwzs3yaVihM!T1MRaރ' )rvvBo})- >dڡEжҺiz.U!ÞMՁH_5 -̐Gq|TJ([)s'HzF;L̠_hTajR 2-*|Afj9|:P玏>"FAP˟])`W nwŎgL"H\Lզչe4W$aƾ*[ yI~NmyH|:FҠ㠠&}d"Tt6IrTСmS>?9EF<}:^#iҗO CMI0=;kiM(T+Bڿ:h˫(=uI;dl:2/KsF5S 1]i2fmÌEZZlI-">>LGgs4ߧ9.\{Fo4~ rtRs <^p= ?r{F'q}VG'ajԝ/XȒN1ZhS(\B{[׭}W-]bXX&&ח=>s*O*h|ا+3:~]öV,QdD(QɪhVцFx?ٟA2QAQ^_q Ph)P"P2a;о@}MN7t0bŘ@ҍs5 .`b'_:2i5s x; 2v-w(g rXrg=]źйIH)b^xYdxGt6z)y/3H >5!>|j49u[KzmO3U]JKW5E5C 2kХ*CʇCa_nS][Ca3m,RL[]Jaٷj~Vƒ~O89DNr \ Z 3R .PB-{XXQd=x駾Xq1ϕ'{qOEY׏.)zWMNYC>X۝{⻖ҽ=/scgcU>9_wLگԠeϕ-?{3„|cEMkS߂S4vNM<{_K_/HYkAӿk}_P\Y86Q@OD@e,1Pd›Yxy͐DJpxŠl-q {^Cr\C]xiWF,өMz1rQֵku鏍|\Ch\:t%gfeI-p/d,^F$;I ӯ:)Mmd,qwRS^ )urWG J7и*zֲ9oް2}}wQJ#ZN$gr&qtT .==z rxohb[8>7|#A|Sx4VgP1/}LZΦ="kJra{Kv3B^cɦm5ZF6?Ml5d_PւB=Sދd^C`:0'ZEs+P- RAX i"Jo3vqc1T>^8vyX0@?ׄg B ܂?SH}H<ڃr @0l AA?B0ŠMdo&PMQE-#.beAᢪJfkd<8;s$48_JJ>@EAyQg,QS ؑ֙NJ/ϰ#`eUi4 E 8YPĦ!A0@\t -!"؂ zP))(yq΃5Aݕh?˳Dy>f;)R74*SraEB`Ay `X^!"7QE ҅Gu@hcErmd2$#_t.4bY*I1%n;7>̞8e*UVꡤ5++tZ@Yl RP6wM/2CW5IEFɼԲw.{9PT*,&|ӫ >n@YZ)L[w2H &(%1J,8C"RHc#kjU*']M冹a8^8JG翯79OVJFb:,$YC1V^ڻB:.UBIt٘B7:*/ʤLI3ˤǗ-bhE4(˚_A˖PV(P4HE@BK?җ(RUXJㆊ`ٍ%\*mT+#?B˶;`xgQE|ҿXϧ~z\ۖurÂkf vd'nzvN$HDH8iO'Ѵ/u1q8tQ/Qv4 - &(4 m٬%+q?ݧ}?ǰk 2'VV%b?aQG7F<`'ePE>~TBgs6p½BH0n{gC})/^ >٪@DɼP Wt, >pFI ][Q5V 3cus46)>㠋0(FmUUUUUyUV}ͤ qR$J@D(M!H3,u~6 !O~gXƿR_Jot|`/_ݳE f"0cTOgyZ< ϏG$H$FyRXJ&!!~zP70|tJ֠[VA|9nvs+RhP;~3kJ b-X &1֘owיλSzAo:5'^tѡ"8N˜Ez|_11sȻ,_ymdM'uَ£ ( " byO,yJ.Yn_qmG|3eVy&΀WTQhAˢrn^}6/Mtey.%2a110bT!&+3m0^Ab<{[ g#h zuZNU??+eXD\6Ȑt4#e85dek$DKt>(kE8Q1=2 ŬI*-ɖHQD1 4e8Շg,x&`av@Lel⾛S |hlq*yS.b]YC; N3X&;^Mu'w{k.6_Bk] ^W_cLuV.n荑 Pz"QuT 汭oy;6VʐyXS7קUvAMלun"x4%p44$!GebX=+'kQ4;j-+ ?bW1h%]Toh:v|`$0Ld5:xI131II HJC|m3#x,[Z뺌39K=&B99Z1br} /Wxp`*33)2$31PIILI'(h?KU@?P;gXPGUL耆.e$-rJ,@|p87%Cx8bOȤҺE!k$H*C fGy GP#@4R'i/2.PL DMHBC#Hҧt Od*"qEclmX$J% Yv3RCULQD@T%Tp4#/QjFE?@ .hSR0?ۂ~I#6_~n+X ~jp;cSAFhzֶ+41u7Ӷm@]'IZimUoyF[L||;o8置--zO k)8HsO)sםYɌ˫;}x֜Ⱊv[껟ed(y۶]nx.^.UZ Z==\>%ŗiv5])Cږy#e^V_‡Lˣ{GY럕t9c>L)־^vBVG0^*a Ol-xg 51͞]zr%N>5'e{ $b҄UjP)^݋PUmɫBlt UѺVz(OJgTdB>Boƶ+a!3͞RsږXEP=>v<>:#tR\$"qo[8SevjB^R0H{VV(7+nkM0z5َ[}]>9 iGC>t16ihbQy+0>^0hmbHz|N=ڵ_͜Թnw4G.Iv6oH*@H,]FN@n!ѡM$1+ ԄɈJAvH:ٝ#g`8\he{#>UE4<=9LBT7lirk]]96oy(PD5H?hkG(dG)CH/AN1!"\[3_4^EAD@34"%NM(?R" ^o7BYJBiB@? !!qA?\f&'so׽pS @"ܖ3M%v iJ6ћgx[ƟFQUvt(Z;>wT,ɇ:iq]Ft̓ڧ_sZ;=x^qL`$a2 V,uSΙJ`]Ԫ7sBר lg\[#=H٦HI]OzGϞ(q.[1H4@`dDպ/<妗^.SUu^Aq,Ӌgr2*:W><*Esdjr>Sb*!y=`c_ݍF*wL>F >s䀆p/Dllg](Ɲ~426 ea6lXH/Sx@ >vN>Rœ[<,mǟc꺣vD :4%eш%Y80Q2C[x_dWj j瀌`6 =^}sjܨ q/h} Bb{c2څ aa T+X) v";qv4K|zԫ%ߞlR9 mR|RבaBML7xk =j*T߂6 m1\۩bJ#lë*kG6]lc%A }T˥NRI F GJ˔8@& dM h^D]7 T3X2F5h6 V [$ E#`ZQ ()% Wy"Hj1{r5XD܂&&V0gC3:7ǖ'^8T1Mxw掘nn_^g&F)8&ڲ^=B.!`ēcDU;QsFIĽ;\l AMy.[T#>\ĭtt|//$e"1OVD=Q @Q0~ ua A,O bK8MD,=,>x&}Za5Փc/ezU@Rpt͕A $!E<[䂀npčOb}zeSA#mgZ+@шc*(`I= $TO)>@(? db-%-c\dV= qu4~oJ&A.)w h?A`SqadRBAjWgE0őWj•f b3Tk-+ 9{:yTE=I+ 2@"NF @G ? z-r{*/ >')"#x0K@Oҁ{{iz ~/=hn> SS=MJPdî!BH3ÈDt gFϻNDB?iwV?̓?3}uC[=iX ' w/O` zt :ɘz4ϊ!~.W3[C|lR+c 4#j8?K'02@U ~+]P~-yG}O,H-:iMs A`>f%VpmTz^DT왭3> *QI ?oZA>yiWyχPg8?ňCk>RyFW|g^]u9-ғ ȤK~Q=]?j\lhi ,4~ ~߆`@"- ٣xRԵݢ$e|d~޺.{8ſOHxP44h6P6ft tao j*=I kU ^ ?)\,AݶRb(6JIJΌ/[gKv|;{D]nH:2S)o6'RCkȯN HAA( čaf$$Y(4 Sr| H5&N{|Q6Ga7bAO_mrkD~ǪYlB(qp ^CӚ_Vx}K)q3[ 5VoNcC5|lWf8!-;μN=qzZIp—To[kPגxN),@܋vZدfU6O$=I"b:>[zVGyFi'/vMakLP⯛,UsO.l )F+KRէN ](1+ꟃc%4Ʋ |"@FXC.!᯺+xݥAQб]~e䮓suj<.F sfi;kL#oNjRlu݂҆I|0a/g>cS/HG,RnxWߏ;oyNI'oM_bHsX5C^?c8f :$ @  GE,yApr Q$tayl^y9  r@?IKb2AR# Af€_^:C*u G_R v;/PAiФt0&FϬ3FZNꭉ!q˶;p*s_Ӊ(iZt򾺭VgJ(*HY#8.S&AvuTOn]ќo_Z֐EF9A1Ne4a >3>䁣z_L3-1ۈrm?HDx9FX?rxX"rSՁj>_Cj&S BǩIrף:4J6o Jc Ї3__,hLԬ4PKT!PTEUVR3`io__M^<D\3JHI|Ў!0${>$}#>vX%NgtS'ͽy-+:xϽi3j]ݲ7(HA蠺uqk ݚ6 yjRI ;݋)4C܀_-^mow 1^H"N#Gdz# _Poxz0<~J;Ym(:y%nN w#g'>ӝߊ6lt 95g*SJ$"!<!PA7*o_?iz)~LMc?O 6x+va:8gB$?җa,@ @90QmPCI0"WP0lLBlHD5% $'`Ul-{T9a 殶 G_7UiJH< *LGqրۀ˧_4&lđ%A9E^J1;?ӊeH`N€(CpbC0sjC# A#~Kѣj!(G z O#h1}_pat&'0OWzv9|0Ȓ2rEzk 4QY9H)j(l@Xҟ_c!@At@o Kx𨁌Jd (@lN@_6B ASK,hl@hȌBvALl[af<^@ J0sE_YPX eM(n(CuuP5((( ©dXPj `XB%hBPI"FJIFfA""eI}GѱHDSΞ('Ca).dT7Ӡ6JϾ p4Y0&_Q1Cv|[0[0!iF\qppbau<"\lB,P=zi_'*!D{9afsGB *jR?M8T!PMmv EÏ5!l |GǍEU_hr J+Їʎ@h4&WeCG#ue:'FtH_@<@y!"cbh/gcbGGOADCvO Dα8O.IIqjJMtS)hHxaeF}m n Gx}N_%_S6?{lC+jKWi~`fƉ*~=A\ qw{i8 9Ѥz:\I2, πHRch}+L sFb 1  B7* mΈa;Bp6Ѐd(a5kZ:9"@bIp &! m1*T"bB $R*LZfJ @e%&YR(Ba0*CoǻL9]#:]wN cD0#8*(( h2HS5Ɋê(X j1#DI()&Iı2;'d G`Fe\1?9@^X ;^N C!$8晬m7u<$bP?`4r :tD"XMid >J)l) 9du5I} )^l$(a%{X;y5\ADjǻɎ8&T0 4=6 ^A$ܾ$xD"h(!'@e)WGc5:OPE ~Q* :[CKItO3hfa0ҸvX4#:%v@k2 zKc[zХ)Ef 1T|.b[-.Q@A@rr*"E'^ pO''2I&S"z!'ќpla&OOOMCT0$R$z^!Bq0ʝT0@C

y2wE)DZO2(F.`2)pA,|wd@'E@Xl  8#ī"zzQ>(iB?%0%RC`T/nv5"TC`A CC{Z7:@\2G pt0Md?0Ʋ51@P|>$($&eJH*i̺~0hffJv `JOj2E%5;Ʒ3ivʜ*W{M71im8lWm*Lggmspvpli;iXK4ƙm6Mo9\DďKq&MƳ8s&q36Sg8;)3hGfלlG9¸DÌϢb<{#`" M O^O<2`?xqIW>53Fx4h\V&() 3EKF(KHҫdˍ-pe*}6#`xN1 HEw FtmkjϕXwum.sn09.Zu%D7}'c#8Iy aO˴]>S{1d!S""%DD""""""""""""$D=z/)ar^O"""""""%kZֵ; jAJKcHHdP6)Rxrr yUԠ6q%UQTн 1,h^| cE &n]wrB[.7uG{̆&ªfm6qqqb$3 mޔ~ 7M(@(PTf*l6퍝'uqmi߈zvMllͬmvYmv1t2PܴLrp)u$F3]3,)$U]6ʪURZeT8Eb7HLt͗U^#ʪm+'6 6I,dvyUULq,k.N$H(iuMDRcdHXXFXl8pn*> """""""=#ȉ"(,*BXz~ N`1LSbMJNVdғyPWx;&1.!4ebQƠѣ$㶵L8 DT^]kvARG@~LЛnaUBL0k[SD_#])AAS ,cIxe c; zDrf)Ȃآ2|348OkC}N<.:A sA;SP0""bcoHqb1RԈC#c*!d̡WQy`c苲< vhH7rb1j4;54M ti^B[;m !(11ĕO;̍y h<< cYz<qPhv̙طݴtG(-CBЬz^&z5tUl$Q@H5wᄠtC=8}Ӎ1E!1O7Vz/yR*{$3G 2)EY\RR@-~C I 4DW zP3`W4QIc316Ho[ӻnEׁ>N=x&Cy>|؋D6-!BR@DY cuXf/P˜̪]Kfem¡v6`Y\Tv7# P+ia1B>7LǙXa:!DkE1 p.HQ1VЌi!hYOz!Ê>G.dlfw9xIP L!pb$%/k'䷾X%+" | ~(Bwҁ qpq%ЎX$lP_EV^W?*q3@redR ރA2A{*qN؋'?:>lC^*?h09II<ɂ8L''`z{SFB O`/#bi q;9@A (|x p6|~/x⁤htWRpuvAB-b`M?Δ@ό4( UH~]G .P3yw__%;AFVFTςϹ 򁷐AvLVd^ }~!J)"+dT2 BpHIevEx '-Uv8/6R-IBE%$ʐۍdtS\-4$ER J10 IHRDEQ% %% @- TL2DTHPDJQ2UDP@AB CDdq$Q:]4H`<'t(E@|Dw;#II3`rW ZQ} .рB`:!eW8'u-J{φd~s,؉$Ab#Q>G Gyp!)&㱰AIz8 $y"D~hCRʩ¦א {A tFQ "1XT' @p0_`H' n;` 7tO*2?(% ծGFQ4/lbbc";&B~, Q!*p?' 0(ZG!wSqNEhSֻ~,=mAAKk҈@^pO0Đ e&Y*#h  m ȺP4"ha$01T we |n" @G76DnhCBmg@`p0H!IDC |T?'{<}8QIE!#Lgl%# {\dATܡ(x =<z|@7 dD6 y> gE)T|d!Cdž&E]b Mfr&TN(EvOUT4yR3)@E؟]=9 xsNPx*(8&"{HS<F@@ N@HEE*@Y!dh n 0` /r?iôd7Qcr=׻8S`2Ag:W؈X$( Pd 5ȡHBMTUE4DY&&ٞ U9@ %NY: iDQj)SvpD$!%R%77لx&Hz_1DJR=بk߉tHHOd!A $dHBCA Jί꓏0:/<*uCGjî>9wQ| s!ץq@!PnFMSG@>_G;,e_#. "0zLeT2I쁉R5@Vt(ٴvc=ROә,C̲#4." "HDbj&+{pKM] 8Q R Ip4>i@ EH_2|G*:4܈I+CAc%  6R *=ϻiE!MϴT}[b!НQ€(BSLe=~/d")&2u_ZhYI 0⊍e yGQ а d䴡萑a*j K1(yֆ5h&tAt; ~ #H |a%}T C<&&P|=|<~^&T/^4a/_43l&) qZZ6rF(0 P[fK2o|qB;cA1P #i"q0.ILQT/0= %@bCk¬$G(G&RT@<4EC=ȠtvZa ҈"8)%D+ǂ , G!0I*sv$TSugDP8ez!8$ɣnQpQ=Q[$%&LEICKs<&諠1W LwH#{JF Ul*\*9 fv/D;(G/dVDtLuUvJ!'>_'ߦ lNqQ< Tc}d;yuyh)QuK] a"l1}.%HID  ~ʞ>x@"Bur@@>0r??(N\k엀 =T<E=HDhl=R!AdOj!! @;4x0ԻiCAdK=~962 (š%x H\NC9ȡGnT($2PBXYvex>uTB=C%ЫW_{@34/ Ć#Ft /DP=>Ie q˅"!,DX_Ϥd"O_7g~el)U^m|I! A7nz]{GW۟Q .0P2$#cMt31\n>y9ř&Fw[w&ACIE3o`qz~s/ϧ_wx?ZUQ-W^_iͷ_zt?'»/zh ҿ0}b ?/:,3p#E#ı5Rv DE+?ސ`~L [m#ra`Ř,ŪW+ N?ogeY B/Z:ˌgH*;5H9G\vUUUwN&0!`ۥCj1[eV,mVJP&<7o<0C֢X' VO@̠G?}$??p4? ϯ ?R=y T‚ټF9$ЎLII =::*  ޏg`p|s D ;ݵ5W].`R,'(*z@Q]fl`Hp$n`b#Pr%/a]R; 7@=Bt7l"0` #?*7JȡQ `zupa@8,0H0L%0Ҵ4# Rm Wߔ*$i'Un b9 <ċ8q4YB%̃q 8bZф4Z+ sU"<#6$p{]k||n<- w )ᮁ䇣b3|R2("E>_I{p;wThJEǁҸl}I@]8p}x⠵I=I6 /i FI/9yn6s_ZmeYbdkutZ| =pz+4.f[^Ǯ\ $WBl b!4kx /p/07'y;&4O\'CxrJ""m{XT艅*^m"xc,"uT1d(c ;qE1.Ji>f4VرZ/x8s=|KYmճ xN8`@!!20,0O+S aREy Dd+a;FNdzIiMǼ%'aFqꬼ\Px1QdWx_ ݶv VM.Ъ8E9l$y(F۫%ѭ AxBbbN2`A z] l n!$aT= .\@rv&{^*@SdU#_ϱ:lQ谘; c|uƍ^:up3:5[TiaH"E-qu[a@A(C;1.*'C(AGq1; "^`,_?UdL*t\A)-M>o =ꈋadQQ8_ld !M#s JȜÇf"4𡳽Rx $i 2[}3?$EU˷fR^K&/aO&~^$`ÜU $EIbj(8Jibkbga=LQE_ܲAq@(̋{0,QzE0(, P~*@(GbnYeM~Pa|hw:D}WT@T5 E}TUTyDM2,H}2w*ߕ]Lz'⒂(Z~C$`TC#F[tGsςJ"v?/$XD LSmH^`TqNjmݶ܀j aȆC6}Cx 8p: m(H:0L2l_;={4Ni%2=|\aa4HBOO9uh(fUr|KxCsIq8"*ρUV0faLǞa o7]6+BdRϸa1PcUMѡ !6h|J)ERp2vC-8>-E4P4U1,tkgjH-1J͘(4l}88wA;6)<8ncnURwotMU}(u;Q7p *1h|, ,3.b`[( ,T?5k3TQFCn-"3g 7GsSܯE MEmv3皢"W4DE\=;{+*yD@: GK$!H~7E$^PDplc}| ׻?>2/p\ tLc@xQ6$T``zP܁Aa̘"* a("=G/bfYjI}am⪨a)B99?~&laB@!Ō-Y}$iDhP^@m8mpAis{y)Il!CLx )|XY YKg|JvmU$黕|4Ș,H {8{DUvEHLEMQ~C٧1=mem=81E||`>w,FP4|F"ys.Ga8{3' H#XwJyo-'lmDE O d8Df8$X^zn 89t<-:12`};j|Qc^E%7cVግ!O:"s 2c0 O4 eP<]x:*œ^*SK dL zdJQud#ldVޙَ2wKԊBce.Ȟ(2i鱭]TEU d2;uAJQ1~~/-`J_bQR]iDܩ͈KK(L1is0)o~p7爪5=8 P~; O1H/ ",T5`|Ij!X'$&~}>p WIy DDEf4a|Q0- hSF11Umc.ş SKE"@h'-a`4+?9 5}74$* 122&B&J#/S$I$j־ө3Q_bYg"!C @Ѓ{:@@n`w^TR WVx2<-Z16+ZdhCZ M&a# Y0]MaG2""mIL ݣie,@zRU%GI.#K3pTu;d|ԚD]C[Rdl6-֔F vh FXHebXc&#묽kUm!nĬ 1jvlu4N`5N%O7cDVÒ*XW2!(0JH2 P@H-S4mFhii ZM4]J(QAA@0,/$80@Id)iLI'_S@ %@Rq.xƇ͂&㧒9 lXB b @]^r#@&RaDK݄ȠTts9g,e@4$1B.}#9#B.VlL8m LӃh8q13!54|Qxaf!PTǢQ #iQE)K@PHq{ϏQ2WhI_azm{>BhHX1⯸аu- T r,!@ tU8Q>ao3qegU"&<̴9@n| p'h~=Gb"Gi38@ݠo""fg>vHĩ'vC/ 4IϾh7z=??y/*ydilr7'PzE#.pY" W ih Znp8h{/H$e!2I~׵˛|60,\Ek#_QRoe7R<'|jhm$1ƕ`T Mpg(zg,yvX<@蠐g@@[K%qE!D>e66<-ȝ7Uᗏ+.#N-UULfmp7߻IBZ ^G笨\oc\`QqNI.:kQn,Ɋ=tix0q=$R q֪!|<10LLZL6S`M19ntOTeQ,m(xE[Bv"UB5X:0`2;]挗L6@T JgWA zk~Mtv&$$oa[[Ez#&O2z2Ng7-hGROl>SHQ~=Ž5q`EKwډyTF8cyd|_-}e"Rw+"^݅d V3?M).ƙ+H.D ]vmQs5B:M#<}'2j7nE DP )(Ci&O ()/&t !IP~;hH!I7)1s/$P6,)ԟfeC=qR( yCvA;{FE`)-/(FNx|]цE 9!I ЃwU_YDBH #1!D*zD9!@kr(T(*Z@hP&Jh@JQHDMipsӓRD)3R*SmQm4H{  @G]^y "}& BSq>Gw)˜Y1ӈzH{1l:t!Cv:xJ{EA><:-by#b` 4ᢊiֈ()XJ IQ X#G 5bmA1,a2@ptL_ޫ AAgAJ y_HgUUo|q:qѺf&y'P0glat-B)x,@5@(ߧV=0y B /ƞG^qbG 5 $) IHHӖJJ pG|?}0J1M=q s KɇT;g7PaG$J r,<0pC<=9 (4 94>Kl Sl $~uIT:S;8zc m(w.U ˯ Ҕ3?  Gü'g"MDDxZ.Ҡ< ~X.sQ!M {_ /܊sr>]a.X ABD="_Hf%~lChքX:#O{KYM4عNb[ t{eH VX>9x%1 Cݔ%SDP"vuet0 'RBpLElUUEUQQUW`C&Rt3ؿ zJAhw(n$ăf8vL*#8BTG50=8 8Ca&""3su܊EG,@aM>< aȺ%n=gv@6 a9 %H!A4i{S(R>b!N?j)z HaH;Ӣms٥ Td%=}.bĴ42'RǙE*fa:2زli@1# pij 2bC643!2E|V (&I4T- J@82S*"r0!ga+t.dق̚@h)H$OV"P &`!ہS8IX 4Z5Z )O$d%j*-&*RUedbL$>4E<D$` >r(DۆD@99Hy8 kQ+š MZ9 nP+i-t{j Ў',WLO@&]&;UtMBJe,IFuec-X1bVw9GZ g< hOy#qb` *dCt(002qSxE%Q??km>ď;bJ z "nH-_U_o5bDJzXf@AXIE@.EpV"@93Xh#j1<\~K !ĆD(1l?pGMG   Oā@p PZ(ejDs$0)h'G(ZLF6h0 Drmb$g \- {Br&&=Q%U(C '+ ҧ  _u̧0HRJĂ|JB=eypWgZ8цa l>dvF{Ցt%)d71*|{fdM ApYN-M~gEͣ=-;f$ZQ)OEl]Z|Lq8zhՅ"ۣHn#"Q';ߜId ϽPWH`؀$ NwVWkW/ۻ1!OeՑ<}JqPvƬN|[ep*2֝T2YqF0 lBРh5jO4l$ MEDUaMmy#s]kU݄IR*bS;.!-\ i9wb B7<;h}gteJYo|gmxy2"&@l>"yױǧiHE{+ ~2Pa/]NU΍?bR_ \ϙ̦HP68nBEsS6|=ŭfՎ[ߥ͆)78+̚Zף., ,U6[2ؿadiʧ%v U&Fq UC% 2%$!>,M "9PDUf" $pq0VR#Ap I<I{h/^kZ֊~ Hy= e dUIDT)TPQCEJR=H0 _yr~K*)eP$Bv5a5w Aϝʄ;$#݌!')<FTt$@`c9 *yy?ƌ# BYd( r1tr22b hi ZCP D !tDҁ N=TvĦ0e"iT4\2$BYb2icfiFPbdѥC"" =#0/9 A{"\|a ˺ZH 58၈8V@e[ǀ(pzI @BkR; / OYD#$~?Ū(D]QEZ tS$#*{,dA݀u'$T1A:W8"-"lphcP >Lm%lt'  !/jt,Q=뉳ÄQ8rC 048˨F8 f6H% "Vd(v[(b8(lF4a&" dË!:mc6ȵCF m12U-0Z+_8NP"B3f(ws mit{!L C5x~m?"  gYBkwR4[AVaHXmnF"d!pv2s)8_m-[b"cY0 ̕M0D0QPE4A! (J"jjR j*x!'7TM$MSQLRDMCQ3SG-mИüMT8 G30( 0hlؘwкTtLq:*Ƌ+(@+EONNVr  ,.Q4#1+Jht @P4DyPqA yv=le]8/>C倵lxc;@ p!m/;s7M E"P1'R e6dr5&5'BmT#@/!Owfwm lɁn|S!()$uP`پq5E{󆓾mA6?O4+!~Ԩ[+ fBH4*$Ј!Z;H`t$:O^j}i"DiF\ yHďqP'%c܎]k-cl2%t:yh=a8հjcX6L 098N kty%1e&AM).UDݤCUcJ%uA V 2 (n!<ŎL q0ybH6ExyDŽBK ,*pH.@.ɷsѶ =JPJS =&(7`1 2xypO DƈG - % PCJUTU HiO1SW[f X<=D a KI"a4TbPӾ| z ^hOp3)l{{P QUJU8_Cqbx^* 'D1t DKL'\8 ē Rq/\888T{CM)Wm^lIhrp%4eGz>xcT"u@=7;Ռ!1)yzݎC9d=9!cH$P 1\ r.b8 MY  +^xff 5ġ& k6{vmTiy&It<#x~ 80s= QgSAL:\;$ &j(I6]QAB$B-V2XS(R tIj(ojلq>JB0Opo]=mB3 TlPTXLh9<$<Ӯ:( S B~c}6jVaE8CeFTo@)MU"z$_9 { xc PhXфpMea"7p}$aEv@XUFDNC=ieD3lȜv1`L̙ M)=xGbX2n )$13L4b m FYefEL:hFj遬! yBP hJT-VF0ƃ(@Eq(zh^R 2hFl8n(imR2E {mQh̦dF9 Ⱦx (k.*B)q4EN A`RY8L= R(f!S&! JʎD8HD I!QbA1-]4`(="_APP#IE@c۞iD#a"@R0L~b 8,L I%k! ȸpٝ˱@$A^1 ԁ#CWO.8=hSbSB3 L5AXC ~S ASB1EĤHPʡ5]B9b Q| 1C$i Ier<xHcRʧ 4RPĝ19NUq ̀|KFa ׽\@?ʗ IDM D&0CB[~zp>:5xd/C 9vDWH 궧"{)AIB) ӈdHE%0{t =91 "*1Ÿdm[G,Ôؼ*/rlS# TvZF'n1 > Ƚ J9zx!nPϮ|~F |ZAᙀCF"=r舄 `^ "NP7؂rɯ݁zdhB{Q& 0l1xY`DhWX$ӥ厕(?):0SIvJ;At8 M"jBNJ(:4 &@nD@e' =~4{~aLf%(8<i +pҾ&*أ!0i(PvGۨ}€v &Z3?Xh#DBT A@LMI`"B(@&bBdj$m E0  A0BDJ0"J1DIDA2 H@DPS5J$,0 HK 3,HC @DJDU!E; p1JQ$>tҖB Rp9LDGxw}Mbr< qc?MȘ< 'n: Z>9VH=U $ϯ0|Jݻ-A]YBizf)v0<^=Msu{C)4T&(!EM\I׾cR͜w 3(>~|h<-egg7گy f&;cjpkW0xZSF]re3nS!)qީweUUeG4"e!l]|w4s/37A6"z<0hɡ8<UrզG{qYd"4eS^#Q}񍈽LwETbm2C;"* p @cp"J<,dF"3ՌCxli%HKCh ߒpSYI!$ !k 4En{1وbhgwۣ5Hyw&qerPvD;\(}Iǂ$4^+V+ta ;:Y0cd4R'):OTcEBt0*#ƌ٘ȕ=H}}2ef!5$&B7;CJ.'Z1% ;ڣbP D@P  gη5ZYi5mCog42 OPv#53'S=9W!\ xI)%tmk]aћ5=ٲBehJ\.*<ԯc׎Nb/ލRݲc)&=Y 6 m|֗!(:Rp4q:z/JwuEyF,X&G$-NMec8Mn'$|ew v çC}W&SGvhְjC]kX=6n-;r P і:#MP{La(͠,#q_OBbst6dxM ry(@F&Ծjσʢ/3R:Q9gnvk(= y [$dId0I6C~=zM҇)ؕӡs ,j[]( uFyKXE ٢`e% 7fêjB[΋fn88@,Ҧa+2l-eKFQXG 62<;Z[J m d&3] (~PJ}Kn$1Cv |nfɞyE\bF`|4q{dwc]w*UC6 'YPhqϧxML&/,ySMc:4LEk5{4#`ڂF:-"B"7gŁ3WN.8eZA[$@c 1L@Zqjγ}[v5C^X3JM*iJPD8qb AY뒛cފ:l~ؽ NlvO;VGY+ l&t];9)I;  88c/ (XЕ&KvLN-5.xINtkd,a7P~(nMѮ}ULz%@v@f4^^ۥS}uzm"nĘ 0'f4iuǨ /s{򘁼*10.TT†#:F6 AEv6f*9xpZACal`5 j[^Q׉o0{m>`&]=tg81mK:䄖T Mt&D4<yVY)CMAٸ"Vv 4gĤhaa!e7#gXrI`I{ɦc @~`b<öVd7pCc4hȳ|1`;G>4I>%xGV &L866:gJJ-^LVwX@oi{* E&Е4VlJI6ƃv$ c䭲]z bvJ/lp=yT}gclݕa_llLH߄Ey:vbln^氱[G/h[kDr a|R4e\rkkMmՎ*B7rGft9r.LsG;֨!թtR<󣜶po^^ <"E8 mmr<8mq.woo{OT6+$i^qkԀ"賱|<=o!V.=js}p`IlW#iwcnDC NL449}tAZK֦BH ,|kvsmŌ,ZD"O{,G U/Gsg:U?&yS\3ڍR鉆Wa+ SgГ,hvv,MKH􁳖Bq&%0{)l}-Hl_lۖioaoG'E+|q]dw}F"ؖ> 2m @aeNp_6=Pa4"e#{-x>fb|@,adnDL܊b*u+!,NE؁ ۄE&P;"26~fMsCFOgg-£rTmeeLC/>12Ǩon8pwRٵ4`[J,R+ijTpɤQVg17Uau5ѸRtaC487\:<etj:|>`Gqm8yңC ń:wk:Ga8W)ylk|!U=i^صލ93~;vEK(3(ʐ˝c:tuYnDD٠pt XvV3XɋXRsncnƆ\L|U@t-x,\e9tQVRڸG[׍谋,ǷXm^%hAH(GpfQL3̆_ܿE%zg*z0#ac5HVYLfLJHTra\_&)V~?GԮOHMkT.ÌMX4 Y~0(HR G_H) 7ռ__]9ˍQθw%=xC$Ԗ7o8g8ZKweX#41πuL∍2s4ܜc7 XYƛ[.84}'qpδT|22M PݿM򭍣I `4s0LrP{MJ  (wMā 0&]دJᅲic f:d^Bw4l[`[=a5b1 ۫ڲn2XqWp܊RJDD!@Q0y#t >@(+j=0GR<@ 2P†:t@9/@珶'X@A. $"@wfPIF %88ٙD&, nC)(t)d: !,<)8in3F;qc^ݹAAC1ё *}Q=>ʁ)@/>J)Ij5e $AAF۱1Ygb]ZC:fް'tj+,,zsHz09Kؤ.=N!$M# #we!3I.P2D 22D$Hp=)dA/T;m,9@SG%7H!: @DaݮvG34SDJϬ@O%I!^$`Bs (UJ[-$bt8$bS6r@E> AEP@|ZK"F2*3 H!G Le@FT&-ut6=QKLl+LVNT[`UyG u} ̉17_3s}*e-3Y)WH&O9:o[a 2[ޅ47eS2@Q6U7B`pDJmj<1r6$_h{wpE\y{Wi!r/ T2rGs\b"Φ/[V9C1qX6%x4kD{Sxv{zOȒZDoFl6q;xLU{WXYz E+N1>yj t\ &cjdSZEٲ*wд6rs4s(GӓdW(plf(`Yn]uWV`v@Es^$>|yvͱ[։*4skfp#SdN uĻӇ<[ U 5X^jؒpnng}+;{M:41YЕ _=h Dt1VSu4V +WzSV6ˆSln#uᆆ U!~>݉LDIwy&ĨM-#'8tx>E"`E%dPѴB 1 D6X}y"kI)̹|΃ڃd R kr'@MI B'cG4*p.lBP @y;Q S`x hvQaVChpE0 !wbmCձ<.I)Oxe7 f[` B)R,vLDL(;>ӯǘFx#~~Zt !tA :mj"4.XF֮bLB(%vk.HU@Syt:A r.ѸaFf@߯dǑ@S߀:m `yB7R'SH0@I% D%$DLEUQ𔰯v_E?l>ZP*>bo88oa4DH; iiifa9=PlEJhzqRz4Q$ekL7q޲'{  M%Ǩ"j4AYCIfgIl ɏk-Fd H'_|bʓ! /{8c/(L}ڶhwOy‡#zP/^ xG""YUq߈  JP$ nH_AY^unGJ}RIL!7T}q:tEPj!)  r$ereCe Wc|8@r6Wy&Srf# 0= ؇$/A5) "pxNb&dh?ƣ{OYDk|YϮ|ͷIUP6Ҧ7 I "e9 Ty&a %!>ri#ΔZ$?xYЇjcV=AC0PUAPQr"PP8ַSx@CrK60Jݻ?ii2CtBlcYa 3+O41DN#yxIܡzR߽Qlce v[n˴#/0y3tDm cq-c/)`1"FH AQM Hq8L2JC#->`I~4VIAjE Y!Xx2VxoKj>k(T!&WE?C@/J1哵6kژY$Ѷx3|i-|ģ>'#85Fqu3oJ̣JIa3Zӛ#nÍ~9T:'g6zv6yBBE@ YD@رDULaO'ع aiZGM${!O5L54hDf}Y,oT/MDTQETFEyT PڻރwRИ %epk&Pc1I-PR?; tRW@@@R!CLJ(PtUCE1 %t s~UU_''ϗ3O!(*d 8?<{zFYxk+ )&,a4 POTe`{US=U4) P\Q1p/=̆}\ a%b JG>sz^bo/C_{)46#8f$FXvfKГI&$~Tp3U<܎DMlAH=4LA".yN:\Tb82:Fxzt0=[fƎm4- B!aXRBXlUʳq -B\L.f (ir*#A0`У{^k0#WtX.Ya{tβ.&TS=Ir(N" ë N:KmTh~F>Hr.n4v I#l!"UOǃ)Y%BSDPSUC vQ6I]MH SXC HY1!ÎS(WlPJCbA " B D(M[LH@E3";&h~tY]iT t|*:0ugED5T4,HE; |a{Kb}̹ٛdXIzE<4^G} ІIzݱJ7V>u7DMAG]뭓IP^?J1"z WJi^ f#1Cph0.߀T%b RO'I ( #З:v"b>ŧHC&"8Θ8? BO_C;^ 4Wwt?lgPXt?gO%@*uJȋlTBUɤ-?HeQ oXPL`L@@J>: pIt:cI+8.qRLJAA 0TLkTVF|1ܾčL!ڐ.!D "KB I8>d%1&C *#6(*@hpBz0vhs-f` U]i*4cZg4NBrl[%(`-M`MRXL`Xbb0i fM30I PhDxG!^AC @`:T BHʈ9P*IE| 6;011A=x/ W6 lPu:`ۚLT9"Kg7AI$MacA';9 djhNzj)h1vv$LO͇: jH $ƈҀB&O%0p#4J4C}D23(Zy LySp$M=,-%_LLCL!aq^:Dȿ@Oq9.Yp!8؃$i88_'QOk ' >8ʗc_9b ?- 6O3&iB[kOW 1g/ AcP(5*{Ai<Z(N7 n((*S;[B1#_0]>x6Z$ _1NDzCh¶T8Dh(=_}!A Ҁm>R@$OKl {V@ ǀPlTQ$E >.j\ehBU<$N! ~HJe=$ |q C*daqe[(`B C)(9A'LEx@',fcь$/_Ay C*=AiPA=)ĈRPd5yN*"Nn&>4ƻgѠ#"0d̈  I5Ii8n o??@gi-E$FHi`s"B\!@I:zo%{x4D P;=lz~:>ex73D;9꘩ ՗ QKW%=h<:{t ~(d7 _l#BP}Rx( PuTa>dqe@rfjhZZZ5i_:)E>)DE%JD^(#HEACPBf12D1D# IaJY#qN1RcM4PHiJ/A#ACD4 l:oF:>g  4an \0%GbCۂC/L5JRDA,R G ! dKQ)灤+L}M1P_E4܇A6z҄Ąĕ>l4΍cLb"`~p>S=hH& +a4e\С 1 (&61{A8 3R`E VLAٺIXBXSQĔ(LƩP 8w?>O< gK=qӪc l8F*$Q.)d`#lַ:R)8Q[:q5a "*aVO?O?~ow,6JI[RI1~E1&Brja ef0Մ3, )"BQ~}\loYѴ\D@;0,:,ē)+ET/ -qFaxf!B(-iTR`Jy83~^K*ܪ#XB/";P0ExD/cJ~p;ߛEThȂ !t:JhJfFbBT! (Q)a4bfQ1Cb #F0B!q1["`Z%(iE( H PKDTRLDĭ NY$ZeZP4 RmbZ.\%RP:h"hZhhX()Z))hY(ZX&  C"() 4e ` (I@)WJS2 CJPIZAКB&Gh[X*h@̈DӢ i&RFE*R+I")#y0]sB<%Xcp@:@~(4JBtA(d)%I(Q  E !E;)%. e&AbZl}Sdɢ!7=\%,h? B&%"J)dhYSB B $5@ABА=&J JBfROLA$]]Kqk]@C Hlw2ag* "DZi T|JX I)%jjJ*UbQ!d@(O/#@ }y~AOPg]#Ih]h UHg7l=BGq*`^d-`} yuRB1p젡$ Qg}Z4!SCO`7S9Kv#ěv\MN8^DDO'mHS @pABdc m cөuȁ ;6l_+@hߗ*wAS#F =d!` B C#8(4&/L† # (SJA4@{Gw)HzGhD4]#""@@v<`0?OmK 5uںj1^HUx_Аc I@4!KJPHCp ZG{"44 cfxnv3)Pjmn+/2L iϨ4`LbOFY b٥|$lԐ6&[]EDnO"*d;Ғws9R]N4ac"$RI eQ.7N 4ҙe WyoZv.Dxk'ӼyNk "–BZoS2Ö#{vFcdr0t& H&I|O@y 8}\%әd-]UqHCrM36I 8f1Y:1]bLt3(weE EH%&i8WpgX1RUPQ7<{ >bH!md t,b cƈ:P zd6vb =QDl*D9oDB@S-<8›Y$HMH J v1PE<bQ@0 A_T;?9sӯCz4@BR a$lԙ2bQP(D;/oڑ(A$c ERrrlšLPxӯ}K_|4}COIuaS }rHCBPqR0hhA]N(':G}H\п 2HϜ`^$u@NLo-4g /b8aA?g#Lz'tٸӂ̓ #e@A a=B:=0;ժ磨]*xcE?X{E?-{ jLR0D@R7a/ޜh4 X_6<7=C P'rWcbd! -H7cjm`;OI!$"|d9C26͜-Hd\:Hs#w&YJlE#8r@{ `/L_SG(M/c|ҐtmASLD&*=Nkiј(~cnC0$B{u[&mvϣYyqh8%_=cE_ c=%&ܘ@K|6ѱRUQ%\z}[5S<2UHNåi*cD')/f$XAd~ _MKl@PRcGXM&~ܫabPs+뛴 l&0_S LR8thAgZ3(K cH`4?3['ߛmr:K Ca'y55T*i; -Hug "yY͛ox1Z.`wOtQM"チmikhߓ<ݭ9%I-xִiVş*5ߣ 8o |݅8g'!ñ5TMmni3oP> X{A}qW^&`ؗQYgyF*\]X ӟW<%ouW Bx1QxD%QHl.EæezQELr;CPWQIAx420rgwrB! Gd& eႃ  ,PCv!gf`j!a{/8zSi/EI> ז`ʋFQ1$#TW78?GTq_rpP>a$:&&Z*])!(jBE)iFBMH"ESRH -B%;bc-H 2}Y?"0~z +=Cż2PO~ *D"ނ$*hd (J ! &!* HZ|4E%"E dC:IbX -% h"HHhd%Fb j bj )pKeOE)%#HIdM%)۹re$HH\.l?Xy}SH2DF@Ivjk߄ /l%$` B FPFITB( Fx~9ލA4'H>W[$Mb!09hW (yƵ G-ʙҧzY֋9۸'$&!!>BSP~ RB$!Pp=p}z[& 0P>Rx&.:Ty!D7R@tYUvEҢ<$ MLT;7n{QG)bM%3PKQ R(R1!,UKTI CCIC*@I,QԱDH SDA3@D APCJ!2 @@I ,H0 2S4BR%1ȃ51}gs}_vv@z*J_ $4h FB,A%i =F!o\+Қ`DA"':&asx }?thG GypB&~4Qo"7XPc Ca&?;PhCB}jA*y* |PCJt>yʉC2`zՙ!"Q\8Re-V+aH JܼĪqtt P%B l:j3;{)q 4Ga1!8b_<=`USԚ|7NkT1,(e'i"@N؈)<*NǑ#*{c8QEC ' ZĆ}Al0f)E yJq qٵ cQ|> 8A@ 0A !ENAַS5QF>!=y[`͑Pf\KP0, F8AL t! HR_Uz"" dO OllFr ̪b ^^[t&PAd@( Ξv:N_ޑ!QĤēH}Cq{GTn)FOEo¤bCc017 O|I`ђ Tۏ8݅! 4wjn?܁A1!{n&OD&`pb#UlIC"e! $!$<p`!Q=q&$QC"V c,AKDgg3C#PPG0',i+1E0@%^1'%::h (ƅKO|m3eO; 3qAQA>rTX7,B$h 0̸DjDu6EDP iM)d**aJ{B[iؠ0 Xb } QE~,pl AeAQ,ox1Me 0Oa lrw3?F3"H/voێ0Oq`"PnM8t@ >"`c1j4& &|>sA2Y2I<'ɓX"H I@EoCЇ_^'Tz#"# ')|d?2Z!Am!1 lqSl!%Ri߹HH  *| q[~F {S 2|A%a=Kݍѳ<0\'x8@@~HwT"~y*/[|CIT{W<5{͐B%Li4+c.bp% w$AU3 IH3̡9Mdx2b)dwbLIA! $@PUMA$0**RF=Ƥ}H~c)&dYI93r<´+Q+/܌Q%C ᄌ|֨myqwI%C (% u@ z0hn&/ DLDDE%USAPL0l;cx_~qѢco<1Sy#_^G9ǥRekF~^Xu<.EIk W7",}PD%%0TĩlU@vj"r-KCD)BA2$JPJ*<>pN'3`YNO?ɬSKz8ljPtmXw elhP(eل͚~¥خcFSuimȗxUJ?Xa(l26OD Ftwk5=,V ޜ DNLDC(9EH!$tBg)f72jD,0]=D=ǂ|p^b2[ziU܁D*0{At,dlͦg!miplIC `cD_(/R4]`_҃wweC@r1Cn"Gy)C!+@ТDIH$ȺB4?DOeR,BȤ H?̓)`<.pv50> MmjS#hl_l׍U lڣ筴[Q8]Ӭ۞f\#bKTO)縀pў}:wG17&ĴiM|2q\J9O{fbΊCڨ@Y4&ʟ|H|b? m` lJørjX4r!-Dҷ0x $X`#\ȿX$}cT(B W.P >,N ޥ뵣 r$d}Z%+ۼ۟:v6!! I I.s tf]v@whP֏`0Ԥ Lr\LP2+pD.r#໎4&>p'm`'VlU{{̌f3`N0GCϯwYBAdLkMQ)|Ŏ.K1N$-b/[f`[` V+VmM4Sr _l$(Fk"] ^w- SOTN6p1O@hR@VVٮݙbF9,waB+Н܆U 0n Mb)jӪcxc ECu6հ(fIhmNq&$ Xsa9'Wd<=8-k^C0x[GGBhq+$FRiZ#Û+dxc~8rVDA0&q Gb_wD Bb*YRK{)d$`- @@ :nDZ(#=鯧1Yʙq!Lm$oqsELadadF a!5P:(/PI/")`GpK9a"!** G` a'jP2hf83(P@2 @*`9#H/Y|_;KxHtBw):bUҁ's&LvVmN 3;nɈ 0t*A #DS ;,HCȽJH%1khf$-DPъ$"F #94qUL~( _jP%)# A;7%f;4$b@`PL„V ;.Y(xy<'F4AB |$SO%%B@ 5p-DH'B lVLwsn{}F2TtW,KHjdZ'f5y[eWv׫mvI=Oů:Mv]I`E`1Le[}^DNX~NZI&H͝oXwqLY!X5O~"BL*B )S{ZYYXZQA!@ QW B)2NP("vPߋ<xz>;Yqȃ).@H4j"$X U a'\{"029H `՞Q] SKHTJ?|4" RB03`GH]@>G@` D$E}dI2 A~aOX #WgXG i6g@d(q ;=bCX |Z0m~'uHM3t.p~^RUšM A@vA* BGJ l 1E04Pr]u8R3831!@VEX ШS8wx(Bd=\zP ҉@Jh l Ċ4# B f-SLv R6 =vw_]i/[뗉 x1'o%XhV0МQB1Q?Y~N:q\$lIјL4`Ia C(vk.uǓZup<{l>I{clq)P0-0 Fע WH((!  Ҽ i8 /.T0]0m(+dޡw8Qhx"A 0GPP.hK "CA38$Et@Spṇ\(P{e>%NDŽ{Ǯ0#,`4G, s(R RP1-il (H.]@XesbHc] 1 \%G(b$ uVCj~ ԑQ"$*rI4y11C?9*@NyXQ"ECpt'^ S^PBE W~G,F6 @I  ItH?XREpBdz.،@A1q*TSF FI™ %WJ Dp\!L "0@k:4G@Zqe:gbAq ,0z?*hnYG}>>PP8%EUO jPVQfDI?f\=jT_TOb}J%ςB Jh XB>>uTC`hDaI&~(Tֿ˅Wɽ{>ڇ&'߭Ge(O) W(L&/A?$@`oùFah @PC D(:&!*D? $kLl@^@(HYT *4_BB1}jlH@!D@D*ABG@A^)?PSA$4¡B d̀ag˲k?0d/>H /! iM/Jkїń !x/рd&DWrڠAEQY@bU=3:xO`<b`^f"'^}kXT0l~3@rwOFd!(lENgaܔoo mSVH%aIaS1 ѣx8О$8?´h hF'BS&!"&tFМYD'Œ$V8{8qhv{*,V&RSqx#th:HDQ>G3rLyJR J ("rDbuT_\PQI]wA% sZW)y#@?U G'O"!`gU.}2 Zf,-$B0Aavi0 )A6- T&9DIeDAAӢZ>(` e *YN!jQR%D1/: DǨy!PQ7D POH6;G= a o&@@l&0>H>X<_䙩R1 {QFl?$(|=h~ē_rp@=t1XIl/Q>i9|ԓHaCC%;2 c s'0^@e/chcAtr 4`,-iSE!\^9MjlHj,RqD{~GTV" H*Z!b?(ECHG&!6Q7Dx< E1RPh; (x=nZ?@KCCӋŠ 51Nb "ls# Dz6)`Oo?O===cA BP3Q6Q ,\]OaF}]SDLH:ӶUTq1/pCED6`GDs4L~RA&gdJU>eSY W肢&"*?õJղ 33\(i(X (y0w& dAp%Leܕ&Z))9zR<2}2~"'{0yhh$`NmT!O91:/܇0R\ VmIá}*(r an Briw?wh ~ 2ID0H7vx.+>PnyOlzIlxPM CI2* /&Di}!V#D馄d5MməD#DQ)S5(40Ġv0";c`HB 4TSBH 1_?^a$M \,$ I[: gMѧv#(mD=_F)FD[@s/& 'rSaSD\= L?Ñ-{PIDv0 k$)>13;(D@%Nk^Ls҂Lxtr񃈟!A9B6R'`%K)L1TCf/ܚ1{ z~.) 1L8!GbP@:($K$G/$D;HhhӤF"%`h'׮ccA RPDd<8(9B{BBS!lF)ɤpYZ&픨lC )冘Yt\f&4ġMPFS\D22’BښBhR iEe q5ü( 0A@$B5\$f1ɼ8="=34HʔsDQ,HhL%UIDE! D2b@1EJ:BiULT0LMQa)@hE?)|_+: lH ("|]: hb , 2ΖD R`-j?N5$@DDE@SlқlKJ@r0UV瘩*(^T${p&J[:h(Xf)aC\@eG#,QD @9rvsFRJF($qQ01r:Bۡ:&)$ehێ袆h<;RYH*O*@6@ !  *B A f $!+" (HBD +*@@I$"Ji4SzC&¡*m@Q^Ѯ12y(bB`*q)cS,0NI PDv2Kȟ|@ca> X"L@8"XcÔTw 2 r2 $J aBBV&H!^b{@t)B@ CC2yJ_Y\@z6>ːe.bBt LobPL 2QBP_Рrdv/@2][4S +-c J4VCI3?pRLABfOәU+,,o@/Eie6kZ~I(HЭ$kAqxК!l?dqJRDQI@R%OgQ$:?;дJ)00%15#RҀ  ܖM(!2Au@ШȂ 9C$U/(4@; 4@BD.~'l'7WB!ZL EA^pUpZ%rs/̃ &??zh<ʫ>D|6*%4S>DCy- K *:K]^A3y}L)NΐF+8ws95BIH0p$)SJ1J: r]xSUWM vpN16N۳"QRC I9)~0-vqjs-MLTjSr0hc\d_|5 NyJCZ0ʠLmF& Q l.%E'g7t_0|]b`~ d3d(oUV4#H2K*~*_ UC:t,n?d8x#*$ `gGcI͔n4ɮ\4};'>8qTQD1CY;x&N{m\t!vV_%颽Ɯgi[qKo_YňgӿqfZdW_-Mr#"+ܦAԟ'iZ}F.~d8¨=/ /g+|YXf=(lD -|hXؼ@lhFeY7=Bm$mKBdxa˳6Th2bpLbi%`ŽT}y(\[<(Oixn׼PD})gd2E-0m:FIw,QCmAʊ>\Cl{0y/G %*AqEhu-Ab`ӄ"Ό|hέZ\Vltuk| H7#r;4>5 BtJ3u}3 %{bI 0E"vZ|;}:[f";;~}LF hL`Ejr1 XYs&[D|wWPNaWKU/5wr(2ȍ%tSFWUqjLPDƒ AYg$׋:[/6N ѸD4X8 ިlFAՓFg3@TZm)8@FEUa˱p7W)3-Jl^ ە.̣Mc[c-za-K_&fm8th <^+>y=Îmnum1L kL2 &s4ζsBy;AL jFmk4Y~f1kP ⩬\6qf|ǂTG{-.r=OnLsA S/%ڛ;32#N4<%6'6 ^ŭ ќ^ *Òu8HQB×)ݛmss꼞P_,d 崢5%6zh݀ 30@A8p1z +f":t'@TB HS!PZ|l$CZ"J@>!vzHfNAqe6~'``4B& P{:{35Yfv%{#@UCz㏔ ~96F% ?1 9ԉ :Kf|g`EȒeՕ 1*I[ `3ͲSQJAw|S(͈Dyg(A` 袖RDe\qS O#؏l.V:DhP '`Bj 5nAwo'=SEeQK)JuchXl#2tȁÙpHjE6@n'"{vHhlaDSa=aa>`O-k>@AUX?i0:p{wDt=L7CKuT^3T6e ϝBٽJ5JȪ$ JP B TC ) DH I@J@ݎJ\L$@fDA%jFAT/߰m# ED#nVm1沘4CMUbl(d ) k}~v⩮s9`4{n@Gh $|@Bǚޤ($D!P$%Oie| 6]J(N48XoOE4pLL܃ :yM E EOp;ORU| r l0{z)~>40v0"(|5p(ӮBJ@0qtPRCNx^*!2Op( &P 9_8>:#<DƙSLr@ 9w Dv뒑aOwh#Jt 5Hi_1E3Ѓvɡtzp4%QSdlQxT?ѕcU DY? o& g ]K @ˊBW$Q䄯{ښI(čF'V;[ჹtI@~Ҏ?~B׈Gr2DЂ!|ȍz `Q,F3ݍKA@*9y>-e$D|@1@z 2Jɳ렙i ("$ؤ~:@NQ#e B` 1hV>Ӕp a'bPPm0>ĸrTA_ `H[sPD !4}[:RP\F" `"" %  Br{ET*iL"""PGaK,'Bh-#h Th.ͥYO)R89py tpyAƍr2qO0WV1HF;hB,Ѣ'I~0cӺ/A{bɽq0Ts0Dq{z71\xe dRaGۈ.p绚vƘۤb<qr')镑C؜# E ,1EuUdNƆ$:7'ȂXG Pxr/ZBCW0wI҅ײ&)  \¢ >Eh0l]ؠwcl`_h&m5q/v3@ӣ@'Hɲ<"t^#l!{XM%1p8:v B ~ & R5u9)~ϥ6 Mt+z f @1,}!̸dUy|t $1 "#@P`>p{}w/s}Ky\eo\WCxg㒓6qL Fb#6޲m}>o 6lY. ٍKo5;{hThie4"okƣH">DgZᙻPIL7؃x,g!Dzcl^L+toţ5p 6$œVk^JoYΆ>j V'H2Xh戻tW@ZTU4@Ѿ3 E tuuc*XpH]spN@8DO.A!ESf,2715&L"衏+ Pؠ P 60OðI/3>=ȏ+mIX X &k-21dY &T1`,]55Uo%-^IaI2ZrзF ̡'(хt!pI,o:%= = o !cxMYd=6+ b9q ƤfPkD sƨ;@5C.FM"d1ew5ppM,njnIDlRǡb<]Nd^-Yse0JVld0Ќd13*|BsmX ^UM>>FZ48g)CQW:Ck[ x4E4zic&QACdAnnie*c&ب--u'=tҜ4vBz07w] C^܅3eօMj+Ty sQbV7'- 0Gѯ0)\)45%.E` O.1=?9ʮ!Oj{z|X{~վ(f1EyGߥ'8ia,?`d^)Pc QD^Gqq̝tWAԜ,]rxYCp*KA(T5 ejnRG1(Ƙ)G++XVt93Wh%&iCf{(yV}֖--E4&洳 :zh̄ kh&+P̊u z4իa -_ H#WvDO>@eܢ?z=b3=]g¡Gn+L5n.mȵI+k|fQI-UM}yםÓ :m=OH=xv3)1h.kZ.jF.$N PaPyKhum!{@ڽ6!"RJA_FJ2Q|Nw4!9&G"2m06\ˢ郺t6 ' Dٿo}i4)l5}N;f9ʧ\4[\ӡ$6ֻib9fz3p6dE2ӭxz:o'U(< %5"slk² UIdmB5d~**%cQ7:+RQEtV8D!R &o;SkWy;Ďiת 1ty3LY &8xGna69́:S<*Lj!  دCJf)0VN0΢6XQ]8ttD8;Fltb() *N $M$BJMT$I$Aל/?$v@ T,8`$-! =G-@^< {dZ(8v;*h4&*RN A`=cztĤI8L (pz1 qA"4 ' %8R" tH6!) J"hy/o4$AESx!TPDXʇ`Pq^k`оC}c>}bĉ rGr.R"0ē"=>HDO @)(P U(@B~}jH! ΤQU( ZJTGM*a (UvZ 1סLX6QcSv'ߞ*i1%p+/VSVG(a9D ܍6 oDLݽCm6QA( _Jp!} ~C"iͧ"AH"w;$(a Bd@vM*E~( 7E/Uv]`e2?&i`ftf5l0.8sVX6J"\hěci>>P@i]].Nxٰ*E"i 8M*}PᇌNaޓHJH,#E= GytTfVU_Ce7PrI B k3;q8e|kM8D6拶RBjR9=1 tm,xʼa1S)+Ơ)G -AE]S44^D.:S"H5U 09m 2 ۆ0 f;7=fB TPFp0my$<@Tɹ)UyA|w&bאP&ub RJ0\@@Cwa;!KA(U8 $!4$IH 8`K'O{_φFrr019V$=dS2>YGZvW!Q4녤ҭB1CUq7 j3upT!?`1UlO(+弔^սQE2)OGIM̯&IHhF`DdO%ipvqMʞljgMn\ P2+Z-s{E؆C"O~(y8'ҋDɃ6Qx#DIp ASIA2ba# ?}~_!ިB?~aB!ha 8x &LĮpE$OA"?b9ZJB$!"b OA QxVߋzT8OSP)hQ&F$b? h}C]B_KaHP>sGJQE]$F7"K]0LR9}J~ה40JujP . 80κs>'@&c w0gŚ $f_Sx>y^CߜP v’O=},@n=xP7_/нL0$ xQY_?dA"T8(:!C,BΈ`' N#ə:th'`̡5>VEOyC邊`9!&IɎXCm;މ&6à|0`#PZ=5D&N"ZD)PBcPXP5 ht" ~+`p_ŹH>/ˁyN`!H JPD bJ<18Чp''̔YN\I@9 (B?hBLE@ eP`(. kr(SKLd&eW2 i& J (H"!0B! (QH!@PNB\ / A  X%WN4?BDM ?ȇB?&N?[5_-ٲňG9 \e 9WCzk ,iC@i[fewy:o^ro4 Gσѭ7Ǯ7^]X _]}^UI]IP{mw9 }Fj5s;w ]l Wk{>zmx^n|mRd:cU^%E[@IH +ͯn%vgv[7D=)*){fmufHTmDRJU@K5!B Рh**: 4ȝn:I] P(U PT@Q{h*Dp' | =W,c7v{}>*}RG=MolH(K׻rmd:`RUkXWt7gSGTFys=mλ ^°vbyB<6ӹmz%PM2Huݹ+JTo:M4t;;vNJM@T}aϼӾ¯jU{2j헦*@fֆ%J:ۗMJ=o{h= %/&٥Km7`UUc@֒}sS=DYwᖼ5Nڜ}^zK {ݼj4zz췦}ϽT2}sۡ{}w׼{7#8}w9uW}I/Y}2`kcn)dV6][hV6zou=0:_^صϻ1}t!{<|׾@_"aNOON@-!w{iD+ǭ. }wqM^UWtE^sZƊ.͉VKm@ J7N>rllێ^MnZ{vr{{3}x}}h>S>BCkS'1ko W3zT6(> 7jQJn*sp3nٍ4_mwQ'k5v:Ka)/s+(a/}zP}Q͆zrP=ڛv( 01@yfTzmwϵM{{jhwl@Jɧ#) 㸠HT)ӗ=v ahɽխm ٖ!*lfm_v]Q>n7((dRp}<>}gM2ם'g@>u @5Y}ᄂhY-e몺;s}e yD>ڜ{|vQ@t hisaƊ}q,o.xFnh]v}$|{W%;チ%r ʛzwe*kp3fO]mTmٸJh@@ @ 4S&i=$f&cR6F@ L D)I(M=$H馠z4)ѐIRHLMHHS){SFM'PzM4&4!%DLSMO3F#*y#fO j  @AF4 !144M1 jQ2SDR! iQdأS=O2=OQh h@$Fʁh/E2>q~w͎ ~xI+Gn@URDG_~És9* <T_Mw  vȠj ɂQ#ET4QJiSADDBQ@ BRPPDd w0$!WWaa&"T@K@v])؄HIP120S!!O(>&a뮩ěi郏H _G6]\Jꥢ߬koIlǓJaË a8 d2o_* #'rLo7c^iC%Da2-~^wfcBRq3)QP DdgYiO PSD!5:PZzCC&dt=5}aM)O: ֩ OtIЩw>Hq1-n(doX$H#@y1wN!|Iy&$;$OqAH~Rj@ @RJR%"hbBG\2@]Q+!/'N (PIZā/~9ۏ ;42CsņJZ)rv4JXP.^p1/(S0a )ZB }oS4h<8]K1!^ڧfCEWQ׷T.ٗmQ"g'&%XLPO+ AhKzvmq#:"`5uz4f&0 nA|: JI?cDUYjhH:H% !(RD ʅQ%J<ՙ!ìa&x( *b  'T`wyټTrX>Ԩ('_VOc|d ׄEWilD[CzX)wy爞U FZЅܴH)[kt"cϪg"QU!@*3440IT4UE%@7eZ&*cX;.O@`J|uX d;Vke.nkZQ4 iQjڊVek-Y1BTeK[heWK5R X=mkaV1 DKm+UUmlF-U-De+IUabm&mZԍ_%2mKJPZZ9+1}k^K׺m3(ZVRyJ r 8*(oO2uy4L5M?dnꤋ'7 TE4AQ_\\_N>ݖ S_ Ț"HRQ &jWkG#F=]Xc Y4QZi-YmwbiR kHTd<=G= .a 25do19e_p&}e !NY:?Կ;ÕUf# o1fR\?GJMw| 4=ҁo׌ &Ϧ[ld7aiHTOi%+m?>0Ky ??0t tRU pu-d$q*<];b)Az8{@:8[yC|כU^%ԀQw '2*1@l*qsNœ$>`y >jfX͝b -_L*֞ Z_ 7yySyvҲv8jvUZܶvmDfW-/4^Q}o057q'@ }ۯKW=O6z6f).Gy6ny!zvٯiU4\4ڡ ju -!ۘF2Q'4eYcl(ItEIrdХ(ZhˋS^R.p/'nM8yp˓C$d;7nI8M{7~p3vCi4sb evjifì.3g>/SyىzD-dT.+Z\{{8牬T7h_o ƫwa&f!J;WlRI32L|%Mrzb'w?6tƘTTCd텗Gwwm Wy=n9ϼ22UU(Z3isIڬ( ',*Jj,v_3|] J BD3wo !=F>>n(zvW qGvY1?k~cv&O/]OhY*yi^ ֛85c@L^Hӵ;^|:LԦ~84O{[63,}-]ZDLd.L?E˃W1벯>Qrѹ.yQnxR,m&̩߇Z4? uNtׂ}ׄ% tl)wG>u,6pf &z߁[aռ=K2˔/4j>YTLfkg>5$cȜHME1D;p"ԪGHD܂ 2Ù';I6rf &:e}WP}yט J5RT@U!@DI~AiJ*h9El=-[%PPTHffšv}zs7%Ͱ2C զGapw#x3ǟwbAt>?*!΋ADQ f5E.3;>6O>q"yIx=zvFuilt-)|CU ^Gg7}z~XI|>Sӊ .l_./B#/qO%k2𑧺^j\/Åz'h*K_VQՏq]8v9q2cF$F[z3I{a\;=G+:Z<凉l ڂ7j'4ZA"ke- %C&DT=&GƨY !CL;Rrϖg3*@ W9fuoB : |c&5]rqI06W=p&l_o3ҧT縘S,brf&`(DX!y| RutI,hSŇXVD/dPx1}}/tv3zɤs(IB(|6FDI>Ϡ>'TDU-/Cc|%ʉ; 3f9eˇ|*FvT}oPe5ڇ!rY2_:a!aq縥Ò8T.9rE%Ɩ؉X~q./n)/[]﮵sxknCG"#I$"񙟔7m9SmLbo̔%\m劾ʥ'7C2M޾ F* oq`0bgI^!7Kdi]8m)euٳ*O" i .La &b DOiwLv捎AF+Fbb^n(gkcf󡐊ulI@bSLK_I݋p)w3ç}%J$ufZeqJ_Ǿ?_8w׊z.>l67Wwz|W\a73+g;qmp{ nAҤg*e5\K6\jGwCψ.WS1MѶc7 yYd" PR*T y5$#)PxH%*PD Gݻz)*:D$.vD"i(zǰR.0EyPGUU Y5w)d+H DHhaA n3Z3nޏ.ru Q0P<¤*j@ qpAaA$0 * ,@QMg7}A үWd&Jم&@bJOc9Xxbέ!Z~D[s(a_]kdH$|}/Ii885UV9' ~[bTRЭA?뫩s꿞6)?XjȂca>vRh[|!x8ο$]gՋW3$HJ>y[EU[+-џ :&3$2h1 %+4ޱYV3>8)Wgŧ<*ϣm8BeW]9Fw}SNћVQMƖVo㾳QOtDx&>ppE}ޘ{2B_S޽ Q^}~YӞDDMBA L NH8ɐ4!Ix; CQp(x]Vo~i Pg` nm03ᆅ~(r@$&WJP.KbN#K4Ѩ1E%9p!NH(f$ Npt&=! V bU>P6X@:=u6sC:?yO~1QJ&f"8מAxprW< PhbZA3o'[ #wAg47&X Z=5|:<bD PH@De>f6l:|v@&T,F@9d;y0kH&(RDLC {XFf0n\ 1> 7KG(z{*l{ηwcHd$@2X HLyݲ8y8T0͛I& $uHw %i7"CwJ@?oG`*F6rt =}jЇفB =R rejĠÄ̋ ! sN. B'05Y@̑/+KE١&YH8-y"JO Zx$/dtC d$- yO.d:c=EކʞxI y;7dLgiK V'dqldcd6} < g%Bd #|xO{?HT&ΐ8&>DVhB4>K O;H#-y#oaρXF Qgqwd\?=0qph5J*!0:΍leėC0hp[!;BYnb1& ù#U4:#d9 & egzd\p 21 a^z2HmZ[ p Áb!֢AgAE`feXqNn:XR3 P )aR8E.;4k5qq{6 0CMYAa%ŠL. UcD(;| 8q$10Q~Ɉ@$0@$2t@>P<€";1$@٘!r=P & H<aCbD  hN eaN;@&P>lvZu (q$i@@32\g:`jt8A¥;M?&4C4S5 2tQ>K 檠O*{"™Cd_2Q(<($ zHFw?M4>Bv8)ЦBA8xzp=?`'8MqUEoP Xdm{5ۏlC9&yÄxx^!cslx>2@ʼnF1x͔c ɴ@; $!&}G]C0FKbWܑ|k4km7awn|{Gk>0%ΡQB`8u:dowCAŚӷޡU15)G@Uفzޒ ),?paC]|-6`=`u 0z;`3fr;)/l384O@7P=qK4sU虃dL S7o*yt&dqIjIJ8n*{n,"KAωJ8SkX-MQx a3!0(!i$"jQ"s >%m\vx/.2foX-udD%&><K)Ԟ>w$`oGr%p fҝ<|}yp#"=d_s'ě7[_ 7&vT;.|ܪydXcͫ8&Xo08 dAð?+b@/H(LɒLf`fOOy]ك -κ0 7XCj&`s=8z㷙߿Ď"p"bIR0cp;qgN`R33& U2@&̕a|{ASİ!0ȩ@S0/ ;3yܗǾD7{I߶Ml;;6v:#Kah7f'i&Z˘ `A*߫-[MmБ4 pvH& t~Xkʝ[?0p"M"`P nL5%%jR{=&0n[=;u2v|}gLyu j0 k8h:~̼w>dBNd}ATz Iq9ϧ 0oGu  ð0>.d|? yGgq@ Ad0c@YdGelL H _bP^%$ AiQ((U*`DH P0J'ȁ "*zC"dGnH$EC͟Շp.@':@R!QJ4vI]٨h䁶a;l]倧#P?ߢDJ2LyR%U>cJܙC'ir"msVs`v :u\ u;dDdb߉x*h,0 y='0r}񙁑_*:wrɘ  [k_TziU&cZ{} IicS6fD?$WpJX>Sw" 冕_$guofpF:-lԼ]Iǯq}HTs#J='_.z-'ⶑۧ$$+P!&~/̻%ac'̔"_R?rDSL) HI 7(Vvt+Έ??_\P^N:s/ʻ_X)xً_暾^9mA⌉mQ-d5D^I܌u+G2*]2y;Wt̾$}5wڍbk\;/G;)5SK~KS#\ZRlCzdbw2l $0 ,\-'qfS@+>ok5/W"B/Lnİ'l*F!OjD0ڋ(4$rm6xעMCX#Nם3x/뚲g|5/\j?$pFq\+]3RUmLjw^\UJ|=?3\O9lk7ܹRi z&!DmEXaTÙIW:Y,LZ֮mホe8y]QL v p>ݜn}f ,O]+ g3:+ςq3Rq:_}=1>ꅖrQޫZ!ppqS<nOt[ow򔶮y{g`E*ӿк]:գO?O+Vs^7wD1ģi%>GIƭ_u+"LFt7W<1{kFҒ{D;Ws[F)\1򵳮LMxVϖ8[Mik;'l{pr2mU%J$+l/_u\?HjMSLxT(m"2VNm݈vVnͤ*dݚӃFw"ZvhK(ߞ|r7S59ڿN13$[k+kqiHq_^4_d4^3½dqzrZUO*=JJtz挻PJ3ϣOJy%p&=SXTЃe\'Z_TݳZpYR1S-49D~B˥$!ü۬or/@У@Yټa_J@ N[͉v)(R:R 0yE'OG_Fx&7M_ X SR9#hxCJr!Jba F姶bǦn& U%B{)r!DCw(삇N0AI$A*A#" =g#a]bgs6I9 ֬n~8ǟMvy79@p$<w~l15A H-_Pl02Nßl:aI˕swCPftC<8i)yf}2FL>~X8)=0 Qb;&;y1v Qji2 (;t?=)$D΃xiR!)&z_"q{Q%)APU7\ƈDdA$5rT(=ٝh=<{uO~/&}8ZGR}k\B*(eI>zh~>R=|Y#"0k1XqX&UAPDCĵ C;))ڄG^]&&fG:>;|N(q&pOD)vHIR%rX$PjD ceJ?g5ʬ LI*M<ϐKxtf3<\Zv6dgy]6056THaIaj1Pf TE( ǫo#vw.~wcy 5A_ @F8࢟^_ s6?ˮï[~xkrO]OoXgjOC|^7{0"3EP4-kU8{0p}qܞtoPn> n3ftC{OaaI$Lk_Qv~,wfYe,B% `> ا댵Fќs`[AlobCPg׭]Ǫw6"x\QH~MP_~2ܘ+2j^Mcl³*ԍy]4Ekx_粗_\L^[.Lpi_5G?i(#*U턘Πa#!wT`I6w D(B+.DpSB谄tѺ ْBcjnƔqXjg>ɁN=@GCμH:Z%IN{nr1[i5$Vs&f-vsYlBK]@ }x9/QDU"c>S\Ҳnx*%+V wlZ_lm It.ghܦ533>8]:lͺ_IVVfVVdxm)Jjh-D$j!}~3IwDڣC)t'&k%+52E^d3{JRV( t*I߯4A4l#_o{3AƎT>Ϸ_l^32%1vEjq1s6=mTԫZWcro!.vLAU OόŢAB`Fl٘`Ch7 /"ó/˷uZh.OZq|,<9]^sUG-f6ZrϞUלk!'H0dҫn .MvS/;O&":RI0a7 8 hb\ރoW6 EyR\.7R~ 7yNW-&ŻCX ;4$jS =ʰ<"z yDTPP$i8;xR?J@;Dsc)(9̤=))7M4GV4~hcĦ#lǕ+F:=q}q "ZQ҈@P 'R'LjO/O~mmjeUUWjUU<3 z xl; DD7ʥLAPQߥv˓跌V^`G+Q5!I$)!}OTġB Gmճ6Y0=$|=~ p<֟@Co"|S^P'o.j= U[pOU\mKyJoUR,J7猰٪/o301h$"^Y7)mP5䜟N}u]+A ~'D97b#]ŃCLL$J'(uP=}z2:ľu9yq

c:_ΡE fLk@ 4 fb!QMmP("XN[~ORZ- ڏ2|rxoCO8{X;=8uzdyj\`Tn ^~=u!dj8p kq/Hk⪒ٷ,˥J~٩qUTr!+|rL@,1 3VZ(G>8f!NTk=#|]&fx:Ϯu"U;?ڪhM9k2ׯtpOuZ_ү|kJMqb.> Q~kxV*'$Z9PO 06r)v( dY\`ƀK6S=[a4/J),@pTMBp 8%.N?8"'lŽխ+E-/֡ >|ϊ@l@qc1(!wT|!t&|[-.ZQPEIنwo3wnZeLOAIs}EL[Z'O);V xe,jGKw=T8qD0JbB ޴6X2Nzp|o2D4m19X ܲ[ZT4F5"%,A<7T-V-{brO=0O-[U8HYSڤts(}PtJU\qM;XgLc(i %d nͱJ7$W/$cIPw62w8ItYV$y2d".s%T8/恶7"-Z;5ˊ?M_"D!ڼ:GNh,Bi(j>raÚƟ~ tWNdѷ%( dD8Qvus S*NP&M=o j:RNۡpj6 o{{􎍲\Lv룍t+T؆54jv2)y;ɢ;swXy':@X}>@ َ.P69p]̭Qs vA!Aq"!MTYLs?{(Q8n ~(TAnPC~\Z\0q`JϋJTI_vrD5ݧD3Ĉ}6J"8I+ξ*RpV>\wsx22^@%A"JUH=?喍w8F] =ä}?`\ N 2+PZ̹X}x5 R9IneܟssOuT,z4|U(KT(Bˎ$Y;'Xu@V>~G]JRt)]cϴ8UXcBЀ4z莐)JRD2R͞gq>8)9>tpvOC / p\z^fjDo"%7[ȸC&}|Cx#Բc)Se*{DiE: yBNпvY{|lnsbG"Ss!Hq27ksVd_s˟Yzqt7ˮQ) VVw53vt'v% ac@DGqLEE||ǡ#i8&k]>O&9Eh9XOONYG _(w4JZ~zㆶZpbrrZх;*;F2Xhؼ!yԵGK āy΋ÃO0qb?[iD(D6P)U&2N3woC>M9M4Mph)I""" Kq=P{8~T4Rn6CTͶo㦉2'  ~ӍL+/_$k#}Mђ8EpD < PCJ{.VT`UJ}:߫iM1A?^2Af4~`wbc svA8f>s~ ͙^(m.yH.Ͽo@o|޸RS]Z$BVbLs]H$DPp%9P};C'0c# C^*~c 1"AtIILɾ$ZcRgF#ဍ[N5S`U> D6;R_NnOͮ'/!hNVMG(0O!3ÊfjLcM[ӈ^(?o\ ]|!&}G=ʆ/"c)"ԌtG0,Ci@#'Ki 9 0yC46IIi4Ȑ4,N8\.ˏP5l&Dx&tF-9JoVU;əl Q1Зφgfߝn64p 2ejHh֔:X(`աG|á#~"2_ՈƗ]==O* h(E6q畇*OڍpuqC?~rM;8B};UJ 1]UZHcsxL۫f&IcII#'¿"aNsW:p~Q2}kvCt R It*КX6_ka3בxIK*Q QO&`b惆;q+\ rBG#38aa_֛m?KU&ͿN<Э|n_EOznu֍ԞfHiz"P^w7Er5#\.7?IN8G9 JÔwҬ3 q6EZ?>N"ޠz,8OGLM Ij,&y+P Q0+Gz&ω $  :081\s# 2 GwČL558E{DaX0jTH={uJĎT.rķ6--9Scstӿj`CPGYTj2.*Fq_%-FA] 5Asx ~c3]þx PULA z(Y.ߛqˀ.uDAC2V{1GB6j txJU7%jm pB4THzDB G|s/ Uwyj<Ƃ?t9eĔ&g*-svq: w/P:X'c ;]1D@ޟ.`na],cB2!QRd xDg&Bi&q0O{A3ʂפJ*y$&$4\t01Cмp>ȴs3ZQ纤FC;ħ2_g^)}A޲wPU{ TA=vTz^*Q۠Cp ش-3ͤVK149Iz, +tL}9fNwPLs5A=I:^ѩhHdtG :9z:9&:e*?Wf|7.  õ?(wa H\)Y.3$fNgưN[+fO;7gUr蚹;c[Ix6s.+S&'`ʑ&֌3*Tgؑ|*m 򢥥 )IӇl-.\g5"a@We XJ J^v{\8\7=3 CNLtbO m"M!١. J穑 8'TL6K]2=sr/>oǶ~0E>74umG>5Z㙯3;2&Ssٔsq-}\^|k[GfʉJuGvLV;Qw|N;PcfSEgk L*}Y4pQ x<9r1>C2-DY$Ɣ]Gɭ!(({(U@Sjb(7ѡ!evn9ç9GwEDu: öG8OH x,JWzOzJ?CW%ј 02f0MU8ZE숰\&if5V;l6s[+Lwr^̀]Ŝd?]у؁f`(̵dtz0IbN.LRҤjbJ,hG&*_ dw_h1%?vVxW2Dc 'pmA^G:>4wU1IǵQ'sJ-S_CNLq'H_(C`SAhG9[yvl4&7 p~4t^ $`BIP;WG!oTRyub9V9wdB`HL< dq."i7'QS*qvfn`i@6C更Mk$ >w}DH!\!?ek.^v(2(Rήv|F1f˼;fbPM;HYJ5 ss^]$~#Ug:Jp7ki1š/Q^yfDkMw2Wh 6y="ނEr81 I;ܰkҖ`S j4|$#kG^T]4Z3<ɒx;߶4o UeSH|{!9{ʛ49t- ]pDlΤ6(kLirjXoDнU*LWLg=]ekS@CZ6'箠I8hq'Wb*- */0䱚>9'\K1/M% ޯaޮ]1q*D>hz`..UtF5U<֤,BF\J&-D뭸&J 22L |PGUnp3+8? +(Lq>4@I6L<IW8-&ZZ0LGy'@-khF^qA" Pᛂ6B'~ZN&y h 2fez]#Z8)Kq,Alˉd%uԹ3⡭ NGRnN|@β>֣e>֗JWls#(I$Va~zbiS@I+#)g٬R3fJkk\6J"  ebdϕb=s-|h֯<׻(H $6z >|ÌHj53b=x*Ҭ<a1MdžRh(߸'5$1SV~*Gs2Y5n5(28Ѓ~+Ad % KXSh'XE9B9gy=ۓjM(>ݧJ 抪& );' ;4rI]QpmƉ5bD9];+Y,CI#BZ :㨢_OԔ$sD=-nj`RQphP8[;nD waMae7Rv“aqec]* ٰ CDlF:|ɇw,ރ%^?g=(uɳkBȸڇ m 4&US,.:\gG!ev;~6q?3YfTjnꔖ1chwq|}+Ilbkvt(V-tB ;R!!9j Eq&Y'r$ޮ @7Sz 5J8أ ^^⢶=)j_A\pd!!1q1le(pD3E(gAK ĐYvՒOHҖ t<"Tr6T@f E~Vs x}iks_]tej&$BX0"VQl"c*ʔ;EghU'$CK3FllæI$:&&27nPIӇ.P\q)ϋD9m-ovƭz@f$= 9<ۇtq,RxrH!✶f ;sΔ(#!&ɺ[y dr1/r>@$V6ZY˩s]iAm#;jrHș]?Gn.G]*a <3d4uva8)f1$2nv{wR| "'j %~?wӧ']F1TƔ=j¹\EA_aH]*~xy:;6i'=^KS4$y #W@v:"AH)~ᖨ4 ;jAD$mh|{k8mACY󣝄gkm&JXp83љ%v*d}X99nw6v%җ|]8띓](̗q:R5)J(Kad'< ٍҘwņ[ٙz&`ԜȊ5%ˇC}rsN` V46rԨȍHEym 9v\J5CJ*z^M$ QXHI5iry;"}1}i\07Q>SyBgT ȹ;X:#"XI b5%٩J1Ν D&mr6qTs ylލ(:$[D$R Th0j%0ܔUHRTP h"4{5Dqip jUjDq &46,8\K׀vmN8  4!(BBsqPuV.&)uRVs$.QKOI KHfQz; !޺n]ƄZw~6F!?XRq (wZD?GKa}ýb^d &n7h(JR/LX[$O-*~jr{p n#Ղ`uÝ=^5j^Q) qFr>l8b)0Ԓu4>nsiuVy߄׊X^.|f6!6BU?29q@$ꊓd襙^r/2Btx$ZIO?T7<2[c*|YY+'?*#DZ>ӷW'sH!q4x'$8rLåƬdM%]HJӪ;PZVcv>D4(qm9}݊줼sC<[.%T?}*0]b?7ij;N AZCIpwzX6iL&Bϭ$uu4@g&D S/F%yp7r8iœ)w,lYS\FpNRt]9[#U&|%#Lv٤)*"hhd &qo3uAcoRua2V@(6\ LdIGSk$f9&_iW(aNArɰȢuGc6認֓9nۦ ] il"_yE)VZ߭@*&LOe0`!r' <Зut]SU'_1qoFç8EOw5qS .W"=Iໝbޮo3% `* 5\][Afgt&pDgN90 T*k3J;4mӧE-7FWۤ0Q0L{uAz`1PdkFlW 򳳙h!Q>sn.y.H-Bǐb) R%aw:x16R2D[l؛I[IG r*㷗sUGK锺!!<V_t;"/4+ޝ%&? Yjɺp$_ tw^_b,(ϹEcES1_^i}4﮸ SZeYC\pvy-^6%C6Q ΒU~OfF KZElՈY%ŏc_?n3I#,aL;4$Ly>yLCܻb^yt.?X?^ܩF%P65jrf l$J"Ǭ*x6 5O6(5z4*qF%-4_,t@59z8~r:h8Ƥ+vCy|*M$ƿ?CKn%Dy1qة0n=f@Q2>"Ʉg%79URh*\$1jxm:P*I\N0Iaތ>1-ekG!}~$,jpR2G1 [4M] >.W)Ťtnu1{sff.|Fdlv[Ékwñ<`;÷72dZr LD^:Ǜͣ}vA؎އu#"@`(TDk#77m܊-7)"y3UQ-5/'CƚjV\'5>8쏼9!.8js49"94=$3%_63((6.UE3n2&%Od$v% /C_F"7цF>Խ dRcw4͸Mˣ@HMD1GчlmS[q F}ͨo٣DI4^".lep"MD6}]@jY2ZC 2!.rؐJV"~yoTG YN{WhC lUa$q Jɚ &9 cqd8⟳f+68!&u'һ޿ N'Lty%9f5"lr҇-c 8Ryũs<xtv:W/;q)2NKW1oA*ƲlI定g(e$kaw,JYFŎKuݿ ]z uD)6[TCdl!Aqwӎ`Olf|uƕjD3] bƙ+ҲGִl2*+]iﺓjv|acZ^2.ۃo+PqѓG]o|=`旒: # 뭆|jOXSuxy23faΣJ%>>Y=~T$wWޯb&u<'~}XɌP,\48H0CJpTUw & :n sMJܕVT>5/w-(IlQl•yd_z37>q%|D6"W<ڿ<s㘵B=Yg X=e[|ܐnxhwxQVd z[ګJnZ~&S>+{q;G!J=LАO5>(Wl?E&{s{cG}vHzDF(]Y)V8Mӗ%iy n_B "Ya&5e-ua5's n )s5k A:9`Sx"Ea*9A N21^5wU3oC(sx<{$<2{ȵԵƼ\4TǮ&e$J?"Zq o@H,嶦SbM\=]BL|u{g kRDt= ۭ.y(~COay9Dy޺NQ={I5d z&2Zt2A"EjR.ͥE\bcf6WLi"dg kfbBR̻;!{ѵQsݵ9GljOtHQYev)ѩ&mGc]oZ42Lt5<<{]]C,)YB@^65$8ݴWUJ=yV-?g>U7lCW0xLs}<ϝI-o㎵Wk ZRFazH hg` I>ڗen7={9D(l'ZØ[?R]lQ!QXk"kyNWO9,S9Q< T*\fp!.)Gy/|plQ8z5Yzc)i9&rOIHښU*,~+K(/D2WMԼ*6݄߉wU糋6\85Z8w"7_Fjoe5Wn2܍7tfNU !FN⋫Dl&eyT xZ..%G]_K"Шf^Q|lel(˂o{~NeCgg/0Ž1Rv]D><ds#/%(qSeQV63?Nn|$2TQ?늈8gr9bUi3jsr&'&Vaٺu#,MnZp9OfmσvƄ&j#f+#Myz+QLfUֶS21\8uX9NrgoH;rЕ d u8c-IcV= (kFHnӫ $Ć;$T%!Wi4JI\=Rznb|AϡZ{iO,Kƭӵ+2tD>Rvy6r&@mo:ȃPpk0q)X3cd]mV9?/c~&Ie>MkJ{ȃCɮb:8ZBB6ù&.ij $=q=FoO1Zgm7} )/d֡Nv}=<^ s-JS w=2RJ({V2 ]=#ڦd@?hwI. ۙ!B-kt:+Yх ˌ¨㋫.G00h$'",31Ss%nk|on&s>DH452 ak-,g:˙sx}bL$HYb"%H"Hvf5G@O?N[/=tׇGb)5,3> rZ`Iy4? (̓;x7S}[iyoM} xmKA2F+Jp&~ ߱\ZOS>G6!͋I1LUf,y%+g׋MhY+~LI gHl)=')TP썣fҝI6C`TC^PL%Rhef[ m'ՎRnzNz;;$>ќc,@{ && & ꁈJ((((i hb4&$h*B-2Af=17'䓰Bff0r%& yymѝ<(e"# $x7"f`j"(&*Z)>n&MgFR6_}Z54 ZZ}/޾WĘ=x-S%*7~rXQR+_\^s^wߗ}۸b '%q}9c~WnY~s ZSe)=;xKtu0羌^3 @ [h Y ?EqZ%2| /u>>2\|Q:cCx&_ d.aP)c_gR rᴤx=mwxbKHT'uE뿁;x}%8Wwj xҒc Jc}KK-P+_7gWb?xy]_H\c>0a2Z 6Ci7x}`D&sN?7'?Ci??!/J#@DA@xHLi"hbRT $LBBx?ՈgE(~<D8TctԼa{~C ,g<#6 jp:;vhˆ+B /jD #7[K1BJ+FFla!`|x1m%__؁  "b#ԟԆlSS >b.=_8@{}Y$9_FQ96*8_Ģ9o듼Ph&M|OyU}/lu9Z?/wUVs3!e&`SsEr?&yE6"M߁f\yjp  er@af2Pgh3ֵʥjHk) "<]CPq$D aFҔBT%!$OS!6%QU>]1%012(l$6͆[z[Ls y Lq'4&4`Fѵp|@a M0 Q<83!@'o?_0 yc$;$_9h$Lѣ?YT`鍦=7Ok?}!9g Hqs΢_LBbCHl 40jT>bN@Z-g$?JPYn涣у+nl?1Kj=N6_W*yQ(1YDݟ{7W8..KSV JEGc_ &$.}̡,͜:7,eJlz#,s>7Xdǔox{hi4vnՐ{?Zefц8Ly8;({"]Xni뛿F*ZܬDOHYqOZk%`8^nMQa֋#a1_@@/1b4I,9۝#%6a8"K.IRS#i & $@ [7|74n |>ߊ 0Mر JQ%m)K.vV)&:ndX aO~Sy0jrR /aIS DO%OVO3n#yq8" ҲCxsYD1=\MiZ шX^90ބ'^ohp?G|uoׯb񨊃{Xv?!dt ~>K32~8C=LdP@I 1O3hX~~0 00!tLXoly{: eW$ܙ(jҧ87u>df3GfKYzԨ}|zhd7 1Ǡ$H%1"HJH~ܭݟa=y*.?REz OUh2Q5\}7a V;&ZO 1XLW=X9#Pis4K'"`ZQ;PyC9&oC?tPieGœ+d8'2a& ;9T}/]XbGRW5 ž'qZ$&6N~žlmvF7j".?!QOZʶ!~maxt af ie1#dH>ʏh--%eD 'dS}50u #(QM~}Bf~9LegPSg\ߝ$LH[ :_m|5_(ߑ4ɽ>LuO_BbGڗn݃OtR!Ф1 @QAC(*C;Smz"}a#c}]L\téSqУǃ%򟍟2P*NP0uz~ҩaڿ¿y0 l&epp6T6` FH2G/_3.^h#jR}_'0Ha=OӇ?o {C$u-%>RDIHqٸc,đD5/:.z.yz*Z]b]2<\ Q}6r_T`iY7G^갪|N{1Ů,oXS ABϕKꁪwS Θ9& a$;&g=} ʺpviVI$1C8̛˲RC2ҞŤ \2$?xwM:]sygEUsqߏ]cH; e>Iӱ4{}@;f|P^Y,8uU7 Šje\jq˳-QdWt'鵜+|bu";:TjЁB!dHI,3p|2p>,2Ld ^@ߒ(<ǐJX36!.u(I|L[t! (qB!2X&z`38I5*w~DGiO#9}JZԘ3mEFKܙΘss!=N!HNOК&- [vm(DFy8%vg\FA1s4gC|zV4O9:.yO`)CԠ1ATS7~N֤ G2Sn"iU'6W̵-Lm +뛚3t?l8=yH)*`Ǽ]mQ&0Ҝ3ʴq~RjR,{(I6_)vAoLy/9kӜFagUkwLrzs VNE_l+) i/8[ܝY 3]qyoXއڹ_ :r_zsF+>^]p1|ჶg߃teCw;91o X 0' nY3=> RW{o)KyeS/ꋖ|k$wG.ȚVOKIe#_/ k4$xI݅Me"MEf:.4)l{ez_;]Z[}rIL'?S8ll/>$d}'37ަ0RRܧo.eꯛt:|W~ gK@Zylm.(%#W4}fR'Ҕ^Gr7zeW+]XN9DCûJ/9~\n?g4S/n9[zU6l}>ij32w3]oٽ%VIv#_* 5ޣH-7vmK Gs$iiˣRy:ֶtR%|)귤jX$RyIy GP4`cn =p1=N1@D0@L01>я$PU (a|I;a(C'/L󊠈iW81}xyF `6u3?k)z EcyDb@?O4`O RR!*Vv~mI>n*f/lo5B?部Lf`nْ&cv#"8ʁ҃QC癘+ͮV1zd|ƊC~1h;7$]}?uO($[?k~꿽(~VTZxg?R9I2B JQ,-1$HoCk?gYG}8/Y"y ~:~ғN=ۛ 엝CI>O99{f){ՙub6 `3(=sxnٝI1(j ]rs=/9 (ʚKb1  $ J3EZѽK識b d3 :iO4?~Ln"ɀduOTUR'@t$@ъ# &" I6~ns^7Yݩ!W[jllG1mWȇ>D% -ڶݸ.=!0jcuG7S9)$r KFq lGa)uѲ꯫]l&-8P[zsHsιyo8 G)օf#:K*jҍp 87ݧs~xv=%IO30Nn¸ +')v3g=Rf]] 03\MAAzmMZSv7:2$:Dlأ!JA7JF;4F$V"`r ?M;8ar=;a30SͩfHgTtfAn` 3`0DD,,LBTЗ0f*]- A䉉RZY$;j,gB!  @ȮSDG)0,ngq.Ae| 2ll#%&߼kv0fvc&v$yMo稁@++yLP@=O0m ٮKS}3Tg^~OCz92Nh}/ص\\v܆2jsuN6*@] h?TLX lg+Lѓ:Q8{["Mś&J+&OC%U! MEhTuA:Sk#^>^th޺?)/SUB gmvrCgIׇxWZ~ćh3~PER PDoS4%v&M*lQ2qdULA=NF&uR$o$ZA8Nd[);smٯm1=cf.h7Kn5A`Gs.gD"0u $,߉9q)ģvU{ ZS˒~N 2$#b(i!y2P2+W!ENRbJ\BP^jwŭǞ4+rKm~7;'i`:Adsr!X~ wI᪻Ab'3PRTA,80^xZuWKfY$]f@IPs9[B<6qG wG"N<@8Be^E3Ȝl46+#]Nq煽`KHu.ez)pD' 8՞Ba&n]30զ1Ƥ-V6 L(Οq7>vR^J.SJ`5p2sMqL mbz\;iZǏi $q~s?ʶ4(.Z *N-ǟ!,@?6<0uvN=pۃq ڌ>?Eޚ_M\Ϋ_yqG.W;W)%$M=XrXrMn}gK)P ;.JmIfJz)뮑M386JDIڛ˩N돱_N w޻կŴ Ns$Z•aec9㨁6hD;ԇ&nD;&s!XJĚN*2f-m8:FTbf;5i9Eő'Ǟ |&g+.$􈸌y)99';m wr+ǟAO`=A9Q6zp{8U( *%"&V j()">eP "{#UPӯcNAU?'Ӗԇځ桥|xJ !CO@ 4I?xrb/\AF/(h휆@Y O E%!E5TGƉh{!OA:CH ={9!>{'PM 'H'OM{)ҝ@Ҥ`z9&/ !B<@,m+;99 6ʕP 4I&y" &=>pЌJe9)σ!yWaKUy&W̄KEВB8&pdQIf=(QH6M 8%в&ݳJ1""(<x=89HT8U4!׽4;xFEr 7 #P@@q˨U9以O@>lj*=p8RZC'GSdn:3p:Bv| [?SAaB>+<$JE0;thde\z`p lMBI $CC4Q@GZޜ>?jhU[dsP*I*M!4@w5BHw{`lHgM=,b1C'`ĆR H!((؏ Gv U@:ʃR&$4=`_x2+L0&(@h4{@n..O}3FaѠsąif*G]vzw3W *:=x*Vv۸ba))1#r逜|] or ƍ@s/gY 6%(?U KMN<⿮F5ަ(W^ZK%;(:~Uog.x'XvI6x V4[TA"K~B2Gr1F!kp_#ry~WEh>RPZ$/&ΙZ\.VzIPFxyk̪f|._ilꨞT~,S-q'Rk~;fc\JHyηeoIR-*đJJ7E^{`Zzjߞ̮RO\CcqrOSulⱰΔ;w14τ-R59tRE<d. OCӫPqh90}DaxG*u#DĜ#|A1vjFV!`0p;?u)ҿ;bp3yS*(VLOd_rc<Tl5KV"ך0oC;.@JoNv)}PP=]]bun0{AJq?r9Nz+".@B5,$.#'`~طJn+#?朥w/:iLQ[B7S=Ya,ѱn팴2I8X8* q2Bhlћ>&upOU2@hY8ʹY5U#i?;ZH(# !8It$cӎ;Y)RYC3# ,QIe b)|yEJ.7msᢔIHbjftͬt?w__?oN"p*%kkN7n#3M‡ѱ2Q7fD0. 4.HD}s[_!J?O naZOkzl% x[]:Yn}#4 =9_[0Lx~n{d1oGLvp4o}$MGNflL8-Մȵ) P 2ꀨH]ɆhcdE {??zwt{z#&WKٶr̜yk|Xť zf~7Հ$s.2`={XXAEAz|0b#NP=ײ˒1}pn `CGFtQ06:Z w6`,2CxHf觗hmE?ײP?M?.~ 6t!AID"NŅ ҉D8/;\YƑ@q$#=C_W>iGt1cSpV;tO ԈJ~`H焐7R;E/{}7|'P*UTI!储FLl;%h~P=q~%9nQRwnBdV]wtb$s0 1<&Kn2Y1y$i[-tcn/}pk EW&{pfCrwIj_HsOoUTrD7'Ȑ=_mmE S_=!9sP yA!G8w.&νi}Bm%qVVu3ԝr؟ջQ2M"4ׯ<bLHqL+~ ꝾWu Qr0n!aY6$ Yf^aڳwz.Y!.h]L9اg#OYC*#^D1=[񣏥HihMϵxMAqLF&ZHڻ=v!N.u-Ol嶐߫Zz]S^;$?z.ۤɢϬow >S6ӓJ駧I7Wg*졄Oϩ5q&6dYT8I:V}Q'6'=bD~{"1q{X!2˅HV 0ݝ>7{}:ռb)({YFH:Bjzk8 DnZ٬(LhI2#^w5p@Õݹ+0:ffvqV~^* \K}~FhBHoHpKtdSwI>WHW쓈Z==*Xʤ/RII$!"KiEg<Lpe-T2L`O)LY7-k]|~LeHP߯ӓ Gl 0fdm|9_q@㔽-;"q)W'.>c2 ׸m(f;]+ ;Xd>Jlr^=fNWO׮}ԵҜ)Z^eq5?n] Xtj= ?]S^x~a&(nګky}'SCXG]kΣ[%DZߍ$qjtUM3t'XDś_ aI؋o5 lb[HEDby;(kqB%G'!>^F}#-'Gx;گjkΝ +1춱^Q<0urQΰ:% VAöS[⎟>:rC^~Y:C~&/Q`9f9<ҐnUyѬ^~<#>>>TJsOg&ySZ>ئ9(IJH0o96ɖD߇\(B]:8\hL͝Vyv+-{\ot*lr5zŎH<>4vYLv)nZr%]cdp y sVcnYٗ:6m?'J:l̓ Y#_^yn.lSg]˿]3fW-Bi\':;l֬9l-tiKz3nǃ%'.p+ɵPt;vc^3̷M t ^=;G7]m<|7VzXqϫo T`TG.uKLcbG7q2cZc70 R  f$8 V@k!!"#ڈ( G! @PoxDAXWa2C $O͗Z=5leي)|mdѽ!<ݯG|Lo:vE_~_W u! ^${:$׿س}*?Io})oS PB1 C>,$ R'ABbRd䕣@n{_`Y[[>,v.:~E >>yǪy 0d!tB`?ɢ?:LƼ YS_,d;&6c!"(=?d'8 bjz  \C[M;J_c9C >2pBOMspK܇ Ck@DU)HTS0ԐRQs|aPa}PF'= AUQ1J|@-Z#dqC|i|@D4 C? Nq,:5V V49*(8<<22{)HtBvԁs' >fq=:_o⪩}g@4J_o(4 y쮕(z&F} ӯl4 #ATh;Xbv)~OO !@Jl3vDȉ"|:? ;d@ryN+LQ)D7ndЄ) HAL4A߲ 'y<(yӬb>0y)7_8B4P0M6@@{RYffTX$!}~U}>PP҅S$ |4% qgJ9 )IW$*?H|C]6*#ʡB<yG(^o '԰ް0CC~ b"?)_m?'""zyw04TűI"wh_C߮D;t?櫠*HzTLä'HjA^CA MQ{: # } (y4'dQUC1uPԤQ=? G#T(X")l3*J!EC$)ܫx SGV\"AݟxMÀ|b9H@|rۚ*]бd2^ GA߅UpDŽ볅Ua9c3 R,D#JJ "K ’ʂЇVB4 HH5T%!AHF3h@~E:C!@%lg^psN3!(!{6DT: P pl6P)Ii<R`j cX&`>#ia^VƆ CzTii{!"% Hq3!d2QUDM=CO? !&BP!C|Cl; @ QJHBM5Mx(XqL"4`!ɾ%C Yؐl8cW߀6A٣g( H] :?.4]vtL@Qavŭx |]^xyf%*ffꧡ'XÊMh̹<`v= ap *e+5,.DM c@H*TrmƧ!ȝØt)Ȋ@ߎ sDIE1Ty)#6*(i1 (`b"]Hy;;$< 8b&@# S1‡vC|>'n1Nx W<&&7!R ~4:DX$r&:U=)@޲2}?Hv9'Ӊb*0Q㈸ ƄS1$y )WaFL?ǸOE~pܡGЂ{C=ݱCj Ji* OR*fWa"h},D0@b4 la|!P tE`DCE1)ːwhQ%rJ&AxGT$<\O$ I =Q#NsshD,~1Z+n%;nCUvCiR2S_4}tH8Ml|MDL#Ag󉠸AᨌTT= (&)|rlm&~ "(%ֱ"""j /ʊ{"(z%s.pF CPXʘ AAE%' K}?&kZ+g85m5Z5Z5Z5Z%q!h֍h֍h֍lkZѭѭѭg9Zŋb*[kFkFkFJZ5Z5Z5kFkFkZֵ/ٱoc!@eO )'QHw?,CyKk*Sms>j5_CsZ֥k+ZֵQnkR5[X:CC#VsZֵkZֵkZֵkZֵkZֵԯ8.p te`)b8ƪ"*`K Ŵ0$ZKqW'^ltgny86Zѭp9CdMTM`=Ɏ@?4٧ɹp뒵k;f% Kvڎ\Pݶp뒵-3Zѭuv%aJtBS_ɵ@91:u#. a,@РA>/ +^>I=AHY-Rʀ"~tgsI! ô!;aM "H.bl7b0{"Cp)QGxo){`)`fa,x~Gkb=&B?j;6CCd _$L C^v{}9*<h.v\;}ػ EpݘUVؙ>Wmԑ"$:]R҃ P QR#+$Ҡҡ8p~I://u9b19>j!(|hh(kd7j`?ېtCoƦ  JCd@eE wQRU$ED]+H RO_^WȇcLOd?[ajTNFk85UTETKVЅ-߫pUUm$)F3VWUDUDЇlM?(k9`V!D5a }C@jn[ A)+:N(yIHO-uK|G:36 {cԢiD`v :h%^eHH$y'C ah{^ Z-rAL f5S%M)p1<4cȯe3}"[UWp`ͅ<;!@I4gB['}*E!$] lS$@^(t  uuP9 NÁQXWU8P4;Ft85> SH& ';wwYCcD14!IT:^W;Ǽъ@e3Br>}x( X#Jn¬ 6vd4 +C Գ-4'dvJ"gwP>P =2PJ>vx vF m@pS>|A˞W~G7H _TP?zb?~1G@: `G`yxC6G &c}]FA{dMN+I:tx(y]SC5TDAɮ<0E2RA(\ 5[J ,ߗCo7ݜ<)! !Q@;x݄(0A'fy& ϓ2K!("()Z:XQ2$H(RjpSAJaLA;^ޕüA9yn8T&X**dfb37x3/B9|Ԛ8+:Ogz~h;*`Va\bx r! &<}@mSB$X3 @f8e\Ct;)SB=( h$g@BIT?ǻ R(}t {"\̃@2q rL %< U^olL#tHbJ-j$#aRВgGtD4EUǧmy9rt/*|ɲd!(%+fGhW˰0CrQcF&e ĨQN qjoŏ@&ޔT8u@6P(n=aCvJB|dm#v@mw3LbS{=TNr=C4/*@^CGЀO3B@ v9>Ib4%/xp0Lq0b8)- ΊM:TZ`CF'@KLXmkBSVB_ Q?OӨ@{L7ït(ljhCH#j4r91܀`U"k@$% Sb TGA + fg5b1JhHEG kq7 #XL L!.M_vUlj##$5)R8 7cdШI`JLI*&[1=DD:eu$~d҄ O@8 _!7  Q@g6 $ra& @׏9`GKs]Q7 `}&G~(`nc"Rdc*(bw6<|p|_XLzj4TW@U_>h"$*$(zC6<"YQUQ +u:BסLr'̎`=o!ds/c`!B\u\p}qhTx94 UOE6 (ʍ ULX@_9TDD!*~9(h $~4@^e3\`8 D dFI92iwh#c#԰/~i cNiŅo)kn Uma8wÉKLFH8"DAj3U-TU 8334>;yY ׏GK?& {~c⏻Œee|V{D:|b|링JLߏめ?'>?Kx`s|}/|g%v<د֩9!pNKKFGOs|g~<>'#ۯϟ}} }_U=E-~[{iIߡۇ^Zx=};sGNVXp<-D/B=óש}>j>rzWo7hHE!L]$q@#d|C#C1Ž/ːZOv'uo#fDN_Hٽ~G!S]yH/O}$_tnøiG;[j|0|mf`Zݚ H|߬o˿׏*(;:4>.՜vO{\{Oqus.vyd~0a׏̨g:ClGs4PB 4k|y9oD?0JD!|{7HvZ<$3v`_:}JG,H?y3"BbWV/X:HPzg_8=?$s{GLn?11;qc ̄$Jw bL$N43 90ͻ!kWZTibT,OM ^gZ ?& >0ڭV@@W&+A8I$U#e:\Q>=>\\yF-gbI;y8#n=E鄏pIKWj*0 AA54'f>R)ڑCIҍڔF?1rʆ92*tE:i1%GY@"Z~'3=A4{&-l Ò~8"?fCd:uC`Tv>'22l&tကf;j{#.KʟQc0LJL0ϚJ$IB9f7RAv:;pb}:0w^ =(f$<9sSV{à{ACU|w,s H49DTTyz|v؏\fQx!$ dl:ai_O =ҪᅤU&Cۼ@o!f{?m CQ @gpA xU>fe>C=@:~#Qp}7"h8 ^[N ~R %2C pwXZy>: PM8Zh(!G"l|7O &NGy8"$bcOB><: Cz") IlQw6usflJZv3~cV 8L\ g8a8)<|D3&y2Hf`ɷА!A"~PDi1;=,TGI"=YUT R_ '&1ffic.L9n֍5Vy3ĵc 2ИhC0w6r4v(S %Eރװ'A""+A!0*NuЧ"b2tlHBR 3;8(&"I\VQP '',  f^U=%|;6p~ q1s&ɔnj8C۫-큆ES^8#\Guġf/,~Ivn|_ ΢. 8lDS-˱Mnmy# kC5aLIC0t7QY$ HFA =Mhn2γ{֊(Z[f5&TW/ rYkLۢ=Q`蹗#S2)$ls2e22Lޠ W9i`k ~L**)G  Wo<`Hk;Ad=ŀБF2V|P@l2ͳa D=E`U~@kK$oU2 I(ŚodQPq.BH\ `% hRa56,r/`L!̌o~ݵ[[Z+l/_E Hr?` T"$hnfy5-HG0#un:a)NUИGChA*;09k.CC7sܹ`ar32S 9ESR1JZ.eʛ(>:Ob[juFZy9^+dg)BĄE%$HUO?ݮػFᾠ$f FZ rxS='_q CKZBr}2ȆXY9GY6Ą.a bTVaù.ʗNM즍2@M ZU'7qYŠ4Co*+OfICł_-YeO=gaRA|@ !jC6'(R(Z8n-D4RLc qh.ԶѸn1aT(`ph49ol  >\J.a  Ѕ9PEUUUUUUU{M&oDdӅB/pȇlux˅E5=~:>7:&"hd10pĺR8lUmhIc4p\F8NrPv Ș&+p)U"oI4I 27bJ‰@Vb!'Uq*-H;WL*40d` Ѧy2(N ' nS [=TTUEEUEE5QQQMEPEEPTTUEE5 F[m֨17a@n>oNfQF*(<o}yaNN8#)OyyH"nJR*"*ZmMTDUD0C[jkc~cQ FQ5-k$K3B*d:Êi.=Sf C%7)Ecl;!eT#ꋁ Or <z‰?>$ }Bz]rM8NrnἘa uW\5A˓Ĝ í]iqFqbl" Tvrf96k "B$䑒hz^?r,L ù=d`M)HѯAꪢڧI|4{D^DH^.(3TZDۇW^8 4AJF>{(QHf)Qj-n+2N8( f;n/wxY/p`_Mg2rtVfr'< =14 ck;f4W5]ƣ'|H㻎鱺lwOq%ň0}ףC~_~<&>/_&ɝݸR9@ӑn- a)&)B`x 5gՀ;w OW|%`jPQ)]l7Ң>yl[|B'd1YfEFCq0Bta6ѥj3 u'=NLLH&]E!T! !]x@1 s$tBDRɇGH[ čjftE3Inzu!!4ow[Ȋi6{"#AA,$rKC@\mLQDM01Fr9#1#U'ªNDU'RrB$$)9D@IQxIB TW!X8HË<<;p#ןSB<*])J" I56B\0r8ĕ,[ I UT1A! X cN@h "qVCuo06F92`B"dF E3POdL h@!ZEda)vzDLA҃ӔŖyW;>hP&hM&Gȡ5IMHMS0FZ{UDk>sQf&lo3Z,D:>tw8׬G"DRrCx=X;wN$y]˨ @̈¸U3% C@P%@48zD^qs2{yBXUmw1˯6R140 CPb"PUI!v8`&Ş)IH/h z/yݰ&dfc ˏ~cb $LM|`LkO``8WZwA\s Gt$h8\A(G( Bٿm̶sA?0 S2&j˫Bs ܓ NC'3G i#; }=qC9%  `0.!( =TM衍k 0S!PN}U᠓:1a6{=^L=y1.\\50ɡSJ)R{‹^SSi3 ߅s\kq֗Μꪨf<}_@ P!@kX%!'$QI65kcE EC1oL9==/T{vjt=]棐84[ I$UڜȫAPCL#e o^mdVMR8n66L1 ;TRf2<mȣc10Өa8N}`:7ѼMiactѦ QaG!o{S4kH&zTN=4E{;A: G>)8t:4wh'ibpC4Q΀ڌGq BDzt}0Z7: UAԢ~K+/z҉ -G~ðmXC^> \|! jvԵ|[)gwA611-D$Dv%׷ E Q M.3%6Cd@Cwv38&.pS5eS؅ &%2d*q! ׻qх$YنM65^}Xߖ!op":*Ba7_ShpLt{a/=>% $Dr3z0JQTcX"Ɍ;XrC[UL֊IoLj=f'l7 ʊ:=3ǟLoς P ;'HG8 @*ד@-("e" *) >n*Ha$N P:`nU;ɅLPRDDYGih=RQ%q8G>̩?OC[g XCSs_ Kv:aB|ID(I pCQEfcy}҅Ur"HmOpUU!T$T) UU1l]d!jb*t(Ā$99s2v] pwC|<'~2oD@uܚPu`C6l؎`l\vm#;A8:lY UU`UUhX UZеUVCeTD` UZеUV:bw*ZBZеUV!UUh3*9j z4oKƗ m! JZE$=gO w: "π1(RHąU5U2@p6U+pdE"OB`"P?i=Pa)Cv+ q/ 0KQHC15LH!HJ+.#T\,"(HjU@(~ȁnBC~P$d~;|:G]HfaȐ05"Q̸݇܈eÓN N`\ CN9zCI'p&:  )C=ӈwP=W nm?DL(LQFA_ԨSJY M Ă**0J N"Nl4T(}EFaFJB  h(@" JD* UzO%P(IA@ԩ /PX+ bC!u{<pxj K{st%|pyCRfstW$b -"дEHA ;F臜8Kd? JF@S' L& 6id>JfX~tGM':9؇UwUNi |XH\z^aPȦ7ޫ56b?SN h"P(cHd$)iha=OiB(P0O)Th …pѱT h$#K/3ן7u Jhy')>2 b HR` 4PːP!؍! 8ABD ]R/6:HBl}`(XJCCKQI&$bE*'Ŕ  "1#B_u0ƒ<}ФJtϨ[f +{A$g@P]0ԔK+0G>$Vhoy(:.B[>kaEG9K8Q,d(h/Ś p.ș FAo 1; 71 AG1@zw$'tS@&1ixao0 aլToꏾd^%'Mlp9D[O|8ic Ѩݾ'Ew>t9U<5-O W[H>I8$&&l 7^\ܔ8ok= o [# > OZCbx16*t7>A Fohy*'ҺRr^T&LWŸV*&?1u?Dhq^&iY:4O긊c€@ǿ K% {AL! @ 0@hN$GB!C !Mv I>(|ր6""VZMz20M/u"v܇Ld; OZ?|3c_]@t)R; q0)C> p^t/יY(ǫz6 8`ebɒ+ڀ5ϭ@'cz5 {!]2J.w; B|`(>_~I 4KBR) ļ_Dƨ~ GWg~oƒeP{הvOh !HЦ f ?dN(9p N~ RHLᇯ0 Cp{ %7IS_'*j-U莢J 8&MC)h?^cmUĴ\PUQh֍kcB([8yO)O징W $&CO^;*w!]^_6)Cd8A*vO0 2(ͱIԏ#ۋ4),Dt3]h `uR%3JA%PS J_2"%_R4L$,Q4QBԲ K J!C@K·*23ҟ *1% ,#K$R%K3…,JDLSD,4HL _$$ Nۓ&p)<Ҡ;zbDZOטF,\p,˽ރɇތk4fɳ&W3"h.2d4#ahR Ќ1iIP ( .ZAg6Be-]E cgHW0`\Ê *޾yQ!o#X'.٦$-sFx<:f.a# &D~'-2x ܲ(chn. #ǙH@B#@̱M%T[Nv`9-A$UFS$ghxkY3=94V(!(J2u(d=ҾנLT% ^8P=: oI$lQ? B10ǯ~t~H;vwTNO #t&BsdRX3퍴H=ҨbLN-"dI*$Cc)$F0s1"~Rw]Ę8gQ2Lk;#02_8{} ~8S㇘Iv??p6>zA _>'.zp(UNPuykT foʘH$ LcGx|M;6Ї.d A4-ʤG C%2P_;wdQJ?P74G}Vqv* @g4*z$< ^iM˦^(^/Ϟ5h:S1=#ZV`sUpF{;LĊ@8H0(w_FLAѐZ~A 1ˁyzpUj8ծ~tnpC9<M+&  H 8G`6ظs% 3&ʇo`\G7-%DE4U S{;C7sq%w /~HI,ݰ'd<@!ABa$8zB6NcV!MMLhzПphSubr CF(PyNbPhq vܝOC'6_x80"ֹvjJ[I$-")͝=&E]Gۼi̤CMεG8a BIX~#GpC$ Ca:䤉hDLR#^#R?\Cu>u23NU35C -2{e֘%,б <]QnH`4g !Ԓl?6PvSFڟj MH|׺@"!h(Abh@eNDr_TPS_QaD$hoIu(@ HJ?Й&ߥ'p ")Jr-*б(ĔCT1XSI*d4A0m5b 6(*Qp`a.J_K*ERp ?&C$3q.&/o { N}Rvٞ aiB!>$ IY$DTz_ ؼi88lDV1 OTR7F{U7{L'V#8zL I"x`vJ=2{bщ"Spc;<D'DDE<WCĨ|fFaYȇq"gљ@n곲@I$2 z>-`DC4%oq' :?wl磌ANЂ}(:a$J1 MϏq |st`Fv8qeK0|@83&kΦlX(pZc~w=1S=O1 "XK  4/y:Bۓ-7χԿ2Q5BQ 7[y 1KqFP%&PcH:62h{beGHrgiX8cQč&"]Q(dzo!$!w*b2ᒣ0k2j":6 +!@KU憐>7o %Y@k__:aIhztQHDC #Y2m?qN~2sCo/Q')COA N@0CE`>!GѢIjqY|!<gv/#4N# CGr8"`?1ǏČKJHi4$]dFTWu(DULA;ַͬyՐ ='#)FaF"1D@P\epTNV9qc$0:/yFƉrBeH&vItFm`3  G$|s$`膀(7$ q8!91a%Z?V~U*8@s*p6c]hA? T=`y`鷣Xq3;ғByznhC_m b?˕~ɮ驯"ḋ80wvȑ#?ne8R4E6ƀ4z;W \x(M+.3%yH(%[+:ĠEA-o"IB|932AضR֔T9y]HCLm ,뀴pЭA+Cqtgԗ(񄉤{JP:ޝ |Bfƶj\\Kxfolv *v'+dv!"s*+.۟8ͼU (PNun'@ X YB채)5QGTjhbɠĉqbi- {M@h+& cHV1'=0J}嶌†J P$BiNw @Mt: fmɇK4 &O xf`$%odSs>` F'xLOr`VЎ||י;k:4He@C: N1|SJIAAⶓ9$N$TJAblD14"a|:Ǜ20+ILBByϑBc[QP8O%b|ȇD(: H I4FɴL(2"d(fcǠ4@pB. 8Ma=߆AB< 6(H*D蝃{iv1pe6\bIpc8=u<Ӓ1 a-S>&' /qjbo/+$uHbD]8hDify9ax7/FˠzP4*BR!@۱0Dr - 1 @Px7h8eLČ%9 F^"db=<$ `vNZpH?auqi zC2ڀ iΡEٚ>'<{鎂DDDDD964Ҕ '<l!0hm)PxIUXHY@|ƓKOh(@ R%b^ ЄK_*N6çC/? $MDQ{xi9,`+%qJEL?-ŔR(U)RP蘡 h0v L%>{Mp5"a* `LB@ 좞pȼ<eC`<yUPagAHu$L0B3٬#U1 BGl#y qf`(HPq8x&^Xr8^ *HSq@Otse() ! HMR5'X)") 90\(h))JH"(t/uDA`xlCL̀bQqsx(PϿ9QEE1 GFYA}8( ldf19fl 20L&K茇ͣ2SD&ǨO6Ȃk>CGpI=!4P*vJ(A""D@bD#$ )|2Q=AFB!OA=GkX{#q Y;8VHZe t6 {2idANl.T¢*KʲpDb&)B*JP@!ӇW(Tj^)88tMC{!"ZD7,#<f`a0O0JT'UK U\B  ;@$*5^ S  p7!*@HwTXV:K!Hcj(> HдQGf36퉠(6N8ЁDQERDJPP+ uzǔޜ J"@INbK5!h If/&rUbtH e͸M~pv?=` \o>8iHO2R}tn_Qf8L=&%-ū55~ܼ#3]{|5g_4~Ͼ2zGY10Y ǃrz2UN7qcC_.B` Sw60v/QzH @Q܍A.oZwQ >v/  gm% wRsN?_Q2~ H5@&с6k{>!1Q"ȧEc'X4,gGkPq{g=4 JP DuÒHF:9wh3]l3="FG |_EsܖK\@YPjffZ*;xQ+|+J8iМ*%GtyE[DD ^i#X5C 5vZv4G$*Rqjh$F88#njԜΪ8f V%;Dr(%)}PDvM baը."KE=<^(IYj1"\o 6pdW5b}s%0p|a&9,E|xYSP-R=~7m@J| Te&sn=D2J[F}aq$EzylonƍDz)ܷ`fgA x}!N9\(nT"0' Dq͋tIezE0CDG(yLˣN,|_I{pH幎7'b*ZĜt68lJ $vmɣ_6 "P,4B"Su`Hj<=ߎ$HIOW['jq8%>w~DW~r;A!̡M'jBJ!IZx @͐XF``[i}F F0M=?S[gQ } G`m[נ }7jZ -I=Rs\!ΙݬS3 6d1y N/!C#)BǖBqdE#mѠ8Y** p=7BIC o=ߜp|c #P=kϹ5ajn9Qa\V'ܘieckV^7v&{Y힦8@q3 1RHC9HPR>o;QƼnfT{5}{X-oSlYiaaK.6$l<}qo['p3=L:745FAÏ;5*=hC#7V +e8sUu/CILfPC6 83l"uXбRPUL\ݍ)71an^CtR&! 㵪c63)hXC!ύ'}af9u"ISɟ)<8LeZ>4P#&S% .#ձB}u )oJ{;gԔN%2-@ |ƫ3#a'j;hT^!͸B7YLx]fDxÉ0C^0Tp:G%dt>`*}w*9ˍ"{+cE;WƸuۮ$0y3Bnq+LG8Xpr!${/kR*%TD1- Mc\qD1q,2"38YM;O& '$XH+%QRyԉ܃qM&F{aʑg:;R|[]L(OAN~(4VD@yGt9<|?; !mAƬI(Ld$'> NLXc&u*1LEAٷg{vwR6_n.Nw=I9C]: ׻Nd|[}M.V/ʮWNr, (1 Ij4Xvu_v2'uZu-:OxooD@`0!;ZWZ. b+^. \Eqfq'% j mt#์E4t,)RKJ&oM"\pӂ; wQZ  tKSL\K;Sە$|Q7Ѫ5 AZT $<1 -ˎ ԇ3Z Oi#~s>)꘬DxdJ$L և>~Jy9p`":c< Z^fP[˸!$ ieC̕*.!)BÅ X$]qŊGCB0*f~f iQҲK`wnvI\--SwE%yrtu]( m[*똕1͓}V[׎8q<w}DIw}wyw~<مĪ<(sk9CTZ);|ykiS$B#mB ^ IUƒ1A1|^Z:fd1ƄJH^9!@<˶Opq:\̋ jފ硞+:;>NoG^j! ;SZje( 3.ETPBD }otm\q-"%GVɔutLx\LL%z6ŃHQH0(|Ӆи/a!ȇ0ǼoQ9Qy1Jlw[^ h8`t:E{{Gzro4Hh09FhdWdN+ڛ҄9y <mHvS4LD$ I  ${ ӦPAЏI1;'B`!2̐ "% :A = ;$p1@e=Q>`cC/0͆&V @Qq%!?0d#J CJD$ULJ%1?Jy 8!&:avN=wO]PApʈY=yC223y-!>@BHhzzȡ~{=ބP b/TGgEt&jTd)gp%tc=E+԰AL5G $y CcK?Tă[aLxp CMX&X%ӘB0pg^ǹ&N$8f-^8 ehFCA'ҧ}h\:6BWS7C6vJͤxYcK9q9κ$aܕA`y>)ZWϭk\zg]#gC'|G( 49.k̪Qo |d h~ Gts1OM#tQ> _:c+=i'0 &{C0ŧFpƆj1=sbcɷ ,i֙&ɕѪՓ yޙAuJZ"d"\b;b kIRNa9 ٲ7`$5#|hv=kG\t%5}Ph>+ *z<&pd;%L AU/ /ꤷ bIx2V 2hط d}NИ1!]/Eqp gw h ~,@v̎jqn: NR3/vT3_#atlFTr7ٚ)ef o|sΈKd"g_yQ׹L.}H^L<2YZ'WhLzTu3ZGGdp]Mt8 ︔ .DE143p[<)LԂh`5&Ԛ֊%a]ėeW[g^n ROCݖ1@a 31@@b5H2RP Q_쀤&JدDM ITRHB CB?1"|{yjoИ6Z@8Ds5nUN%:yu^x` ^sɖrLc*0#Z@y;ר_VaRρq}3ΥN"i#Gso1MK.d.tU*q._h! 5 $}`|'i"u! V$2{{IL'#l|Ⱦ -!O.X_IO!v`?O8d]p\qQEp^= W?20Sw1ֈ? WWuPT?'q(3.\H*8ۙ'{\ӼAPEhIlA6Y<^p9؏Z:T(i_T.d$IZݩ6 .q@C"nT>$5Fi">OXdTTk P@EO B8$!Bs-$͐\7?ojN4^VB@MS5g~;QSW-ﯧoS"J6,-p#dDGf0"psq Wc8A ز1 A>}d JaSKyЧk|E!$&tC #GZ4#U NrIZX-T0\i'e6&ޕ6ț!Eyd "(h[r4ABNt4dԉe\@A,'NSlHdb69DG<MZ͢ )A/Po~?IM8$@B`B& MMG79M9QTw$[^»B he {'j;B[,n|^ ~:#G 8fmkOK@> ~d;d00L8~X]/&&iuUUUT|<)(gRƅRa:ꎥò ꦢ?P#H_(jvRAj{$}&wGf=E&*y$b@ WQ~lX *iVD!ޗdPqg$`;{iDi=eI1A";a{ yw]+2I.u[LGl@Dg}/1ItQ=061BZ"9AE9y[AS8v 2E =.ANxN0ID)3I0Ɔ2et^M%^&cÑE/ef&E#=@i;Q`"3!t!Gw/@B  fR i`.H( &j '1-SJ@CDBzq+Pкd̓`/#2@u舏R/ߠ?uߩ9ל ؃GiP?zC` =3O4 H =y!a(p8iu".!|n'![.uqQqS=y/$NaDEtqL*")JQPDJ)!_{\TҒ dPS]`=zXar|o<3^Oƨɛƣޢrm+WH–RvѢ3_y \x[BaB_,Ц ~>;dK`%-aE_-"( +b=/:*;@lQZ`a) 1I#pҎC^cܽ@%JQ{gS$P@#06x݅"LHb.w﯂ O<mG@%=G(D1ڃ2|Rf>dڡI"')@`z= -oL2fA4*A~cakzRDD]z9D )h" bP(1%0@;⼵PDDTD2u QAy9`YC8#I2 `D[ya (*:)C3PSCRwۘa9wzsx3v t65p.Q#|*JҒP;J+f݂NAӋ"0RÇ`Ԭ;G0(v_#F]q9+ Rc[Z gLaidɫJ,c*M.'>qē @'v` PAU7 b"$*$d! $% I" $ %e H )&JE "@4&ϐQFȎ+ ɰDIME3,}CxTTKzû#}iԔTJ?R\HBFD&)dplAOhF1 }6 ƙC5?eϘ5P~B{-P[* 'P6JW Q17ἉA!*dV \\CABR3$IAgh46aP"  "DQ)25, ;tpN$(j$2L-; àAc 4I와l2ȱyH&1 $е64VIY51H~Pv0W,O]] CڒR)i4" .' ,ES(,dFV+-)r ӳ1 M1[6? I*K*#HQ0! R% $ SEJ*Dc ),@OS^~X8zߝђ׉8&#X.*FO m5:O=޴PhtDbP'`TBcia8my?ށM󳦽6CYpg o !:g#4BR40\M7P`Q=y(x'uxdQ=ׅa9p&?ʕ~aO& $XpQ8 4a7>a:_U?K&_ @'y0!^Se=9EA#B+~h BbR0JiV!'p^"S$G"9D}cik$4hOA$̲eLB G\§`LxQ]1A8 ILA!?:η+FFp*tMnty!@& **)$=ҘCX -F]>T9 v(Dh LŢ4SH$zCXL:#KaDc@la"]mgˣp:'HOq&#u sװZ" ?ZZKSLAN:Ai*)8OGbxM1EDL:H|@~:Ym1:qÌxwtf {}D:0aѵ~kRz텀%KOrP=xR~LɺX1?£C֤ Њ7pwkfP̀B*(D*e/:WR@J] 4"H.B!#'mCz>5~hN/$I9I .eZa㹝t?!$xb!QQ8_%b; OdA':@϶((D"/Ywqm?RWPCbʻX 8ʑPC0D&"FA xC$(%PZ#I@2TSP'ЇIB^Ƈ*&$1Q:u¡)&cV8S3o,qP >"/z06}'А5$@ẂN78}}խ/+!?w`Y"hR EC~# < dE$ytNy. ͢ހ A>~"~RtSb EҸG*J(!"n{x hZJ"j(RҴ44@ ! dBD p_r@㇤*8Ick˧CfBa>77o4Y*갉{1RBS|%y{d1 ~^(ԧ# qUPLF݂n$u`-11%R`hA"4G;>E Q)C= $? CJ_Lj{Uo ?OX;$&(bGA!AO8P4.Ds-ofȝQqSBZ[SN^L_)Ab[UK Fݷcd&ZӆvI;mSu@S +" =RHf t $:SU/qcgG LFiͅ$UC[JٰrI#|O{|؊K{=(@@[DT|hWmެD_R?C 1! (KBm*&v@gHONO7wDP)JA9ӫ3{ 4 @h;Bbei@S4嗟?B9>AIdj BUȴ ~^tQ9V"RןD[r],X !?KUTBͱltʋm$?t>>qJ T=RFXuHXh EDJi BD$42 LD F؀-*JhE&& R (+,JBAl H@DD'AH0 Rҭ*ġ@҆eJm4$D4.("G%3HAM+ġ*iLD0IJPD%*S0dPFb)@bɖ"c$ d  4H1 MI1ЄCAITB L'BQP BA$ N&$ ` R!M9vd%j P*J@-`2@4a0KM4v"14ti3E &hgE`dӥ(uc QbX4*"p#AC2.HCC2PD(oa{*O+dkY(0-a~;AM Ð@lC2.X}D H20DM)JP5D"!ITS4T0)k 8!?sHUZMEȢ$qp(PKKb!mT(-.9آ-&;zUS-,hSIY )BQ Rfi*(JPaT4**`B]`$T$3ME'PET]"f$fb8Hm rZ2q?bLuBv4^HZ?&qʪ!& =J;U>PA)AT$HE#J BBPPDQ#IRL D $T$R4E4USL$S0KE1 D2DIP@Ȕ1$DLh$F&8?ϛ3t2`@ùy4y`DQE|?)C^hPT%.Jh>dE~pD|OZ<޼MIL~Hx?^q`Ǹ{kut>(#H1)BPAB@H- ұ$H(,HPT B!5B)f< qp]OW86ށgfH.1">:@GJ,? | 61/bhdH( BBi)JB$If)H4к@4q+ hSd_O TF$zq1X/ljJ(T1<=k^hNH$?u|@|!F%RpNi>NǜkHNw_0ei5clyLK@(%BJVXa V|ӹKԾF@pHWHvv7Z<`9|d| Љ@&aDSyq'1Kr)E04`?nw eqzf)doix0.cnEA 8x!i A`|qA (WÕˋ`Q@4'lSAN J1F,@GPTEQQḨ0SI˅4tgFq P#1+Jtb@DR F8I`$CIH5l"SxևcLMՐ' JZP*[aiX3=\?0c"t=Ʋ  EB/D 9OUOg2gch;eVm#liKVLcQAW* Rʊ1-jHeԘA&I#L'v& y",Ok 3Vm6mӾEKy|;ժ$.%,v:IJƥBy]ٷDƮ킌;x҂C 0CGAUUUUUUUUVn5 bӘ7zy^5j<ݕ''1!&LcM u]-i~p3@E.Y[j>o898< ˣc] 4 T%wiل![#1'p IS")4 IDQ@ā& FI riaU'7AJPYyN&z?SvE9R* 3N!iҤsF b) $8 ;!*Rt @D8|r- d7CƿjsH&QV1U8e=,d`fpuomთN&5(3Tr䢆ibO$Ac`ri+A Sa/Sήᰝ ,$}vp]$*o}^CT}/Oމ׎dI-2]1} Ϣꃌ+0N zE '$1-" 4Xp1v8 ) ]B=D)OG1:ږ1@0a~+yX4ʦBW)!^`P0b?9< p)tm"6:9Q܏ 0 QL=b>t0PB9EpEI`l}`2(QB-"7E,sGiO!՛}˷f[s3-[VIn*]Hd9Ei?Y1m jC E[P4p&Vka0CיJk]wUg6D%^Md0;0͞dhg_U2~z G>Zv6M!1 }vb#$M+A1'Ple%Wͦu(1 eihqኲIM& 8^OJ09BQ H7ŕJŸ(fK8 ̸<$bq aG0YӒ(\#>wh)MFҚT-38;/^^qWlp~20cу Cd#H1rW*x{C㇐A$1D.++H:O)PAﯲc= f.u`z|x{ω>bCyBd ?oGy-Zb@$\B{|vd/@ErۻT X4 NpLɂGx!zsj~D>NW;7DUPX U1kI~f4 Ap!,wI~2ƫbfw#cQ*$B& tDBsuD+E$;] _H7r<9d4ȼkGI{]'x =CD#kuVZlq~Կ?yׅyH|~EQ%!CQ 4T!BD EAERRIP!IQ0Iȡ)b(bdfa"dd DiH(( i&(h P $D"*JiV(Yd(`JbHJjhHJ BJ@ )Pm9dVFO9" N9镠'm"`‰ת$2S ;!*|TSEPQACC!XB%$ L J쩚H!)dXdHa@02 $D3'` Ii!" *e@!4R$t&(a)4 `?D UYTAXd~ 0gD1X0S2žy*!mQ>Cs܇yUA+|` ?0zٳRr s@w:9@Py:R!HA(V)ZhRE85JCܮ(zO$ dA$DGSMC0kk⟰ѡ׈8J_"`:yv?5( ZG2xt$p0}v{fx&v + !KRt2I2\wA=GҨ8}oO~>t=௒I|π 6$ 8iMe~zaC )|yQCcNH J(IedDtA`fY"R* & !""A(y4LJ e;! 1LE$IP ZHQs EP$T̀Pĕ" ҌQ68CdD&R <|d| ҟv0 O܏/9@4:bi?sc- 1Yh'N6 D@FֶML@Bk4CZr *9VC@2 OL$GeĘf­ݛibvQ@Ӭ) +PRH^OBh ̄$1[THhH%R  ؂ htOP1J@GFiHe026FXڌ+k_FQS&f}ځ'#W8S(M +Ey T@jz *G ѣG4/< <(VJLB@%iZ!a("Ƈ246ͬeT?J PPYAb:TX `;D*@@a8 )yE9&C!С}]1B )B%D=е4EX`1As  RR$%hy `tC1h&'@ ^]wu8@RkmIyuS1(& &%@!#\e~ph5h0dr1N ðzp ;͒qڶ!']vˋ(8)Dϝ8TY`Ѥ˜mM)B&(P0* Bp9!  #:3!LqS/NRD=<@?/WPmx: ,NMc&$yLMEWi~F iH4'4׹ Ε``x50zE^ Δ X}lU䮼wEކUL!GHClyBid;vT2PE) !KCz  (z$<탄ҹh$ =@g bNJ(VB"*N' 8 -!JIPPDĄ%PQH,-0R EDz W8j;pkk#g9^\kdHG]m@cϵGO2i& L #KL^0&37a(؜V֭j,Hwvm<I@*/ 8hӑdأF: C9W  `"YBh3h$6y*f'ih6FԞb)*@ MJP!B~. h;b@wFC'X!7 NLӰ1=q 0̠"V"=`3U:y&^`|Wo>7$B:W@?~@q bBX&(Fx_x.]qA@Xbj@.5?tdMG Q5Դz{Y5Eqj6 0ˌ򨀽ܚ*@IsB9;u#242.2I&6[[97BmHTƐ!89EctXAG˚ikALbj$NP0tnߊ8t xg װ`n/68y]o烈}A_Y-cۍo+72͆1jRv8/l7R֠97 : zlMg|lҡ X*&ST!YD[H M!(*C2bE8*)IZ` Q\fP7=BWG:~hݴV##ҨAy<P^@")1Q5٘Oa`e>` 9u<`~D}i@V]*{<5$ "W v4˃m_>ww_ΜKD|%dqI'"Orz~z6@/l폦:C:ǿCZ!w܉AG }UJas/?f&!z@RT͚ƣf yn-(؊&([nMxuk4c0%h((*BT_)4(w piBSAŇPف7U <{|ILG/xcFOgRI1opc >U~cոzr_%PBE0pBRҦa|'u&&| EBpHC9w^ );Wtt{EA"jh'!l!;#.f`v0!ȶ4D$h*A)"%.ӊi PҔkI?8=>/ j ^^҈b "12-@?\}-ꪢ<]`d<Αp  uX,D;y?d^)*ď@t JDQ61_<8HD-1CJ|Dש"E*Č2PD<٭3`Dq$_JE{*:P%CIx&*, x`d~ȃpYQ~xr`iqg+)oϮd/cibrcɱtx'yry=ƇsbqWvBy41'#1;NvPromd opnSz6tuq'ns̍xtӂ!d}@A Y̧|=/Ca#/v0AG@`;bxY͈NR^ϑNL{?w-i J;}Z#´#7~hod= H8]B?Fyy. J䐈|0Ad3B_;>wpb2I{ۛCGev|ٍSh8Q l5qn C:OY䀦Jс7.N< {x@UWz{$zmjt@u"éOIv u4(W3wq|h|;H$e)j)t6GI iBgUyhc1?z*!郂Gl?WoaSpX HM=}9P1#`GCNOTUDJ nP ty3QC$ 'qI̊iP^"e Bu:̾ ÃGX1Im v3'@p(@1A RŦ&UxT]ճ\QA }m`Qjŕ0n N _:ߜ+@Smq~5w0&\BhhB JZD٨!=eu2@J=J!BL (WЄ?* lsG{)9-ro|$oxO?yAI8p? cx<bT($sū]uƌ9b"siOwv p nI"A4v~ey ? !5,_uݬ*t>a>S(>gJtc|a P<&X$$IbkNL⊼÷kX,vv!pH1cIM"zL}I?44HSDA9yk["r<; `'AV3IIfu_o=EGE=d4A>iD=i taGDJDh@IRD AHaH!I? (I) dXƶk#v&@.ߋT?9 la$C0gHi& aSxLʴ@"+HEP4$ J \Q - E E RґM @ALH1 J*EP`T` R+܀ᵎ4H Hjk;'Hvb6J>焤S!vI ϥ 1ĂHLo<Y.@ cfp$(h 1`a.,opxEm Nu E2 [uvB'0(HGycLu΍x tKӘj )$~ -4 HGvmI0+9'Iyj[ϳit@cIic(RwC4c~qaHIK0qD=' M=wCf/xn 4rxL::ΠwݤC\(g0M1+]"PJFbjBO\I +F↥]CJJM"YEc]w<-_N 2P9! ʼn!!<؇q?dMC4^*i@(K S8,ZH@hTBKlp HPJ@v<?-W /4`e8,Ȗ h,l1&S@;㞶0b $쬚IZmi` OFJPiY("S JkԪ`U)P9*'Bp8+@J4@P@B&E <(侠!}rɴ&hA#bUdE% v'8-jGQ89ӶaT~BR(T c/ʢ4fgx) Hj!!%"`&("V"hBQǫ|i,pQt.Z$K2I C!q*OPjV/-LU>I&{cȊgA="yH{uNΜ8>TQW1U $>3"H !]9=P,(đ!5-4*@LpfD *et`3əJC B +4 H JCI A1F!q@ \&(hbWVM(©H)T Bn  ;(6HL]NHHM!B/*!h2$ p;`nv@xc1h }:̯WqEפAS4yԡ\ A>+@G@c A o4$PJ/s܉'QPpHcvn΀=Lf菼^OLHU Z}llzW_E8}U聚ccːs >ø߯azyO$^C‹O-Zⴔn&TJ Hz*^$g͛M^ S; O3!Q 5!HR'hB16%M \Eybĥö 45 Ԥ0!QEFYxkgל (m1+iF:8ﳅ$+4P9hg=a~"hjeCd EbKTBFX9jEز?b*iDd?x(-㺵SxGq;G=&8xR"Dd|z?2͟? ;#>",(L~ Qyi;AJPlRAz63̠;#(~qdi0MƂy{(k=Bq/nb( i~FD@7RP.ʡZ^@c I*R%׬plp y0r܎UE>zCDmB#I :/Yt|~-R E%GJ}whxjHr@uO/ @~1 KB!"/= \0hS "|ٵj*9e75Bn{"hY;0x*?{1e¯6mC\ε&n#y𷩄Y's=GX{HqsOlJAiVU% $DZg<O@xw~Lz?3 p$ p/iM`# B#N{`.vO>ʫW?\EAʜHLW4&[H:`4~`0s&#d5M*vbLI<&M9 J#20E=ZR/pw>_RaaTDz{ēD0I4gE9C2 (!;CDG{aY< @ɰZDzJ8; B{OwD؋ОР^Ct&zyUUUUUUUQ\jőuyv`%' ~7vKYv {̂"@I'ZJlۼ~p=H@~PCOO u?vhmQhQl#;)Pi,apzѩ~@!Ap=gNh0p2Bx̊:7G3Ep۰;s31#!h Rfa),z*LFQЊ)=c> PqX)*TN'%zx$??`gvA ~.?w}uA_~SFrs/dP~2V?M5NDEgъ*im4XI6HE:9hKZSc To<"JV~F2aMP@5Ę"pdLUA u: U=O7O p =!P1W>'x-0Dye Tϥ1Ct X!@2QV1$Q?G A3i15Q̀щơ<;{*"#QSMRZĔDHu*wBH*=vk B.6HX;,H? HD,Q>1DSӭ8VCJP[.hvwu$06$)!!*@`J"fDDBC4U$PDE%[bS01 ԇ6xB(Z ݒuF`  \P_:JQ$&gFD*bL9DPSDD_]0F"tOS@DP,԰TzOPI*t>аIDZLPHDDDK55-)#,왠((!#bDRCI@FHy:bJVH4Fqą$=]:/z /!4BcSPh7  kJl#@fif|aN\S*0:N;b|HR FALnh$%}"Do#>0AwO t+JQjEGq: '@ja )a !(D4 T(J8n`}Gwv } Y5xxIs1Qa ]Z'hF<64 PM)9FUy R@{/ }@SRwK&:sbH,07*t9ӇYh<2<"44M,@  (>d,7pHlFidC=h|f 1"WdZA l*~ W@`oCOH`#^{E!(2007H.PE~΢Sp#D@x$n(Ia%D2HdݩU*'~RL !1:QI?(ڪxn8tw>U( bi.7m > ) r<")I BЮ!@FoO3";)w!pZ")ԱACPp^~1̎'ŴDRHE7bk6LALg+w"V G1q(7=+oS!>=$GaCLNwYɂwqLR\g6 <;Mbe.MF҉:٣cc5N0O ʳQxdX@::9 +>1;c2Pa=ٞcˊ}u8!@` "H$)(jJJVB>=<EXA>A]xJ!Y @y!ZcߋJDegAGA2 BҨ~E,M%ZPRH714 %k\3?~2 ϮP2*@쇘ɤ/O$Mfcf}!_OP {RY^qA62T$ ?`D]%Jh$,e@ǥ˥$MԒI@'!攨ߑ@R$#~}5C f :oֶ`!Dܘ(*a8'=_who"!4p!V#N峜BY&_ͼ-sv}@TPHE #QDҭ2U3H's+XHWՔ(DR)$`j7 X!HU,ADM I$@πoغptҪy8#+`r쿙@P!vʦ€h!# 3ݬ́ |CΠfJu=jy;؀< feZ`'`ǁBHr&VnpIGϙ(S42<  9P4СHEn ,)Jb"T`HК,hYH U1DX&R4 я_#=ɸ/ 90U9B)JՖCB|4DB֔MړlМ@)J +UǶGԧ|Av#ҁh::@PRcA$/'  Ьqpg1.b0JAHR-mNC 4URQIGD Q !^$E(P0+j5#oe3s1ddR7ǦO׭]ZT Ž](QrbGWJqnX^mhցp; D.8߳E>\]Q~OG[>| =' rWTHr`V9im"bJ"*8dX7ҡ H՗ ȁd1 _3`Gрm :߉]chss804=,6R46pWs1RrjwՃR?YR$| 6u/*4}nS|ze_ ܝW*/JD]NEf.P$4:I F 4Z}tj>$2c FÑ'@cr!4)OmB8Dr R#>$qDGO: !&ҏ\q:YSG^޾mzPi!YgpAIKd! {QNGmb7CPI-wMPL"1N g; DEJPHN'H9>:$M9[|< Ql 5\ׅbi:vIwz;vA˝¯'O4Vm%ㄬrgE]1$>fxlJ醀;cDHW p[8zѤ0XAƮ'Cr h[qE|FZƔWKD5JWiUfdT_s͗ژbAE ZA,IhN!&[SvdɘWnáb˺x}#F?4D虭`ny5jDۭFH=$>\iVLH7A!ɮZ8616DD>Y(to`쾤Xg.#D~8BG¥Q||xmSvԹ~'xa4i`Bvq(I$U$cKh5f]mjOE?ڠб6rWTren^~P7Ki O*ZQnNYtw.o`J%.QY(nGLcbQ@3ퟯ7bJ4ZRDun5^݇*9#Fj5Ҋ7D†N-,]A͍8WMލȑg h^Ppdq.+GȀ%D1xu9ؠ(aU*sҥ@#Ͼ;½K.U=*tQ\q<֦6*1 '/ h- `0f+->5~ fpe~cgQ*#m*6I5?sfnm̟@wQkCρ"(`!!13[w.`QŬ A-գN"zPW  hj%RqY0 f .W D2dj2S%ӝ9ێ<4-/0Fan hQ2u4)U# B]d ֋H{`8$?W||$1Ⱥg|$ٌE'*I{Ty 8G҇2' `'v?K : HOӄ/-oZXp<܀CzҘy%Ƨg|SYDO?lt3BP$$4ᶳ8S\~nE.! :@w ff,Êaah('y d7 ;2?а@698Օ6=ѻS I Lj 1ǝwr=( 1A kFr|Qп{!&x00n37rǙScܹ؉CgN!`$s (3;'LC̳dJ "@?~>6=HD"g3T/_0RJ)%(፯1c4oSgDkk ܐk[6sLR1,Pb|+x՛YƯ1Q"%U `DUB$RU$Td"!`z @Rb?-@Nb1IJY(A}v3ͺۖr 52 ,zG$;6 jXZZ Ћ@PJ5лQ˜vrˮTc^gμMIc/\ƅ4y3!lwSOɡ?Y8N^ғa;PӬA|<㈠8;F<ϝvxRRP4>``;6#i𕈓c>pp` =򅾺~)FO|N: -(V{q?$vXc&tʕ&^E?]\* ȑ4v<=\8~AĿ 3v8fZ4Jp-#Z =>B#cD0(yR^J95{a*e( bB@6x"i#c( 0-P,f>vfM%ІɃ>՞ p1g5/|2A% AJa"$"& "V"c}T_."qG! DǕǽ=Om1y $N:7fʸy &J50TԑDxsl8HkG|[޲ ȭX8&&H-h4[;s5 nsȬ̿.>MEov>_3`ۣv`x;DT_4q؞q'{̀|vOPJ!P<.mwCB1-Ow (Ht hBe` )RBJA&Pr$$30|$t%- `@*R*Mfxj5X4Cay/1y}?Q*"8';oy1#?o0ySQOf" !bq. THE'l. D\ |A?Xqʐ3Ӱ3{å,Lp L:{zE <<|=* TPB`P_/\ӆl5:SMuI A+Ҵ@x {ݓ08_C8|_b"cGPF wT?"R?Oo_,OuQ=8 8!K÷P* y{dqtqH f^K~SB>I(Ii4I[zy{!OQݡ*TBmϋMb~D$NHfģAl90߇(((*& G7;cFdCٵ: Gy000RL jnrbT_Y2N< e v]j@S $Ap}J>lJ) Ĵ 44 5כH?H$ǃwqŘ1Dcjـ\ÏJTc#q(Ajl9nb"7XtS[fQP0a \$%U1EPv^xϧUzBBX# Qθ13PύooyH#244LDET9.` Oozn;Qǀ8p>F 83fFJSh;ED',  k`xιo,7X 6-'W]DBP\87Zpå ZS3ԦfFqV#B)1K5FbdPqG(8]i%:|wB69bA' ,֎j|h]R|c{9 TЄ9VP0s]DXgRVpdr6u JF!ǸK]3roDri"Q4jM姖EhRmaVI+$Yf0Q2S( T + %;t>qe>>j~`;€y $tB9"8BPHS)[/3OxR5 #(]89K6N !CJb {'MzT-ʒ]a&ϲ2 F=>^ϏH"䅢F PDCQ12!-Un:rMEI1D!rgy Ip6fqSlaH@UDDT.3OY E- d̩ TA7@SGNwELtBlq4}@f8Ƿ((`@@荼pOHUv=Sv)!t d&.X9% TE TG8MSFyp=U}34XcEIe³`n!9BAxanxmX"HXCEL@p ;0*R8  G2^pz@pB=Q  *P`]ct RleM~Y;2%p*OI@ (ТtE?sw2.!H)JR"SJPЩ )B" OHJ(OrU9*PtM"4)R*dhQiG K>ҿxĢЫ+zBD"Bq"%>ЋD:A@!=*!҅ Q@DJRTPHAN=J=hB.J&Bx]NdDBlpqzLAʌgb$M ^ x!hj #n? ʦ'2O G^} xC_A Q?}ܯ: L(%!z2^p5P)BZ=@y]L$oi [<}V 0t`KA:XRqDA?#y?|D"_;?ϕHfBvu=A0>x<~ФC 1z$>Of&f ׵7ze ぬɥe݅ "P_8,jU4"Fu n ;Cd2v`(Bth[VB"ڲ`6}$:j /5M ϒ"&/6""$#0ivScr߃$f!B!&J4j ѯl}{4 ? TL@盟$Hћ9htmNx2'% SBD/c4RÆfl~ {WȞM2F$JBJ`;}xHqJP&Ҕ.?u1:,@//B5JP4 EHGvh|@<{='LJJ%->N2`);?۳1jdыz_o$R8NtE[n&?`55L>ES0Wiv|f W o. QNakR$CXW4r/jfN҅$`BBFd~g &_Ѵh[DC"A@a|z >YLeiR'uH9ӹ.] | ,GTAS IJ/ ~ȃQ P00_itBcO}cTM4Tb`AzHxw9,Ts2I/VyGcLFEظeTTPI)-S 4ԲQ SAM/h ٸ&׵>owSȂ[@`dH%&Bjp:;> 폤恺|@?v* E QBP"}aPt H y w;P?Hc> w s 9Y·puB<>_:on=}g>&|1A@1#)6)Ub%K^M @(/@0R C|/?p:&@`dx7wq7{}Y3qcR}OIda,H*%1aC1R# r[vz]>,! < ";`  30ۃp~1F`ВHt\_ofDha@MQ$Yx !EdCwT?T;Hpwp@kk}b &H|2mdrqw=)e< l-Ƶ+ c)V`:q ?wys)I冇;!Tؙ jQV$9s^/pTJRxA69 CG0`j/XYein8`|(A`v=1 I?La\b.oK^u=I0*ۀf;Y(nyh'od-+( 1 KNˋ5AIK "i]1!ˇ#i MT{ hR%Omŏi|ΌwMg%D\8sW*0JؔCjB'07UڛV6Qp[\6(Bj]gLQIѧho:d1~h oT.y+